*** empty log message ***

This commit is contained in:
Mark Mine 2000-10-27 06:47:48 +00:00
parent 24110ec036
commit c738d0f324
8 changed files with 356 additions and 294 deletions

View File

@ -6,7 +6,7 @@ class DirectCameraControl(PandaObject):
def __init__(self, direct): def __init__(self, direct):
# Create the grid # Create the grid
self.direct = direct self.direct = direct
self.chan = direct.chanCenter self.chan = direct.chan
self.camera = self.chan.camera self.camera = self.chan.camera
self.orthoViewRoll = 0.0 self.orthoViewRoll = 0.0
self.lastView = 0 self.lastView = 0
@ -27,13 +27,17 @@ class DirectCameraControl(PandaObject):
# Where are we in the channel? # Where are we in the channel?
if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)): if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)):
# MOUSE IS IN CENTRAL REGION # 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 (self.direct.fShift):
# If shift key is pressed, just perform horiz and vert pan: # If shift key is pressed, just perform horiz and vert pan:
self.spawnHPPan() self.spawnHPPan()
else: else:
# Otherwise, check for a hit point based on current mouse position # Otherwise, check for a hit point based on current mouse position
# And then spawn task to determine mouse mode # 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) coa = Point3(0)
if(numEntries): if(numEntries):
# Start off with first point # Start off with first point
@ -77,6 +81,10 @@ class DirectCameraControl(PandaObject):
def mouseFlyStop(self): def mouseFlyStop(self):
taskMgr.removeTasksNamed('determineMouseFlyMode') taskMgr.removeTasksNamed('determineMouseFlyMode')
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Show the marker
self.coaMarker.show()
# Resize it
self.updateCoaMarkerSize()
def determineMouseFlyMode(self): def determineMouseFlyMode(self):
# Otherwise, determine mouse fly mode # Otherwise, determine mouse fly mode
@ -103,8 +111,16 @@ class DirectCameraControl(PandaObject):
self.coaDist = Vec3(self.coa - self.zeroPoint).length() self.coaDist = Vec3(self.coa - self.zeroPoint).length()
# Place the marker in render space # Place the marker in render space
self.coaMarker.setPos(self.camera,self.coa) self.coaMarker.setPos(self.camera,self.coa)
# Resize it
self.updateCoaMarkerSize(coaDist)
# Record marker pos in render space # 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): def homeCam(self, chan):
chan.camera.setMat(Mat4.identMat()) chan.camera.setMat(Mat4.identMat())
@ -155,16 +171,17 @@ class DirectCameraControl(PandaObject):
def SpawnMoveToView(self, chan, view): def SpawnMoveToView(self, chan, view):
# Kill any existing tasks # Kill any existing tasks
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Calc hprOffset # Calc hprOffset
hprOffset = VBase3() hprOffset = VBase3()
if view == 8: if view == 8:
# Try the next roll angle # Try the next roll angle
self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0 self.orthoViewRoll = (self.orthoViewRoll + 90.0) % 360.0
# but use the last view # but use the last view
view = self.lastView view = self.lastView
else:
self.orthoViewRoll = 0.0
# Adjust offset based on specified view
if view == 1: if view == 1:
hprOffset.set(180., 0., 0.) hprOffset.set(180., 0., 0.)
elif view == 2: elif view == 2:
@ -180,30 +197,25 @@ class DirectCameraControl(PandaObject):
elif view == 7: elif view == 7:
hprOffset.set(135., -35.264, 0.) hprOffset.set(135., -35.264, 0.)
# Position target # Position target
self.relNodePath.setPosHpr(self.coaMarker, self.zeroBaseVec, self.relNodePath.setPosHpr(self.coaMarker, self.zeroBaseVec,
hprOffset) hprOffset)
# Scale center vec by current distance to target # Scale center vec by current distance to target
offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) - offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) -
self.zeroPoint).length() self.zeroPoint).length()
scaledCenterVec = self.centerVec * (-1.0 * offsetDistance) scaledCenterVec = self.centerVec * (-1.0 * offsetDistance)
# Now put the relNodePath at that point
# Now put the relNodePath at that point self.relNodePath.setPosHpr(self.relNodePath,
self.relNodePath.setPosHpr(self.relNodePath,
scaledCenterVec, scaledCenterVec,
self.zeroBaseVec) self.zeroBaseVec)
# Record view for next time around
# Store this view for next time
# Reset orthoViewRoll if you change views
if view != self.lastView:
self.orthoViewRoll = 0.0
self.lastView = view self.lastView = view
chan.camera.lerpPosHpr(self.zeroPoint, chan.camera.lerpPosHpr(self.zeroPoint,
VBase3(0,0,self.orthoViewRoll), VBase3(0,0,self.orthoViewRoll),
CAM_MOVE_DURATION, CAM_MOVE_DURATION,
other = self.relNodePath, other = self.relNodePath,
blendType = 'easeInOut', blendType = 'easeInOut',
task = 'manipulateCamera') task = 'manipulateCamera')
def swingCamAboutWidget(self, chan, degrees, t): def swingCamAboutWidget(self, chan, degrees, t):
# Remove existing camera manipulation task # Remove existing camera manipulation task
@ -231,6 +243,8 @@ class DirectCameraControl(PandaObject):
def spawnHPanYZoom(self): def spawnHPanYZoom(self):
# Kill any existing tasks # Kill any existing tasks
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# hide the marker
self.coaMarker.hide()
# Negate vec to give it the correct sense for mouse motion below # Negate vec to give it the correct sense for mouse motion below
targetVector = self.coa * -1 targetVector = self.coa * -1
t = Task.Task(self.HPanYZoomTask) t = Task.Task(self.HPanYZoomTask)
@ -253,6 +267,8 @@ class DirectCameraControl(PandaObject):
def spawnXZTranslateOrHPPan(self): def spawnXZTranslateOrHPPan(self):
# Kill any existing tasks # Kill any existing tasks
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Hide the marker
self.coaMarker.hide()
t = Task.Task(self.XZTranslateOrHPPanTask) t = Task.Task(self.XZTranslateOrHPPanTask)
t.scaleFactor = (self.coaDist / self.chan.near) t.scaleFactor = (self.coaDist / self.chan.near)
taskMgr.spawnTaskNamed(t, 'manipulateCamera') taskMgr.spawnTaskNamed(t, 'manipulateCamera')
@ -279,6 +295,8 @@ class DirectCameraControl(PandaObject):
def spawnXZTranslate(self): def spawnXZTranslate(self):
# Kill any existing tasks # Kill any existing tasks
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Hide the marker
self.coaMarker.hide()
t = Task.Task(self.XZTranslateTask) t = Task.Task(self.XZTranslateTask)
t.scaleFactor = (self.coaDist / self.chan.near) t.scaleFactor = (self.coaDist / self.chan.near)
taskMgr.spawnTaskNamed(t, 'manipulateCamera') taskMgr.spawnTaskNamed(t, 'manipulateCamera')
@ -316,6 +334,8 @@ class DirectCameraControl(PandaObject):
def spawnHPPan(self): def spawnHPPan(self):
# Kill any existing tasks # Kill any existing tasks
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Hide the marker
self.coaMarker.hide()
t = Task.Task(self.HPPanTask) t = Task.Task(self.HPPanTask)
taskMgr.spawnTaskNamed(t, 'manipulateCamera') taskMgr.spawnTaskNamed(t, 'manipulateCamera')

