Weird interval assertion error

In this scene I have 2 intervals loop, and if you press space, the new interval will be created. Before the new one created, the looping 2 ones paused first.
Without try-except, the error will be raised in IntervalManager.py :
__storeInterval(self, interval, index):
assert self.ivals[index] == None or self.ivals[index] == interval

  1. The index generated by addCInterval in addInterval is 1, which is the index of the last paused ival.
  2. Somehow the last paused ival is still in ivals[], so the expression will return false :
    lastPausedIval == newIval
from pandac.PandaModules import Vec3,Vec4,CIntervalManager
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Parallel, Sequence, LerpHprInterval, LerpColorScaleInterval

class World(DirectObject):
  def __init__(self):
      self.CIM=CIntervalManager.getGlobalPtr()
      self.acceptOnce('space',self.createNewIval)
      base.cam.setY(-5)

      smiley1=loader.loadModelCopy('smiley')
      smiley1.reparentTo(render)
      smiley1.setScale(.6)
      smiley1.setZ(-.8)
      Sequence(
        Parallel( LerpHprInterval( smiley1,2,Vec3(360,0,0)),
                  LerpColorScaleInterval( smiley1,2,Vec4(1,0,0,1))),
        Parallel( LerpHprInterval( smiley1,2,Vec3(720,0,0)),
                  LerpColorScaleInterval( smiley1,2,smiley1.getColorScale()))
      ).loop()

      smiley2=loader.loadModelCopy('smiley')
      smiley2.reparentTo(render)
      smiley2.setScale(.5)
      Sequence(
        Parallel( LerpHprInterval( smiley2,2,Vec3(360,0,0)),
                  LerpColorScaleInterval( smiley2,2,Vec4(0,0,1,1))),
        Parallel( LerpHprInterval( smiley2,2,Vec3(720,0,0)),
                  LerpColorScaleInterval( smiley2,2,smiley2.getColorScale()))
      ).loop()


  def createNewIval(self):
      self.activeIval=[]
      for i in range(self.CIM.getNumIntervals()):
          self.activeIval.append(self.CIM.getCInterval(i))
          self.CIM.getCInterval(i).pause()

      smiley3=loader.loadModelCopy('smiley')
      smiley3.reparentTo(render)
      smiley3.setScale(.3)
      smiley3.setZ(.6)
      try:
          Sequence(
            Parallel( LerpHprInterval( smiley3,2,Vec3(360,0,0)),
                      LerpColorScaleInterval( smiley3,2,Vec4(0,1,0,1))),
            Parallel( LerpHprInterval( smiley3,2,Vec3(720,0,0)),
                      LerpColorScaleInterval( smiley3,2,smiley3.getColorScale()))
          ).loop()
      except:
          pass

World()
run() 

Thanks.

Hi, I was trying to run your code to take a look at what was going on but I get this message before the application even loads up on the DOS screen:

Warning: DirectNotify: category ‘Interval’ already exists

Thats the only warning I seem to get & then the load screen just hangs indefinitely.

it even crashed ?
Nah… now what ?

You’re actually breaking the system by going directly to the CIntervalManager. You shouldn’t do that, because you’ll lose the Python part of a hybrid Python/C interval, and the system will get out of sync–which is what’s triggering the assertion in this case.

From Python, you should always use IntervalGlobal.ivalMgr as the interval manager. This object doesn’t provide a method to iterate through all of its intervals, though; the assumption has been that you will be responsible for keeping the intervals that you want to be able to pause later.

There is a method called finishIntervalsMatching(), though, which can be used to finish (not pause) all intervals. Here’s a modified code snippet that works:

from pandac.PandaModules import Vec3,Vec4,CIntervalManager
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Parallel, Sequence, LerpHprInterval, LerpColorScaleInterval, ivalMgr

