浏览代码

stop() replaces setFinalT()

David Rose 23 年之前
父节点
当前提交
74d183f54b

+ 29 - 21
direct/src/extensions/CInterval-extensions.py

@@ -7,27 +7,44 @@
     def play(self, t0 = 0.0, duration = None, scale = 1.0):
     def play(self, t0 = 0.0, duration = None, scale = 1.0):
         """ play(t0, duration)
         """ play(t0, duration)
         """
         """
-        self.stop()
+        if self.isPlaying():
+            self.stop()
         if duration:  # None or 0 implies full length
         if duration:  # None or 0 implies full length
             self.setupPlay(t0, t0 + duration, scale)
             self.setupPlay(t0, t0 + duration, scale)
         else:
         else:
             self.setupPlay(t0, -1, scale)
             self.setupPlay(t0, -1, scale)
         self.__loop = 0
         self.__loop = 0
-        # Spawn task
-        taskMgr.add(self.__playTask, self.getName() + '-play')
+        self.resume()
 
 
     def loop(self, t0 = 0.0, duration = None, scale = 1.0):
     def loop(self, t0 = 0.0, duration = None, scale = 1.0):
         self.play(t0, duration, scale)
         self.play(t0, duration, scale)
         self.__loop = 1
         self.__loop = 1
         return
         return
 
 
-    def stop(self):
-        """ stop()
-        """
+    def pause(self):
+        self.interrupt()
         # Kill task
         # Kill task
         taskMgr.remove(self.getName() + '-play')
         taskMgr.remove(self.getName() + '-play')
         return self.getT()
         return self.getT()
 
 
+    def resume(self):
+        # Spawn task
+        taskMgr.add(self.__playTask, self.getName() + '-play')
+    
+    def stop(self):
+        # Nowadays, stop() will implicitly set the interval to its
+        # terminal state, like setFinalT() used to.  Use pause()
+        # instead if you just want to leave the interval in its
+        # current state, whatever that may be.
+        self.pause()
+        self.finalize()
+        if hasattr(self, "setTHooks"):
+            for func in self.setTHooks:
+                func(self.getT())
+
+    def setFinalT(self):
+        self.stop()
+
     def setT(self, t, event = ETStep):
     def setT(self, t, event = ETStep):
         # Overridden from the C++ layer.  We rename the C++ function
         # Overridden from the C++ layer.  We rename the C++ function
         # in FFIRename to make this possible.
         # in FFIRename to make this possible.
@@ -35,15 +52,6 @@
         if hasattr(self, "setTHooks"):
         if hasattr(self, "setTHooks"):
             for func in self.setTHooks:
             for func in self.setTHooks:
                 func(t)
                 func(t)
-    
-    def setFinalT(self):
-        # We have to define this at the Python level so we can
-        # implicitly call stop().
-        self.stop()
-        self.finalize()
-        if hasattr(self, "setTHooks"):
-            for func in self.setTHooks:
-                func(self.getT())
 
 
     def isPlaying(self):
     def isPlaying(self):
         return taskMgr.hasTaskNamed(self.getName() + '-play')
         return taskMgr.hasTaskNamed(self.getName() + '-play')
@@ -81,30 +89,30 @@
         # So when you drag scale with mouse its like you started a playback
         # So when you drag scale with mouse its like you started a playback
         def onPress(s=self,es=es):
         def onPress(s=self,es=es):
             # Kill playback task
             # Kill playback task
-            s.stop()
+            s.pause()
             # INIT interval
             # INIT interval
             s.setT(es.get(), CInterval.ETInitialize)
             s.setT(es.get(), CInterval.ETInitialize)
         es.onPress = onPress
         es.onPress = onPress
         # To make sure you stop free running intervals
         # To make sure you stop free running intervals
