From 74d183f54b147df9b77e33b746695b3f4c04bedb Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 4 Sep 2002 18:52:47 +0000 Subject: [PATCH] stop() replaces setFinalT() --- direct/src/extensions/CInterval-extensions.py | 50 +++++++++++-------- direct/src/interval/ActorInterval.py | 11 ++-- direct/src/interval/Interval.py | 50 +++++++++++-------- direct/src/interval/MetaInterval.py | 19 ++++++- direct/src/interval/ParticleInterval.py | 13 ++--- direct/src/interval/SoundInterval.py | 16 ++---- direct/src/interval/cInterval.I | 4 ++ direct/src/interval/cInterval.cxx | 18 +++++++ direct/src/interval/cInterval.h | 4 +- direct/src/interval/cMetaInterval.cxx | 23 +++++++++ direct/src/interval/cMetaInterval.h | 1 + 11 files changed, 139 insertions(+), 70 deletions(-) diff --git a/direct/src/extensions/CInterval-extensions.py b/direct/src/extensions/CInterval-extensions.py index 94b2607f19..87b05c53de 100644 --- a/direct/src/extensions/CInterval-extensions.py +++ b/direct/src/extensions/CInterval-extensions.py @@ -7,27 +7,44 @@ def play(self, t0 = 0.0, duration = None, scale = 1.0): """ play(t0, duration) """ - self.stop() + if self.isPlaying(): + self.stop() if duration: # None or 0 implies full length self.setupPlay(t0, t0 + duration, scale) else: self.setupPlay(t0, -1, scale) 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): self.play(t0, duration, scale) self.__loop = 1 return - def stop(self): - """ stop() - """ + def pause(self): + self.interrupt() # Kill task taskMgr.remove(self.getName() + '-play') 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): # Overridden from the C++ layer. We rename the C++ function # in FFIRename to make this possible. @@ -35,15 +52,6 @@ if hasattr(self, "setTHooks"): for func in self.setTHooks: 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): return taskMgr.hasTaskNamed(self.getName() + '-play') @@ -81,30 +89,30 @@ # So when you drag scale with mouse its like you started a playback def onPress(s=self,es=es): # Kill playback task - s.stop() + s.pause() # INIT interval s.setT(es.get(), CInterval.ETInitialize) es.onPress = onPress # 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 def onReturn(s = self, es = es): s.setT(es.get(), CInterval.ETInitialize) - s.stop() + s.pause() es.onReturnRelease = onReturn es.pack(expand = 1, fill = X) bf = Frame(outerFrame) # Jump to start and end def toStart(s=self, es=es): s.setT(0.0, CInterval.ETInitialize) - s.stop() + s.pause() def toEnd(s=self): s.setT(s.getDuration(), CInterval.ETInitialize) - s.stop() + s.pause() jumpToStart = Button(bf, text = '<<', command = toStart) # Stop/play buttons stop = Button(bf, text = 'Stop', - command = lambda s=self: s.stop()) + command = lambda s=self: s.pause()) play = Button( bf, text = 'Play', command = lambda s=self, es=es: s.play(es.get())) diff --git a/direct/src/interval/ActorInterval.py b/direct/src/interval/ActorInterval.py index 42f90f52ba..626a39465e 100644 --- a/direct/src/interval/ActorInterval.py +++ b/direct/src/interval/ActorInterval.py @@ -61,10 +61,6 @@ class ActorInterval(Interval.Interval): # Initialize superclass Interval.Interval.__init__(self, name, duration) - # Update stopEvent - self.stopEvent = id + '_stopEvent' - if self.loopAnim: - self.stopEventList = [self.stopEvent] def calcFrame(self, t): segmentLength = abs(self.finishTime - self.startTime) @@ -108,19 +104,20 @@ class ActorInterval(Interval.Interval): if (t >= self.duration): self.actor.stop(self.animName) frame = self.goToT(self.duration) - if self.loopAnim: - self.ignore(self.stopEvent) elif self.loopAnim == 1: if event == Interval.IVAL_INIT: # Pose anim self.goToT(t) # And start loop, restart flag says continue from current frame self.actor.loop(self.animName, restart=0) - self.acceptOnce(self.stopEvent, self.actor.stop) else: # Pose anim self.goToT(t) + def interrupt(self): + if self.loopAnim: + self.actor.stop + class LerpAnimInterval(CLerpAnimEffectInterval): # Blends between two anims. Start both anims first (or use diff --git a/direct/src/interval/Interval.py b/direct/src/interval/Interval.py index 09eb220ea4..c080596d0e 100644 --- a/direct/src/interval/Interval.py +++ b/direct/src/interval/Interval.py @@ -25,7 +25,6 @@ class Interval(DirectObject): self.duration = duration self.curr_t = 0.0 self.prev_t = -1 - self.stopEventList = [] self.setTHooks = [] # Set true if interval responds to setT(t): t>duration self.openEnded = openEnded @@ -68,15 +67,14 @@ class Interval(DirectObject): # Subclasses define this function pass + def interrupt(self): + # Subclasses define this function + pass + def setTHook(self, t): # Used by control panel to update scale pass - def setFinalT(self): - """ setFinalT() - """ - self.setT(self.getDuration(), IVAL_DONE) - def play(self, t0=0.0, duration=0.0, scale=1.0): """ play(t0, duration) """ @@ -85,7 +83,8 @@ class Interval(DirectObject): t0 = self.duration # Kill ongoing play task - taskMgr.remove(self.name + '-play') + if self.isPlaying(): + self.stop() # Start new one self.offset = t0 self.startT = globalClock.getFrameTime() @@ -101,8 +100,7 @@ class Interval(DirectObject): self.endTime = min(self.duration, self.offset + duration) 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): self.accept(self.name + '-loop', self.play, @@ -110,18 +108,30 @@ class Interval(DirectObject): self.play(t0, duration, scale) return - def stop(self): - """ stop() - """ + def pause(self): # First send event to stop freerunning (e.g. sound and anim) intervals - for stopEvent in self.stopEventList: - messenger.send(stopEvent) + self.interrupt() # Kill task taskMgr.remove(self.name + '-play') # No more looping. self.ignore(self.name + '-loop') 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): 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 def onPress(s=self,es=es): # Kill playback task - taskMgr.remove(s.name + '-play') + self.pause() # INIT interval s.setT(es.get(), IVAL_INIT) es.onPress = onPress # 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 def onReturn(s = self, es = es): s.setT(es.get(), IVAL_INIT) - s.stop() + s.pause() es.onReturnRelease = onReturn es.pack(expand = 1, fill = X) bf = Frame(outerFrame) # Jump to start and end def toStart(s=self, es=es): s.setT(0.0, IVAL_INIT) - s.stop() + s.pause() def toEnd(s=self): s.setT(s.getDuration(), IVAL_INIT) - s.stop() + s.pause() jumpToStart = Button(bf, text = '<<', command = toStart) # Stop/play buttons stop = Button(bf, text = 'Stop', - command = lambda s=self: s.stop()) + command = lambda s=self: s.pause()) play = Button( bf, text = 'Play', command = lambda s=self, es=es: s.play(es.get())) diff --git a/direct/src/interval/MetaInterval.py b/direct/src/interval/MetaInterval.py index 5533512066..b759d1c413 100644 --- a/direct/src/interval/MetaInterval.py +++ b/direct/src/interval/MetaInterval.py @@ -291,6 +291,9 @@ class MetaInterval(CMetaInterval): elif eventType == CInterval.ETReverseInstant: ival.setT(0, Interval.IVAL_INIT) + elif eventType == CInterval.ETInterrupt: + ival.interrupt() + else: self.notify.error("Unhandled event type %s" % (eventType)) @@ -309,10 +312,24 @@ class MetaInterval(CMetaInterval): CMetaInterval.setT(self, t, event) self.__doPythonCallbacks() - def setFinalT(self): + def interrupt(self): # This function overrides the C++ function to check for Python # callbacks afterwards. 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) self.__doPythonCallbacks() diff --git a/direct/src/interval/ParticleInterval.py b/direct/src/interval/ParticleInterval.py index bc254a62af..b15a900555 100644 --- a/direct/src/interval/ParticleInterval.py +++ b/direct/src/interval/ParticleInterval.py @@ -28,9 +28,6 @@ class ParticleInterval(Interval.Interval): assert(duration > 0.0 or loop == 1) # Initialize superclass Interval.Interval.__init__(self, name, duration) - # Update stopEvent - self.stopEvent = id + '_stopEvent' - self.stopEventList = [self.stopEvent] self.cleanedUp = 0 def updateFunc(self, t, event=Interval.IVAL_NONE): @@ -44,7 +41,6 @@ class ParticleInterval(Interval.Interval): if (t >= self.getDuration()): # If duration reached or stop event received, stop particle effect self.particleEffect.cleanup() - self.ignore(self.stopEvent) self.cleanedUp = 1 elif (event == Interval.IVAL_INIT): # IVAL_INIT event, start new particle effect @@ -52,13 +48,12 @@ class ParticleInterval(Interval.Interval): if self.worldRelative: renderParent = render 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 assert(self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t))) - + + def interrupt(self): + self.particleEffect.cleanup() + self.cleanedUp = 1 diff --git a/direct/src/interval/SoundInterval.py b/direct/src/interval/SoundInterval.py index 7366287b3f..6ad0150930 100644 --- a/direct/src/interval/SoundInterval.py +++ b/direct/src/interval/SoundInterval.py @@ -43,9 +43,6 @@ class SoundInterval(Interval.Interval): name = id # Initialize superclass Interval.Interval.__init__(self, name, duration) - # Update stopEvent - self.stopEvent = id + '_stopEvent' - self.stopEventList = [self.stopEvent] def updateFunc(self, t, event = Interval.IVAL_NONE): """ updateFunc(t, event) @@ -53,10 +50,9 @@ class SoundInterval(Interval.Interval): """ # Update sound based on current time 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: self.sound.stop() - self.ignore(self.stopEvent) elif (event == Interval.IVAL_INIT): # IVAL_INIT event, start new sound # 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.setVolume(self.volume) self.sound.play() - # Accept event to kill sound - self.acceptOnce(self.stopEvent, - lambda s = self: s.sound.stop()) + # Print debug information self.notify.debug('updateFunc() - %s: t = %f' % (self.name, t)) - - - + def interrupt(self): + if self.sound: + self.sound.stop() diff --git a/direct/src/interval/cInterval.I b/direct/src/interval/cInterval.I index 07cbaa5bdb..de821fe123 100644 --- a/direct/src/interval/cInterval.I +++ b/direct/src/interval/cInterval.I @@ -92,6 +92,10 @@ set_t(double t, CInterval::EventType event) { case ET_reverse_finalize: reverse_finalize(); break; + + case ET_interrupt: + interrupt(); + break; } } diff --git a/direct/src/interval/cInterval.cxx b/direct/src/interval/cInterval.cxx index 6fb7a6be07..2f395a7744 100644 --- a/direct/src/interval/cInterval.cxx +++ b/direct/src/interval/cInterval.cxx @@ -309,6 +309,24 @@ reverse_finalize() { 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 // Access: Published, Virtual diff --git a/direct/src/interval/cInterval.h b/direct/src/interval/cInterval.h index 8c393c40d4..15b6b5dc67 100644 --- a/direct/src/interval/cInterval.h +++ b/direct/src/interval/cInterval.h @@ -52,7 +52,8 @@ PUBLISHED: ET_finalize, ET_reverse_initialize, ET_reverse_instant, - ET_reverse_finalize + ET_reverse_finalize, + ET_interrupt }; INLINE void set_t(double t, EventType event = ET_step); @@ -69,6 +70,7 @@ PUBLISHED: virtual void reverse_initialize(double t); virtual void reverse_instant(); virtual void reverse_finalize(); + virtual void interrupt(); virtual void output(ostream &out) const; virtual void write(ostream &out, int indent_level) const; diff --git a/direct/src/interval/cMetaInterval.cxx b/direct/src/interval/cMetaInterval.cxx index 0fac488c18..2d2f16eb58 100644 --- a/direct/src/interval/cMetaInterval.cxx +++ b/direct/src/interval/cMetaInterval.cxx @@ -536,6 +536,29 @@ reverse_finalize() { _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 // Access: Published, Virtual diff --git a/direct/src/interval/cMetaInterval.h b/direct/src/interval/cMetaInterval.h index a3ef33a5e1..dbb412383c 100644 --- a/direct/src/interval/cMetaInterval.h +++ b/direct/src/interval/cMetaInterval.h @@ -81,6 +81,7 @@ PUBLISHED: virtual void reverse_initialize(double t); virtual void reverse_instant(); virtual void reverse_finalize(); + virtual void interrupt(); INLINE bool is_event_ready(); INLINE int get_event_index() const;