From c738d0f324062d0f4246c580b7ea1a3d5633b9f9 Mon Sep 17 00:00:00 2001 From: Mark Mine Date: Fri, 27 Oct 2000 06:47:48 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/directutil/DirectCameraControl.py | 62 ++- direct/src/directutil/DirectGeometry.py | 12 + direct/src/directutil/DirectSelection.py | 434 ++++++++++--------- direct/src/directutil/DirectSession.py | 107 ++--- direct/src/directutil/DirectSessionGlobal.py | 2 - direct/src/extensions/NodePath-extensions.py | 29 +- direct/src/showbase/ShowBase.py | 3 + direct/src/showbase/ShowBaseGlobal.py | 1 + 8 files changed, 356 insertions(+), 294 deletions(-) diff --git a/direct/src/directutil/DirectCameraControl.py b/direct/src/directutil/DirectCameraControl.py index 2e195b4890..9c02b7440b 100644 --- a/direct/src/directutil/DirectCameraControl.py +++ b/direct/src/directutil/DirectCameraControl.py @@ -6,7 +6,7 @@ class DirectCameraControl(PandaObject): def __init__(self, direct): # Create the grid self.direct = direct - self.chan = direct.chanCenter + self.chan = direct.chan self.camera = self.chan.camera self.orthoViewRoll = 0.0 self.lastView = 0 @@ -27,13 +27,17 @@ class DirectCameraControl(PandaObject): # Where are we in the channel? if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)): # MOUSE IS IN CENTRAL REGION + # Hide the marker for this kind of motion + self.coaMarker.hide() + # See if the shift key is pressed 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) + numEntries = self.direct.iRay.pickGeom( + render,chan.mouseX,chan.mouseY) coa = Point3(0) if(numEntries): # Start off with first point @@ -77,6 +81,10 @@ class DirectCameraControl(PandaObject): def mouseFlyStop(self): taskMgr.removeTasksNamed('determineMouseFlyMode') taskMgr.removeTasksNamed('manipulateCamera') + # Show the marker + self.coaMarker.show() + # Resize it + self.updateCoaMarkerSize() def determineMouseFlyMode(self): # Otherwise, determine mouse fly mode @@ -103,8 +111,16 @@ class DirectCameraControl(PandaObject): self.coaDist = Vec3(self.coa - self.zeroPoint).length() # Place the marker in render space self.coaMarker.setPos(self.camera,self.coa) + # Resize it + self.updateCoaMarkerSize(coaDist) # Record marker pos in render space - self.coaMarkerPos = self.coaMarker.getPos() + self.coaMarkerPos.assign(self.coaMarker.getPos()) + + def updateCoaMarkerSize(self, coaDist = None): + if not coaDist: + coaDist = Vec3(self.coaMarker.getPos( self.chan.camera )).length() + self.coaMarker.setScale(0.01 * coaDist * + math.tan(deg2Rad(self.chan.fovV))) def homeCam(self, chan): chan.camera.setMat(Mat4.identMat()) @@ -155,16 +171,17 @@ class DirectCameraControl(PandaObject): def SpawnMoveToView(self, chan, view): # Kill any existing tasks - taskMgr.removeTasksNamed('manipulateCamera') + taskMgr.removeTasksNamed('manipulateCamera') # Calc hprOffset - hprOffset = VBase3() - + 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 - + else: + self.orthoViewRoll = 0.0 + # Adjust offset based on specified view if view == 1: hprOffset.set(180., 0., 0.) elif view == 2: @@ -180,30 +197,25 @@ class DirectCameraControl(PandaObject): elif view == 7: hprOffset.set(135., -35.264, 0.) # Position target - self.relNodePath.setPosHpr(self.coaMarker, 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) - + # 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.centerVec * (-1.0 * offsetDistance) + # Now put the relNodePath at that point + self.relNodePath.setPosHpr(self.relNodePath, scaledCenterVec, self.zeroBaseVec) - - # Store this view for next time - # Reset orthoViewRoll if you change views - if view != self.lastView: - self.orthoViewRoll = 0.0 - + # Record view for next time around self.lastView = view - chan.camera.lerpPosHpr(self.zeroPoint, + chan.camera.lerpPosHpr(self.zeroPoint, VBase3(0,0,self.orthoViewRoll), CAM_MOVE_DURATION, other = self.relNodePath, blendType = 'easeInOut', task = 'manipulateCamera') + def swingCamAboutWidget(self, chan, degrees, t): # Remove existing camera manipulation task @@ -231,6 +243,8 @@ class DirectCameraControl(PandaObject): def spawnHPanYZoom(self): # Kill any existing tasks taskMgr.removeTasksNamed('manipulateCamera') + # hide the marker + self.coaMarker.hide() # Negate vec to give it the correct sense for mouse motion below targetVector = self.coa * -1 t = Task.Task(self.HPanYZoomTask) @@ -253,6 +267,8 @@ class DirectCameraControl(PandaObject): def spawnXZTranslateOrHPPan(self): # Kill any existing tasks taskMgr.removeTasksNamed('manipulateCamera') + # Hide the marker + self.coaMarker.hide() t = Task.Task(self.XZTranslateOrHPPanTask) t.scaleFactor = (self.coaDist / self.chan.near) taskMgr.spawnTaskNamed(t, 'manipulateCamera') @@ -279,6 +295,8 @@ class DirectCameraControl(PandaObject): def spawnXZTranslate(self): # Kill any existing tasks taskMgr.removeTasksNamed('manipulateCamera') + # Hide the marker + self.coaMarker.hide() t = Task.Task(self.XZTranslateTask) t.scaleFactor = (self.coaDist / self.chan.near) taskMgr.spawnTaskNamed(t, 'manipulateCamera') @@ -316,6 +334,8 @@ class DirectCameraControl(PandaObject): def spawnHPPan(self): # Kill any existing tasks taskMgr.removeTasksNamed('manipulateCamera') + # Hide the marker + self.coaMarker.hide() t = Task.Task(self.HPPanTask) taskMgr.spawnTaskNamed(t, 'manipulateCamera') diff --git a/direct/src/directutil/DirectGeometry.py b/direct/src/directutil/DirectGeometry.py index ad14f70af4..12fec10e6f 100644 --- a/direct/src/directutil/DirectGeometry.py +++ b/direct/src/directutil/DirectGeometry.py @@ -56,3 +56,15 @@ class LineNodePath(NodePath): def getVertexColor( self ): return self.lineSegs.getVertexColor() + + +## +## Given a point in space, and a direction, find the point of intersection +## of that ray with a plane at the specified origin, with the specified normal +def planeIntersect (lineOrigin, lineDir, planeOrigin, normal): + t = 0 + offset = planeOrigin - lineOrigin + t = offset.dot(normal) / lineDir.dot(normal) + hitPt = lineDir * t + return hitPt + lineOrigin + diff --git a/direct/src/directutil/DirectSelection.py b/direct/src/directutil/DirectSelection.py index 713a9250a0..dcb240eab9 100644 --- a/direct/src/directutil/DirectSelection.py +++ b/direct/src/directutil/DirectSelection.py @@ -3,46 +3,184 @@ from DirectGeometry import * from DirectSelection import * -class SelectionRay: - def __init__(self, camera, fGeom = 1): - # Record the camera associated with this selection ray - 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) - # Create a collision ray - self.ray = CollisionRay() - # Add the ray to the collision Node - rayCollisionNode.addSolid( self.ray ) - # Create a queue to hold the collision results - self.cq = CollisionHandlerQueue() - self.numEntries = 0 - # And a traverser to do the actual collision tests - self.ct = CollisionTraverser( RenderRelation.getClassType() ) - # Let the traverser know about the queue and the collision node - self.ct.addCollider(rayCollisionNode, self.cq ) +class DirectNodePath(NodePath): + # A node path augmented with info, bounding box, and utility methods + def __init__(self, nodePath): + # Initialize the superclass + NodePath.__init__(self) + self.assign(nodePath) + # Get a reasonable name + self.name = self.getNodePathName() + # Create a bounding box + self.bbox = DirectBoundingBox(self) + center = self.bbox.getCenter() + # Create matrix to hold the offset between the nodepath + # and its center of action (COA) + self.mCoa2Dnp = Mat4() + self.mCoa2Dnp.assign(Mat4.identMat()) + self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1)) + # Transform from nodePath to widget + self.mDnp2Widget = Mat4() + self.mDnp2Widget.assign(Mat4.identMat()) + # Use value of this pointer as unique ID + self.id = self.node().this - def pick(self, targetNodePath, mouseX, mouseY): - # Determine ray direction based upon the mouse coordinates - # Note! This has to be a cam object (of type ProjectionNode) - self.ray.setProjection( base.cam.node(), mouseX, mouseY ) - self.ct.traverse( targetNodePath.node() ) - self.numEntries = self.cq.getNumEntries() - return self.numEntries + def highlight(self): + self.bbox.show() - def objectToHitPt(self, index): - return self.cq.getEntry(index).getIntoIntersectionPoint() + def dehighlight(self): + self.bbox.hide() - def camToHitPt(self, index): - # Get the specified entry - entry = self.cq.getEntry(index) - hitPt = entry.getIntoIntersectionPoint() - # Convert point from object local space to camera space - return entry.getInvWrtSpace().xformPoint(hitPt) + def getCenter(self): + return self.bbox.getCenter() + + def getRadius(self): + return self.bbox.getRadius() + + def getMin(self): + return self.bbox.getMin() + + def getMax(self): + return self.bbox.getMax() + + def __repr__(self): + return ('NodePath:\t%s\n' % self.name) + + +class SelectedNodePaths(PandaObject): + def __init__(self,direct): + self.direct = direct + self.selectedDict = {} + self.deselectedDict = {} + self.last = None + + def select(self, nodePath, fMultiSelect = 0): + # Do nothing if nothing selected + if not nodePath: + print 'Nothing selected!!' + return None + + # Reset selected objects and highlight if multiSelect is false + if not fMultiSelect: + self.deselectAll() + + # Get this pointer + id = nodePath.node().this + # First see if its already in the selected dictionary + dnp = self.selectedDict.get(id, None) + # If so, we're done + if not dnp: + # See if it is in the deselected dictionary + dnp = self.deselectedDict.get(id, None) + if dnp: + # It has been previously selected: + # Show its bounding box + dnp.highlight() + # Remove it from the deselected dictionary + del(self.deselectedDict[id]) + else: + # Didn't find it, create a new selectedNodePath instance + dnp = DirectNodePath(nodePath) + # Show its bounding box + dnp.highlight() + # Add it to the selected dictionary + self.selectedDict[dnp.id] = dnp + # And update last + self.last = dnp + return dnp + + def deselect(self, nodePath): + # Get this pointer + id = nodePath.node().this + # See if it is in the selected dictionary + dnp = self.selectedDict.get(id, None) + if dnp: + # It was selected: + # Hide its bounding box + dnp.dehighlight() + # Remove it from the selected dictionary + del(self.selectedDict[id]) + # And keep track of it in the deselected dictionary + self.deselectedDict[id] = dnp + return dnp + + def selectedAsList(self): + list = [] + for key in self.selectedDict.keys(): + list.append(self.selectedDict[key]) + + def deselectedAsList(self): + list = [] + for key in self.deselectedDict.keys(): + list.append(self.deselectedDict[key]) + + def forEachSelectedNodePathDo(self, func): + duplicateKeys = self.selectedDict.keys()[:] + for key in duplicateKeys: + func(self.selectedDict[key]) + + def forEachDeselectedNodePathDo(self, func): + duplicateKeys = self.deselectedDict.keys()[:] + for key in duplicateKeys: + func(self.deselectedDict[key]) + + def getWrtAll(self): + self.forEachSelectedNodePathDo(self.getWrt) + + def getWrt(self, nodePath): + nodePath.mDnp2Widget.assign(nodePath.getMat(self.direct.widget)) + + def moveWrtWidgetAll(self): + self.forEachSelectedNodePathDo(self.moveWrtWidget) + + def moveWrtWidget(self, nodePath): + nodePath.setMat(self.direct.widget, nodePath.mDnp2Widget) + + def deselectAll(self): + self.forEachSelectedNodePathDo(self.deselect) + + def highlightAll(self): + self.forEachSelectedNodePathDo(DirectNodePath.highlight) + + def dehighlightAll(self): + self.forEachSelectedNodePathDo(DirectNodePath.dehighlight) + + def removeSelected(self): + selected = self.dnp.last + if selected: + selected.remove() + + def removeAll(self): + # Remove all selected nodePaths from the Scene Graph + self.forEachSelectedNodePathDo(NodePath.remove) + + def toggleVizSelected(self): + selected = self.dnp.last + # Toggle visibility of selected node paths + if selected: + selected.toggleViz() + + def toggleVizAll(self): + # Toggle viz for all selected node paths + self.forEachSelectedNodePathDo(NodePath.toggleViz) + + def isolateSelected(self): + selected = self.dnp.last + if selected: + selected.isolate() + + def getDirectNodePath(self, nodePath): + # Get this pointer + id = nodePath.node().this + # First check selected dict + dnp = self.selectedDict.get(id, None) + if dnp: + return dnp + # Otherwise return result of deselected search + return self.selectedDict.get(id, None) + + def getNumSelected(self): + return len(self.selectedDict.keys()) class DirectBoundingBox: @@ -163,7 +301,7 @@ class DirectBoundingBox: def __repr__(self): return (`self.__class__` + - '\nNodePath:\t%s\n' % self.name + + '\nNodePath:\t%s\n' % self.nodePath.getNodePathName() + 'Min:\t\t%s\n' % self.vecAsString(self.min) + 'Max:\t\t%s\n' % self.vecAsString(self.max) + 'Center:\t\t%s\n' % self.vecAsString(self.center) + @@ -171,178 +309,64 @@ class DirectBoundingBox: ) -class DirectNodePath(NodePath): - # A node path augmented with info, bounding box, and utility methods - def __init__(self, nodePath): - # Initialize the superclass - NodePath.__init__(self) - self.assign(nodePath) - # Get a reasonable name - self.name = self.getNodePathName() - # Create a bounding box - self.bbox = DirectBoundingBox(self) - # Use value of this pointer as unique ID - self.id = self.node().this - # Show bounding box - self.highlight() +class SelectionRay: + def __init__(self, camera): + # Record the camera associated with this selection ray + 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() + self.rayCollisionNode = self.rayCollisionNodePath.node() + # Intersect with geometry to begin with + self.collideWithGeom() + # Create a collision ray + self.ray = CollisionRay() + # Add the ray to the collision Node + self.rayCollisionNode.addSolid( self.ray ) + # Create a queue to hold the collision results + self.cq = CollisionHandlerQueue() + self.numEntries = 0 + # And a traverser to do the actual collision tests + self.ct = CollisionTraverser( RenderRelation.getClassType() ) + # Let the traverser know about the queue and the collision node + self.ct.addCollider(self.rayCollisionNode, self.cq ) - def highlight(self): - self.bbox.show() + def pickGeom(self, targetNodePath, mouseX, mouseY): + self.collideWithGeom() + return self.pick(targetNodePath, mouseX, mouseY) - def dehighlight(self): - self.bbox.hide() + def pickWidget(self, targetNodePath, mouseX, mouseY): + self.collideWithWidget() + return self.pick(targetNodePath, mouseX, mouseY) - def getCenter(self): - return self.bbox.getCenter() + def pick(self, targetNodePath, mouseX, mouseY): + # Determine ray direction based upon the mouse coordinates + # Note! This has to be a cam object (of type ProjectionNode) + self.ray.setProjection( base.cam.node(), mouseX, mouseY ) + self.ct.traverse( targetNodePath.node() ) + self.numEntries = self.cq.getNumEntries() + return self.numEntries - def getRadius(self): - return self.bbox.getRadius() + def collideWithGeom(self): + self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff()) + self.rayCollisionNode.setFromCollideMask(BitMask32().allOff()) + self.rayCollisionNode.setCollideGeom(1) - def getMin(self): - return self.bbox.getMin() + def collideWithWidget(self): + self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff()) + mask = BitMask32() + mask.setWord(0x80000000) + self.rayCollisionNode.setFromCollideMask(mask) + self.rayCollisionNode.setCollideGeom(0) - def getMax(self): - return self.bbox.getMax() + def objectToHitPt(self, index): + return self.cq.getEntry(index).getIntoIntersectionPoint() - def __repr__(self): - return ('NodePath:\t%s\n' % self.name) + def camToHitPt(self, index): + # Get the specified entry + entry = self.cq.getEntry(index) + hitPt = entry.getIntoIntersectionPoint() + # Convert point from object local space to camera space + return entry.getInvWrtSpace().xformPoint(hitPt) -class SelectedNodePaths(PandaObject): - def __init__(self): - self.selectedDict = {} - self.deselectedDict = {} - self.last = None - - def select(self, nodePath, fMultiSelect = 0): - # Do nothing if nothing selected - if not nodePath: - print 'Nothing selected!!' - return None - - # Reset selected objects and highlight if multiSelect is false - if not fMultiSelect: - self.deselectAll() - - # Get this pointer - id = nodePath.node().this - # First see if its already in the selected dictionary - dnp = self.selectedDict.get(id, None) - # If so, we're done - if not dnp: - # See if it is in the deselected dictionary - dnp = self.deselectedDict.get(id, None) - if dnp: - # It has been previously selected: - # Show its bounding box - dnp.highlight() - # Remove it from the deselected dictionary - del(self.deselectedDict[id]) - else: - # Didn't find it, create a new selectedNodePath instance - dnp = DirectNodePath(nodePath) - # Add it to the selected dictionary - self.selectedDict[dnp.id] = dnp - # And update last - self.last = dnp - return dnp - - def deselect(self, nodePath): - # Get this pointer - id = nodePath.node().this - # See if it is in the selected dictionary - dnp = self.selectedDict.get(id, None) - if dnp: - # It was selected: - # Hide its bounding box - dnp.dehighlight() - # Remove it from the selected dictionary - del(self.selectedDict[id]) - # And keep track of it in the deselected dictionary - self.deselectedDict[id] = dnp - return dnp - - def selectedAsList(self): - list = [] - for key in self.selectedDict.keys(): - list.append(self.selectedDict[key]) - - def deselectedAsList(self): - list = [] - for key in self.deselectedDict.keys(): - list.append(self.deselectedDict[key]) - - def forEachSelectedNodePathDo(self, func): - duplicateKeys = self.selectedDict.keys()[:] - for key in duplicateKeys: - func(self.selectedDict[key]) - - def forEachDeselectedNodePathDo(self, func): - duplicateKeys = self.deselectedDict.keys()[:] - for key in duplicateKeys: - func(self.deselectedDict[key]) - - def deselectAll(self): - self.forEachSelectedNodePathDo(self.deselect) - - def highlightAll(self): - self.forEachSelectedNodePathDo(DirectNodePath.highlight) - - def dehighlightAll(self): - self.forEachSelectedNodePathDo(DirectNodePath.dehighlight) - - def removeSelected(self): - selected = self.dnp.last - if selected: - selected.remove() - - def removeAll(self): - # Remove all selected nodePaths from the Scene Graph - self.forEachSelectedNodePathDo(NodePath.remove) - - def toggleVizSelected(self): - selected = self.dnp.last - # Toggle visibility of selected node paths - if selected: - selected.toggleViz() - - def toggleVizAll(self): - # Toggle viz for all selected node paths - self.forEachSelectedNodePathDo(NodePath.toggleViz) - - def isolateSelected(self): - selected = self.dnp.last - if selected: - selected.isolate() - - def getDirectNodePath(self, nodePath): - # Get this pointer - id = nodePath.node().this - # First check selected dict - dnp = self.selectedDict.get(id, None) - if dnp: - return dnp - # Otherwise return result of deselected search - return self.selectedDict.get(id, None) - - def getNumSelected(self): - return len(self.selectedDict.keys()) - -""" -dd = loader.loadModel(r"I:\beta\toons\install\neighborhoods\donalds_dock") -dd.reparentTo(render) - -# Operations on cq -cq.getNumEntries() -cq.getEntry(0).getIntoNode() -cq.getEntry(0).getIntoNode().getName() -print cq.getEntry(i).getIntoIntersectionPoint() - -for i in range(0,bobo.cq.getNumEntries()): - name = bobo.cq.getEntry(i).getIntoNode().getName() - if not name: - name = "" - print name - print bobo.cq.getEntry(i).getIntoIntersectionPoint()[0], - print bobo.cq.getEntry(i).getIntoIntersectionPoint()[1], - print bobo.cq.getEntry(i).getIntoIntersectionPoint()[2] -""" diff --git a/direct/src/directutil/DirectSession.py b/direct/src/directutil/DirectSession.py index 22a8381cb8..23ea1fbf76 100644 --- a/direct/src/directutil/DirectSession.py +++ b/direct/src/directutil/DirectSession.py @@ -14,31 +14,30 @@ class DirectSession(PandaObject): for camera in base.cameraList: self.contextList.append(DisplayRegionContext(base.win, camera)) self.iRayList.append(SelectionRay(camera)) - self.chanCenter = self.getChanData(0) + self.chan = self.getChanData(0) + self.camera = base.cameraList[0] - self.cameraControls = DirectCameraControl(self) - self.manipulationControls = DirectManipulationControl(self) + self.cameraControl = DirectCameraControl(self) + self.manipulationControl = DirectManipulationControl(self) + self.useObjectHandles() # Initialize the collection of selected nodePaths - self.selected = SelectedNodePaths() + self.selected = SelectedNodePaths(self) self.readout = OnscreenText.OnscreenText( '', 0.1, -0.95 ) # self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5) self.readout.reparentTo( hidden ) - self.createObjectHandles() - self.useObjectHandles() - self.fControl = 0 self.fAlt = 0 self.fShift = 0 self.in2DWidget = 0 + self.pos = VBase3() + self.hpr = VBase3() + self.scale = VBase3() + 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 = [('select', self.select), @@ -52,7 +51,6 @@ class DirectSession(PandaObject): 'shift', 'shift-up', 'alt', 'alt-up', 'control', 'control-up', 'b', 'c', 'f', 'l', 't', 'v', 'w'] - self.mouseEvents = ['mouse1', 'mouse1-up', 'mouse2', 'mouse2-up', 'mouse3', 'mouse3-up'] @@ -64,36 +62,38 @@ class DirectSession(PandaObject): self.readout.reparentTo(render2d) self.readout.setText(dnp.name) # Show the manipulation widget - self.objectHandles.reparentTo(render) - # Adjust its size - self.objectHandles.setScale(dnp.getRadius()) + self.widget.reparentTo(render) - # TBD Compute widget COA - # Update camera controls coa to this point - wrtMat = dnp.getMat(base.camera) - self.cameraControls.updateCoa( - wrtMat.xformPoint(dnp.getCenter())) + # Coa2Camera = Coa2Dnp * Dnp2Camera + mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(base.camera) + row = mCoa2Camera.getRow(3) + coa = Vec3(row[0], row[1], row[2]) + self.cameraControl.updateCoa(coa) + + # Adjust widgets size + self.widget.setScale(dnp.getRadius()) # Spawn task to have object handles follow the selected object taskMgr.removeTasksNamed('followSelectedNodePath') t = Task.Task(self.followSelectedNodePathTask) - t.nodePath = dnp + t.dnp = dnp taskMgr.spawnTaskNamed(t, 'followSelectedNodePath') # Send an message marking the event messenger.send('selectedNodePath', [dnp]) def followSelectedNodePathTask(self, state): - nodePath = state.nodePath - pos = nodePath.getPos(render) - self.objectHandles.setPos(pos) + mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render) + mCoa2Render.decomposeMatrix( + self.scale,self.hpr,self.pos,getDefaultCoordinateSystem()) + self.widget.setPosHpr(self.pos,self.hpr) return Task.cont def deselect(self, nodePath): - dnp = self.snp.deselect(nodePath) + dnp = self.selected.deselect(nodePath) if dnp: # Hide the manipulation widget - self.objectHandles.reparentTo(hidden) + self.widget.reparentTo(hidden) self.readout.reparentTo(hidden) self.readout.setText(' ') taskMgr.removeTasksNamed('followSelectedNodePath') @@ -103,7 +103,7 @@ class DirectSession(PandaObject): def deselectAll(self): self.selected.deselectAll() # Hide the manipulation widget - self.objectHandles.reparentTo(hidden) + self.widget.reparentTo(hidden) self.readout.reparentTo(hidden) self.readout.setText(' ') taskMgr.removeTasksNamed('followSelectedNodePath') @@ -116,9 +116,9 @@ class DirectSession(PandaObject): for context in self.contextList: context.spawnContextTask() # Turn on mouse Flying - self.cameraControls.enableMouseFly() + self.cameraControl.enableMouseFly() # Turn on object manipulation - self.manipulationControls.enableManipulation() + self.manipulationControl.enableManipulation() # Accept appropriate hooks self.enableKeyEvents() self.enableMouseEvents() @@ -129,9 +129,9 @@ class DirectSession(PandaObject): for context in self.contextList: context.removeContextTask() # Turn off camera fly - self.cameraControls.disableMouseFly() + self.cameraControl.disableMouseFly() # Turn off object manipulation - self.manipulationControls.disableManipulation() + self.manipulationControl.disableManipulation() self.disableKeyEvents() self.disableMouseEvents() self.disableActionEvents() @@ -141,7 +141,7 @@ class DirectSession(PandaObject): for context in self.contextList: context.removeContextTask() # Turn off camera fly - self.cameraControls.disableMouseFly() + self.cameraControl.disableMouseFly() # Ignore keyboard and action events self.disableKeyEvents() self.disableActionEvents() @@ -167,7 +167,7 @@ class DirectSession(PandaObject): self.accept(event, self.inputHandler, [event]) def disableActionEvents(self): - for event in self.actionEvents: + for event, method in self.actionEvents: self.ignore(event) def disableKeyEvents(self): @@ -179,7 +179,7 @@ class DirectSession(PandaObject): self.ignore(event) def useObjectHandles(self): - self.widget = self.objectHandles + self.widget = self.manipulationControl.objectHandles def hideReadout(self): self.readout.reparentTo(hidden) @@ -236,32 +236,6 @@ class DirectSession(PandaObject): base.toggleTexture() elif input == 'w': base.toggleWireframe() - - def createObjectHandles(self): - oh = self.objectHandles = hidden.attachNewNode( - NamedNode('objectHandles') ) - ohLines = LineNodePath( oh ) - ohLines.setColor( VBase4( 1.0, 0.0, 1.0, 1.0) ) - ohLines.setThickness( 3.0 ) - - # InnerRing - ohLines.moveTo( 0.8, 0.0, 0.0 ) - for ang in range(10, 360, 10): - ohLines.drawTo( (0.8 * math.cos(deg2Rad(ang))), - (0.8 * math.sin(deg2Rad(ang))), - 0.0 ) - - # Outer Ring - ohLines.moveTo( 1.2, 0.0, 0.0 ) - for ang in range(0, 360, 10): - ohLines.drawTo( (1.2 * math.cos(deg2Rad(ang))), - (1.2 * math.sin(deg2Rad(ang))), - 0.0 ) - - ohLines.moveTo( 0.0, 0.0, 0.0 ) - ohLines.drawTo( 0.0, 0.0, 1.5 ) - # Create the line segments - ohLines.create() class DisplayRegionContext(PandaObject): def __init__(self, win, camera): @@ -270,6 +244,7 @@ class DisplayRegionContext(PandaObject): self.cam = camera.getChild(0) self.camNode = self.cam.getNode(0) self.mouseData = win.getMouseData(0) + self.nearVec = Vec3(0) self.mouseX = 0.0 self.mouseY = 0.0 @@ -303,17 +278,27 @@ class DisplayRegionContext(PandaObject): self.fovV = self.camNode.getVfov() self.nearWidth = math.tan(deg2Rad(self.fovH / 2.0)) * self.near * 2.0 self.nearHeight = math.tan(deg2Rad(self.fovV / 2.0)) * self.near * 2.0 + self.left = -self.nearWidth/2.0 + self.right = self.nearWidth/2.0 + self.top = self.nearHeight/2.0 + self.bottom = -self.nearHeight/2.0 # Mouse Data # Last frame self.mouseLastX = self.mouseX self.mouseLastY = self.mouseY - # This frame + # Values for this frame + # Pixel coordinates of the mouse self.mousePixelX = self.mouseData.getX() self.mousePixelY = self.mouseData.getY() + # This ranges from -1 to 1 self.mouseX = ((self.mousePixelX / float(self.width)) * 2.0) - 1.0 self.mouseY = ((self.mousePixelY / float(self.height)) * -2.0) + 1.0 + # Delta percent of window the mouse moved self.mouseDeltaX = self.mouseX - self.mouseLastX self.mouseDeltaY = self.mouseY - self.mouseLastY + self.nearVec.set((self.nearWidth/2.0) * self.mouseX, + self.near, + (self.nearHeight/2.0) * self.mouseY) # Continue the task return Task.cont diff --git a/direct/src/directutil/DirectSessionGlobal.py b/direct/src/directutil/DirectSessionGlobal.py index eff36d9abe..89def18c6d 100644 --- a/direct/src/directutil/DirectSessionGlobal.py +++ b/direct/src/directutil/DirectSessionGlobal.py @@ -4,9 +4,7 @@ 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/extensions/NodePath-extensions.py b/direct/src/extensions/NodePath-extensions.py index 4fa2b20381..26a6336e1f 100644 --- a/direct/src/extensions/NodePath-extensions.py +++ b/direct/src/extensions/NodePath-extensions.py @@ -51,12 +51,31 @@ self.hideSiblings() def remove(self): - # Send message in case anyone needs to do something + from PandaObject import * + # Send message in case anyone needs to do something # before node is deleted - messenger.send('preRemoveNodePath', [self]) - # Remove nodePath - self.reparentTo(hidden) - self.removeNode() + messenger.send('preRemoveNodePath', [self]) + # Remove nodePath + self.reparentTo(hidden) + self.removeNode() + + def reversels(self): + ancestry = self.getAncestry() + indentString = "" + for nodePath in ancestry: + type = nodePath.node().getType().getName() + name = nodePath.getNodePathName() + print indentString + type + " " + name + indentString = indentString + " " + + def getAncestry(self): + from PandaObject import * + if self.node() != render.node(): + ancestry = self.getParent().getAncestry() + ancestry.append(self) + return ancestry + else: + return [self] # private methods diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 3278ca07d4..34f7c5237f 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -27,6 +27,9 @@ class ShowBase: import Loader self.initialState = NodeAttributes() + # Set a default "off color" (i.e. use poly color) for color transitions + self.initialState.setAttribute(ColorTransition.getClassType(), + ColorAttribute()) self.renderTop = NodePath(NamedNode('renderTop')) self.render = self.renderTop.attachNewNode('render') self.hidden = NodePath(NamedNode('hidden')) diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index dd79b70292..00fe2051e3 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -10,5 +10,6 @@ render = base.render hidden = base.hidden camera = base.camera loader = base.loader +ostream = Notify.out() run = base.run tkroot = base.tkroot