From ae843d2401ed6ad925b7b2f5e1c068d36c10775a Mon Sep 17 00:00:00 2001 From: Mark Mine Date: Wed, 4 Apr 2001 01:39:05 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/interval/AnimInterval.py | 39 ++--- direct/src/interval/FunctionInterval.py | 45 +++--- direct/src/interval/Interval.py | 99 ++++++++++-- direct/src/interval/IntervalTest.py | 2 +- direct/src/interval/LerpInterval.py | 95 ++++++------ direct/src/interval/MopathInterval.py | 32 ++-- direct/src/interval/MultiTrack.py | 10 +- direct/src/interval/SoundInterval.py | 49 +++--- direct/src/interval/Track.py | 190 +++++++++++++++--------- direct/src/interval/WaitInterval.py | 16 +- 10 files changed, 337 insertions(+), 240 deletions(-) diff --git a/direct/src/interval/AnimInterval.py b/direct/src/interval/AnimInterval.py index 72a569f735..e67e546fa0 100644 --- a/direct/src/interval/AnimInterval.py +++ b/direct/src/interval/AnimInterval.py @@ -4,43 +4,46 @@ from PandaModules import * from Interval import * class AnimInterval(Interval): - + # Name counter animNum = 1 - - # special methods - + # Class methods def __init__(self, animControl, loop=0, name=None): """__init__(name) """ + # Record class specific variables self.animControl = animControl - duration = (float(animControl.getNumFrames()) / - animControl.getFrameRate()) self.loop = loop + # Generate unique name if necessary if (name == None): - n = 'Anim-%d' % self.animNum - self.animNum = self.animNum + 1 - else: - n = name - Interval.__init__(self, n, duration) + name = 'Anim-%d' % AnimInterval.animNum + AnimInterval.animNum += 1 + # Compute anim duration + duration = (float(animControl.getNumFrames()) / + animControl.getFrameRate()) + # Initialize superclass + Interval.__init__(self, name, duration) - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) Go to time t """ - if (t < 0): - return - elif (t > self.duration): + # Update animation based upon current time + if (t == self.getDuration()): if (self.isPlaying == 1): self.isPlaying = 0 if (self.loop): self.animControl.stop() - return - elif (entry == 1): + else: + # Set flag self.isPlaying = 1 # Determine the current frame frame = int(self.animControl.getFrameRate() * t) + # Pose anim if (self.loop): self.animControl.pos(frame) self.animControl.loop(0) else: self.animControl.play(frame, self.animControl.getNumFrames()) + + + diff --git a/direct/src/interval/FunctionInterval.py b/direct/src/interval/FunctionInterval.py index 76b895f870..dd402fa780 100644 --- a/direct/src/interval/FunctionInterval.py +++ b/direct/src/interval/FunctionInterval.py @@ -5,33 +5,28 @@ from Interval import * from MessengerGlobal import * class FunctionInterval(Interval): - + # Name counter functionIntervalNum = 1 - - # special methods - def __init__(self, function, name = None): + # Class methods + def __init__(self, function, name = None, openEnded = 1): """__init__(function, name = None) """ - duration = 0.0 - self.prevt = 0.0 + # Record instance variables self.function = function - + # Create a unique name for the interval if necessary if (name == None): name = 'FunctionInterval-%d' % FunctionInterval.functionIntervalNum FunctionInterval.functionIntervalNum += 1 - - Interval.__init__(self, name, duration) - - def setT(self, t, entry=0): - """ setT(t, entry) + # Initialize superclass + # Set openEnded true if calls after end time cause interval + # function to be called + Interval.__init__(self, name, duration = 0.0, openEnded = openEnded) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) Go to time t """ - if (t < 0): - self.prevt = t - return - elif (t == 0) or (self.prevt < 0): - self.function() - self.prevt = 0.0 + # Evaluate the function + self.function() ### FunctionInterval subclass for throwing events ### class EventInterval(FunctionInterval): @@ -42,7 +37,8 @@ class EventInterval(FunctionInterval): def sendFunc(event = event, sentArgs = sentArgs): messenger.send(event, sentArgs) # Create function interval - FunctionInterval.__init__(self, sendFunc, name = event) + FunctionInterval.__init__(self, sendFunc, name = event, + openEnded = 0) ### FunctionInterval subclass for accepting hooks ### class AcceptInterval(FunctionInterval): @@ -54,7 +50,8 @@ class AcceptInterval(FunctionInterval): print "accepting..." dirObj.accept(event, function) # Create function interval - FunctionInterval.__init__(self, acceptFunc, name = name) + FunctionInterval.__init__(self, acceptFunc, name = name, + openEnded = 0) ### FunctionInterval subclass for throwing events ### class IgnoreInterval(FunctionInterval): @@ -66,7 +63,8 @@ class IgnoreInterval(FunctionInterval): print "ignoring..." dirObj.ignore(event) # Create function interval - FunctionInterval.__init__(self, ignoreFunc, name = name) + FunctionInterval.__init__(self, ignoreFunc, name = name, + openEnded = 0) ### Function Interval subclass for adjusting scene graph hierarchy ### class ParentInterval(FunctionInterval): @@ -97,7 +95,8 @@ class WrtParentInterval(FunctionInterval): nodePath.wrtReparentTo(parent) # Determine name if (name == None): - name = 'WrtParentInterval-%d' % WrtParentInterval.wrtParentIntervalNum + name = ('WrtParentInterval-%d' % + WrtParentInterval.wrtParentIntervalNum) WrtParentInterval.wrtParentIntervalNum += 1 # Create function interval FunctionInterval.__init__(self, wrtReparentFunc, name = name) @@ -210,7 +209,6 @@ class PosHprScaleInterval(FunctionInterval): # Create function interval FunctionInterval.__init__(self, posHprScaleFunc, name = name) - """ SAMPLE CODE from IntervalGlobal import * @@ -226,6 +224,7 @@ def printHello(): i3 = FunctionInterval(printHello) # Create track t1 = Track([(0.0, i1), (2.0, i2), (4.0, i3)], name = 'demo') + # Play track t1.play() diff --git a/direct/src/interval/Interval.py b/direct/src/interval/Interval.py index 8ca4b0ac14..7828570722 100644 --- a/direct/src/interval/Interval.py +++ b/direct/src/interval/Interval.py @@ -4,6 +4,10 @@ from DirectObject import * import ClockObject import Task +# Interval events +IVAL_NONE = 0 +IVAL_INIT = 1 + class Interval(DirectObject): """Interval class: Base class for timeline functionality""" @@ -13,13 +17,17 @@ class Interval(DirectObject): # special methods - def __init__(self, name, duration): + def __init__(self, name, duration, openEnded = 1): """__init__(name, duration) """ self.name = name self.duration = duration self.clock = ClockObject.ClockObject.getGlobalClock() self.curr_t = 0.0 + self.prev_t = 0.0 + self.setTHooks = [] + # Set true if interval responds to setT(t): t>duration + self.fOpenEnded = openEnded def getName(self): """ getName() @@ -31,16 +39,40 @@ class Interval(DirectObject): """ return self.duration - def setT(self, t, entry=0): - """ setT(t, entry) + def setfOpenEnded(self, openEnded): + """ setfOpenEnded(openEnded) + """ + self.fOpenEnded = openEnded + + def getfOpenEnded(self): + """ getfOpenEnded() + """ + return self.fOpenEnded + + def setT(self, t, event = IVAL_NONE): + """ setT(t, event) Go to time t """ - pass + # Update current time + self.curr_t = t + # Perform interval actions + self.updateFunc(t, event) + # Call setT Hook + for func in self.setTHooks: + func(t) + # Record t for next time around + self.prev_t = self.curr_t + + def updateFunc(self, t, event = IVAL_NONE): + pass + + def setTHook(self, t): + pass def setFinalT(self): """ setFinalT() """ - self.setT(self.getDuration(), entry=1) + self.setT(self.getDuration(), event=IVAL_NONE) def play(self, t0=0.0, duration=0.0, scale=1.0): """ play(t0, duration) @@ -51,10 +83,10 @@ class Interval(DirectObject): self.scale = scale self.firstTime = 1 if (duration == 0.0): - self.playDuration = self.duration + self.endTime = self.offset + self.duration else: - self.playDuration = duration - assert(t0 <= self.playDuration) + self.endTime = self.offset + duration + assert(t0 <= self.endTime) taskMgr.spawnMethodNamed(self.__playTask, self.name + '-play') def stop(self): @@ -68,16 +100,15 @@ class Interval(DirectObject): """ t = self.clock.getFrameTime() te = self.offset + ((t - self.startT) * self.scale) - self.curr_t = te - if (te <= self.playDuration): + if (te <= self.endTime): if (self.firstTime): - self.setT(te, entry=1) + self.setT(te, event = IVAL_INIT) self.firstTime = 0 else: self.setT(te) return Task.cont else: - self.setT(self.playDuration) + self.setT(self.endTime) return Task.done def __repr__(self, indent=0): @@ -86,16 +117,54 @@ class Interval(DirectObject): space = '' for l in range(indent): space = space + ' ' - return (space + self.name + ' dur: %.2f\n' % self.duration) + return (space + self.name + ' dur: %.2f' % self.duration) def popupControls(self): + import fpformat + import string # I moved this here because Toontown does not ship Tk from Tkinter import * import Pmw import EntryScale tl = Toplevel() + tl.title(self.getName() + ' Interval Controls') es = EntryScale.EntryScale( - tl, min = 0, max = self.duration, + tl, text = 'Time', + min = 0, max = string.atof(fpformat.fix(self.duration, 2)), command = lambda t, s = self: s.setT(t)) - es.onPress = lambda s=self: s.setT(s.curr_t, entry = 1) + es.onRelease = lambda s=self, es = es: s.setT(es.get(), + event = IVAL_INIT) + es.onReturnRelease = lambda s=self, es = es: s.setT(es.get(), + event = IVAL_INIT) es.pack(expand = 1, fill = X) + f = Frame(tl) + def toStart(s=self, es=es): + s.stop() + s.setT(0.0, event = IVAL_INIT) + def toEnd(s=self): + s.stop() + s.setT(s.getDuration(), event = IVAL_INIT) + jumpToStart = Button(tl, text = '<<', command = toStart) + stop = Button(tl, text = 'Stop', + command = lambda s=self: s.stop()) + play = Button( + tl, text = 'Play', + command = lambda s=self, es=es: s.play(es.get())) + jumpToEnd = Button(tl, text = '>>', command = toEnd) + jumpToStart.pack(side = LEFT, expand = 1, fill = X) + play.pack(side = LEFT, expand = 1, fill = X) + stop.pack(side = LEFT, expand = 1, fill = X) + jumpToEnd.pack(side = LEFT, expand = 1, fill = X) + f.pack(expand = 1, fill = X) + # Add hook to update slider on changes in curr_t + def update(t,es=es): + es.set(t, fCommand = 0) + self.setTHooks.append(update) + # Clear out hook on destroy + def onDestroy(e, s=self, u=update): + if u in s.setTHooks: + s.setTHooks.remove(u) + tl.bind('', onDestroy) + + + diff --git a/direct/src/interval/IntervalTest.py b/direct/src/interval/IntervalTest.py index 8955095648..68a945a441 100644 --- a/direct/src/interval/IntervalTest.py +++ b/direct/src/interval/IntervalTest.py @@ -50,7 +50,7 @@ waterEventTrack.setIntervalStartTime('water-is-done', eventTime) mtrack = MultiTrack([boatTrack, dockTrack, soundTrack, waterEventTrack]) # Print out MultiTrack parameters -mtrack +print(mtrack) def handleWaterDone(): print 'water is done' diff --git a/direct/src/interval/LerpInterval.py b/direct/src/interval/LerpInterval.py index d932bdef80..af7b9c24ce 100644 --- a/direct/src/interval/LerpInterval.py +++ b/direct/src/interval/LerpInterval.py @@ -9,21 +9,20 @@ class LerpInterval(Interval): def __init__(self, name, duration, functorFunc, blendType='noBlend'): """__init__(name, duration, functorFunc, blendType) """ + self.lerp = None self.functorFunc = functorFunc self.blendType = self.getBlend(blendType) Interval.__init__(self, name, duration) - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) """ - if (t < 0): - return - elif (entry == 1): + # First check to see if we need to create the lerp + if (event == IVAL_INIT): self.lerp = Lerp.Lerp(self.functorFunc(), self.duration, - self.blendType) - if (entry == 1) and (t > self.duration): - self.lerp.setT(self.duration) - elif (t <= self.duration): - self.lerp.setT(t) + self.blendType) + # Now evaluate the lerp + if self.lerp: + self.lerp.setT(t) def getBlend(self, blendType): """__getBlend(self, string) Return the C++ blend class corresponding to blendType string @@ -42,9 +41,9 @@ class LerpInterval(Interval): 'Error: LerpInterval.__getBlend: Unknown blend type') class LerpPosInterval(LerpInterval): - + # Name counter lerpPosNum = 1 - + # Class methods def __init__(self, node, duration, pos, startPos=None, other=None, blendType='noBlend', name=None): """ __init__(node, duration, pos, startPos, other, blendType, name) @@ -66,18 +65,15 @@ class LerpPosInterval(LerpInterval): functor = PosLerpFunctor.PosLerpFunctor( node, startPos, pos) return functor - + # Generate unique name if necessary if (name == None): - n = 'LerpPosInterval-%d' % LerpPosInterval.lerpPosNum + name = 'LerpPosInterval-%d' % LerpPosInterval.lerpPosNum LerpPosInterval.lerpPosNum += 1 - else: - n = name - - LerpInterval.__init__(self, n, duration, functorFunc, blendType) + # Initialize superclass + LerpInterval.__init__(self, name, duration, functorFunc, blendType) class LerpHprInterval(LerpInterval): - - # Interval counter + # Name counter lerpHprNum = 1 # Class methods def __init__(self, node, duration, hpr, startHpr=None, @@ -101,14 +97,12 @@ class LerpHprInterval(LerpInterval): functor = HprLerpFunctor.HprLerpFunctor( node, startHpr, hpr) return functor - + # Generate unique name if necessary if (name == None): - n = 'LerpHprInterval-%d' % LerpHprInterval.lerpHprNum + name = 'LerpHprInterval-%d' % LerpHprInterval.lerpHprNum LerpHprInterval.lerpHprNum += 1 - else: - n = name - - LerpInterval.__init__(self, n, duration, functorFunc, blendType) + # Initialize superclass + LerpInterval.__init__(self, name, duration, functorFunc, blendType) class LerpScaleInterval(LerpInterval): @@ -137,13 +131,12 @@ class LerpScaleInterval(LerpInterval): node, startScale, scale) return functor + # Generate unique name if necessary if (name == None): - n = 'LerpScaleInterval-%d' % LerpScaleInterval.lerpScaleNum + name = 'LerpScaleInterval-%d' % LerpScaleInterval.lerpScaleNum LerpScaleInterval.lerpScaleNum += 1 - else: - n = name - - LerpInterval.__init__(self, n, duration, functorFunc, blendType) + # Initialize superclass + LerpInterval.__init__(self, name, duration, functorFunc, blendType) class LerpPosHprInterval(LerpInterval): # Interval counter @@ -179,13 +172,12 @@ class LerpPosHprInterval(LerpInterval): startHpr, hpr) return functor + # Generate unique name if necessary if (name == None): - n = 'LerpPosHpr-%d' % LerpPosHprInterval.lerpPosHprNum + name = 'LerpPosHpr-%d' % LerpPosHprInterval.lerpPosHprNum LerpPosHprInterval.lerpPosHprNum += 1 - else: - n = name - - LerpInterval.__init__(self, n, duration, functorFunc, blendType) + # Initialize superclass + LerpInterval.__init__(self, name, duration, functorFunc, blendType) class LerpPosHprScaleInterval(LerpInterval): # Interval counter @@ -226,14 +218,13 @@ class LerpPosHprScaleInterval(LerpInterval): node, startPos, pos, startHpr, hpr, startScale, scale) return functor + # Generate unique name if necessary if (name == None): - n = ('LerpPosHprScale-%d' % - LerpPosHprScaleInterval.lerpPosHprScaleNum) + name = ('LerpPosHprScale-%d' % + LerpPosHprScaleInterval.lerpPosHprScaleNum) LerpPosHprScaleInterval.lerpPosHprScaleNum += 1 - else: - n = name - - LerpInterval.__init__(self, n, duration, functorFunc, blendType) + # Initialize superclass + LerpInterval.__init__(self, name, duration, functorFunc, blendType) # Class used to execute a function over time. Function can access fromData # and toData to perform blend @@ -245,27 +236,29 @@ class LerpFunctionInterval(Interval): blendType = 'noBlend', name = None): """__init__(function, duration, fromData, toData, name) """ + # Record instance variables self.function = function self.fromData = fromData self.toData = toData self.blendType = self.getBlend(blendType) + # Generate unique name if necessary if (name == None): name = ('LerpFunctionInterval-%d' % LerpFunctionInterval.lerpFunctionIntervalNum) LerpFunctionInterval.lerpFunctionIntervalNum += 1 # Initialize superclass Interval.__init__(self, name, duration) - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) """ - if (t < 0): - return - if (entry == 1) and (t > self.duration): - self.function(self.toData) - elif (t <= self.duration): + # Evaluate the function + if (t == self.duration): + # Set to end value + self.function(self.toData) + else: + # In the middle of the lerp, compute appropriate value try: - #bt = self.blendType(t/self.duration) - bt = t/self.duration + bt = self.blendType(t/self.duration) data = (self.fromData * (1 - bt)) + (self.toData * bt) self.function(data) except ZeroDivisionError: diff --git a/direct/src/interval/MopathInterval.py b/direct/src/interval/MopathInterval.py index ec7fe3bdb9..9cc998b85e 100644 --- a/direct/src/interval/MopathInterval.py +++ b/direct/src/interval/MopathInterval.py @@ -5,31 +5,25 @@ from Interval import * import Mopath class MopathInterval(Interval): - + # Name counter mopathNum = 1 - - # special methods - + # Class methods def __init__(self, mopath, node, name=None): """__init__(mopath, node, name) """ - self.node = node self.mopath = mopath - duration = self.mopath.getMaxT() + self.node = node + # Generate unique name if necessary if (name == None): - n = 'Mopath-%d' % self.mopathNum - self.mopathNum = self.mopathNum + 1 - else: - n = name - Interval.__init__(self, n, duration) + name = 'Mopath-%d' % MopathInterval.mopathNum + MopathInterval.mopathNum += 1 + # Compute duration + duration = self.mopath.getMaxT() + # Initialize superclass + Interval.__init__(self, name, duration) - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) Go to time t """ - if (t < 0): - return - elif (entry == 1) and (t > self.duration): - self.mopath.goTo(self.node, self.duration) - else: - self.mopath.goTo(self.node, t) + self.mopath.goTo(self.node, t) diff --git a/direct/src/interval/MultiTrack.py b/direct/src/interval/MultiTrack.py index 8e0b3ea656..cd2b6b3d31 100644 --- a/direct/src/interval/MultiTrack.py +++ b/direct/src/interval/MultiTrack.py @@ -35,19 +35,17 @@ class MultiTrack(Interval): duration = dur return duration - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) Go to time t """ - if (t > self.duration): - pass for track in self.tlist: - track.setT(t, entry) + track.setT(min(t, track.getDuration()), event) def __repr__(self, indent=0): """ __repr__(indent) """ - str = Interval.__repr__(self, indent) + str = Interval.__repr__(self, indent) + '\n' for t in self.tlist: str = str + t.__repr__(indent+1) return str diff --git a/direct/src/interval/SoundInterval.py b/direct/src/interval/SoundInterval.py index 1eb8f66b69..6cf4cf9cd4 100644 --- a/direct/src/interval/SoundInterval.py +++ b/direct/src/interval/SoundInterval.py @@ -4,43 +4,42 @@ from PandaModules import * from Interval import * class SoundInterval(Interval): - + # Name counter soundNum = 1 - - # special methods - + # Class methods def __init__(self, sound, loop=0, name=None): """__init__(sound, loop, name) """ self.sound = sound - duration = self.sound.length() self.loop = loop self.isPlaying = 0 + # Generate unique name if necessary if (name == None): - n = 'Sound-%d' % self.soundNum - self.soundNum = self.soundNum + 1 - else: - n = name - self.prevt = 0.0 - Interval.__init__(self, n, duration) + name = 'Sound-%d' % SoundInterval.soundNum + SoundInterval.soundNum += 1 + # Calculate duration + duration = self.sound.length() + # Initialize superclass + Interval.__init__(self, name, duration) - def setT(self, t, entry=0): - """ setT(t, entry) - Go to time t + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) + Go to time t """ - if (t < 0): - self.prevt = t - return - elif (t > self.duration): + if(t == self.duration): + # Stop sound if necessary if (self.isPlaying == 1): - AudioManager.stop(self.sound) self.isPlaying = 0 - return - elif (entry == 1): + AudioManager.stop(self.sound) + elif (event == IVAL_INIT): + # Set flag self.isPlaying = 1 - if (self.prevt < 0.0): - AudioManager.play(self.sound) - else: - AudioManager.play(self.sound, t) + # If its within a 20th of a second of the start, + # start at the beginning + if (t < 0.05): + t = 0.0 + # Start sound + AudioManager.play(self.sound, t) + # Loop in necessary if (self.loop): AudioManager.setLoop(self.sound, 1) diff --git a/direct/src/interval/Track.py b/direct/src/interval/Track.py index 48d7b640c1..2c0a8556be 100644 --- a/direct/src/interval/Track.py +++ b/direct/src/interval/Track.py @@ -8,33 +8,39 @@ PREVIOUS_END = 1 PREVIOUS_START = 2 TRACK_START = 3 +IDATA_IVAL = 0 +IDATA_TIME = 1 +IDATA_TYPE = 2 +IDATA_START = 3 +IDATA_END = 4 + class Track(Interval): - + # Name counter trackNum = 1 - - # special methods - + # Class methods def __init__(self, intervalList, name=None): """__init__(intervalList, name) """ - if (name == None): - n = 'Track-%d' % Track.trackNum - Track.trackNum = Track.trackNum + 1 - else: - n = name + # Record instance variables self.__buildIlist(intervalList) - duration = self.__computeDuration(len(self.ilist)) self.currentInterval = None - Interval.__init__(self, n, duration) + # Generate unique name if necessary + if (name == None): + name = 'Track-%d' % Track.trackNum + Track.trackNum = Track.trackNum + 1 + # Compute duration + duration = self.__computeDuration() + # Initialize superclass + Interval.__init__(self, name, duration) def __getitem__(self, item): - return self.ilist[item][0] + return self.ilist[item] def __buildIlist(self, intervalList): self.ilist = [] for i in intervalList: if isinstance(i, Interval): - self.ilist.append((i, 0.0, PREVIOUS_END)) + self.ilist.append([i, 0.0, PREVIOUS_END, 0.0, 0.0]) elif (isinstance(i, types.ListType) or isinstance(i, types.TupleType)): t0 = i[0] @@ -43,21 +49,22 @@ class Track(Interval): type = i[2] except IndexError: type = TRACK_START - self.ilist.append((ival, t0, type)) + self.ilist.append([ival, t0, type, 0.0, 0.0]) else: print 'Track.__buildIlist: Invalid intervallist entry' - def __computeDuration(self, length): - """ __computeDuration(length) + def __computeDuration(self): + """ __computeDuration() """ - assert(length <= len(self.ilist)) duration = 0.0 prev = None - for i in self.ilist[0:length]: - ival = i[0] - t0 = i[1] - type = i[2] + for idata in self.ilist: + ival = idata[IDATA_IVAL] + t0 = idata[IDATA_TIME] + type = idata[IDATA_TYPE] assert(t0 >= 0.0) + # Compute fill time, time between end of last interval and + # start of this one fillTime = t0 if (type == PREVIOUS_END): pass @@ -72,23 +79,27 @@ class Track(Interval): if (fillTime < 0.0): Interval.notify.error( 'Track.__computeDuration(): overlap detected') - duration = duration + fillTime + ival.getDuration() + # Compute start time of interval + idata[IDATA_START] = duration + fillTime + # Compute end time of interval + idata[IDATA_END] = idata[IDATA_START] + ival.getDuration() + # Keep track of current duration + duration = idata[IDATA_END] prev = ival return duration def setIntervalStartTime(self, name, t0, type=TRACK_START): """ setIntervalStartTime(name, t0, type) """ - length = len(self.ilist) found = 0 - for i in range(length): - if (self.ilist[i][0].getName() == name): - newi = (self.ilist[i][0], t0, type) - self.ilist[i] = newi + for idata in self.ilist: + if (idata[IDATA_IVAL].getName() == name): + idata[IDATA_TIME] = t0 + idata[IDATA_TYPE] = type found = 1 - break; + break if (found): - self.duration = self.__computeDuration(length) + self.duration = self.__computeDuration() else: Interval.notify.warning( 'Track.setIntervalStartTime(): no Interval named: %s' % name) @@ -96,71 +107,104 @@ class Track(Interval): def getIntervalStartTime(self, name): """ getIntervalStartTime(name) """ - for i in range(len(self.ilist)): - if (self.ilist[i][0].getName() == name): - return (self.__computeDuration(i+1) - - self.ilist[i][0].getDuration()) + for idata in self.ilist: + if (idata[IDATA_IVAL].getName() == name): + return idata[IDATA_START] Interval.notify.warning( 'Track.getIntervalStartTime(): no Interval named: %s' % name) - return 0.0 + return None def __getIntervalStartTime(self, interval): """ __getIntervalStartTime(interval) """ - for i in range(len(self.ilist)): - if (self.ilist[i][0] == interval): - return (self.__computeDuration(i+1) - interval.getDuration()) + for idata in self.ilist: + if (idata[IDATA_IVAL] == interval): + return idata[IDATA_START] Interval.notify.warning( 'Track.getIntervalStartTime(): Interval not found') - return 0.0 + return None def getIntervalEndTime(self, name): """ getIntervalEndTime(name) """ - for i in range(len(self.ilist)): - if (self.ilist[i][0].getName() == name): - return self.__computeDuration(i+1) + for idata in self.ilist: + if (idata[IDATA_IVAL].getName() == name): + return idata[IDATA_END] Interval.notify.warning( 'Track.getIntervalEndTime(): no Interval named: %s' % name) - return 0.0 + return None - def setT(self, t, entry=0): - """ setT(t, entry) + def updateFunc(self, t, event = IVAL_NONE): + """ updateFunc(t, event) Go to time t """ + # Make sure track actually contains some intervals + if not self.ilist: + Interval.notify.warning( + 'Track.updateFunc(): track has no intervals') + return + # Deterimine which interval, if any to evaluate if (t < 0): - return - elif (entry == 1): - self.currentInterval = None - if (len(self.ilist) == 0): - Interval.notify.warning('Track.setT(): track has no intervals') - return - elif (entry == 1) and (t > self.duration): - # Anything beyond the end of the track is assumed to be the - # final state of the last Interval on the track - self.ilist[len(self.ilist)-1][0].setT(t, entry=1) + # Before start of track, do nothing + pass else: - for i in self.ilist: - # Calculate the track relative start time for the interval - ival = i[0] - t0 = self.__getIntervalStartTime(ival) - - # Calculate the interval-relative time value for t - tc = t - t0 - - # There can only be one interval active at any given time - # per track, so see if we've crossed over - if ((t0 <= t) and (t <= t0 + ival.getDuration()) and - (self.currentInterval != ival)): - ival.setT(tc, entry=1) - self.currentInterval = ival - else: - ival.setT(tc) + # Initialize local variables + currentInterval = None + # First entry, re-init instance variables + if (event == IVAL_INIT): + # Initialize prev_t to max t of track + self.prev_t = self.getDuration() + # Clear record of currentInterval + self.currentInterval = None + # Compare t with start and end of each interval to determine + # which interval(s) to execute. + # If t falls between the start and end of an interval, that + # becomes the current interval. If we've crossed over the end + # of an interval ((prev_t < tEnd) and (t > tEnd)) then execute + # that interval at its final value. If we've crossed over the + # start of an interval ((prev_t > tStart) and (t < tStart)) + # then execute that interval at its start value + for ival, itime, itype, tStart, tEnd in self.ilist: + # Compare time with ival's start/end times + if (t < tStart): + if self.prev_t > tStart: + # We just crossed the start of this interval + # going backwards (e.g. via the slider) + # Execute this interval at its start time + ival.setT(0.0) + # Done checking intervals + break + elif (t >= tStart) and (t <= tEnd): + # Between start/end, record current interval + currentInterval = ival + # Make sure event == IVAL_INIT if entering new interval + if ((self.prev_t < tStart) or + (ival != self.currentInterval)): + event = IVAL_INIT + # Evaluate interval at interval relative time + currentInterval.setT(t - tStart, event) + # Done checking intervals + break + elif (t > tEnd): + # Crossing over interval end + if ((self.prev_t < tEnd) or + ((event == IVAL_INIT) and ival.getfOpenEnded())): + # If we've just crossed the end of this interval + # or its an INIT event after the interval's end + # and the interval is openended, + # then execute the interval at its end time + ival.setT(ival.getDuration()) + # May not be the last, keep checking other intervals + # Record current interval (may be None) + self.currentInterval = currentInterval def __repr__(self, indent=0): """ __repr__(indent) """ - str = Interval.__repr__(self, indent) - for i in self.ilist: - str = str + i[0].__repr__(indent+1) + str = Interval.__repr__(self, indent) + '\n' + for idata in self.ilist: + str = (str + idata[IDATA_IVAL].__repr__(indent+1) + + (' start: %0.2f end: %0.2f' % + (idata[IDATA_START], idata[IDATA_END])) + '\n' + ) return str diff --git a/direct/src/interval/WaitInterval.py b/direct/src/interval/WaitInterval.py index 8caf0d1eaa..84a2ae7a9a 100644 --- a/direct/src/interval/WaitInterval.py +++ b/direct/src/interval/WaitInterval.py @@ -4,17 +4,15 @@ from PandaModules import * from Interval import * class WaitInterval(Interval): - + # Name counter waitNum = 1 - - # special methods - + # Class methods def __init__(self, duration, name=None): """__init__(duration, name) """ + # Generate unique name if necessary if (name == None): - n = 'Wait-%d' % self.waitNum - self.waitNum = self.waitNum + 1 - else: - n = name - Interval.__init__(self, n, duration) + name = 'Wait-%d' % WaitInterval.waitNum + WaitInterval.waitNum += 1 + # Initialize superclass + Interval.__init__(self, name, duration)