-        es.onRelease = lambda s=self: s.stop()
+        es.onRelease = lambda s=self: s.pause()
         # To update scale and execute intervals with ETInitialize
         # To update scale and execute intervals with ETInitialize
         def onReturn(s = self, es = es):
         def onReturn(s = self, es = es):
             s.setT(es.get(), CInterval.ETInitialize)
             s.setT(es.get(), CInterval.ETInitialize)
-            s.stop()
+            s.pause()
         es.onReturnRelease = onReturn
         es.onReturnRelease = onReturn
         es.pack(expand = 1, fill = X)
         es.pack(expand = 1, fill = X)
         bf = Frame(outerFrame)
         bf = Frame(outerFrame)
         # Jump to start and end
         # Jump to start and end
         def toStart(s=self, es=es):
         def toStart(s=self, es=es):
             s.setT(0.0, CInterval.ETInitialize)
             s.setT(0.0, CInterval.ETInitialize)
-            s.stop()
+            s.pause()
         def toEnd(s=self):
         def toEnd(s=self):
             s.setT(s.getDuration(), CInterval.ETInitialize)
             s.setT(s.getDuration(), CInterval.ETInitialize)
-            s.stop()
+            s.pause()
         jumpToStart = Button(bf, text = '<<', command = toStart)
         jumpToStart = Button(bf, text = '<<', command = toStart)
         # Stop/play buttons
         # Stop/play buttons
         stop = Button(bf, text = 'Stop',
         stop = Button(bf, text = 'Stop',
-                      command = lambda s=self: s.stop())
+                      command = lambda s=self: s.pause())
         play = Button(
         play = Button(
             bf, text = 'Play',
             bf, text = 'Play',
             command = lambda s=self, es=es: s.play(es.get()))
             command = lambda s=self, es=es: s.play(es.get()))

+ 4 - 7
direct/src/interval/ActorInterval.py

@@ -61,10 +61,6 @@ class ActorInterval(Interval.Interval):
 
 
         # Initialize superclass
         # Initialize superclass
         Interval.Interval.__init__(self, name, duration)
         Interval.Interval.__init__(self, name, duration)
-        # Update stopEvent
-        self.stopEvent = id + '_stopEvent'
-        if self.loopAnim:
-            self.stopEventList = [self.stopEvent]
 
 
     def calcFrame(self, t):
     def calcFrame(self, t):
         segmentLength = abs(self.finishTime - self.startTime)
         segmentLength = abs(self.finishTime - self.startTime)
@@ -108,19 +104,20 @@ class ActorInterval(Interval.Interval):
         if (t >= self.duration):
         if (t >= self.duration):
             self.actor.stop(self.animName)
             self.actor.stop(self.animName)
             frame = self.goToT(self.duration)
             frame = self.goToT(self.duration)
-            if self.loopAnim:
-                self.ignore(self.stopEvent)
         elif self.loopAnim == 1:
         elif self.loopAnim == 1:
             if event == Interval.IVAL_INIT:
             if event == Interval.IVAL_INIT:
                 # Pose anim
                 # Pose anim
                 self.goToT(t)
                 self.goToT(t)
                 # 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)
         else:
         else:
             # Pose anim
             # Pose anim
             self.goToT(t)
             self.goToT(t)
 
 
+    def interrupt(self):
+        if self.loopAnim:
+            self.actor.stop
+        
 
 
 class LerpAnimInterval(CLerpAnimEffectInterval):
 class LerpAnimInterval(CLerpAnimEffectInterval):
     # Blends between two anims.  Start both anims first (or use
     # Blends between two anims.  Start both anims first (or use

+ 30 - 20
direct/src/interval/Interval.py

@@ -25,7 +25,6 @@ class Interval(DirectObject):
         self.duration = duration
         self.duration = duration
         self.curr_t = 0.0
         self.curr_t = 0.0
         self.prev_t = -1
         self.prev_t = -1
-        self.stopEventList = []
         self.setTHooks = []
         self.setTHooks = []
         # Set true if interval responds to setT(t): t>duration
         # Set true if interval responds to setT(t): t>duration
         self.openEnded = openEnded
         self.openEnded = openEnded
