parent and child entity active states bug?

@John changing the parent.entity.active from false to true will set all the children.entity.active=true. This does not seem to me to be the desired behaviour? I think the visibility of a child should be the product of the parent and the child active states- the child active state should not be modified.

That does seem like a bug that’s easily fixed, I’ll see what @John thinks

Unity has a similar thing, active vs activeSelf vs activeInHierarchy. I’ll see if I can do something similar.

@piinthesky @Simeon @John I thought I’d try playing with the parent children Craft variables. I can control each of the children (red or blue ball) by the children parameter. I can control both the red and blue ball by the parent parameter, but only if the child parameter is on. If both children are on, I can turn them both off or on with the parent parameter. If one is on, I can turn it off, but I can’t turn the one that was originally off back on with the parent parameter. I think it works the way it’s supposed to. I don’t know if this is what’s mentioned in the top post or not.

PS. After playing with this more, I think I see what’s happening with the original post. If I comment out the 2 child parameters and comment out the code in the function active() that controls the 2 children and add code to turn the 2 children active to false in the function createObjects(), then turning the parent parameter on and off will also turn the 2 children on and off even though they were off to start. I think that also works correct. If I don’t control the children individually, then the parent should.

function setup()
    assert(OrbitViewer, "Please include Cameras (not Camera) as a dependency")
    parameter.boolean("redActive",true)
    parameter.boolean("blueActive",true)
    parameter.boolean("parentActive",true)
    scene = craft.scene()
    parent=scene:entity()
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 50, 0, 200)
    createObjects()
end

function createObjects()    
    sphere1=scene:entity()
    sphere1.position=vec3(-5,0,0)
    sphere1.model = craft.model.icosphere(4,2)
    sphere1.material = craft.material("Materials:Specular")
    sphere1.material.diffuse=color(255,0,0)
    sphere1.parent=parent
    
    sphere2=scene:entity()
    sphere2.position=vec3(5,0,0)
    sphere2.model = craft.model.icosphere(4,2)
    sphere2.material = craft.material("Materials:Specular")
    sphere2.material.diffuse=color(0,0,255)
    sphere2.parent=parent
end

function draw()
    update(DeltaTime)
    scene:draw()
    active() 
end

function active()
    if parentActive then
        parent.active=true
    else
        parent.active=false
    end
    if redActive then
        parent.children[1].active=true
    else
        parent.children[1].active=false
    end
    if blueActive then
        parent.children[2].active=true
    else
        parent.children[2].active=false
    end
end

function update(dt)
    scene:update(dt)
end

@dave1707 I think what @piinthesky is looking for is for the active status of a child to be preserved so that if you had a fairly complex hierarchy and disabled the root, the children that were previously disabled would remain so when the root was enabled again.

In your example it looks like you are manually keeping track of active status for each thing and refreshing them in the correct order each time one of them changes. It works, but it’s more complicated and duplicates state.

@John Now that you explain it that way, I see your point. If I control them, they work the way I want them to. If I don’t, then they don’t work the same way.

PS. I never tried the parent/child code before this so I didn’t know how they were supposed to work. I thought I had to control them individually.

@dave1707 @John, sorry if i did not explain it very well. @john explained it better. I often use a parent as a master switch to control whether all its children are visible or not. The active state of the children themselves can be quite complex and for me should not be modified by the parent state.

@john, it seems the ar.pause/ar.run works properly now, did you fix it?

@piinthesky You probably explained it well enough, I just didn’t know enough about how the parent/child process was supposed to work. Like I said above, I never tried using them before so you got me to learn something new which is always good.

what must i include as dependencies to try this? and will it work on 2.6.1? thanks!

sorted, thanks

@RonJeffries the next version no longer requires Craft as an explicit dependency so the option will be removed. All projects will just include it implicitly.

yay. now that i understand. :slight_smile:

@john did you get a chance think anymore about the parent/child active issue? It would simplify my life a lot if the child state was not modified by the parent state and its visibility was the product of the states in its hierarchy.

@John , i don’t get it to work! I guess i am doing something wrong. A second plea to please post the code from the video.

@piinthesky Here’s some code where I was doing parent/child code. Not sure if this is how it’s really supposed to be, but it seems to work. Move the sliders to turn things on/off.

displayMode(STANDARD)

