mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
define ivalMgr
This commit is contained in:
parent
707fd440c9
commit
24f194bd45
@ -5,59 +5,17 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def setT(self, t):
|
def setT(self, t):
|
||||||
t = min(max(t, 0.0), self.getDuration())
|
# Overridden from the C++ function to call privPostEvent
|
||||||
state = self.getState()
|
# afterward. We do this by renaming the C++ function in
|
||||||
if state == CInterval.SInitial:
|
# FFIRename.
|
||||||
self.privInitialize(t)
|
self.__cSetT(t)
|
||||||
elif state == CInterval.SFinal:
|
|
||||||
self.privReverseInitialize(t)
|
|
||||||
else:
|
|
||||||
self.privStep(t)
|
|
||||||
self.privPostEvent()
|
self.privPostEvent()
|
||||||
|
|
||||||
def start(self, t0 = 0.0, duration = None, scale = 1.0):
|
def play(self, t0 = 0.0, duration = None, scale = 1.0):
|
||||||
if self.isPlaying():
|
|
||||||
self.finish()
|
|
||||||
if duration: # None or 0 implies full length
|
if duration: # None or 0 implies full length
|
||||||
self.setupPlay(t0, t0 + duration, scale)
|
self.start(t0, t0 + duration, scale)
|
||||||
else:
|
else:
|
||||||
self.setupPlay(t0, -1, scale)
|
self.start(t0, -1, scale)
|
||||||
self.privPostEvent()
|
|
||||||
self.__loop = 0
|
|
||||||
self.__spawnTask()
|
|
||||||
|
|
||||||
def loop(self, t0 = 0.0, duration = None, scale = 1.0):
|
|
||||||
self.start(t0, duration, scale)
|
|
||||||
self.__loop = 1
|
|
||||||
return
|
|
||||||
|
|
||||||
def pause(self):
|
|
||||||
if self.getState() == CInterval.SStarted:
|
|
||||||
self.privInterrupt()
|
|
||||||
self.privPostEvent()
|
|
||||||
self.__removeTask()
|
|
||||||
return self.getT()
|
|
||||||
|
|
||||||
def resume(self, t0 = None):
|
|
||||||
if not hasattr(self, "_CInterval__loop"):
|
|
||||||
self.__loop = 0
|
|
||||||
if t0 != None:
|
|
||||||
self.setT(t0)
|
|
||||||
self.setupResume()
|
|
||||||
if not self.isPlaying():
|
|
||||||
self.__spawnTask()
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
state = self.getState()
|
|
||||||
if state == CInterval.SInitial:
|
|
||||||
self.privInstant()
|
|
||||||
elif state != CInterval.SFinal:
|
|
||||||
self.privFinalize()
|
|
||||||
self.privPostEvent()
|
|
||||||
self.__removeTask()
|
|
||||||
|
|
||||||
def play(self, *args, **kw):
|
|
||||||
self.start(*args, **kw)
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.finish()
|
self.finish()
|
||||||
@ -65,9 +23,6 @@
|
|||||||
def setFinalT(self):
|
def setFinalT(self):
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
def isPlaying(self):
|
|
||||||
return taskMgr.hasTaskNamed(self.getName() + '-play')
|
|
||||||
|
|
||||||
def privPostEvent(self):
|
def privPostEvent(self):
|
||||||
# Call after calling any of the priv* methods to do any required
|
# Call after calling any of the priv* methods to do any required
|
||||||
# Python finishing steps.
|
# Python finishing steps.
|
||||||
@ -76,32 +31,6 @@
|
|||||||
for func in self.setTHooks:
|
for func in self.setTHooks:
|
||||||
func(t)
|
func(t)
|
||||||
|
|
||||||
def __spawnTask(self):
|
|
||||||
# Spawn task
|
|
||||||
import Task
|
|
||||||
taskName = self.getName() + '-play'
|
|
||||||
task = Task.Task(self.__playTask)
|
|
||||||
task.interval = self
|
|
||||||
taskMgr.add(task, taskName)
|
|
||||||
|
|
||||||
def __removeTask(self):
|
|
||||||
# Kill old task(s), including those from a similarly-named but
|
|
||||||
# different interval.
|
|
||||||
taskName = self.getName() + '-play'
|
|
||||||
oldTasks = taskMgr.getTasksNamed(taskName)
|
|
||||||
for task in oldTasks:
|
|
||||||
if hasattr(task, "interval"):
|
|
||||||
taskMgr.remove(task)
|
|
||||||
|
|
||||||
def __playTask(self, task):
|
|
||||||
import Task
|
|
||||||
loopCount = self.stepPlay()
|
|
||||||
self.privPostEvent()
|
|
||||||
if loopCount == 0 or self.__loop:
|
|
||||||
return Task.cont
|
|
||||||
else:
|
|
||||||
return Task.done
|
|
||||||
|
|
||||||
def popupControls(self, tl = None):
|
def popupControls(self, tl = None):
|
||||||
""" popupControls()
|
""" popupControls()
|
||||||
Popup control panel for interval.
|
Popup control panel for interval.
|
||||||
|
@ -44,6 +44,7 @@ methodRenameDictionary = {
|
|||||||
'operator<<=' : '__ilshift__',
|
'operator<<=' : '__ilshift__',
|
||||||
'operator>>=' : '__irshift__',
|
'operator>>=' : '__irshift__',
|
||||||
'print' : 'Cprint',
|
'print' : 'Cprint',
|
||||||
|
'CInterval.setT' : '__cSetT',
|
||||||
}
|
}
|
||||||
|
|
||||||
classRenameDictionary = {
|
classRenameDictionary = {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""ActorInterval module: contains the ActorInterval class"""
|
"""ActorInterval module: contains the ActorInterval class"""
|
||||||
|
|
||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
|
from DirectNotifyGlobal import *
|
||||||
import Interval
|
import Interval
|
||||||
import math
|
import math
|
||||||
import LerpBlendHelpers
|
import LerpBlendHelpers
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
from MessengerGlobal import *
|
from MessengerGlobal import *
|
||||||
|
from DirectNotifyGlobal import *
|
||||||
import Interval
|
import Interval
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
@ -27,14 +27,15 @@ class Interval(DirectObject):
|
|||||||
self.__startTAtStart = 1
|
self.__startTAtStart = 1
|
||||||
self.__endT = duration
|
self.__endT = duration
|
||||||
self.__endTAtEnd = 1
|
self.__endTAtEnd = 1
|
||||||
|
self.__playRate = 1.0
|
||||||
|
self.__doLoop = 0
|
||||||
|
self.__loopCount = 0
|
||||||
|
|
||||||
# Set true if the interval should be invoked if it was
|
# Set true if the interval should be invoked if it was
|
||||||
# completely skipped over during initialize or finalize, false
|
# completely skipped over during initialize or finalize, false
|
||||||
# if it should be ignored in this case.
|
# if it should be ignored in this case.
|
||||||
self.openEnded = openEnded
|
self.openEnded = openEnded
|
||||||
|
|
||||||
self.__loop = 0
|
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
@ -54,9 +55,54 @@ class Interval(DirectObject):
|
|||||||
return (self.getState() == CInterval.SInitial or \
|
return (self.getState() == CInterval.SInitial or \
|
||||||
self.getState() == CInterval.SFinal)
|
self.getState() == CInterval.SFinal)
|
||||||
|
|
||||||
|
def setT(self, t):
|
||||||
|
t = min(max(t, 0.0), self.getDuration())
|
||||||
|
state = self.getState()
|
||||||
|
if state == CInterval.SInitial:
|
||||||
|
self.privInitialize(t)
|
||||||
|
elif state == CInterval.SFinal:
|
||||||
|
self.privReverseInitialize(t)
|
||||||
|
else:
|
||||||
|
self.privStep(t)
|
||||||
|
self.privPostEvent()
|
||||||
|
|
||||||
def getT(self):
|
def getT(self):
|
||||||
return self.currT
|
return self.currT
|
||||||
|
|
||||||
|
def start(self, startT = 0.0, endT = -1.0, playRate = 1.0):
|
||||||
|
self.setupPlay(startT, endT, playRate, 0)
|
||||||
|
self.__spawnTask()
|
||||||
|
|
||||||
|
def loop(self, startT = 0.0, endT = -1.0, playRate = 1.0):
|
||||||
|
self.setupPlay(startT, endT, playRate, 1)
|
||||||
|
self.__spawnTask()
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
if self.getState() == CInterval.SStarted:
|
||||||
|
self.privInterrupt()
|
||||||
|
self.privPostEvent()
|
||||||
|
self.__removeTask()
|
||||||
|
return self.getT()
|
||||||
|
|
||||||
|
def resume(self, t0 = None):
|
||||||
|
if t0 != None:
|
||||||
|
self.setT(t0)
|
||||||
|
self.setupResume()
|
||||||
|
if not self.isPlaying():
|
||||||
|
self.__spawnTask()
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
state = self.getState()
|
||||||
|
if state == CInterval.SInitial:
|
||||||
|
self.privInstant()
|
||||||
|
elif state != CInterval.SFinal:
|
||||||
|
self.privFinalize()
|
||||||
|
self.privPostEvent()
|
||||||
|
self.__removeTask()
|
||||||
|
|
||||||
|
def isPlaying(self):
|
||||||
|
return taskMgr.hasTaskNamed(self.getName() + '-play')
|
||||||
|
|
||||||
def setDoneEvent(self, event):
|
def setDoneEvent(self, event):
|
||||||
self.doneEvent = event
|
self.doneEvent = event
|
||||||
|
|
||||||
@ -133,7 +179,7 @@ class Interval(DirectObject):
|
|||||||
if self.doneEvent:
|
if self.doneEvent:
|
||||||
messenger.throw(self.doneEvent)
|
messenger.throw(self.doneEvent)
|
||||||
|
|
||||||
def setupPlay(self, startT, endT, playRate):
|
def setupPlay(self, startT, endT, playRate, doLoop):
|
||||||
duration = self.getDuration()
|
duration = self.getDuration()
|
||||||
|
|
||||||
if startT <= 0:
|
if startT <= 0:
|
||||||
@ -155,6 +201,7 @@ class Interval(DirectObject):
|
|||||||
|
|
||||||
self.__clockStart = globalClock.getFrameTime()
|
self.__clockStart = globalClock.getFrameTime()
|
||||||
self.__playRate = playRate
|
self.__playRate = playRate
|
||||||
|
self.__doLoop = doLoop
|
||||||
self.__loopCount = 0
|
self.__loopCount = 0
|
||||||
|
|
||||||
def setupResume(self):
|
def setupResume(self):
|
||||||
@ -178,7 +225,7 @@ class Interval(DirectObject):
|
|||||||
if self.isStopped():
|
if self.isStopped():
|
||||||
self.privInitialize(t)
|
self.privInitialize(t)
|
||||||
else:
|
else:
|
||||||
self.prevStep(t)
|
self.privStep(t)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Past the ending point; time to finalize.
|
# Past the ending point; time to finalize.
|
||||||
@ -214,6 +261,8 @@ class Interval(DirectObject):
|
|||||||
# Not supported at the moment.
|
# Not supported at the moment.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
return (self.__loopCount == 0 or self.__doLoop)
|
||||||
|
|
||||||
def __repr__(self, indent=0):
|
def __repr__(self, indent=0):
|
||||||
""" __repr__(indent)
|
""" __repr__(indent)
|
||||||
"""
|
"""
|
||||||
@ -226,58 +275,6 @@ class Interval(DirectObject):
|
|||||||
# The rest of these methods are duplicates of functions defined
|
# The rest of these methods are duplicates of functions defined
|
||||||
# for the CInterval class via the file CInterval-extensions.py.
|
# for the CInterval class via the file CInterval-extensions.py.
|
||||||
|
|
||||||
def setT(self, t):
|
|
||||||
t = min(max(t, 0.0), self.getDuration())
|
|
||||||
state = self.getState()
|
|
||||||
if state == CInterval.SInitial:
|
|
||||||
self.privInitialize(t)
|
|
||||||
elif state == CInterval.SFinal:
|
|
||||||
self.privReverseInitialize(t)
|
|
||||||
else:
|
|
||||||
self.privStep(t)
|
|
||||||
self.privPostEvent()
|
|
||||||
|
|
||||||
def start(self, t0 = 0.0, duration = None, scale = 1.0):
|
|
||||||
if self.isPlaying():
|
|
||||||
self.finish()
|
|
||||||
if duration: # None or 0 implies full length
|
|
||||||
self.setupPlay(t0, t0 + duration, scale)
|
|
||||||
else:
|
|
||||||
self.setupPlay(t0, -1, scale)
|
|
||||||
self.privPostEvent()
|
|
||||||
self.__loop = 0
|
|
||||||
self.__spawnTask()
|
|
||||||
|
|
||||||
def loop(self, t0 = 0.0, duration = None, scale = 1.0):
|
|
||||||
self.start(t0, duration, scale)
|
|
||||||
self.__loop = 1
|
|
||||||
return
|
|
||||||
|
|
||||||
def pause(self):
|
|
||||||
if self.getState() == CInterval.SStarted:
|
|
||||||
self.privInterrupt()
|
|
||||||
self.privPostEvent()
|
|
||||||
self.__removeTask()
|
|
||||||
return self.getT()
|
|
||||||
|
|
||||||
def resume(self, t0 = None):
|
|
||||||
if not hasattr(self, "_CInterval__loop"):
|
|
||||||
self.__loop = 0
|
|
||||||
if t0 != None:
|
|
||||||
self.setT(t0)
|
|
||||||
self.setupResume()
|
|
||||||
if not self.isPlaying():
|
|
||||||
self.__spawnTask()
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
state = self.getState()
|
|
||||||
if state == CInterval.SInitial:
|
|
||||||
self.privInstant()
|
|
||||||
elif state != CInterval.SFinal:
|
|
||||||
self.privFinalize()
|
|
||||||
self.privPostEvent()
|
|
||||||
self.__removeTask()
|
|
||||||
|
|
||||||
def play(self, *args, **kw):
|
def play(self, *args, **kw):
|
||||||
self.start(*args, **kw)
|
self.start(*args, **kw)
|
||||||
|
|
||||||
@ -287,9 +284,6 @@ class Interval(DirectObject):
|
|||||||
def setFinalT(self):
|
def setFinalT(self):
|
||||||
self.finish()
|
self.finish()
|
||||||
|
|
||||||
def isPlaying(self):
|
|
||||||
return taskMgr.hasTaskNamed(self.getName() + '-play')
|
|
||||||
|
|
||||||
def privPostEvent(self):
|
def privPostEvent(self):
|
||||||
# Call after calling any of the priv* methods to do any required
|
# Call after calling any of the priv* methods to do any required
|
||||||
# Python finishing steps.
|
# Python finishing steps.
|
||||||
@ -301,6 +295,7 @@ class Interval(DirectObject):
|
|||||||
def __spawnTask(self):
|
def __spawnTask(self):
|
||||||
# Spawn task
|
# Spawn task
|
||||||
import Task
|
import Task
|
||||||
|
self.__removeTask()
|
||||||
taskName = self.getName() + '-play'
|
taskName = self.getName() + '-play'
|
||||||
task = Task.Task(self.__playTask)
|
task = Task.Task(self.__playTask)
|
||||||
task.interval = self
|
task.interval = self
|
||||||
@ -318,9 +313,9 @@ class Interval(DirectObject):
|
|||||||
|
|
||||||
def __playTask(self, task):
|
def __playTask(self, task):
|
||||||
import Task
|
import Task
|
||||||
loopCount = self.stepPlay()
|
again = self.stepPlay()
|
||||||
self.privPostEvent()
|
self.privPostEvent()
|
||||||
if loopCount == 0 or self.__loop:
|
if again:
|
||||||
return Task.cont
|
return Task.cont
|
||||||
else:
|
else:
|
||||||
return Task.done
|
return Task.done
|
||||||
|
@ -10,3 +10,4 @@ from ParticleInterval import *
|
|||||||
from SoundInterval import *
|
from SoundInterval import *
|
||||||
from WaitInterval import *
|
from WaitInterval import *
|
||||||
from MetaInterval import *
|
from MetaInterval import *
|
||||||
|
from IntervalManager import *
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
from DirectNotifyGlobal import *
|
from DirectNotifyGlobal import *
|
||||||
|
from IntervalManager import ivalMgr
|
||||||
import Interval
|
import Interval
|
||||||
import Task
|
import Task
|
||||||
import types
|
import types
|
||||||
@ -31,6 +32,11 @@ class MetaInterval(CMetaInterval):
|
|||||||
name = kw['name']
|
name = kw['name']
|
||||||
del kw['name']
|
del kw['name']
|
||||||
|
|
||||||
|
interruptible = 0
|
||||||
|
if kw.has_key('interruptible'):
|
||||||
|
interruptible = kw['interruptible']
|
||||||
|
del kw['interruptible']
|
||||||
|
|
||||||
if kw:
|
if kw:
|
||||||
self.notify.error("Unexpected keyword parameters: %s" % (kw.keys()))
|
self.notify.error("Unexpected keyword parameters: %s" % (kw.keys()))
|
||||||
|
|
||||||
@ -50,6 +56,8 @@ class MetaInterval(CMetaInterval):
|
|||||||
MetaInterval.SequenceNum += 1
|
MetaInterval.SequenceNum += 1
|
||||||
|
|
||||||
CMetaInterval.__init__(self, name)
|
CMetaInterval.__init__(self, name)
|
||||||
|
self.__manager = ivalMgr
|
||||||
|
self.setInterruptible(interruptible)
|
||||||
|
|
||||||
self.pythonIvals = []
|
self.pythonIvals = []
|
||||||
|
|
||||||
@ -113,6 +121,7 @@ class MetaInterval(CMetaInterval):
|
|||||||
self.__ivalsDirty = 1
|
self.__ivalsDirty = 1
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
# Functions to define sequence, parallel, and track behaviors:
|
||||||
|
|
||||||
def addSequence(self, list, relTime, relTo):
|
def addSequence(self, list, relTime, relTo):
|
||||||
# Adds the given list of intervals to the MetaInterval to be
|
# Adds the given list of intervals to the MetaInterval to be
|
||||||
@ -209,6 +218,52 @@ class MetaInterval(CMetaInterval):
|
|||||||
else:
|
else:
|
||||||
self.notify.error("Not an Interval: %s" % (ival,))
|
self.notify.error("Not an Interval: %s" % (ival,))
|
||||||
|
|
||||||
|
# Functions to support automatic playback of MetaIntervals along
|
||||||
|
# with all of their associated Python callbacks:
|
||||||
|
|
||||||
|
def setManager(self, manager):
|
||||||
|
self.__manager = manager
|
||||||
|
CMetaInterval.setManager(self, manager)
|
||||||
|
|
||||||
|
def getManager(self):
|
||||||
|
return self.__manager
|
||||||
|
|
||||||
|
def start(self, startT = 0.0, endT = -1.0, playRate = 1.0):
|
||||||
|
self.__updateIvals()
|
||||||
|
self.setupPlay(startT, endT, playRate, 0)
|
||||||
|
self.__manager.addInterval(self)
|
||||||
|
|
||||||
|
def loop(self, startT = 0.0, endT = -1.0, playRate = 1.0):
|
||||||
|
self.__updateIvals()
|
||||||
|
self.setupPlay(startT, endT, playRate, 1)
|
||||||
|
self.__manager.addInterval(self)
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
if self.getState() == CInterval.SStarted:
|
||||||
|
self.privInterrupt()
|
||||||
|
self.__manager.removeInterval(self)
|
||||||
|
self.privPostEvent()
|
||||||
|
return self.getT()
|
||||||
|
|
||||||
|
def resume(self, t0 = None):
|
||||||
|
self.__updateIvals()
|
||||||
|
if t0 != None:
|
||||||
|
self.setT(t0)
|
||||||
|
self.setupResume()
|
||||||
|
self.__manager.addInterval(self)
|
||||||
|
|
||||||
|
def finish(self):
|
||||||
|
state = self.getState()
|
||||||
|
if state == CInterval.SInitial:
|
||||||
|
self.privInstant()
|
||||||
|
elif state != CInterval.SFinal:
|
||||||
|
self.privFinalize()
|
||||||
|
self.__manager.removeInterval(self)
|
||||||
|
self.privPostEvent()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Internal functions:
|
||||||
|
|
||||||
def __updateIvals(self):
|
def __updateIvals(self):
|
||||||
# The MetaInterval object does not create the C++ list of
|
# The MetaInterval object does not create the C++ list of
|
||||||
@ -312,20 +367,6 @@ class MetaInterval(CMetaInterval):
|
|||||||
self.__updateIvals()
|
self.__updateIvals()
|
||||||
return CMetaInterval.getDuration(self)
|
return CMetaInterval.getDuration(self)
|
||||||
|
|
||||||
def start(self, *args, **kw):
|
|
||||||
# This function overrides from the parent level to force it to
|
|
||||||
# update the interval list first, if necessary.
|
|
||||||
|
|
||||||
self.__updateIvals()
|
|
||||||
return CMetaInterval.start(self, *args, **kw)
|
|
||||||
|
|
||||||
def loop(self, *args, **kw):
|
|
||||||
# This function overrides from the parent level to force it to
|
|
||||||
# update the interval list first, if necessary.
|
|
||||||
|
|
||||||
self.__updateIvals()
|
|
||||||
return CMetaInterval.loop(self, *args, **kw)
|
|
||||||
|
|
||||||
def __repr__(self, *args, **kw):
|
def __repr__(self, *args, **kw):
|
||||||
# This function overrides from the parent level to force it to
|
# This function overrides from the parent level to force it to
|
||||||
# update the interval list first, if necessary.
|
# update the interval list first, if necessary.
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
import Interval
|
import Interval
|
||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
|
from DirectNotifyGlobal import *
|
||||||
|
|
||||||
# import Mopath
|
# import Mopath
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""ParticleInterval module: contains the ParticleInterval class"""
|
"""ParticleInterval module: contains the ParticleInterval class"""
|
||||||
|
|
||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
|
from DirectNotifyGlobal import *
|
||||||
import Interval
|
import Interval
|
||||||
|
|
||||||
import ParticleEffect
|
import ParticleEffect
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""SoundInterval module: contains the SoundInterval class"""
|
"""SoundInterval module: contains the SoundInterval class"""
|
||||||
|
|
||||||
from PandaModules import *
|
from PandaModules import *
|
||||||
|
from DirectNotifyGlobal import *
|
||||||
import Interval
|
import Interval
|
||||||
|
|
||||||
class SoundInterval(Interval.Interval):
|
class SoundInterval(Interval.Interval):
|
||||||
@ -61,6 +62,9 @@ class SoundInterval(Interval.Interval):
|
|||||||
def privStep(self, t):
|
def privStep(self, t):
|
||||||
if self.state == CInterval.SPaused:
|
if self.state == CInterval.SPaused:
|
||||||
# Restarting from a pause.
|
# Restarting from a pause.
|
||||||
|
self.sound.setVolume(self.volume)
|
||||||
|
self.sound.setTime(t)
|
||||||
|
self.sound.setLoop(self.loop)
|
||||||
self.sound.play()
|
self.sound.play()
|
||||||
self.state = CInterval.SStarted
|
self.state = CInterval.SStarted
|
||||||
self.currT = t
|
self.currT = t
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#define SOURCES \
|
#define SOURCES \
|
||||||
config_interval.cxx config_interval.h \
|
config_interval.cxx config_interval.h \
|
||||||
cInterval.cxx cInterval.I cInterval.h \
|
cInterval.cxx cInterval.I cInterval.h \
|
||||||
|
cIntervalManager.cxx cIntervalManager.I cIntervalManager.h \
|
||||||
cLerpInterval.cxx cLerpInterval.I cLerpInterval.h \
|
cLerpInterval.cxx cLerpInterval.I cLerpInterval.h \
|
||||||
cLerpNodePathInterval.cxx cLerpNodePathInterval.I cLerpNodePathInterval.h \
|
cLerpNodePathInterval.cxx cLerpNodePathInterval.I cLerpNodePathInterval.h \
|
||||||
cLerpAnimEffectInterval.cxx cLerpAnimEffectInterval.I cLerpAnimEffectInterval.h \
|
cLerpAnimEffectInterval.cxx cLerpAnimEffectInterval.I cLerpAnimEffectInterval.h \
|
||||||
|
@ -78,18 +78,6 @@ is_stopped() const {
|
|||||||
return (_state == S_initial || _state == S_final);
|
return (_state == S_initial || _state == S_final);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: CInterval::get_t
|
|
||||||
// Access: Published
|
|
||||||
// Description: Returns the current time of the interval: the last
|
|
||||||
// value of t passed to priv_initialize(), priv_step(), or
|
|
||||||
// priv_finalize().
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
INLINE double CInterval::
|
|
||||||
get_t() const {
|
|
||||||
return _curr_t;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CInterval::set_done_event
|
// Function: CInterval::set_done_event
|
||||||
// Access: Published
|
// Access: Published
|
||||||
@ -116,6 +104,74 @@ get_done_event() const {
|
|||||||
return _done_event;
|
return _done_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::get_t
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the current time of the interval: the last
|
||||||
|
// value of t passed to priv_initialize(), priv_step(), or
|
||||||
|
// priv_finalize().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE double CInterval::
|
||||||
|
get_t() const {
|
||||||
|
return _curr_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::set_interruptible
|
||||||
|
// Access: Published
|
||||||
|
// Description: Changes the state of the 'interruptible' flag. If
|
||||||
|
// this is true, the interval may be arbitrarily
|
||||||
|
// interrupted when the system needs to reset due to
|
||||||
|
// some external event by calling
|
||||||
|
// CIntervalManager::pause_all_interruptible(). If this
|
||||||
|
// is false (the default), the interval must always be
|
||||||
|
// explicitly finished or paused.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void CInterval::
|
||||||
|
set_interruptible(bool interruptible) {
|
||||||
|
_interruptible = interruptible;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::get_interruptible
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the state of the 'interruptible' flag. See
|
||||||
|
// set_interruptible().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE bool CInterval::
|
||||||
|
get_interruptible() const {
|
||||||
|
return _interruptible;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::set_manager
|
||||||
|
// Access: Published
|
||||||
|
// Description: Indicates the CIntervalManager object which will be
|
||||||
|
// responsible for playing this interval. This defaults
|
||||||
|
// to the global CIntervalManager; you should need to
|
||||||
|
// change this only if you have special requirements for
|
||||||
|
// playing this interval.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE void CInterval::
|
||||||
|
set_manager(CIntervalManager *manager) {
|
||||||
|
_manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::get_manager
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the CIntervalManager object which will be
|
||||||
|
// responsible for playing this interval. Note that
|
||||||
|
// this can only return a C++ object; if the particular
|
||||||
|
// CIntervalManager object has been extended in the
|
||||||
|
// scripting language, this will return the encapsulated
|
||||||
|
// C++ object, not the full extended object.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
INLINE CIntervalManager *CInterval::
|
||||||
|
get_manager() const {
|
||||||
|
return _manager;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CInterval::recompute
|
// Function: CInterval::recompute
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "cInterval.h"
|
#include "cInterval.h"
|
||||||
|
#include "cIntervalManager.h"
|
||||||
#include "indent.h"
|
#include "indent.h"
|
||||||
#include "clockObject.h"
|
#include "clockObject.h"
|
||||||
#include "throw_event.h"
|
#include "throw_event.h"
|
||||||
@ -38,198 +39,157 @@ CInterval(const string &name, double duration, bool open_ended) :
|
|||||||
_open_ended(open_ended),
|
_open_ended(open_ended),
|
||||||
_dirty(false)
|
_dirty(false)
|
||||||
{
|
{
|
||||||
|
_interruptible = false;
|
||||||
|
_manager = CIntervalManager::get_global_ptr();
|
||||||
_clock_start = 0.0;
|
_clock_start = 0.0;
|
||||||
_start_t = 0.0;
|
_start_t = 0.0;
|
||||||
_end_t = _duration;
|
_end_t = _duration;
|
||||||
_start_t_at_start = true;
|
_start_t_at_start = true;
|
||||||
_end_t_at_end = true;
|
_end_t_at_end = true;
|
||||||
_play_rate = 1.0;
|
_play_rate = 1.0;
|
||||||
|
_do_loop = false;
|
||||||
_loop_count = 0;
|
_loop_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CInterval::setup_play
|
// Function: CInterval::set_t
|
||||||
// Access: Published
|
// Access: Published
|
||||||
// Description: Called to prepare the interval for automatic timed
|
// Description: Explicitly sets the time within the interval.
|
||||||
// playback, e.g. via a Python task. The interval will
|
// Normally, you would use start() .. finish() to let
|
||||||
// be played from start_t to end_t, at a time factor
|
// the time play normally, but this may be used to set
|
||||||
// specified by play_rate. start_t must always be less
|
// the time to some particular value.
|
||||||
// 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::
|
void CInterval::
|
||||||
setup_play(double start_t, double end_t, double play_rate) {
|
set_t(double t) {
|
||||||
nassertv(start_t < end_t || end_t < 0.0);
|
t = min(max(t, 0.0), get_duration());
|
||||||
nassertv(play_rate != 0.0);
|
switch (get_state()) {
|
||||||
|
case S_initial:
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: CInterval::setup_resume
|
|
||||||
// Access: Published
|
|
||||||
// Description: Called to prepare the interval for restarting at the
|
|
||||||
// current point within the interval after an
|
|
||||||
// interruption.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
void CInterval::
|
|
||||||
setup_resume() {
|
|
||||||
double now = ClockObject::get_global_clock()->get_frame_time();
|
|
||||||
if (_play_rate > 0.0) {
|
|
||||||
_clock_start = now - ((get_t() - _start_t) / _play_rate);
|
|
||||||
|
|
||||||
} else if (_play_rate < 0.0) {
|
|
||||||
_clock_start = now - ((get_t() - _end_t) / _play_rate);
|
|
||||||
}
|
|
||||||
_loop_count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// 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 (_end_t_at_end) {
|
|
||||||
_end_t = get_duration();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t < _end_t) {
|
|
||||||
// In the middle of the interval, not a problem.
|
|
||||||
if (is_stopped()) {
|
|
||||||
priv_initialize(t);
|
priv_initialize(t);
|
||||||
} else {
|
break;
|
||||||
|
|
||||||
|
case S_final:
|
||||||
|
priv_reverse_initialize(t);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
priv_step(t);
|
priv_step(t);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
////////////////////////////////////////////////////////////////////
|
||||||
// Past the ending point; time to finalize.
|
// Function: CInterval::start
|
||||||
if (_end_t_at_end) {
|
// Access: Published
|
||||||
// Only finalize if the playback cycle includes the whole
|
// Description: Starts the interval playing by registering it with
|
||||||
// interval.
|
// the current CIntervalManager. The interval will
|
||||||
if (is_stopped()) {
|
// play to the end and stop.
|
||||||
if (get_open_ended() || _loop_count != 0) {
|
//
|
||||||
priv_instant();
|
// If end_t is less than zero, it indicates the end of
|
||||||
|
// the interval.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
start(double start_t, double end_t, double play_rate) {
|
||||||
|
setup_play(start_t, end_t, play_rate, false);
|
||||||
|
_manager->add_c_interval(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::loop
|
||||||
|
// Access: Published
|
||||||
|
// Description: Starts the interval playing by registering it with
|
||||||
|
// the current CIntervalManager. The interval will
|
||||||
|
// play until it is interrupted with finish() or
|
||||||
|
// pause(), looping back to start_t when it reaches
|
||||||
|
// end_t.
|
||||||
|
//
|
||||||
|
// If end_t is less than zero, it indicates the end of
|
||||||
|
// the interval.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
loop(double start_t, double end_t, double play_rate) {
|
||||||
|
setup_play(start_t, end_t, play_rate, true);
|
||||||
|
_manager->add_c_interval(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::pause
|
||||||
|
// Access: Published
|
||||||
|
// Description: Stops the interval from playing but leaves it in its
|
||||||
|
// current state. It may later be resumed from this
|
||||||
|
// point by calling resume().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
double CInterval::
|
||||||
|
pause() {
|
||||||
|
if (get_state() == S_started) {
|
||||||
|
priv_interrupt();
|
||||||
}
|
}
|
||||||
} else {
|
int index = _manager->find_c_interval(this->get_name());
|
||||||
|
if (index >= 0) {
|
||||||
|
_manager->remove_c_interval(index);
|
||||||
|
}
|
||||||
|
return get_t();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::resume
|
||||||
|
// Access: Published
|
||||||
|
// Description: Restarts the interval from its current point after a
|
||||||
|
// previous call to pause().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
resume() {
|
||||||
|
setup_resume();
|
||||||
|
_manager->add_c_interval(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::resume
|
||||||
|
// Access: Published
|
||||||
|
// Description: Restarts the interval from the indicated point after a
|
||||||
|
// previous call to pause().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
resume(double start_t) {
|
||||||
|
set_t(start_t);
|
||||||
|
setup_resume();
|
||||||
|
_manager->add_c_interval(this, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::finish
|
||||||
|
// Access: Published
|
||||||
|
// Description: Stops the interval from playing and sets it to its
|
||||||
|
// final state.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
finish() {
|
||||||
|
switch (get_state()) {
|
||||||
|
case S_initial:
|
||||||
|
priv_instant();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S_final:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
priv_finalize();
|
priv_finalize();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (is_stopped()) {
|
|
||||||
priv_initialize(_end_t);
|
|
||||||
} else {
|
|
||||||
priv_step(_end_t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance the clock for the next loop cycle. We might have to
|
int index = _manager->find_c_interval(this->get_name());
|
||||||
// advance multiple times if we skipped several cycles in the past
|
if (index >= 0) {
|
||||||
// frame.
|
_manager->remove_c_interval(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_end_t == _start_t) {
|
////////////////////////////////////////////////////////////////////
|
||||||
// If the interval has no length, we loop exactly once each
|
// Function: CInterval::is_playing
|
||||||
// time.
|
// Access: Published
|
||||||
_loop_count++;
|
// Description: Returns true if the interval is currently playing,
|
||||||
|
// false otherwise.
|
||||||
} else {
|
////////////////////////////////////////////////////////////////////
|
||||||
// Otherwise, figure out how many loops we need to skip.
|
bool CInterval::
|
||||||
double time_per_loop = (_end_t - _start_t) / _play_rate;
|
is_playing() const {
|
||||||
double num_loops = floor((now - _clock_start) / time_per_loop);
|
int index = _manager->find_c_interval(this->get_name());
|
||||||
_loop_count += (int)num_loops;
|
return (index >= 0);
|
||||||
_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 (is_stopped()) {
|
|
||||||
priv_reverse_initialize(t);
|
|
||||||
} else {
|
|
||||||
priv_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 (is_stopped()) {
|
|
||||||
if (get_open_ended() || _loop_count != 0) {
|
|
||||||
priv_reverse_instant();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
priv_reverse_finalize();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_stopped()) {
|
|
||||||
priv_reverse_initialize(_start_t);
|
|
||||||
} else {
|
|
||||||
priv_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -434,6 +394,192 @@ write(ostream &out, int indent_level) const {
|
|||||||
indent(out, indent_level) << *this << "\n";
|
indent(out, indent_level) << *this << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// 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, bool do_loop) {
|
||||||
|
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;
|
||||||
|
_do_loop = do_loop;
|
||||||
|
_loop_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::setup_resume
|
||||||
|
// Access: Published
|
||||||
|
// Description: Called to prepare the interval for restarting at the
|
||||||
|
// current point within the interval after an
|
||||||
|
// interruption.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CInterval::
|
||||||
|
setup_resume() {
|
||||||
|
double now = ClockObject::get_global_clock()->get_frame_time();
|
||||||
|
if (_play_rate > 0.0) {
|
||||||
|
_clock_start = now - ((get_t() - _start_t) / _play_rate);
|
||||||
|
|
||||||
|
} else if (_play_rate < 0.0) {
|
||||||
|
_clock_start = now - ((get_t() - _end_t) / _play_rate);
|
||||||
|
}
|
||||||
|
_loop_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CInterval::step_play
|
||||||
|
// Access: Published
|
||||||
|
// Description: Should be called once per frame to execute the
|
||||||
|
// automatic timed playback begun with setup_play().
|
||||||
|
//
|
||||||
|
// Returns true if the interval should continue, false
|
||||||
|
// if it is done and should stop.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool 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 (_end_t_at_end) {
|
||||||
|
_end_t = get_duration();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (t < _end_t) {
|
||||||
|
// In the middle of the interval, not a problem.
|
||||||
|
if (is_stopped()) {
|
||||||
|
priv_initialize(t);
|
||||||
|
} else {
|
||||||
|
priv_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 (is_stopped()) {
|
||||||
|
if (get_open_ended() || _loop_count != 0) {
|
||||||
|
priv_instant();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
priv_finalize();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_stopped()) {
|
||||||
|
priv_initialize(_end_t);
|
||||||
|
} else {
|
||||||
|
priv_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 (is_stopped()) {
|
||||||
|
priv_reverse_initialize(t);
|
||||||
|
} else {
|
||||||
|
priv_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 (is_stopped()) {
|
||||||
|
if (get_open_ended() || _loop_count != 0) {
|
||||||
|
priv_reverse_instant();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
priv_reverse_finalize();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (is_stopped()) {
|
||||||
|
priv_reverse_initialize(_start_t);
|
||||||
|
} else {
|
||||||
|
priv_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 == 0 || _do_loop);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: CInterval::mark_dirty
|
// Function: CInterval::mark_dirty
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
#include "config_interval.h"
|
#include "config_interval.h"
|
||||||
|
|
||||||
|
class CIntervalManager;
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Class : CInterval
|
// Class : CInterval
|
||||||
// Description : The base class for timeline components. A CInterval
|
// Description : The base class for timeline components. A CInterval
|
||||||
@ -66,14 +68,26 @@ PUBLISHED:
|
|||||||
|
|
||||||
INLINE State get_state() const;
|
INLINE State get_state() const;
|
||||||
INLINE bool is_stopped() const;
|
INLINE bool is_stopped() const;
|
||||||
INLINE double get_t() const;
|
|
||||||
|
|
||||||
INLINE void set_done_event(const string &event);
|
INLINE void set_done_event(const string &event);
|
||||||
INLINE const string &get_done_event() const;
|
INLINE const string &get_done_event() const;
|
||||||
|
|
||||||
void setup_play(double start_time, double end_time, double play_rate);
|
void set_t(double t);
|
||||||
void setup_resume();
|
INLINE double get_t() const;
|
||||||
int step_play();
|
|
||||||
|
INLINE void set_interruptible(bool interruptible);
|
||||||
|
INLINE bool get_interruptible() const;
|
||||||
|
|
||||||
|
INLINE void set_manager(CIntervalManager *manager);
|
||||||
|
INLINE CIntervalManager *get_manager() const;
|
||||||
|
|
||||||
|
void start(double start_t = 0.0, double end_t = -1.0, double play_rate = 1.0);
|
||||||
|
void loop(double start_t = 0.0, double end_t = -1.0, double play_rate = 1.0);
|
||||||
|
double pause();
|
||||||
|
void resume();
|
||||||
|
void resume(double start_t);
|
||||||
|
void finish();
|
||||||
|
bool is_playing() const;
|
||||||
|
|
||||||
// These functions control the actual playback of the interval.
|
// These functions control the actual playback of the interval.
|
||||||
// Don't call them directly; they're intended to be called from a
|
// Don't call them directly; they're intended to be called from a
|
||||||
@ -96,6 +110,11 @@ PUBLISHED:
|
|||||||
virtual void output(ostream &out) const;
|
virtual void output(ostream &out) const;
|
||||||
virtual void write(ostream &out, int indent_level) const;
|
virtual void write(ostream &out, int indent_level) const;
|
||||||
|
|
||||||
|
void setup_play(double start_time, double end_time, double play_rate,
|
||||||
|
bool do_loop);
|
||||||
|
void setup_resume();
|
||||||
|
bool step_play();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void mark_dirty();
|
void mark_dirty();
|
||||||
|
|
||||||
@ -113,6 +132,9 @@ protected:
|
|||||||
string _done_event;
|
string _done_event;
|
||||||
double _duration;
|
double _duration;
|
||||||
|
|
||||||
|
bool _interruptible;
|
||||||
|
CIntervalManager *_manager;
|
||||||
|
|
||||||
// For setup_play() and step_play().
|
// For setup_play() and step_play().
|
||||||
double _clock_start;
|
double _clock_start;
|
||||||
double _start_t;
|
double _start_t;
|
||||||
@ -120,6 +142,7 @@ protected:
|
|||||||
bool _end_t_at_end;
|
bool _end_t_at_end;
|
||||||
bool _start_t_at_start;
|
bool _start_t_at_start;
|
||||||
double _play_rate;
|
double _play_rate;
|
||||||
|
bool _do_loop;
|
||||||
int _loop_count;
|
int _loop_count;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
25
direct/src/interval/cIntervalManager.I
Normal file
25
direct/src/interval/cIntervalManager.I
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Filename: cIntervalManager.I
|
||||||
|
// Created by: drose (10Sep02)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 .
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
INLINE ostream &
|
||||||
|
operator << (ostream &out, const CIntervalManager &ival_mgr) {
|
||||||
|
ival_mgr.output(out);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
417
direct/src/interval/cIntervalManager.cxx
Normal file
417
direct/src/interval/cIntervalManager.cxx
Normal file
@ -0,0 +1,417 @@
|
|||||||
|
// Filename: cIntervalManager.cxx
|
||||||
|
// Created by: drose (10Sep02)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 "cIntervalManager.h"
|
||||||
|
#include "cMetaInterval.h"
|
||||||
|
#include "dcast.h"
|
||||||
|
|
||||||
|
CIntervalManager *CIntervalManager::_global_ptr;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::Constructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CIntervalManager::
|
||||||
|
CIntervalManager() {
|
||||||
|
_first_slot = 0;
|
||||||
|
_next_event_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::Destructor
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CIntervalManager::
|
||||||
|
~CIntervalManager() {
|
||||||
|
nassertv(_name_index.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::add_c_interval
|
||||||
|
// Access: Published
|
||||||
|
// Description: Adds the interval to the manager, and returns a
|
||||||
|
// unique index for the interval. This index will be
|
||||||
|
// unique among all the currently added intervals, but
|
||||||
|
// not unique across all intervals ever added to the
|
||||||
|
// manager. The maximum index value will never exceed
|
||||||
|
// the maximum number of intervals added at any given
|
||||||
|
// time.
|
||||||
|
//
|
||||||
|
// If the external flag is true, the interval is
|
||||||
|
// understood to also be stored in the scripting
|
||||||
|
// language data structures. In this case, it will be
|
||||||
|
// available for information returned by
|
||||||
|
// get_next_event() and get_next_removal(). If external
|
||||||
|
// is false, the interval's index will never be returned
|
||||||
|
// by these two functions.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
add_c_interval(CInterval *interval, bool external) {
|
||||||
|
// First, check the name index. If we already have an interval by
|
||||||
|
// this name, it gets finished and removed.
|
||||||
|
NameIndex::iterator ni = _name_index.find(interval->get_name());
|
||||||
|
if (ni != _name_index.end()) {
|
||||||
|
int old_index = (*ni).second;
|
||||||
|
nassertr(old_index >= 0 && old_index < (int)_intervals.size(), -1)
|
||||||
|
CInterval *old_interval = _intervals[old_index]._interval;
|
||||||
|
if (old_interval == interval) {
|
||||||
|
// No, it's the same interval that was already here. In this
|
||||||
|
// case, don't finish the interval; just return it.
|
||||||
|
return old_index;
|
||||||
|
}
|
||||||
|
finish_interval(old_interval);
|
||||||
|
remove_index(old_index);
|
||||||
|
_name_index.erase(ni);
|
||||||
|
}
|
||||||
|
|
||||||
|
int slot;
|
||||||
|
|
||||||
|
if (_first_slot >= (int)_intervals.size()) {
|
||||||
|
// All the slots are filled; make a new slot.
|
||||||
|
nassertr(_first_slot == (int)_intervals.size(), -1);
|
||||||
|
slot = (int)_intervals.size();
|
||||||
|
_intervals.push_back(IntervalDef());
|
||||||
|
_first_slot = (int)_intervals.size();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Some slot is available; use it.
|
||||||
|
slot = _first_slot;
|
||||||
|
nassertr(slot >= 0 && slot < (int)_intervals.size(), -1);
|
||||||
|
_first_slot = _intervals[slot]._next_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
IntervalDef &def = _intervals[slot];
|
||||||
|
def._interval = interval;
|
||||||
|
def._flags = 0;
|
||||||
|
if (external) {
|
||||||
|
def._flags |= F_external;
|
||||||
|
}
|
||||||
|
if (interval->is_of_type(CMetaInterval::get_class_type())) {
|
||||||
|
def._flags |= F_meta_interval;
|
||||||
|
}
|
||||||
|
def._next_slot = -1;
|
||||||
|
|
||||||
|
_name_index[interval->get_name()] = slot;
|
||||||
|
nassertr(_first_slot >= 0, slot);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::find_c_interval
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the index associated with the named interval,
|
||||||
|
// if there is such an interval, or -1 if there is not.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
find_c_interval(const string &name) const {
|
||||||
|
NameIndex::const_iterator ni = _name_index.find(name);
|
||||||
|
if (ni != _name_index.end()) {
|
||||||
|
return (*ni).second;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::get_c_interval
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the interval associated with the given index.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CInterval *CIntervalManager::
|
||||||
|
get_c_interval(int index) const {
|
||||||
|
nassertr(index >= 0 && index < (int)_intervals.size(), NULL);
|
||||||
|
return _intervals[index]._interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::remove_c_interval
|
||||||
|
// Access: Published
|
||||||
|
// Description: Removes the indicated interval from the queue
|
||||||
|
// immediately. It will not be returned from
|
||||||
|
// get_next_removal(), and none of its pending events,
|
||||||
|
// if any, will be returned by get_next_event().
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
remove_c_interval(int index) {
|
||||||
|
nassertv(index >= 0 && index < (int)_intervals.size());
|
||||||
|
IntervalDef &def = _intervals[index];
|
||||||
|
nassertv(def._interval != (CInterval *)NULL);
|
||||||
|
|
||||||
|
NameIndex::iterator ni = _name_index.find(def._interval->get_name());
|
||||||
|
nassertv(ni != _name_index.end());
|
||||||
|
nassertv((*ni).second == index);
|
||||||
|
_name_index.erase(ni);
|
||||||
|
|
||||||
|
def._interval = (CInterval *)NULL;
|
||||||
|
def._next_slot = _first_slot;
|
||||||
|
_first_slot = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::pause_all_interruptible
|
||||||
|
// Access: Published
|
||||||
|
// Description: Pauses (removes from the active queue) all intervals
|
||||||
|
// tagged as "interruptible". These are intervals that
|
||||||
|
// someone fired up but won't necessarily expect to
|
||||||
|
// clean up; they can be interrupted at will when
|
||||||
|
// necessary.
|
||||||
|
//
|
||||||
|
// Returns the number of intervals affected.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
pause_all_interruptible() {
|
||||||
|
int num_paused = 0;
|
||||||
|
|
||||||
|
NameIndex::iterator ni;
|
||||||
|
ni = _name_index.begin();
|
||||||
|
while (ni != _name_index.end()) {
|
||||||
|
int index = (*ni).second;
|
||||||
|
const IntervalDef &def = _intervals[index];
|
||||||
|
nassertr(def._interval != (CInterval *)NULL, num_paused);
|
||||||
|
if (!def._interval->get_interruptible()) {
|
||||||
|
// This interval may be interrupted.
|
||||||
|
if (def._interval->get_state() == CInterval::S_started) {
|
||||||
|
def._interval->priv_interrupt();
|
||||||
|
}
|
||||||
|
NameIndex::iterator prev;
|
||||||
|
prev = ni;
|
||||||
|
++ni;
|
||||||
|
_name_index.erase(prev);
|
||||||
|
remove_index(index);
|
||||||
|
num_paused++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The interval should remain on the active list.
|
||||||
|
++ni;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::get_num_intervals
|
||||||
|
// Access: Published
|
||||||
|
// Description: Returns the number of currently active intervals.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
get_num_intervals() const {
|
||||||
|
return _name_index.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::step
|
||||||
|
// Access: Published
|
||||||
|
// Description: This should be called every frame to do the
|
||||||
|
// processing for all the active intervals. It will
|
||||||
|
// call step_play() for each interval that has been
|
||||||
|
// added and that has not yet been removed.
|
||||||
|
//
|
||||||
|
// After each call to step(), the scripting language
|
||||||
|
// should call get_next_event() and get_next_removal()
|
||||||
|
// repeatedly to process all the high-level
|
||||||
|
// (e.g. Python-interval-based) events and to manage the
|
||||||
|
// high-level list of intervals.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
step() {
|
||||||
|
NameIndex::iterator ni;
|
||||||
|
ni = _name_index.begin();
|
||||||
|
while (ni != _name_index.end()) {
|
||||||
|
int index = (*ni).second;
|
||||||
|
const IntervalDef &def = _intervals[index];
|
||||||
|
nassertv(def._interval != (CInterval *)NULL);
|
||||||
|
if (!def._interval->step_play()) {
|
||||||
|
// This interval is finished and wants to be removed from the
|
||||||
|
// active list.
|
||||||
|
NameIndex::iterator prev;
|
||||||
|
prev = ni;
|
||||||
|
++ni;
|
||||||
|
_name_index.erase(prev);
|
||||||
|
remove_index(index);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// The interval can remain on the active list.
|
||||||
|
++ni;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_next_event_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::get_next_event
|
||||||
|
// Access: Published
|
||||||
|
// Description: This should be called by the scripting language after
|
||||||
|
// each call to step(). It returns the index number of
|
||||||
|
// the next interval that has events requiring servicing
|
||||||
|
// by the scripting language, or -1 if no more intervals
|
||||||
|
// have any events pending.
|
||||||
|
//
|
||||||
|
// If this function returns something other than -1, it
|
||||||
|
// is the scripting language's responsibility to query
|
||||||
|
// the indicated interval for its next event via
|
||||||
|
// get_event_index(), and eventually pop_event().
|
||||||
|
//
|
||||||
|
// Then get_next_event() should be called again until it
|
||||||
|
// returns -1.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
get_next_event() {
|
||||||
|
while (_next_event_index < (int)_intervals.size()) {
|
||||||
|
IntervalDef &def = _intervals[_next_event_index];
|
||||||
|
if (def._interval != (CInterval *)NULL &&
|
||||||
|
(def._flags & F_meta_interval) != 0) {
|
||||||
|
CMetaInterval *meta_interval;
|
||||||
|
DCAST_INTO_R(meta_interval, def._interval, -1);
|
||||||
|
if (meta_interval->is_event_ready()) {
|
||||||
|
nassertr((def._flags & F_external) != 0, -1);
|
||||||
|
return _next_event_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_next_event_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::get_next_removal
|
||||||
|
// Access: Published
|
||||||
|
// Description: This should be called by the scripting language after
|
||||||
|
// each call to step(). It returns the index number of
|
||||||
|
// an interval that was recently removed, or -1 if no
|
||||||
|
// intervals were removed.
|
||||||
|
//
|
||||||
|
// If this returns something other than -1, the
|
||||||
|
// scripting language should clean up its own data
|
||||||
|
// structures accordingly, and then call
|
||||||
|
// get_next_removal() again.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
int CIntervalManager::
|
||||||
|
get_next_removal() {
|
||||||
|
if (!_removed.empty()) {
|
||||||
|
int index = _removed.back();
|
||||||
|
_removed.pop_back();
|
||||||
|
|
||||||
|
nassertr(index >= 0 && index < (int)_intervals.size(), -1);
|
||||||
|
IntervalDef &def = _intervals[index];
|
||||||
|
def._interval = (CInterval *)NULL;
|
||||||
|
def._next_slot = _first_slot;
|
||||||
|
_first_slot = index;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::output
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
output(ostream &out) const {
|
||||||
|
out << "CIntervalManager, " << (int)_name_index.size() << " intervals.";
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::write
|
||||||
|
// Access: Published
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
write(ostream &out) const {
|
||||||
|
NameIndex::const_iterator ni;
|
||||||
|
for (ni = _name_index.begin(); ni != _name_index.end(); ++ni) {
|
||||||
|
int index = (*ni).second;
|
||||||
|
nassertv(index >= 0 && index < (int)_intervals.size());
|
||||||
|
const IntervalDef &def = _intervals[index];
|
||||||
|
nassertv(def._interval != (CInterval *)NULL);
|
||||||
|
out << *def._interval << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_removed.empty()) {
|
||||||
|
out << "\nRemoved:\n";
|
||||||
|
Removed::const_iterator ri;
|
||||||
|
for (ri = _removed.begin(); ri != _removed.end(); ++ri) {
|
||||||
|
int index = (*ri);
|
||||||
|
nassertv(index >= 0 && index < (int)_intervals.size());
|
||||||
|
const IntervalDef &def = _intervals[index];
|
||||||
|
nassertv(def._interval != (CInterval *)NULL);
|
||||||
|
out << "(R)" << *def._interval << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::get_global_ptr
|
||||||
|
// Access: Published, Static
|
||||||
|
// Description: Returns the pointer to the one global
|
||||||
|
// CIntervalManager object.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
CIntervalManager *CIntervalManager::
|
||||||
|
get_global_ptr() {
|
||||||
|
if (_global_ptr == (CIntervalManager *)NULL) {
|
||||||
|
_global_ptr = new CIntervalManager;
|
||||||
|
}
|
||||||
|
return _global_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::finish_interval
|
||||||
|
// Access: Private
|
||||||
|
// Description: Explicitly finishes the indicated interval in
|
||||||
|
// preparation for moving it to the removed queue.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
finish_interval(CInterval *interval) {
|
||||||
|
switch (interval->get_state()) {
|
||||||
|
case CInterval::S_initial:
|
||||||
|
interval->priv_instant();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CInterval::S_final:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
interval->priv_finalize();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: CIntervalManager::remove_index
|
||||||
|
// Access: Private
|
||||||
|
// Description: Removes the indicated index number from the active
|
||||||
|
// list, either by moving it to the removed queue if it
|
||||||
|
// is flagged external, or by simply making the slot
|
||||||
|
// available again if it is not.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void CIntervalManager::
|
||||||
|
remove_index(int index) {
|
||||||
|
nassertv(index >= 0 && index < (int)_intervals.size());
|
||||||
|
IntervalDef &def = _intervals[index];
|
||||||
|
if ((def._flags & F_external) != 0) {
|
||||||
|
_removed.push_back(index);
|
||||||
|
} else {
|
||||||
|
def._interval = (CInterval *)NULL;
|
||||||
|
def._next_slot = _first_slot;
|
||||||
|
_first_slot = index;
|
||||||
|
}
|
||||||
|
}
|
101
direct/src/interval/cIntervalManager.h
Normal file
101
direct/src/interval/cIntervalManager.h
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Filename: cIntervalManager.h
|
||||||
|
// Created by: drose (10Sep02)
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// 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 CINTERVALMANAGER_H
|
||||||
|
#define CINTERVALMANAGER_H
|
||||||
|
|
||||||
|
#include "directbase.h"
|
||||||
|
#include "cInterval.h"
|
||||||
|
#include "pointerTo.h"
|
||||||
|
#include "pvector.h"
|
||||||
|
#include "pmap.h"
|
||||||
|
#include "vector_int.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Class : CIntervalManager
|
||||||
|
// Description : This object holds a number of currently-playing
|
||||||
|
// intervals and is responsible for advancing them each
|
||||||
|
// frame as needed.
|
||||||
|
//
|
||||||
|
// There is normally only one IntervalManager object in
|
||||||
|
// the world, and it is the responsibility of the
|
||||||
|
// scripting language to call step() on this object once
|
||||||
|
// each frame, and to then process the events indicated by
|
||||||
|
// get_next_event().
|
||||||
|
//
|
||||||
|
// It is also possible to create multiple
|
||||||
|
// IntervalManager objects for special needs.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
class EXPCL_DIRECT CIntervalManager {
|
||||||
|
PUBLISHED:
|
||||||
|
CIntervalManager();
|
||||||
|
~CIntervalManager();
|
||||||
|
|
||||||
|
int add_c_interval(CInterval *interval, bool external);
|
||||||
|
int find_c_interval(const string &name) const;
|
||||||
|
|
||||||
|
CInterval *get_c_interval(int index) const;
|
||||||
|
void remove_c_interval(int index);
|
||||||
|
|
||||||
|
int pause_all_interruptible();
|
||||||
|
int get_num_intervals() const;
|
||||||
|
|
||||||
|
void step();
|
||||||
|
int get_next_event();
|
||||||
|
int get_next_removal();
|
||||||
|
|
||||||
|
void output(ostream &out) const;
|
||||||
|
void write(ostream &out) const;
|
||||||
|
|
||||||
|
static CIntervalManager *get_global_ptr();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void finish_interval(CInterval *interval);
|
||||||
|
void remove_index(int index);
|
||||||
|
|
||||||
|
enum Flags {
|
||||||
|
F_external = 0x0001,
|
||||||
|
F_meta_interval = 0x0002,
|
||||||
|
};
|
||||||
|
class IntervalDef {
|
||||||
|
public:
|
||||||
|
PT(CInterval) _interval;
|
||||||
|
int _flags;
|
||||||
|
int _next_slot;
|
||||||
|
};
|
||||||
|
typedef pvector<IntervalDef> Intervals;
|
||||||
|
Intervals _intervals;
|
||||||
|
typedef pmap<string, int> NameIndex;
|
||||||
|
NameIndex _name_index;
|
||||||
|
typedef vector_int Removed;
|
||||||
|
Removed _removed;
|
||||||
|
|
||||||
|
int _first_slot;
|
||||||
|
int _next_event_index;
|
||||||
|
|
||||||
|
static CIntervalManager *_global_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
INLINE ostream &operator << (ostream &out, const CInterval &ival_mgr);
|
||||||
|
|
||||||
|
#include "cIntervalManager.I"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -444,6 +444,14 @@ priv_step(double t) {
|
|||||||
check_started("priv_step");
|
check_started("priv_step");
|
||||||
int now = double_to_int_time(t);
|
int now = double_to_int_time(t);
|
||||||
|
|
||||||
|
// One special case: if we step to t == 0.0, it really means to the
|
||||||
|
// very beginning of the interval, *before* any events that occurred
|
||||||
|
// at time 0. (Most of the time, stepping to a particular time
|
||||||
|
// means *after* any events that occurred at that time.)
|
||||||
|
if (t == 0.0) {
|
||||||
|
now = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Now look for events between the last time we ran and the current
|
// Now look for events between the last time we ran and the current
|
||||||
// time.
|
// time.
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ from EventManagerGlobal import *
|
|||||||
from PythonUtil import *
|
from PythonUtil import *
|
||||||
from ParticleManagerGlobal import *
|
from ParticleManagerGlobal import *
|
||||||
from PhysicsManagerGlobal import *
|
from PhysicsManagerGlobal import *
|
||||||
|
from IntervalManager import ivalMgr
|
||||||
|
|
||||||
import Task
|
import Task
|
||||||
import EventManager
|
import EventManager
|
||||||
@ -543,6 +544,11 @@ class ShowBase:
|
|||||||
self.dgTrav.traverse(self.dataRootNode)
|
self.dgTrav.traverse(self.dataRootNode)
|
||||||
return Task.cont
|
return Task.cont
|
||||||
|
|
||||||
|
def ivalloop(self, state):
|
||||||
|
# Execute all intervals in the global ivalMgr.
|
||||||
|
ivalMgr.step()
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
def igloop(self, state):
|
def igloop(self, state):
|
||||||
# run the collision traversal if we have a
|
# run the collision traversal if we have a
|
||||||
# CollisionTraverser set.
|
# CollisionTraverser set.
|
||||||
@ -567,11 +573,15 @@ class ShowBase:
|
|||||||
# give the dataloop task a reasonably "early" priority,
|
# give the dataloop task a reasonably "early" priority,
|
||||||
# so that it will get run before most tasks
|
# so that it will get run before most tasks
|
||||||
self.taskMgr.add(self.dataloop, 'dataloop', priority = -50)
|
self.taskMgr.add(self.dataloop, 'dataloop', priority = -50)
|
||||||
|
# spawn the ivalloop with a later priority, so that it will
|
||||||
|
# run after most tasks, but before igloop.
|
||||||
|
self.taskMgr.add(self.ivalloop, 'ivalloop', priority = 10)
|
||||||
self.eventMgr.restart()
|
self.eventMgr.restart()
|
||||||
|
|
||||||
def shutdown(self):
|
def shutdown(self):
|
||||||
self.taskMgr.remove('igloop')
|
self.taskMgr.remove('igloop')
|
||||||
self.taskMgr.remove('dataloop')
|
self.taskMgr.remove('dataloop')
|
||||||
|
self.taskMgr.remove('ivalloop')
|
||||||
self.eventMgr.shutdown()
|
self.eventMgr.shutdown()
|
||||||
|
|
||||||
def getBackgroundColor(self):
|
def getBackgroundColor(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user