Bladeren bron

make ActorInterval more efficient

David Rose 23 jaren geleden
bovenliggende
commit
e0291f7303
2 gewijzigde bestanden met toevoegingen van 180 en 271 verwijderingen
  1. 166 254
      direct/src/actor/Actor.py
  2. 14 17
      direct/src/interval/ActorInterval.py

+ 166 - 254
direct/src/actor/Actor.py

@@ -442,70 +442,42 @@ class Actor(PandaObject, NodePath):
     
     
     def getFrameRate(self, animName=None, partName=None):
     def getFrameRate(self, animName=None, partName=None):
         """getFrameRate(self, string, string=None)
         """getFrameRate(self, string, string=None)
-        Return duration of given anim name and given part.
+        Return actual frame rate of given anim name and given part.
         If no anim specified, use the currently playing anim.
         If no anim specified, use the currently playing anim.
         If no part specified, return anim durations of first part.
         If no part specified, return anim durations of first part.
-        NOTE: returns info only for the first LOD"""
-        # use the first LOD
+        NOTE: returns info only for an arbitrary LOD"""
         lodName = self.__animControlDict.keys()[0]
         lodName = self.__animControlDict.keys()[0]
-
-        if (partName == None):
-            partName = self.__animControlDict[lodName].keys()[0]
-    
-        if (animName==None):
-            animName = self.getCurrentAnim(partName)
-
-        # get duration for named part only
-        if (self.__animControlDict[lodName].has_key(partName)):        
-            animControl = self.getAnimControl(animName, partName, lodName)
-            if (animControl != None):
-                return animControl.getFrameRate()
-        else:
-            Actor.notify.warning("no part named %s" % (partName))
-        return None
+        controls = self.getAnimControls(animName, partName)
+        if len(controls) == 0:
+            return None
+        
+        return controls[0].getFrameRate()
     
     
     def getBaseFrameRate(self, animName=None, partName=None):
     def getBaseFrameRate(self, animName=None, partName=None):
         """getBaseFrameRate(self, string, string=None)
         """getBaseFrameRate(self, string, string=None)
-        Return duration of given anim name and given part, unmodified
+        Return frame rate of given anim name and given part, unmodified
         by any play rate in effect.
         by any play rate in effect.
         """
         """
         lodName = self.__animControlDict.keys()[0]
         lodName = self.__animControlDict.keys()[0]
+        controls = self.getAnimControls(animName, partName)
+        if len(controls) == 0:
+            return None
 
 
-        if (partName == None):
-            partName = self.__animControlDict[lodName].keys()[0]
-    
-        if (animName==None):
-            animName = self.getCurrentAnim(partName)
-
-        # get duration for named part only
-        if (self.__animControlDict[lodName].has_key(partName)):        
-            animControl = self.getAnimControl(animName, partName, lodName)
-            if (animControl != None):
-                return animControl.getAnim().getBaseFrameRate()
-        else:
-            Actor.notify.warning("no part named %s" % (partName))
-        return None
+        return controls[0].getAnim().getBaseFrameRate()
 
 
     def getPlayRate(self, animName=None, partName=None):
     def getPlayRate(self, animName=None, partName=None):
         """getPlayRate(self, string=None, string=None)
         """getPlayRate(self, string=None, string=None)
         Return the play rate of given anim for a given part.
         Return the play rate of given anim for a given part.
         If no part is given, assume first part in dictionary.
         If no part is given, assume first part in dictionary.
         If no anim is given, find the current anim for the part.
         If no anim is given, find the current anim for the part.
-        NOTE: Returns info only for the first LOD"""
+        NOTE: Returns info only for an arbitrary LOD"""
         # use the first lod
         # use the first lod
         lodName = self.__animControlDict.keys()[0]
         lodName = self.__animControlDict.keys()[0]
-            
-        if (partName==None):
-            partName = self.__animControlDict[lodName].keys()[0]
-
-        if (animName==None):
-            animName = self.getCurrentAnim(partName)
-
-        animControl = self.getAnimControl(animName, partName, lodName)
-        if (animControl != None):
-            return animControl.getPlayRate()
-        else:
+        controls = self.getAnimControls(animName, partName)
+        if len(controls) == 0:
             return None
             return None