class World(DirectObject):
  def __init__(self):
      self.acceptOnce('space',self.createNewIval)
      base.cam.setY(-5)

      smiley1=loader.loadModelCopy('smiley')
      smiley1.reparentTo(render)
      smiley1.setScale(.6)
      smiley1.setZ(-.8)
      Sequence(
        Parallel( LerpHprInterval( smiley1,2,Vec3(360,0,0)),
                  LerpColorScaleInterval( smiley1,2,Vec4(1,0,0,1))),
        Parallel( LerpHprInterval( smiley1,2,Vec3(720,0,0)),
                  LerpColorScaleInterval( smiley1,2,smiley1.getColorScale()))
      ).loop()

      smiley2=loader.loadModelCopy('smiley')
      smiley2.reparentTo(render)
      smiley2.setScale(.5)
      Sequence(
        Parallel( LerpHprInterval( smiley2,2,Vec3(360,0,0)),
                  LerpColorScaleInterval( smiley2,2,Vec4(0,0,1,1))),
        Parallel( LerpHprInterval( smiley2,2,Vec3(720,0,0)),
                  LerpColorScaleInterval( smiley2,2,smiley2.getColorScale()))
      ).loop()


  def createNewIval(self):
      ivalMgr.finishIntervalsMatching('*')

      smiley3=loader.loadModelCopy('smiley')
      smiley3.reparentTo(render)
      smiley3.setScale(.3)
      smiley3.setZ(.6)
      Sequence(
          Parallel( LerpHprInterval( smiley3,2,Vec3(360,0,0)),
                    LerpColorScaleInterval( smiley3,2,Vec4(0,1,0,1))),
          Parallel( LerpHprInterval( smiley3,2,Vec3(720,0,0)),
                    LerpColorScaleInterval( smiley3,2,smiley3.getColorScale()))
          ).loop()

World()
run()

Although we didn’t have a method to iterate through all intervals already, I’ve just added such a method, for cases such as this (for people who really do want to iterate through all intervals). I’ve just added ivalMgr.getIntervalsMatching(’’), which will return a list of all intervals, or a list of whatever subset you suggest. I’ve also added ivalMgr.pauseIntervalsMatching(’’), for completeness.

David

Thanks for your quick efforts. Nice cleanup & typo (BarrowRefrence ?) correction.
But adding pauseIntervals without resumeIntervals is not complete solution. I changed and added it a little :

    def pauseIntervalsMatching(self, pattern):
        self.pausedIvals = self.getIntervalsMatching(pattern)
        for ival in self.pausedIvals:
            ival.pause()
        return len(self.pausedIvals)

    def resumePausedIntervals(self):
        for ival in self.pausedIvals:
            ival.resume()
        self.pausedIvals=None

just to get this to work :

from pandac.PandaModules import Vec3,Vec4
import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from direct.interval.IntervalGlobal import Parallel, Sequence, LerpHprInterval, LerpColorScaleInterval, ivalMgr
from random import random
import sys

class World(DirectObject):
  def __init__(self):
      self.ival2=1
      self.accept('space',self.toggleIvals)
      self.accept('escape',sys.exit)
      base.cam.setY(-10)

      self.smileys=render.attachNewNode('')
      self.smileys.hprInterval(20,Vec3(0,0,360)).loop()
      num=21
      for x in range(num):
          for z in range(num):
              smiley1=loader.loadModelCopy('smiley')
              smiley1.reparentTo(self.smileys)
              smiley1.setScale(.1)
              smiley1.setPos((x-(num-1)*.5)*.2,0,(z-(num-1)*.5)*.2)
              Sequence(
                Parallel( LerpHprInterval( smiley1,2,Vec3(360,0,0)),
                          LerpColorScaleInterval( smiley1,2,Vec4(random(),random(),random(),1))),
                Parallel( LerpHprInterval( smiley1,2,Vec3(720,0,0)),
                          LerpColorScaleInterval( smiley1,2,smiley1.getColorScale()))
              ).loop()

  def toggleIvals(self):
      self.ival2=not self.ival2
      if self.ival2:
         ivalMgr.finishIntervalsMatching('*')
         self.smiley3.removeNode()
         ivalMgr.resumePausedIntervals()
      else:
         ivalMgr.pauseIntervalsMatching('*')
         self.smiley3=loader.loadModelCopy('smiley')
         self.smiley3.reparentTo(render)
         self.smiley3.setScale(.3)
         Sequence(
             Parallel( LerpHprInterval( self.smiley3,2,Vec3(0,360,0)),
                       LerpColorScaleInterval( self.smiley3,2,Vec4(0,1,0,1))),
             Parallel( LerpHprInterval( self.smiley3,2,Vec3(0,720,0)),
                       LerpColorScaleInterval( self.smiley3,2,self.smiley3.getColorScale()))
             ).loop()

World()
run()

Thanks again.

OK. If you don’t mind, I’d prefer to keep resumePausedIntervals() out of the ivalMgr, though–the IntervalManager shouldn’t be in the business of storing intervals after you’ve paused them. You’re responsible for keeping your own intervals.

You could put both of these methods on your own class, though.

David

Sure, no problem.
Thanks for your time.