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):
""" 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()))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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