From ff94c0d83721e483b86bf49e35cc3b85b11984a9 Mon Sep 17 00:00:00 2001 From: Mark Mine Date: Fri, 20 Oct 2000 23:46:47 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/directutil/DirectGeometry.py | 1 - direct/src/directutil/DirectSelection.py | 2 + direct/src/directutil/DirectSession.py | 338 ++++++++++++++++++- direct/src/directutil/DirectSessionGlobal.py | 12 + direct/src/showbase/OnscreenText.py | 2 - direct/src/showbase/PandaObject.py | 1 - direct/src/showbase/ShowBase.py | 1 + direct/src/showbase/ShowBaseGlobal.py | 9 - 8 files changed, 349 insertions(+), 17 deletions(-) create mode 100644 direct/src/directutil/DirectSessionGlobal.py diff --git a/direct/src/directutil/DirectGeometry.py b/direct/src/directutil/DirectGeometry.py index de3e05df56..ad14f70af4 100644 --- a/direct/src/directutil/DirectGeometry.py +++ b/direct/src/directutil/DirectGeometry.py @@ -1,5 +1,4 @@ from PandaObject import * -import math class LineNodePath(NodePath): def __init__(self, parent = None, **kw): diff --git a/direct/src/directutil/DirectSelection.py b/direct/src/directutil/DirectSelection.py index 1ae9015999..2c44e55093 100644 --- a/direct/src/directutil/DirectSelection.py +++ b/direct/src/directutil/DirectSelection.py @@ -6,6 +6,8 @@ class SelectionRay: self.camera = camera # Create a collision node self.rayCollisionNodePath = camera.attachNewNode( CollisionNode() ) + # Don't pay the penalty of drawing this collision ray + self.rayCollisionNodePath.hide() rayCollisionNode = self.rayCollisionNodePath.node() # Specify if this ray collides with geometry rayCollisionNode.setCollideGeom(fGeom) diff --git a/direct/src/directutil/DirectSession.py b/direct/src/directutil/DirectSession.py index 14edeaab00..b95ddb4f1d 100644 --- a/direct/src/directutil/DirectSession.py +++ b/direct/src/directutil/DirectSession.py @@ -1,9 +1,8 @@ from PandaObject import * -from DirectGeometry import * -from DirectSelection import * from DirectCameraControl import * +from DirectSelection import * +from DirectGeometry import * import OnscreenText -import math class DirectSession(PandaObject): @@ -316,8 +315,10 @@ class DirectSession(PandaObject): elif input == 'w': base.toggleWireframe() - def createBBox(self, parent = hidden): + def createBBox(self, parent = None): # Create a line segments object for the bbox + if parent is None: + parent = hidden bbox = self.bbox = LineNodePath(parent) #bbox.setName('bbox') bbox.setColor( VBase4( 1., 0., 0., 1. ) ) @@ -428,3 +429,332 @@ class DisplayRegionContext(PandaObject): 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/directutil/DirectSessionGlobal.py b/direct/src/directutil/DirectSessionGlobal.py new file mode 100644 index 0000000000..eff36d9abe --- /dev/null +++ b/direct/src/directutil/DirectSessionGlobal.py @@ -0,0 +1,12 @@ +from ShowBaseGlobal import * +from DirectSession import * + +# If specified in the user's Configrc, create the direct session +if base.wantDIRECT: + direct = base.direct = DirectSession() + chanCenter = direct.chanCenter +else: + # Otherwise set the values to None + direct = base.direct = None + chanCenter = None + diff --git a/direct/src/showbase/OnscreenText.py b/direct/src/showbase/OnscreenText.py index 592447795e..72adb06420 100644 --- a/direct/src/showbase/OnscreenText.py +++ b/direct/src/showbase/OnscreenText.py @@ -2,8 +2,6 @@ from PandaObject import * - - class OnscreenText(PandaObject, NodePath): Font = loader.loadModelOnce("fonts/ttf-comic").node() diff --git a/direct/src/showbase/PandaObject.py b/direct/src/showbase/PandaObject.py index 56dfdef89f..38127cdc6c 100644 --- a/direct/src/showbase/PandaObject.py +++ b/direct/src/showbase/PandaObject.py @@ -1,4 +1,3 @@ - from DirectObject import * from PandaModules import * from ShowBaseGlobal import * diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 9aed3f378e..1ad7408759 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -7,6 +7,7 @@ from EventManagerGlobal import * from PythonUtil import * import Task import EventManager +import math import sys class ShowBase: diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 84989febd8..dd79b70292 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -12,12 +12,3 @@ camera = base.camera loader = base.loader run = base.run tkroot = base.tkroot - -# Now create the DIRECT tools -if base.wantDIRECT: - import DirectSession - direct = base.direct = DirectSession.DirectSession() - chanCenter = direct.chanCenter -else: - direct = base.direct = None - chanCenter = None