@@ -68,15 +67,14 @@ class Interval(DirectObject):
         # Subclasses define this function
         # Subclasses define this function
         pass
         pass
 
 
+    def interrupt(self):
+        # Subclasses define this function
+        pass
+
     def setTHook(self, t):
     def setTHook(self, t):
         # Used by control panel to update scale
         # Used by control panel to update scale
         pass
         pass
 
 
-    def setFinalT(self):
-        """ setFinalT()
-        """
-        self.setT(self.getDuration(), IVAL_DONE)
-
     def play(self, t0=0.0, duration=0.0, scale=1.0):
     def play(self, t0=0.0, duration=0.0, scale=1.0):
         """ play(t0, duration)
         """ play(t0, duration)
         """
         """
@@ -85,7 +83,8 @@ class Interval(DirectObject):
             t0 = self.duration
             t0 = self.duration
 
 
         # Kill ongoing play task
         # Kill ongoing play task
-        taskMgr.remove(self.name + '-play')
+        if self.isPlaying():
+            self.stop()
         # Start new one
         # Start new one
         self.offset = t0
         self.offset = t0
         self.startT = globalClock.getFrameTime()
         self.startT = globalClock.getFrameTime()
@@ -101,8 +100,7 @@ class Interval(DirectObject):
             self.endTime = min(self.duration, self.offset + duration)
             self.endTime = min(self.duration, self.offset + duration)
         assert(t0 <= self.endTime)
         assert(t0 <= self.endTime)
 
 
