Problem with rotate several NodePaths assigned to another NodePath by hprInterval

Hi,
I have a problem with the rotation of objects.
In my code I detect collisions from several small boxes with another big box.
After detecting collision I assign small box to big box (wrtReparentTo) and rotate big box using setHpr() method. As a result, the small boxes rotate together with the big box as a whole. And it works as it should.


def do_rotate(self, coll_entry):
        pivot: NodePath = coll_entry.getIntoNodePath()  # get big box
        name = pivot.getName()
        cubes = self.collided_cubes  #list of small cubes NodePaths
        children = pivot.getChildren() 
        children.wrtReparentTo(self.render)
        pivot.clearTransform()
        children.reparentTo(pivot)

        for cubo in cubes:
            cubo.wrtReparentTo(pivot)  # reparent small boxes to big box 

        pivot.setHpr(self.mapping_sides[name]['rotation']*self.direction) 
        # rotate by Vec3 eg.: Vec3(0, 0, 90)

        for cube in cubes:
            cube: NodePath
            cube.wrtReparentTo(self.scene)
            children.reparentTo(self.render)

Now I’m trying to make the same rotation using hprInterval, so that all boxes rotate a given number of degrees in 0.3 seconds.


def do_rotate(self, coll_entry):
        pivot: NodePath = coll_entry.getIntoNodePath()  # get big box
        name = pivot.getName()
        cubes = self.collided_cubes  #list of small cubes NodePaths
        children = pivot.getChildren() 
        children.wrtReparentTo(self.render)
        pivot.clearTransform()
        children.reparentTo(pivot)

        for cubo in cubes:
            cubo.wrtReparentTo(pivot)  # reparent small boxes to big box 

        # rotate by Vec3 eg.: Vec3(0, 0, 90)
        hprInterval = pivot.hprInterval(0.3, self.mapping_sides[name]['rotation']*self.direction) 
        hprInterval.start()

        for cube in cubes:
            cube: NodePath
            cube.wrtReparentTo(self.scene)
            children.reparentTo(self.render)

But the second code causes only the big box to rotate.

I think that the problem is that you’re immediately removing the small boxes from the big box, directly after starting the interval.

You see, when you apply your rotation via “setHpr”, the change is immediate, and thus has been applied by the time that the code reaches the removal of the small boxes at the end of the method.

However, when you apply your rotation via an interval, the change will instead (presumably) take place over a period of time, over multiple frames as the program updates. But when the code reaches the removal of the small boxes–immediately after the call to “hprInterval.start()”–no new updates have yet occurred (after all, the code is still in the same update, the same frame, as it was at the start of the method).

Thus presumably no change has yet been applied when the code removes the small boxes, leaving only the large box to be rotated during subsequent updates.

1 Like

To fix your problem, you could wrap the cube-removal code into a Func object which you append to a Sequence that contains the hprInterval:

def do_rotate(self, coll_entry):
        pivot: NodePath = coll_entry.getIntoNodePath()  # get big box
        name = pivot.getName()
        cubes = self.collided_cubes  #list of small cubes NodePaths
        children = pivot.getChildren() 
        children.wrtReparentTo(self.render)
        pivot.clearTransform()
        children.reparentTo(pivot)

        for cubo in cubes:
            cubo.wrtReparentTo(pivot)  # reparent small boxes to big box

        def remove_cubes():
            for cube in cubes:
                cube: NodePath
                cube.wrtReparentTo(self.scene)
            children.reparentTo(self.render)

        seq = Sequence()
        # rotate by Vec3 eg.: Vec3(0, 0, 90)
        hprInterval = pivot.hprInterval(0.3, self.mapping_sides[name]['rotation']*self.direction)
        seq.append(hprInterval)
        seq.append(Func(remove_cubes))
        seq.start()
2 Likes