|
@@ -6,6 +6,7 @@ from direct.directnotify.DirectNotifyGlobal import *
|
|
|
from direct.showbase import ExceptionVarDump
|
|
from direct.showbase import ExceptionVarDump
|
|
|
import signal
|
|
import signal
|
|
|
import types
|
|
import types
|
|
|
|
|
+import time
|
|
|
|
|
|
|
|
from pandac.PandaModules import *
|
|
from pandac.PandaModules import *
|
|
|
|
|
|
|
@@ -66,20 +67,24 @@ class TaskManager:
|
|
|
notify = directNotify.newCategory("TaskManager")
|
|
notify = directNotify.newCategory("TaskManager")
|
|
|
|
|
|
|
|
extendedExceptions = False
|
|
extendedExceptions = False
|
|
|
|
|
+ MaxEpochSpeed = 1.0/30.0
|
|
|
|
|
|
|
|
def __init__(self):
|
|
def __init__(self):
|
|
|
self.mgr = AsyncTaskManager('TaskManager')
|
|
self.mgr = AsyncTaskManager('TaskManager')
|
|
|
|
|
|
|
|
self.resumeFunc = None
|
|
self.resumeFunc = None
|
|
|
- self.globalClock = None
|
|
|
|
|
|
|
+ self.globalClock = self.mgr.getClock()
|
|
|
self.stepping = False
|
|
self.stepping = False
|
|
|
self.running = False
|
|
self.running = False
|
|
|
self.fKeyboardInterrupt = False
|
|
self.fKeyboardInterrupt = False
|
|
|
self.interruptCount = 0
|
|
self.interruptCount = 0
|
|
|
|
|
|
|
|
def destroy(self):
|
|
def destroy(self):
|
|
|
- self.mgr.stopThreads()
|
|
|
|
|
- self.removeTasksMatching('*')
|
|
|
|
|
|
|
+ self.mgr.cleanup()
|
|
|
|
|
+
|
|
|
|
|
+ def setClock(self, clockObject):
|
|
|
|
|
+ self.mgr.setClock(clockObject)
|
|
|
|
|
+ self.globalClock = clockObject
|
|
|
|
|
|
|
|
def keyboardInterruptHandler(self, signalNumber, stackFrame):
|
|
def keyboardInterruptHandler(self, signalNumber, stackFrame):
|
|
|
self.fKeyboardInterrupt = 1
|
|
self.fKeyboardInterrupt = 1
|
|
@@ -137,11 +142,24 @@ class TaskManager:
|
|
|
chain.setFrameBudget(frameBudget)
|
|
chain.setFrameBudget(frameBudget)
|
|
|
|
|
|
|
|
def hasTaskNamed(self, taskName):
|
|
def hasTaskNamed(self, taskName):
|
|
|
|
|
+ """Returns true if there is at least one task, active or
|
|
|
|
|
+ sleeping, with the indicated name. """
|
|
|
|
|
+
|
|
|
return bool(self.mgr.findTask(taskName))
|
|
return bool(self.mgr.findTask(taskName))
|
|
|
|
|
|
|
|
def getTasksNamed(self, taskName):
|
|
def getTasksNamed(self, taskName):
|
|
|
|
|
+ """Returns a list of all tasks, active or sleeping, with the
|
|
|
|
|
+ indicated name. """
|
|
|
return self.__makeTaskList(self.mgr.findTasks(taskName))
|
|
return self.__makeTaskList(self.mgr.findTasks(taskName))
|
|
|
|
|
|
|
|
|
|
+ def getTasks(self):
|
|
|
|
|
+ """Returns list of all active tasks in arbitrary order. """
|
|
|
|
|
+ return self.__makeTaskList(self.mgr.getActiveTasks())
|
|
|
|
|
+
|
|
|
|
|
+ def getDoLaters(self):
|
|
|
|
|
+ """Returns list of all sleeping tasks in arbitrary order. """
|
|
|
|
|
+ return self.__makeTaskList(self.mgr.getSleepingTasks())
|
|
|
|
|
+
|
|
|
def __makeTaskList(self, taskCollection):
|
|
def __makeTaskList(self, taskCollection):
|
|
|
l = []
|
|
l = []
|
|
|
for i in range(taskCollection.getNumTasks()):
|
|
for i in range(taskCollection.getNumTasks()):
|
|
@@ -150,27 +168,28 @@ class TaskManager:
|
|
|
|
|
|
|
|
def doMethodLater(self, delayTime, funcOrTask, name, priority = None,
|
|
def doMethodLater(self, delayTime, funcOrTask, name, priority = None,
|
|
|
sort = None, extraArgs = None, taskChain = None,
|
|
sort = None, extraArgs = None, taskChain = None,
|
|
|
- appendTask = False):
|
|
|
|
|
|
|
+ appendTask = False, owner = None, uponDeath = None):
|
|
|
if delayTime < 0:
|
|
if delayTime < 0:
|
|
|
assert self.notify.warning('doMethodLater: added task: %s with negative delay: %s' % (name, delayTime))
|
|
assert self.notify.warning('doMethodLater: added task: %s with negative delay: %s' % (name, delayTime))
|
|
|
|
|
|
|
|
- task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask)
|
|
|
|
|
|
|
+ task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath)
|
|
|
task.setDelay(delayTime)
|
|
task.setDelay(delayTime)
|
|
|
self.mgr.add(task)
|
|
self.mgr.add(task)
|
|
|
return task
|
|
return task
|
|
|
|
|
|
|
|
def add(self, funcOrTask, name, priority = None, sort = None,
|
|
def add(self, funcOrTask, name, priority = None, sort = None,
|
|
|
- extraArgs = None, taskChain = None, appendTask = False):
|
|
|
|
|
|
|
+ extraArgs = None, taskChain = None, appendTask = False,
|
|
|
|
|
+ owner = None, uponDeath = None):
|
|
|
|
|
|
|
|
"""
|
|
"""
|
|
|
Add a new task to the taskMgr.
|
|
Add a new task to the taskMgr.
|
|
|
You can add a Task object or a method that takes one argument.
|
|
You can add a Task object or a method that takes one argument.
|
|
|
"""
|
|
"""
|
|
|
- task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask)
|
|
|
|
|
|
|
+ task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath)
|
|
|
self.mgr.add(task)
|
|
self.mgr.add(task)
|
|
|
return task
|
|
return task
|
|
|
|
|
|
|
|
- def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask):
|
|
|
|
|
|
|
+ def __setupTask(self, funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath):
|
|
|
if isinstance(funcOrTask, PythonTask):
|
|
if isinstance(funcOrTask, PythonTask):
|
|
|
task = funcOrTask
|
|
task = funcOrTask
|
|
|
elif callable(funcOrTask):
|
|
elif callable(funcOrTask):
|
|
@@ -179,6 +198,11 @@ class TaskManager:
|
|
|
self.notify.error(
|
|
self.notify.error(
|
|
|
'add: Tried to add a task that was not a Task or a func')
|
|
'add: Tried to add a task that was not a Task or a func')
|
|
|
assert isinstance(name, types.StringTypes), 'Name must be a string type'
|
|
assert isinstance(name, types.StringTypes), 'Name must be a string type'
|
|
|
|
|
+ if extraArgs is None:
|
|
|
|
|
+ extraArgs = []
|
|
|
|
|
+ appendTask = True
|
|
|
|
|
+ task.setArgs(extraArgs, appendTask)
|
|
|
|
|
+
|
|
|
task.setName(name)
|
|
task.setName(name)
|
|
|
|
|
|
|
|
# For historical reasons, if priority is specified but not
|
|
# For historical reasons, if priority is specified but not
|
|
@@ -191,14 +215,20 @@ class TaskManager:
|
|
|
if sort is not None:
|
|
if sort is not None:
|
|
|
task.setSort(sort)
|
|
task.setSort(sort)
|
|
|
|
|
|
|
|
- if taskChain is not None:
|
|
|
|
|
- task.setTaskChain(taskChain)
|
|
|
|
|
-
|
|
|
|
|
if extraArgs is None:
|
|
if extraArgs is None:
|
|
|
extraArgs = []
|
|
extraArgs = []
|
|
|
appendTask = True
|
|
appendTask = True
|
|
|
task.setArgs(extraArgs, appendTask)
|
|
task.setArgs(extraArgs, appendTask)
|
|
|
|
|
|
|
|
|
|
+ if taskChain is not None:
|
|
|
|
|
+ task.setTaskChain(taskChain)
|
|
|
|
|
+
|
|
|
|
|
+ if owner is not None:
|
|
|
|
|
+ task.setOwner(owner)
|
|
|
|
|
+
|
|
|
|
|
+ if uponDeath is not None:
|
|
|
|
|
+ task.setUponDeath(uponDeath)
|
|
|
|
|
+
|
|
|
return task
|
|
return task
|
|
|
|
|
|
|
|
def remove(self, taskOrName):
|
|
def remove(self, taskOrName):
|
|
@@ -226,7 +256,13 @@ class TaskManager:
|
|
|
self.interruptCount = 0
|
|
self.interruptCount = 0
|
|
|
signal.signal(signal.SIGINT, self.keyboardInterruptHandler)
|
|
signal.signal(signal.SIGINT, self.keyboardInterruptHandler)
|
|
|
|
|
|
|
|
|
|
+ startFrameTime = self.globalClock.getRealTime()
|
|
|
|
|
+
|
|
|
self.mgr.poll()
|
|
self.mgr.poll()
|
|
|
|
|
+
|
|
|
|
|
+ # This is the spot for an internal yield function
|
|
|
|
|
+ nextTaskTime = self.mgr.getNextWakeTime()
|
|
|
|
|
+ self.doYield(startFrameTime, nextTaskTime)
|
|
|
|
|
|
|
|
# Restore default interrupt handler
|
|
# Restore default interrupt handler
|
|
|
signal.signal(signal.SIGINT, signal.default_int_handler)
|
|
signal.signal(signal.SIGINT, signal.default_int_handler)
|
|
@@ -236,11 +272,10 @@ class TaskManager:
|
|
|
def run(self):
|
|
def run(self):
|
|
|
# Set the clock to have last frame's time in case we were
|
|
# Set the clock to have last frame's time in case we were
|
|
|
# Paused at the prompt for a long time
|
|
# Paused at the prompt for a long time
|
|
|
- if self.globalClock:
|
|
|
|
|
- t = self.globalClock.getFrameTime()
|
|
|
|
|
- timeDelta = t - globalClock.getRealTime()
|
|
|
|
|
- self.globalClock.setRealTime(t)
|
|
|
|
|
- messenger.send("resetClock", [timeDelta])
|
|
|
|
|
|
|
+ t = self.globalClock.getFrameTime()
|
|
|
|
|
+ timeDelta = t - globalClock.getRealTime()
|
|
|
|
|
+ self.globalClock.setRealTime(t)
|
|
|
|
|
+ messenger.send("resetClock", [timeDelta])
|
|
|
|
|
|
|
|
if self.resumeFunc != None:
|
|
if self.resumeFunc != None:
|
|
|
self.resumeFunc()
|
|
self.resumeFunc()
|
|
@@ -299,3 +334,519 @@ class TaskManager:
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
def __repr__(self):
|
|
|
return str(self.mgr)
|
|
return str(self.mgr)
|
|
|
|
|
+
|
|
|
|
|
+ # In the event we want to do frame time managment, this is the
|
|
|
|
|
+ # function to replace or overload.
|
|
|
|
|
+ def doYield(self, frameStartTime, nextScheduledTaskTime):
|
|
|
|
|
+ None
|
|
|
|
|
+
|
|
|
|
|
+ def doYieldExample(self, frameStartTime, nextScheduledTaskTime):
|
|
|
|
|
+ minFinTime = frameStartTime + self.MaxEpochSpeed
|
|
|
|
|
+ if nextScheduledTaskTime > 0 and nextScheduledTaskTime < minFinTime:
|
|
|
|
|
+ print ' Adjusting Time'
|
|
|
|
|
+ minFinTime = nextScheduledTaskTime
|
|
|
|
|
+ delta = minFinTime - self.globalClock.getRealTime()
|
|
|
|
|
+ while(delta > 0.002):
|
|
|
|
|
+ print ' sleep %s'% (delta)
|
|
|
|
|
+ time.sleep(delta)
|
|
|
|
|
+ delta = minFinTime - self.globalClock.getRealTime()
|
|
|
|
|
+
|
|
|
|
|
+ if __debug__:
|
|
|
|
|
+ # to catch memory leaks during the tests at the bottom of the file
|
|
|
|
|
+ def _startTrackingMemLeaks(self):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def _stopTrackingMemLeaks(self):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def _checkMemLeaks(self):
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def _runTests(self):
|
|
|
|
|
+ if __debug__:
|
|
|
|
|
+ tm = TaskManager()
|
|
|
|
|
+ tm.setClock(ClockObject())
|
|
|
|
|
+ tm.setupTaskChain("default", tickClock = True)
|
|
|
|
|
+
|
|
|
|
|
+ # check for memory leaks after every test
|
|
|
|
|
+ tm._startTrackingMemLeaks()
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # run-once task
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDone(task, l=l):
|
|
|
|
|
+ l.append(None)
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ tm.add(_testDone, 'testDone')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ _testDone = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # remove by name
|
|
|
|
|
+ def _testRemoveByName(task):
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ tm.add(_testRemoveByName, 'testRemoveByName')
|
|
|
|
|
+ assert tm.remove('testRemoveByName') == 1
|
|
|
|
|
+ assert tm.remove('testRemoveByName') == 0
|
|
|
|
|
+ _testRemoveByName = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # duplicate named tasks
|
|
|
|
|
+ def _testDupNamedTasks(task):
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ tm.add(_testDupNamedTasks, 'testDupNamedTasks')
|
|
|
|
|
+ tm.add(_testDupNamedTasks, 'testDupNamedTasks')
|
|
|
|
|
+ assert tm.remove('testRemoveByName') == 0
|
|
|
|
|
+ _testDupNamedTasks = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # continued task
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testCont(task, l = l):
|
|
|
|
|
+ l.append(None)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.add(_testCont, 'testCont')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ tm.remove('testCont')
|
|
|
|
|
+ _testCont = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # continue until done task
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testContDone(task, l = l):
|
|
|
|
|
+ l.append(None)
|
|
|
|
|
+ if len(l) >= 2:
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ else:
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.add(_testContDone, 'testContDone')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ assert not tm.hasTaskNamed('testContDone')
|
|
|
|
|
+ _testContDone = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # hasTaskNamed
|
|
|
|
|
+ def _testHasTaskNamed(task):
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ tm.add(_testHasTaskNamed, 'testHasTaskNamed')
|
|
|
|
|
+ assert tm.hasTaskNamed('testHasTaskNamed')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert not tm.hasTaskNamed('testHasTaskNamed')
|
|
|
|
|
+ _testHasTaskNamed = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # task sort
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testPri1(task, l = l):
|
|
|
|
|
+ l.append(1)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ def _testPri2(task, l = l):
|
|
|
|
|
+ l.append(2)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.add(_testPri1, 'testPri1', sort = 1)
|
|
|
|
|
+ tm.add(_testPri2, 'testPri2', sort = 2)
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ assert l == [1, 2,]
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 4
|
|
|
|
|
+ assert l == [1, 2, 1, 2,]
|
|
|
|
|
+ tm.remove('testPri1')
|
|
|
|
|
+ tm.remove('testPri2')
|
|
|
|
|
+ _testPri1 = None
|
|
|
|
|
+ _testPri2 = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # task extraArgs
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testExtraArgs(arg1, arg2, l=l):
|
|
|
|
|
+ l.extend([arg1, arg2,])
|
|
|
|
|
+ return done
|
|
|
|
|
+ tm.add(_testExtraArgs, 'testExtraArgs', extraArgs=[4,5])
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ assert l == [4, 5,]
|
|
|
|
|
+ _testExtraArgs = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # task appendTask
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testAppendTask(arg1, arg2, task, l=l):
|
|
|
|
|
+ l.extend([arg1, arg2,])
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ tm.add(_testAppendTask, '_testAppendTask', extraArgs=[4,5], appendTask=True)
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ assert l == [4, 5,]
|
|
|
|
|
+ _testAppendTask = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # task uponDeath
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _uponDeathFunc(task, l=l):
|
|
|
|
|
+ l.append(task.name)
|
|
|
|
|
+ def _testUponDeath(task):
|
|
|
|
|
+ return done
|
|
|
|
|
+ tm.add(_testUponDeath, 'testUponDeath', uponDeath=_uponDeathFunc)
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ assert l == ['testUponDeath']
|
|
|
|
|
+ _testUponDeath = None
|
|
|
|
|
+ _uponDeathFunc = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # task owner
|
|
|
|
|
+ class _TaskOwner:
|
|
|
|
|
+ def _addTask(self, task):
|
|
|
|
|
+ self.addedTaskName = task.name
|
|
|
|
|
+ def _clearTask(self, task):
|
|
|
|
|
+ self.clearedTaskName = task.name
|
|
|
|
|
+ to = _TaskOwner()
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testOwner(task):
|
|
|
|
|
+ return done
|
|
|
|
|
+ tm.add(_testOwner, 'testOwner', owner=to)
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert getattr(to, 'addedTaskName', None) == 'testOwner'
|
|
|
|
|
+ assert getattr(to, 'clearedTaskName', None) == 'testOwner'
|
|
|
|
|
+ _testOwner = None
|
|
|
|
|
+ del to
|
|
|
|
|
+ _TaskOwner = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ doLaterTests = [0,]
|
|
|
|
|
+
|
|
|
|
|
+ # doLater
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDoLater1(task, l=l):
|
|
|
|
|
+ l.append(1)
|
|
|
|
|
+ def _testDoLater2(task, l=l):
|
|
|
|
|
+ l.append(2)
|
|
|
|
|
+ def _monitorDoLater(task, tm=tm, l=l, doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .03:
|
|
|
|
|
+ assert l == [1, 2,]
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLater1, 'testDoLater1')
|
|
|
|
|
+ tm.doMethodLater(.02, _testDoLater2, 'testDoLater2')
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLater, 'monitorDoLater', sort=10)
|
|
|
|
|
+ _testDoLater1 = None
|
|
|
|
|
+ _testDoLater2 = None
|
|
|
|
|
+ _monitorDoLater = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # doLater sort
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDoLaterPri1(task, l=l):
|
|
|
|
|
+ l.append(1)
|
|
|
|
|
+ def _testDoLaterPri2(task, l=l):
|
|
|
|
|
+ l.append(2)
|
|
|
|
|
+ def _monitorDoLaterPri(task, tm=tm, l=l, doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .02:
|
|
|
|
|
+ assert l == [1, 2,]
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterPri1, 'testDoLaterPri1', sort=1)
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterPri2, 'testDoLaterPri2', sort=2)
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLaterPri, 'monitorDoLaterPri', sort=10)
|
|
|
|
|
+ _testDoLaterPri1 = None
|
|
|
|
|
+ _testDoLaterPri2 = None
|
|
|
|
|
+ _monitorDoLaterPri = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # doLater extraArgs
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDoLaterExtraArgs(arg1, l=l):
|
|
|
|
|
+ l.append(arg1)
|
|
|
|
|
+ def _monitorDoLaterExtraArgs(task, tm=tm, l=l, doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .02:
|
|
|
|
|
+ assert l == [3,]
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterExtraArgs, 'testDoLaterExtraArgs', extraArgs=[3,])
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLaterExtraArgs, 'monitorDoLaterExtraArgs', sort=10)
|
|
|
|
|
+ _testDoLaterExtraArgs = None
|
|
|
|
|
+ _monitorDoLaterExtraArgs = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # doLater appendTask
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDoLaterAppendTask(arg1, task, l=l):
|
|
|
|
|
+ assert task.name == 'testDoLaterAppendTask'
|
|
|
|
|
+ l.append(arg1)
|
|
|
|
|
+ def _monitorDoLaterAppendTask(task, tm=tm, l=l, doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .02:
|
|
|
|
|
+ assert l == [4,]
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterAppendTask, 'testDoLaterAppendTask',
|
|
|
|
|
+ extraArgs=[4,], appendTask=True)
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLaterAppendTask, 'monitorDoLaterAppendTask', sort=10)
|
|
|
|
|
+ _testDoLaterAppendTask = None
|
|
|
|
|
+ _monitorDoLaterAppendTask = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # doLater uponDeath
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testUponDeathFunc(task, l=l):
|
|
|
|
|
+ assert task.name == 'testDoLaterUponDeath'
|
|
|
|
|
+ l.append(10)
|
|
|
|
|
+ def _testDoLaterUponDeath(arg1, l=l):
|
|
|
|
|
+ return done
|
|
|
|
|
+ def _monitorDoLaterUponDeath(task, tm=tm, l=l, doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .02:
|
|
|
|
|
+ assert l == [10,]
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterUponDeath, 'testDoLaterUponDeath',
|
|
|
|
|
+ uponDeath=_testUponDeathFunc)
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLaterUponDeath, 'monitorDoLaterUponDeath', sort=10)
|
|
|
|
|
+ _testUponDeathFunc = None
|
|
|
|
|
+ _testDoLaterUponDeath = None
|
|
|
|
|
+ _monitorDoLaterUponDeath = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # doLater owner
|
|
|
|
|
+ class _DoLaterOwner:
|
|
|
|
|
+ def _addTask(self, task):
|
|
|
|
|
+ self.addedTaskName = task.name
|
|
|
|
|
+ def _clearTask(self, task):
|
|
|
|
|
+ self.clearedTaskName = task.name
|
|
|
|
|
+ doLaterOwner = _DoLaterOwner()
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testDoLaterOwner(l=l):
|
|
|
|
|
+ pass
|
|
|
|
|
+ def _monitorDoLaterOwner(task, tm=tm, l=l, doLaterOwner=doLaterOwner,
|
|
|
|
|
+ doLaterTests=doLaterTests):
|
|
|
|
|
+ if task.time > .02:
|
|
|
|
|
+ assert getattr(doLaterOwner, 'addedTaskName', None) == 'testDoLaterOwner'
|
|
|
|
|
+ assert getattr(doLaterOwner, 'clearedTaskName', None) == 'testDoLaterOwner'
|
|
|
|
|
+ doLaterTests[0] -= 1
|
|
|
|
|
+ return task.done
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.doMethodLater(.01, _testDoLaterOwner, 'testDoLaterOwner',
|
|
|
|
|
+ owner=doLaterOwner)
|
|
|
|
|
+ doLaterTests[0] += 1
|
|
|
|
|
+ # make sure we run this task after the doLaters if they all occur on the same frame
|
|
|
|
|
+ tm.add(_monitorDoLaterOwner, 'monitorDoLaterOwner', sort=10)
|
|
|
|
|
+ _testDoLaterOwner = None
|
|
|
|
|
+ _monitorDoLaterOwner = None
|
|
|
|
|
+ del doLaterOwner
|
|
|
|
|
+ _DoLaterOwner = None
|
|
|
|
|
+ # don't check until all the doLaters are finished
|
|
|
|
|
+ #tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # run the doLater tests
|
|
|
|
|
+ while doLaterTests[0] > 0:
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ del doLaterTests
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # getTasks
|
|
|
|
|
+ def _testGetTasks(task):
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ # No doLaterProcessor in the new world.
|
|
|
|
|
+ assert len(tm.getTasks()) == 0
|
|
|
|
|
+ tm.add(_testGetTasks, 'testGetTasks1')
|
|
|
|
|
+ assert len(tm.getTasks()) == 1
|
|
|
|
|
+ assert (tm.getTasks()[0].name == 'testGetTasks1' or
|
|
|
|
|
+ tm.getTasks()[1].name == 'testGetTasks1')
|
|
|
|
|
+ tm.add(_testGetTasks, 'testGetTasks2')
|
|
|
|
|
+ tm.add(_testGetTasks, 'testGetTasks3')
|
|
|
|
|
+ assert len(tm.getTasks()) == 3
|
|
|
|
|
+ tm.remove('testGetTasks2')
|
|
|
|
|
+ assert len(tm.getTasks()) == 2
|
|
|
|
|
+ tm.remove('testGetTasks1')
|
|
|
|
|
+ tm.remove('testGetTasks3')
|
|
|
|
|
+ assert len(tm.getTasks()) == 0
|
|
|
|
|
+ _testGetTasks = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # getDoLaters
|
|
|
|
|
+ def _testGetDoLaters():
|
|
|
|
|
+ pass
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 0
|
|
|
|
|
+ tm.doMethodLater(.1, _testGetDoLaters, 'testDoLater1')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 1
|
|
|
|
|
+ assert tm.getDoLaters()[0].name == 'testDoLater1'
|
|
|
|
|
+ tm.doMethodLater(.1, _testGetDoLaters, 'testDoLater2')
|
|
|
|
|
+ tm.doMethodLater(.1, _testGetDoLaters, 'testDoLater3')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 3
|
|
|
|
|
+ tm.remove('testDoLater2')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 2
|
|
|
|
|
+ tm.remove('testDoLater1')
|
|
|
|
|
+ tm.remove('testDoLater3')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 0
|
|
|
|
|
+ _testGetDoLaters = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # duplicate named doLaters removed via taskMgr.remove
|
|
|
|
|
+ def _testDupNameDoLaters():
|
|
|
|
|
+ pass
|
|
|
|
|
+ # the doLaterProcessor is always running
|
|
|
|
|
+ tm.doMethodLater(.1, _testDupNameDoLaters, 'testDupNameDoLater')
|
|
|
|
|
+ tm.doMethodLater(.1, _testDupNameDoLaters, 'testDupNameDoLater')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 2
|
|
|
|
|
+ tm.remove('testDupNameDoLater')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 0
|
|
|
|
|
+ _testDupNameDoLaters = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # duplicate named doLaters removed via remove()
|
|
|
|
|
+ def _testDupNameDoLatersRemove():
|
|
|
|
|
+ pass
|
|
|
|
|
+ # the doLaterProcessor is always running
|
|
|
|
|
+ dl1 = tm.doMethodLater(.1, _testDupNameDoLatersRemove, 'testDupNameDoLaterRemove')
|
|
|
|
|
+ dl2 = tm.doMethodLater(.1, _testDupNameDoLatersRemove, 'testDupNameDoLaterRemove')
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 2
|
|
|
|
|
+ dl2.remove()
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 1
|
|
|
|
|
+ dl1.remove()
|
|
|
|
|
+ assert len(tm.getDoLaters()) == 0
|
|
|
|
|
+ _testDupNameDoLatersRemove = None
|
|
|
|
|
+ # nameDict etc. isn't cleared out right away with task.remove()
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # getTasksNamed
|
|
|
|
|
+ def _testGetTasksNamed(task):
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ assert len(tm.getTasksNamed('testGetTasksNamed')) == 0
|
|
|
|
|
+ tm.add(_testGetTasksNamed, 'testGetTasksNamed')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testGetTasksNamed')) == 1
|
|
|
|
|
+ assert tm.getTasksNamed('testGetTasksNamed')[0].name == 'testGetTasksNamed'
|
|
|
|
|
+ tm.add(_testGetTasksNamed, 'testGetTasksNamed')
|
|
|
|
|
+ tm.add(_testGetTasksNamed, 'testGetTasksNamed')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testGetTasksNamed')) == 3
|
|
|
|
|
+ tm.remove('testGetTasksNamed')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testGetTasksNamed')) == 0
|
|
|
|
|
+ _testGetTasksNamed = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # removeTasksMatching
|
|
|
|
|
+ def _testRemoveTasksMatching(task):
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ tm.add(_testRemoveTasksMatching, 'testRemoveTasksMatching')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching')) == 1
|
|
|
|
|
+ tm.removeTasksMatching('testRemoveTasksMatching')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching')) == 0
|
|
|
|
|
+ tm.add(_testRemoveTasksMatching, 'testRemoveTasksMatching1')
|
|
|
|
|
+ tm.add(_testRemoveTasksMatching, 'testRemoveTasksMatching2')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching1')) == 1
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching2')) == 1
|
|
|
|
|
+ tm.removeTasksMatching('testRemoveTasksMatching*')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching1')) == 0
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching2')) == 0
|
|
|
|
|
+ tm.add(_testRemoveTasksMatching, 'testRemoveTasksMatching1a')
|
|
|
|
|
+ tm.add(_testRemoveTasksMatching, 'testRemoveTasksMatching2a')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching1a')) == 1
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching2a')) == 1
|
|
|
|
|
+ tm.removeTasksMatching('testRemoveTasksMatching?a')
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching1a')) == 0
|
|
|
|
|
+ assert len(tm.getTasksNamed('testRemoveTasksMatching2a')) == 0
|
|
|
|
|
+ _testRemoveTasksMatching = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # create Task object and add to mgr
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testTaskObj(task, l=l):
|
|
|
|
|
+ l.append(None)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ t = Task(_testTaskObj)
|
|
|
|
|
+ tm.add(t, 'testTaskObj')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ tm.remove('testTaskObj')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ _testTaskObj = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ # remove Task via task.remove()
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testTaskObjRemove(task, l=l):
|
|
|
|
|
+ l.append(None)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ t = Task(_testTaskObjRemove)
|
|
|
|
|
+ tm.add(t, 'testTaskObjRemove')
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 1
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ t.remove()
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ del t
|
|
|
|
|
+ _testTaskObjRemove = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+
|
|
|
|
|
+ """
|
|
|
|
|
+ # this test fails, and it's not clear what the correct behavior should be.
|
|
|
|
|
+ # sort passed to Task.__init__ is always overridden by taskMgr.add()
|
|
|
|
|
+ # even if no sort is specified, and calling Task.setSort() has no
|
|
|
|
|
+ # effect on the taskMgr's behavior.
|
|
|
|
|
+ # set/get Task sort
|
|
|
|
|
+ l = []
|
|
|
|
|
+ def _testTaskObjSort(arg, task, l=l):
|
|
|
|
|
+ l.append(arg)
|
|
|
|
|
+ return task.cont
|
|
|
|
|
+ t1 = Task(_testTaskObjSort, sort=1)
|
|
|
|
|
+ t2 = Task(_testTaskObjSort, sort=2)
|
|
|
|
|
+ tm.add(t1, 'testTaskObjSort1', extraArgs=['a',], appendTask=True)
|
|
|
|
|
+ tm.add(t2, 'testTaskObjSort2', extraArgs=['b',], appendTask=True)
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 2
|
|
|
|
|
+ assert l == ['a', 'b']
|
|
|
|
|
+ assert t1.getSort() == 1
|
|
|
|
|
+ assert t2.getSort() == 2
|
|
|
|
|
+ t1.setSort(3)
|
|
|
|
|
+ assert t1.getSort() == 3
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 4
|
|
|
|
|
+ assert l == ['a', 'b', 'b', 'a',]
|
|
|
|
|
+ t1.remove()
|
|
|
|
|
+ t2.remove()
|
|
|
|
|
+ tm.step()
|
|
|
|
|
+ assert len(l) == 4
|
|
|
|
|
+ del t1
|
|
|
|
|
+ del t2
|
|
|
|
|
+ _testTaskObjSort = None
|
|
|
|
|
+ tm._checkMemLeaks()
|
|
|
|
|
+ """
|
|
|
|
|
+
|
|
|
|
|
+ del l
|
|
|
|
|
+ tm.destroy()
|
|
|
|
|
+ del tm
|