function setup()
    scene = craft.scene()
    parent=scene:entity()
    v=scene.camera:add(OrbitViewer, vec3(0,0,0), 50, 0, 200)
    createObjects()
    parameter.boolean("s1",true,function() parent.children[1].active=s1 end)
    parameter.watch("sphere1.activeInHierarchy")
    
    parameter.boolean("s2",true,function() sphere1.children[1].active=s2 end)
    parameter.watch("sphere2.activeInHierarchy")
    
    parameter.boolean("s3",true,function() sphere2.children[1].active=s3 end)
    parameter.watch("sphere3.activeInHierarchy")
    
    parameter.boolean("s31",true,function() sphere3.children[1].active=s31 end)
    parameter.watch("sphere31.activeInHierarchy")
    
    parameter.boolean("s32",true,function() sphere31.children[1].active=s32 end)
    parameter.watch("sphere32.activeInHierarchy")
    
    parameter.boolean("s4",true,function() sphere3.children[2].active=s4 end)
    parameter.watch("sphere4.activeInHierarchy")
    
    parameter.boolean("s5",true,function() sphere4.children[1].active=s5 end)
    parameter.watch("sphere5.activeInHierarchy")
    
    parameter.boolean("s6",true,function() sphere5.children[1].active=s6 end)
    parameter.watch("sphere6.activeInHierarchy")
end

function createObjects()
    sphere1=scene:entity()
    sphere1.position=vec3(7,0,0)
    sphere1.model = craft.model.icosphere(1,2)
    sphere1.material = craft.material("Materials:Specular")
    sphere1.material.diffuse=color(255,0,0)
    sphere1.parent=parent
    
    sphere2=scene:entity()
    sphere2.position=vec3(-2.5,0,0)
    sphere2.model = craft.model.icosphere(1,2)
    sphere2.material = craft.material("Materials:Specular")
    sphere2.material.diffuse=color(0,0,255)
    sphere2.parent=sphere1
    
    sphere3=scene:entity()
    sphere3.position=vec3(-2.5,0,0)
    sphere3.model = craft.model.icosphere(1,2)
    sphere3.material = craft.material("Materials:Specular")
    sphere3.material.diffuse=color(0,255,255)
    sphere3.parent=sphere2
    
    sphere31=scene:entity()
    sphere31.position=vec3(0,-2.5,0)
    sphere31.model = craft.model.icosphere(1,2)
    sphere31.material = craft.material("Materials:Specular")
    sphere31.material.diffuse=color(0,255,255)
    sphere31.parent=sphere3
    
    sphere32=scene:entity()
    sphere32.position=vec3(0,-2.5,0)
    sphere32.model = craft.model.icosphere(1,2)
    sphere32.material = craft.material("Materials:Specular")
    sphere32.material.diffuse=color(0,255,255)
    sphere32.parent=sphere31
    
    
    sphere4=scene:entity()
    sphere4.position=vec3(-2.5,0,0)
    sphere4.model = craft.model.icosphere(1,2)
    sphere4.material = craft.material("Materials:Specular")
    sphere4.material.diffuse=color(255, 0, 235, 255)
    sphere4.parent=sphere3
    
    sphere5=scene:entity()
    sphere5.position=vec3(-2.5,0,0)
    sphere5.model = craft.model.icosphere(1,2)
    sphere5.material = craft.material("Materials:Specular")
    sphere5.material.diffuse=color(133, 255, 0, 255)
    sphere5.parent=sphere4
    
    sphere6=scene:entity()
    sphere6.position=vec3(-2.5,0,0)
    sphere6.model = craft.model.icosphere(1,2)
    sphere6.material = craft.material("Materials:Specular")
    sphere6.material.diffuse=color(255, 212, 0, 255)
    sphere6.parent=sphere5
end

function draw()
    update(DeltaTime)
    scene:draw()
end

function update(dt)
    scene:update(dt)
end

@john, may i hassle you about this again! I keep hitting a lot of complexity in my code because the active state of child is changed when the parent is changed. I still think it is better if the final ‘activeness’ of a child is just the ‘product’ of the active states of its hierarchy.

Hi @piinthesky, sorry for dragging my feet on this one. I’ll have a look at the code and see how difficult it will be to add this one.

@piinthesky Ok, I’ve fixed this bug (still needs testing) and it will appear in the next beta build.

Each entity now has a persistent active state that is either on or off. There is a new property entity.activeInHierarchy which will return true when the entity is both itself active and all parents in the hierarchy up to the root are also active.

A few other bugs were also fixed in the process, such as the .active read property not updating right away and issues with setting .active true and false multiple times in a single frame.

Here’s an example video of me demonstrating the new behaviour - https://twitter.com/johntwolives/status/1179611068735188992?s=20

@john, wonderful! Looking forward to removing a lot of redundant code in my app.

@John Could you post the code that you show in the video. It would be a lot easier to see the code then try to write something from scratch using parent/child.