View File

@ -56,3 +56,15 @@ class LineNodePath(NodePath):
def getVertexColor( self ): def getVertexColor( self ):
return self.lineSegs.getVertexColor() 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

View File

@ -3,46 +3,184 @@ from DirectGeometry import *
from DirectSelection import * from DirectSelection import *
class SelectionRay: class DirectNodePath(NodePath):
def __init__(self, camera, fGeom = 1): # A node path augmented with info, bounding box, and utility methods
# Record the camera associated with this selection ray def __init__(self, nodePath):
self.camera = camera # Initialize the superclass
# Create a collision node NodePath.__init__(self)
self.rayCollisionNodePath = camera.attachNewNode( CollisionNode() ) self.assign(nodePath)
# Don't pay the penalty of drawing this collision ray # Get a reasonable name
self.rayCollisionNodePath.hide() self.name = self.getNodePathName()
rayCollisionNode = self.rayCollisionNodePath.node() # Create a bounding box
# Specify if this ray collides with geometry self.bbox = DirectBoundingBox(self)
rayCollisionNode.setCollideGeom(fGeom) center = self.bbox.getCenter()
# Create a collision ray # Create matrix to hold the offset between the nodepath
self.ray = CollisionRay() # and its center of action (COA)
# Add the ray to the collision Node self.mCoa2Dnp = Mat4()
rayCollisionNode.addSolid( self.ray ) self.mCoa2Dnp.assign(Mat4.identMat())
# Create a queue to hold the collision results self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
self.cq = CollisionHandlerQueue() # Transform from nodePath to widget
self.numEntries = 0 self.mDnp2Widget = Mat4()
# And a traverser to do the actual collision tests self.mDnp2Widget.assign(Mat4.identMat())
self.ct = CollisionTraverser( RenderRelation.getClassType() ) # Use value of this pointer as unique ID
# Let the traverser know about the queue and the collision node self.id = self.node().this
self.ct.addCollider(rayCollisionNode, self.cq )
def pick(self, targetNodePath, mouseX, mouseY): def highlight(self):
# Determine ray direction based upon the mouse coordinates self.bbox.show()
# 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 objectToHitPt(self, index): def dehighlight(self):
return self.cq.getEntry(index).getIntoIntersectionPoint() self.bbox.hide()
def camToHitPt(self, index): def getCenter(self):
# Get the specified entry return self.bbox.getCenter()
entry = self.cq.getEntry(index)
hitPt = entry.getIntoIntersectionPoint() def getRadius(self):
# Convert point from object local space to camera space return self.bbox.getRadius()
return entry.getInvWrtSpace().xformPoint(hitPt)
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: class DirectBoundingBox:
@ -163,7 +301,7 @@ class DirectBoundingBox:
def __repr__(self): def __repr__(self):
return (`self.__class__` + 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) + 'Min:\t\t%s\n' % self.vecAsString(self.min) +
'Max:\t\t%s\n' % self.vecAsString(self.max) + 'Max:\t\t%s\n' % self.vecAsString(self.max) +
'Center:\t\t%s\n' % self.vecAsString(self.center) + 'Center:\t\t%s\n' % self.vecAsString(self.center) +
@ -171,178 +309,64 @@ class DirectBoundingBox:
) )
class DirectNodePath(NodePath): class SelectionRay:
# A node path augmented with info, bounding box, and utility methods def __init__(self, camera):
def __init__(self, nodePath): # Record the camera associated with this selection ray
# Initialize the superclass self.camera = camera
NodePath.__init__(self) # Create a collision node
self.assign(nodePath) self.rayCollisionNodePath = camera.attachNewNode( CollisionNode() )
# Get a reasonable name # Don't pay the penalty of drawing this collision ray
self.name = self.getNodePathName() self.rayCollisionNodePath.hide()
# Create a bounding box self.rayCollisionNode = self.rayCollisionNodePath.node()
self.bbox = DirectBoundingBox(self) # Intersect with geometry to begin with
# Use value of this pointer as unique ID self.collideWithGeom()
self.id = self.node().this # Create a collision ray
# Show bounding box self.ray = CollisionRay()
self.highlight() # 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): def pickGeom(self, targetNodePath, mouseX, mouseY):
self.bbox.show() self.collideWithGeom()
return self.pick(targetNodePath, mouseX, mouseY)
def dehighlight(self): def pickWidget(self, targetNodePath, mouseX, mouseY):
self.bbox.hide() self.collideWithWidget()
return self.pick(targetNodePath, mouseX, mouseY)
def getCenter(self): def pick(self, targetNodePath, mouseX, mouseY):
return self.bbox.getCenter() # 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): def collideWithGeom(self):
return self.bbox.getRadius() self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
self.rayCollisionNode.setFromCollideMask(BitMask32().allOff())
self.rayCollisionNode.setCollideGeom(1)
def getMin(self): def collideWithWidget(self):
return self.bbox.getMin() self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
mask = BitMask32()
mask.setWord(0x80000000)
self.rayCollisionNode.setFromCollideMask(mask)
self.rayCollisionNode.setCollideGeom(0)
def getMax(self): def objectToHitPt(self, index):
return self.bbox.getMax() return self.cq.getEntry(index).getIntoIntersectionPoint()
def __repr__(self): def camToHitPt(self, index):
return ('NodePath:\t%s\n' % self.name) # 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 = "<noname>"
print name
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[0],
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[1],
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[2]
"""

View File

@ -14,31 +14,30 @@ class DirectSession(PandaObject):
for camera in base.cameraList: for camera in base.cameraList:
self.contextList.append(DisplayRegionContext(base.win, camera)) self.contextList.append(DisplayRegionContext(base.win, camera))
self.iRayList.append(SelectionRay(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.cameraControl = DirectCameraControl(self)
self.manipulationControls = DirectManipulationControl(self) self.manipulationControl = DirectManipulationControl(self)
self.useObjectHandles()
# Initialize the collection of selected nodePaths # Initialize the collection of selected nodePaths
self.selected = SelectedNodePaths() self.selected = SelectedNodePaths(self)
self.readout = OnscreenText.OnscreenText( '', 0.1, -0.95 ) self.readout = OnscreenText.OnscreenText( '', 0.1, -0.95 )
# self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5) # self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5)
self.readout.reparentTo( hidden ) self.readout.reparentTo( hidden )
self.createObjectHandles()
self.useObjectHandles()
self.fControl = 0 self.fControl = 0
self.fAlt = 0 self.fAlt = 0
self.fShift = 0 self.fShift = 0
self.in2DWidget = 0 self.in2DWidget = 0
self.pos = VBase3()
self.hpr = VBase3()
self.scale = VBase3()
self.iRay = self.iRayList[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.hitPt = Point3(0.0)
self.actionEvents = [('select', self.select), self.actionEvents = [('select', self.select),
@ -52,7 +51,6 @@ class DirectSession(PandaObject):
'shift', 'shift-up', 'alt', 'alt-up', 'shift', 'shift-up', 'alt', 'alt-up',
'control', 'control-up', 'control', 'control-up',
'b', 'c', 'f', 'l', 't', 'v', 'w'] 'b', 'c', 'f', 'l', 't', 'v', 'w']
self.mouseEvents = ['mouse1', 'mouse1-up', self.mouseEvents = ['mouse1', 'mouse1-up',
'mouse2', 'mouse2-up', 'mouse2', 'mouse2-up',
'mouse3', 'mouse3-up'] 'mouse3', 'mouse3-up']
@ -64,36 +62,38 @@ class DirectSession(PandaObject):
self.readout.reparentTo(render2d) self.readout.reparentTo(render2d)
self.readout.setText(dnp.name) self.readout.setText(dnp.name)
# Show the manipulation widget # Show the manipulation widget
self.objectHandles.reparentTo(render) self.widget.reparentTo(render)
# Adjust its size
self.objectHandles.setScale(dnp.getRadius())
# TBD Compute widget COA
# Update camera controls coa to this point # Update camera controls coa to this point
wrtMat = dnp.getMat(base.camera) # Coa2Camera = Coa2Dnp * Dnp2Camera
self.cameraControls.updateCoa( mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(base.camera)
wrtMat.xformPoint(dnp.getCenter())) 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 # Spawn task to have object handles follow the selected object
taskMgr.removeTasksNamed('followSelectedNodePath') taskMgr.removeTasksNamed('followSelectedNodePath')
t = Task.Task(self.followSelectedNodePathTask) t = Task.Task(self.followSelectedNodePathTask)
t.nodePath = dnp t.dnp = dnp
taskMgr.spawnTaskNamed(t, 'followSelectedNodePath') taskMgr.spawnTaskNamed(t, 'followSelectedNodePath')
# Send an message marking the event # Send an message marking the event
messenger.send('selectedNodePath', [dnp]) messenger.send('selectedNodePath', [dnp])
def followSelectedNodePathTask(self, state): def followSelectedNodePathTask(self, state):
nodePath = state.nodePath mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render)
pos = nodePath.getPos(render) mCoa2Render.decomposeMatrix(
self.objectHandles.setPos(pos) self.scale,self.hpr,self.pos,getDefaultCoordinateSystem())
self.widget.setPosHpr(self.pos,self.hpr)
return Task.cont return Task.cont
def deselect(self, nodePath): def deselect(self, nodePath):
dnp = self.snp.deselect(nodePath) dnp = self.selected.deselect(nodePath)
if dnp: if dnp:
# Hide the manipulation widget # Hide the manipulation widget
self.objectHandles.reparentTo(hidden) self.widget.reparentTo(hidden)
self.readout.reparentTo(hidden) self.readout.reparentTo(hidden)
self.readout.setText(' ') self.readout.setText(' ')
taskMgr.removeTasksNamed('followSelectedNodePath') taskMgr.removeTasksNamed('followSelectedNodePath')
@ -103,7 +103,7 @@ class DirectSession(PandaObject):
def deselectAll(self): def deselectAll(self):
self.selected.deselectAll() self.selected.deselectAll()
# Hide the manipulation widget # Hide the manipulation widget
self.objectHandles.reparentTo(hidden) self.widget.reparentTo(hidden)
self.readout.reparentTo(hidden) self.readout.reparentTo(hidden)
self.readout.setText(' ') self.readout.setText(' ')
taskMgr.removeTasksNamed('followSelectedNodePath') taskMgr.removeTasksNamed('followSelectedNodePath')
@ -116,9 +116,9 @@ class DirectSession(PandaObject):
for context in self.contextList: for context in self.contextList:
context.spawnContextTask() context.spawnContextTask()
# Turn on mouse Flying # Turn on mouse Flying
self.cameraControls.enableMouseFly() self.cameraControl.enableMouseFly()
# Turn on object manipulation # Turn on object manipulation
self.manipulationControls.enableManipulation() self.manipulationControl.enableManipulation()
# Accept appropriate hooks # Accept appropriate hooks
self.enableKeyEvents() self.enableKeyEvents()
self.enableMouseEvents() self.enableMouseEvents()
@ -129,9 +129,9 @@ class DirectSession(PandaObject):
for context in self.contextList: for context in self.contextList:
context.removeContextTask() context.removeContextTask()
# Turn off camera fly # Turn off camera fly
self.cameraControls.disableMouseFly() self.cameraControl.disableMouseFly()
# Turn off object manipulation # Turn off object manipulation
self.manipulationControls.disableManipulation() self.manipulationControl.disableManipulation()
self.disableKeyEvents() self.disableKeyEvents()
self.disableMouseEvents() self.disableMouseEvents()
self.disableActionEvents() self.disableActionEvents()
@ -141,7 +141,7 @@ class DirectSession(PandaObject):
for context in self.contextList: for context in self.contextList:
context.removeContextTask() context.removeContextTask()
# Turn off camera fly # Turn off camera fly
self.cameraControls.disableMouseFly() self.cameraControl.disableMouseFly()
# Ignore keyboard and action events # Ignore keyboard and action events
self.disableKeyEvents() self.disableKeyEvents()
self.disableActionEvents() self.disableActionEvents()
@ -167,7 +167,7 @@ class DirectSession(PandaObject):
self.accept(event, self.inputHandler, [event]) self.accept(event, self.inputHandler, [event])
def disableActionEvents(self): def disableActionEvents(self):
for event in self.actionEvents: for event, method in self.actionEvents:
self.ignore(event) self.ignore(event)
def disableKeyEvents(self): def disableKeyEvents(self):
@ -179,7 +179,7 @@ class DirectSession(PandaObject):
self.ignore(event) self.ignore(event)
def useObjectHandles(self): def useObjectHandles(self):
self.widget = self.objectHandles self.widget = self.manipulationControl.objectHandles
def hideReadout(self): def hideReadout(self):
self.readout.reparentTo(hidden) self.readout.reparentTo(hidden)
@ -236,32 +236,6 @@ class DirectSession(PandaObject):
base.toggleTexture() base.toggleTexture()
elif input == 'w': elif input == 'w':
base.toggleWireframe() 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): class DisplayRegionContext(PandaObject):
def __init__(self, win, camera): def __init__(self, win, camera):
@ -270,6 +244,7 @@ class DisplayRegionContext(PandaObject):
self.cam = camera.getChild(0) self.cam = camera.getChild(0)
self.camNode = self.cam.getNode(0) self.camNode = self.cam.getNode(0)
self.mouseData = win.getMouseData(0) self.mouseData = win.getMouseData(0)
self.nearVec = Vec3(0)
self.mouseX = 0.0 self.mouseX = 0.0
self.mouseY = 0.0 self.mouseY = 0.0
@ -303,17 +278,27 @@ class DisplayRegionContext(PandaObject):
self.fovV = self.camNode.getVfov() self.fovV = self.camNode.getVfov()
self.nearWidth = math.tan(deg2Rad(self.fovH / 2.0)) * self.near * 2.0 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.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 # Mouse Data
# Last frame # Last frame
self.mouseLastX = self.mouseX self.mouseLastX = self.mouseX
self.mouseLastY = self.mouseY self.mouseLastY = self.mouseY
# This frame # Values for this frame
# Pixel coordinates of the mouse
self.mousePixelX = self.mouseData.getX() self.mousePixelX = self.mouseData.getX()
self.mousePixelY = self.mouseData.getY() self.mousePixelY = self.mouseData.getY()
# This ranges from -1 to 1
self.mouseX = ((self.mousePixelX / float(self.width)) * 2.0) - 1.0 self.mouseX = ((self.mousePixelX / float(self.width)) * 2.0) - 1.0
self.mouseY = ((self.mousePixelY / float(self.height)) * -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.mouseDeltaX = self.mouseX - self.mouseLastX
self.mouseDeltaY = self.mouseY - self.mouseLastY 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 # Continue the task
return Task.cont return Task.cont

View File

@ -4,9 +4,7 @@ from DirectSession import *
# If specified in the user's Configrc, create the direct session # If specified in the user's Configrc, create the direct session
if base.wantDIRECT: if base.wantDIRECT:
direct = base.direct = DirectSession() direct = base.direct = DirectSession()
chanCenter = direct.chanCenter
else: else:
# Otherwise set the values to None # Otherwise set the values to None
direct = base.direct = None direct = base.direct = None
chanCenter = None

View File

@ -51,12 +51,31 @@
self.hideSiblings() self.hideSiblings()
def remove(self): 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 # before node is deleted
messenger.send('preRemoveNodePath', [self]) messenger.send('preRemoveNodePath', [self])
# Remove nodePath # Remove nodePath
self.reparentTo(hidden) self.reparentTo(hidden)
self.removeNode() 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 # private methods

View File

@ -27,6 +27,9 @@ class ShowBase:
import Loader import Loader
self.initialState = NodeAttributes() 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.renderTop = NodePath(NamedNode('renderTop'))
self.render = self.renderTop.attachNewNode('render') self.render = self.renderTop.attachNewNode('render')
self.hidden = NodePath(NamedNode('hidden')) self.hidden = NodePath(NamedNode('hidden'))

View File

@ -10,5 +10,6 @@ render = base.render
hidden = base.hidden hidden = base.hidden
camera = base.camera camera = base.camera
loader = base.loader loader = base.loader
ostream = Notify.out()
run = base.run run = base.run
tkroot = base.tkroot tkroot = base.tkroot