diff --git a/direct/src/directutil/DirectCameraControl.py b/direct/src/directutil/DirectCameraControl.py index 1e8524b7af..577fd2509f 100644 --- a/direct/src/directutil/DirectCameraControl.py +++ b/direct/src/directutil/DirectCameraControl.py @@ -7,9 +7,13 @@ class DirectCameraControl(PandaObject): # Create the grid self.direct = direct self.defChan = direct.chanCenter + self.camera = self.defChan.camera self.orthoViewRoll = 0.0 self.lastView = 0 self.coa = Point3(0) + self.coaMarker = loader.loadModel('misc/sphere') + self.coaMarker.setColor(1,0,0) + self.coaMarkerPos = Point3(0) self.relNodePath = render.attachNewNode(NamedNode('targetNode')) self.zeroBaseVec = VBase3(0) self.zeroVector = Vec3(0) @@ -22,25 +26,50 @@ class DirectCameraControl(PandaObject): self.initMouseY = chan.mouseY # Where are we in the channel? if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)): - # Mouse is in central region - # First compute a hit point based on current mouse position - if(self.direct.iRay.pick(render, chan.mouseX, chan.mouseY)): - # Find hit point in camera's space - self.coa = self.direct.iRay.hitPt(0) - # Handle case of bad coa point (too close or too far) - self.coaDist = Vec3(self.coa - self.zeroPoint).length() - if ((self.coaDist < (1.1 * self.defChan.near)) | - (self.coaDist > self.defChan.far)): - # Put it out in front of the camera + # MOUSE IS IN CENTRAL REGION + if (self.direct.fShift): + # If shift key is pressed, just perform horiz and vert pan: + self.spawnHPPan() + else: + # Otherwise, check for a hit point based on current mouse position + # And then spawn task to determine mouse mode + numEntries = self.direct.iRay.pick(render,chan.mouseX,chan.mouseY) + if(numEntries): + # Start off with first point + minPt = 0 + # Find hit point in camera's space + self.coa = self.direct.iRay.camToHitPt(minPt) + self.coaDist = Vec3(self.coa - self.zeroPoint).length() + # Check other intersection points, sorting them + # TBD: Use TBS C++ function to do this + if numEntries > 1: + for i in range(1,numEntries): + hitPt = self.direct.iRay.camToHitPt(i) + dist = Vec3(hitPt - self.zeroPoint).length() + if (dist < self.coaDist): + self.coaDist = dist + self.coa = hitPt + minPt = i + + # Handle case of bad coa point (too close or too far) + if ((self.coaDist < (1.1 * self.defChan.near)) | + (self.coaDist > self.defChan.far)): + # Put it out in front of the camera + self.coa.set(0,10,0) + self.coaDist = 10 + else: + # If no intersection point: + # Put coa out in front of the camera self.coa.set(0,10,0) self.coaDist = 10 - else: - # If no intersection point: - # Put coa out in front of the camera - self.coa.set(0,10,0) - self.coaDist = 10 - # Now spawn task to determine mouse fly mode - self.determineMouseFlyMode() + + # Place the marker in render space + self.coaMarker.setPos(self.camera,self.coa) + # Record this point for later use + self.coaMarkerPos = self.coaMarker.getPos() + # Now spawn task to determine mouse fly mode + self.determineMouseFlyMode() + # END MOUSE IN CENTRAL REGION else: # Mouse is in outer frame, spawn mouseRotateTask self.spawnMouseRotateTask() @@ -92,14 +121,14 @@ class DirectCameraControl(PandaObject): def centerCamIn(self, chan,t): # Chan is a display region context taskMgr.removeTasksNamed('manipulateCamera') - widgetToCam = self.direct.widget.getPos( chan.camera ) - dist = Vec3(widgetToCam - self.zeroPoint).length() + markerToCam = self.coaMarker.getPos( chan.camera ) + dist = Vec3(markerToCam - self.zeroPoint).length() scaledCenterVec = self.centerVec * dist - delta = widgetToCam - scaledCenterVec + delta = markerToCam - scaledCenterVec self.relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0)) - chan.camera.lerpPos(self.relNodePath, - Point3(delta), + chan.camera.lerpPos(Point3(delta), CAM_MOVE_DURATION, + other = self.relNodePath, blendType = 'easeInOut', task = 'manipulateCamera') @@ -107,7 +136,7 @@ class DirectCameraControl(PandaObject): taskMgr.removeTasksNamed('manipulateCamera') # Find a point zoom factor times the current separation # of the widget and cam - zoomPtToCam = self.direct.widget.getPos(chan.camera) * zoomFactor + zoomPtToCam = self.coaMarker.getPos(chan.camera) * zoomFactor # Put a target nodePath there self.relNodePath.setPos(chan.camera, zoomPtToCam) # Move to that point @@ -122,6 +151,13 @@ class DirectCameraControl(PandaObject): taskMgr.removeTasksNamed('manipulateCamera') # Calc hprOffset hprOffset = VBase3() + + if view == 8: + # Try the next roll angle + self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0 + # but use the last view + view = self.lastView + if view == 1: hprOffset.set(180., 0., 0.) elif view == 2: @@ -137,8 +173,7 @@ class DirectCameraControl(PandaObject): elif view == 7: hprOffset.set(135., -35.264, 0.) # Position target - self.relNodePath.setPosHpr(self.direct.widget, - self.zeroBaseVec, + self.relNodePath.setPosHpr(self.coaMarker, self.zeroBaseVec, hprOffset) # Scale center vec by current distance to target offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) - @@ -150,9 +185,11 @@ class DirectCameraControl(PandaObject): scaledCenterVec, self.zeroBaseVec) - # Start off with best view if change is to new view - if (view != self.lastView): + # Store this view for next time + # Reset orthoViewRoll if you change views + if view != self.lastView: self.orthoViewRoll = 0.0 + self.lastView = view chan.camera.lerpPosHpr(self.zeroPoint, VBase3(0,0,self.orthoViewRoll), @@ -161,40 +198,33 @@ class DirectCameraControl(PandaObject): blendType = 'easeInOut', task = 'manipulateCamera') - # Try another roll next time - self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0 - def swingCamAboutWidget(self, chan, degrees, t): # Remove existing camera manipulation task taskMgr.removeTasksNamed('manipulateCamera') # Coincident with widget - self.relNodePath.setPos(self.direct.widget, self.zeroPoint) + self.relNodePath.setPos(self.coaMarker, self.zeroPoint) # But aligned with render space self.relNodePath.setHpr(self.zeroPoint) - parent = self.defChan.camera.getParent + parent = self.defChan.camera.getParent() self.defChan.camera.wrtReparentTo(self.relNodePath) - self.relNodePath.lerpHpr(VBase3(degrees,0,0), - CAM_MOVE_DURATION, - blendType = 'easeInOut', - task = 'manipulateCamera') - # TODO: Convert this to an upon death - reparentTask = Task.Task(self.reparentCam) - reparentTask.parent = parent - reparentLater = Task.doLater(CAM_MOVE_DURATION, - reparentTask, - 'manipulateCamera') - taskMgr.spawnTaskNamed(reparentLater, 'manipulateCamera') + manipTask = self.relNodePath.lerpHpr(VBase3(degrees,0,0), + CAM_MOVE_DURATION, + blendType = 'easeInOut', + task = 'manipulateCamera') + # Upon death, reparent Cam to parent + manipTask.parent = parent + manipTask.uponDeath = self.reparentCam def reparentCam(self, state): self.defChan.camera.wrtReparentTo(state.parent) - return Task.done def spawnHPanYZoom(self): # Negate vec to give it the correct sense for mouse motion below - targetVector = self.coa * -1 + # targetVector = self.coa * -1 + targetVector = self.coa * -1 t = Task.Task(self.HPanYZoomTask) t.targetVector = targetVector taskMgr.spawnTaskNamed(t, 'manipulateCamera') @@ -253,7 +283,7 @@ class DirectCameraControl(PandaObject): return Task.cont def spawnMouseRotateTask(self): - self.relNodePath.setPos(self.coa) + self.relNodePath.setPos(render, self.coaMarkerPos) self.relNodePath.setHpr(self.defChan.camera, self.zeroPoint) t = Task.Task(self.mouseRotateTask) t.wrtMat = self.defChan.camera.getMat( self.relNodePath ) @@ -284,6 +314,7 @@ class DirectCameraControl(PandaObject): def enableMouseFly(self): self.enableMouseInteraction() self.enableHotKeys() + self.coaMarker.reparentTo(render) def enableMouseInteraction(self): # disable C++ fly interface @@ -297,17 +328,19 @@ class DirectCameraControl(PandaObject): self.accept('u', self.uprightCam, [self.defChan]) self.accept('c', self.centerCamIn, [self.defChan, 0.5]) self.accept('h', self.homeCam, [self.defChan]) - for i in range(1,8): + for i in range(1,9): self.accept(`i`, self.SpawnMoveToView, [self.defChan, i]) self.accept('9', self.swingCamAboutWidget, [self.defChan, -90.0, t]) self.accept('0', self.swingCamAboutWidget, [self.defChan, 90.0, t]) - self.accept('8', self.removeManipulateCameraTask) + self.accept('`', self.removeManipulateCameraTask) self.accept('=', self.zoomCam, [self.defChan, 0.5, t]) self.accept('+', self.zoomCam, [self.defChan, 0.5, t]) self.accept('-', self.zoomCam, [self.defChan, -2.0, t]) self.accept('_', self.zoomCam, [self.defChan, -2.0, t]) def disableMouseFly(self): + # Hide the marker + self.coaMarker.reparentTo(hidden) # Accept middle mouse events self.ignore('mouse2') self.ignore('mouse2-up') @@ -319,10 +352,9 @@ class DirectCameraControl(PandaObject): self.ignore('=') self.ignore('+') self.ignore('-') - self.ignore('=') + self.ignore('_') + self.ignore('`') def removeManipulateCameraTask(self): taskMgr.removeTasksNamed('manipulateCamera') - - diff --git a/direct/src/directutil/DirectSelection.py b/direct/src/directutil/DirectSelection.py index 2c44e55093..359b521423 100644 --- a/direct/src/directutil/DirectSelection.py +++ b/direct/src/directutil/DirectSelection.py @@ -31,13 +31,15 @@ class SelectionRay: self.numEntries = self.cq.getNumEntries() return self.numEntries - def localHitPt(self, index): + def objectToHitPt(self, index): return self.cq.getEntry(index).getIntoIntersectionPoint() - def hitPt(self, index): + def camToHitPt(self, index): + # Get the specified entry entry = self.cq.getEntry(index) hitPt = entry.getIntoIntersectionPoint() - return entry.getWrtSpace().xformPoint(hitPt) + # Convert point from object local space to camera space + return entry.getInvWrtSpace().xformPoint(hitPt) """ dd = loader.loadModel(r"I:\beta\toons\install\neighborhoods\donalds_dock") diff --git a/direct/src/directutil/DirectSession.py b/direct/src/directutil/DirectSession.py index b95ddb4f1d..77f3db6631 100644 --- a/direct/src/directutil/DirectSession.py +++ b/direct/src/directutil/DirectSession.py @@ -37,6 +37,8 @@ class DirectSession(PandaObject): self.in2DWidget = 0 self.iRay = self.iRayList[0] + self.iRay.rayCollisionNodePath.node().setFromCollideMask(BitMask32().allOff()) + self.iRay.rayCollisionNodePath.node().setIntoCollideMask(BitMask32().allOff()) self.hitPt = Point3(0.0) self.actionEvents = [('selectNodePath', self.selectNodePath), @@ -288,17 +290,17 @@ class DirectSession(PandaObject): elif input == 'mouse3-up': messenger.send('handleMouse3Up') elif input == 'shift': - self.fShift = true + self.fShift = 1 elif input == 'shift-up': - self.fShift = false + self.fShift = 0 elif input == 'control': - self.fControl = true + self.fControl = 1 elif input == 'control-up': - self.fControl = false + self.fControl = 0 elif input == 'alt': - self.fAlt = true + self.fAlt = 1 elif input == 'alt-up': - self.fAlt = false + self.fAlt = 0 elif input == 'escape': self.deselectAll() elif input == 'l': @@ -427,334 +429,3 @@ class DisplayRegionContext(PandaObject): self.mouseDeltaY = self.mouseY - self.mouseLastY # Continue the task return Task.cont - - -CAM_MOVE_DURATION = 1.0 - -class DirectCameraControl(PandaObject): - def __init__(self, direct): - # Create the grid - self.direct = direct - self.defChan = direct.chanCenter - self.orthoViewRoll = 0.0 - self.lastView = 0 - self.coa = Point3(0) - self.relNodePath = render.attachNewNode(NamedNode('targetNode')) - self.zeroBaseVec = VBase3(0) - self.zeroVector = Vec3(0) - self.centerVec = Vec3(0, 1, 0) - self.zeroPoint = Point3(0) - - def mouseFlyStart(self, chan): - # Record starting mouse positions - self.initMouseX = chan.mouseX - self.initMouseY = chan.mouseY - # Where are we in the channel? - if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)): - # Mouse is in central region - # First compute a hit point based on current mouse position - if(self.direct.iRay.pick(render, chan.mouseX, chan.mouseY)): - # Find hit point in camera's space - self.coa = self.direct.iRay.hitPt(0) - # Handle case of bad coa point (too close or too far) - self.coaDist = Vec3(self.coa - self.zeroPoint).length() - if ((self.coaDist < (1.1 * self.defChan.near)) | - (self.coaDist > self.defChan.far)): - # Put it out in front of the camera - self.coa.set(0,-10,0) - self.coaDist = 10 - else: - # If no intersection point: - # Put coa out in front of the camera - self.coa.set(0,-10,0) - self.coaDist = 10 - - # Now spawn task to determine mouse fly mode - self.determineMouseFlyMode() - else: - # Mouse is in outer frame, spawn mouseRotateTask - self.spawnMouseRotateTask() - - def mouseFlyStop(self): - taskMgr.removeTasksNamed('determineMouseFlyMode') - taskMgr.removeTasksNamed('manipulateCamera') - - def determineMouseFlyMode(self): - if (self.direct.fShift): - # If shift key is pressed: - self.spawnHPPan() - else: - # Otherwise, determine mouse fly mode - t = Task.Task(self.determineMouseFlyModeTask) - taskMgr.spawnTaskNamed(t, 'determineMouseFlyMode') - - def determineMouseFlyModeTask(self, state): - deltaX = self.defChan.mouseX - self.initMouseX - deltaY = self.defChan.mouseY - self.initMouseY - if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)): - return Task.cont - else: - if (abs(deltaY) > 0.1): - self.spawnHPanYZoom() - else: - self.spawnXZTranslate() - return Task.done - - def homeCam(self, chan): - chan.camera.setMat(Mat4.identMat()) - - def uprightCam(self, chan): - taskMgr.removeTasksNamed('manipulateCamera') - currH = chan.camera.getH() - chan.camera.lerpHpr(currH, 0, 0, - CAM_MOVE_DURATION, - other = render, - blendType = 'easeInOut', - task = 'manipulateCamera') - - def centerCam(self, chan): - # Chan is a display region context - self.centerCamIn(chan, 1.0) - - def centerCamNow(self, chan): - self.centerCamIn(chan, 0.) - - def centerCamIn(self, chan,t): - # Chan is a display region context - taskMgr.removeTasksNamed('manipulateCamera') - widgetToCam = self.direct.widget.getPos( chan.camera ) - dist = Vec3(widgetToCam - self.zeroPoint).length() - scaledCenterVec = self.centerVec * dist - delta = widgetToCam - scaledCenterVec - self.relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0)) - chan.camera.lerpPos(self.relNodePath, - Point3(delta), - CAM_MOVE_DURATION, - blendType = 'easeInOut', - task = 'manipulateCamera') - - def zoomCam(self, chan, zoomFactor, t): - taskMgr.removeTasksNamed('manipulateCamera') - # Find a point zoom factor times the current separation - # of the widget and cam - zoomPtToCam = self.direct.widget.getPos(chan.camera) * zoomFactor - # Put a target nodePath there - self.relNodePath.setPos(chan.camera, zoomPtToCam) - # Move to that point - chan.camera.lerpPos(self.zeroPoint, - CAM_MOVE_DURATION, - other = self.relNodePath, - blendType = 'easeInOut', - task = 'manipulateCamera') - - def SpawnMoveToView(self, chan, view): - # Kill any existing tasks - taskMgr.removeTasksNamed('manipulateCamera') - # Calc hprOffset - hprOffset = VBase3() - if view == 1: - hprOffset.set(180., 0., 0.) - elif view == 2: - hprOffset.set(0., 0., 0.) - elif view == 3: - hprOffset.set(90., 0., 0.) - elif view == 4: - hprOffset.set(-90., 0., 0.) - elif view == 5: - hprOffset.set(0., -90., 0.) - elif view == 6: - hprOffset.set(0., 90., 0.) - elif view == 7: - hprOffset.set(135., -35.264, 0.) - # Position target - self.relNodePath.setPosHpr(self.direct.widget, - self.zeroBaseVec, - hprOffset) - # Scale center vec by current distance to target - offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) - - self.zeroPoint).length() - scaledCenterVec = self.centerVec * (-1.0 * offsetDistance) - - # Now put the relNodePath at that point - self.relNodePath.setPosHpr(self.relNodePath, - scaledCenterVec, - self.zeroBaseVec) - - # Start off with best view if change is to new view - if (view != self.lastView): - self.orthoViewRoll = 0.0 - self.lastView = view - chan.camera.lerpPosHpr(self.zeroPoint, - VBase3(0,0,self.orthoViewRoll), - CAM_MOVE_DURATION, - other = self.relNodePath, - blendType = 'easeInOut', - task = 'manipulateCamera') - - # Try another roll next time - self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0 - - def swingCamAboutWidget(self, chan, degrees, t): - # Remove existing camera manipulation task - taskMgr.removeTasksNamed('manipulateCamera') - - # Coincident with widget - self.relNodePath.setPos(self.direct.widget, self.zeroPoint) - # But aligned with render space - self.relNodePath.setHpr(self.zeroPoint) - - parent = self.defChan.camera.getParent - self.defChan.camera.wrtReparentTo(self.relNodePath) - - self.relNodePath.lerpHpr(VBase3(degrees,0,0), - CAM_MOVE_DURATION, - blendType = 'easeInOut', - task = 'manipulateCamera') - # TODO: Convert this to an upon death - reparentTask = Task.Task(self.reparentCam) - reparentTask.parent = parent - reparentLater = Task.doLater(CAM_MOVE_DURATION, - reparentTask, - 'manipulateCamera') - taskMgr.spawnTaskNamed(reparentLater, 'manipulateCamera') - - def reparentCam(self, state): - self.defChan.camera.wrtReparentTo(state.parent) - return Task.done - - def spawnHPanYZoom(self): - # Negate vec to give it the correct sense for mouse motion below - # targetVector = self.coa * -1 - targetVector = self.coa - print self.coa[0], self.coa[1], self.coa[2] - t = Task.Task(self.HPanYZoomTask) - t.targetVector = targetVector - taskMgr.spawnTaskNamed(t, 'manipulateCamera') - - def HPanYZoomTask(self,state): - targetVector = state.targetVector - distToMove = targetVector * self.defChan.mouseDeltaY - self.defChan.camera.setPosHpr(self.defChan.camera, - distToMove[0], - distToMove[1], - distToMove[2], - (0.5 * self.defChan.mouseDeltaX * - self.defChan.fovH), - 0.0, 0.0) - return Task.cont - - - def spawnXZTranslateOrHPPan(self): - t = Task.Task(self.XZTranslateOrHPPanTask) - t.scaleFactor = (self.coaDist / self.defChan.near) - taskMgr.spawnTaskNamed(t, 'manipulateCamera') - - def XZTranslateOrHPPanTask(self, state): - if self.direct.fShift: - self.defChan.camera.setHpr(self.defChan.camera, - (0.5 * self.defChan.mouseDeltaX * - self.defChan.fovH), - (-0.5 * self.defChan.mouseDeltaY * - self.defChan.fovV), - 0.0) - else: - self.defChan.camera.setPos(self.defChan.camera, - (-0.5 * self.defChan.mouseDeltaX * - self.defChan.nearWidth * - state.scaleFactor), - 0.0, - (-0.5 * self.defChan.mouseDeltaY * - self.defChan.nearHeight * - state.scaleFactor)) - return Task.cont - - def spawnXZTranslate(self): - t = Task.Task(self.XZTranslateTask) - t.scaleFactor = (self.coaDist / self.defChan.near) - taskMgr.spawnTaskNamed(t, 'manipulateCamera') - - def XZTranslateTask(self,state): - self.defChan.camera.setPos(self.defChan.camera, - (-0.5 * self.defChan.mouseDeltaX * - self.defChan.nearWidth * - state.scaleFactor), - 0.0, - (-0.5 * self.defChan.mouseDeltaY * - self.defChan.nearHeight * - state.scaleFactor)) - return Task.cont - - def spawnMouseRotateTask(self): - self.relNodePath.setPos(self.coa) - self.relNodePath.setHpr(self.defChan.camera, self.zeroPoint) - t = Task.Task(self.mouseRotateTask) - t.wrtMat = self.defChan.camera.getMat( self.relNodePath ) - taskMgr.spawnTaskNamed(t, 'manipulateCamera') - - def mouseRotateTask(self, state): - wrtMat = state.wrtMat - self.relNodePath.setHpr(self.relNodePath, - (-0.5 * self.defChan.mouseDeltaX * 180.0), - (0.5 * self.defChan.mouseDeltaY * 180.0), - 0.0) - self.defChan.camera.setMat(self.relNodePath, wrtMat) - return Task.cont - - def spawnHPPan(self): - t = Task.Task(self.HPPanTask) - taskMgr.spawnTaskNamed(t, 'manipulateCamera') - - def HPPanTask(self, state): - self.defChan.camera.setHpr(self.defChan.camera, - (0.5 * self.defChan.mouseDeltaX * - self.defChan.fovH), - (-0.5 * self.defChan.mouseDeltaY * - self.defChan.fovV), - 0.0) - return Task.cont - - def enableMouseFly(self): - self.enableMouseInteraction() - self.enableHotKeys() - - def enableMouseInteraction(self): - # disable C++ fly interface - base.disableMouse() - # Accept middle mouse events - self.accept('mouse2', self.mouseFlyStart, [self.defChan]) - self.accept('mouse2-up', self.mouseFlyStop) - - def enableHotKeys(self): - t = CAM_MOVE_DURATION - self.accept('u', self.uprightCam, [self.defChan]) - self.accept('c', self.centerCamIn, [self.defChan, 0.5]) - self.accept('h', self.homeCam, [self.defChan]) - for i in range(1,8): - self.accept(`i`, self.SpawnMoveToView, [self.defChan, i]) - self.accept('9', self.swingCamAboutWidget, [self.defChan, -90.0, t]) - self.accept('0', self.swingCamAboutWidget, [self.defChan, 90.0, t]) - self.accept('8', self.removeManipulateCameraTask) - self.accept('=', self.zoomCam, [self.defChan, 0.5, t]) - self.accept('+', self.zoomCam, [self.defChan, 0.5, t]) - self.accept('-', self.zoomCam, [self.defChan, -2.0, t]) - self.accept('_', self.zoomCam, [self.defChan, -2.0, t]) - - def disableMouseFly(self): - # Accept middle mouse events - self.ignore('mouse2') - self.ignore('mouse2-up') - self.ignore('u') - self.ignore('c') - self.ignore('h') - for i in range(0,10): - self.ignore(`i`) - self.ignore('=') - self.ignore('+') - self.ignore('-') - self.ignore('=') - - def removeManipulateCameraTask(self): - taskMgr.removeTasksNamed('manipulateCamera') - - - diff --git a/direct/src/showbase/Task.py b/direct/src/showbase/Task.py index 79530523b4..fb82a8f12c 100644 --- a/direct/src/showbase/Task.py +++ b/direct/src/showbase/Task.py @@ -29,6 +29,7 @@ def getTimeFrame(): class Task: def __init__(self, callback): self.__call__ = callback + self.uponDeath = None def setStartTimeFrame(self, startTime, startFrame): self.starttime = startTime @@ -212,6 +213,8 @@ class TaskManager: except: pass # TODO: upon death + if task.uponDeath: + task.uponDeath(task) def removeTasksNamed(self, taskName): removedTasks = [] @@ -318,6 +321,7 @@ t = taskMgr.spawnTaskNamed(seq, 'doLater-fooLater') run() # tasks with state +# Combined with uponDeath someValue = 1 @@ -329,9 +333,19 @@ def func(state): state.someValue = state.someValue + 1 return Task.cont +def deathFunc(state): + print 'Value at death: ', state.someValue + task = Task.Task(func) + # set task state here task.someValue = someValue + +# Use instance variable uponDeath to specify function +# to perform on task removal +# Default value of uponDeath is None +task.uponDeath = deathFunc + t = taskMgr.spawnTaskNamed(task, 'funcTask') run() """