-        # Spawn task
-        taskMgr.add(self.__playTask, self.name + '-play')
+        self.resume()
 
 
     def loop(self, t0=0.0, duration=0.0, scale=1.0):
     def loop(self, t0=0.0, duration=0.0, scale=1.0):
         self.accept(self.name + '-loop', self.play,
         self.accept(self.name + '-loop', self.play,
@@ -110,18 +108,30 @@ class Interval(DirectObject):
         self.play(t0, duration, scale)
         self.play(t0, duration, scale)
         return
         return
 
 
-    def stop(self):
-        """ stop()
-        """
+    def pause(self):
         # First send event to stop freerunning (e.g. sound and anim) intervals
         # First send event to stop freerunning (e.g. sound and anim) intervals
-        for stopEvent in self.stopEventList:
-            messenger.send(stopEvent)
+        self.interrupt()
         # Kill task
         # Kill task
         taskMgr.remove(self.name + '-play')
         taskMgr.remove(self.name + '-play')
         # No more looping.
         # No more looping.
         self.ignore(self.name + '-loop')
         self.ignore(self.name + '-loop')
         return self.curr_t
         return self.curr_t
 
 
+    def resume(self):
+        # Spawn task
+        taskMgr.add(self.__playTask, self.getName() + '-play')
+
+    def stop(self):
+        # Nowadays, stop() will implicitly set the interval to its
+        # terminal state, like setFinalT() used to.  Use pause()
+        # instead if you just want to leave the interval in its
+        # current state, whatever that may be.
+        self.pause()
+        self.setT(self.getDuration(), IVAL_DONE)
+
+    def setFinalT(self):
+        self.stop()
+
     def isPlaying(self):
     def isPlaying(self):
         return taskMgr.hasTaskNamed(self.name + '-play')
         return taskMgr.hasTaskNamed(self.name + '-play')
 
 
@@ -179,30 +189,30 @@ class Interval(DirectObject):
         # So when you drag scale with mouse its like you started a playback
         # So when you drag scale with mouse its like you started a playback
         def onPress(s=self,es=es):
         def onPress(s=self,es=es):
             # Kill playback task
             # Kill playback task
-            taskMgr.remove(s.name + '-play')
+            self.pause()
             # INIT interval
             # INIT interval
             s.setT(es.get(), IVAL_INIT)
             s.setT(es.get(), IVAL_INIT)
         es.onPress = onPress
         es.onPress = onPress
         # To make sure you stop free running intervals
         # To make sure you stop free running intervals
-        es.onRelease = lambda s=self: s.stop()
+        es.onRelease = lambda s=self: s.pause()
         # To update scale and execute intervals with IVAL_INIT
         # To update scale and execute intervals with IVAL_INIT
         def onReturn(s = self, es = es):
         def onReturn(s = self, es = es):
             s.setT(es.get(), IVAL_INIT)
             s.setT(es.get(), IVAL_INIT)
-            s.stop()
+            s.pause()
         es.onReturnRelease = onReturn
         es.onReturnRelease = onReturn
         es.pack(expand = 1, fill = X)
         es.pack(expand = 1, fill = X)
         bf = Frame(outerFrame)
         bf = Frame(outerFrame)
         # Jump to start and end
         # Jump to start and end
         def toStart(s=self, es=es):
         def toStart(s=self, es=es):
             s.setT(0.0, IVAL_INIT)
             s.setT(0.0, IVAL_INIT)
-            s.stop()
+            s.pause()
         def toEnd(s=self):
         def toEnd(s=self):
             s.setT(s.getDuration(), IVAL_INIT)
             s.setT(s.getDuration(), IVAL_INIT)
-            s.stop()
+            s.pause()
         jumpToStart = Button(bf, text = '<<', command = toStart)
         jumpToStart = Button(bf, text = '<<', command = toStart)
         # Stop/play buttons
         # Stop/play buttons
         stop = Button(bf, text = 'Stop',
         stop = Button(bf, text = 'Stop',
-                      command = lambda s=self: s.stop())
+                      command = lambda s=self: s.pause())
         play = Button(
         play = Button(
             bf, text = 'Play',
             bf, text = 'Play',
             command = lambda s=self, es=es: s.play(es.get()))
             command = lambda s=self, es=es: s.play(es.get()))

+ 18 - 1
direct/src/interval/MetaInterval.py

@@ -291,6 +291,9 @@ class MetaInterval(CMetaInterval):
             elif eventType == CInterval.ETReverseInstant:
             elif eventType == CInterval.ETReverseInstant:
                 ival.setT(0, Interval.IVAL_INIT)
                 ival.setT(0, Interval.IVAL_INIT)
 
 
+            elif eventType == CInterval.ETInterrupt:
+                ival.interrupt()
+
             else:
             else:
                 self.notify.error("Unhandled event type %s" % (eventType))
                 self.notify.error("Unhandled event type %s" % (eventType))
 
 
@@ -309,10 +312,24 @@ class MetaInterval(CMetaInterval):
         CMetaInterval.setT(self, t, event)
         CMetaInterval.setT(self, t, event)
         self.__doPythonCallbacks()
         self.__doPythonCallbacks()
 
 
-    def setFinalT(self):
+    def interrupt(self):
         # This function overrides the C++ function to check for Python
         # This function overrides the C++ function to check for Python
         # callbacks afterwards.
         # callbacks afterwards.
         self.__updateIvals()
         self.__updateIvals()
+        CMetaInterval.interrupt(self)
+        self.__doPythonCallbacks()
+
+    def stop(self):
+        # This function overrides from the parent level to check for Python
+        # callbacks afterwards.
+        self.__updateIvals()
+        CMetaInterval.stop(self)
+        self.__doPythonCallbacks()
+
+    def setFinalT(self):
+        # This function overrides from the parent level to check for Python
+        # callbacks afterwards.
+        self.__updateIvals()
         CMetaInterval.setFinalT(self)
         CMetaInterval.setFinalT(self)
         self.__doPythonCallbacks()
         self.__doPythonCallbacks()
 
 

+ 4 - 9
direct/src/interval/ParticleInterval.py

@@ -28,9 +28,6 @@ class ParticleInterval(Interval.Interval):
         assert(duration > 0.0 or loop == 1)
         assert(duration > 0.0 or loop == 1)
         # Initialize superclass
         # Initialize superclass
         Interval.Interval.__init__(self, name, duration)
         Interval.Interval.__init__(self, name, duration)
-        # Update stopEvent
-        self.stopEvent = id + '_stopEvent'
-        self.stopEventList = [self.stopEvent]
         self.cleanedUp = 0
         self.cleanedUp = 0
 
 
     def updateFunc(self, t, event=Interval.IVAL_NONE):
     def updateFunc(self, t, event=Interval.IVAL_NONE):
@@ -44,7 +41,6 @@ class ParticleInterval(Interval.Interval):
         if (t >= self.getDuration()):
         if (t >= self.getDuration()):
             # If duration reached or stop event received, stop particle effect 
             # If duration reached or stop event received, stop particle effect 
             self.particleEffect.cleanup()
             self.particleEffect.cleanup()
-            self.ignore(self.stopEvent)
             self.cleanedUp = 1
             self.cleanedUp = 1
         elif (event == Interval.IVAL_INIT):
         elif (event == Interval.IVAL_INIT):
             # IVAL_INIT event, start new particle effect
             # IVAL_INIT event, start new particle effect
@@ -52,13 +48,12 @@ class ParticleInterval(Interval.Interval):
             if self.worldRelative:
             if self.worldRelative:
                 renderParent = render
                 renderParent = render
             self.particleEffect.start(self.parent, renderParent)
             self.particleEffect.start(self.parent, renderParent)
-            # Accept event to kill particle effect 
-            self.acceptOnce(self.stopEvent,
-                        lambda s = self: 
-                s.particleEffect.cleanup())
         # Print debug information
         # Print debug information
         assert(self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t)))
         assert(self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t)))