+
+        return controls[0].getPlayRate()
     
     
     def setPlayRate(self, rate, animName=None, partName=None):
     def setPlayRate(self, rate, animName=None, partName=None):
         """getPlayRate(self, float, string=None, string=None)
         """getPlayRate(self, float, string=None, string=None)
@@ -513,104 +485,76 @@ class Actor(PandaObject, NodePath):
         If no part is given, set for all parts in dictionary.
         If no part is given, set for all parts in dictionary.
         If no anim is given, find the current anim for the part.
         If no anim is given, find the current anim for the part.
         NOTE: sets play rate on all LODs"""
         NOTE: sets play rate on all LODs"""
-        # make a list of partNames for loop below
-        for lodName in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[lodName]
-            if (partName==None):
-                partNames = animControlDict.keys()
-            else:
-                partNames = []
-                partNames.append(partName)
-
-            # for each part in list, set play rate on given or current anim
-            for thisPart in partNames:
-                if (animName==None):
-                    thisAnim = self.getCurrentAnim(thisPart)
-                else:
-                    thisAnim = animName
-                animControl = self.getAnimControl(thisAnim, thisPart, lodName)
-                if (animControl != None):
-                    animControl.setPlayRate(rate)
+        for control in self.getAnimControls(animName, partName):
+            control.setPlayRate(rate)
 
 
     def getDuration(self, animName=None, partName=None):
     def getDuration(self, animName=None, partName=None):
         """getDuration(self, string, string=None)
         """getDuration(self, string, string=None)
         Return duration of given anim name and given part.
         Return duration of given anim name and given part.
         If no anim specified, use the currently playing anim.
         If no anim specified, use the currently playing anim.
         If no part specified, return anim duration of first part.
         If no part specified, return anim duration of first part.
-        NOTE: returns info for first LOD only"""
+        NOTE: returns info for arbitrary LOD"""
         lodName = self.__animControlDict.keys()[0]
         lodName = self.__animControlDict.keys()[0]
-        if (partName == None):
-            partName = self.__animControlDict[lodName].keys()[0]
-
-        if (animName==None):
-            animName = self.getCurrentAnim(partName)          
-
-        # get duration for named part only
-        if (self.__animControlDict[lodName].has_key(partName)):        
-            animControl = self.getAnimControl(animName, partName, lodName)
-            if (animControl != None):
-                return (animControl.getNumFrames() / \
-                        animControl.getFrameRate())
-        else:
-            Actor.notify.warning("no part named %s" % (partName))
+        controls = self.getAnimControls(animName, partName)
+        if len(controls) == 0:
+            return None
 
 
-        return None
+        animControl = controls[0]
+        return (animControl.getNumFrames() / animControl.getFrameRate())
 
 
     def getNumFrames(self, animName=None, partName=None):
     def getNumFrames(self, animName=None, partName=None):
         """ getNumFrames(animName, partName)
         """ getNumFrames(animName, partName)
         """
         """
         lodName = self.__animControlDict.keys()[0]
         lodName = self.__animControlDict.keys()[0]
-        if (partName == None):
-            partName = self.__animControlDict[lodName].keys()[0]
-        if (animName == None):
-            animName = self.getCurrentAnim(partName)
-        if (self.__animControlDict[lodName].has_key(partName)):
-            animControl = self.getAnimControl(animName, partName, lodName)
-            if (animControl != None):
-                return animControl.getNumFrames()
-            else:
-                Actor.notify.error('no anim control!')
-        else:
-            Actor.notify.warning('no part named: %s' % (partName))
+        controls = self.getAnimControls(animName, partName)
+        if len(controls) == 0:
+            return None
+
+        return controls[0].getNumFrames()
         
         
     def getCurrentAnim(self, partName=None):
     def getCurrentAnim(self, partName=None):
         """getCurrentAnim(self, string=None)
         """getCurrentAnim(self, string=None)
