Solved, not a bug: hprInterval always starts from (0, 0, 0)

Here is the situation. I have a class for simulating sun that moves on the sky starting from (0, 0, 0) and ending on (0, -180, 0) (going upward and then down). Sun is the directional light. When I press space bar, it pauses, and if I press again, resumes. This is done by an interval that is included into sequence (I will need to add more intervals later).
The problem is that always after I pause the sequence and then resume it, the interval starts from (0, 0, 0), not from previous position.

class Lights():
    def __init__(self):
        self.setDirectionalL()
        self.updateLights()

    def setDirectionalL(self):
        self.sun = DirectionalL()

    def updateLights(self):
        taskMgr.add(self.sun.updateDirectionalL,
                    "updateSunTask")

class DirectionalL():
    def __init__(self):
        self.sunLight = DirectionalLight("sun")
        self.sunLight.setColor(Vec4(0.8, 0.8, 0.8, 1))
        self.sunNP = render.attachNewNode(self.sunLight)
        render.setLight(self.sunNP)

        self.sunNP.setHpr(0, 0, 0)
        self.sunIsMoving = False

        self.sunI1 = self.sunNP.hprInterval(2.0,
                                        Vec3(0, -180, 0))
        self.sequence1 = Sequence(self.sunI1)

    def updateDirectionalL(self, task):
        if controls.keyMap["toggleSun"]:
            if self.sunIsMoving:
                self.sunIsMoving = False
                self.sequence1.pause()
            else:
                self.sunIsMoving = True
                self.sequence1.loop()

        print "Is Interval playing according to game logic?", self.sunIsMoving
        print "Current Directional Light Hpr:", self.sunNP.getHpr()
        print "Is Interval actually playing accoring to Panda?", self.sequence1.isPlaying()
        print

        return Task.cont

I tried to change “loop()” to “resume()” (and later to “start()”) but then it plays only once, without looping. I also tried many versions of code “finish()” instead of “pause()”.
I also tried to save the Hpr values before “pause()” or “finish()”, and then calling “self.sunNP.setHpr()” before “loop()” but without success.
If I use “startT” parameter with “loop()” then it only loops from startT, and skips the beginning. For this day I have also tried numerous combinations of the above.
Gentlemen, please, what to do?
If you are interested what the print statements print, here is one example:

Is Interval playing according to game logic? False
Current Directional Light Hpr: VBase3(0, -87.48, 0)
Is Interval actually playing accoring to Panda? 0

Is Interval playing according to game logic? False
Current Directional Light Hpr: VBase3(0, -87.48, 0)
Is Interval actually playing accoring to Panda? 0

Is Interval playing according to game logic? True
Current Directional Light Hpr: VBase3(0, -87.48, 0)
Is Interval actually playing accoring to Panda? 1

Is Interval playing according to game logic? True
Current Directional Light Hpr: VBase3(0, 0, 0)
Is Interval actually playing accoring to Panda? 1

Is Interval playing according to game logic? True
Current Directional Light Hpr: VBase3(0, -0.36, 0)
Is Interval actually playing accoring to Panda? 1

Is Interval playing according to game logic? True
Current Directional Light Hpr: VBase3(0, -0.9, 0)
Is Interval actually playing accoring to Panda? 1

I’ve never had any problem pausing/resuming intervals. The correct way are pause() and resume(). I guess it’s simply your logic.

  1. What does sunIsMoving used for ? Only to save the ival’s play/pause state ?
  2. It seems that you want to loop() (start it for the 1st time) also by pressing spacebar. Is that true ?
    Add “self.sunIvalStarted = False” to init and :
        if controls.keyMap["toggleSun"]:
            if self.sunIsMoving:
                self.sunIsMoving = False
                self.sequence1.pause()
            else:
                self.sunIsMoving = True
                if self.sunIvalStarted:
                   self.sequence1.resume()
                else:
                   self.sequence1.loop()
                   self.sunIvalStarted = True

Hmm, can’t you work around it by supplying startHpr = self.sunNP.getHpr() in the interval constructor?

PS. could this be that bakeInStart is enabled or so?

ynjh_jo, your solution worked :slight_smile:
pro-rsoft, I tried startHpr = self.sunNP.getHpr() - no results. It seems, “startHpr” parameter is bugged and doesn’t work for hprInterval. I will test it more, and report the bug, if it’s true.

As far as i remember, startPosition and EndPosition are evaluated at the start of the interval.
If you need them to be evaluated according to current position of the node then you need to set bakeInStart=False in the interval parameter.

This allow to blend interval on the same node…
(at least in 1.4)

I have just tried to play with bakeInStart, but without success either. It seems it’s bug!
I have made an archive with test files (code, eggs and textures). Please, check it and see what is wrong. Lines related to the interval begin after 127. You can play with parameters to see the difference (or, most likely, to see no difference).
Download it here: hprIntervalTest.zip
Press spacebar to start interval, press spacebar again to pause it.
In the code the interval is supposed to begin from the current sun position but in fact is always starts from (0, 0, 0).
The log:

The sequence is playing,
and the sun is in VBase3(0, -23.49, 0)
The sequence is playing,
and the sun is in VBase3(0, -23.625, 0)

The sun is paused in VBase3(0, -23.76, 0)

The sequence is playing,
and the sun is in VBase3(0, -23.76, 0)
The sequence is playing,
and the sun is in VBase3(0, 0, 0)
The sequence is playing,
and the sun is in VBase3(0, -0.135, 0)
The sequence is playing,
and the sun is in VBase3(0, -0.315, 0)
The sequence is playing,
and the sun is in VBase3(0, -0.45, 0)

2.9 MB ? Who would want to DL it ? :laughing:
This shows a little clean trick :

def toggleIval():
    ival.pause() if ival.isPlaying() else ival.resume()

DO=DirectObject()
DO.accept('space',toggleIval)

s=loader.loadModel('smiley')
s.find('**/+GeomNode').setY(-5)
s.reparentTo(render)

hprI=s.hprInterval(2,Vec3(0,-180,0))
ival=Sequence(hprI)
# this is the key : start the loop and pause it immediately
ival.loop()
ival.pause()

camera.setPos(-20,-15,10)
camera.lookAt(render)
mat=Mat4(camera.getMat())
mat.invertInPlace()
base.mouseInterfaceNode.setMat(mat)

Thanks, ynjh_jo! Brilliant idea! :slight_smile:

But anyway, hprInterval seems to ignore the “startHpr” parameter. If this is the case, then its bug. Could someone check it, please?

Here is another archive under 1 MB: hprIntervalTest.zip

Nothing is wrong with it. startHpr is only saved upon construction, and used only for reference and not updated each step, which is unnecessary anyway.
The problem lies in your head. You’re keep using loop() instead of resume(). loop() always starts the ival from the beginning (time=0), unless you pass startT=ival.getT() :

but the next loops will use that startT, instead of 0.
I don’t think loop() is intended to behave as resume(). Think of loop() as another variant of start() plus looping, while resume() simply resumes the ival, regardless of its looping status. If you want to resume, just use resume().

And damn, you made me DL ralph ! :laughing: :laughing:

OK, ynjh_jo, I got it now :slight_smile: Thank you for your patience.