-            
+
+    def interrupt(self):
+        self.particleEffect.cleanup()
+        self.cleanedUp = 1
 
 
 
 
 
 

+ 5 - 11
direct/src/interval/SoundInterval.py

@@ -43,9 +43,6 @@ class SoundInterval(Interval.Interval):
             name = id
             name = id
         # Initialize superclass
         # Initialize superclass
         Interval.Interval.__init__(self, name, duration)
         Interval.Interval.__init__(self, name, duration)
-        # Update stopEvent
-        self.stopEvent = id + '_stopEvent'
-        self.stopEventList = [self.stopEvent]
 
 
     def updateFunc(self, t, event = Interval.IVAL_NONE):
     def updateFunc(self, t, event = Interval.IVAL_NONE):
         """ updateFunc(t, event)
         """ updateFunc(t, event)
@@ -53,10 +50,9 @@ class SoundInterval(Interval.Interval):
         """
         """
         # Update sound based on current time
         # Update sound based on current time
         if (t >= self.getDuration()):
         if (t >= self.getDuration()):
-            # If end of sound reached or stop event received, stop sound
+            # If end of sound reached, stop sound
             if self.sound:
             if self.sound:
                 self.sound.stop()
                 self.sound.stop()
-            self.ignore(self.stopEvent)
         elif (event == Interval.IVAL_INIT):
         elif (event == Interval.IVAL_INIT):
             # IVAL_INIT event, start new sound
             # IVAL_INIT event, start new sound
             # If its within a 10th of a second of the start,
             # If its within a 10th of a second of the start,
@@ -69,12 +65,10 @@ class SoundInterval(Interval.Interval):
                 self.sound.setLoop(self.loop)
                 self.sound.setLoop(self.loop)
                 self.sound.setVolume(self.volume)
                 self.sound.setVolume(self.volume)
                 self.sound.play()
                 self.sound.play()
-                # Accept event to kill sound
-                self.acceptOnce(self.stopEvent,
-                        lambda s = self: s.sound.stop())
+
         # Print debug information
         # Print debug information
         self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
         self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))
             
             
-
-
-
+    def interrupt(self):
+        if self.sound:
+            self.sound.stop()

+ 4 - 0
direct/src/interval/cInterval.I