-        Return the anim current playing on the actor. If part not
-        specified return current anim of first part in dictionary.
-        NOTE: only returns info for the first LOD"""
-        lodName = self.__animControlDict.keys()[0]
-        if (partName==None):
-            partName = self.__animControlDict[lodName].keys()[0]
+        Return the anim currently playing on the actor. If part not
+        specified return current anim of an arbitrary part in dictionary.
+        NOTE: only returns info for an arbitrary LOD"""
+        lodName, animControlDict = self.__animControlDict.items()[0]
+        if partName == None:
+            partName, animDict = animControlDict.items()[0]
+        else:
+            animDict = animControlDict.get(partName)
+            if animDict == None:
+                # part was not present
+                Actor.notify.warning("couldn't find part: %s" % (partName))
+                return None
 
 
         # loop through all anims for named part and find if any are playing
         # loop through all anims for named part and find if any are playing
-        if (self.__animControlDict[lodName].has_key(partName)):
-            for animName in self.__animControlDict[lodName][partName].keys():
-                if (self.getAnimControl(animName, partName, lodName).isPlaying()):
-                    return animName
-        else:
-            Actor.notify.warning("no part named %s" % (partName))
+        for animName, anim in animDict.items():
+            if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
+                return animName
 
 
         # we must have found none, or gotten an error
         # we must have found none, or gotten an error
         return None
         return None
 
 
     def getCurrentFrame(self, animName=None, partName=None):
     def getCurrentFrame(self, animName=None, partName=None):
         """getCurrentAnim(self, string=None)
         """getCurrentAnim(self, string=None)
-        Return the anim current playing on the actor. If part not
-        specified return current anim of first part in dictionary.
-        NOTE: only returns info for the first LOD"""
-        if animName == None:
-            animName = self.getCurrentAnim(partName)
-
-        lodName = self.__animControlDict.keys()[0]
-        if (partName==None):
-            partName = self.__animControlDict[lodName].keys()[0]
-
-        # check the part name
-        if (self.__animControlDict[lodName].has_key(partName)):
-            animControl = self.getAnimControl(animName, partName, lodName)
-            return animControl.getFrame()
+        Return the current frame number of the anim current playing on
+        the actor. If part not specified return current anim of first
+        part in dictionary.
+        NOTE: only returns info for an arbitrary LOD"""
+        lodName, animControlDict = self.__animControlDict.items()[0]
+        if partName == None:
+            partName, animDict = animControlDict.items()[0]
         else:
         else:
-            Actor.notify.warning("no part named %s" % (partName))
+            animDict = animControlDict.get(partName)
+            if animDict == None:
+                # part was not present
+                Actor.notify.warning("couldn't find part: %s" % (partName))
+                return None
+
+        # loop through all anims for named part and find if any are playing
+        for animName, anim in animDict.items():
+            if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
+                return anim[1].getFrame()
 
 
         # we must have found none, or gotten an error
         # we must have found none, or gotten an error
         return None
         return None
@@ -941,53 +885,20 @@ class Actor(PandaObject, NodePath):
         Stop named animation on the given part of the actor.
         Stop named animation on the given part of the actor.
         If no name specified then stop all animations on the actor.
         If no name specified then stop all animations on the actor.
         NOTE: stops all LODs"""
         NOTE: stops all LODs"""
-        for thisLod in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[thisLod]
-            # assemble lists of parts and anims
-            if (partName == None):
-                partNames = animControlDict.keys()
-            else:
-                partNames = [partName]
-            if (animName == None):
-                animNames = animControlDict[partNames[0]].keys()
-            else:
-                animNames = [animName]
-
-            # loop over all parts
-            for thisPart in partNames:
-                for thisAnim in animNames:
-                    # only stop if it's bound
-                    if isinstance(animControlDict[thisPart][thisAnim][1],
-                                  AnimControl):
-                        animControlDict[thisPart][thisAnim][1].stop()
+        for control in self.getAnimControls(animName, partName):
+            control.stop()
         
         
     def play(self, animName, partName=None, fromFrame=None, toFrame=None):
     def play(self, animName, partName=None, fromFrame=None, toFrame=None):
         """play(self, string, string=None)
         """play(self, string, string=None)
         Play the given animation on the given part of the actor.
         Play the given animation on the given part of the actor.
         If no part is specified, try to play on all parts. NOTE:
         If no part is specified, try to play on all parts. NOTE:
         plays over ALL LODs"""
         plays over ALL LODs"""
