stop() replaces setFinalT()

This commit is contained in:
David Rose 2002-09-04 18:52:47 +00:00
parent 6a35ec3075
commit 74d183f54b
11 changed files with 139 additions and 70 deletions

View File

@ -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 self.resume()
taskMgr.add(self.__playTask, self.getName() + '-play')
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): def pause(self):
""" stop() 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.
@ -36,15 +53,6 @@
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()))

View File

@ -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

View File

@ -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 self.resume()
taskMgr.add(self.__playTask, self.name + '-play')
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): def pause(self):
""" stop()
"""
# 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: self.interrupt()
messenger.send(stopEvent)
# 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()))

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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;
} }
} }

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;