diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 67814c10e3..9084ea10e2 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -211,7 +211,7 @@ class Actor(PandaObject, NodePath): """getPartNames(self): Return list of Actor part names. If not an multipart actor, returns 'modelRoot' NOTE: returns parts of first LOD""" - return self.__partBundleDict[0].keys() + return self.__partBundleDict.values()[0].keys() def getGeomNode(self): """getGeomNode(self) @@ -335,7 +335,7 @@ class Actor(PandaObject, NodePath): # get duration for named part only if (self.__animControlDict[lodName].has_key(partName)): - animControl = self.__getAnimControl(animName, partName, lodName) + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): return animControl.getFrameRate() else: @@ -357,7 +357,7 @@ class Actor(PandaObject, NodePath): if (animName==None): animName = self.getCurrentAnim(partName) - animControl = self.__getAnimControl(animName, partName, lodName) + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): return animControl.getPlayRate() else: @@ -382,7 +382,7 @@ class Actor(PandaObject, NodePath): for partName in partNames: if (animName==None): animName = self.getCurrentAnim(partName) - animControl = self.__getAnimControl(animName, partName, lodName) + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): animControl.setPlayRate(rate) @@ -401,7 +401,7 @@ class Actor(PandaObject, NodePath): # get duration for named part only if (self.__animControlDict[lodName].has_key(partName)): - animControl = self.__getAnimControl(animName, partName, lodName) + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): return (animControl.getNumFrames() / \ animControl.getFrameRate()) @@ -422,7 +422,7 @@ class Actor(PandaObject, NodePath): # loop through all anims for named part and find if any are playing if (self.__animControlDict[lodName].has_key(partName)): for animName in self.__animControlDict[lodName][partName].keys(): - if (self.__getAnimControl(animName, partName, lodName).isPlaying()): + if (self.getAnimControl(animName, partName, lodName).isPlaying()): return animName else: Actor.notify.warning("no part named %s" % (partName)) @@ -772,13 +772,13 @@ class Actor(PandaObject, NodePath): if (partName == None): # loop all parts for thisPart in animControlDict.keys(): - animControl = self.__getAnimControl(animName, thisPart, + animControl = self.getAnimControl(animName, thisPart, lodName) if (animControl != None): animControl.play() else: - animControl = self.__getAnimControl(animName, partName, + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): animControl.play() @@ -795,13 +795,13 @@ class Actor(PandaObject, NodePath): if (partName == None): # loop all parts for thisPart in animControlDict.keys(): - animControl = self.__getAnimControl(animName, thisPart, + animControl = self.getAnimControl(animName, thisPart, lodName) if (animControl != None): animControl.loop(restart) else: # loop a specific part - animControl = self.__getAnimControl(animName, partName, + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): animControl.loop(restart) @@ -816,21 +816,19 @@ class Actor(PandaObject, NodePath): if (partName==None): # pose all parts for thisPart in animControlDict.keys(): - animControl = self.__getAnimControl(animName, thisPart, + animControl = self.getAnimControl(animName, thisPart, lodName) if (animControl != None): animControl.pose(frame) else: # pose a specific part - animControl = self.__getAnimControl(animName, partName, + animControl = self.getAnimControl(animName, partName, lodName) if (animControl != None): animControl.pose(frame) - #private - - def __getAnimControl(self, animName, partName, lodName="lodRoot"): - """__getAnimControl(self, string, string, string="lodRoot") + def getAnimControl(self, animName, partName, lodName="lodRoot"): + """getAnimControl(self, string, string, string="lodRoot") Search the animControl dictionary indicated by lodName for a given anim and part. Return the animControl if present, or None otherwise diff --git a/direct/src/interval/AnimInterval.py b/direct/src/interval/AnimInterval.py index e67e546fa0..03ad2b3a21 100644 --- a/direct/src/interval/AnimInterval.py +++ b/direct/src/interval/AnimInterval.py @@ -7,43 +7,45 @@ class AnimInterval(Interval): # Name counter animNum = 1 # Class methods - def __init__(self, animControl, loop=0, name=None): + def __init__(self, animControl, loop = 0, duration = 0.0, name=None): """__init__(name) """ # Record class specific variables self.animControl = animControl - self.loop = loop + self.loop = loop # Generate unique name if necessary if (name == None): name = 'Anim-%d' % AnimInterval.animNum AnimInterval.animNum += 1 # Compute anim duration - duration = (float(animControl.getNumFrames()) / - animControl.getFrameRate()) + self.numFrames = self.animControl.getNumFrames() + if duration == 0.0: + duration = (float(self.numFrames)/animControl.getFrameRate()) # Initialize superclass Interval.__init__(self, name, duration) - def updateFunc(self, t, event = IVAL_NONE): """ updateFunc(t, event) Go to time t """ # Update animation based upon current time - if (t == self.getDuration()): - if (self.isPlaying == 1): - self.isPlaying = 0 - if (self.loop): - self.animControl.stop() + # Pose or stop anim + if (t >= self.getDuration()) or (event == IVAL_STOP): + self.animControl.stop() + elif self.loop == 1: + if event == IVAL_INIT: + # Determine the current frame + frame = (int(self.animControl.getFrameRate() * t) % + self.numFrames) + # Pose anim + self.animControl.pose(frame) + # And start loop + self.animControl.loop(0) else: - # Set flag - self.isPlaying = 1 - # Determine the current frame - frame = int(self.animControl.getFrameRate() * t) + # Determine the current frame + frame = (int(self.animControl.getFrameRate() * t) % + self.numFrames) # Pose anim - if (self.loop): - self.animControl.pos(frame) - self.animControl.loop(0) - else: - self.animControl.play(frame, self.animControl.getNumFrames()) - + self.animControl.pose(frame) + diff --git a/direct/src/interval/FunctionInterval.py b/direct/src/interval/FunctionInterval.py index dd402fa780..3b6d8b58ec 100644 --- a/direct/src/interval/FunctionInterval.py +++ b/direct/src/interval/FunctionInterval.py @@ -25,8 +25,9 @@ class FunctionInterval(Interval): """ updateFunc(t, event) Go to time t """ - # Evaluate the function - self.function() + if event != IVAL_STOP: + # Evaluate the function + self.function() ### FunctionInterval subclass for throwing events ### class EventInterval(FunctionInterval): diff --git a/direct/src/interval/Interval.py b/direct/src/interval/Interval.py index 441ff0663c..dd36cb61a8 100644 --- a/direct/src/interval/Interval.py +++ b/direct/src/interval/Interval.py @@ -7,6 +7,7 @@ import Task # Interval events IVAL_NONE = 0 IVAL_INIT = 1 +IVAL_STOP = 2 class Interval(DirectObject): """Interval class: Base class for timeline functionality""" @@ -98,6 +99,7 @@ class Interval(DirectObject): """ stop() """ taskMgr.removeTasksNamed(self.name + '-play') + self.setT(self.curr_t, event = IVAL_STOP) return self.curr_t def __playTask(self, task): @@ -137,8 +139,14 @@ class Interval(DirectObject): tl, text = 'Time', min = 0, max = string.atof(fpformat.fix(self.duration, 2)), command = lambda t, s = self: s.setT(t)) - es.onRelease = lambda s=self, es = es: s.setT(es.get(), - event = IVAL_INIT) + # So when you drag scale with mouse its like you started a playback + def onPress(s=self,es=es): + # Kill playback task + taskMgr.removeTasksNamed(s.name + '-play') + # INIT interval + s.setT(es.get(), event = IVAL_INIT) + es.onPress = onPress + es.onRelease = lambda s=self: s.stop() es.onReturnRelease = lambda s=self, es = es: s.setT(es.get(), event = IVAL_INIT) es.pack(expand = 1, fill = X) diff --git a/direct/src/interval/IntervalTest.py b/direct/src/interval/IntervalTest.py index 68a945a441..0333a7fdeb 100644 --- a/direct/src/interval/IntervalTest.py +++ b/direct/src/interval/IntervalTest.py @@ -1,12 +1,19 @@ from PandaModules import * from DirectSessionGlobal import * from IntervalGlobal import * +from Actor import * import Mopath boat = loader.loadModel('models/directmodels/smiley') boat.reparentTo(render) +donald = Actor() +donald.loadModel("phase_3/models/char/donald-wheel-mod") +donald.loadAnims({"steer":"phase_3/models/char/donald-wheel-chan"}) +steerAnimControl = donald.getAnimControl('steer', 'modelRoot') +donald.reparentTo(boat) + dock = loader.loadModel('models/directmodels/smiley') dock.reparentTo(render) @@ -21,6 +28,14 @@ boatTrack = Track([boatMopath], 'boattrack') BOAT_START = boatTrack.getIntervalStartTime('boatpath') BOAT_END = boatTrack.getIntervalEndTime('boatpath') +# This will create an anim interval that is posed every frame +donaldSteerInterval = AnimInterval(steerAnimControl) +# This will create an anim interval that is started at t = 0 and then +# loops for 10 seconds +donaldLoopInterval = AnimInterval(steerAnimControl, loop = 1, duration = 10.0) +donaldSteerTrack = Track([donaldSteerInterval, donaldLoopInterval], + name = 'steerTrack') + # Make the dock lerp up so that it's up when the boat reaches the end of # its mopath dockLerp = LerpPosHprInterval(dock, 5.0, @@ -48,7 +63,8 @@ waterDone = EventInterval('water-is-done') waterEventTrack = Track([waterDone]) waterEventTrack.setIntervalStartTime('water-is-done', eventTime) -mtrack = MultiTrack([boatTrack, dockTrack, soundTrack, waterEventTrack]) +mtrack = MultiTrack([boatTrack, dockTrack, soundTrack, waterEventTrack, + donaldSteerTrack]) # Print out MultiTrack parameters print(mtrack) diff --git a/direct/src/interval/MultiTrack.py b/direct/src/interval/MultiTrack.py index e3b3862772..3ee170190a 100644 --- a/direct/src/interval/MultiTrack.py +++ b/direct/src/interval/MultiTrack.py @@ -44,9 +44,9 @@ class MultiTrack(Interval): # Compare time with track's end times if (t > tEnd): if (self.prev_t < tEnd) or (event == IVAL_INIT): - track.setT(t) + track.setT(t, event) else: - track.setT(t) + track.setT(t, event) def __repr__(self, indent=0): """ __repr__(indent) diff --git a/direct/src/interval/SoundInterval.py b/direct/src/interval/SoundInterval.py index 6cf4cf9cd4..70bf507084 100644 --- a/direct/src/interval/SoundInterval.py +++ b/direct/src/interval/SoundInterval.py @@ -26,7 +26,7 @@ class SoundInterval(Interval): """ updateFunc(t, event) Go to time t """ - if(t == self.duration): + if (t == self.duration) or (event == IVAL_STOP): # Stop sound if necessary if (self.isPlaying == 1): self.isPlaying = 0 diff --git a/direct/src/interval/Track.py b/direct/src/interval/Track.py index 577f556450..37e0ff2950 100644 --- a/direct/src/interval/Track.py +++ b/direct/src/interval/Track.py @@ -168,19 +168,20 @@ class Track(Interval): 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: + if (self.prev_t > tStart) and (event != IVAL_STOP): # 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) + ival.setT(0.0, event) # 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)): + if ((event == IVAL_NONE) and + ((self.prev_t < tStart) or + (ival != self.currentInterval))): event = IVAL_INIT # Evaluate interval at interval relative time currentInterval.setT(t - tStart, event) @@ -188,13 +189,13 @@ class Track(Interval): break elif (t > tEnd): # Crossing over interval end - if ((self.prev_t < tEnd) or + if (((event == IVAL_NONE) and (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()) + ival.setT(ival.getDuration(), event) # May not be the last, keep checking other intervals # Record current interval (may be None) self.currentInterval = currentInterval diff --git a/direct/src/tkwidgets/EntryScale.py b/direct/src/tkwidgets/EntryScale.py index d804cc2440..ea04f66d01 100644 --- a/direct/src/tkwidgets/EntryScale.py +++ b/direct/src/tkwidgets/EntryScale.py @@ -36,6 +36,7 @@ class EntryScale(Pmw.MegaWidget): # Initialize some class variables self.value = self['initialValue'] self.entryFormat = '%.2f' + self.fScaleCommand = 0 # Create the components. @@ -104,12 +105,8 @@ class EntryScale(Pmw.MegaWidget): self.scale.pack(side = 'left', expand = 1, fill = 'x') # Set scale to the middle of its range self.scale.set(self['initialValue']) - self.scale.bind('', - lambda event, s = self: - apply(s.onPress, s['callbackData'])) - self.scale.bind('', - lambda event, s = self: - apply(s.onRelease, s['callbackData'])) + self.scale.bind('', self.__onPress) + self.scale.bind('', self.__onRelease) self.maxLabel = self.createcomponent('maxLabel', (), None, Button, self.minMaxFrame, @@ -174,6 +171,8 @@ class EntryScale(Pmw.MegaWidget): self.maxLabel['text'] = self['max'] def _scaleCommand(self, strVal): + if not self.fScaleCommand: + return # convert scale val to float self.set(string.atof(strVal)) """ @@ -213,7 +212,7 @@ class EntryScale(Pmw.MegaWidget): # Round by resolution if self['resolution'] is not None: newVal = round(newVal / self['resolution']) * self['resolution'] - + # Record updated value self.value = newVal # Update scale's position @@ -234,10 +233,22 @@ class EntryScale(Pmw.MegaWidget): """ User redefinable callback executed on release in entry """ pass + def __onPress(self, event): + # First execute onpress callback + apply(self.onPress, self['callbackData']) + # Now enable slider command + self.fScaleCommand = 1 + def onPress(self, *args): """ User redefinable callback executed on button press """ pass + def __onRelease(self, event): + # Now disable slider command + self.fScaleCommand = 0 + # First execute onpress callback + apply(self.onRelease, self['callbackData']) + def onRelease(self, *args): """ User redefinable callback executed on button release """ pass