|
@@ -14,17 +14,27 @@ class ActorInterval(Interval.Interval):
|
|
|
# Name counter
|
|
# Name counter
|
|
|
animNum = 1
|
|
animNum = 1
|
|
|
# Class methods
|
|
# Class methods
|
|
|
- # Interval used to play an animation. If loop = 0, animation is
|
|
|
|
|
- # played only once and the pose of the anim depends on t passed
|
|
|
|
|
- # into the setT method every frame. If loop = 1, the animation is
|
|
|
|
|
- # started and plays on its own and stopped when t >= duration or
|
|
|
|
|
- # playback stop event occurs. If no duration is specified, interval
|
|
|
|
|
- # duration defaults to be equal to the length of the animation.
|
|
|
|
|
- # Note: if loop == 0 and duration > anim duration then the animation
|
|
|
|
|
- # will play once and then nothing will happen for the remainder of the
|
|
|
|
|
- # interval
|
|
|
|
|
- def __init__(self, actor, animName, loop=0, duration=0.0,
|
|
|
|
|
- startTime=0.0, endTime=None, playRate=1.0, name=None):
|
|
|
|
|
|
|
+
|
|
|
|
|
+ # Plays an animation on an Actor. The subrange of the animation
|
|
|
|
|
+ # to be played may be specified via frames (startFrame up to and
|
|
|
|
|
+ # including endFrame) or seconds (startTime up to and including
|
|
|
|
|
+ # endTime). If neither is specified, the default is the entire
|
|
|
|
|
+ # range of the animation.
|
|
|
|
|
+
|
|
|
|
|
+ # The duration may be implicit or explicit. If it is omitted, it
|
|
|
|
|
+ # is taken to be endTime - startTime. There's not much point in
|
|
|
|
|
+ # specifying otherwise unless you also specify loop=1, which will
|
|
|
|
|
+ # loop the animation over its frame range during the duration of
|
|
|
|
|
+ # the interval.
|
|
|
|
|
+
|
|
|
|
|
+ # Note: if loop == 0 and duration > anim duration then the
|
|
|
|
|
+ # animation will play once and then hold its final pose for the
|
|
|
|
|
+ # remainder of the interval.
|
|
|
|
|
+
|
|
|
|
|
+ def __init__(self, actor, animName, loop=0, duration=None,
|
|
|
|
|
+ startTime=None, endTime=None,
|
|
|
|
|
+ startFrame=None, endFrame=None,
|
|
|
|
|
+ playRate=1.0, name=None):
|
|
|
"""__init__(name)
|
|
"""__init__(name)
|
|
|
"""
|
|
"""
|
|
|
# Generate unique id
|
|
# Generate unique id
|
|
@@ -34,58 +44,67 @@ class ActorInterval(Interval.Interval):
|
|
|
self.actor = actor
|
|
self.actor = actor
|
|
|
self.animName = animName
|
|
self.animName = animName
|
|
|
self.controls = self.actor.getAnimControls(self.animName)
|
|
self.controls = self.actor.getAnimControls(self.animName)
|
|
|
- assert(len(self.controls) > 0)
|
|
|
|
|
self.loopAnim = loop
|
|
self.loopAnim = loop
|
|
|
- self.frameRate = self.controls[0].getAnim().getBaseFrameRate() * playRate
|
|
|
|
|
- self.numFrames = self.controls[0].getNumFrames()
|
|
|
|
|
- # Compute start time
|
|
|
|
|
- self.startTime = startTime
|
|
|
|
|
|
|
+
|
|
|
# If no name specified, use id as name
|
|
# If no name specified, use id as name
|
|
|
if (name == None):
|
|
if (name == None):
|
|
|
name = id
|
|
name = id
|
|
|
- # Compute duration if no duration specified
|
|
|
|
|
- self.reverse = 0
|
|
|
|
|
- if duration == 0.0:
|
|
|
|
|
- if (endTime == None):
|
|
|
|
|
- duration = max(self.actor.getDuration(self.animName) - \
|
|
|
|
|
- startTime, 0.0)
|
|
|
|
|
- else:
|
|
|
|
|
- duration = endTime - startTime
|
|
|
|
|
- if (duration < 0.0):
|
|
|
|
|
- duration = -duration
|
|
|
|
|
- if (endTime == None):
|
|
|
|
|
- self.finishTime = self.startTime + duration
|
|
|
|
|
|
|
+
|
|
|
|
|
+ if len(self.controls) == 0:
|
|
|
|
|
+ self.notify.warning("Unknown animation for actor: %s" % (self.animName))
|
|
|
|
|
+ self.frameRate = 1.0
|
|
|
|
|
+ self.startFrame = 0
|
|
|
|
|
+ self.endFrame = 0
|
|
|
else:
|
|
else:
|
|
|
- self.finishTime = endTime
|
|
|
|
|
- if (self.startTime > self.finishTime):
|
|
|
|
|
|
|
+
|
|
|
|
|
+ self.frameRate = self.controls[0].getAnim().getBaseFrameRate() * abs(playRate)
|
|
|
|
|
+ # Compute start and end frames.
|
|
|
|
|
+ if startFrame != None:
|
|
|
|
|
+ self.startFrame = startFrame
|
|
|
|
|
+ elif startTime != None:
|
|
|
|
|
+ self.startFrame = int(math.floor(startTime * self.frameRate + 0.0001))
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.startFrame = 0
|
|
|
|
|
+
|
|
|
|
|
+ if endFrame != None:
|
|
|
|
|
+ self.endFrame = endFrame
|
|
|
|
|
+ elif endTime != None:
|
|
|
|
|
+ self.endFrame = int(math.floor(endTime * self.frameRate + 0.0001))
|
|
|
|
|
+ else:
|
|
|
|
|
+ self.endFrame = self.controls[0].getNumFrames() - 1
|
|
|
|
|
+
|
|
|
|
|
+ # Must we play the animation backwards?
|
|
|
|
|
+ self.reverse = 0
|
|
|
|
|
+ if self.endFrame < self.startFrame:
|
|
|
self.reverse = 1
|
|
self.reverse = 1
|
|
|
|
|
+ t = self.endFrame
|
|
|
|
|
+ self.endFrame = self.startFrame
|
|
|
|
|
+ self.startFrame = t
|
|
|
|
|
+
|
|
|
|
|
+ self.numFrames = self.endFrame - self.startFrame + 1
|
|
|
|
|
+
|
|
|
|
|
+ # Compute duration if no duration specified
|
|
|
|
|
+ self.implicitDuration = 0
|
|
|
|
|
+ if duration == None:
|
|
|
|
|
+ self.implicitDuration = 1
|
|
|
|
|
+ duration = float(self.numFrames - 1) / self.frameRate
|
|
|
|
|
|
|
|
# Initialize superclass
|
|
# Initialize superclass
|
|
|
Interval.Interval.__init__(self, name, duration)
|
|
Interval.Interval.__init__(self, name, duration)
|
|
|
|
|
|
|
|
- def calcFrame(self, t):
|
|
|
|
|
- segmentLength = abs(self.finishTime - self.startTime)
|
|
|
|
|
- if segmentLength == 0:
|
|
|
|
|
- offset = 0
|
|
|
|
|
|
|
+ def privStep(self, t):
|
|
|
|
|
+ # Calc integer frame number
|
|
|
|
|
+ frame = int(math.floor(t * self.frameRate + 0.0001))
|
|
|
|
|
+ if self.loopAnim:
|
|
|
|
|
+ frame = frame % self.numFrames
|
|
|
else:
|
|
else:
|
|
|
- offset = t % segmentLength
|
|
|
|
|
- # Handle boundary case where we want to set the final frame
|
|
|
|
|
- if (t == self.getDuration() and offset < 0.0001):
|
|
|
|
|
- offset = segmentLength
|
|
|
|
|
- # Compute current frame based upon current time
|
|
|
|
|
- if (self.reverse == 0):
|
|
|
|
|
- floatFrame = self.frameRate * (self.startTime + offset)
|
|
|
|
|
|
|
+ frame = max(min(frame, self.numFrames - 1), 0)
|
|
|
|
|
+
|
|
|
|
|
+ if self.reverse:
|
|
|
|
|
+ frame = self.endFrame - frame
|
|
|
else:
|
|
else:
|
|
|
- negOffset = (self.startTime - self.finishTime) - offset
|
|
|
|
|
- floatFrame = self.frameRate * (self.finishTime + negOffset)
|
|
|
|
|
- # Need max to avoid frame = -1 when t = 0
|
|
|
|
|
- frame = max(0, int(math.ceil(floatFrame)) - 1)
|
|
|
|
|
- # Modulo in case of looping anim
|
|
|
|
|
- return frame % self.numFrames
|
|
|
|
|
-
|
|
|
|
|
- def goToT(self, t):
|
|
|
|
|
- # Calc integer frame number
|
|
|
|
|
- frame = self.calcFrame(t)
|
|
|
|
|
|
|
+ frame = self.startFrame + frame
|
|
|
|
|
+
|
|
|
# Pose anim
|
|
# Pose anim
|
|
|
|
|
|
|
|
# We use our pre-computed list of animControls for
|
|
# We use our pre-computed list of animControls for
|
|
@@ -94,33 +113,26 @@ class ActorInterval(Interval.Interval):
|
|
|
for control in self.controls:
|
|
for control in self.controls:
|
|
|
control.pose(frame)
|
|
control.pose(frame)
|
|
|
|
|
|
|
|
- return frame
|
|
|
|
|
-
|
|
|
|
|
- def privInitialize(self, t):
|
|
|
|
|
self.state = CInterval.SStarted
|
|
self.state = CInterval.SStarted
|
|
|
- self.goToT(t)
|
|
|
|
|
- if self.loopAnim:
|
|
|
|
|
- self.actor.loop(self.animName, restart = 0)
|
|
|
|
|
self.currT = t
|
|
self.currT = t
|
|
|
|
|
|
|
|
def privFinalize(self):
|
|
def privFinalize(self):
|
|
|
- if self.loopAnim:
|
|
|
|
|
- self.actor.stop()
|
|
|
|
|
|
|
+ if self.implicitDuration:
|
|
|
|
|
+ # As a special case, we ensure we end up posed to the last
|
|
|
|
|
+ # frame of the animation if the original duration was
|
|
|
|
|
+ # implicit. This is necessary only to guard against
|
|
|
|
|
+ # possible roundoff error in computing the final frame
|
|
|
|
|
+ # from the duration.
|
|
|
|
|
+ for control in self.controls:
|
|
|
|
|
+ control.pose(self.endFrame)
|
|
|
|
|
+
|
|
|
else:
|
|
else:
|
|
|
- self.goToT(self.getDuration())
|
|
|
|
|
- self.currT = self.getDuration()
|
|
|
|
|
- self.state = CInterval.SFinal
|
|
|
|
|
|
|
+ # Otherwise, the user-specified duration determines which
|
|
|
|
|
+ # is our final frame.
|
|
|
|
|
+ self.privStep(self.getDuration())
|
|
|
|
|
|
|
|
- def privStep(self, t):
|
|
|
|
|
- if not self.loopAnim:
|
|
|
|
|
- self.goToT(t)
|
|
|
|
|
-
|
|
|
|
|
- self.state = CInterval.SStarted
|
|
|
|
|
- self.currT = t
|
|
|
|
|
-
|
|
|
|
|
- def privInterrupt(self):
|
|
|
|
|
- if self.loopAnim:
|
|
|
|
|
- self.actor.stop
|
|
|
|
|
|
|
+ self.state = CInterval.SFinal
|
|
|
|
|
+ self.intervalDone()
|
|
|
|
|
|
|
|
|
|
|
|
|
class LerpAnimInterval(CLerpAnimEffectInterval):
|
|
class LerpAnimInterval(CLerpAnimEffectInterval):
|