-        for thisLod in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[thisLod]
-            if (partName == None):
-                # play all parts
-                for thisPart in animControlDict.keys():            
-                    animControl = self.getAnimControl(animName, thisPart,
-                                                        thisLod)
-                    if (animControl != None):
-                        if (fromFrame == None):
-                            animControl.play()
-                        else:
-                            animControl.play(fromFrame, toFrame)
-
-            else:
-                animControl = self.getAnimControl(animName, partName,
-                                                    thisLod)
-                if (animControl != None):
-                    if (fromFrame == None):
-                        animControl.play()
-                    else:
-                        animControl.play(fromFrame, toFrame)
-
+        if fromFrame == None:
+            for control in self.getAnimControls(animName, partName):
+                control.play(restart)
+        else:
+            for control in self.getAnimControls(animName, partName):
+                control.play(restart, fromFrame, toFrame)
 
 
     def loop(self, animName, restart=1, partName=None,
     def loop(self, animName, restart=1, partName=None,
              fromFrame=None, toFrame=None):
              fromFrame=None, toFrame=None):
@@ -996,27 +907,12 @@ class Actor(PandaObject, NodePath):
         restarting at zero frame if requested. If no part name
         restarting at zero frame if requested. If no part name
         is given then try to loop on all parts. NOTE: loops on
         is given then try to loop on all parts. NOTE: loops on
         all LOD's"""
         all LOD's"""
-        for thisLod in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[thisLod]
-            if (partName == None):
-                # loop all parts
-                for thisPart in animControlDict.keys():
-                    animControl = self.getAnimControl(animName, thisPart,
-                                                      thisLod)
-                    if (animControl != None):
-                        if (fromFrame == None):
-                            animControl.loop(restart)
-                        else:
-                            animControl.loop(restart, fromFrame, toFrame)
-            else:
-                # loop a specific part
-                animControl = self.getAnimControl(animName, partName,
-                                                  thisLod)
-                if (animControl != None):
-                    if (fromFrame == None):
-                        animControl.loop(restart)
-                    else:
-                        animControl.loop(restart, fromFrame, toFrame)
+        if fromFrame == None:
+            for control in self.getAnimControls(animName, partName):
+                control.loop(restart)
+        else:
+            for control in self.getAnimControls(animName, partName):
+                control.loop(restart, fromFrame, toFrame)
 
 
     def pingpong(self, animName, fromFrame, toFrame, restart=1, partName=None):
     def pingpong(self, animName, fromFrame, toFrame, restart=1, partName=None):
         """pingpong(self, string, fromFrame, toFrame, int=1, string=None)
         """pingpong(self, string, fromFrame, toFrame, int=1, string=None)
@@ -1024,42 +920,16 @@ class Actor(PandaObject, NodePath):
         restarting at zero frame if requested. If no part name
         restarting at zero frame if requested. If no part name
         is given then try to loop on all parts. NOTE: loops on
         is given then try to loop on all parts. NOTE: loops on
         all LOD's"""
         all LOD's"""
