From 7f6b94eba1784c79b07f218f4cf139f7d729f75e Mon Sep 17 00:00:00 2001 From: Gyedo Jeon Date: Fri, 19 Feb 2010 18:51:04 +0000 Subject: [PATCH] Updated to be compatible with new LE multi view control --- direct/src/directtools/DirectCameraControl.py | 35 +- direct/src/directtools/DirectManipulation.py | 413 +++++++++++++----- direct/src/directtools/DirectSession.py | 45 +- 3 files changed, 363 insertions(+), 130 deletions(-) diff --git a/direct/src/directtools/DirectCameraControl.py b/direct/src/directtools/DirectCameraControl.py index 5810bb6880..d4c1ae02ea 100644 --- a/direct/src/directtools/DirectCameraControl.py +++ b/direct/src/directtools/DirectCameraControl.py @@ -2,6 +2,7 @@ from direct.showbase.DirectObject import DirectObject from DirectUtil import * from DirectGeometry import * from DirectGlobals import * +from DirectSelection import SelectionRay from direct.interval.IntervalGlobal import Sequence, Func from direct.directnotify import DirectNotifyGlobal from direct.task import Task @@ -124,8 +125,8 @@ class DirectCameraControl(DirectObject): self.startT= globalClock.getFrameTime() self.startF = globalClock.getFrameCount() # If the cam is orthogonal, spawn differentTask - if (hasattr(base.direct.cam.node(), "getLens") and - base.direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"): + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\ + base.direct.camera.getName() != 'persp': self.spawnOrthoZoom() else: # Start manipulation @@ -144,7 +145,12 @@ class DirectCameraControl(DirectObject): self.startT= globalClock.getFrameTime() self.startF = globalClock.getFrameCount() # Start manipulation - self.spawnXZTranslate() + # If the cam is orthogonal, spawn differentTask + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\ + base.direct.camera.getName() != 'persp': + self.spawnOrthoTranslate() + else: + self.spawnXZTranslate() self.altDown = 1 elif not self.useMayaCamControls: # Where are we in the display region? @@ -231,6 +237,12 @@ class DirectCameraControl(DirectObject): # Spawn new task taskMgr.add(self.XZTranslateTask, 'manipulateCamera') + def spawnOrthoTranslate(self): + # Kill any existing tasks + taskMgr.remove('manipulateCamera') + # Spawn new task + taskMgr.add(self.OrthoTranslateTask, 'manipulateCamera') + def spawnHPanYZoom(self): # Kill any existing tasks taskMgr.remove('manipulateCamera') @@ -279,6 +291,21 @@ class DirectCameraControl(DirectObject): xlateSF)) return Task.cont + def OrthoTranslateTask(self, state): + # create ray from the camera to detect 3d position + iRay = SelectionRay(base.direct.camera) + iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY) + iRay.collideWithBitMask(1) + iRay.ct.traverse(base.direct.grid) + + entry = iRay.getEntry(0) + hitPt = entry.getSurfacePoint(entry.getFromNodePath()) + del iRay + if hasattr(state, 'prevPt'): + base.direct.camera.setPos(base.direct.camera, (state.prevPt - hitPt)) + state.prevPt = hitPt + return Task.cont + def HPanYZoomTask(self, state): # If the cam is orthogonal, don't rotate or zoom. if (hasattr(base.direct.cam.node(), "getLens") and @@ -324,6 +351,8 @@ class DirectCameraControl(DirectObject): x = base.direct.dr.getWidth() y = base.direct.dr.getHeight() base.direct.dr.orthoFactor -= factor + if base.direct.dr.orthoFactor < 0: + base.direct.dr.orthoFactor = 0.0001 base.direct.dr.updateFilmSize(x, y) return Task.cont diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index 20a50f38e5..dcafdb5051 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -2,6 +2,7 @@ from direct.showbase.DirectObject import DirectObject from DirectGlobals import * from DirectUtil import * from DirectGeometry import * +from DirectSelection import SelectionRay from direct.task import Task import types @@ -11,6 +12,10 @@ class DirectManipulationControl(DirectObject): self.objectHandles = ObjectHandles() self.hitPt = Point3(0) self.prevHit = Vec3(0) + + self.hitPtScale = Point3(0) # [gjeon] to be used in new LE's camera control + self.prevHitScale = Vec3(0) # [gjeon] to be used in new LE's camera control + self.rotationCenter = Point3(0) self.initScaleMag = 1 self.manipRef = base.direct.group.attachNewNode('manipRef') @@ -21,9 +26,11 @@ class DirectManipulationControl(DirectObject): self.fSetCoa = 0 self.fHitInit = 1 self.fScaleInit = 1 + self.fScaleInit1 = 1 # [gjeon] to be used in new LE's camera control self.fWidgetTop = 0 self.fFreeManip = 1 - self.fScaling = 0 + self.fScaling3D = 0 + self.fScaling1D = 0 self.fMovable = 1 self.mode = None self.actionEvents = [ @@ -99,23 +106,28 @@ class DirectManipulationControl(DirectObject): if self.fAllowSelectionOnly: return - # Check for a widget hit point - entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET) - # Did we hit a widget? - if entry: - # Yes! - self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath())) - self.hitPtDist = Vec3(self.hitPt).length() - # Constraint determined by nodes name - self.constraint = entry.getIntoNodePath().getName() + if self.fScaling1D == 0 and\ + self.fScaling3D == 0: + + # Check for a widget hit point + entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET) + # Did we hit a widget? + if entry: + # Yes! + self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath())) + self.hitPtDist = Vec3(self.hitPt).length() + # Constraint determined by nodes name + self.constraint = entry.getIntoNodePath().getName() + else: + # Nope, off the widget, no constraint + self.constraint = None + # [gjeon] to prohibit unwanted object movement while direct window doesn't have focus + if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers) \ + and not self.fAllowMarquee: + return else: - # Nope, off the widget, no constraint - self.constraint = None - # [gjeon] to prohibit unwanted object movement while direct window doesn't have focus - if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers) \ - and not self.fAllowMarquee: - return - + entry = None + if not base.direct.gotAlt(modifiers): if entry: # Check to see if we are moving the object @@ -170,6 +182,8 @@ class DirectManipulationControl(DirectObject): if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt: return + if base.direct.fControl: + return endX = base.direct.dr.mouseX endY = base.direct.dr.mouseY @@ -315,22 +329,33 @@ class DirectManipulationControl(DirectObject): base.direct.select(entry.getIntoNodePath(), base.direct.fShift) else: base.direct.deselectAll() - elif self.mode == 'move': - self.manipulateObjectCleanup() + #elif self.mode == 'move': + self.manipulateObjectCleanup() self.mode = None def manipulateObjectCleanup(self): - if self.fScaling: + if self.fScaling3D or self.fScaling1D: # We had been scaling, need to reset object handles - self.objectHandles.transferObjectHandlesScale() - self.fScaling = 0 + if hasattr(base.direct, 'widget'): + base.direct.widget.transferObjectHandlesScale() + else: + self.objectHandles.transferObjectHandlesScale() + self.fScaling3D = 0 + self.fScaling1D = 0 base.direct.selected.highlightAll() - self.objectHandles.showAllHandles() + if hasattr(base.direct, 'widget'): + base.direct.widget.showAllHandles() + else: + self.objectHandles.showAllHandles() if base.direct.clusterMode == 'client': cluster( 'base.direct.manipulationControl.objectHandles.showAllHandles()') - self.objectHandles.hideGuides() + if hasattr(base.direct, 'widget'): + base.direct.widget.hideGuides() + else: + self.objectHandles.hideGuides() + # Restart followSelectedNodePath task self.spawnFollowSelectedNodePathTask() messenger.send('DIRECT_manipulateObjectCleanup', @@ -394,11 +419,20 @@ class DirectManipulationControl(DirectObject): self.fSetCoa = 1 - self.fSetCoa if self.fSetCoa: - self.objectHandles.coaModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.coaModeColor() + else: + self.objectHandles.coaModeColor() else: - self.objectHandles.manipModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.manipModeColor() + else: + self.objectHandles.manipModeColor() else: - self.objectHandles.disabledModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.disabledModeColor() + else: + self.objectHandles.disabledModeColor() def removeManipulateObjectTask(self): taskMgr.remove('manipulateObject') @@ -406,13 +440,22 @@ class DirectManipulationControl(DirectObject): def enableWidgetMove(self): self.fMovable = 1 if self.fSetCoa: - self.objectHandles.coaModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.coaModeColor() + else: + self.objectHandles.coaModeColor() else: - self.objectHandles.manipModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.manipModeColor() + else: + self.objectHandles.manipModeColor() def disableWidgetMove(self): self.fMovable = 0 - self.objectHandles.disabledModeColor() + if hasattr(base.direct, 'widget'): + base.direct.widget.disableModeColor() + else: + self.objectHandles.disabledModeColor() #-------------------------------------------------------------------------- # Function: get edit types list for specified objects which indicate @@ -452,9 +495,14 @@ class DirectManipulationControl(DirectObject): # Record undo point base.direct.pushUndo(base.direct.selected) # Update object handles visibility - self.objectHandles.showGuides() - self.objectHandles.hideAllHandles() - self.objectHandles.showHandle(self.constraint) + if hasattr(base.direct, 'widget'): + base.direct.widget.showGuides() + base.direct.widget.hideAllHandles() + base.direct.widget.showHandle(self.constraint) + else: + self.objectHandles.showGuides() + self.objectHandles.hideAllHandles() + self.objectHandles.showHandle(self.constraint) if base.direct.clusterMode == 'client': oh = 'base.direct.manipulationControl.objectHandles' cluster(oh + '.showGuides()', 0) @@ -474,6 +522,9 @@ class DirectManipulationControl(DirectObject): # reset hit-pt flag self.fHitInit = 1 self.fScaleInit = 1 + if not self.fScaling1D and\ + not self.fScaling3D: + self.fScaleInit1 = 1 # record initial offset between widget and camera t = Task.Task(self.manipulateObjectTask) t.fMouseX = abs(base.direct.dr.mouseX) > 0.9 @@ -490,56 +541,66 @@ class DirectManipulationControl(DirectObject): taskMgr.add(t, 'manipulateObject') def manipulateObjectTask(self, state): - # Widget takes precedence - if self.constraint: - type = self.constraint[2:] - if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE: - if type == 'post': - # [gjeon] non-uniform scaling - self.fScaling = 1 - self.scale1D(state) + if self.fScaling1D: + self.scale1D(state) + elif self.fScaling3D: + self.scale3D(state) + else: + # Widget takes precedence + if self.constraint: + type = self.constraint[2:] + if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE: + if type == 'post': + # [gjeon] non-uniform scaling + self.fScaling1D = 1 + self.scale1D(state) + else: + # [gjeon] uniform scaling + self.fScaling3D = 1 + self.scale3D(state) else: - # [gjeon] uniform scaling - self.fScaling = 1 - self.scale3D(state) - else: - if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: - self.xlate1D(state) - elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: - self.xlate2D(state) - elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: - self.rotate1D(state) - # No widget interaction, determine free manip mode - elif self.fFreeManip: - # If we've been scaling and changed modes, reset object handles - if 0 and self.fScaling and (not base.direct.fAlt): - self.objectHandles.transferObjectHandlesScale() - self.fScaling = 0 - # Alt key switches to a scaling mode - if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE: - self.fScaling = 1 - self.scale3D(state) - # Otherwise, manip mode depends on where you started - elif state.fMouseX and state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: - # In the corner, spin around camera's axis - self.rotateAboutViewVector(state) - elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: - # Mouse started elsewhere in the outer frame, rotate - self.rotate2D(state) - elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE: - # Mouse started in central region, xlate - # Mode depends on shift key - if base.direct.fShift or base.direct.fControl: - self.xlateCamXY(state) - else: - self.xlateCamXZ(state) + if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: + self.xlate1D(state) + elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: + self.xlate2D(state) + elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: + self.rotate1D(state) + # No widget interaction, determine free manip mode + elif self.fFreeManip: + # If we've been scaling and changed modes, reset object handles + if 0 and (self.fScaling1D or self.fScaling3D) and (not base.direct.fAlt): + if hasattr(base.direct, 'widget'): + base.direct.widget.transferObjectHandleScale() + else: + self.objectHandles.transferObjectHandlesScale() + + self.fScaling1D = 0 + self.fScaling3D = 0 + # Alt key switches to a scaling mode + if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE: + self.fScaling3D = 1 + self.scale3D(state) + # Otherwise, manip mode depends on where you started + elif state.fMouseX and state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: + # In the corner, spin around camera's axis + self.rotateAboutViewVector(state) + elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: + # Mouse started elsewhere in the outer frame, rotate + self.rotate2D(state) + elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE: + # Mouse started in central region, xlate + # Mode depends on shift key + if base.direct.fShift or base.direct.fControl: + self.xlateCamXY(state) + else: + self.xlateCamXZ(state) if self.fSetCoa: # Update coa based on current widget position base.direct.selected.last.mCoa2Dnp.assign( base.direct.widget.getMat(base.direct.selected.last)) else: # Move the objects with the widget - base.direct.selected.moveWrtWidgetAll() + base.direct.selected.moveWrtWidgetAll() # Continue return Task.cont @@ -550,39 +611,45 @@ class DirectManipulationControl(DirectObject): def removeTag(self, tag): self.unmovableTagList.remove(tag) - def gridSnapping(self, offset): - offsetX = offset.getX() - offsetY = offset.getY() - offsetZ = offset.getZ() - if math.fabs(offsetX) < base.direct.grid.gridSpacing / 2.0: - offsetX = 0 + def gridSnapping(self, nodePath, offset): + offsetX = nodePath.getX() + offset.getX() + offsetY = nodePath.getY() + offset.getY() + offsetZ = nodePath.getZ() + offset.getZ() + + if offsetX < 0.0: + signX = -1.0 else: - if offsetX < 0: - offsetX = -1 * base.direct.grid.gridSpacing - else: - offsetX = base.direct.grid.gridSpacing - - if math.fabs(offsetY) < base.direct.grid.gridSpacing / 2.0: - offsetY = 0 + signX = 1.0 + modX = math.fabs(offsetX) % base.direct.grid.gridSpacing + floorX = math.floor(math.fabs(offsetX) / base.direct.grid.gridSpacing) + if modX < base.direct.grid.gridSpacing / 2.0: + offsetX = signX * floorX * base.direct.grid.gridSpacing else: - if offsetY < 0: - offsetY = -1 * base.direct.grid.gridSpacing - else: - offsetY = base.direct.grid.gridSpacing + offsetX = signX * (floorX + 1) * base.direct.grid.gridSpacing - if math.fabs(offsetZ) < base.direct.grid.gridSpacing / 2.0: - offsetZ = 0 + if offsetY < 0.0: + signY = -1.0 else: - if offsetZ < 0: - offsetZ = -1 * base.direct.grid.gridSpacing - else: - offsetZ = base.direct.grid.gridSpacing + signY = 1.0 + modY = math.fabs(offsetY) % base.direct.grid.gridSpacing + floorY = math.floor(math.fabs(offsetY) / base.direct.grid.gridSpacing) + if modY < base.direct.grid.gridSpacing / 2.0: + offsetY = signY * floorY * base.direct.grid.gridSpacing + else: + offsetY = signY * (floorY + 1) * base.direct.grid.gridSpacing - offset.setX(offsetX) - offset.setY(offsetY) - offset.setZ(offsetZ) + if offsetZ < 0.0: + signZ = -1.0 + else: + signZ = 1.0 + modZ = math.fabs(offsetZ) % base.direct.grid.gridSpacing + floorZ = math.floor(math.fabs(offsetZ) / base.direct.grid.gridSpacing) + if modZ < base.direct.grid.gridSpacing / 2.0: + offsetZ = signZ * floorZ * base.direct.grid.gridSpacing + else: + offsetZ = signZ * (floorZ + 1) * base.direct.grid.gridSpacing - return offset + return Point3(offsetX, offsetY, offsetZ) ### WIDGET MANIPULATION METHODS ### def xlate1D(self, state): @@ -601,14 +668,19 @@ class DirectManipulationControl(DirectObject): # Move widget to keep hit point as close to mouse as possible offset = self.hitPt - self.prevHit - if self.fGridSnap: - offset = self.gridSnapping(offset) - if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView: for widget in base.direct.manipulationControl.widgetList: - widget.setPos(widget, offset) + if self.fGridSnap: + widget.setPos(self.gridSnapping(widget, offset)) + else: + widget.setPos(widget, offset) + if base.direct.camera.getName() != 'persp': + self.prevHit.assign(self.hitPt) else: - base.direct.widget.setPos(base.direct.widget, offset) + if self.fGridSnap: + base.direct.widget.setPos(self.gridSnapping(base.direct.widget, offset)) + else: + base.direct.widget.setPos(base.direct.widget, offset) def xlate2D(self, state): # Constrained 2D (planar) translation @@ -617,6 +689,7 @@ class DirectManipulationControl(DirectObject): # This point tracks all subsequent mouse movements self.hitPt.assign(self.objectHandles.getWidgetIntersectPt( base.direct.widget, self.constraint[:1])) + # use it to see how far to move the widget if self.fHitInit: # First time through just record hit point @@ -625,14 +698,19 @@ class DirectManipulationControl(DirectObject): else: offset = self.hitPt - self.prevHit - if self.fGridSnap: - offset = self.gridSnapping(offset) - if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView: for widget in base.direct.manipulationControl.widgetList: - widget.setPos(widget, offset) + if self.fGridSnap: + widget.setPos(self.gridSnapping(widget, offset)) + else: + widget.setPos(widget, offset) + if base.direct.camera.getName() != 'persp': + self.prevHit.assign(self.hitPt) else: - base.direct.widget.setPos(base.direct.widget, offset) + if self.fGridSnap: + base.direct.widget.setPos(self.gridSnapping(base.direct.widget, offset)) + else: + base.direct.widget.setPos(base.direct.widget, offset) def rotate1D(self, state): # Constrained 1D rotation about the widget's main axis (X, Y, or Z) @@ -722,6 +800,7 @@ class DirectManipulationControl(DirectObject): # Move widget (and objects) based upon mouse motion # Scaled up accordingly based upon widget distance dr = base.direct.dr + base.direct.widget.setX( base.direct.camera, x + 0.5 * dr.mouseDeltaX * dr.nearWidth * (y/dr.near)) @@ -764,6 +843,7 @@ class DirectManipulationControl(DirectObject): # The object, however, stays at the same relative point to mouse in X vWidget2Camera.setX((dr.nearVec[0] + self.deltaNearX) * (vWidget2Camera[1]/dr.near)) + # Move widget base.direct.widget.setPos(base.direct.camera, vWidget2Camera) @@ -801,6 +881,38 @@ class DirectManipulationControl(DirectObject): relHpr(base.direct.widget, base.direct.camera, 0, 0, -deltaAngle) def scale1D(self, state): + print self.constraint + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView: + self.hitPtScale.assign(self.objectHandles.getMouseIntersectPt()) + + if self.fScaleInit1: + # First time through just record hit point + self.fScaleInit1 = 0 + self.prevHitScale.assign(self.hitPtScale) + else: + widgetPos = base.direct.widget.getPos() + d0 = (self.prevHitScale - widgetPos).length() + d1 = (self.hitPtScale - widgetPos).length() + offset = d1 - d0 + currScale = base.direct.widget.getScale() + + # Scale factor is ratio current mag with init mag + if self.constraint[:1] == 'x': + currScale = Vec3(currScale.getX() + offset, currScale.getY(), currScale.getZ()) + if currScale.getX() < 0.0: + currScale.setX(0.01) + elif self.constraint[:1] == 'y': + currScale = Vec3(currScale.getX(), currScale.getY() + offset, currScale.getZ()) + if currScale.getY() < 0.0: + currScale.setY(0.01) + elif self.constraint[:1] == 'z': + currScale = Vec3(currScale.getX(), currScale.getY(), currScale.getZ() + offset) + if currScale.getZ() < 0.0: + currScale.setZ(0.01) + base.direct.widget.setScale(currScale) + self.prevHitScale.assign(self.hitPtScale) + return + # [gjeon] Constrained 1D scale of the selected node based upon up down mouse motion if self.fScaleInit: self.fScaleInit = 0 @@ -830,6 +942,27 @@ class DirectManipulationControl(DirectObject): base.direct.widget.setScale(currScale) def scale3D(self, state): + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView: + self.hitPtScale.assign(self.objectHandles.getMouseIntersectPt()) + + if self.fScaleInit1: + # First time through just record hit point + self.fScaleInit1 = 0 + self.prevHitScale.assign(self.hitPtScale) + else: + widgetPos = base.direct.widget.getPos() + d0 = (self.prevHitScale - widgetPos).length() + d1 = (self.hitPtScale - widgetPos).length() + offset = d1 - d0 + currScale = base.direct.widget.getScale() + currScale += offset + if currScale.getX() < 0.0 and\ + currScale.getY() < 0.0 and\ + currScale.getZ() < 0.0: + currScale = VBase3(0.01, 0.01, 0.01) + base.direct.widget.setScale(currScale) + self.prevHitScale.assign(self.hitPtScale) + return # Scale the selected node based upon up down mouse motion # Mouse motion from edge to edge results in a factor of 4 scaling # From midpoint to edge doubles or halves objects scale @@ -1328,6 +1461,35 @@ class ObjectHandles(NodePath, DirectObject): lines.setName('z-guide') def getAxisIntersectPt(self, axis): + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\ + base.direct.camera.getName() != 'persp': + # create ray from the camera to detect 3d position + iRay = SelectionRay(base.direct.camera) + iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY) + iRay.collideWithBitMask(1) + iRay.ct.traverse(base.direct.grid) + + entry = iRay.getEntry(0) + hitPt = entry.getSurfacePoint(entry.getFromNodePath()) + + # create a temp nodePath to get the position + np = NodePath('temp') + np.setPos(base.direct.camera, hitPt) + self.hitPt.assign(np.getPos()) + np.remove() + del iRay + if axis == 'x': + # We really only care about the nearest point on the axis + self.hitPt.setY(0) + self.hitPt.setZ(0) + elif axis == 'y': + self.hitPt.setX(0) + self.hitPt.setZ(0) + elif axis == 'z': + self.hitPt.setX(0) + self.hitPt.setY(0) + return self.hitPt + # Calc the xfrom from camera to widget mCam2Widget = base.direct.camera.getMat(base.direct.widget) lineDir = Vec3(mCam2Widget.xformVec(base.direct.dr.nearVec)) @@ -1372,7 +1534,31 @@ class ObjectHandles(NodePath, DirectObject): self.hitPt.setY(0) return self.hitPt + def getMouseIntersectPt(self): + # create ray from the camera to detect 3d position + iRay = SelectionRay(base.direct.camera) + iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY) + iRay.collideWithBitMask(1) + iRay.ct.traverse(base.direct.grid) + + entry = iRay.getEntry(0) + hitPt = entry.getSurfacePoint(entry.getFromNodePath()) + + # create a temp nodePath to get the position + np = NodePath('temp') + np.setPos(base.direct.camera, hitPt) + resultPt = Point3(0) + resultPt.assign(np.getPos()) + np.remove() + del iRay + return resultPt + def getWidgetIntersectPt(self, nodePath, plane): + if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\ + base.direct.camera.getName() != 'persp': + self.hitPt.assign(self.getMouseIntersectPt()) + return self.hitPt + # Find out the point of interection of the ray passing though the mouse # with the plane containing the 2D xlation or 1D rotation widgets @@ -1399,6 +1585,7 @@ class ObjectHandles(NodePath, DirectObject): elif plane == 'z': self.hitPt.assign(planeIntersect( lineOrigin, lineDir, ORIGIN, Z_AXIS)) + return self.hitPt diff --git a/direct/src/directtools/DirectSession.py b/direct/src/directtools/DirectSession.py index 7f1067ea19..653272c05b 100644 --- a/direct/src/directtools/DirectSession.py +++ b/direct/src/directtools/DirectSession.py @@ -38,6 +38,8 @@ class DirectSession(DirectObject): self.fEnabled = 0 self.fEnabledLight = 0 self.fScaleWidgetByCam = 0 # [gjeon] flag for scaling widget by distance from the camera + self.fIgnoreDirectOnlyKeyMap = 0 # [gjeon] to skip old direct controls in new LE + self.drList = DisplayRegionList() self.iRayList = map(lambda x: x.iRay, self.drList) self.dr = self.drList[0] @@ -161,6 +163,9 @@ class DirectSession(DirectObject): ['SGE_Delete', self.removeNodePath], ['SGE_Set Name', self.getAndSetName], ['DIRECT-delete', self.removeAllSelected], + ['DIRECT-Undo', self.undo], + ['DIRECT-Redo', self.redo], + ['DIRECT-OOBE', self.oobe], ] if base.wantTk: @@ -207,13 +212,7 @@ class DirectSession(DirectObject): 'alt-mouse3', 'alt-mouse3-up', ] - self.hotKeyMap = { - 'c': ('Center Camera', 0, 'DIRECT-centerCamIn'), - 'f': ('Fit on Widget', 0, 'DIRECT-fitOnWidget'), - 'h': ('Move Camera to ', 0, 'DIRECT-homeCam'), - 'shift-v': ('Toggle Marker', 0, 'DIRECT-toggleMarkerVis'), - 'm': ('Move to fit', 0, 'DIRECT-moveToFit'), - 'n': ('Pick Next COA', 0, 'DIRECT-pickNextCOA'), + self.directOnlyKeyMap = { 'u': ('Orbit Upright Camera', 0, 'DIRECT-orbitUprightCam'), 'shift-u': ('Upright Camera', 0, 'DIRECT-uprightCam'), '1': ('Move Camera to View 1', 0, 'DIRECT-spwanMoveToView-1'), @@ -231,10 +230,23 @@ class DirectSession(DirectObject): 'shift-=': ('Zoom In', 0, 'DIRECT-zoomInCam'), 'shift-_': ('Zoom Out', 0, 'DIRECT-zoomOutCam'), '-': ('Zoom Out', 0, 'DIRECT-zoomOutCam'), + 'o': ('Toggle OOBE', 0, 'DIRECT-OOBE'), + '[': ('DIRECT-Undo', 0, 'DIRECT-Undo'), + 'shift-[': ('DIRECT-Undo', 0, 'DIRECT-Undo'), + ']': ('DIRECT-Redo', 0, 'DIRECT-Redo'), + 'shift-]': ('DIRECT-Redo', 0, 'DIRECT-Redo'), + } + + self.hotKeyMap = { + 'c': ('Center Camera', 0, 'DIRECT-centerCamIn'), + 'f': ('Fit on Widget', 0, 'DIRECT-fitOnWidget'), + 'h': ('Move Camera to ', 0, 'DIRECT-homeCam'), + 'shift-v': ('Toggle Marker', 0, 'DIRECT-toggleMarkerVis'), + 'm': ('Move to fit', 0, 'DIRECT-moveToFit'), + 'n': ('Pick Next COA', 0, 'DIRECT-pickNextCOA'), 'delete': ('Delete', 0, 'DIRECT-delete'), '.': ('Scale Up Widget', 0, 'DIRECT-widgetScaleUp'), ',': ('Scale Down Widget', 0, 'DIRECT-widgetScaleDown'), - 'page_up': ('Up Ancestry', 'self.upAncestry()', 0), 'page_down': ('Down Ancestry', 'self.downAncestry()', 0), 'escape': ('Deselect All', 'self.deselectAll()', 0), @@ -243,7 +255,6 @@ class DirectSession(DirectObject): 'control-f': ('Flash', 'self.flash(last)', 0), 'l': ('Toggle lights', 'self.lights.toggle()', 0), 'shift-l': ('Toggle COA Lock', 'self.cameraControl.toggleCOALock()', 0), - 'o': ('Toggle OOBE', 'self.oobe()', 0), 'p': ('Set Active Parent', 'self.doSetActiveParent()', 0), 'r': ('Wrt Reparent', 'self.doWrtReparent()', 0), 'shift-r': ('Reparent', 'self.doReparent()', 0), @@ -251,10 +262,6 @@ class DirectSession(DirectObject): 't': ('Toggle Textures', 'base.toggleTexture()', 0), 'shift-a': ('Toggle Vis all', 'self.selected.toggleVisAll()', 0), 'w': ('Toggle Wireframe', 'base.toggleWireframe()', 0), - '[': ('DIRECT-Undo', 'self.undo()', 0), - 'shift-[': ('DIRECT-Undo', 'self.undo()', 0), - ']': ('DIRECT-Redo', 'DIRECT-self.redo()', 0), - 'shift-]': ('DIRECT-Redo', 'self.redo()', 0), 'control-z': ('Undo', 0, 'LE-Undo'), 'shift-z' : ('Redo', 0, 'LE-Redo'), } @@ -508,6 +515,8 @@ class DirectSession(DirectObject): self.trueCamera = self.camera self.cam = NodePath(winCtrl.camNode) self.camNode = winCtrl.camNode + if hasattr(winCtrl, 'grid'): + base.direct.grid = winCtrl.grid base.direct.dr = base.direct.drList[base.camList.index(NodePath(winCtrl.camNode))] base.direct.iRay = base.direct.dr.iRay base.mouseWatcher = winCtrl.mouseWatcher @@ -530,7 +539,15 @@ class DirectSession(DirectObject): messenger.send(keyDesc[2]) else: # [gjeon] when we need to call a function eval(keyDesc[1]) - + elif input in self.directOnlyKeyMap.keys(): + if self.fIgnoreDirectOnlyKeyMap: + return + keyDesc = self.directOnlyKeyMap[input] + if len(keyDesc) == 3: + if keyDesc[1] == 0: # [gjeon] when we need to send a message + messenger.send(keyDesc[2]) + else: # [gjeon] when we need to call a function + eval(keyDesc[1]) elif input == 'mouse1-up': self.fMouse1 = 0 # [gjeon] to update alt key information while mouse1 is pressed messenger.send('DIRECT-mouse1Up')