mirror of
https://github.com/panda3d/panda3d.git
synced 2026-02-14 02:58:41 -06:00
new C++-based intervals
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
#define BUILDING_DLL BUILDING_DIRECT
|
||||
|
||||
#define COMPONENT_LIBS \
|
||||
directbase dcparser showbase deadrec directd
|
||||
directbase dcparser showbase deadrec directd interval
|
||||
|
||||
#define OTHER_LIBS panda pandaexpress dtoolconfig dtool
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ class ActorInterval(Interval.Interval):
|
||||
self.goToT(t)
|
||||
|
||||
|
||||
class LerpAnimInterval(Interval.Interval):
|
||||
class LerpAnimInterval(CLerpAnimEffectInterval):
|
||||
# Blends between two anims. Start both anims first (or use
|
||||
# parallel ActorIntervals), then invoke LerpAnimInterval to
|
||||
# smoothly blend the control effect from the first to the second.
|
||||
@@ -131,58 +131,25 @@ class LerpAnimInterval(Interval.Interval):
|
||||
def __init__(self, actor, duration, startAnim, endAnim,
|
||||
startWeight = 0.0, endWeight = 1.0,
|
||||
blendType = 'noBlend', name = None):
|
||||
""" __init__(actor, duration, pos, startPos, other, blendType, name)
|
||||
"""
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpAnimInterval-%d' % LerpAnimInterval.lerpAnimNum
|
||||
LerpAnimInterval.lerpAnimNum += 1
|
||||
|
||||
# Record class specific variables
|
||||
self.actor = actor
|
||||
self.startAnim = startAnim
|
||||
self.endAnim = endAnim
|
||||
self.startWeight = startWeight
|
||||
self.deltaWeight = endWeight - startWeight
|
||||
self.blendType = self.getBlend(blendType)
|
||||
blendType = self.stringBlendType(blendType)
|
||||
assert(blendType != self.BTInvalid)
|
||||
|
||||
# Initialize superclass
|
||||
Interval.Interval.__init__(self, name, duration)
|
||||
CLerpAnimEffectInterval.__init__(self, name, duration, blendType)
|
||||
|
||||
|
||||
def updateFunc(self, t, event=Interval.IVAL_NONE):
|
||||
""" updateFunc(t, event)
|
||||
Go to time t
|
||||
"""
|
||||
if (self.actor.isEmpty()):
|
||||
self.notify.warning('updateFunc() - %s empty actor!' % self.name)
|
||||
return
|
||||
|
||||
# First, normalize t into the range 0 .. 1, and apply the blendType.
|
||||
t = self.blendType(float(t) / self.duration)
|
||||
|
||||
# Then compute the current weight based on the time elapsed so far.
|
||||
w = self.startWeight + t * self.deltaWeight
|
||||
|
||||
# Apply that weight to the two anims.
|
||||
if self.startAnim != None:
|
||||
self.actor.setControlEffect(self.startAnim, 1.0 - w)
|
||||
if self.endAnim != None:
|
||||
self.actor.setControlEffect(self.endAnim, w)
|
||||
|
||||
|
||||
def getBlend(self, blendType):
|
||||
"""__getBlend(self, string)
|
||||
Return the C++ blend class corresponding to blendType string
|
||||
"""
|
||||
if (blendType == "easeIn"):
|
||||
return LerpBlendHelpers.easeIn
|
||||
elif (blendType == "easeOut"):
|
||||
return LerpBlendHelpers.easeOut
|
||||
elif (blendType == "easeInOut"):
|
||||
return LerpBlendHelpers.easeInOut
|
||||
elif (blendType == "noBlend"):
|
||||
return LerpBlendHelpers.noBlend
|
||||
else:
|
||||
raise Exception(
|
||||
'Error: LerpAnimInterval.getBlend: Unknown blend type')
|
||||
if startAnim != None:
|
||||
controls = actor.getAnimControls(startAnim)
|
||||
for control in controls:
|
||||
self.addControl(control, startAnim,
|
||||
1.0 - startWeight, 1.0 - endWeight)
|
||||
|
||||
if endAnim != None:
|
||||
controls = actor.getAnimControls(endAnim)
|
||||
for control in controls:
|
||||
self.addControl(control, endAnim,
|
||||
startWeight, endWeight)
|
||||
|
||||
@@ -27,7 +27,7 @@ class FunctionInterval(Interval.Interval):
|
||||
self.function = function
|
||||
# Create a unique name for the interval if necessary
|
||||
if (name == None):
|
||||
name = 'FunctionInterval-%d' % FunctionInterval.functionIntervalNum
|
||||
name = 'FunctionInterval-%s-%d' % (function.__name__, FunctionInterval.functionIntervalNum)
|
||||
FunctionInterval.functionIntervalNum += 1
|
||||
assert(isinstance(name, types.StringType))
|
||||
# Record any arguments
|
||||
|
||||
@@ -5,9 +5,9 @@ from PandaModules import *
|
||||
import Task
|
||||
|
||||
# Interval events
|
||||
IVAL_NONE = 0
|
||||
IVAL_INIT = 1
|
||||
IVAL_DONE = 2
|
||||
IVAL_NONE = CInterval.ETStep
|
||||
IVAL_INIT = CInterval.ETInitialize
|
||||
IVAL_DONE = CInterval.ETFinalize
|
||||
|
||||
class Interval(DirectObject):
|
||||
"""Interval class: Base class for timeline functionality"""
|
||||
@@ -75,7 +75,7 @@ class Interval(DirectObject):
|
||||
def setFinalT(self):
|
||||
""" setFinalT()
|
||||
"""
|
||||
self.setT(self.getDuration(), event=IVAL_DONE)
|
||||
self.setT(self.getDuration(), IVAL_DONE)
|
||||
|
||||
def play(self, t0=0.0, duration=0.0, scale=1.0):
|
||||
""" play(t0, duration)
|
||||
@@ -133,7 +133,7 @@ class Interval(DirectObject):
|
||||
if (te < self.endTime):
|
||||
if (self.firstTime):
|
||||
# If first call, init intervals
|
||||
self.setT(te, event = IVAL_INIT)
|
||||
self.setT(te, IVAL_INIT)
|
||||
self.firstTime = 0
|
||||
else:
|
||||
self.setT(te)
|
||||
@@ -142,7 +142,7 @@ class Interval(DirectObject):
|
||||
te = self.endTime
|
||||
if (self.firstTime):
|
||||
# If first call, init intervals
|
||||
self.setT(te, event = IVAL_INIT)
|
||||
self.setT(te, IVAL_INIT)
|
||||
self.firstTime = 0
|
||||
else:
|
||||
self.setT(te, IVAL_DONE)
|
||||
@@ -181,23 +181,23 @@ class Interval(DirectObject):
|
||||
# Kill playback task
|
||||
taskMgr.remove(s.name + '-play')
|
||||
# INIT interval
|
||||
s.setT(es.get(), event = IVAL_INIT)
|
||||
s.setT(es.get(), IVAL_INIT)
|
||||
es.onPress = onPress
|
||||
# To make sure you stop free running intervals
|
||||
es.onRelease = lambda s=self: s.stop()
|
||||
# To update scale and execute intervals with IVAL_INIT
|
||||
def onReturn(s = self, es = es):
|
||||
s.setT(es.get(), event = IVAL_INIT)
|
||||
s.setT(es.get(), IVAL_INIT)
|
||||
s.stop()
|
||||
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, event = IVAL_INIT)
|
||||
s.setT(0.0, IVAL_INIT)
|
||||
s.stop()
|
||||
def toEnd(s=self):
|
||||
s.setT(s.getDuration(), event = IVAL_INIT)
|
||||
s.setT(s.getDuration(), IVAL_INIT)
|
||||
s.stop()
|
||||
jumpToStart = Button(bf, text = '<<', command = toStart)
|
||||
# Stop/play buttons
|
||||
|
||||
@@ -9,6 +9,4 @@ from MopathInterval import *
|
||||
from ParticleInterval import *
|
||||
from SoundInterval import *
|
||||
from WaitInterval import *
|
||||
|
||||
from Track import *
|
||||
from MultiTrack import *
|
||||
from MetaInterval import *
|
||||
|
||||
@@ -5,6 +5,262 @@ from DirectNotifyGlobal import *
|
||||
import Interval
|
||||
import LerpBlendHelpers
|
||||
|
||||
#
|
||||
# Most of the intervals defined in this module--the group up here at
|
||||
# the front of the file--are now derived from a CInterval instead of
|
||||
# an Interval, so they can run in the low-level C++ code at high
|
||||
# performance.
|
||||
#
|
||||
|
||||
class LerpNodePathInterval(CLerpNodePathInterval):
|
||||
# This is the base class for all of the lerps, defined below, that
|
||||
# affect a property on a NodePath, like pos or hpr.
|
||||
lerpNodePathNum = 1
|
||||
|
||||
def __init__(self, name, duration, blendType, node, other):
|
||||
if name == None:
|
||||
name = '%s-%d' % (self.__class__.__name__, self.lerpNodePathNum)
|
||||
LerpNodePathInterval.lerpNodePathNum += 1
|
||||
|
||||
blendType = self.stringBlendType(blendType)
|
||||
assert(blendType != self.BTInvalid)
|
||||
|
||||
if other == None:
|
||||
other = NodePath()
|
||||
|
||||
CLerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
|
||||
def anyCallable(self, *params):
|
||||
# Returns true if any of the parameters listed is a callable
|
||||
# functor, false if none of them are. This is used by derived
|
||||
# classes to determine if a functor was passed in for a
|
||||
# parameter.
|
||||
|
||||
for param in params:
|
||||
if callable(param):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def setupParam(self, func, param):
|
||||
# Stores the indicated parameter by passing it to the given
|
||||
# function (probably a C++ setter function). If the param is
|
||||
# a callable functor, calls it; otherwise, uses the param
|
||||
# directly.
|
||||
if param != None:
|
||||
if callable(param):
|
||||
func(param())
|
||||
else:
|
||||
func(param)
|
||||
|
||||
#####################################################################
|
||||
##
|
||||
## It is legal to pass in a functor for the any of the pos, hpr,
|
||||
## or scale parameters in the intervals below. These will be
|
||||
## evaluated at the time the interval starts in order to determine
|
||||
## the actual final position. However, doing so forces the entire
|
||||
## LerpInterval to be executed up in Python, instead of down in the
|
||||
## low-level C++ code, at a significant performance cost.
|
||||
##
|
||||
#####################################################################
|
||||
|
||||
class LerpPosInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, pos, startPos = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(pos, startPos):
|
||||
self.endPos = pos
|
||||
self.startPos = startPos
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndPos(pos)
|
||||
if startPos != None:
|
||||
self.setStartPos(startPos)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndPos, self.endPos)
|
||||
self.setupParam(self.setStartPos, self.startPos)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
|
||||
class LerpHprInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, hpr, startHpr = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(hpr, startHpr):
|
||||
self.endHpr = hpr
|
||||
self.startHpr = startHpr
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndHpr(hpr)
|
||||
if startHpr != None:
|
||||
self.setStartHpr(startHpr)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndHpr, self.endHpr)
|
||||
self.setupParam(self.setStartHpr, self.startHpr)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
class LerpScaleInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, scale, startScale = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(scale, startScale):
|
||||
self.endScale = scale
|
||||
self.startScale = startScale
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndScale(scale)
|
||||
if startScale != None:
|
||||
self.setStartScale(startScale)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndScale, self.endScale)
|
||||
self.setupParam(self.setStartScale, self.startScale)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
class LerpPosHprInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, pos, hpr,
|
||||
startPos = None, startHpr = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(pos, startPos, hpr, startHpr):
|
||||
self.endPos = pos
|
||||
self.startPos = startPos
|
||||
self.endHpr = hpr
|
||||
self.startHpr = startHpr
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndPos(pos)
|
||||
if startPos != None:
|
||||
self.setStartPos(startPos)
|
||||
self.setEndHpr(hpr)
|
||||
if startHpr != None:
|
||||
self.setStartHpr(startHpr)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndPos, self.endPos)
|
||||
self.setupParam(self.setStartPos, self.startPos)
|
||||
self.setupParam(self.setEndHpr, self.endHpr)
|
||||
self.setupParam(self.setStartHpr, self.startHpr)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
class LerpHprScaleInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, hpr, scale,
|
||||
startHpr = None, startScale = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(hpr, startHpr, scale, startScale):
|
||||
self.endHpr = hpr
|
||||
self.startHpr = startHpr
|
||||
self.endScale = scale
|
||||
self.startScale = startScale
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndHpr(hpr)
|
||||
if startHpr != None:
|
||||
self.setStartHpr(startHpr)
|
||||
self.setEndScale(scale)
|
||||
if startScale != None:
|
||||
self.setStartScale(startScale)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndHpr, self.endHpr)
|
||||
self.setupParam(self.setStartHpr, self.startHpr)
|
||||
self.setupParam(self.setEndScale, self.endScale)
|
||||
self.setupParam(self.setStartScale, self.startScale)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
class LerpPosHprScaleInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, pos, hpr, scale,
|
||||
startPos = None, startHpr = None, startScale = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
# Check for functors in the input parameters.
|
||||
if self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale):
|
||||
self.endPos = pos
|
||||
self.startPos = startPos
|
||||
self.endHpr = hpr
|
||||
self.startHpr = startHpr
|
||||
self.endScale = scale
|
||||
self.startScale = startScale
|
||||
self.inPython = 1
|
||||
else:
|
||||
self.setEndPos(pos)
|
||||
if startPos != None:
|
||||
self.setStartPos(startPos)
|
||||
self.setEndHpr(hpr)
|
||||
if startHpr != None:
|
||||
self.setStartHpr(startHpr)
|
||||
self.setEndScale(scale)
|
||||
if startScale != None:
|
||||
self.setStartScale(startScale)
|
||||
|
||||
def setT(self, t, event):
|
||||
# This function is only used if Python functors were passed in
|
||||
# for some of the input parameters.
|
||||
if event == Interval.IVAL_INIT:
|
||||
self.setupParam(self.setEndPos, self.endPos)
|
||||
self.setupParam(self.setStartPos, self.startPos)
|
||||
self.setupParam(self.setEndHpr, self.endHpr)
|
||||
self.setupParam(self.setStartHpr, self.startHpr)
|
||||
self.setupParam(self.setEndScale, self.endScale)
|
||||
self.setupParam(self.setStartScale, self.startScale)
|
||||
LerpNodePathInterval.setT(self, t, event)
|
||||
|
||||
class LerpColorScaleInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, colorScale, startColorScale = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
self.setEndColorScale(colorScale)
|
||||
if startColorScale != None:
|
||||
self.setStartColorScale(startColorScale)
|
||||
|
||||
class LerpColorInterval(LerpNodePathInterval):
|
||||
def __init__(self, node, duration, color, startColor = None,
|
||||
other = None, blendType = 'noBlend', name = None):
|
||||
LerpNodePathInterval.__init__(self, name, duration, blendType,
|
||||
node, other)
|
||||
self.setEndColor(color)
|
||||
if startColor != None:
|
||||
self.setStartColor(startColor)
|
||||
|
||||
|
||||
#
|
||||
# The remaining intervals defined in this module are the old-school
|
||||
# Python-based intervals.
|
||||
#
|
||||
|
||||
class LerpInterval(Interval.Interval):
|
||||
# create LerpInterval DirectNotify category
|
||||
notify = directNotify.newCategory('LerpInterval')
|
||||
@@ -51,342 +307,6 @@ class LerpInterval(Interval.Interval):
|
||||
raise Exception(
|
||||
'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)
|
||||
"""
|
||||
def functorFunc(node=node, pos=pos, startPos=startPos,
|
||||
other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(pos):
|
||||
# This may be a thunk that returns a point.
|
||||
pos = pos()
|
||||
# Make a our own copy of the parameters:
|
||||
if (pos != None): pos=Point3(pos)
|
||||
if (startPos != None): startPos=Point3(startPos)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startPos == None):
|
||||
startPos = node.getPos(other)
|
||||
functor = PosLerpFunctor(node, startPos, pos, other)
|
||||
else:
|
||||
if (startPos == None):
|
||||
startPos = node.getPos()
|
||||
functor = PosLerpFunctor(node, startPos, pos)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpPosInterval-%d' % LerpPosInterval.lerpPosNum
|
||||
LerpPosInterval.lerpPosNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
class LerpHprInterval(LerpInterval):
|
||||
# Name counter
|
||||
lerpHprNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, hpr, startHpr=None,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
""" __init__(node, duration, hpr, startHpr, other, blendType, name)
|
||||
"""
|
||||
def functorFunc(node=node, hpr=hpr, startHpr=startHpr,
|
||||
other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(hpr):
|
||||
# This may be a thunk that returns a point.
|
||||
hpr = hpr()
|
||||
# Make a our own copy of the parameters:
|
||||
if (hpr != None): hpr=VBase3(hpr)
|
||||
if (startHpr != None): startHpr=VBase3(startHpr)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startHpr == None):
|
||||
startHpr = VBase3(node.getHpr(other))
|
||||
functor = HprLerpFunctor(node, startHpr, hpr, other)
|
||||
else:
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr()
|
||||
functor = HprLerpFunctor(node, startHpr, hpr)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpHprInterval-%d' % LerpHprInterval.lerpHprNum
|
||||
LerpHprInterval.lerpHprNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
class LerpScaleInterval(LerpInterval):
|
||||
|
||||
# Interval counter
|
||||
lerpScaleNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, scale, startScale=None,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
""" __init__(node, duration, scale, startScale, other, blendType, name)
|
||||
"""
|
||||
def functorFunc(node=node, scale=scale,
|
||||
startScale=startScale, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(scale):
|
||||
# This may be a thunk that returns a point.
|
||||
scale = scale()
|
||||
# Make a our own copy of the parameters:
|
||||
if (scale != None): scale=VBase3(scale)
|
||||
if (startScale != None): startScale=VBase3(startScale)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startScale == None):
|
||||
startScale = node.getScale(other)
|
||||
functor = ScaleLerpFunctor(node, startScale, scale, other)
|
||||
else:
|
||||
if (startScale == None):
|
||||
startScale = node.getScale()
|
||||
functor = ScaleLerpFunctor(node, startScale, scale)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpScaleInterval-%d' % LerpScaleInterval.lerpScaleNum
|
||||
LerpScaleInterval.lerpScaleNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
class LerpPosHprInterval(LerpInterval):
|
||||
# Interval counter
|
||||
|
||||
lerpPosHprNum = 1
|
||||
|
||||
def __init__(self, node, duration, pos, hpr, startPos=None,
|
||||
startHpr=None, other=None, blendType='noBlend', name=None):
|
||||
""" __init__(node, duration, pos, hpr, startPos, startHpr,
|
||||
other, blendType, name)
|
||||
"""
|
||||
def functorFunc(node=node, pos=pos, hpr=hpr,
|
||||
startPos=startPos, startHpr=startHpr, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(pos):
|
||||
# This may be a thunk that returns a point.
|
||||
pos = pos()
|
||||
if callable(hpr):
|
||||
# This may be a thunk that returns a point.
|
||||
hpr = hpr()
|
||||
# Make a our own copy of the parameters:
|
||||
if (pos != None): pos=Point3(pos)
|
||||
if (hpr != None): hpr=VBase3(hpr)
|
||||
if (startPos != None): startPos=Point3(startPos)
|
||||
if (startHpr != None): startHpr=VBase3(startHpr)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startPos == None):
|
||||
startPos = node.getPos(other)
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr(other)
|
||||
functor = PosHprLerpFunctor(
|
||||
node, startPos, pos,
|
||||
startHpr, hpr, other)
|
||||
else:
|
||||
if (startPos == None):
|
||||
startPos = node.getPos()
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr()
|
||||
functor = PosHprLerpFunctor(
|
||||
node, startPos, pos,
|
||||
startHpr, hpr)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpPosHpr-%d' % LerpPosHprInterval.lerpPosHprNum
|
||||
LerpPosHprInterval.lerpPosHprNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
class LerpHprScaleInterval(LerpInterval):
|
||||
# Interval counter
|
||||
lerpHprScaleNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, hpr, scale,
|
||||
startHpr=None, startScale=None,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
""" __init__(node, duration, hpr, scale,
|
||||
startHpr, startScale,
|
||||
other, blendType, name)
|
||||
"""
|
||||
def functorFunc(node=node, hpr=hpr, scale=scale,
|
||||
startHpr=startHpr,
|
||||
startScale=startScale, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(hpr):
|
||||
# This may be a thunk that returns a point.
|
||||
hpr = hpr()
|
||||
if callable(scale):
|
||||
# This may be a thunk that returns a point.
|
||||
scale = scale()
|
||||
# Make a our own copy of the parameters:
|
||||
if (hpr != None): hpr=VBase3(hpr)
|
||||
if (scale != None): scale=VBase3(scale)
|
||||
if (startHpr != None): startHpr=VBase3(startHpr)
|
||||
if (startScale != None): startScale=VBase3(startScale)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr(other)
|
||||
if (startScale == None):
|
||||
startScale = node.getScale(other)
|
||||
functor = HprScaleLerpFunctor(
|
||||
node, startHpr, hpr,
|
||||
startScale, scale, other)
|
||||
else:
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr()
|
||||
if (startScale == None):
|
||||
startScale = node.getScale()
|
||||
functor = HprScaleLerpFunctor(
|
||||
node, startHpr, hpr, startScale, scale)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = ('LerpHprScale-%d' %
|
||||
LerpHprScaleInterval.lerpHprScaleNum)
|
||||
LerpHprScaleInterval.lerpHprScaleNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
class LerpPosHprScaleInterval(LerpInterval):
|
||||
# Interval counter
|
||||
lerpPosHprScaleNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, pos, hpr, scale,
|
||||
startPos=None, startHpr=None, startScale=None,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
""" __init__(node, duration, pos, hpr, scale,
|
||||
startPos, startHpr, startScale,
|
||||
other, blendType, name)
|
||||
"""
|
||||
def functorFunc(node=node, pos=pos, hpr=hpr, scale=scale,
|
||||
startPos=startPos, startHpr=startHpr,
|
||||
startScale=startScale, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(pos):
|
||||
# This may be a thunk that returns a point.
|
||||
pos = pos()
|
||||
if callable(hpr):
|
||||
# This may be a thunk that returns a point.
|
||||
hpr = hpr()
|
||||
if callable(scale):
|
||||
# This may be a thunk that returns a point.
|
||||
scale = scale()
|
||||
# Make a our own copy of the parameters:
|
||||
if (pos != None): pos=Point3(pos)
|
||||
if (hpr != None): hpr=VBase3(hpr)
|
||||
if (scale != None): scale=VBase3(scale)
|
||||
if (startPos != None): startPos=Point3(startPos)
|
||||
if (startHpr != None): startHpr=VBase3(startHpr)
|
||||
if (startScale != None): startScale=VBase3(startScale)
|
||||
if (other != None):
|
||||
# lerp wrt other
|
||||
if (startPos == None):
|
||||
startPos = node.getPos(other)
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr(other)
|
||||
if (startScale == None):
|
||||
startScale = node.getScale(other)
|
||||
functor = PosHprScaleLerpFunctor(
|
||||
node, startPos, pos, startHpr, hpr,
|
||||
startScale, scale, other)
|
||||
else:
|
||||
if (startPos == None):
|
||||
startPos = node.getPos()
|
||||
if (startHpr == None):
|
||||
startHpr = node.getHpr()
|
||||
if (startScale == None):
|
||||
startScale = node.getScale()
|
||||
functor = PosHprScaleLerpFunctor(
|
||||
node, startPos, pos, startHpr, hpr, startScale, scale)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = ('LerpPosHprScale-%d' %
|
||||
LerpPosHprScaleInterval.lerpPosHprScaleNum)
|
||||
LerpPosHprScaleInterval.lerpPosHprScaleNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
|
||||
class LerpColorScaleInterval(LerpInterval):
|
||||
# Name counter
|
||||
lerpColorScaleNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, startColor, endColor,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
|
||||
def functorFunc(node=node, startColor=startColor, endColor=endColor, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(endColor):
|
||||
# This may be a thunk that returns a point.
|
||||
endColor = endColor()
|
||||
if callable(startColor):
|
||||
# This may be a thunk that returns a point.
|
||||
startColor = startColor()
|
||||
# Make a our own copy of the parameters:
|
||||
if (startColor != None): startColor=VBase4(startColor)
|
||||
if (endColor != None): endColor=VBase4(endColor)
|
||||
if (other != None):
|
||||
functor = ColorScaleLerpFunctor(node, startColor, endColor, other)
|
||||
else:
|
||||
functor = ColorScaleLerpFunctor(node, startColor, endColor)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpColorScaleInterval-%d' % LerpColorScaleInterval.lerpColorScaleNum
|
||||
LerpColorScaleInterval.lerpColorScaleNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
|
||||
|
||||
class LerpColorInterval(LerpInterval):
|
||||
# Name counter
|
||||
lerpColorNum = 1
|
||||
# Class methods
|
||||
def __init__(self, node, duration, startColor, endColor,
|
||||
other=None, blendType='noBlend', name=None):
|
||||
|
||||
def functorFunc(node=node, startColor=startColor,
|
||||
endColor=endColor, other=other):
|
||||
assert(not node.isEmpty())
|
||||
if callable(endColor):
|
||||
# This may be a thunk that returns a point.
|
||||
endColor = endColor()
|
||||
if callable(startColor):
|
||||
# This may be a thunk that returns a point.
|
||||
startColor = startColor()
|
||||
# Make a our own copy of the parameters:
|
||||
if (startColor != None): startColor=VBase4(startColor)
|
||||
if (endColor != None): endColor=VBase4(endColor)
|
||||
if (other != None):
|
||||
functor = ColorLerpFunctor(node, startColor, endColor, other)
|
||||
else:
|
||||
functor = ColorLerpFunctor(node, startColor, endColor)
|
||||
return functor
|
||||
|
||||
# Generate unique name if necessary
|
||||
if (name == None):
|
||||
name = 'LerpColorInterval-%d' % LerpColorInterval.lerpColorNum
|
||||
LerpColorInterval.lerpColorNum += 1
|
||||
# Initialize superclass
|
||||
LerpInterval.__init__(self, name, duration, functorFunc, blendType)
|
||||
|
||||
|
||||
|
||||
class LerpFunctionInterval(Interval.Interval):
|
||||
"""
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
"""MultiTrack module: contains the MultiTrack class"""
|
||||
|
||||
import Interval
|
||||
|
||||
|
||||
class MultiTrack(Interval.Interval):
|
||||
# Name counter
|
||||
multiTrackNum = 1
|
||||
# Class methods
|
||||
def __init__(self, trackList, name=None):
|
||||
"""__init__(trackList, name)
|
||||
"""
|
||||
# Record track list
|
||||
self.tlist = trackList
|
||||
# Generate name if necessary
|
||||
if (name == None):
|
||||
name = 'MultiTrack-%d' % MultiTrack.multiTrackNum
|
||||
MultiTrack.multiTrackNum = MultiTrack.multiTrackNum + 1
|
||||
# Duration is max of all track durations
|
||||
duration = self.__computeDuration()
|
||||
# Initialize superclass
|
||||
Interval.Interval.__init__(self, name, duration)
|
||||
# Update stopEventList after initialization
|
||||
# It is the union of the stopEventLists of all tracks in the MultiTrack
|
||||
for t in self.tlist:
|
||||
self.stopEventList = self.stopEventList + t.stopEventList
|
||||
|
||||
# Access track at given index
|
||||
def __getitem__(self, item):
|
||||
return self.tlist[item]
|
||||
|
||||
def __computeDuration(self):
|
||||
""" __computeDuration()
|
||||
Returns the duration of the longest Track
|
||||
"""
|
||||
duration = 0.0
|
||||
for t in self.tlist:
|
||||
dur = t.getDuration()
|
||||
if (dur > duration):
|
||||
duration = dur
|
||||
return duration
|
||||
|
||||
def updateFunc(self, t, event = Interval.IVAL_NONE):
|
||||
""" updateFunc(t, event)
|
||||
Go to time t
|
||||
"""
|
||||
|
||||
for track in self.tlist:
|
||||
# We used to try to be smart about calling this only in
|
||||
# certain cases, but in fact we just called it in every
|
||||
# case anyway, so might as well eliminate all of the
|
||||
# comparisons.
|
||||
track.setT(t, event)
|
||||
|
||||
# Print out representation of MultiTrack
|
||||
def __repr__(self, indent=0):
|
||||
""" __repr__(indent)
|
||||
"""
|
||||
str = Interval.Interval.__repr__(self, indent) + '\n'
|
||||
for t in self.tlist:
|
||||
str = str + t.__repr__(indent+1)
|
||||
return str
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Parallel(MultiTrack):
|
||||
def __init__(self, *tracks, **kw):
|
||||
MultiTrack.__init__(self, tracks, **kw)
|
||||
20
direct/src/interval/Sources.pp
Normal file
20
direct/src/interval/Sources.pp
Normal file
@@ -0,0 +1,20 @@
|
||||
#begin lib_target
|
||||
#define TARGET interval
|
||||
#define LOCAL_LIBS \
|
||||
directbase
|
||||
#define OTHER_LIBS \
|
||||
pgraph:c putil:c panda:m express:c pandaexpress:m dtoolconfig dtool
|
||||
|
||||
#define SOURCES \
|
||||
config_interval.cxx config_interval.h \
|
||||
cInterval.cxx cInterval.I cInterval.h \
|
||||
cLerpInterval.cxx cLerpInterval.I cLerpInterval.h \
|
||||
cLerpNodePathInterval.cxx cLerpNodePathInterval.I cLerpNodePathInterval.h \
|
||||
cLerpAnimEffectInterval.cxx cLerpAnimEffectInterval.I cLerpAnimEffectInterval.h \
|
||||
cMetaInterval.cxx cMetaInterval.I cMetaInterval.h \
|
||||
showInterval.cxx showInterval.I showInterval.h \
|
||||
hideInterval.cxx hideInterval.I hideInterval.h \
|
||||
lerp_helpers.h
|
||||
|
||||
#define IGATESCAN all
|
||||
#end lib_target
|
||||
@@ -1,267 +0,0 @@
|
||||
"""Track module: contains the Track class"""
|
||||
|
||||
import Interval
|
||||
import types
|
||||
|
||||
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.Interval):
|
||||
# Name counter
|
||||
trackNum = 1
|
||||
# Class methods
|
||||
def __init__(self, intervalList, name=None):
|
||||
"""__init__(intervalList, name)
|
||||
intervalList: <Interval> |
|
||||
'[' <delay>,
|
||||
<Interval>
|
||||
[ , PREVIOUS_END | PREVIOUS_START | TRACK_START ] ']'
|
||||
"""
|
||||
# Record instance variables
|
||||
self.currentInterval = None
|
||||
# Build ilist (need to do this before computing duration)
|
||||
self.__buildIlist(intervalList)
|
||||
# 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.Interval.__init__(self, name, duration)
|
||||
# Update stopEventList
|
||||
for i in self.ilist:
|
||||
self.stopEventList = self.stopEventList + i[0].stopEventList
|
||||
|
||||
# Access interval at given index
|
||||
def __getitem__(self, item):
|
||||
return self.ilist[item]
|
||||
|
||||
# Create a list of this track's intervals, recording time
|
||||
# and time type (relative to track start, previous start, or previous end)
|
||||
def __buildIlist(self, intervalList):
|
||||
self.ilist = []
|
||||
for i in intervalList:
|
||||
if isinstance(i, Interval.Interval):
|
||||
self.ilist.append([i, 0.0, PREVIOUS_END, 0.0, 0.0])
|
||||
elif (isinstance(i, types.ListType) or
|
||||
isinstance(i, types.TupleType)):
|
||||
itime = i[0]
|
||||
ival = i[1]
|
||||
try:
|
||||
type = i[2]
|
||||
except IndexError:
|
||||
type = TRACK_START
|
||||
self.ilist.append([ival, itime, type, 0.0, 0.0])
|
||||
else:
|
||||
print 'Track.__buildIlist: Invalid intervallist entry'
|
||||
|
||||
# Compute duration of the track and precompute start and end time of
|
||||
# each interval
|
||||
def __computeDuration(self):
|
||||
""" __computeDuration()
|
||||
"""
|
||||
duration = 0.0
|
||||
prev = None
|
||||
for idata in self.ilist:
|
||||
ival = idata[IDATA_IVAL]
|
||||
itime = idata[IDATA_TIME]
|
||||
type = idata[IDATA_TYPE]
|
||||
assert(itime >= 0.0)
|
||||
# Compute fill time, time between end of last interval and
|
||||
# start of this one. Depend on interval type
|
||||
fillTime = itime
|
||||
if (type == PREVIOUS_END):
|
||||
pass
|
||||
elif (type == PREVIOUS_START):
|
||||
if (prev != None):
|
||||
fillTime = itime - prev.getDuration()
|
||||
elif (type == TRACK_START):
|
||||
fillTime = itime - duration
|
||||
else:
|
||||
self.notify.error(
|
||||
'Track.__computeDuration(): unknown type: %d' % type)
|
||||
# Check for overlap
|
||||
if (fillTime < 0.0):
|
||||
self.notify.error(
|
||||
'Track.__computeDuration(): overlap detected')
|
||||
# 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 cumulative duration
|
||||
duration = idata[IDATA_END]
|
||||
prev = ival
|
||||
return duration
|
||||
|
||||
def setIntervalStartTime(self, name, itime, type=TRACK_START):
|
||||
""" setIntervalStartTime(name, itime, type)
|
||||
"""
|
||||
found = 0
|
||||
# Check for interval in current interval list
|
||||
for idata in self.ilist:
|
||||
# If found, update time and type
|
||||
if (idata[IDATA_IVAL].getName() == name):
|
||||
idata[IDATA_TIME] = itime
|
||||
idata[IDATA_TYPE] = type
|
||||
found = 1
|
||||
break
|
||||
if (found):
|
||||
# And recompute duration
|
||||
self.duration = self.__computeDuration()
|
||||
else:
|
||||
self.notify.warning(
|
||||
'Track.setIntervalStartTime(): no Interval named: %s' % name)
|
||||
|
||||
def getIntervalStartTime(self, name):
|
||||
""" getIntervalStartTime(name)
|
||||
"""
|
||||
# Search for interval of given name
|
||||
for idata in self.ilist:
|
||||
if (idata[IDATA_IVAL].getName() == name):
|
||||
return idata[IDATA_START]
|
||||
self.notify.warning(
|
||||
'Track.getIntervalStartTime(): no Interval named: %s' % name)
|
||||
return None
|
||||
|
||||
def __getIntervalStartTime(self, interval):
|
||||
""" __getIntervalStartTime(interval)
|
||||
"""
|
||||
# Search for given interval
|
||||
for idata in self.ilist:
|
||||
if (idata[IDATA_IVAL] == interval):
|
||||
return idata[IDATA_START]
|
||||
self.notify.warning(
|
||||
'Track.getIntervalStartTime(): Interval not found')
|
||||
return None
|
||||
|
||||
def getIntervalEndTime(self, name):
|
||||
""" getIntervalEndTime(name)
|
||||
"""
|
||||
# Search for interval of given name
|
||||
for idata in self.ilist:
|
||||
if (idata[IDATA_IVAL].getName() == name):
|
||||
return idata[IDATA_END]
|
||||
self.notify.warning(
|
||||
'Track.getIntervalEndTime(): no Interval named: %s' % name)
|
||||
return None
|
||||
|
||||
def updateFunc(self, t, event = Interval.IVAL_NONE):
|
||||
""" updateFunc(t, event)
|
||||
Go to time t
|
||||
"""
|
||||
# Deterimine which interval, if any to evaluate
|
||||
if (self.currentInterval != None and
|
||||
event == Interval.IVAL_NONE and
|
||||
t > self.currentStart and t < self.currentEnd):
|
||||
# If nothing interesting happened--we're still somewhere
|
||||
# within the same interval we were within last time--just
|
||||
# run that one. Trivial case.
|
||||
self.currentInterval.setT(t - self.currentStart, event)
|
||||
|
||||
elif (t < 0):
|
||||
# Before start of track, do nothing
|
||||
pass
|
||||
|
||||
else:
|
||||
# The more sophisticated, look-for-the-proper-interval case.
|
||||
|
||||
# Make sure track actually contains some intervals
|
||||
if not self.ilist:
|
||||
self.notify.warning(
|
||||
'Track.updateFunc(): track has no intervals')
|
||||
return
|
||||
|
||||
# Initialize local variables
|
||||
currentInterval = None
|
||||
currentStart = 0.0
|
||||
currentEnd = 0.0
|
||||
# First entry, re-init instance variables
|
||||
if (event == Interval.IVAL_INIT):
|
||||
# Initialize prev_t to 0.0
|
||||
self.prev_t = 0.0
|
||||
# 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 each ival's start/end times
|
||||
if (t < tStart):
|
||||
if (event == Interval.IVAL_DONE):
|
||||
# This should only happen in cases of floating
|
||||
# point instability where t is very close to
|
||||
# but less than tStart
|
||||
ival.setT(ival.getDuration(), event)
|
||||
elif (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, event)
|
||||
# Done checking intervals
|
||||
break
|
||||
elif (t >= tStart) and (t <= tEnd):
|
||||
# Between start/end, record current interval
|
||||
# Make sure event == Interval.IVAL_INIT if entering new interval
|
||||
if ((event == Interval.IVAL_NONE) and
|
||||
((self.prev_t < tStart) or
|
||||
(ival != self.currentInterval))):
|
||||
event = Interval.IVAL_INIT
|
||||
# Evaluate interval at interval relative time
|
||||
if (event == Interval.IVAL_DONE):
|
||||
ival.setT(ival.getDuration(), event)
|
||||
else:
|
||||
ival.setT(t - tStart, event)
|
||||
currentInterval = ival
|
||||
currentStart = tStart
|
||||
currentEnd = tEnd
|
||||
elif (t > tEnd):
|
||||
# Crossing over interval end
|
||||
if (((event == Interval.IVAL_NONE) or (event == Interval.IVAL_DONE)) and
|
||||
(self.prev_t < tEnd)):
|
||||
# We've just crossed the end of this interval,
|
||||
# execute the interval at its end time
|
||||
# and flag event as Interval.IVAL_DONE
|
||||
ival.setT(ival.getDuration(), Interval.IVAL_DONE)
|
||||
elif ((event == Interval.IVAL_INIT) and ival.getOpenEnded()):
|
||||
# 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(), Interval.IVAL_INIT)
|
||||
# May not be the last, keep checking other intervals
|
||||
# Record current interval (may be None)
|
||||
self.currentInterval = currentInterval
|
||||
self.currentStart = currentStart
|
||||
self.currentEnd = currentEnd
|
||||
|
||||
# Create a printable representation of the track
|
||||
def __repr__(self, indent=0):
|
||||
""" __repr__(indent)
|
||||
"""
|
||||
str = Interval.Interval.__repr__(self, indent) + '\n'
|
||||
for idata in self.ilist:
|
||||
# Tack on start and end time for this interval
|
||||
str = (str + idata[IDATA_IVAL].__repr__(indent+1) +
|
||||
(' start: %0.2f end: %0.2f' %
|
||||
(idata[IDATA_START], idata[IDATA_END])) + '\n'
|
||||
)
|
||||
return str
|
||||
|
||||
|
||||
class Sequence(Track):
|
||||
def __init__(self, *intervals, **kw):
|
||||
Track.__init__(self, intervals, **kw)
|
||||
127
direct/src/interval/cInterval.I
Normal file
127
direct/src/interval/cInterval.I
Normal file
@@ -0,0 +1,127 @@
|
||||
// Filename: cInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::get_name
|
||||
// Access: Published
|
||||
// Description: Returns the interval's name.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &CInterval::
|
||||
get_name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::get_duration
|
||||
// Access: Published
|
||||
// Description: Returns the duration of the interval in seconds.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double CInterval::
|
||||
get_duration() const {
|
||||
recompute();
|
||||
return _duration;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::get_open_ended
|
||||
// Access: Published
|
||||
// Description: Returns the state of the "open_ended" flag. This is
|
||||
// primarily intended for instantaneous intervals like
|
||||
// FunctionIntervals; it indicates true if the interval
|
||||
// has some lasting effect that should be applied even
|
||||
// if the interval doesn't get started until after its
|
||||
// finish time, or false if the interval is a transitive
|
||||
// thing that doesn't need to be called late.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CInterval::
|
||||
get_open_ended() const {
|
||||
return _open_ended;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::set_t
|
||||
// Access: Published
|
||||
// Description: Advances the interval. This function is provided
|
||||
// mainly to provide compatibility with the Python
|
||||
// Interval class; you should use initialize(), step(),
|
||||
// and finalize() instead.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CInterval::
|
||||
set_t(double t, CInterval::EventType event) {
|
||||
switch (event) {
|
||||
case ET_initialize:
|
||||
initialize(t);
|
||||
break;
|
||||
|
||||
case ET_instant:
|
||||
instant();
|
||||
break;
|
||||
|
||||
case ET_step:
|
||||
step(t);
|
||||
break;
|
||||
|
||||
case ET_finalize:
|
||||
finalize();
|
||||
break;
|
||||
|
||||
case ET_reverse_initialize:
|
||||
reverse_initialize(t);
|
||||
break;
|
||||
|
||||
case ET_reverse_instant:
|
||||
reverse_instant();
|
||||
break;
|
||||
|
||||
case ET_reverse_finalize:
|
||||
reverse_finalize();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::get_t
|
||||
// Access: Published
|
||||
// Description: Returns the current time of the interval: the last
|
||||
// value of t passed to initialize(), step(), or
|
||||
// finalize() (or set_t()).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double CInterval::
|
||||
get_t() const {
|
||||
return _curr_t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::recompute
|
||||
// Access: Protected
|
||||
// Description: Calls do_recompute() if the dirty flag has been set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CInterval::
|
||||
recompute() const {
|
||||
if (_dirty) {
|
||||
((CInterval *)this)->do_recompute();
|
||||
}
|
||||
}
|
||||
|
||||
INLINE ostream &
|
||||
operator << (ostream &out, const CInterval &ival) {
|
||||
ival.output(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
362
direct/src/interval/cInterval.cxx
Normal file
362
direct/src/interval/cInterval.cxx
Normal file
@@ -0,0 +1,362 @@
|
||||
// Filename: cInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cInterval.h"
|
||||
#include "indent.h"
|
||||
#include "clockObject.h"
|
||||
|
||||
TypeHandle CInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CInterval::
|
||||
CInterval(const string &name, double duration, bool open_ended) :
|
||||
_curr_t(0.0),
|
||||
_name(name),
|
||||
_duration(duration),
|
||||
_open_ended(open_ended),
|
||||
_dirty(false)
|
||||
{
|
||||
_clock_start = 0.0;
|
||||
_start_t = 0.0;
|
||||
_end_t = 0.0;
|
||||
_start_t_at_start = false;
|
||||
_end_t_at_end = false;
|
||||
_play_rate = 1.0;
|
||||
_loop_count = 0;
|
||||
_restart = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::setup_play
|
||||
// Access: Published
|
||||
// Description: Called to prepare the interval for automatic timed
|
||||
// playback, e.g. via a Python task. The interval will
|
||||
// be played from start_t to end_t, at a time factor
|
||||
// specified by play_rate. start_t must always be less
|
||||
// than end_t (except for the exception for end_t == -1,
|
||||
// below), but if play_rate is negative the interval
|
||||
// will be played backwards.
|
||||
//
|
||||
// Specify end_t of -1 to play the entire interval from
|
||||
// start_t.
|
||||
//
|
||||
// Call step_play() repeatedly to execute the interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
setup_play(double start_t, double end_t, double play_rate) {
|
||||
nassertv(start_t < end_t || end_t < 0.0);
|
||||
nassertv(play_rate != 0.0);
|
||||
|
||||
double duration = get_duration();
|
||||
|
||||
if (start_t < 0.0) {
|
||||
_start_t = 0.0;
|
||||
_start_t_at_start = true;
|
||||
} else if (start_t > duration) {
|
||||
_start_t = duration;
|
||||
_start_t_at_start = false;
|
||||
} else {
|
||||
_start_t = start_t;
|
||||
_start_t_at_start = false;
|
||||
}
|
||||
if (end_t < 0.0 || end_t >= duration) {
|
||||
_end_t = duration;
|
||||
_end_t_at_end = true;
|
||||
} else {
|
||||
_end_t = end_t;
|
||||
_end_t_at_end = false;
|
||||
}
|
||||
|
||||
_clock_start = ClockObject::get_global_clock()->get_frame_time();
|
||||
_play_rate = play_rate;
|
||||
_loop_count = 0;
|
||||
_restart = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::step_play
|
||||
// Access: Published
|
||||
// Description: Should be called once per frame to execute the
|
||||
// automatic timed playback begun with setup_play().
|
||||
// The return value is the number of times the interval
|
||||
// is about to repeat; stop when this reaches one to
|
||||
// play the interval through exactly once.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CInterval::
|
||||
step_play() {
|
||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||
|
||||
if (_play_rate >= 0.0) {
|
||||
double t = (now - _clock_start) * _play_rate + _start_t;
|
||||
|
||||
if (t < _end_t) {
|
||||
// In the middle of the interval, not a problem.
|
||||
if (_restart) {
|
||||
initialize(t);
|
||||
_restart = false;
|
||||
} else {
|
||||
step(t);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Past the ending point; time to finalize.
|
||||
if (_end_t_at_end) {
|
||||
// Only finalize if the playback cycle includes the whole
|
||||
// interval.
|
||||
if (_restart) {
|
||||
if (get_open_ended() || _loop_count != 0) {
|
||||
instant();
|
||||
}
|
||||
} else {
|
||||
finalize();
|
||||
_restart = true;
|
||||
}
|
||||
} else {
|
||||
if (_restart) {
|
||||
initialize(_end_t);
|
||||
_restart = false;
|
||||
} else {
|
||||
step(_end_t);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance the clock for the next loop cycle. We might have to
|
||||
// advance multiple times if we skipped several cycles in the past
|
||||
// frame.
|
||||
|
||||
if (_end_t == _start_t) {
|
||||
// If the interval has no length, we loop exactly once each
|
||||
// time.
|
||||
_loop_count++;
|
||||
|
||||
} else {
|
||||
// Otherwise, figure out how many loops we need to skip.
|
||||
double time_per_loop = (_end_t - _start_t) / _play_rate;
|
||||
double num_loops = floor((now - _clock_start) / time_per_loop);
|
||||
_loop_count += (int)num_loops;
|
||||
_clock_start += num_loops * time_per_loop;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Playing backwards.
|
||||
double t = (now - _clock_start) * _play_rate + _end_t;
|
||||
|
||||
if (t >= _start_t) {
|
||||
// In the middle of the interval, not a problem.
|
||||
if (_restart) {
|
||||
reverse_initialize(t);
|
||||
_restart = false;
|
||||
} else {
|
||||
step(t);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Past the ending point; time to finalize.
|
||||
if (_start_t_at_start) {
|
||||
// Only finalize if the playback cycle includes the whole
|
||||
// interval.
|
||||
if (_restart) {
|
||||
if (get_open_ended() || _loop_count != 0) {
|
||||
reverse_instant();
|
||||
}
|
||||
} else {
|
||||
reverse_finalize();
|
||||
_restart = true;
|
||||
}
|
||||
} else {
|
||||
if (_restart) {
|
||||
reverse_initialize(_start_t);
|
||||
_restart = false;
|
||||
} else {
|
||||
step(_start_t);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance the clock for the next loop cycle. We might have to
|
||||
// advance multiple times if we skipped several cycles in the past
|
||||
// frame.
|
||||
|
||||
if (_end_t == _start_t) {
|
||||
// If the interval has no length, we loop exactly once each
|
||||
// time.
|
||||
_loop_count++;
|
||||
|
||||
} else {
|
||||
// Otherwise, figure out how many loops we need to skip.
|
||||
double time_per_loop = (_end_t - _start_t) / -_play_rate;
|
||||
double num_loops = floor((now - _clock_start) / time_per_loop);
|
||||
_loop_count += (int)num_loops;
|
||||
_clock_start += num_loops * time_per_loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _loop_count;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: This replaces the first call to step(), and indicates
|
||||
// that the interval has just begun. This may be
|
||||
// overridden by derived classes that need to do some
|
||||
// explicit initialization on the first call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
initialize(double t) {
|
||||
recompute();
|
||||
step(t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of initialize() .. step()
|
||||
// .. finalize(), when everything is to happen within
|
||||
// one frame. The interval should initialize itself,
|
||||
// then leave itself in the final state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
instant() {
|
||||
recompute();
|
||||
step(get_duration());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::step
|
||||
// Access: Published, Virtual
|
||||
// Description: Advances the time on the interval. The time may
|
||||
// either increase (the normal case) or decrease
|
||||
// (e.g. if the interval is being played by a slider).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
step(double t) {
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::finalize
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called to stop an interval, forcing it to
|
||||
// whatever state it would be after it played all the
|
||||
// way through. It's generally invoked by
|
||||
// set_final_t().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
finalize() {
|
||||
step(get_duration());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::reverse_initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: Similar to initialize(), but this is called when the
|
||||
// interval is being played backwards; it indicates that
|
||||
// the interval should start at the finishing state and
|
||||
// undo any intervening intervals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
reverse_initialize(double t) {
|
||||
recompute();
|
||||
step(t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::reverse_instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of reverse_initialize()
|
||||
// .. step() .. reverse_finalize(), when everything is
|
||||
// to happen within one frame. The interval should
|
||||
// initialize itself, then leave itself in the initial
|
||||
// state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
reverse_instant() {
|
||||
recompute();
|
||||
step(0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::reverse_finalize
|
||||
// Access: Published, Virtual
|
||||
// Description: Called generally following a reverse_initialize(),
|
||||
// this indicates the interval should set itself to the
|
||||
// initial state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
reverse_finalize() {
|
||||
step(0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::output
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
output(ostream &out) const {
|
||||
out << get_name();
|
||||
if (get_duration() != 0.0) {
|
||||
out << " dur " << get_duration();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::write
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << *this << "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::mark_dirty
|
||||
// Access: Public
|
||||
// Description: Called by a derived class to indicate the interval has
|
||||
// been changed internally and must be recomputed before
|
||||
// its duration may be returned.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
mark_dirty() {
|
||||
if (!_dirty) {
|
||||
_dirty = true;
|
||||
Parents::iterator pi;
|
||||
for (pi = _parents.begin(); pi != _parents.end(); ++pi) {
|
||||
(*pi)->mark_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CInterval::do_recompute
|
||||
// Access: Protected, Virtual
|
||||
// Description: Does whatever processing is necessary to recompute
|
||||
// the interval after a call to mark_dirty() has
|
||||
// indicated a recomputation is necessary.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CInterval::
|
||||
do_recompute() {
|
||||
_dirty = false;
|
||||
}
|
||||
135
direct/src/interval/cInterval.h
Normal file
135
direct/src/interval/cInterval.h
Normal file
@@ -0,0 +1,135 @@
|
||||
// Filename: cInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CINTERVAL_H
|
||||
#define CINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CInterval
|
||||
// Description : The base class for timeline components. A CInterval
|
||||
// represents a single action, event, or collection of
|
||||
// nested intervals that will be performed at some
|
||||
// specific time or over a period of time.
|
||||
//
|
||||
// This is essentially similar to the Python "Interval"
|
||||
// class, but it is implemented in C++ (hence the name).
|
||||
// Intervals that may be implemented in C++ will inherit
|
||||
// from this class; Intervals that must be implemented
|
||||
// in Python will inherit from the similar Python class.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT CInterval : public TypedReferenceCount {
|
||||
public:
|
||||
CInterval(const string &name, double duration, bool open_ended);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE const string &get_name() const;
|
||||
INLINE double get_duration() const;
|
||||
INLINE bool get_open_ended() const;
|
||||
|
||||
enum EventType {
|
||||
ET_initialize,
|
||||
ET_instant,
|
||||
ET_step,
|
||||
ET_finalize,
|
||||
ET_reverse_initialize,
|
||||
ET_reverse_instant,
|
||||
ET_reverse_finalize
|
||||
};
|
||||
|
||||
INLINE void set_t(double t, EventType event = ET_step);
|
||||
INLINE double get_t() const;
|
||||
|
||||
void setup_play(double start_time, double end_time, double play_rate);
|
||||
int step_play();
|
||||
|
||||
// These functions control the actual playback of the interval.
|
||||
virtual void initialize(double t);
|
||||
virtual void instant();
|
||||
virtual void step(double t);
|
||||
virtual void finalize();
|
||||
virtual void reverse_initialize(double t);
|
||||
virtual void reverse_instant();
|
||||
virtual void reverse_finalize();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
public:
|
||||
void mark_dirty();
|
||||
|
||||
protected:
|
||||
INLINE void recompute() const;
|
||||
virtual void do_recompute();
|
||||
|
||||
double _curr_t;
|
||||
string _name;
|
||||
double _duration;
|
||||
|
||||
// For setup_play() and step_play().
|
||||
double _clock_start;
|
||||
double _start_t;
|
||||
double _end_t;
|
||||
bool _end_t_at_end;
|
||||
bool _start_t_at_start;
|
||||
double _play_rate;
|
||||
int _loop_count;
|
||||
bool _restart;
|
||||
|
||||
private:
|
||||
bool _open_ended;
|
||||
bool _dirty;
|
||||
|
||||
// We keep a record of the "parent" intervals (that is, any
|
||||
// CMetaInterval objects that keep a pointer to this one) strictly
|
||||
// so we can mark all of our parents dirty when this interval gets
|
||||
// dirty.
|
||||
typedef pvector<CInterval *> Parents;
|
||||
Parents _parents;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "CInterval",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class CMetaInterval;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const CInterval &ival);
|
||||
|
||||
#include "cInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
62
direct/src/interval/cLerpAnimEffectInterval.I
Normal file
62
direct/src/interval/cLerpAnimEffectInterval.I
Normal file
@@ -0,0 +1,62 @@
|
||||
// Filename: cLerpAnimEffectInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpAnimEffectInterval::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLerpAnimEffectInterval::
|
||||
CLerpAnimEffectInterval(const string &name, double duration,
|
||||
CLerpInterval::BlendType blend_type) :
|
||||
CLerpInterval(name, duration, blend_type)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpAnimEffectInterval::add_control
|
||||
// Access: Published
|
||||
// Description: Adds another AnimControl to the list of AnimControls
|
||||
// affected by the lerp. This control will be lerped
|
||||
// from begin_effect to end_effect over the period of
|
||||
// the lerp.
|
||||
//
|
||||
// The AnimControl name parameter is only used when
|
||||
// formatting the interval for output.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpAnimEffectInterval::
|
||||
add_control(AnimControl *control, const string &name,
|
||||
float begin_effect, float end_effect) {
|
||||
_controls.push_back(ControlDef(control, name, begin_effect, end_effect));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpAnimEffectInterval::ControlDef::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLerpAnimEffectInterval::ControlDef::
|
||||
ControlDef(AnimControl *control, const string &name,
|
||||
float begin_effect, float end_effect) :
|
||||
_control(control),
|
||||
_name(name),
|
||||
_begin_effect(begin_effect),
|
||||
_end_effect(end_effect)
|
||||
{
|
||||
}
|
||||
70
direct/src/interval/cLerpAnimEffectInterval.cxx
Normal file
70
direct/src/interval/cLerpAnimEffectInterval.cxx
Normal file
@@ -0,0 +1,70 @@
|
||||
// Filename: cLerpAnimEffectInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cLerpAnimEffectInterval.h"
|
||||
#include "lerp_helpers.h"
|
||||
#include "partBundle.h"
|
||||
|
||||
TypeHandle CLerpAnimEffectInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpAnimEffectInterval::step
|
||||
// Access: Published, Virtual
|
||||
// Description: Advances the time on the interval. The time may
|
||||
// either increase (the normal case) or decrease
|
||||
// (e.g. if the interval is being played by a slider).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpAnimEffectInterval::
|
||||
step(double t) {
|
||||
double d = compute_delta(t);
|
||||
|
||||
Controls::iterator ci;
|
||||
for (ci = _controls.begin(); ci != _controls.end(); ++ci) {
|
||||
ControlDef &def = (*ci);
|
||||
float effect;
|
||||
lerp_value(effect, d, def._begin_effect, def._end_effect);
|
||||
def._control->get_part()->set_control_effect(def._control, effect);
|
||||
}
|
||||
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpAnimEffectInterval::output
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpAnimEffectInterval::
|
||||
output(ostream &out) const {
|
||||
out << get_name() << ": ";
|
||||
|
||||
if (_controls.empty()) {
|
||||
out << "(no controls)";
|
||||
} else {
|
||||
Controls::const_iterator ci;
|
||||
ci = _controls.begin();
|
||||
out << (*ci)._name;
|
||||
++ci;
|
||||
while (ci != _controls.end()) {
|
||||
out << ", " << (*ci)._name;
|
||||
++ci;
|
||||
}
|
||||
}
|
||||
|
||||
out << " dur " << get_duration();
|
||||
}
|
||||
87
direct/src/interval/cLerpAnimEffectInterval.h
Normal file
87
direct/src/interval/cLerpAnimEffectInterval.h
Normal file
@@ -0,0 +1,87 @@
|
||||
// Filename: cLerpAnimEffectInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLERPANIMEFFECTINTERVAL_H
|
||||
#define CLERPANIMEFFECTINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cLerpInterval.h"
|
||||
#include "animControl.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CLerpAnimEffectInterval
|
||||
// Description : This interval lerps between different amounts of
|
||||
// control effects for various AnimControls that might
|
||||
// be playing on an actor. It's used to change the
|
||||
// blending amount between multiple animations.
|
||||
//
|
||||
// The idea is to start all the animations playing
|
||||
// first, then use a CLerpAnimEffectInterval to adjust
|
||||
// the degree to which each animation affects the actor.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT CLerpAnimEffectInterval : public CLerpInterval {
|
||||
PUBLISHED:
|
||||
INLINE CLerpAnimEffectInterval(const string &name, double duration,
|
||||
BlendType blend_type);
|
||||
|
||||
INLINE void add_control(AnimControl *control, const string &name,
|
||||
float begin_effect, float end_effect);
|
||||
|
||||
virtual void step(double t);
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
class ControlDef {
|
||||
public:
|
||||
INLINE ControlDef(AnimControl *control, const string &name,
|
||||
float begin_effect, float end_effect);
|
||||
PT(AnimControl) _control;
|
||||
string _name;
|
||||
float _begin_effect;
|
||||
float _end_effect;
|
||||
};
|
||||
|
||||
typedef pvector<ControlDef> Controls;
|
||||
Controls _controls;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CLerpInterval::init_type();
|
||||
register_type(_type_handle, "CLerpAnimEffectInterval",
|
||||
CLerpInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cLerpAnimEffectInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
43
direct/src/interval/cLerpInterval.I
Normal file
43
direct/src/interval/cLerpInterval.I
Normal file
@@ -0,0 +1,43 @@
|
||||
// Filename: cLerpInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpInterval::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLerpInterval::
|
||||
CLerpInterval(const string &name, double duration,
|
||||
CLerpInterval::BlendType blend_type) :
|
||||
CInterval(name, duration, true),
|
||||
_blend_type(blend_type)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpInterval::get_blend_type
|
||||
// Access: Published
|
||||
// Description: Returns the blend type specified for the interval.
|
||||
// This controls how the linear interpolation behaves
|
||||
// near the beginning and end of the lerp period.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CLerpInterval::BlendType CLerpInterval::
|
||||
get_blend_type() const {
|
||||
return _blend_type;
|
||||
}
|
||||
85
direct/src/interval/cLerpInterval.cxx
Normal file
85
direct/src/interval/cLerpInterval.cxx
Normal file
@@ -0,0 +1,85 @@
|
||||
// Filename: cLerpInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cLerpInterval.h"
|
||||
#include "string_utils.h"
|
||||
|
||||
TypeHandle CLerpInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpInterval::string_blend_type
|
||||
// Access: Published, Static
|
||||
// Description: Returns the BlendType enumerated value corresponding
|
||||
// to the indicated string, or BT_invalid if the string
|
||||
// doesn't match anything.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CLerpInterval::BlendType CLerpInterval::
|
||||
string_blend_type(const string &blend_type) {
|
||||
if (blend_type == "easeIn") {
|
||||
return BT_ease_in;
|
||||
} else if (blend_type == "easeOut") {
|
||||
return BT_ease_out;
|
||||
} else if (blend_type == "easeInOut") {
|
||||
return BT_ease_in_out;
|
||||
} else if (blend_type == "noBlend") {
|
||||
return BT_no_blend;
|
||||
} else {
|
||||
return BT_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpInterval::compute_delta
|
||||
// Access: Protected
|
||||
// Description: Given a t value in the range [0, get_duration()],
|
||||
// returns the corresponding delta value clamped to the
|
||||
// range [0, 1], after scaling by duration and applying
|
||||
// the blend type.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double CLerpInterval::
|
||||
compute_delta(double t) const {
|
||||
double duration = get_duration();
|
||||
if (duration == 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
t /= duration;
|
||||
t = min(max(t, 0.0), 1.0);
|
||||
|
||||
switch (_blend_type) {
|
||||
case BT_ease_in:
|
||||
{
|
||||
double t2 = t * t;
|
||||
return ((3.0 * t2) - (t2 * t)) * 0.5;
|
||||
}
|
||||
|
||||
case BT_ease_out:
|
||||
{
|
||||
double t2 = t * t;
|
||||
return ((3.0 * t2) - (t2 * t)) * 0.5;
|
||||
}
|
||||
|
||||
case BT_ease_in_out:
|
||||
{
|
||||
double t2 = t * t;
|
||||
return (3.0 * t2) - (2.0 * t * t2);
|
||||
}
|
||||
|
||||
default:
|
||||
return t;
|
||||
}
|
||||
}
|
||||
78
direct/src/interval/cLerpInterval.h
Normal file
78
direct/src/interval/cLerpInterval.h
Normal file
@@ -0,0 +1,78 @@
|
||||
// Filename: cLerpInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLERPINTERVAL_H
|
||||
#define CLERPINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cInterval.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CLerpInterval
|
||||
// Description : The base class for a family of intervals that
|
||||
// linearly interpolate one or more numeric values over
|
||||
// time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT CLerpInterval : public CInterval {
|
||||
PUBLISHED:
|
||||
enum BlendType {
|
||||
BT_no_blend,
|
||||
BT_ease_in,
|
||||
BT_ease_out,
|
||||
BT_ease_in_out,
|
||||
BT_invalid
|
||||
};
|
||||
|
||||
public:
|
||||
INLINE CLerpInterval(const string &name, double duration,
|
||||
BlendType blend_type);
|
||||
|
||||
PUBLISHED:
|
||||
INLINE BlendType get_blend_type() const;
|
||||
|
||||
static BlendType string_blend_type(const string &blend_type);
|
||||
|
||||
protected:
|
||||
double compute_delta(double t) const;
|
||||
|
||||
private:
|
||||
BlendType _blend_type;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CInterval::init_type();
|
||||
register_type(_type_handle, "CLerpInterval",
|
||||
CInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cLerpInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
219
direct/src/interval/cLerpNodePathInterval.I
Normal file
219
direct/src/interval/cLerpNodePathInterval.I
Normal file
@@ -0,0 +1,219 @@
|
||||
// Filename: cLerpNodePathInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::get_node
|
||||
// Access: Published
|
||||
// Description: Returns the node being lerped.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const NodePath &CLerpNodePathInterval::
|
||||
get_node() const {
|
||||
return _node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::get_other
|
||||
// Access: Published
|
||||
// Description: Returns the "other" node, which the lerped node is
|
||||
// being moved relative to. If this is an empty node
|
||||
// path, the lerped node is being moved in its own
|
||||
// coordinate system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const NodePath &CLerpNodePathInterval::
|
||||
get_other() const {
|
||||
return _other;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_pos
|
||||
// Access: Published
|
||||
// Description: Indicates the initial position of the lerped node.
|
||||
// This is meaningful only if set_end_pos() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// position at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_pos(const LVecBase3f &pos) {
|
||||
_start_pos = pos;
|
||||
_flags |= F_start_pos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_pos
|
||||
// Access: Published
|
||||
// Description: Indicates that the position of the node should be
|
||||
// lerped, and specifies the final position of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's position will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_pos(const LVecBase3f &pos) {
|
||||
_end_pos = pos;
|
||||
_flags |= F_end_pos;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_hpr
|
||||
// Access: Published
|
||||
// Description: Indicates the initial rotation of the lerped node.
|
||||
// This is meaningful only if set_end_hpr() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// rotation at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_hpr(const LVecBase3f &hpr) {
|
||||
_start_hpr = hpr;
|
||||
_flags |= F_start_hpr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_hpr
|
||||
// Access: Published
|
||||
// Description: Indicates that the rotation of the node should be
|
||||
// lerped, and specifies the final rotation of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's rotation will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_hpr(const LVecBase3f &hpr) {
|
||||
_end_hpr = hpr;
|
||||
_flags |= F_end_hpr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_scale
|
||||
// Access: Published
|
||||
// Description: Indicates the initial scale of the lerped node.
|
||||
// This is meaningful only if set_end_scale() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// scale at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_scale(const LVecBase3f &scale) {
|
||||
_start_scale = scale;
|
||||
_flags |= F_start_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_scale
|
||||
// Access: Published
|
||||
// Description: Indicates the initial scale of the lerped node.
|
||||
// This is meaningful only if set_end_scale() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// scale at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_scale(float scale) {
|
||||
set_start_scale(LVecBase3f(scale, scale, scale));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_scale
|
||||
// Access: Published
|
||||
// Description: Indicates that the scale of the node should be
|
||||
// lerped, and specifies the final scale of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's scale will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_scale(const LVecBase3f &scale) {
|
||||
_end_scale = scale;
|
||||
_flags |= F_end_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_scale
|
||||
// Access: Published
|
||||
// Description: Indicates that the scale of the node should be
|
||||
// lerped, and specifies the final scale of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's scale will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_scale(float scale) {
|
||||
set_end_scale(LVecBase3f(scale, scale, scale));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_color
|
||||
// Access: Published
|
||||
// Description: Indicates the initial color of the lerped node.
|
||||
// This is meaningful only if set_end_color() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// color at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_color(const LVecBase4f &color) {
|
||||
_start_color = color;
|
||||
_flags |= F_start_color;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_color
|
||||
// Access: Published
|
||||
// Description: Indicates that the color of the node should be
|
||||
// lerped, and specifies the final color of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's color will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_color(const LVecBase4f &color) {
|
||||
_end_color = color;
|
||||
_flags |= F_end_color;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_start_color_scale
|
||||
// Access: Published
|
||||
// Description: Indicates the initial color scale of the lerped node.
|
||||
// This is meaningful only if set_end_color_scale() is also
|
||||
// called. This parameter is optional; if unspecified,
|
||||
// the value will be taken from the node's actual
|
||||
// color scale at the time the lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_start_color_scale(const LVecBase4f &color_scale) {
|
||||
_start_color_scale = color_scale;
|
||||
_flags |= F_start_color_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::set_end_color_scale
|
||||
// Access: Published
|
||||
// Description: Indicates that the color scale of the node should be
|
||||
// lerped, and specifies the final color scale of the node.
|
||||
// This should be called before initialize(). If this
|
||||
// is not called, the node's color scale will not be
|
||||
// affected by the lerp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CLerpNodePathInterval::
|
||||
set_end_color_scale(const LVecBase4f &color_scale) {
|
||||
_end_color_scale = color_scale;
|
||||
_flags |= F_end_color_scale;
|
||||
}
|
||||
351
direct/src/interval/cLerpNodePathInterval.cxx
Normal file
351
direct/src/interval/cLerpNodePathInterval.cxx
Normal file
@@ -0,0 +1,351 @@
|
||||
// Filename: cLerpNodePathInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cLerpNodePathInterval.h"
|
||||
#include "lerp_helpers.h"
|
||||
#include "transformState.h"
|
||||
#include "renderState.h"
|
||||
#include "colorAttrib.h"
|
||||
#include "colorScaleAttrib.h"
|
||||
#include "dcast.h"
|
||||
|
||||
TypeHandle CLerpNodePathInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::Constructor
|
||||
// Access: Published
|
||||
// Description: Constructs a lerp interval that will lerp some
|
||||
// properties on the indicated node, possibly relative
|
||||
// to the indicated other node (if other is nonempty).
|
||||
//
|
||||
// You must call set_end_pos(), etc. for the various
|
||||
// properties you wish to lerp before the first call to
|
||||
// initialize(). If you want to set a starting value
|
||||
// for any of the properties, you may call
|
||||
// set_start_pos(), etc.; otherwise, the starting value
|
||||
// is taken from the actual node's value at the time the
|
||||
// lerp is performed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CLerpNodePathInterval::
|
||||
CLerpNodePathInterval(const string &name, double duration,
|
||||
CLerpInterval::BlendType blend_type,
|
||||
const NodePath &node, const NodePath &other) :
|
||||
CLerpInterval(name, duration, blend_type),
|
||||
_node(node),
|
||||
_other(other),
|
||||
_flags(0)
|
||||
{
|
||||
_prev_d = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: This replaces the first call to step(), and indicates
|
||||
// that the interval has just begun. This may be
|
||||
// overridden by derived classes that need to do some
|
||||
// explicit initialization on the first call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
initialize(double t) {
|
||||
recompute();
|
||||
_prev_d = 0.0;
|
||||
step(t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of initialize() .. step()
|
||||
// .. finalize(), when everything is to happen within
|
||||
// one frame. The interval should initialize itself,
|
||||
// then leave itself in the final state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
instant() {
|
||||
recompute();
|
||||
_prev_d = 0.0;
|
||||
step(get_duration());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::step
|
||||
// Access: Published, Virtual
|
||||
// Description: Advances the time on the interval. The time may
|
||||
// either increase (the normal case) or decrease
|
||||
// (e.g. if the interval is being played by a slider).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
step(double t) {
|
||||
double d = compute_delta(t);
|
||||
|
||||
if ((_flags & (F_end_pos | F_end_hpr | F_end_scale)) != 0) {
|
||||
// We have some transform lerp.
|
||||
CPT(TransformState) transform;
|
||||
|
||||
if (_other.is_empty()) {
|
||||
// If there is no other node, it's a local transform lerp.
|
||||
transform = _node.get_transform();
|
||||
} else {
|
||||
// If there *is* another node, we get the transform relative to
|
||||
// that node.
|
||||
transform = _node.get_transform(_other);
|
||||
}
|
||||
|
||||
LPoint3f pos;
|
||||
LVecBase3f hpr;
|
||||
LVecBase3f scale;
|
||||
|
||||
if ((_flags & F_end_pos) != 0) {
|
||||
if ((_flags & F_start_pos) != 0) {
|
||||
lerp_value(pos, d, _start_pos, _end_pos);
|
||||
|
||||
} else {
|
||||
pos = transform->get_pos();
|
||||
lerp_value_from_prev(pos, d, _prev_d, pos, _end_pos);
|
||||
}
|
||||
}
|
||||
if ((_flags & F_end_hpr) != 0) {
|
||||
if ((_flags & F_start_hpr) != 0) {
|
||||
lerp_value(hpr, d, _start_hpr, _end_hpr);
|
||||
|
||||
} else {
|
||||
hpr = transform->get_hpr();
|
||||
lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr);
|
||||
}
|
||||
}
|
||||
if ((_flags & F_end_scale) != 0) {
|
||||
if ((_flags & F_start_scale) != 0) {
|
||||
lerp_value(scale, d, _start_scale, _end_scale);
|
||||
|
||||
} else {
|
||||
scale = transform->get_scale();
|
||||
lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale);
|
||||
}
|
||||
}
|
||||
|
||||
// Now apply the modifications back to the transform. We want to
|
||||
// be a little careful here, because we don't want to assume the
|
||||
// transform has hpr/scale components if they're not needed. And
|
||||
// in any case, we only want to apply the components that we
|
||||
// computed, above.
|
||||
switch (_flags & (F_end_pos | F_end_hpr | F_end_scale)) {
|
||||
case F_end_pos:
|
||||
transform = transform->set_pos(pos);
|
||||
break;
|
||||
|
||||
case F_end_hpr:
|
||||
transform = transform->set_hpr(hpr);
|
||||
break;
|
||||
|
||||
case F_end_scale:
|
||||
transform = transform->set_scale(scale);
|
||||
break;
|
||||
|
||||
case F_end_hpr | F_end_scale:
|
||||
transform = TransformState::make_pos_hpr_scale(transform->get_pos(), hpr, scale);
|
||||
break;
|
||||
|
||||
case F_end_pos | F_end_hpr:
|
||||
transform = TransformState::make_pos_hpr_scale(pos, hpr, transform->get_scale());
|
||||
break;
|
||||
|
||||
case F_end_pos | F_end_scale:
|
||||
if (transform->quat_given()) {
|
||||
transform = TransformState::make_pos_quat_scale(pos, transform->get_quat(), scale);
|
||||
} else {
|
||||
transform = TransformState::make_pos_hpr_scale(pos, transform->get_hpr(), scale);
|
||||
}
|
||||
break;
|
||||
|
||||
case F_end_pos | F_end_hpr | F_end_scale:
|
||||
transform = TransformState::make_pos_hpr_scale(pos, hpr, scale);
|
||||
break;
|
||||
|
||||
default:
|
||||
interval_cat.error()
|
||||
<< "Internal error in CLerpNodePathInterval::step().\n";
|
||||
}
|
||||
|
||||
// Now apply the new transform back to the node.
|
||||
if (_other.is_empty()) {
|
||||
_node.set_transform(transform);
|
||||
} else {
|
||||
_node.set_transform(_other, transform);
|
||||
}
|
||||
}
|
||||
|
||||
if ((_flags & (F_end_color | F_end_color_scale)) != 0) {
|
||||
// We have some render state lerp.
|
||||
CPT(RenderState) state;
|
||||
|
||||
if (_other.is_empty()) {
|
||||
// If there is no other node, it's a local state lerp. This is
|
||||
// most common.
|
||||
state = _node.get_state();
|
||||
} else {
|
||||
// If there *is* another node, we get the state relative to that
|
||||
// node. This is weird, but you could lerp color (for instance)
|
||||
// relative to some other node's color.
|
||||
state = _node.get_state(_other);
|
||||
}
|
||||
|
||||
// Unlike in the transform case above, we can go ahead and modify
|
||||
// the state immediately with each attribute change, since these
|
||||
// attributes don't interrelate.
|
||||
|
||||
if ((_flags & F_end_color) != 0) {
|
||||
Colorf color;
|
||||
|
||||
if ((_flags & F_start_color) != 0) {
|
||||
lerp_value(color, d, _start_color, _end_color);
|
||||
|
||||
} else {
|
||||
// Get the previous color.
|
||||
color.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
const RenderAttrib *attrib =
|
||||
state->get_attrib(ColorAttrib::get_class_type());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
const ColorAttrib *ca = DCAST(ColorAttrib, attrib);
|
||||
if (ca->get_color_type() == ColorAttrib::T_flat) {
|
||||
color = ca->get_color();
|
||||
}
|
||||
}
|
||||
|
||||
lerp_value_from_prev(color, d, _prev_d, color, _end_color);
|
||||
}
|
||||
|
||||
state = state->add_attrib(ColorAttrib::make_flat(color));
|
||||
}
|
||||
|
||||
if ((_flags & F_end_color_scale) != 0) {
|
||||
LVecBase4f color_scale;
|
||||
|
||||
if ((_flags & F_start_color_scale) != 0) {
|
||||
lerp_value(color_scale, d, _start_color_scale, _end_color_scale);
|
||||
|
||||
} else {
|
||||
// Get the previous color scale.
|
||||
color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
const RenderAttrib *attrib =
|
||||
state->get_attrib(ColorScaleAttrib::get_class_type());
|
||||
if (attrib != (const RenderAttrib *)NULL) {
|
||||
const ColorScaleAttrib *csa = DCAST(ColorScaleAttrib, attrib);
|
||||
color_scale = csa->get_scale();
|
||||
}
|
||||
|
||||
lerp_value_from_prev(color_scale, d, _prev_d, color_scale, _end_color_scale);
|
||||
}
|
||||
|
||||
state = state->add_attrib(ColorScaleAttrib::make(color_scale));
|
||||
}
|
||||
|
||||
// Now apply the new state back to the node.
|
||||
if (_other.is_empty()) {
|
||||
_node.set_state(state);
|
||||
} else {
|
||||
_node.set_state(_other, state);
|
||||
}
|
||||
}
|
||||
|
||||
_prev_d = d;
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::reverse_initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: Similar to initialize(), but this is called when the
|
||||
// interval is being played backwards; it indicates that
|
||||
// the interval should start at the finishing state and
|
||||
// undo any intervening intervals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
reverse_initialize(double t) {
|
||||
recompute();
|
||||
_prev_d = 1.0;
|
||||
step(t);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::reverse_instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of reverse_initialize()
|
||||
// .. step() .. reverse_finalize(), when everything is
|
||||
// to happen within one frame. The interval should
|
||||
// initialize itself, then leave itself in the initial
|
||||
// state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
reverse_instant() {
|
||||
recompute();
|
||||
_prev_d = 1.0;
|
||||
step(0.0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CLerpNodePathInterval::output
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CLerpNodePathInterval::
|
||||
output(ostream &out) const {
|
||||
out << get_name() << ":";
|
||||
|
||||
if ((_flags & F_end_pos) != 0) {
|
||||
out << " pos";
|
||||
if ((_flags & F_start_pos) != 0) {
|
||||
out << " from " << _start_pos;
|
||||
}
|
||||
out << " to " << _end_pos;
|
||||
}
|
||||
|
||||
if ((_flags & F_end_hpr) != 0) {
|
||||
out << " hpr";
|
||||
if ((_flags & F_start_hpr) != 0) {
|
||||
out << " from " << _start_hpr;
|
||||
}
|
||||
out << " to " << _end_hpr;
|
||||
}
|
||||
|
||||
if ((_flags & F_end_scale) != 0) {
|
||||
out << " scale";
|
||||
if ((_flags & F_start_scale) != 0) {
|
||||
out << " from " << _start_scale;
|
||||
}
|
||||
out << " to " << _end_scale;
|
||||
}
|
||||
|
||||
if ((_flags & F_end_color) != 0) {
|
||||
out << " color";
|
||||
if ((_flags & F_start_color) != 0) {
|
||||
out << " from " << _start_color;
|
||||
}
|
||||
out << " to " << _end_color;
|
||||
}
|
||||
|
||||
if ((_flags & F_end_color_scale) != 0) {
|
||||
out << " color_scale";
|
||||
if ((_flags & F_start_color_scale) != 0) {
|
||||
out << " from " << _start_color_scale;
|
||||
}
|
||||
out << " to " << _end_color_scale;
|
||||
}
|
||||
|
||||
out << " dur " << get_duration();
|
||||
}
|
||||
109
direct/src/interval/cLerpNodePathInterval.h
Normal file
109
direct/src/interval/cLerpNodePathInterval.h
Normal file
@@ -0,0 +1,109 @@
|
||||
// Filename: cLerpNodePathInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CLERPNODEPATHINTERVAL_H
|
||||
#define CLERPNODEPATHINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cLerpInterval.h"
|
||||
#include "nodePath.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CLerpNodePathInterval
|
||||
// Description : An interval that lerps one or more properties (like
|
||||
// pos, hpr, etc.) on a NodePath over time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT CLerpNodePathInterval : public CLerpInterval {
|
||||
PUBLISHED:
|
||||
CLerpNodePathInterval(const string &name, double duration,
|
||||
BlendType blend_type,
|
||||
const NodePath &node, const NodePath &other);
|
||||
|
||||
INLINE const NodePath &get_node() const;
|
||||
INLINE const NodePath &get_other() const;
|
||||
|
||||
INLINE void set_start_pos(const LVecBase3f &pos);
|
||||
INLINE void set_end_pos(const LVecBase3f &pos);
|
||||
INLINE void set_start_hpr(const LVecBase3f &hpr);
|
||||
INLINE void set_end_hpr(const LVecBase3f &hpr);
|
||||
INLINE void set_start_scale(const LVecBase3f &scale);
|
||||
INLINE void set_start_scale(float scale);
|
||||
INLINE void set_end_scale(const LVecBase3f &scale);
|
||||
INLINE void set_end_scale(float scale);
|
||||
INLINE void set_start_color(const LVecBase4f &color);
|
||||
INLINE void set_end_color(const LVecBase4f &color);
|
||||
INLINE void set_start_color_scale(const LVecBase4f &color_scale);
|
||||
INLINE void set_end_color_scale(const LVecBase4f &color_scale);
|
||||
|
||||
virtual void initialize(double t);
|
||||
virtual void instant();
|
||||
virtual void step(double t);
|
||||
virtual void reverse_initialize(double t);
|
||||
virtual void reverse_instant();
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
NodePath _node;
|
||||
NodePath _other;
|
||||
|
||||
enum Flags {
|
||||
F_end_pos = 0x0001,
|
||||
F_end_hpr = 0x0002,
|
||||
F_end_scale = 0x0004,
|
||||
F_end_color = 0x0008,
|
||||
F_end_color_scale = 0x0010,
|
||||
|
||||
F_start_pos = 0x0100,
|
||||
F_start_hpr = 0x0200,
|
||||
F_start_scale = 0x0400,
|
||||
F_start_color = 0x0800,
|
||||
F_start_color_scale = 0x1000,
|
||||
};
|
||||
|
||||
int _flags;
|
||||
LPoint3f _start_pos, _end_pos;
|
||||
LVecBase3f _start_hpr, _end_hpr;
|
||||
LVecBase3f _start_scale, _end_scale;
|
||||
Colorf _start_color, _end_color;
|
||||
LVecBase4f _start_color_scale, _end_color_scale;
|
||||
|
||||
double _prev_d;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CLerpInterval::init_type();
|
||||
register_type(_type_handle, "CLerpNodePathInterval",
|
||||
CLerpInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cLerpNodePathInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
239
direct/src/interval/cMetaInterval.I
Normal file
239
direct/src/interval/cMetaInterval.I
Normal file
@@ -0,0 +1,239 @@
|
||||
// Filename: cMetaInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::set_precision
|
||||
// Access: Published
|
||||
// Description: Indicates the precision with which time measurements
|
||||
// are compared. For numerical accuracy, all
|
||||
// floating-point time values are converted to integer
|
||||
// values internally by scaling by the precision factor.
|
||||
// The larger the number given here, the smaller the
|
||||
// delta of time that can be differentiated; the
|
||||
// limit is the maximum integer that can be represented
|
||||
// in the system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CMetaInterval::
|
||||
set_precision(double precision) {
|
||||
_precision = precision;
|
||||
mark_dirty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_precision
|
||||
// Access: Published
|
||||
// Description: Returns the precision with which time measurements
|
||||
// are compared. See set_precision().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double CMetaInterval::
|
||||
get_precision() const {
|
||||
return _precision;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_num_defs
|
||||
// Access: Published
|
||||
// Description: Returns the number of interval and push/pop
|
||||
// definitions that have been added to the meta
|
||||
// interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int CMetaInterval::
|
||||
get_num_defs() const {
|
||||
return (int)_defs.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_def_type
|
||||
// Access: Published
|
||||
// Description: Returns the type of the nth interval definition that
|
||||
// has been added.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CMetaInterval::DefType CMetaInterval::
|
||||
get_def_type(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_defs.size(), DT_c_interval);
|
||||
return _defs[n]._type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_c_interval
|
||||
// Access: Published
|
||||
// Description: Return the CInterval pointer associated with the nth
|
||||
// interval definition. It is only valid to call this
|
||||
// if get_def_type(n) returns DT_c_interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CInterval *CMetaInterval::
|
||||
get_c_interval(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_defs.size(), NULL);
|
||||
nassertr(_defs[n]._type == DT_c_interval, NULL);
|
||||
return _defs[n]._c_interval;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_ext_index
|
||||
// Access: Published
|
||||
// Description: Return the external interval index number associated
|
||||
// with the nth interval definition. It is only valid
|
||||
// to call this if get_def_type(n) returns DT_ext_index.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int CMetaInterval::
|
||||
get_ext_index(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_defs.size(), NULL);
|
||||
nassertr(_defs[n]._type == DT_ext_index, NULL);
|
||||
return _defs[n]._ext_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::is_event_ready
|
||||
// Access: Published
|
||||
// Description: Returns true if a recent call to initialize(),
|
||||
// step(), or finalize() has left some external
|
||||
// intervals ready to play. If this returns true, call
|
||||
// get_event_index(), get_event_t(), and pop_event() to
|
||||
// retrieve the relevant information.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CMetaInterval::
|
||||
is_event_ready() {
|
||||
return service_event_queue();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_event_index
|
||||
// Access: Published
|
||||
// Description: If a previous call to is_event_ready() returned
|
||||
// true, this returns the index number (added via
|
||||
// add_event_index()) of the external interval that needs
|
||||
// to be played.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int CMetaInterval::
|
||||
get_event_index() const {
|
||||
nassertr(!_event_queue.empty(), -1);
|
||||
const EventQueueEntry &entry = _event_queue.front();
|
||||
const IntervalDef &def = _defs[entry._n];
|
||||
nassertr(def._type == DT_ext_index, -1);
|
||||
return def._ext_index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_event_t
|
||||
// Access: Published
|
||||
// Description: If a previous call to is_event_ready() returned
|
||||
// true, this returns the t value that should be fed to
|
||||
// the given interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double CMetaInterval::
|
||||
get_event_t() const {
|
||||
nassertr(!_event_queue.empty(), 0.0f);
|
||||
return int_to_double_time(_event_queue.front()._time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_event_type
|
||||
// Access: Published
|
||||
// Description: If a previous call to is_event_ready() returned
|
||||
// true, this returns the type of the event (initialize,
|
||||
// step, finalize, etc.) for the given interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CInterval::EventType CMetaInterval::
|
||||
get_event_type() const {
|
||||
nassertr(!_event_queue.empty(), ET_step);
|
||||
return _event_queue.front()._event_type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::pop_event
|
||||
// Access: Published
|
||||
// Description: Acknowledges that the external interval on the top of
|
||||
// the queue has been extracted, and is about to be
|
||||
// serviced by the scripting language. This prepares
|
||||
// the interval so the next call to is_event_ready()
|
||||
// will return information about the next external
|
||||
// interval on the queue, if any.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void CMetaInterval::
|
||||
pop_event() {
|
||||
#ifndef NDEBUG
|
||||
nassertv(!_event_queue.empty());
|
||||
const EventQueueEntry &entry = _event_queue.front();
|
||||
const IntervalDef &def = _defs[entry._n];
|
||||
nassertv(def._type == DT_ext_index);
|
||||
#endif
|
||||
_event_queue.pop_front();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::double_to_int_time
|
||||
// Access: Private
|
||||
// Description: Converts from an external double time value or offset
|
||||
// in seconds to an internal integer value or offset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int CMetaInterval::
|
||||
double_to_int_time(double t) const {
|
||||
// Use floor() just in case there are negative values involved.
|
||||
return (int)floor(t * _precision + 0.5);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::int_to_double_time
|
||||
// Access: Private
|
||||
// Description: Converts from an internal integer time value or
|
||||
// offset to an external double time value or offset in
|
||||
// seconds.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double CMetaInterval::
|
||||
int_to_double_time(int time) const {
|
||||
return (double)time / _precision;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::PlaybackEvent::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CMetaInterval::PlaybackEvent::
|
||||
PlaybackEvent(int time, int n,
|
||||
CMetaInterval::PlaybackEventType type) :
|
||||
_time(time),
|
||||
_n(n),
|
||||
_type(type)
|
||||
{
|
||||
_begin_event = this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::PlaybackEvent::Ordering operator
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool CMetaInterval::PlaybackEvent::
|
||||
operator < (const CMetaInterval::PlaybackEvent &other) const {
|
||||
return _time < other._time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::EventQueueEntry::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE CMetaInterval::EventQueueEntry::
|
||||
EventQueueEntry(int n, CInterval::EventType event_type, int time) :
|
||||
_n(n),
|
||||
_event_type(event_type),
|
||||
_time(time)
|
||||
{
|
||||
}
|
||||
877
direct/src/interval/cMetaInterval.cxx
Normal file
877
direct/src/interval/cMetaInterval.cxx
Normal file
@@ -0,0 +1,877 @@
|
||||
// Filename: cMetaInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "cMetaInterval.h"
|
||||
#include "config_interval.h"
|
||||
#include "indirectLess.h"
|
||||
#include <algorithm>
|
||||
#include <math.h> // for log10()
|
||||
#include <stdio.h> // for sprintf()
|
||||
|
||||
TypeHandle CMetaInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CMetaInterval::
|
||||
CMetaInterval(const string &name) :
|
||||
CInterval(name, 0.0, true)
|
||||
{
|
||||
_precision = interval_precision;
|
||||
_current_nesting_level = 0;
|
||||
_next_event_index = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
CMetaInterval::
|
||||
~CMetaInterval() {
|
||||
clear_intervals();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::clear_intervals
|
||||
// Access: Published
|
||||
// Description: Resets the list of intervals and prepares for
|
||||
// receiving a new list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
clear_intervals() {
|
||||
// Better not do this unless you have serviced all of the
|
||||
// outstanding events!
|
||||
nassertv(_event_queue.empty());
|
||||
|
||||
clear_events();
|
||||
|
||||
// Go through all of our nested intervals and remove ourselves as
|
||||
// their parent.
|
||||
Defs::iterator di;
|
||||
for (di = _defs.begin(); di != _defs.end(); ++di) {
|
||||
IntervalDef &def = (*di);
|
||||
if (def._c_interval != (CInterval *)NULL) {
|
||||
CInterval::Parents::iterator pi =
|
||||
find(def._c_interval->_parents.begin(),
|
||||
def._c_interval->_parents.end(),
|
||||
this);
|
||||
nassertv(pi != def._c_interval->_parents.end());
|
||||
def._c_interval->_parents.erase(pi);
|
||||
}
|
||||
}
|
||||
_defs.clear();
|
||||
|
||||
_current_nesting_level = 0;
|
||||
_next_event_index = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::push_level
|
||||
// Access: Published
|
||||
// Description: Marks the beginning of a nested level of child
|
||||
// intervals. Within the nested level, a RelativeStart
|
||||
// time of RS_level_begin refers to the start of the
|
||||
// level, and the first interval added within the level
|
||||
// is always relative to the start of the level.
|
||||
//
|
||||
// The return value is the index of the def entry
|
||||
// created by this push.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
push_level(double rel_time, RelativeStart rel_to) {
|
||||
_defs.push_back(IntervalDef());
|
||||
IntervalDef &def = _defs.back();
|
||||
def._type = DT_push_level;
|
||||
def._rel_time = rel_time;
|
||||
def._rel_to = rel_to;
|
||||
_current_nesting_level++;
|
||||
mark_dirty();
|
||||
|
||||
return (int)_defs.size() - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::add_c_interval
|
||||
// Access: Published
|
||||
// Description: Adds a new CInterval to the list. The interval will
|
||||
// be played when the indicated time (relative to the
|
||||
// given point) has been reached.
|
||||
//
|
||||
// The return value is the index of the def entry
|
||||
// representing the new interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
add_c_interval(CInterval *c_interval,
|
||||
double rel_time, RelativeStart rel_to) {
|
||||
nassertr(c_interval != (CInterval *)NULL, -1);
|
||||
|
||||
c_interval->_parents.push_back(this);
|
||||
_defs.push_back(IntervalDef());
|
||||
IntervalDef &def = _defs.back();
|
||||
def._type = DT_c_interval;
|
||||
def._c_interval = c_interval;
|
||||
def._rel_time = rel_time;
|
||||
def._rel_to = rel_to;
|
||||
mark_dirty();
|
||||
|
||||
return (int)_defs.size() - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::add_ext_index
|
||||
// Access: Published
|
||||
// Description: Adds a new external interval to the list. This
|
||||
// represents some object in the external scripting
|
||||
// language that has properties similar to a CInterval
|
||||
// (for instance, a Python Interval object).
|
||||
//
|
||||
// The CMetaInterval object cannot play this external
|
||||
// interval directly, but it records a placeholder for
|
||||
// it and will ask the scripting language to play it
|
||||
// when it is time, via is_event_ready() and related
|
||||
// methods.
|
||||
//
|
||||
// The ext_index number itself is simply a handle that
|
||||
// the scripting language makes up and associates with
|
||||
// its interval object somehow. The CMetaInterval
|
||||
// object does not attempt to interpret this value.
|
||||
//
|
||||
// The return value is the index of the def entry
|
||||
// representing the new interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
add_ext_index(int ext_index, const string &name, double duration,
|
||||
bool open_ended,
|
||||
double rel_time, RelativeStart rel_to) {
|
||||
_defs.push_back(IntervalDef());
|
||||
IntervalDef &def = _defs.back();
|
||||
def._type = DT_ext_index;
|
||||
def._ext_index = ext_index;
|
||||
def._ext_name = name;
|
||||
def._ext_duration = duration;
|
||||
def._ext_open_ended = open_ended;
|
||||
def._rel_time = rel_time;
|
||||
def._rel_to = rel_to;
|
||||
mark_dirty();
|
||||
|
||||
return (int)_defs.size() - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::pop_level
|
||||
// Access: Published
|
||||
// Description: Finishes a level marked by a previous call to
|
||||
// push_level(), and returns to the previous level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
pop_level() {
|
||||
nassertr(_current_nesting_level > 0, -1);
|
||||
|
||||
_defs.push_back(IntervalDef());
|
||||
IntervalDef &def = _defs.back();
|
||||
def._type = DT_pop_level;
|
||||
_current_nesting_level--;
|
||||
mark_dirty();
|
||||
|
||||
return (int)_defs.size() - 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: This replaces the first call to step(), and indicates
|
||||
// that the interval has just begun. This may be
|
||||
// overridden by derived classes that need to do some
|
||||
// explicit initialization on the first call.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
initialize(double t) {
|
||||
// It may be tempting to flush the event_queue here, but don't do
|
||||
// it. Those are events that must still be serviced from some
|
||||
// previous interval operation. Throwing them away would be a
|
||||
// mistake.
|
||||
|
||||
recompute();
|
||||
_next_event_index = 0;
|
||||
_active.clear();
|
||||
|
||||
int now = double_to_int_time(t);
|
||||
|
||||
// Now look for events from the beginning up to the current time.
|
||||
ActiveEvents new_active;
|
||||
while (_next_event_index < _events.size() &&
|
||||
_events[_next_event_index]->_time <= now) {
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
|
||||
// Do the indicated event.
|
||||
do_event_forward(event, new_active, true);
|
||||
_next_event_index++;
|
||||
}
|
||||
finish_events_forward(now, new_active);
|
||||
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of initialize() .. step()
|
||||
// .. finalize(), when everything is to happen within
|
||||
// one frame. The interval should initialize itself,
|
||||
// then leave itself in the final state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
instant() {
|
||||
recompute();
|
||||
_active.clear();
|
||||
|
||||
// Apply all of the events. This just means we invoke "instant" for
|
||||
// any end or instant event, ignoring the begin events.
|
||||
PlaybackEvents::iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
PlaybackEvent *event = (*ei);
|
||||
if (event->_type != PET_begin) {
|
||||
enqueue_event(event->_n, ET_instant, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
_next_event_index = _events.size();
|
||||
_curr_t = get_duration();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::step
|
||||
// Access: Published, Virtual
|
||||
// Description: Advances the time on the interval. The time may
|
||||
// either increase (the normal case) or decrease
|
||||
// (e.g. if the interval is being played by a slider).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
step(double t) {
|
||||
int now = double_to_int_time(t);
|
||||
|
||||
// Now look for events between the last time we ran and the current
|
||||
// time.
|
||||
|
||||
if (_next_event_index < _events.size() &&
|
||||
_events[_next_event_index]->_time <= now) {
|
||||
// The normal case: time is increasing.
|
||||
ActiveEvents new_active;
|
||||
while (_next_event_index < _events.size() &&
|
||||
_events[_next_event_index]->_time <= now) {
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
|
||||
// Do the indicated event.
|
||||
do_event_forward(event, new_active, false);
|
||||
_next_event_index++;
|
||||
}
|
||||
|
||||
finish_events_forward(now, new_active);
|
||||
|
||||
} else {
|
||||
// A less usual case: time is decreasing.
|
||||
ActiveEvents new_active;
|
||||
while (_next_event_index > 0 &&
|
||||
_events[_next_event_index - 1]->_time > now) {
|
||||
_next_event_index--;
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
do_event_reverse(event, new_active, false);
|
||||
}
|
||||
|
||||
finish_events_reverse(now, new_active);
|
||||
}
|
||||
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::finalize
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called when an interval is interrupted. It
|
||||
// should advance the time as if step() were called, and
|
||||
// also perform whatever cleanup might be required.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
finalize() {
|
||||
// Do all remaining events.
|
||||
ActiveEvents new_active;
|
||||
while (_next_event_index < _events.size()) {
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
// Do the indicated event.
|
||||
do_event_forward(event, new_active, false);
|
||||
_next_event_index++;
|
||||
}
|
||||
|
||||
_curr_t = get_duration();
|
||||
finish_events_forward(double_to_int_time(_curr_t), new_active);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::reverse_initialize
|
||||
// Access: Published, Virtual
|
||||
// Description: Similar to initialize(), but this is called when the
|
||||
// interval is being played backwards; it indicates that
|
||||
// the interval should start at the finishing state and
|
||||
// undo any intervening intervals.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
reverse_initialize(double t) {
|
||||
// It may be tempting to flush the event_queue here, but don't do
|
||||
// it. Those are events that must still be serviced from some
|
||||
// previous interval operation. Throwing them away would be a
|
||||
// mistake.
|
||||
|
||||
recompute();
|
||||
_next_event_index = _events.size();
|
||||
_active.clear();
|
||||
|
||||
int now = double_to_int_time(t);
|
||||
|
||||
// Now look for events from the end down to the current time.
|
||||
ActiveEvents new_active;
|
||||
while (_next_event_index > 0 &&
|
||||
_events[_next_event_index - 1]->_time > now) {
|
||||
_next_event_index--;
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
|
||||
// Do the indicated event.
|
||||
do_event_reverse(event, new_active, true);
|
||||
}
|
||||
finish_events_reverse(now, new_active);
|
||||
|
||||
_curr_t = t;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::reverse_instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of reverse_initialize()
|
||||
// .. step() .. reverse_finalize(), when everything is
|
||||
// to happen within one frame. The interval should
|
||||
// initialize itself, then leave itself in the initial
|
||||
// state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
reverse_instant() {
|
||||
recompute();
|
||||
_active.clear();
|
||||
|
||||
// Apply all of the events. This just means we invoke "instant" for
|
||||
// any end or instant event, ignoring the begin events.
|
||||
PlaybackEvents::reverse_iterator ei;
|
||||
for (ei = _events.rbegin(); ei != _events.rend(); ++ei) {
|
||||
PlaybackEvent *event = (*ei);
|
||||
if (event->_type != PET_begin) {
|
||||
enqueue_event(event->_n, ET_reverse_instant, true, 0);
|
||||
}
|
||||
}
|
||||
|
||||
_next_event_index = 0;
|
||||
_curr_t = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::reverse_finalize
|
||||
// Access: Published, Virtual
|
||||
// Description: Called generally following a reverse_initialize(),
|
||||
// this indicates the interval should set itself to the
|
||||
// initial state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
reverse_finalize() {
|
||||
// Do all remaining events at the beginning.
|
||||
ActiveEvents new_active;
|
||||
|
||||
while (_next_event_index > 0) {
|
||||
_next_event_index--;
|
||||
PlaybackEvent *event = _events[_next_event_index];
|
||||
do_event_reverse(event, new_active, false);
|
||||
}
|
||||
|
||||
finish_events_reverse(0, new_active);
|
||||
_curr_t = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::write
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
write(ostream &out, int indent_level) const {
|
||||
recompute();
|
||||
|
||||
// How many digits of precision should we output for time?
|
||||
int num_decimals = (int)ceil(log10(_precision));
|
||||
int total_digits = num_decimals + 4;
|
||||
static const int max_digits = 32; // totally arbitrary
|
||||
nassertv(total_digits <= max_digits);
|
||||
char format_str[12];
|
||||
sprintf(format_str, "%%%d.%df", total_digits, num_decimals);
|
||||
|
||||
indent(out, indent_level) << get_name() << ":\n";
|
||||
|
||||
int extra_indent_level = 1;
|
||||
Defs::const_iterator di;
|
||||
for (di = _defs.begin(); di != _defs.end(); ++di) {
|
||||
const IntervalDef &def = (*di);
|
||||
char time_str[max_digits + 1];
|
||||
sprintf(time_str, format_str, int_to_double_time(def._actual_begin_time));
|
||||
indent(out, indent_level) << time_str;
|
||||
|
||||
switch (def._type) {
|
||||
case DT_c_interval:
|
||||
indent(out, extra_indent_level)
|
||||
<< *def._c_interval;
|
||||
if (!def._c_interval->get_open_ended()) {
|
||||
out << " (!oe)";
|
||||
}
|
||||
out << "\n";
|
||||
break;
|
||||
|
||||
case DT_ext_index:
|
||||
indent(out, extra_indent_level)
|
||||
<< "*" << def._ext_name;
|
||||
if (def._ext_duration != 0.0) {
|
||||
out << " dur " << def._ext_duration;
|
||||
}
|
||||
if (!def._ext_open_ended) {
|
||||
out << " (!oe)";
|
||||
}
|
||||
out<< "\n";
|
||||
break;
|
||||
|
||||
case DT_push_level:
|
||||
indent(out, extra_indent_level)
|
||||
<< "{\n";
|
||||
extra_indent_level += 2;
|
||||
break;
|
||||
|
||||
case DT_pop_level:
|
||||
extra_indent_level -= 2;
|
||||
indent(out, extra_indent_level)
|
||||
<< "}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::do_recompute
|
||||
// Access: Protected, Virtual
|
||||
// Description: Recomputes all of the events (and the duration)
|
||||
// according to the set of interval defs.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
do_recompute() {
|
||||
_dirty = false;
|
||||
clear_events();
|
||||
|
||||
int n = recompute_level(0, 0, _end_time);
|
||||
|
||||
if (n != (int)_defs.size()) {
|
||||
interval_cat.warning()
|
||||
<< "CMetaInterval pushes don't match pops.\n";
|
||||
}
|
||||
|
||||
// We do a stable_sort() to guarantee ordering of events that have
|
||||
// the same start time. These must be invoked in the order in which
|
||||
// they appear.
|
||||
stable_sort(_events.begin(), _events.end(), IndirectLess<PlaybackEvent>());
|
||||
_duration = int_to_double_time(_end_time);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::clear_events
|
||||
// Access: Private
|
||||
// Description: Removes all entries from the _events list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
clear_events() {
|
||||
PlaybackEvents::iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
PlaybackEvent *event = (*ei);
|
||||
delete event;
|
||||
}
|
||||
_events.clear();
|
||||
_active.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::do_event_forward
|
||||
// Access: Private
|
||||
// Description: Process a single event in the interval, moving
|
||||
// forwards in time. If the event represents a new
|
||||
// begin, adds it to the new_active list; if it is an
|
||||
// end, finalizes it.
|
||||
//
|
||||
// If is_initial is true, it is as if we are in
|
||||
// initialize: instant events will be invoked only if
|
||||
// they are marked open_ended.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
do_event_forward(CMetaInterval::PlaybackEvent *event,
|
||||
CMetaInterval::ActiveEvents &new_active, bool is_initial) {
|
||||
switch (event->_type) {
|
||||
case PET_begin:
|
||||
{
|
||||
nassertv(event->_begin_event == event);
|
||||
nassertv(_active.find(event) == _active.end());
|
||||
bool okflag = new_active.insert(event).second;
|
||||
nassertv(okflag);
|
||||
}
|
||||
break;
|
||||
|
||||
case PET_end:
|
||||
{
|
||||
// Erase the event from either the new active or the current
|
||||
// active lists.
|
||||
int erase_count = new_active.erase(event->_begin_event);
|
||||
if (erase_count != 0) {
|
||||
// This interval was new this frame; we must invoke it as
|
||||
// an instant event.
|
||||
enqueue_event(event->_n, ET_instant, is_initial);
|
||||
} else {
|
||||
erase_count = _active.erase(event->_begin_event);
|
||||
enqueue_event(event->_n, ET_finalize, is_initial);
|
||||
}
|
||||
nassertv(erase_count == 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case PET_instant:
|
||||
nassertv(event->_begin_event == event);
|
||||
nassertv(new_active.find(event) == new_active.end());
|
||||
nassertv(_active.find(event) == _active.end());
|
||||
enqueue_event(event->_n, ET_instant, is_initial);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::finish_events_forward
|
||||
// Access: Private
|
||||
// Description: After walking through the event list and adding a
|
||||
// bunch of new events to new_active, finished up by
|
||||
// calling step() on all of the events still in _active
|
||||
// and initialize() on all the events in new_active,
|
||||
// then copying the events from new_active to active.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
finish_events_forward(int now, CMetaInterval::ActiveEvents &new_active) {
|
||||
// Do whatever's still active.
|
||||
ActiveEvents::iterator ai;
|
||||
for (ai = _active.begin(); ai != _active.end(); ++ai) {
|
||||
PlaybackEvent *event = (*ai);
|
||||
enqueue_event(event->_n, ET_step, false, now - event->_time);
|
||||
}
|
||||
|
||||
// Initialize whatever new intervals we came across.
|
||||
for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
|
||||
PlaybackEvent *event = (*ai);
|
||||
enqueue_event(event->_n, ET_initialize, false, now - event->_time);
|
||||
bool inserted = _active.insert(event).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::do_event_reverse
|
||||
// Access: Private
|
||||
// Description: Process a single event in the interval, moving
|
||||
// backwards in time. This undoes the indicated event.
|
||||
// If the event represents a new begin, adds it to the
|
||||
// new_active list; if it is an end, finalizes it.
|
||||
//
|
||||
// If is_initial is true, it is as if we are in
|
||||
// reverse_initialize: instant events will be invoked
|
||||
// only if they are marked open_ended.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
do_event_reverse(CMetaInterval::PlaybackEvent *event,
|
||||
CMetaInterval::ActiveEvents &new_active, bool is_initial) {
|
||||
// Undo the indicated event.
|
||||
switch (event->_type) {
|
||||
case PET_begin:
|
||||
{
|
||||
nassertv(event->_begin_event == event);
|
||||
// Erase the event from either the new active or the current
|
||||
// active lists.
|
||||
int erase_count = new_active.erase(event);
|
||||
if (erase_count != 0) {
|
||||
// This interval was new this frame; we invoke it as an
|
||||
// instant event.
|
||||
enqueue_event(event->_n, ET_reverse_instant, is_initial);
|
||||
} else {
|
||||
erase_count = _active.erase(event->_begin_event);
|
||||
enqueue_event(event->_n, ET_reverse_finalize, is_initial);
|
||||
}
|
||||
nassertv(erase_count == 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case PET_end:
|
||||
{
|
||||
nassertv(new_active.find(event->_begin_event) == new_active.end());
|
||||
bool okflag = new_active.insert(event->_begin_event).second;
|
||||
nassertv(okflag);
|
||||
}
|
||||
break;
|
||||
|
||||
case PET_instant:
|
||||
nassertv(event->_begin_event == event);
|
||||
nassertv(_active.find(event) == _active.end());
|
||||
nassertv(new_active.find(event) == new_active.end());
|
||||
enqueue_event(event->_n, ET_reverse_instant, is_initial);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::finish_events_reverse
|
||||
// Access: Private
|
||||
// Description: After walking through the event list and adding a
|
||||
// bunch of new events to new_active, finishes up by
|
||||
// calling step() on all of the events still in _active
|
||||
// and reverse_initialize() on all the events in
|
||||
// new_active, then copying the events from new_active
|
||||
// to active.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
finish_events_reverse(int now, CMetaInterval::ActiveEvents &new_active) {
|
||||
// Do whatever's still active.
|
||||
ActiveEvents::iterator ai;
|
||||
for (ai = _active.begin(); ai != _active.end(); ++ai) {
|
||||
PlaybackEvent *event = (*ai);
|
||||
enqueue_event(event->_n, ET_step, false, now - event->_time);
|
||||
}
|
||||
|
||||
// Initialize whatever new intervals we came across.
|
||||
for (ai = new_active.begin(); ai != new_active.end(); ++ai) {
|
||||
PlaybackEvent *event = (*ai);
|
||||
enqueue_event(event->_n, ET_reverse_initialize, false, now - event->_time);
|
||||
bool inserted = _active.insert(event).second;
|
||||
nassertv(inserted);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::enqueue_event
|
||||
// Access: Private
|
||||
// Description: Enqueues the indicated interval for invocation after
|
||||
// we have finished scanning for events that need
|
||||
// processing this frame.
|
||||
//
|
||||
// is_initial is only relevant for event types
|
||||
// ET_instant or ET_reverse_instant, and indicates
|
||||
// whether we are in the initialize() (or
|
||||
// reverse_initialize()) call, and should therefore only
|
||||
// invoke open-ended intervals.
|
||||
//
|
||||
// time is only relevant for ET_initialize,
|
||||
// ET_reverse_initialize, and ET_step.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void CMetaInterval::
|
||||
enqueue_event(int n, CInterval::EventType event_type, bool is_initial, int time) {
|
||||
nassertv(n >= 0 && n < (int)_defs.size());
|
||||
const IntervalDef &def = _defs[n];
|
||||
switch (def._type) {
|
||||
case DT_c_interval:
|
||||
if (is_initial &&
|
||||
(event_type == ET_instant || event_type == ET_reverse_instant) &&
|
||||
!def._c_interval->get_open_ended()) {
|
||||
// Ignore a non-open-ended interval that we skipped completely
|
||||
// past on initialize().
|
||||
return;
|
||||
} else {
|
||||
if (_event_queue.empty()) {
|
||||
// if the event queue is empty, we can process this C++
|
||||
// interval immediately. We only need to defer it if there
|
||||
// are external (e.g. Python) intervals in the queue that need
|
||||
// to be processed first.
|
||||
def._c_interval->set_t(int_to_double_time(time), event_type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DT_ext_index:
|
||||
if (is_initial &&
|
||||
(event_type == ET_instant || event_type == ET_reverse_instant) &&
|
||||
!def._ext_open_ended) {
|
||||
// Ignore a non-open-ended interval that we skipped completely
|
||||
// past on initialize().
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nassertv(false);
|
||||
return;
|
||||
}
|
||||
|
||||
_event_queue.push_back(EventQueueEntry(n, event_type, time));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::service_event_queue
|
||||
// Access: Private
|
||||
// Description: Invokes whatever C++ intervals might be at the head
|
||||
// of the queue, and prepares for passing an external
|
||||
// interval to the scripting language.
|
||||
//
|
||||
// The return value is true if there remains at least
|
||||
// one external event to be serviced, false if all
|
||||
// events are handled.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool CMetaInterval::
|
||||
service_event_queue() {
|
||||
while (!_event_queue.empty()) {
|
||||
const EventQueueEntry &entry = _event_queue.front();
|
||||
nassertr(entry._n >= 0 && entry._n < (int)_defs.size(), false);
|
||||
const IntervalDef &def = _defs[entry._n];
|
||||
switch (def._type) {
|
||||
case DT_c_interval:
|
||||
// Handle the C++ event.
|
||||
def._c_interval->set_t(int_to_double_time(entry._time), entry._event_type);
|
||||
break;
|
||||
|
||||
case DT_ext_index:
|
||||
// Here's an external event; leave it there and return.
|
||||
return true;
|
||||
|
||||
default:
|
||||
nassertr(false, false);
|
||||
return false;
|
||||
}
|
||||
_event_queue.pop_front();
|
||||
}
|
||||
|
||||
// No more events on the queue.
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::recompute_level
|
||||
// Access: Private
|
||||
// Description: Recursively recomputes a complete level (delimited by
|
||||
// push/pop definitions).
|
||||
//
|
||||
// The value n on entry refers to the first entry after
|
||||
// the push; the return value will reference the
|
||||
// matching pop, or an index greater than the last
|
||||
// element in the array if there was no matching pop.
|
||||
//
|
||||
// The level_begin value indicates the begin time of
|
||||
// this level. On return, level_end is filled with the
|
||||
// end time of this level.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
recompute_level(int n, int level_begin, int &level_end) {
|
||||
level_end = level_begin;
|
||||
int previous_begin = level_begin;
|
||||
int previous_end = level_begin;
|
||||
|
||||
while (n < (int)_defs.size() && _defs[n]._type != DT_pop_level) {
|
||||
IntervalDef &def = _defs[n];
|
||||
int begin_time, end_time;
|
||||
switch (def._type) {
|
||||
case DT_c_interval:
|
||||
begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
|
||||
def._actual_begin_time = begin_time;
|
||||
end_time = begin_time + double_to_int_time(def._c_interval->get_duration());
|
||||
if (begin_time == end_time) {
|
||||
_events.push_back(new PlaybackEvent(begin_time, n, PET_instant));
|
||||
} else {
|
||||
PlaybackEvent *begin = new PlaybackEvent(begin_time, n, PET_begin);
|
||||
PlaybackEvent *end = new PlaybackEvent(end_time, n, PET_end);
|
||||
end->_begin_event = begin;
|
||||
_events.push_back(begin);
|
||||
_events.push_back(end);
|
||||
}
|
||||
break;
|
||||
|
||||
case DT_ext_index:
|
||||
begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
|
||||
def._actual_begin_time = begin_time;
|
||||
end_time = begin_time + double_to_int_time(def._ext_duration);
|
||||
if (begin_time == end_time) {
|
||||
_events.push_back(new PlaybackEvent(begin_time, n, PET_instant));
|
||||
} else {
|
||||
PlaybackEvent *begin = new PlaybackEvent(begin_time, n, PET_begin);
|
||||
PlaybackEvent *end = new PlaybackEvent(end_time, n, PET_end);
|
||||
end->_begin_event = begin;
|
||||
_events.push_back(begin);
|
||||
_events.push_back(end);
|
||||
}
|
||||
break;
|
||||
|
||||
case DT_push_level:
|
||||
begin_time = get_begin_time(def, level_begin, previous_begin, previous_end);
|
||||
def._actual_begin_time = begin_time;
|
||||
n = recompute_level(n + 1, begin_time, end_time);
|
||||
break;
|
||||
|
||||
case DT_pop_level:
|
||||
nassertr(false, _defs.size());
|
||||
break;
|
||||
}
|
||||
|
||||
previous_begin = begin_time;
|
||||
previous_end = end_time;
|
||||
level_end = max(level_end, end_time);
|
||||
n++;
|
||||
}
|
||||
|
||||
if (n < (int)_defs.size()) {
|
||||
// The final pop "begins" at the level end time, just for clarity
|
||||
// on output.
|
||||
IntervalDef &def = _defs[n];
|
||||
def._actual_begin_time = level_end;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: CMetaInterval::get_begin_time
|
||||
// Access: Private
|
||||
// Description: Returns the integer begin time indicated by the given
|
||||
// IntervalDef, given the indicated level begin,
|
||||
// previous begin, and previous end times.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int CMetaInterval::
|
||||
get_begin_time(const CMetaInterval::IntervalDef &def, int level_begin,
|
||||
int previous_begin, int previous_end) {
|
||||
switch (def._rel_to) {
|
||||
case RS_previous_end:
|
||||
return previous_end + double_to_int_time(def._rel_time);
|
||||
|
||||
case RS_previous_begin:
|
||||
return previous_begin + double_to_int_time(def._rel_time);
|
||||
|
||||
case RS_level_begin:
|
||||
return level_begin + double_to_int_time(def._rel_time);
|
||||
}
|
||||
|
||||
nassertr(false, previous_end);
|
||||
return previous_end;
|
||||
}
|
||||
190
direct/src/interval/cMetaInterval.h
Normal file
190
direct/src/interval/cMetaInterval.h
Normal file
@@ -0,0 +1,190 @@
|
||||
// Filename: cMetaInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CMETAINTERVAL_H
|
||||
#define CMETAINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cInterval.h"
|
||||
|
||||
#include <pdeque.h>
|
||||
#include <pvector.h>
|
||||
#include <pset.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : CMetaInterval
|
||||
// Description : This interval contains a list of nested intervals,
|
||||
// each of which has its own begin and end times. Some
|
||||
// of them may overlap and some of them may not.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT CMetaInterval : public CInterval {
|
||||
PUBLISHED:
|
||||
CMetaInterval(const string &name);
|
||||
virtual ~CMetaInterval();
|
||||
|
||||
enum RelativeStart {
|
||||
RS_previous_end,
|
||||
RS_previous_begin,
|
||||
RS_level_begin,
|
||||
};
|
||||
|
||||
INLINE void set_precision(double precision);
|
||||
INLINE double get_precision() const;
|
||||
|
||||
void clear_intervals();
|
||||
int push_level(double rel_time, RelativeStart rel_to);
|
||||
int add_c_interval(CInterval *c_interval,
|
||||
double rel_time, RelativeStart rel_to);
|
||||
int add_ext_index(int ext_index, const string &name,
|
||||
double duration, bool open_ended,
|
||||
double rel_time, RelativeStart rel_to);
|
||||
int pop_level();
|
||||
|
||||
enum DefType {
|
||||
DT_c_interval,
|
||||
DT_ext_index,
|
||||
DT_push_level,
|
||||
DT_pop_level
|
||||
};
|
||||
|
||||
INLINE int get_num_defs() const;
|
||||
INLINE DefType get_def_type(int n) const;
|
||||
INLINE CInterval *get_c_interval(int n) const;
|
||||
INLINE int get_ext_index(int n) const;
|
||||
|
||||
virtual void initialize(double t);
|
||||
virtual void instant();
|
||||
virtual void step(double t);
|
||||
virtual void finalize();
|
||||
virtual void reverse_initialize(double t);
|
||||
virtual void reverse_instant();
|
||||
virtual void reverse_finalize();
|
||||
|
||||
INLINE bool is_event_ready();
|
||||
INLINE int get_event_index() const;
|
||||
INLINE double get_event_t() const;
|
||||
INLINE EventType get_event_type() const;
|
||||
INLINE void pop_event();
|
||||
|
||||
virtual void write(ostream &out, int indent_level) const;
|
||||
|
||||
protected:
|
||||
virtual void do_recompute();
|
||||
|
||||
private:
|
||||
class IntervalDef {
|
||||
public:
|
||||
DefType _type;
|
||||
PT(CInterval) _c_interval;
|
||||
int _ext_index;
|
||||
string _ext_name;
|
||||
double _ext_duration;
|
||||
bool _ext_open_ended;
|
||||
double _rel_time;
|
||||
RelativeStart _rel_to;
|
||||
int _actual_begin_time;
|
||||
};
|
||||
|
||||
enum PlaybackEventType {
|
||||
PET_begin,
|
||||
PET_end,
|
||||
PET_instant
|
||||
};
|
||||
|
||||
class PlaybackEvent {
|
||||
public:
|
||||
INLINE PlaybackEvent(int time, int n, PlaybackEventType type);
|
||||
INLINE bool operator < (const PlaybackEvent &other) const;
|
||||
int _time;
|
||||
int _n;
|
||||
PlaybackEventType _type;
|
||||
PlaybackEvent *_begin_event;
|
||||
};
|
||||
|
||||
class EventQueueEntry {
|
||||
public:
|
||||
INLINE EventQueueEntry(int n, EventType event_type, int time);
|
||||
int _n;
|
||||
EventType _event_type;
|
||||
int _time;
|
||||
};
|
||||
|
||||
typedef pvector<IntervalDef> Defs;
|
||||
typedef pvector<PlaybackEvent *> PlaybackEvents;
|
||||
typedef pset<PlaybackEvent *> ActiveEvents;
|
||||
typedef pdeque<EventQueueEntry> EventQueue;
|
||||
|
||||
INLINE int double_to_int_time(double t) const;
|
||||
INLINE double int_to_double_time(int time) const;
|
||||
|
||||
void clear_events();
|
||||
void do_event_forward(PlaybackEvent *event, ActiveEvents &new_active,
|
||||
bool is_initial);
|
||||
void finish_events_forward(int now, ActiveEvents &new_active);
|
||||
void do_event_reverse(PlaybackEvent *event, ActiveEvents &new_active,
|
||||
bool is_initial);
|
||||
void finish_events_reverse(int now, ActiveEvents &new_active);
|
||||
|
||||
void enqueue_event(int n, CInterval::EventType event_type, bool is_initial,
|
||||
int time = 0);
|
||||
bool service_event_queue();
|
||||
|
||||
int recompute_level(int n, int level_begin, int &level_end);
|
||||
int get_begin_time(const IntervalDef &def, int level_begin,
|
||||
int previous_begin, int previous_end);
|
||||
|
||||
double _precision;
|
||||
Defs _defs;
|
||||
int _current_nesting_level;
|
||||
|
||||
PlaybackEvents _events;
|
||||
ActiveEvents _active;
|
||||
int _end_time;
|
||||
|
||||
size_t _next_event_index;
|
||||
|
||||
// This is the queue of events that have occurred due to a recent
|
||||
// initialize(), step(), etc., but have not yet been serviced, due
|
||||
// to an embedded external (e.g. Python) interval that the scripting
|
||||
// language must service. This queue should be considered precious,
|
||||
// and should never be arbitrarily flushed without servicing all of
|
||||
// its events.
|
||||
EventQueue _event_queue;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CInterval::init_type();
|
||||
register_type(_type_handle, "CMetaInterval",
|
||||
CInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "cMetaInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
65
direct/src/interval/config_interval.cxx
Normal file
65
direct/src/interval/config_interval.cxx
Normal file
@@ -0,0 +1,65 @@
|
||||
// Filename: config_interval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_interval.h"
|
||||
#include "cInterval.h"
|
||||
#include "cLerpInterval.h"
|
||||
#include "cLerpNodePathInterval.h"
|
||||
#include "cLerpAnimEffectInterval.h"
|
||||
#include "cMetaInterval.h"
|
||||
#include "showInterval.h"
|
||||
#include "hideInterval.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_interval);
|
||||
NotifyCategoryDef(interval, "");
|
||||
|
||||
ConfigureFn(config_interval) {
|
||||
init_libinterval();
|
||||
}
|
||||
|
||||
// Set this to the default value for set_precision() for each
|
||||
// CMetaInterval created.
|
||||
const double interval_precision = config_interval.GetDouble("interval-precision", 1000.0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libinterval
|
||||
// Description: Initializes the library. This must be called at
|
||||
// least once before any of the functions or classes in
|
||||
// this library can be used. Normally it will be
|
||||
// called by the static initializers and need not be
|
||||
// called explicitly, but special cases exist.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
init_libinterval() {
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
CInterval::init_type();
|
||||
CLerpInterval::init_type();
|
||||
CLerpNodePathInterval::init_type();
|
||||
CLerpAnimEffectInterval::init_type();
|
||||
CMetaInterval::init_type();
|
||||
ShowInterval::init_type();
|
||||
HideInterval::init_type();
|
||||
}
|
||||
|
||||
32
direct/src/interval/config_interval.h
Normal file
32
direct/src/interval/config_interval.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Filename: config_interval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_INTERVAL_H
|
||||
#define CONFIG_INTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
NotifyCategoryDecl(interval, EXPCL_DIRECT, EXPTP_DIRECT);
|
||||
|
||||
extern const double interval_precision;
|
||||
|
||||
extern EXPCL_DIRECT void init_libinterval();
|
||||
|
||||
#endif
|
||||
18
direct/src/interval/hideInterval.I
Normal file
18
direct/src/interval/hideInterval.I
Normal file
@@ -0,0 +1,18 @@
|
||||
// Filename: hideInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
68
direct/src/interval/hideInterval.cxx
Normal file
68
direct/src/interval/hideInterval.cxx
Normal file
@@ -0,0 +1,68 @@
|
||||
// Filename: hideInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "hideInterval.h"
|
||||
|
||||
int HideInterval::_unique_index;
|
||||
TypeHandle HideInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HideInterval::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
HideInterval::
|
||||
HideInterval(const NodePath &node, const string &name) :
|
||||
CInterval(name, 0.0, true),
|
||||
_node(node)
|
||||
{
|
||||
nassertv(!node.is_empty());
|
||||
if (_name.empty()) {
|
||||
ostringstream name_strm;
|
||||
name_strm
|
||||
<< "HideInterval-" << node.node()->get_name() << "-" << ++_unique_index;
|
||||
_name = name_strm.str();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HideInterval::instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of initialize() .. step()
|
||||
// .. finalize(), when everything is to happen within
|
||||
// one frame. The interval should initialize itself,
|
||||
// then leave itself in the final state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HideInterval::
|
||||
instant() {
|
||||
_node.hide();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: HideInterval::reverse_instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of reverse_initialize()
|
||||
// .. step() .. reverse_finalize(), when everything is
|
||||
// to happen within one frame. The interval should
|
||||
// initialize itself, then leave itself in the initial
|
||||
// state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void HideInterval::
|
||||
reverse_instant() {
|
||||
_node.show();
|
||||
}
|
||||
61
direct/src/interval/hideInterval.h
Normal file
61
direct/src/interval/hideInterval.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Filename: hideInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef HIDEINTERVAL_H
|
||||
#define HIDEINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cInterval.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : HideInterval
|
||||
// Description : An interval that calls NodePath::hide().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT HideInterval : public CInterval {
|
||||
PUBLISHED:
|
||||
HideInterval(const NodePath &node, const string &name = string());
|
||||
|
||||
virtual void instant();
|
||||
virtual void reverse_instant();
|
||||
|
||||
private:
|
||||
NodePath _node;
|
||||
static int _unique_index;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CInterval::init_type();
|
||||
register_type(_type_handle, "HideInterval",
|
||||
CInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "hideInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
75
direct/src/interval/lerp_helpers.h
Normal file
75
direct/src/interval/lerp_helpers.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// Filename: lerp_helpers.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LERP_HELPERS_H
|
||||
#define LERP_HELPERS_H
|
||||
|
||||
#include "directbase.h"
|
||||
|
||||
//
|
||||
// This header file is only included within .cxx files in this
|
||||
// directory.
|
||||
//
|
||||
|
||||
//
|
||||
// The functions defined here include some trivial template functions
|
||||
// for handling basic lerp computations, common to several .cxx files
|
||||
// here.
|
||||
//
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: lerp_value
|
||||
// Description: Applies the linear lerp computation for a single
|
||||
// parameter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class NumericType>
|
||||
INLINE void
|
||||
lerp_value(NumericType ¤t_value,
|
||||
double d,
|
||||
const NumericType &starting_value,
|
||||
const NumericType &ending_value) {
|
||||
current_value = starting_value + d * (ending_value - starting_value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: lerp_value_from_prev
|
||||
// Description: Applies the linear lerp computation for a single
|
||||
// parameter, when the starting value is implicit.
|
||||
//
|
||||
// This computes the new value based on assuming the
|
||||
// prev_value represents the value computed at delta
|
||||
// prev_d.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class NumericType>
|
||||
INLINE void
|
||||
lerp_value_from_prev(NumericType ¤t_value,
|
||||
double d, double prev_d,
|
||||
const NumericType &prev_value,
|
||||
const NumericType &ending_value) {
|
||||
if (prev_d == 1.0) {
|
||||
current_value = ending_value;
|
||||
} else {
|
||||
NumericType starting_value =
|
||||
(prev_value - prev_d * ending_value) / (1.0 - prev_d);
|
||||
current_value = starting_value + d * (ending_value - starting_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
18
direct/src/interval/showInterval.I
Normal file
18
direct/src/interval/showInterval.I
Normal file
@@ -0,0 +1,18 @@
|
||||
// Filename: showInterval.I
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
68
direct/src/interval/showInterval.cxx
Normal file
68
direct/src/interval/showInterval.cxx
Normal file
@@ -0,0 +1,68 @@
|
||||
// Filename: showInterval.cxx
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "showInterval.h"
|
||||
|
||||
int ShowInterval::_unique_index;
|
||||
TypeHandle ShowInterval::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShowInterval::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
ShowInterval::
|
||||
ShowInterval(const NodePath &node, const string &name) :
|
||||
CInterval(name, 0.0, true),
|
||||
_node(node)
|
||||
{
|
||||
nassertv(!node.is_empty());
|
||||
if (_name.empty()) {
|
||||
ostringstream name_strm;
|
||||
name_strm
|
||||
<< "ShowInterval-" << node.node()->get_name() << "-" << ++_unique_index;
|
||||
_name = name_strm.str();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShowInterval::instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of initialize() .. step()
|
||||
// .. finalize(), when everything is to happen within
|
||||
// one frame. The interval should initialize itself,
|
||||
// then leave itself in the final state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ShowInterval::
|
||||
instant() {
|
||||
_node.show();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ShowInterval::reverse_instant
|
||||
// Access: Published, Virtual
|
||||
// Description: This is called in lieu of reverse_initialize()
|
||||
// .. step() .. reverse_finalize(), when everything is
|
||||
// to happen within one frame. The interval should
|
||||
// initialize itself, then leave itself in the initial
|
||||
// state.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ShowInterval::
|
||||
reverse_instant() {
|
||||
_node.hide();
|
||||
}
|
||||
61
direct/src/interval/showInterval.h
Normal file
61
direct/src/interval/showInterval.h
Normal file
@@ -0,0 +1,61 @@
|
||||
// Filename: showInterval.h
|
||||
// Created by: drose (27Aug02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SHOWINTERVAL_H
|
||||
#define SHOWINTERVAL_H
|
||||
|
||||
#include "directbase.h"
|
||||
#include "cInterval.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ShowInterval
|
||||
// Description : An interval that calls NodePath::show().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_DIRECT ShowInterval : public CInterval {
|
||||
PUBLISHED:
|
||||
ShowInterval(const NodePath &node, const string &name = string());
|
||||
|
||||
virtual void instant();
|
||||
virtual void reverse_instant();
|
||||
|
||||
private:
|
||||
NodePath _node;
|
||||
static int _unique_index;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
CInterval::init_type();
|
||||
register_type(_type_handle, "ShowInterval",
|
||||
CInterval::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "showInterval.I"
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user