-        for thisLod in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[thisLod]
-            if (partName == None):
-                # loop all parts
-                for thisPart in animControlDict.keys():
-                    animControl = self.getAnimControl(animName, thisPart,
-                                                        thisLod)
-                    if (animControl != None):
-                        animControl.pingpong(restart, fromFrame, toFrame)
-            else:
-                # loop a specific part
-                animControl = self.getAnimControl(animName, partName,
-                                                    thisLod)
-                if (animControl != None):
-                    animControl.pingpong(restart, fromFrame, toFrame)
+        for control in self.getAnimControls(animName, partName):
+            control.pingpong(restart, fromFrame, toFrame)
         
         
-    def pose(self, animName, frame, partName=None):
+    def pose(self, animName, frame, partName=None, lodName=None):
         """pose(self, string, int, string=None)
         """pose(self, string, int, string=None)
         Pose the actor in position found at given frame in the specified
         Pose the actor in position found at given frame in the specified
         animation for the specified part. If no part is specified attempt
         animation for the specified part. If no part is specified attempt
-        to apply pose to all parts. NOTE: poses all LODs"""
-        for thisLod in self.__animControlDict.keys():
-            animControlDict = self.__animControlDict[thisLod]
-            if (partName==None):
-                # pose all parts
-                for thisPart in animControlDict.keys():
-                    animControl = self.getAnimControl(animName, thisPart,
-                                                        thisLod)
-                    if (animControl != None):
-                        animControl.pose(frame)
-            else:
-                # pose a specific part
-                animControl = self.getAnimControl(animName, partName,
-                                                    thisLod)
-                if (animControl != None):
-                    animControl.pose(frame)
+        to apply pose to all parts."""
+        for control in self.getAnimControls(animName, partName, lodName):
+            control.pose(frame)
 
 
     def enableBlend(self, partName = None):
     def enableBlend(self, partName = None):
         """Enables blending of multiple animations simultaneously.
         """Enables blending of multiple animations simultaneously.
@@ -1106,32 +976,8 @@ class Actor(PandaObject, NodePath):
         animations; it only makes sense to call this after a previous
         animations; it only makes sense to call this after a previous
         call to enableBlend().
         call to enableBlend().
         """
         """
-        if lodName == None:
-            for lodName, controlDict in self.__animControlDict.items():
-                if partName == None:
-                    for part in controlDict.keys():
-                        ac = self.getAnimControl(animName, part, lodName)
-                        if ac != None:
-                            ac.getPart().setControlEffect(ac, effect)
-                else:
-                    ac = self.getAnimControl(animName, partName, lodName)
-                    if ac != None:
-                        ac.getPart().setControlEffect(ac, effect)
-        else:
-            if partName == None:
-                controlDict = self.__animControlDict.get(lodName)
-                if controlDict != None:
-                    for part in controlDict.keys():
-                        ac = self.getAnimControl(animName, part, lodName)
-                        if ac != None:
-                            ac.getPart().setControlEffect(ac, effect)
-                else:
-                    Actor.notify.warning("couldn't find lod: %s" % (lodName))
-            else:
-                ac = self.getAnimControl(animName, partName, lodName)
-                if ac != None:
-                    ac.getPart().setControlEffect(ac, effect)
-            
+        for control in self.getAnimControls(animName, partName, lodName):
+            control.getPart().setControlEffect(control, effect)
 
 
     def getAnimControl(self, animName, partName, lodName="lodRoot"):
     def getAnimControl(self, animName, partName, lodName="lodRoot"):
         """getAnimControl(self, string, string, string="lodRoot")
         """getAnimControl(self, string, string, string="lodRoot")
@@ -1139,26 +985,90 @@ class Actor(PandaObject, NodePath):
         a given anim and part. Return the animControl if present,
         a given anim and part. Return the animControl if present,
         or None otherwise
         or None otherwise
         """
         """
-        if (self.__animControlDict.has_key(lodName)):
-            animControlDict = self.__animControlDict[lodName]
-            if (animControlDict.has_key(partName)):
-                if (animControlDict[partName].has_key(animName)):
-                    # make sure the anim is bound first
-                    self.bindAnim(animName, partName, lodName)
-                    return animControlDict[partName][animName][1]
-                else:
-                    # anim was not present
-                    Actor.notify.warning("couldn't find anim: %s" % (animName))
-            else:
-                # part was not present
-                Actor.notify.warning("couldn't find part: %s" % (partName))
+        animControlDict = self.__animControlDict.get(lodName)
+        # if this assertion fails, named lod was not present
+        assert(animControlDict != None)
+
+        animDict = animControlDict.get(partName)
+        if animDict == None:
+            # part was not present
+            Actor.notify.warning("couldn't find part: %s" % (partName))
         else:
         else:
