mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
*** empty log message ***
This commit is contained in:
parent
be2b62c779
commit
9b44311ec2
@ -1,449 +1,448 @@
|
||||
from PandaObject import *
|
||||
|
||||
CAM_MOVE_DURATION = 1.0
|
||||
Y_AXIS = Vec3(0,1,0)
|
||||
|
||||
class DirectCameraControl(PandaObject):
|
||||
def __init__(self, direct):
|
||||
# Create the grid
|
||||
self.direct = direct
|
||||
self.chan = direct.chan
|
||||
self.camera = self.chan.camera
|
||||
self.orthoViewRoll = 0.0
|
||||
self.lastView = 0
|
||||
self.coa = Point3(0)
|
||||
self.coaMarker = loader.loadModel('models/misc/sphere')
|
||||
self.coaMarker.setColor(1,0,0)
|
||||
self.coaMarkerPos = Point3(0)
|
||||
self.relNodePath = render.attachNewNode(NamedNode('targetNode'))
|
||||
self.zeroBaseVec = VBase3(0)
|
||||
self.zeroVector = Vec3(0)
|
||||
self.centerVec = Vec3(0, 1, 0)
|
||||
self.zeroPoint = Point3(0)
|
||||
|
||||
def mouseFlyStart(self, chan):
|
||||
# Record starting mouse positions
|
||||
self.initMouseX = chan.mouseX
|
||||
self.initMouseY = chan.mouseY
|
||||
# Where are we in the channel?
|
||||
if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)):
|
||||
# MOUSE IS IN CENTRAL REGION
|
||||
# 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.pickGeom(
|
||||
render,chan.mouseX,chan.mouseY)
|
||||
# Filter out hidden nodes from entry list
|
||||
indexList = []
|
||||
for i in range(0,numEntries):
|
||||
entry = self.direct.iRay.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
if node.isHidden():
|
||||
pass
|
||||
else:
|
||||
# Not one of the widgets, use it
|
||||
indexList.append(i)
|
||||
coa = Point3(0)
|
||||
if(indexList):
|
||||
# Start off with first point
|
||||
minPt = indexList[0]
|
||||
# Find hit point in camera's space
|
||||
hitPt = self.direct.iRay.camToHitPt(minPt)
|
||||
coa.set(hitPt[0],hitPt[1],hitPt[2])
|
||||
coaDist = Vec3(coa - self.zeroPoint).length()
|
||||
# Check other intersection points, sorting them
|
||||
# TBD: Use TBS C++ function to do this
|
||||
if len(indexList) > 1:
|
||||
for i in range(1,len(indexList)):
|
||||
entryNum = indexList[i]
|
||||
hitPt = self.direct.iRay.camToHitPt(entryNum)
|
||||
dist = Vec3(hitPt - self.zeroPoint).length()
|
||||
if (dist < coaDist):
|
||||
coaDist = dist
|
||||
coa.set(hitPt[0],hitPt[1],hitPt[2])
|
||||
minPt = i
|
||||
|
||||
# Handle case of bad coa point (too close or too far)
|
||||
if ((coaDist < (1.1 * self.chan.near)) |
|
||||
(coaDist > self.chan.far)):
|
||||
# Put it out in front of the camera
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
else:
|
||||
# If no intersection point:
|
||||
# Put coa out in front of the camera
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
|
||||
# Update coa and marker
|
||||
self.updateCoa(coa, coaDist)
|
||||
# Now spawn task to determine mouse fly mode
|
||||
self.determineMouseFlyMode()
|
||||
# END MOUSE IN CENTRAL REGION
|
||||
else:
|
||||
# Mouse is in outer frame, spawn mouseRotateTask
|
||||
self.spawnMouseRotateTask()
|
||||
|
||||
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
|
||||
t = Task.Task(self.determineMouseFlyModeTask)
|
||||
taskMgr.spawnTaskNamed(t, 'determineMouseFlyMode')
|
||||
|
||||
def determineMouseFlyModeTask(self, state):
|
||||
deltaX = self.chan.mouseX - self.initMouseX
|
||||
deltaY = self.chan.mouseY - self.initMouseY
|
||||
if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)):
|
||||
return Task.cont
|
||||
else:
|
||||
if (abs(deltaY) > 0.1):
|
||||
self.spawnHPanYZoom()
|
||||
else:
|
||||
self.spawnXZTranslate()
|
||||
return Task.done
|
||||
|
||||
def updateCoa(self, cam2point, coaDist = None):
|
||||
self.coa.set(cam2point[0], cam2point[1], cam2point[2])
|
||||
if coaDist:
|
||||
self.coaDist = coaDist
|
||||
else:
|
||||
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.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())
|
||||
|
||||
def uprightCam(self, chan):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
currH = chan.camera.getH()
|
||||
chan.camera.lerpHpr(currH, 0, 0,
|
||||
CAM_MOVE_DURATION,
|
||||
other = render,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def centerCam(self, chan):
|
||||
# Chan is a display region context
|
||||
self.centerCamIn(chan, 1.0)
|
||||
|
||||
def centerCamNow(self, chan):
|
||||
self.centerCamIn(chan, 0.)
|
||||
|
||||
def centerCamIn(self, chan, t):
|
||||
# Chan is a display region context
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
markerToCam = self.coaMarker.getPos( chan.camera )
|
||||
dist = Vec3(markerToCam - self.zeroPoint).length()
|
||||
scaledCenterVec = self.centerVec * dist
|
||||
delta = markerToCam - scaledCenterVec
|
||||
self.relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0))
|
||||
chan.camera.lerpPos(Point3(delta),
|
||||
CAM_MOVE_DURATION,
|
||||
other = self.relNodePath,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def zoomCam(self, chan, zoomFactor, t):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Find a point zoom factor times the current separation
|
||||
# of the widget and cam
|
||||
zoomPtToCam = self.coaMarker.getPos(chan.camera) * zoomFactor
|
||||
# Put a target nodePath there
|
||||
self.relNodePath.setPos(chan.camera, zoomPtToCam)
|
||||
# Move to that point
|
||||
chan.camera.lerpPos(self.zeroPoint,
|
||||
CAM_MOVE_DURATION,
|
||||
other = self.relNodePath,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def SpawnMoveToView(self, chan, view):
|
||||
# Kill any existing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Calc hprOffset
|
||||
hprOffset = VBase3()
|
||||
if view == 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:
|
||||
hprOffset.set(0., 0., 0.)
|
||||
elif view == 3:
|
||||
hprOffset.set(90., 0., 0.)
|
||||
elif view == 4:
|
||||
hprOffset.set(-90., 0., 0.)
|
||||
elif view == 5:
|
||||
hprOffset.set(0., -90., 0.)
|
||||
elif view == 6:
|
||||
hprOffset.set(0., 90., 0.)
|
||||
elif view == 7:
|
||||
hprOffset.set(135., -35.264, 0.)
|
||||
# Position target
|
||||
self.relNodePath.setPosHpr(self.coaMarker, self.zeroBaseVec,
|
||||
hprOffset)
|
||||
# Scale center vec by current distance to target
|
||||
offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) -
|
||||
self.zeroPoint).length()
|
||||
scaledCenterVec = self.centerVec * (-1.0 * offsetDistance)
|
||||
# Now put the relNodePath at that point
|
||||
self.relNodePath.setPosHpr(self.relNodePath,
|
||||
scaledCenterVec,
|
||||
self.zeroBaseVec)
|
||||
# Record view for next time around
|
||||
self.lastView = view
|
||||
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
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
# Coincident with widget
|
||||
self.relNodePath.setPos(self.coaMarker, self.zeroPoint)
|
||||
# But aligned with render space
|
||||
self.relNodePath.setHpr(self.zeroPoint)
|
||||
|
||||
parent = self.camera.getParent()
|
||||
self.camera.wrtReparentTo(self.relNodePath)
|
||||
|
||||
manipTask = self.relNodePath.lerpHpr(VBase3(degrees,0,0),
|
||||
CAM_MOVE_DURATION,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
# Upon death, reparent Cam to parent
|
||||
manipTask.parent = parent
|
||||
manipTask.uponDeath = self.reparentCam
|
||||
|
||||
def reparentCam(self, state):
|
||||
self.camera.wrtReparentTo(state.parent)
|
||||
|
||||
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)
|
||||
t.targetVector = targetVector
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def HPanYZoomTask(self,state):
|
||||
targetVector = state.targetVector
|
||||
distToMove = targetVector * self.chan.mouseDeltaY
|
||||
self.camera.setPosHpr(self.camera,
|
||||
distToMove[0],
|
||||
distToMove[1],
|
||||
distToMove[2],
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
0.0, 0.0)
|
||||
return Task.cont
|
||||
|
||||
|
||||
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')
|
||||
|
||||
def XZTranslateOrHPPanTask(self, state):
|
||||
if self.direct.fShift:
|
||||
self.camera.setHpr(self.camera,
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.fovV),
|
||||
0.0)
|
||||
else:
|
||||
self.camera.setPos(self.camera,
|
||||
(-0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.nearWidth *
|
||||
state.scaleFactor),
|
||||
0.0,
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.nearHeight *
|
||||
state.scaleFactor))
|
||||
return Task.cont
|
||||
|
||||
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')
|
||||
|
||||
def XZTranslateTask(self,state):
|
||||
self.camera.setPos(self.camera,
|
||||
(-0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.nearWidth *
|
||||
state.scaleFactor),
|
||||
0.0,
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.nearHeight *
|
||||
state.scaleFactor))
|
||||
return Task.cont
|
||||
|
||||
def spawnMouseRotateTask(self):
|
||||
# Kill any existing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Set at markers position in render coordinates
|
||||
self.relNodePath.setPos(self.coaMarkerPos)
|
||||
self.relNodePath.setHpr(self.camera, self.zeroPoint)
|
||||
t = Task.Task(self.mouseRotateTask)
|
||||
t.wrtMat = self.camera.getMat( self.relNodePath )
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def mouseRotateTask(self, state):
|
||||
wrtMat = state.wrtMat
|
||||
self.relNodePath.setHpr(self.relNodePath,
|
||||
(-0.5 * self.chan.mouseDeltaX * 180.0),
|
||||
(0.5 * self.chan.mouseDeltaY * 180.0),
|
||||
0.0)
|
||||
self.camera.setMat(self.relNodePath, wrtMat)
|
||||
return Task.cont
|
||||
|
||||
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')
|
||||
|
||||
def HPPanTask(self, state):
|
||||
self.camera.setHpr(self.camera,
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.fovV),
|
||||
0.0)
|
||||
return Task.cont
|
||||
|
||||
def fitOnWidget(self):
|
||||
# Fit the node on the screen
|
||||
|
||||
# stop any ongoing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
# How big is the node?
|
||||
nodeScale = self.direct.widget.scalingNode.getScale(render)
|
||||
maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
|
||||
maxDim = min(self.chan.nearWidth, self.chan.nearHeight)
|
||||
|
||||
# At what distance does the object fill 30% of the screen?
|
||||
# Assuming radius of 1 on widget
|
||||
camY = self.chan.near * (2.0 * maxScale)/(0.3 * maxDim)
|
||||
|
||||
# What is the vector through the center of the screen?
|
||||
centerVec = Y_AXIS * camY
|
||||
|
||||
# Where is the node relative to the viewpoint
|
||||
vWidget2Camera = self.direct.widget.getPos(self.camera)
|
||||
|
||||
# How far do you move the camera to be this distance from the node?
|
||||
deltaMove = vWidget2Camera - centerVec
|
||||
|
||||
# Move a target there
|
||||
self.relNodePath.setPos(self.camera, deltaMove)
|
||||
|
||||
parent = self.camera.getParent()
|
||||
self.camera.wrtReparentTo(self.relNodePath)
|
||||
fitTask = self.camera.lerpPos(Point3(0,0,0),
|
||||
CAM_MOVE_DURATION,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
# Upon death, reparent Cam to parent
|
||||
fitTask.parent = parent
|
||||
fitTask.uponDeath = self.reparentCam
|
||||
|
||||
def enableMouseFly(self):
|
||||
self.enableMouseInteraction()
|
||||
self.enableHotKeys()
|
||||
self.coaMarker.reparentTo(render)
|
||||
|
||||
def enableMouseInteraction(self):
|
||||
# disable C++ fly interface
|
||||
base.disableMouse()
|
||||
# Accept middle mouse events
|
||||
self.accept('handleMouse2', self.mouseFlyStart, [self.chan])
|
||||
self.accept('handleMouse2Up', self.mouseFlyStop)
|
||||
|
||||
def enableHotKeys(self):
|
||||
t = CAM_MOVE_DURATION
|
||||
self.accept('u', self.uprightCam, [self.chan])
|
||||
self.accept('c', self.centerCamIn, [self.chan, 0.5])
|
||||
self.accept('h', self.homeCam, [self.chan])
|
||||
self.accept('f', self.fitOnWidget)
|
||||
for i in range(1,9):
|
||||
self.accept(`i`, self.SpawnMoveToView, [self.chan, i])
|
||||
self.accept('9', self.swingCamAboutWidget, [self.chan, -90.0, t])
|
||||
self.accept('0', self.swingCamAboutWidget, [self.chan, 90.0, t])
|
||||
self.accept('`', self.removeManipulateCameraTask)
|
||||
self.accept('=', self.zoomCam, [self.chan, 0.5, t])
|
||||
self.accept('+', self.zoomCam, [self.chan, 0.5, t])
|
||||
self.accept('-', self.zoomCam, [self.chan, -2.0, t])
|
||||
self.accept('_', self.zoomCam, [self.chan, -2.0, t])
|
||||
|
||||
def disableMouseFly(self):
|
||||
# Hide the marker
|
||||
self.coaMarker.reparentTo(hidden)
|
||||
# Ignore middle mouse events
|
||||
self.ignore('handleMouse2')
|
||||
self.ignore('handleMouse2Up')
|
||||
self.ignore('u')
|
||||
self.ignore('c')
|
||||
self.ignore('h')
|
||||
self.ignore('f')
|
||||
for i in range(0,10):
|
||||
self.ignore(`i`)
|
||||
self.ignore('=')
|
||||
self.ignore('+')
|
||||
self.ignore('-')
|
||||
self.ignore('_')
|
||||
self.ignore('`')
|
||||
|
||||
def removeManipulateCameraTask(self):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
from PandaObject import *
|
||||
|
||||
CAM_MOVE_DURATION = 1.0
|
||||
Y_AXIS = Vec3(0,1,0)
|
||||
|
||||
class DirectCameraControl(PandaObject):
|
||||
def __init__(self):
|
||||
# Create the grid
|
||||
self.chan = direct.chan
|
||||
self.camera = self.chan.camera
|
||||
self.orthoViewRoll = 0.0
|
||||
self.lastView = 0
|
||||
self.coa = Point3(0)
|
||||
self.coaMarker = loader.loadModel('models/misc/sphere')
|
||||
self.coaMarker.setColor(1,0,0)
|
||||
self.coaMarkerPos = Point3(0)
|
||||
self.relNodePath = render.attachNewNode(NamedNode('targetNode'))
|
||||
self.zeroBaseVec = VBase3(0)
|
||||
self.zeroVector = Vec3(0)
|
||||
self.centerVec = Vec3(0, 1, 0)
|
||||
self.zeroPoint = Point3(0)
|
||||
|
||||
def mouseFlyStart(self, chan):
|
||||
# Record starting mouse positions
|
||||
self.initMouseX = chan.mouseX
|
||||
self.initMouseY = chan.mouseY
|
||||
# Where are we in the channel?
|
||||
if ((abs(self.initMouseX) < 0.9) & (abs(self.initMouseY) < 0.9)):
|
||||
# MOUSE IS IN CENTRAL REGION
|
||||
# Hide the marker for this kind of motion
|
||||
self.coaMarker.hide()
|
||||
# See if the shift key is pressed
|
||||
if (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 = direct.iRay.pickGeom(
|
||||
render,chan.mouseX,chan.mouseY)
|
||||
# Filter out hidden nodes from entry list
|
||||
indexList = []
|
||||
for i in range(0,numEntries):
|
||||
entry = direct.iRay.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
if node.isHidden():
|
||||
pass
|
||||
else:
|
||||
# Not one of the widgets, use it
|
||||
indexList.append(i)
|
||||
coa = Point3(0)
|
||||
if(indexList):
|
||||
# Start off with first point
|
||||
minPt = indexList[0]
|
||||
# Find hit point in camera's space
|
||||
hitPt = direct.iRay.camToHitPt(minPt)
|
||||
coa.set(hitPt[0],hitPt[1],hitPt[2])
|
||||
coaDist = Vec3(coa - self.zeroPoint).length()
|
||||
# Check other intersection points, sorting them
|
||||
# TBD: Use TBS C++ function to do this
|
||||
if len(indexList) > 1:
|
||||
for i in range(1,len(indexList)):
|
||||
entryNum = indexList[i]
|
||||
hitPt = direct.iRay.camToHitPt(entryNum)
|
||||
dist = Vec3(hitPt - self.zeroPoint).length()
|
||||
if (dist < coaDist):
|
||||
coaDist = dist
|
||||
coa.set(hitPt[0],hitPt[1],hitPt[2])
|
||||
minPt = i
|
||||
|
||||
# Handle case of bad coa point (too close or too far)
|
||||
if ((coaDist < (1.1 * self.chan.near)) |
|
||||
(coaDist > self.chan.far)):
|
||||
# Put it out in front of the camera
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
else:
|
||||
# If no intersection point:
|
||||
# Put coa out in front of the camera
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
|
||||
# Update coa and marker
|
||||
self.updateCoa(coa, coaDist)
|
||||
# Now spawn task to determine mouse fly mode
|
||||
self.determineMouseFlyMode()
|
||||
# END MOUSE IN CENTRAL REGION
|
||||
else:
|
||||
# Mouse is in outer frame, spawn mouseRotateTask
|
||||
self.spawnMouseRotateTask()
|
||||
|
||||
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
|
||||
t = Task.Task(self.determineMouseFlyModeTask)
|
||||
taskMgr.spawnTaskNamed(t, 'determineMouseFlyMode')
|
||||
|
||||
def determineMouseFlyModeTask(self, state):
|
||||
deltaX = self.chan.mouseX - self.initMouseX
|
||||
deltaY = self.chan.mouseY - self.initMouseY
|
||||
if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)):
|
||||
return Task.cont
|
||||
else:
|
||||
if (abs(deltaY) > 0.1):
|
||||
self.spawnHPanYZoom()
|
||||
else:
|
||||
self.spawnXZTranslate()
|
||||
return Task.done
|
||||
|
||||
def updateCoa(self, cam2point, coaDist = None):
|
||||
self.coa.set(cam2point[0], cam2point[1], cam2point[2])
|
||||
if coaDist:
|
||||
self.coaDist = coaDist
|
||||
else:
|
||||
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.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())
|
||||
|
||||
def uprightCam(self, chan):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
currH = chan.camera.getH()
|
||||
chan.camera.lerpHpr(currH, 0, 0,
|
||||
CAM_MOVE_DURATION,
|
||||
other = render,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def centerCam(self, chan):
|
||||
# Chan is a display region context
|
||||
self.centerCamIn(chan, 1.0)
|
||||
|
||||
def centerCamNow(self, chan):
|
||||
self.centerCamIn(chan, 0.)
|
||||
|
||||
def centerCamIn(self, chan, t):
|
||||
# Chan is a display region context
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
markerToCam = self.coaMarker.getPos( chan.camera )
|
||||
dist = Vec3(markerToCam - self.zeroPoint).length()
|
||||
scaledCenterVec = self.centerVec * dist
|
||||
delta = markerToCam - scaledCenterVec
|
||||
self.relNodePath.setPosHpr(chan.camera, Point3(0), Point3(0))
|
||||
chan.camera.lerpPos(Point3(delta),
|
||||
CAM_MOVE_DURATION,
|
||||
other = self.relNodePath,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def zoomCam(self, chan, zoomFactor, t):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Find a point zoom factor times the current separation
|
||||
# of the widget and cam
|
||||
zoomPtToCam = self.coaMarker.getPos(chan.camera) * zoomFactor
|
||||
# Put a target nodePath there
|
||||
self.relNodePath.setPos(chan.camera, zoomPtToCam)
|
||||
# Move to that point
|
||||
chan.camera.lerpPos(self.zeroPoint,
|
||||
CAM_MOVE_DURATION,
|
||||
other = self.relNodePath,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
|
||||
def SpawnMoveToView(self, chan, view):
|
||||
# Kill any existing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Calc hprOffset
|
||||
hprOffset = VBase3()
|
||||
if view == 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:
|
||||
hprOffset.set(0., 0., 0.)
|
||||
elif view == 3:
|
||||
hprOffset.set(90., 0., 0.)
|
||||
elif view == 4:
|
||||
hprOffset.set(-90., 0., 0.)
|
||||
elif view == 5:
|
||||
hprOffset.set(0., -90., 0.)
|
||||
elif view == 6:
|
||||
hprOffset.set(0., 90., 0.)
|
||||
elif view == 7:
|
||||
hprOffset.set(135., -35.264, 0.)
|
||||
# Position target
|
||||
self.relNodePath.setPosHpr(self.coaMarker, self.zeroBaseVec,
|
||||
hprOffset)
|
||||
# Scale center vec by current distance to target
|
||||
offsetDistance = Vec3(chan.camera.getPos(self.relNodePath) -
|
||||
self.zeroPoint).length()
|
||||
scaledCenterVec = self.centerVec * (-1.0 * offsetDistance)
|
||||
# Now put the relNodePath at that point
|
||||
self.relNodePath.setPosHpr(self.relNodePath,
|
||||
scaledCenterVec,
|
||||
self.zeroBaseVec)
|
||||
# Record view for next time around
|
||||
self.lastView = view
|
||||
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
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
# Coincident with widget
|
||||
self.relNodePath.setPos(self.coaMarker, self.zeroPoint)
|
||||
# But aligned with render space
|
||||
self.relNodePath.setHpr(self.zeroPoint)
|
||||
|
||||
parent = self.camera.getParent()
|
||||
self.camera.wrtReparentTo(self.relNodePath)
|
||||
|
||||
manipTask = self.relNodePath.lerpHpr(VBase3(degrees,0,0),
|
||||
CAM_MOVE_DURATION,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
# Upon death, reparent Cam to parent
|
||||
manipTask.parent = parent
|
||||
manipTask.uponDeath = self.reparentCam
|
||||
|
||||
def reparentCam(self, state):
|
||||
self.camera.wrtReparentTo(state.parent)
|
||||
|
||||
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)
|
||||
t.targetVector = targetVector
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def HPanYZoomTask(self,state):
|
||||
targetVector = state.targetVector
|
||||
distToMove = targetVector * self.chan.mouseDeltaY
|
||||
self.camera.setPosHpr(self.camera,
|
||||
distToMove[0],
|
||||
distToMove[1],
|
||||
distToMove[2],
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
0.0, 0.0)
|
||||
return Task.cont
|
||||
|
||||
|
||||
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')
|
||||
|
||||
def XZTranslateOrHPPanTask(self, state):
|
||||
if direct.fShift:
|
||||
self.camera.setHpr(self.camera,
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.fovV),
|
||||
0.0)
|
||||
else:
|
||||
self.camera.setPos(self.camera,
|
||||
(-0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.nearWidth *
|
||||
state.scaleFactor),
|
||||
0.0,
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.nearHeight *
|
||||
state.scaleFactor))
|
||||
return Task.cont
|
||||
|
||||
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')
|
||||
|
||||
def XZTranslateTask(self,state):
|
||||
self.camera.setPos(self.camera,
|
||||
(-0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.nearWidth *
|
||||
state.scaleFactor),
|
||||
0.0,
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.nearHeight *
|
||||
state.scaleFactor))
|
||||
return Task.cont
|
||||
|
||||
def spawnMouseRotateTask(self):
|
||||
# Kill any existing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Set at markers position in render coordinates
|
||||
self.relNodePath.setPos(self.coaMarkerPos)
|
||||
self.relNodePath.setHpr(self.camera, self.zeroPoint)
|
||||
t = Task.Task(self.mouseRotateTask)
|
||||
t.wrtMat = self.camera.getMat( self.relNodePath )
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def mouseRotateTask(self, state):
|
||||
wrtMat = state.wrtMat
|
||||
self.relNodePath.setHpr(self.relNodePath,
|
||||
(-0.5 * self.chan.mouseDeltaX * 180.0),
|
||||
(0.5 * self.chan.mouseDeltaY * 180.0),
|
||||
0.0)
|
||||
self.camera.setMat(self.relNodePath, wrtMat)
|
||||
return Task.cont
|
||||
|
||||
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')
|
||||
|
||||
def HPPanTask(self, state):
|
||||
self.camera.setHpr(self.camera,
|
||||
(0.5 * self.chan.mouseDeltaX *
|
||||
self.chan.fovH),
|
||||
(-0.5 * self.chan.mouseDeltaY *
|
||||
self.chan.fovV),
|
||||
0.0)
|
||||
return Task.cont
|
||||
|
||||
def fitOnWidget(self):
|
||||
# Fit the node on the screen
|
||||
|
||||
# stop any ongoing tasks
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
# How big is the node?
|
||||
nodeScale = direct.widget.scalingNode.getScale(render)
|
||||
maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
|
||||
maxDim = min(self.chan.nearWidth, self.chan.nearHeight)
|
||||
|
||||
# At what distance does the object fill 30% of the screen?
|
||||
# Assuming radius of 1 on widget
|
||||
camY = self.chan.near * (2.0 * maxScale)/(0.3 * maxDim)
|
||||
|
||||
# What is the vector through the center of the screen?
|
||||
centerVec = Y_AXIS * camY
|
||||
|
||||
# Where is the node relative to the viewpoint
|
||||
vWidget2Camera = direct.widget.getPos(self.camera)
|
||||
|
||||
# How far do you move the camera to be this distance from the node?
|
||||
deltaMove = vWidget2Camera - centerVec
|
||||
|
||||
# Move a target there
|
||||
self.relNodePath.setPos(self.camera, deltaMove)
|
||||
|
||||
parent = self.camera.getParent()
|
||||
self.camera.wrtReparentTo(self.relNodePath)
|
||||
fitTask = self.camera.lerpPos(Point3(0,0,0),
|
||||
CAM_MOVE_DURATION,
|
||||
blendType = 'easeInOut',
|
||||
task = 'manipulateCamera')
|
||||
# Upon death, reparent Cam to parent
|
||||
fitTask.parent = parent
|
||||
fitTask.uponDeath = self.reparentCam
|
||||
|
||||
def enableMouseFly(self):
|
||||
self.enableMouseInteraction()
|
||||
self.enableHotKeys()
|
||||
self.coaMarker.reparentTo(render)
|
||||
|
||||
def enableMouseInteraction(self):
|
||||
# disable C++ fly interface
|
||||
base.disableMouse()
|
||||
# Accept middle mouse events
|
||||
self.accept('handleMouse2', self.mouseFlyStart, [self.chan])
|
||||
self.accept('handleMouse2Up', self.mouseFlyStop)
|
||||
|
||||
def enableHotKeys(self):
|
||||
t = CAM_MOVE_DURATION
|
||||
self.accept('u', self.uprightCam, [self.chan])
|
||||
self.accept('c', self.centerCamIn, [self.chan, 0.5])
|
||||
self.accept('h', self.homeCam, [self.chan])
|
||||
self.accept('f', self.fitOnWidget)
|
||||
for i in range(1,9):
|
||||
self.accept(`i`, self.SpawnMoveToView, [self.chan, i])
|
||||
self.accept('9', self.swingCamAboutWidget, [self.chan, -90.0, t])
|
||||
self.accept('0', self.swingCamAboutWidget, [self.chan, 90.0, t])
|
||||
self.accept('`', self.removeManipulateCameraTask)
|
||||
self.accept('=', self.zoomCam, [self.chan, 0.5, t])
|
||||
self.accept('+', self.zoomCam, [self.chan, 0.5, t])
|
||||
self.accept('-', self.zoomCam, [self.chan, -2.0, t])
|
||||
self.accept('_', self.zoomCam, [self.chan, -2.0, t])
|
||||
|
||||
def disableMouseFly(self):
|
||||
# Hide the marker
|
||||
self.coaMarker.reparentTo(hidden)
|
||||
# Ignore middle mouse events
|
||||
self.ignore('handleMouse2')
|
||||
self.ignore('handleMouse2Up')
|
||||
self.ignore('u')
|
||||
self.ignore('c')
|
||||
self.ignore('h')
|
||||
self.ignore('f')
|
||||
for i in range(0,10):
|
||||
self.ignore(`i`)
|
||||
self.ignore('=')
|
||||
self.ignore('+')
|
||||
self.ignore('-')
|
||||
self.ignore('_')
|
||||
self.ignore('`')
|
||||
|
||||
def removeManipulateCameraTask(self):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
|
||||
|
@ -2,14 +2,11 @@ from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
|
||||
class DirectGrid(NodePath,PandaObject):
|
||||
def __init__(self, direct):
|
||||
def __init__(self):
|
||||
# Initialize superclass
|
||||
NodePath.__init__(self)
|
||||
self.assign(hidden.attachNewNode( NamedNode('DirectGrid')))
|
||||
|
||||
# Record handle to direct session
|
||||
self.direct = direct
|
||||
|
||||
# Load up grid parts to initialize grid object
|
||||
# Polygon used to mark grid plane
|
||||
self.gridBack = loader.loadModel('models/misc/gridBack')
|
||||
@ -60,7 +57,7 @@ class DirectGrid(NodePath,PandaObject):
|
||||
|
||||
def selectGridBackParent(self, nodePath):
|
||||
if nodePath.getName() == 'GridBack':
|
||||
self.direct.select(self)
|
||||
direct.select(self)
|
||||
|
||||
def updateGrid(self):
|
||||
# Update grid lines based upon current grid spacing and grid size
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,380 +1,379 @@
|
||||
from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import *
|
||||
|
||||
|
||||
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.getName()
|
||||
# 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())
|
||||
|
||||
def highlight(self):
|
||||
self.bbox.show()
|
||||
|
||||
def dehighlight(self):
|
||||
self.bbox.hide()
|
||||
|
||||
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.id()
|
||||
# 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.id()
|
||||
# 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])
|
||||
return list
|
||||
|
||||
def __getitem__(self,index):
|
||||
return self.selectedAsList()[index]
|
||||
|
||||
def deselectedAsList(self):
|
||||
list = []
|
||||
for key in self.deselectedDict.keys():
|
||||
list.append(self.deselectedDict[key])
|
||||
return list
|
||||
|
||||
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.id()
|
||||
# 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:
|
||||
def __init__(self, nodePath):
|
||||
# Record the node path
|
||||
self.nodePath = nodePath
|
||||
# Compute bounds, min, max, etc.
|
||||
self.computeBounds()
|
||||
# Generate the bounding box
|
||||
self.lines = self.createBBoxLines()
|
||||
|
||||
def computeBounds(self):
|
||||
self.bounds = self.nodePath.getBounds()
|
||||
if self.bounds.isEmpty():
|
||||
self.center = Point3(0)
|
||||
self.radius = 1.0
|
||||
else:
|
||||
self.center = self.bounds.getCenter()
|
||||
self.radius = self.bounds.getRadius()
|
||||
self.min = Point3(self.center - Point3(self.radius))
|
||||
self.max = Point3(self.center + Point3(self.radius))
|
||||
|
||||
def createBBoxLines(self):
|
||||
# Create a line segments object for the bbox
|
||||
lines = LineNodePath(hidden)
|
||||
lines.node().setName('bboxLines')
|
||||
lines.setColor( VBase4( 1., 0., 0., 1. ) )
|
||||
lines.setThickness( 0.5 )
|
||||
|
||||
minX = self.min[0]
|
||||
minY = self.min[1]
|
||||
minZ = self.min[2]
|
||||
maxX = self.max[0]
|
||||
maxY = self.max[1]
|
||||
maxZ = self.max[2]
|
||||
|
||||
# Bottom face
|
||||
lines.moveTo( minX, minY, minZ )
|
||||
lines.drawTo( maxX, minY, minZ )
|
||||
lines.drawTo( maxX, maxY, minZ )
|
||||
lines.drawTo( minX, maxY, minZ )
|
||||
lines.drawTo( minX, minY, minZ )
|
||||
|
||||
# Front Edge/Top face
|
||||
lines.drawTo( minX, minY, maxZ )
|
||||
lines.drawTo( maxX, minY, maxZ )
|
||||
lines.drawTo( maxX, maxY, maxZ )
|
||||
lines.drawTo( minX, maxY, maxZ )
|
||||
lines.drawTo( minX, minY, maxZ )
|
||||
|
||||
# Three remaining edges
|
||||
lines.moveTo( maxX, minY, minZ )
|
||||
lines.drawTo( maxX, minY, maxZ )
|
||||
lines.moveTo( maxX, maxY, minZ )
|
||||
lines.drawTo( maxX, maxY, maxZ )
|
||||
lines.moveTo( minX, maxY, minZ )
|
||||
lines.drawTo( minX, maxY, maxZ )
|
||||
|
||||
# Create and return bbox lines
|
||||
lines.create()
|
||||
return lines
|
||||
|
||||
def updateBBoxLines(self):
|
||||
ls = self.lines.lineSegs
|
||||
|
||||
minX = self.min[0]
|
||||
minY = self.min[1]
|
||||
minZ = self.min[2]
|
||||
maxX = self.max[0]
|
||||
maxY = self.max[1]
|
||||
maxZ = self.max[2]
|
||||
|
||||
# Bottom face
|
||||
ls.setVertex( 0, minX, minY, minZ )
|
||||
ls.setVertex( 1, maxX, minY, minZ )
|
||||
ls.setVertex( 2, maxX, maxY, minZ )
|
||||
ls.setVertex( 3, minX, maxY, minZ )
|
||||
ls.setVertex( 4, minX, minY, minZ )
|
||||
|
||||
# Front Edge/Top face
|
||||
ls.setVertex( 5, minX, minY, maxZ )
|
||||
ls.setVertex( 6, maxX, minY, maxZ )
|
||||
ls.setVertex( 7, maxX, maxY, maxZ )
|
||||
ls.setVertex( 8, minX, maxY, maxZ )
|
||||
ls.setVertex( 9, minX, minY, maxZ )
|
||||
|
||||
# Three remaining edges
|
||||
ls.setVertex( 10, maxX, minY, minZ )
|
||||
ls.setVertex( 11, maxX, minY, maxZ )
|
||||
ls.setVertex( 12, maxX, maxY, minZ )
|
||||
ls.setVertex( 13, maxX, maxY, maxZ )
|
||||
ls.setVertex( 14, minX, maxY, minZ )
|
||||
ls.setVertex( 15, minX, maxY, maxZ )
|
||||
|
||||
def getBounds(self):
|
||||
# Get a node path's bounds
|
||||
nodeBounds = self.nodePath.node().getBound()
|
||||
for child in self.nodePath.getChildrenAsList():
|
||||
nodeBounds.extendBy(child.getBottomArc().getBound())
|
||||
return nodeBounds.makeCopy()
|
||||
|
||||
def show(self):
|
||||
self.lines.reparentTo(self.nodePath)
|
||||
|
||||
def hide(self):
|
||||
self.lines.reparentTo(hidden)
|
||||
|
||||
def getCenter(self):
|
||||
return self.center
|
||||
|
||||
def getRadius(self):
|
||||
return self.radius
|
||||
|
||||
def getMin(self):
|
||||
return self.min
|
||||
|
||||
def getMax(self):
|
||||
return self.max
|
||||
|
||||
def vecAsString(self, vec):
|
||||
return '%.2f %.2f %.2f' % (vec[0], vec[1], vec[2])
|
||||
|
||||
def __repr__(self):
|
||||
return (`self.__class__` +
|
||||
'\nNodePath:\t%s\n' % self.nodePath.getName() +
|
||||
'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) +
|
||||
'Radius:\t\t%.2f' % self.radius
|
||||
)
|
||||
|
||||
|
||||
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 pickGeom(self, targetNodePath, mouseX, mouseY):
|
||||
self.collideWithGeom()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
|
||||
def pickWidget(self, targetNodePath, mouseX, mouseY):
|
||||
self.collideWithWidget()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
|
||||
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()
|
||||
self.cq.sortEntries()
|
||||
return self.numEntries
|
||||
|
||||
def collideWithGeom(self):
|
||||
self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
|
||||
self.rayCollisionNode.setFromCollideMask(BitMask32().allOff())
|
||||
self.rayCollisionNode.setCollideGeom(1)
|
||||
|
||||
def collideWithWidget(self):
|
||||
self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
|
||||
mask = BitMask32()
|
||||
mask.setWord(0x80000000)
|
||||
self.rayCollisionNode.setFromCollideMask(mask)
|
||||
self.rayCollisionNode.setCollideGeom(0)
|
||||
|
||||
def objectToHitPt(self, index):
|
||||
return self.cq.getEntry(index).getIntoIntersectionPoint()
|
||||
|
||||
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)
|
||||
|
||||
from PandaObject import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import *
|
||||
|
||||
|
||||
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.getName()
|
||||
# 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())
|
||||
|
||||
def highlight(self):
|
||||
self.bbox.show()
|
||||
|
||||
def dehighlight(self):
|
||||
self.bbox.hide()
|
||||
|
||||
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):
|
||||
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.id()
|
||||
# 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.id()
|
||||
# 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])
|
||||
return list
|
||||
|
||||
def __getitem__(self,index):
|
||||
return self.selectedAsList()[index]
|
||||
|
||||
def deselectedAsList(self):
|
||||
list = []
|
||||
for key in self.deselectedDict.keys():
|
||||
list.append(self.deselectedDict[key])
|
||||
return list
|
||||
|
||||
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(direct.widget))
|
||||
|
||||
def moveWrtWidgetAll(self):
|
||||
self.forEachSelectedNodePathDo(self.moveWrtWidget)
|
||||
|
||||
def moveWrtWidget(self, nodePath):
|
||||
nodePath.setMat(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.id()
|
||||
# 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:
|
||||
def __init__(self, nodePath):
|
||||
# Record the node path
|
||||
self.nodePath = nodePath
|
||||
# Compute bounds, min, max, etc.
|
||||
self.computeBounds()
|
||||
# Generate the bounding box
|
||||
self.lines = self.createBBoxLines()
|
||||
|
||||
def computeBounds(self):
|
||||
self.bounds = self.nodePath.getBounds()
|
||||
if self.bounds.isEmpty():
|
||||
self.center = Point3(0)
|
||||
self.radius = 1.0
|
||||
else:
|
||||
self.center = self.bounds.getCenter()
|
||||
self.radius = self.bounds.getRadius()
|
||||
self.min = Point3(self.center - Point3(self.radius))
|
||||
self.max = Point3(self.center + Point3(self.radius))
|
||||
|
||||
def createBBoxLines(self):
|
||||
# Create a line segments object for the bbox
|
||||
lines = LineNodePath(hidden)
|
||||
lines.node().setName('bboxLines')
|
||||
lines.setColor( VBase4( 1., 0., 0., 1. ) )
|
||||
lines.setThickness( 0.5 )
|
||||
|
||||
minX = self.min[0]
|
||||
minY = self.min[1]
|
||||
minZ = self.min[2]
|
||||
maxX = self.max[0]
|
||||
maxY = self.max[1]
|
||||
maxZ = self.max[2]
|
||||
|
||||
# Bottom face
|
||||
lines.moveTo( minX, minY, minZ )
|
||||
lines.drawTo( maxX, minY, minZ )
|
||||
lines.drawTo( maxX, maxY, minZ )
|
||||
lines.drawTo( minX, maxY, minZ )
|
||||
lines.drawTo( minX, minY, minZ )
|
||||
|
||||
# Front Edge/Top face
|
||||
lines.drawTo( minX, minY, maxZ )
|
||||
lines.drawTo( maxX, minY, maxZ )
|
||||
lines.drawTo( maxX, maxY, maxZ )
|
||||
lines.drawTo( minX, maxY, maxZ )
|
||||
lines.drawTo( minX, minY, maxZ )
|
||||
|
||||
# Three remaining edges
|
||||
lines.moveTo( maxX, minY, minZ )
|
||||
lines.drawTo( maxX, minY, maxZ )
|
||||
lines.moveTo( maxX, maxY, minZ )
|
||||
lines.drawTo( maxX, maxY, maxZ )
|
||||
lines.moveTo( minX, maxY, minZ )
|
||||
lines.drawTo( minX, maxY, maxZ )
|
||||
|
||||
# Create and return bbox lines
|
||||
lines.create()
|
||||
return lines
|
||||
|
||||
def updateBBoxLines(self):
|
||||
ls = self.lines.lineSegs
|
||||
|
||||
minX = self.min[0]
|
||||
minY = self.min[1]
|
||||
minZ = self.min[2]
|
||||
maxX = self.max[0]
|
||||
maxY = self.max[1]
|
||||
maxZ = self.max[2]
|
||||
|
||||
# Bottom face
|
||||
ls.setVertex( 0, minX, minY, minZ )
|
||||
ls.setVertex( 1, maxX, minY, minZ )
|
||||
ls.setVertex( 2, maxX, maxY, minZ )
|
||||
ls.setVertex( 3, minX, maxY, minZ )
|
||||
ls.setVertex( 4, minX, minY, minZ )
|
||||
|
||||
# Front Edge/Top face
|
||||
ls.setVertex( 5, minX, minY, maxZ )
|
||||
ls.setVertex( 6, maxX, minY, maxZ )
|
||||
ls.setVertex( 7, maxX, maxY, maxZ )
|
||||
ls.setVertex( 8, minX, maxY, maxZ )
|
||||
ls.setVertex( 9, minX, minY, maxZ )
|
||||
|
||||
# Three remaining edges
|
||||
ls.setVertex( 10, maxX, minY, minZ )
|
||||
ls.setVertex( 11, maxX, minY, maxZ )
|
||||
ls.setVertex( 12, maxX, maxY, minZ )
|
||||
ls.setVertex( 13, maxX, maxY, maxZ )
|
||||
ls.setVertex( 14, minX, maxY, minZ )
|
||||
ls.setVertex( 15, minX, maxY, maxZ )
|
||||
|
||||
def getBounds(self):
|
||||
# Get a node path's bounds
|
||||
nodeBounds = self.nodePath.node().getBound()
|
||||
for child in self.nodePath.getChildrenAsList():
|
||||
nodeBounds.extendBy(child.getBottomArc().getBound())
|
||||
return nodeBounds.makeCopy()
|
||||
|
||||
def show(self):
|
||||
self.lines.reparentTo(self.nodePath)
|
||||
|
||||
def hide(self):
|
||||
self.lines.reparentTo(hidden)
|
||||
|
||||
def getCenter(self):
|
||||
return self.center
|
||||
|
||||
def getRadius(self):
|
||||
return self.radius
|
||||
|
||||
def getMin(self):
|
||||
return self.min
|
||||
|
||||
def getMax(self):
|
||||
return self.max
|
||||
|
||||
def vecAsString(self, vec):
|
||||
return '%.2f %.2f %.2f' % (vec[0], vec[1], vec[2])
|
||||
|
||||
def __repr__(self):
|
||||
return (`self.__class__` +
|
||||
'\nNodePath:\t%s\n' % self.nodePath.getName() +
|
||||
'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) +
|
||||
'Radius:\t\t%.2f' % self.radius
|
||||
)
|
||||
|
||||
|
||||
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 pickGeom(self, targetNodePath, mouseX, mouseY):
|
||||
self.collideWithGeom()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
|
||||
def pickWidget(self, targetNodePath, mouseX, mouseY):
|
||||
self.collideWithWidget()
|
||||
return self.pick(targetNodePath, mouseX, mouseY)
|
||||
|
||||
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()
|
||||
self.cq.sortEntries()
|
||||
return self.numEntries
|
||||
|
||||
def collideWithGeom(self):
|
||||
self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
|
||||
self.rayCollisionNode.setFromCollideMask(BitMask32().allOff())
|
||||
self.rayCollisionNode.setCollideGeom(1)
|
||||
|
||||
def collideWithWidget(self):
|
||||
self.rayCollisionNode.setIntoCollideMask(BitMask32().allOff())
|
||||
mask = BitMask32()
|
||||
mask.setWord(0x80000000)
|
||||
self.rayCollisionNode.setFromCollideMask(mask)
|
||||
self.rayCollisionNode.setCollideGeom(0)
|
||||
|
||||
def objectToHitPt(self, index):
|
||||
return self.cq.getEntry(index).getIntoIntersectionPoint()
|
||||
|
||||
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)
|
||||
|
||||
|
@ -5,10 +5,14 @@ from DirectSelection import *
|
||||
from DirectGrid import *
|
||||
from DirectGeometry import *
|
||||
import OnscreenText
|
||||
import __builtin__
|
||||
|
||||
class DirectSession(PandaObject):
|
||||
|
||||
def __init__(self):
|
||||
# Establish a global pointer to the direct object early on
|
||||
# so dependant classes can access it in their code
|
||||
__builtin__.direct = self
|
||||
self.contextList = []
|
||||
self.iRayList = []
|
||||
for camera in base.cameraList:
|
||||
@ -17,14 +21,14 @@ class DirectSession(PandaObject):
|
||||
self.chan = self.getChanData(0)
|
||||
self.camera = base.cameraList[0]
|
||||
|
||||
self.cameraControl = DirectCameraControl(self)
|
||||
self.manipulationControl = DirectManipulationControl(self)
|
||||
self.cameraControl = DirectCameraControl()
|
||||
self.manipulationControl = DirectManipulationControl()
|
||||
self.useObjectHandles()
|
||||
self.grid = DirectGrid(self)
|
||||
self.grid = DirectGrid()
|
||||
self.grid.disable()
|
||||
|
||||
# Initialize the collection of selected nodePaths
|
||||
self.selected = SelectedNodePaths(self)
|
||||
self.selected = SelectedNodePaths()
|
||||
|
||||
self.readout = OnscreenText.OnscreenText( '', 0.1, -0.95 )
|
||||
# self.readout.textNode.setCardColor(0.5, 0.5, 0.5, 0.5)
|
||||
|
@ -1,10 +1,11 @@
|
||||
from ShowBaseGlobal import *
|
||||
|
||||
# If specified in the user's Configrc, create the direct session
|
||||
if base.wantDIRECT:
|
||||
from DirectSession import *
|
||||
direct = base.direct = DirectSession()
|
||||
else:
|
||||
# Otherwise set the values to None
|
||||
direct = base.direct = None
|
||||
|
||||
from ShowBaseGlobal import *
|
||||
import __builtin__
|
||||
|
||||
# If specified in the user's Configrc, create the direct session
|
||||
if base.wantDIRECT:
|
||||
from DirectSession import *
|
||||
__builtin__.direct = base.direct = DirectSession()
|
||||
else:
|
||||
# Otherwise set the values to None
|
||||
__builtin__.direct = base.direct = None
|
||||
|
||||
|
@ -1,15 +1,16 @@
|
||||
"""instantiate global ShowBase object"""
|
||||
|
||||
from ShowBase import *
|
||||
import __builtin__
|
||||
|
||||
base = ShowBase()
|
||||
__builtin__.base = ShowBase()
|
||||
|
||||
# Make some global aliases for convenience
|
||||
render2d = base.render2d
|
||||
render = base.render
|
||||
hidden = base.hidden
|
||||
camera = base.camera
|
||||
loader = base.loader
|
||||
ostream = Notify.out()
|
||||
run = base.run
|
||||
tkroot = base.tkroot
|
||||
__builtin__.render2d = base.render2d
|
||||
__builtin__.render = base.render
|
||||
__builtin__.hidden = base.hidden
|
||||
__builtin__.camera = base.camera
|
||||
__builtin__.loader = base.loader
|
||||
__builtin__.ostream = Notify.out()
|
||||
__builtin__.run = base.run
|
||||
__builtin__.tkroot = base.tkroot
|
||||
|
Loading…
x
Reference in New Issue
Block a user