Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

parent and child entity active states bug?

in Bugs Posts: 417
@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.

Comments

  • SimeonSimeon Admin Mod
    Posts: 5,054

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

  • JohnJohn Admin Mod
    Posts: 587

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

  • dave1707dave1707 Mod
    edited December 2018 Posts: 7,912

    @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
    
  • JohnJohn Admin Mod
    Posts: 587

    @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.

  • dave1707dave1707 Mod
    edited December 2018 Posts: 7,912

    @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?
  • dave1707dave1707 Mod
    Posts: 7,912

    @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

  • SimeonSimeon Admin Mod
    Posts: 5,054

    @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. :)

  • Posts: 417

    @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, 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.

  • JohnJohn Admin Mod
    Posts: 587

    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.

  • JohnJohn Admin Mod
    Posts: 587

    @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 -

  • Posts: 417

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

  • dave1707dave1707 Mod
    Posts: 7,912

    @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.

  • Posts: 417
    @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.
  • dave1707dave1707 Mod
    edited October 11 Posts: 7,912

    @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
    
  • edited October 11 Posts: 417

    @dave1707 thanks, that is what i am doing. Although i would just do sphere3.active=true rather than sphere2.children[1].active=true.

    Still trying to understand my problems-but part of it is that if the active state of a parent is false and then a child is created, the child will be displayed even though the parent is false and the activeInHierarchy of the child is false. I think there is a bug here.

  • dave1707dave1707 Mod
    Posts: 7,912

    @piinthesky The table is used because there are more than one child for the parent and you need to set the table value for a specific child. In my code above, the parent is a sphere just above or just to the left of another sphere. If you change the state of a sphere to the right or below another sphere, that state is remembered when the parent state is changed. Maybe I’ll try writing another example that shows a better example of parent/children.

  • dave1707dave1707 Mod
    Posts: 7,912

    @piinthesky Here’s another parent/child example. The robot is the parent to the shield. The shield is the parent to the blue and white flags. You can turn the shield and flags on/off with the boolean sliders. The state of the flags are remembered when the state of the shield is turned on or off. You can rotate the robot or shield with the sliders.

    displayMode(STANDARD)
    
    function setup()
        parameter.number("Rotate", 0, 360, 208)
        parameter.number("shy",-180,180,-30)
        parameter.number("shz",-180,180,30)
    
        scene = craft.scene()
    
        ground = scene:entity()
        ground.model = craft.model.cube(vec3(10,.2,10))
        ground.material = craft.material("Materials:Specular")
        ground.material.map = readImage("Blocks:Dirt")
        ground.material.specular = color(0, 0, 0, 255)
        ground.material.offsetRepeat = vec4(0,0,1,1)
        ground.y = -1
    
        robot = scene:entity()
        robot.model = craft.model("Blocky Characters:Robot")
        robot.y = -1
        robot.z = 0
        robot.scale = vec3(1,1,1) / 8
    
        shield = scene:entity()
        shield.model = craft.model("CastleKit:shieldRed")
        shield.x = -3
        shield.y = 7
        shield.z = 4
        shield.scale = vec3(2.5,2.5,.1)
    
        flag1 = scene:entity()
        flag1.model = craft.model("CastleKit:flagBlueWide")
        flag1.x = 0
        flag1.y = 0
        flag1.z = 0
        flag1.scale = vec3(.5,.5,.5)
    
        flag2 = scene:entity()
        flag2.model = craft.model("CastleKit:flagWhiteWide")
        flag2.x = 0
        flag2.y = 0
        flag2.z = 0
        flag2.scale = vec3(.5,.5,.5)
    
        sword = scene:entity()
        sword.model = craft.model("CastleKit:sword")
        sword.x = 3.2
        sword.y = 6
        sword.z = 1
        sword.scale = vec3(1,1,1)*1.6
    
        scene.camera.z = -6
    
        shield.parent=robot
        flag1.parent=shield
        flag2.parent=shield
        sword.parent=robot
    
        parameter.boolean("sh",true,   function() robot.children[1].active=sh end)    
        parameter.boolean("blue",true, function() shield.children[1].active=blue end)    
        parameter.boolean("white",true,function() shield.children[2].active=white end)
    end
    
    function update(dt)
        robot.eulerAngles=vec3(0,Rotate,0)
        sword.eulerAngles=vec3(45,0,0)
        shield.eulerAngles=vec3(180,shy,shz)
        flag1.eulerAngles=vec3(180,-90,45)
        flag2.eulerAngles=vec3(120,-90,45)
        scene:update(dt)
    end
    
    function draw()
        update(DeltaTime)
        scene:draw()       
    end
    
  • Posts: 417

    @dave1707, thats a nice example and illustrates how the child inherits the transforms (rotation, displacement, scaling) from the parent.

    I fixed all the bugs in my code-so now a happy camper.

  • Posts: 417

    @John, new parent/child code works great. The only small bug i found is that if the parent.active=false is set before the child is created then the child will be active.

  • dave1707dave1707 Mod
    Posts: 7,912

    @piinthesky Maybe when to create a child, you can check the status of the parent and set the child the same as the parent.

  • JohnJohn Admin Mod
    Posts: 587

    @piinthesky Hey, sorry I didn't post that example code, I've been getting ready for an overseas trip. I'll post it by tomorrow. Thanks for finding that bug, I didn't consider that particular edge case. It shouldn't be too hard to fix though.

    @dave1707 the child should probably keep it's own internal active state but the emergent active state will be based on the chain of parents up to the root when the parent is set.

  • JohnJohn Admin Mod
    Posts: 587

    Here’s the code from the sample I showed on twitter:

    -- Active Test
    
    -- Use this function to perform your initial setup
    function setup()
        print("Hello World!")
        scene = craft.scene()
        scene.camera.z = -20
    
        objs = {}
        createObjects(objs, vec3(5,0,0), nil, 5)
    end
    
    -- This function gets called once every frame
    function draw()
    
        for k,v in pairs(objs) do 
            v.y = math.sin(v.x + ElapsedTime)
        end
    
        scene:update(DeltaTime)
        scene:draw() 
    end
    
    function createObjects(objs, pos, parent, count)
        local e = scene:entity()
        e.model = craft.model("Primitives:Monkey")
        e.model:getMaterial(0).diffuse = color(math.random(100,200), math.random(100,200), math.random(100,200), 255)
        e.position = pos
        if parent == nil then e.rotation = quat.eulerAngles(0,180,0) end
        e.parent = parent
        table.insert(objs, e)
    
        parameter.boolean("Entity "..(5-count+1).." Active", true, function(b)
            e.active = b
            e.active = not b
            e.active = b
        end)
    
        parameter.watch("objs["..#objs.."].activeInHierarchy")
        parameter.watch("objs["..#objs.."].active")    
    
        if count > 0 then 
            createObjects(objs, vec3(3,0,0), e, count-1)
        end
    end
    
Sign In or Register to comment.