@@ -92,6 +92,10 @@ set_t(double t, CInterval::EventType event) {
   case ET_reverse_finalize:
   case ET_reverse_finalize:
     reverse_finalize();
     reverse_finalize();
     break;
     break;
+
+  case ET_interrupt:
+    interrupt();
+    break;
   }
   }
 }
 }
 
 

+ 18 - 0
direct/src/interval/cInterval.cxx

@@ -309,6 +309,24 @@ reverse_finalize() {
   step(0.0);
   step(0.0);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CInterval::interrupt
+//       Access: Published, Virtual
+//  Description: This is called while the interval is playing to
+//               indicate that it is about to be interrupted; that is,
+//               step() will not be called for a length of time.  But
+//               the interval should remain in its current state in
+//               anticipation of being eventually restarted when the
+//               calls to step() eventually resume.
+//
+//               The purpose of this function is to allow self-running
+//               intervals like sound intervals to stop the actual
+//               sound playback during the pause.
+////////////////////////////////////////////////////////////////////
+void CInterval::
+interrupt() {
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CInterval::output
 //     Function: CInterval::output
 //       Access: Published, Virtual
 //       Access: Published, Virtual

+ 3 - 1
direct/src/interval/cInterval.h

@@ -52,7 +52,8 @@ PUBLISHED:
     ET_finalize,
     ET_finalize,
     ET_reverse_initialize,
     ET_reverse_initialize,
     ET_reverse_instant,
     ET_reverse_instant,
-    ET_reverse_finalize
+    ET_reverse_finalize,
+    ET_interrupt
   };
   };
 
 
   INLINE void set_t(double t, EventType event = ET_step);
   INLINE void set_t(double t, EventType event = ET_step);
@@ -69,6 +70,7 @@ PUBLISHED:
   virtual void reverse_initialize(double t);
   virtual void reverse_initialize(double t);
   virtual void reverse_instant();
   virtual void reverse_instant();
   virtual void reverse_finalize();
   virtual void reverse_finalize();
+  virtual void interrupt();
 
 
   virtual void output(ostream &out) const;
   virtual void output(ostream &out) const;
   virtual void write(ostream &out, int indent_level) const;
   virtual void write(ostream &out, int indent_level) const;

+ 23 - 0
direct/src/interval/cMetaInterval.cxx

@@ -536,6 +536,29 @@ reverse_finalize() {
   _curr_t = 0.0;
   _curr_t = 0.0;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: CMetaInterval::interrupt
+//       Access: Published, Virtual
+//  Description: This is called while the interval is playing to
+//               indicate that it is about to be interrupted; that is,
+//               step() will not be called for a length of time.  But
+//               the interval should remain in its current state in
+//               anticipation of being eventually restarted when the
+//               calls to step() eventually resume.
+//
+//               The purpose of this function is to allow self-running
+//               intervals like sound intervals to stop the actual
+//               sound playback during the pause.
+////////////////////////////////////////////////////////////////////
+void CMetaInterval::
+interrupt() {
+  ActiveEvents::iterator ai;
+  for (ai = _active.begin(); ai != _active.end(); ++ai) {
+    PlaybackEvent *event = (*ai);
+    enqueue_event(event->_n, ET_interrupt, false);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: CMetaInterval::write
 //     Function: CMetaInterval::write
 //       Access: Published, Virtual
 //       Access: Published, Virtual

+ 1 - 0
direct/src/interval/cMetaInterval.h

@@ -81,6 +81,7 @@ PUBLISHED:
   virtual void reverse_initialize(double t);
   virtual void reverse_initialize(double t);
   virtual void reverse_instant();
   virtual void reverse_instant();
   virtual void reverse_finalize();
   virtual void reverse_finalize();
+  virtual void interrupt();
 
 
   INLINE bool is_event_ready();
   INLINE bool is_event_ready();
   INLINE int get_event_index() const;
   INLINE int get_event_index() const;