-            # lod was not present
-            Actor.notify.warning("couldn't find lod: %s" % (lodName))
-            assert(0)
+            anim = animDict.get(animName)
+            if anim == None:
+                # anim was not present
+                Actor.notify.warning("couldn't find anim: %s" % (animName))
+            else:
+                # bind the animation first if we need to
+                if not isinstance(anim[1], AnimControl):
+                    self.__bindAnimToPart(animName, partName, lodName)
+                return anim[1]
             
             
         return None
         return None
+        
+    def getAnimControls(self, animName=None, partName=None, lodName=None):
+        """getAnimControls(self, string, string=None, string=None)
+
+        Returns a list of the AnimControls that represent the given
+        animation for the given part and the given lod.  If animName
+        is omitted, the currently-playing animation (or all
+        currently-playing animations) is returned.  If partName is
+        omitted, all parts are returned.  If lodName is omitted, all
+        LOD's are returned.
+        """
+        controls = []
 
 
+        # build list of lodNames and corresponding animControlDicts
+        # requested.
+        if lodName == None:
+            # Get all LOD's
+            animControlDictItems = self.__animControlDict.items()
+        else:
+            animControlDict = self.__animControlDict.get(lodName)
+            if animControlDict == None:
+                Actor.notify.warning("couldn't find lod: %s" % (lodName))
+                animControlDictItems = []
+            else:
+                animControlDictItems = [(lodName, animControlDict)]
+
+        for lodName, animControlDict in animControlDictItems:
+            # Now, build the list of partNames and the corresponding
+            # animDicts.
+            if partName == None:
+                # Get all parts
+                animDictItems = animControlDict.items()
+            else:
+                # Get a specific part
+                animDict = animControlDict.get(partName)
+                if animDict == None:
+                    # part was not present
+                    Actor.notify.warning("couldn't find part: %s" % (partName))
+                    animDictItems = []
+                else:
+                    animDictItems = [(partName, animDict)]
+                
+            if animName == None:
+                # get all playing animations
+                for thisPart, animDict in animDictItems:
+                    for anim in animDict.values():
+                        if isinstance(anim[1], AnimControl) and anim[1].isPlaying():
+                            controls.append(anim[1])
+            else:
+                # get the named animation only. 
+                for thisPart, animDict in animDictItems:
+                    anim = animDict.get(animName)
+                    if anim == None:
+                        # anim was not present
+                        Actor.notify.warning("couldn't find anim: %s" % (animName))
+                    else:
+                        # bind the animation first if we need to
+                        if not isinstance(anim[1], AnimControl):
+                            if self.__bindAnimToPart(animName, thisPart, lodName):
+                                controls.append(anim[1])
+                        else:
+                            controls.append(anim[1])
+
+        return controls
             
             
     def loadModel(self, modelPath, partName="modelRoot", lodName="lodRoot", copy = 1):
     def loadModel(self, modelPath, partName="modelRoot", lodName="lodRoot", copy = 1):
         """loadModel(self, string, string="modelRoot", string="lodRoot",
         """loadModel(self, string, string="modelRoot", string="lodRoot",
@@ -1327,6 +1237,8 @@ class Actor(PandaObject, NodePath):
         # enough to preload, fetch from disk :(
         # enough to preload, fetch from disk :(
         animPath = self.__animControlDict[lodName][partName][animName][0]
         animPath = self.__animControlDict[lodName][partName][animName][0]
         anim = loader.loadModelOnce(animPath)
         anim = loader.loadModelOnce(animPath)
+        if anim == None:
+            return None
         animBundle = \
         animBundle = \
                    (anim.find("**/+AnimBundleNode").node()).getBundle()
                    (anim.find("**/+AnimBundleNode").node()).getBundle()
 
 

+ 14 - 17
direct/src/interval/ActorInterval.py

@@ -32,9 +32,11 @@ class ActorInterval(Interval.Interval):
         # Record class specific variables
         # Record class specific variables
         self.actor = actor
         self.actor = actor
         self.animName = animName
         self.animName = animName
+        self.controls = self.actor.getAnimControls(self.animName)
+        assert(len(self.controls) > 0)
         self.loopAnim = loop
         self.loopAnim = loop
-        self.frameRate = self.actor.getBaseFrameRate(self.animName) * playRate
-        self.numFrames = self.actor.getNumFrames(self.animName)
+        self.frameRate = self.controls[0].getAnim().getBaseFrameRate() * playRate
+        self.numFrames = self.controls[0].getNumFrames()
         # Compute start time
         # Compute start time
         self.startTime = startTime
         self.startTime = startTime
         # If no name specified, use id as name
         # If no name specified, use id as name
@@ -85,10 +87,13 @@ class ActorInterval(Interval.Interval):
         # Calc integer frame number
         # Calc integer frame number
         frame = self.calcFrame(t)
         frame = self.calcFrame(t)
         # Pose anim
         # Pose anim
-        self.actor.pose(self.animName, frame)
-        # Print debug information
-        self.notify.debug('goToT() - %s pose to frame: %d' %
-                          (self.name,frame))
+
+        # We use our pre-computed list of animControls for
+        # efficiency's sake, rather than going through the relatively
+        # expensive Actor interface every frame.
+        for control in self.controls:
+            control.pose(frame)
+            
         return frame
         return frame
 
 
     def updateFunc(self, t, event=Interval.IVAL_NONE):
     def updateFunc(self, t, event=Interval.IVAL_NONE):
@@ -100,15 +105,11 @@ class ActorInterval(Interval.Interval):
             return
             return
         # Update animation based upon current time
         # Update animation based upon current time
         # Pose or stop anim
         # Pose or stop anim
-        if (t >= self.getDuration()):
+        if (t >= self.duration):
             self.actor.stop(self.animName)
             self.actor.stop(self.animName)
-            frame = self.goToT(self.getDuration())
+            frame = self.goToT(self.duration)
             if self.loopAnim:
             if self.loopAnim:
                 self.ignore(self.stopEvent)
                 self.ignore(self.stopEvent)
-            # Print debug information
-            self.notify.debug(
-                'updateFunc() - %s stoping at frame: ' % self.name +
-                '%d Num frames: %d' % (frame, self.numFrames))
         elif self.loopAnim == 1:
         elif self.loopAnim == 1:
             if event == Interval.IVAL_INIT:
             if event == Interval.IVAL_INIT:
                 # Pose anim
                 # Pose anim
@@ -116,10 +117,6 @@ class ActorInterval(Interval.Interval):
                 # And start loop, restart flag says continue from current frame
                 # And start loop, restart flag says continue from current frame
                 self.actor.loop(self.animName, restart=0)
                 self.actor.loop(self.animName, restart=0)
                 self.acceptOnce(self.stopEvent, self.actor.stop)
                 self.acceptOnce(self.stopEvent, self.actor.stop)
-                # Print debug information
-                self.notify.debug(
-                    'updateFunc() - IVAL_INIT %s looping anim' %
-                    self.name)
         else:
         else:
             # Pose anim
             # Pose anim
             self.goToT(t)
             self.goToT(t)
@@ -162,7 +159,7 @@ class LerpAnimInterval(Interval.Interval):
             return
             return
 
 
         # First, normalize t into the range 0 .. 1, and apply the blendType.
         # First, normalize t into the range 0 .. 1, and apply the blendType.
-        t = self.blendType(float(t) / self.getDuration())
+        t = self.blendType(float(t) / self.duration)
 
 
         # Then compute the current weight based on the time elapsed so far.
         # Then compute the current weight based on the time elapsed so far.
         w = self.startWeight + t * self.deltaWeight
         w = self.startWeight + t * self.deltaWeight