mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-29 16:20:11 -04:00
*** empty log message ***
This commit is contained in:
parent
24110ec036
commit
c738d0f324
@ -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')
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 = "<noname>"
|
||||
print name
|
||||
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[0],
|
||||
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[1],
|
||||
print bobo.cq.getEntry(i).getIntoIntersectionPoint()[2]
|
||||
"""
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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'))
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user