mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 02:15:43 -04:00
*** empty log message ***
This commit is contained in:
parent
1a1b9ae9c2
commit
8ecb2f612c
@ -1,5 +1,5 @@
|
|||||||
from PandaObject import *
|
from PandaObject import *
|
||||||
from DirectGeometry import useDirectRenderStyle
|
from DirectGeometry import *
|
||||||
|
|
||||||
CAM_MOVE_DURATION = 1.0
|
CAM_MOVE_DURATION = 1.0
|
||||||
COA_MARKER_SF = 0.0075
|
COA_MARKER_SF = 0.0075
|
||||||
@ -19,26 +19,24 @@ class DirectCameraControl(PandaObject):
|
|||||||
useDirectRenderStyle(self.coaMarker)
|
useDirectRenderStyle(self.coaMarker)
|
||||||
self.coaMarkerPos = Point3(0)
|
self.coaMarkerPos = Point3(0)
|
||||||
self.camManipRef = direct.group.attachNewNode('camManipRef')
|
self.camManipRef = direct.group.attachNewNode('camManipRef')
|
||||||
self.zeroBaseVec = VBase3(0)
|
|
||||||
self.zeroVector = Vec3(0)
|
|
||||||
self.centerVec = Vec3(0, 1, 0)
|
|
||||||
self.zeroPoint = Point3(0)
|
|
||||||
t = CAM_MOVE_DURATION
|
t = CAM_MOVE_DURATION
|
||||||
self.actionEvents = [
|
self.actionEvents = [
|
||||||
['handleMouse2', self.mouseFlyStart],
|
['handleMouse2', self.mouseFlyStart],
|
||||||
['handleMouse2Up', self.mouseFlyStop],
|
['handleMouse2Up', self.mouseFlyStop],
|
||||||
['u', self.uprightCam],
|
|
||||||
['c', self.centerCamIn, 0.5],
|
['c', self.centerCamIn, 0.5],
|
||||||
['h', self.homeCam],
|
|
||||||
['f', self.fitOnWidget],
|
['f', self.fitOnWidget],
|
||||||
[`1`, self.SpawnMoveToView, 1],
|
['h', self.homeCam],
|
||||||
[`2`, self.SpawnMoveToView, 2],
|
['m', self.moveToFit],
|
||||||
[`3`, self.SpawnMoveToView, 3],
|
['u', self.orbitUprightCam],
|
||||||
[`4`, self.SpawnMoveToView, 4],
|
['U', self.uprightCam],
|
||||||
[`5`, self.SpawnMoveToView, 5],
|
[`1`, self.spawnMoveToView, 1],
|
||||||
[`6`, self.SpawnMoveToView, 6],
|
[`2`, self.spawnMoveToView, 2],
|
||||||
[`7`, self.SpawnMoveToView, 7],
|
[`3`, self.spawnMoveToView, 3],
|
||||||
[`8`, self.SpawnMoveToView, 8],
|
[`4`, self.spawnMoveToView, 4],
|
||||||
|
[`5`, self.spawnMoveToView, 5],
|
||||||
|
[`6`, self.spawnMoveToView, 6],
|
||||||
|
[`7`, self.spawnMoveToView, 7],
|
||||||
|
[`8`, self.spawnMoveToView, 8],
|
||||||
['9', self.swingCamAboutWidget, -90.0, t],
|
['9', self.swingCamAboutWidget, -90.0, t],
|
||||||
['0', self.swingCamAboutWidget, 90.0, t],
|
['0', self.swingCamAboutWidget, 90.0, t],
|
||||||
['`', self.removeManipulateCameraTask],
|
['`', self.removeManipulateCameraTask],
|
||||||
@ -59,102 +57,241 @@ class DirectCameraControl(PandaObject):
|
|||||||
# MOUSE IS IN CENTRAL REGION
|
# MOUSE IS IN CENTRAL REGION
|
||||||
# Hide the marker for this kind of motion
|
# Hide the marker for this kind of motion
|
||||||
self.coaMarker.hide()
|
self.coaMarker.hide()
|
||||||
# See if the shift key is pressed
|
# Check for a hit point based on
|
||||||
if (direct.fShift):
|
# current mouse position
|
||||||
# If shift key is pressed, just perform horiz and vert pan:
|
# And then spawn task to determine mouse mode
|
||||||
self.spawnHPPan()
|
numEntries = direct.iRay.pickGeom(
|
||||||
else:
|
render,direct.dr.mouseX,direct.dr.mouseY)
|
||||||
# Otherwise, check for a hit point based on
|
# Sort intersection points
|
||||||
# current mouse position
|
direct.iRay.cq.sortEntries()
|
||||||
# And then spawn task to determine mouse mode
|
# Then filter out hidden nodes from entry list
|
||||||
numEntries = direct.iRay.pickGeom(
|
indexList = []
|
||||||
render,direct.dr.mouseX,direct.dr.mouseY)
|
for i in range(0,numEntries):
|
||||||
# Filter out hidden nodes from entry list
|
entry = direct.iRay.cq.getEntry(i)
|
||||||
indexList = []
|
node = entry.getIntoNode()
|
||||||
for i in range(0,numEntries):
|
if node.isHidden():
|
||||||
entry = direct.iRay.cq.getEntry(i)
|
pass
|
||||||
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 * direct.dr.near)) |
|
|
||||||
(coaDist > direct.dr.far)):
|
|
||||||
# Just use existing point
|
|
||||||
coa.assign(self.coaMarker.getPos(direct.camera))
|
|
||||||
coaDist = Vec3(coa - self.zeroPoint).length()
|
|
||||||
if coaDist < (1.1 * direct.dr.near):
|
|
||||||
coa.set(0,100,0)
|
|
||||||
coaDist = 100
|
|
||||||
else:
|
else:
|
||||||
# If no intersection point:
|
# Not one of the widgets, use it
|
||||||
# Use existing point
|
indexList.append(i)
|
||||||
|
coa = Point3(0)
|
||||||
|
if(indexList):
|
||||||
|
# Grab first point (it should be the closest)
|
||||||
|
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 - ZERO_POINT).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 - ZERO_POINT).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 * direct.dr.near)) |
|
||||||
|
(coaDist > direct.dr.far)):
|
||||||
|
# Just use existing point
|
||||||
coa.assign(self.coaMarker.getPos(direct.camera))
|
coa.assign(self.coaMarker.getPos(direct.camera))
|
||||||
coaDist = Vec3(coa - self.zeroPoint).length()
|
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||||
if coaDist < (1.1 * direct.dr.near):
|
if coaDist < (1.1 * direct.dr.near):
|
||||||
coa.set(0,100,0)
|
coa.set(0,100,0)
|
||||||
coaDist = 100
|
coaDist = 100
|
||||||
# Update coa and marker
|
else:
|
||||||
self.updateCoa(coa, coaDist)
|
# If no intersection point:
|
||||||
# Now spawn task to determine mouse fly mode
|
# Use existing point
|
||||||
self.determineMouseFlyMode()
|
coa.assign(self.coaMarker.getPos(direct.camera))
|
||||||
|
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||||
|
# Check again its not to close
|
||||||
|
if coaDist < (1.1 * direct.dr.near):
|
||||||
|
coa.set(0,100,0)
|
||||||
|
coaDist = 100
|
||||||
|
# Update coa and marker
|
||||||
|
self.updateCoa(coa, coaDist)
|
||||||
|
# Start manipulation
|
||||||
|
self.spawnXZTranslateOrHPanYZoom()
|
||||||
# END MOUSE IN CENTRAL REGION
|
# END MOUSE IN CENTRAL REGION
|
||||||
else:
|
else:
|
||||||
# Mouse is in outer frame, spawn mouseRotateTask
|
if ((abs(self.initMouseX) > 0.9) & (abs(self.initMouseY) > 0.9)):
|
||||||
self.spawnMouseRotateTask()
|
# Mouse is in corners, spawn roll task
|
||||||
|
self.spawnMouseRollTask()
|
||||||
|
else:
|
||||||
|
# Mouse is in outer frame, spawn mouseRotateTask
|
||||||
|
self.spawnMouseRotateTask()
|
||||||
|
|
||||||
def mouseFlyStop(self):
|
def mouseFlyStop(self):
|
||||||
taskMgr.removeTasksNamed('determineMouseFlyMode')
|
|
||||||
taskMgr.removeTasksNamed('manipulateCamera')
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
# Show the marker
|
# Show the marker
|
||||||
self.coaMarker.show()
|
self.coaMarker.show()
|
||||||
# Resize it
|
# Resize it
|
||||||
self.updateCoaMarkerSize()
|
self.updateCoaMarkerSize()
|
||||||
|
|
||||||
def determineMouseFlyMode(self):
|
def spawnXZTranslateOrHPanYZoom(self):
|
||||||
# Otherwise, determine mouse fly mode
|
# Kill any existing tasks
|
||||||
t = Task.Task(self.determineMouseFlyModeTask)
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
taskMgr.spawnTaskNamed(t, 'determineMouseFlyMode')
|
# Spawn the new task
|
||||||
|
t = Task.Task(self.XZTranslateOrHPanYZoomTask)
|
||||||
|
# For HPanYZoom
|
||||||
|
t.zoomSF = Vec3(self.coa).length()
|
||||||
|
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||||
|
|
||||||
def determineMouseFlyModeTask(self, state):
|
def spawnXZTranslateOrHPPan(self):
|
||||||
deltaX = direct.dr.mouseX - self.initMouseX
|
# Kill any existing tasks
|
||||||
deltaY = direct.dr.mouseY - self.initMouseY
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)):
|
# Spawn new task
|
||||||
return Task.cont
|
taskMgr.spawnMethodNamed(self.XZTranslateOrHPPanTask,
|
||||||
|
'manipulateCamera')
|
||||||
|
|
||||||
|
def spawnXZTranslate(self):
|
||||||
|
# Kill any existing tasks
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Spawn new task
|
||||||
|
taskMgr.spawnMethodNamed(self.XZTranslateTask, 'manipulateCamera')
|
||||||
|
|
||||||
|
def spawnHPanYZoom(self):
|
||||||
|
# Kill any existing tasks
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Spawn new task
|
||||||
|
t = Task.Task(self.HPanYZoomTask)
|
||||||
|
t.zoomSF = Vec3(self.coa).length()
|
||||||
|
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||||
|
|
||||||
|
def spawnHPPan(self):
|
||||||
|
# Kill any existing tasks
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Spawn new task
|
||||||
|
taskMgr.spawnMethodNamed(self.HPPanTask, 'manipulateCamera')
|
||||||
|
|
||||||
|
def XZTranslateOrHPanYZoomTask(self, state):
|
||||||
|
if direct.fShift:
|
||||||
|
return self.XZTranslateTask(state)
|
||||||
else:
|
else:
|
||||||
if (abs(deltaY) > 0.1):
|
return self.HPanYZoomTask(state)
|
||||||
self.spawnHPanYZoom()
|
|
||||||
else:
|
def XZTranslateOrHPPanTask(self, state):
|
||||||
self.spawnXZTranslate()
|
if direct.fShift:
|
||||||
return Task.done
|
# Panning action
|
||||||
|
return self.HPPanTask(state)
|
||||||
|
else:
|
||||||
|
# Translation action
|
||||||
|
return self.XZTranslateTask(state)
|
||||||
|
|
||||||
|
def XZTranslateTask(self,state):
|
||||||
|
coaDist = Vec3(self.coaMarker.getPos(direct.camera)).length()
|
||||||
|
xlateSF = (coaDist / direct.dr.near)
|
||||||
|
direct.camera.setPos(direct.camera,
|
||||||
|
(-0.5 * direct.dr.mouseDeltaX *
|
||||||
|
direct.dr.nearWidth *
|
||||||
|
xlateSF),
|
||||||
|
0.0,
|
||||||
|
(-0.5 * direct.dr.mouseDeltaY *
|
||||||
|
direct.dr.nearHeight *
|
||||||
|
xlateSF))
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def HPanYZoomTask(self,state):
|
||||||
|
if direct.fControl:
|
||||||
|
moveDir = Vec3(Y_AXIS)
|
||||||
|
else:
|
||||||
|
moveDir = Vec3(self.coaMarker.getPos(direct.camera))
|
||||||
|
# If marker is behind camera invert vector
|
||||||
|
if moveDir[1] < 0.0:
|
||||||
|
moveDir.assign(moveDir * -1)
|
||||||
|
moveDir.normalize()
|
||||||
|
moveDir.assign(moveDir * (-2.0 * direct.dr.mouseDeltaY *
|
||||||
|
state.zoomSF))
|
||||||
|
direct.camera.setPosHpr(direct.camera,
|
||||||
|
moveDir[0],
|
||||||
|
moveDir[1],
|
||||||
|
moveDir[2],
|
||||||
|
(0.5 * direct.dr.mouseDeltaX *
|
||||||
|
direct.dr.fovH),
|
||||||
|
0.0, 0.0)
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def HPPanTask(self, state):
|
||||||
|
direct.camera.setHpr(direct.camera,
|
||||||
|
(0.5 * direct.dr.mouseDeltaX *
|
||||||
|
direct.dr.fovH),
|
||||||
|
(-0.5 * direct.dr.mouseDeltaY *
|
||||||
|
direct.dr.fovV),
|
||||||
|
0.0)
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def spawnMouseRotateTask(self):
|
||||||
|
# Kill any existing tasks
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Set at markers position in render coordinates
|
||||||
|
self.camManipRef.setPos(self.coaMarkerPos)
|
||||||
|
self.camManipRef.setHpr(direct.camera, ZERO_POINT)
|
||||||
|
t = Task.Task(self.mouseRotateTask)
|
||||||
|
if abs(direct.dr.mouseX) > 0.9:
|
||||||
|
t.constrainedDir = 'y'
|
||||||
|
else:
|
||||||
|
t.constrainedDir = 'x'
|
||||||
|
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||||
|
|
||||||
|
def mouseRotateTask(self, state):
|
||||||
|
# If moving within frame, ignore motion perpendicular to edge
|
||||||
|
if ((state.constrainedDir == 'y') & (abs(direct.dr.mouseX) > 0.9)):
|
||||||
|
deltaX = 0
|
||||||
|
deltaY = direct.dr.mouseDeltaY
|
||||||
|
elif ((state.constrainedDir == 'x') & (abs(direct.dr.mouseY) > 0.9)):
|
||||||
|
deltaX = direct.dr.mouseDeltaX
|
||||||
|
deltaY = 0
|
||||||
|
else:
|
||||||
|
deltaX = direct.dr.mouseDeltaX
|
||||||
|
deltaY = direct.dr.mouseDeltaY
|
||||||
|
if direct.fShift:
|
||||||
|
direct.camera.setHpr(direct.camera,
|
||||||
|
(deltaX * direct.dr.fovH),
|
||||||
|
(-deltaY * direct.dr.fovV),
|
||||||
|
0.0)
|
||||||
|
self.camManipRef.setPos(self.coaMarkerPos)
|
||||||
|
self.camManipRef.setHpr(direct.camera, ZERO_POINT)
|
||||||
|
else:
|
||||||
|
wrtMat = direct.camera.getMat( self.camManipRef )
|
||||||
|
self.camManipRef.setHpr(self.camManipRef,
|
||||||
|
(-1 * deltaX * 180.0),
|
||||||
|
(deltaY * 180.0),
|
||||||
|
0.0)
|
||||||
|
direct.camera.setMat(self.camManipRef, wrtMat)
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
|
def spawnMouseRollTask(self):
|
||||||
|
# Kill any existing tasks
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Set at markers position in render coordinates
|
||||||
|
self.camManipRef.setPos(self.coaMarkerPos)
|
||||||
|
self.camManipRef.setHpr(direct.camera, ZERO_POINT)
|
||||||
|
t = Task.Task(self.mouseRollTask)
|
||||||
|
t.coaCenter = getScreenXY(self.coaMarker)
|
||||||
|
t.lastAngle = getCrankAngle(t.coaCenter)
|
||||||
|
t.wrtMat = direct.camera.getMat( self.camManipRef )
|
||||||
|
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||||
|
|
||||||
|
def mouseRollTask(self, state):
|
||||||
|
wrtMat = state.wrtMat
|
||||||
|
angle = getCrankAngle(state.coaCenter)
|
||||||
|
deltaAngle = angle - state.lastAngle
|
||||||
|
state.lastAngle = angle
|
||||||
|
self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle)
|
||||||
|
direct.camera.setMat(self.camManipRef, wrtMat)
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
def updateCoa(self, cam2point, coaDist = None):
|
def updateCoa(self, cam2point, coaDist = None):
|
||||||
self.coa.set(cam2point[0], cam2point[1], cam2point[2])
|
self.coa.set(cam2point[0], cam2point[1], cam2point[2])
|
||||||
if coaDist:
|
if coaDist:
|
||||||
self.coaDist = coaDist
|
self.coaDist = coaDist
|
||||||
else:
|
else:
|
||||||
self.coaDist = Vec3(self.coa - self.zeroPoint).length()
|
self.coaDist = Vec3(self.coa - ZERO_POINT).length()
|
||||||
# Place the marker in render space
|
# Place the marker in render space
|
||||||
self.coaMarker.setPos(direct.camera,self.coa)
|
self.coaMarker.setPos(direct.camera,self.coa)
|
||||||
# Resize it
|
# Resize it
|
||||||
@ -162,6 +299,10 @@ class DirectCameraControl(PandaObject):
|
|||||||
# Record marker pos in render space
|
# Record marker pos in render space
|
||||||
self.coaMarkerPos.assign(self.coaMarker.getPos())
|
self.coaMarkerPos.assign(self.coaMarker.getPos())
|
||||||
|
|
||||||
|
def updateCoaMarkerSizeOnDeath(self, state):
|
||||||
|
# Needed because tasks pass in state as first arg
|
||||||
|
self.updateCoaMarkerSize()
|
||||||
|
|
||||||
def updateCoaMarkerSize(self, coaDist = None):
|
def updateCoaMarkerSize(self, coaDist = None):
|
||||||
if not coaDist:
|
if not coaDist:
|
||||||
coaDist = Vec3(self.coaMarker.getPos( direct.camera )).length()
|
coaDist = Vec3(self.coaMarker.getPos( direct.camera )).length()
|
||||||
@ -172,18 +313,59 @@ class DirectCameraControl(PandaObject):
|
|||||||
# Record undo point
|
# Record undo point
|
||||||
direct.pushUndo([direct.camera])
|
direct.pushUndo([direct.camera])
|
||||||
direct.camera.setMat(Mat4.identMat())
|
direct.camera.setMat(Mat4.identMat())
|
||||||
|
# Resize coa marker
|
||||||
|
self.updateCoaMarkerSize()
|
||||||
|
|
||||||
def uprightCam(self):
|
def uprightCam(self):
|
||||||
taskMgr.removeTasksNamed('manipulateCamera')
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
currH = direct.camera.getH()
|
|
||||||
# Record undo point
|
# Record undo point
|
||||||
direct.pushUndo([direct.camera])
|
direct.pushUndo([direct.camera])
|
||||||
|
# Pitch camera till upright
|
||||||
|
currH = direct.camera.getH()
|
||||||
direct.camera.lerpHpr(currH, 0, 0,
|
direct.camera.lerpHpr(currH, 0, 0,
|
||||||
CAM_MOVE_DURATION,
|
CAM_MOVE_DURATION,
|
||||||
other = render,
|
other = render,
|
||||||
blendType = 'easeInOut',
|
blendType = 'easeInOut',
|
||||||
task = 'manipulateCamera')
|
task = 'manipulateCamera')
|
||||||
|
|
||||||
|
def orbitUprightCam(self):
|
||||||
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
|
# Record undo point
|
||||||
|
direct.pushUndo([direct.camera])
|
||||||
|
# Transform camera z axis to render space
|
||||||
|
mCam2Render = camera.getMat(render)
|
||||||
|
zAxis = Vec3(mCam2Render.xformVec(Z_AXIS))
|
||||||
|
zAxis.normalize()
|
||||||
|
# Compute rotation angle needed to upright cam
|
||||||
|
orbitAngle = rad2Deg(math.acos(CLAMP(zAxis.dot(Z_AXIS),-1,1)))
|
||||||
|
# Check angle
|
||||||
|
if orbitAngle < 0.1:
|
||||||
|
# Already upright
|
||||||
|
return
|
||||||
|
# Compute orthogonal axis of rotation
|
||||||
|
rotAxis = Vec3(zAxis.cross(Z_AXIS))
|
||||||
|
rotAxis.normalize()
|
||||||
|
# Find angle between rot Axis and render X_AXIS
|
||||||
|
rotAngle = rad2Deg(math.acos(CLAMP(rotAxis.dot(X_AXIS),-1,1)))
|
||||||
|
# Determine sign or rotation angle
|
||||||
|
if rotAxis[1] < 0:
|
||||||
|
rotAngle *= -1
|
||||||
|
# Position ref CS at coa marker with xaxis aligned with rot axis
|
||||||
|
self.camManipRef.setPos(self.coaMarker, Vec3(0))
|
||||||
|
self.camManipRef.setHpr(render, rotAngle, 0, 0)
|
||||||
|
# Reparent Cam to ref Coordinate system
|
||||||
|
parent = direct.camera.getParent()
|
||||||
|
direct.camera.wrtReparentTo(self.camManipRef)
|
||||||
|
# Rotate ref CS to final orientation
|
||||||
|
t = self.camManipRef.lerpHpr(rotAngle, orbitAngle, 0,
|
||||||
|
CAM_MOVE_DURATION,
|
||||||
|
other = render,
|
||||||
|
blendType = 'easeInOut',
|
||||||
|
task = 'manipulateCamera')
|
||||||
|
# Upon death, reparent Cam to parent
|
||||||
|
t.parent = parent
|
||||||
|
t.uponDeath = self.reparentCam
|
||||||
|
|
||||||
def centerCam(self):
|
def centerCam(self):
|
||||||
self.centerCamIn(1.0)
|
self.centerCamIn(1.0)
|
||||||
|
|
||||||
@ -196,15 +378,16 @@ class DirectCameraControl(PandaObject):
|
|||||||
direct.pushUndo([direct.camera])
|
direct.pushUndo([direct.camera])
|
||||||
# Determine marker location
|
# Determine marker location
|
||||||
markerToCam = self.coaMarker.getPos( direct.camera )
|
markerToCam = self.coaMarker.getPos( direct.camera )
|
||||||
dist = Vec3(markerToCam - self.zeroPoint).length()
|
dist = Vec3(markerToCam - ZERO_POINT).length()
|
||||||
scaledCenterVec = self.centerVec * dist
|
scaledCenterVec = Y_AXIS * dist
|
||||||
delta = markerToCam - scaledCenterVec
|
delta = markerToCam - scaledCenterVec
|
||||||
self.camManipRef.setPosHpr(direct.camera, Point3(0), Point3(0))
|
self.camManipRef.setPosHpr(direct.camera, Point3(0), Point3(0))
|
||||||
direct.camera.lerpPos(Point3(delta),
|
t = direct.camera.lerpPos(Point3(delta),
|
||||||
CAM_MOVE_DURATION,
|
CAM_MOVE_DURATION,
|
||||||
other = self.camManipRef,
|
other = self.camManipRef,
|
||||||
blendType = 'easeInOut',
|
blendType = 'easeInOut',
|
||||||
task = 'manipulateCamera')
|
task = 'manipulateCamera')
|
||||||
|
t.uponDeath = self.updateCoaMarkerSizeOnDeath
|
||||||
|
|
||||||
def zoomCam(self, zoomFactor, t):
|
def zoomCam(self, zoomFactor, t):
|
||||||
taskMgr.removeTasksNamed('manipulateCamera')
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
@ -216,13 +399,14 @@ class DirectCameraControl(PandaObject):
|
|||||||
# Put a target nodePath there
|
# Put a target nodePath there
|
||||||
self.camManipRef.setPos(direct.camera, zoomPtToCam)
|
self.camManipRef.setPos(direct.camera, zoomPtToCam)
|
||||||
# Move to that point
|
# Move to that point
|
||||||
direct.camera.lerpPos(self.zeroPoint,
|
t = direct.camera.lerpPos(ZERO_POINT,
|
||||||
CAM_MOVE_DURATION,
|
CAM_MOVE_DURATION,
|
||||||
other = self.camManipRef,
|
other = self.camManipRef,
|
||||||
blendType = 'easeInOut',
|
blendType = 'easeInOut',
|
||||||
task = 'manipulateCamera')
|
task = 'manipulateCamera')
|
||||||
|
t.uponDeath = self.updateCoaMarkerSizeOnDeath
|
||||||
|
|
||||||
def SpawnMoveToView(self, view):
|
def spawnMoveToView(self, view):
|
||||||
# Kill any existing tasks
|
# Kill any existing tasks
|
||||||
taskMgr.removeTasksNamed('manipulateCamera')
|
taskMgr.removeTasksNamed('manipulateCamera')
|
||||||
# Record undo point
|
# Record undo point
|
||||||
@ -252,25 +436,26 @@ class DirectCameraControl(PandaObject):
|
|||||||
elif view == 7:
|
elif view == 7:
|
||||||
hprOffset.set(135., -35.264, 0.)
|
hprOffset.set(135., -35.264, 0.)
|
||||||
# Position target
|
# Position target
|
||||||
self.camManipRef.setPosHpr(self.coaMarker, self.zeroBaseVec,
|
self.camManipRef.setPosHpr(self.coaMarker, ZERO_VEC,
|
||||||
hprOffset)
|
hprOffset)
|
||||||
# Scale center vec by current distance to target
|
# Scale center vec by current distance to target
|
||||||
offsetDistance = Vec3(direct.camera.getPos(self.camManipRef) -
|
offsetDistance = Vec3(direct.camera.getPos(self.camManipRef) -
|
||||||
self.zeroPoint).length()
|
ZERO_POINT).length()
|
||||||
scaledCenterVec = self.centerVec * (-1.0 * offsetDistance)
|
scaledCenterVec = Y_AXIS * (-1.0 * offsetDistance)
|
||||||
# Now put the camManipRef at that point
|
# Now put the camManipRef at that point
|
||||||
self.camManipRef.setPosHpr(self.camManipRef,
|
self.camManipRef.setPosHpr(self.camManipRef,
|
||||||
scaledCenterVec,
|
scaledCenterVec,
|
||||||
self.zeroBaseVec)
|
ZERO_VEC)
|
||||||
# Record view for next time around
|
# Record view for next time around
|
||||||
self.lastView = view
|
self.lastView = view
|
||||||
direct.camera.lerpPosHpr(self.zeroPoint,
|
t = direct.camera.lerpPosHpr(ZERO_POINT,
|
||||||
VBase3(0,0,self.orthoViewRoll),
|
VBase3(0,0,self.orthoViewRoll),
|
||||||
CAM_MOVE_DURATION,
|
CAM_MOVE_DURATION,
|
||||||
other = self.camManipRef,
|
other = self.camManipRef,
|
||||||
blendType = 'easeInOut',
|
blendType = 'easeInOut',
|
||||||
task = 'manipulateCamera')
|
task = 'manipulateCamera')
|
||||||
|
t.uponDeath = self.updateCoaMarkerSizeOnDeath
|
||||||
|
|
||||||
|
|
||||||
def swingCamAboutWidget(self, degrees, t):
|
def swingCamAboutWidget(self, degrees, t):
|
||||||
# Remove existing camera manipulation task
|
# Remove existing camera manipulation task
|
||||||
@ -280,9 +465,9 @@ class DirectCameraControl(PandaObject):
|
|||||||
direct.pushUndo([direct.camera])
|
direct.pushUndo([direct.camera])
|
||||||
|
|
||||||
# Coincident with widget
|
# Coincident with widget
|
||||||
self.camManipRef.setPos(self.coaMarker, self.zeroPoint)
|
self.camManipRef.setPos(self.coaMarker, ZERO_POINT)
|
||||||
# But aligned with render space
|
# But aligned with render space
|
||||||
self.camManipRef.setHpr(self.zeroPoint)
|
self.camManipRef.setHpr(ZERO_POINT)
|
||||||
|
|
||||||
parent = direct.camera.getParent()
|
parent = direct.camera.getParent()
|
||||||
direct.camera.wrtReparentTo(self.camManipRef)
|
direct.camera.wrtReparentTo(self.camManipRef)
|
||||||
@ -297,115 +482,7 @@ class DirectCameraControl(PandaObject):
|
|||||||
|
|
||||||
def reparentCam(self, state):
|
def reparentCam(self, state):
|
||||||
direct.camera.wrtReparentTo(state.parent)
|
direct.camera.wrtReparentTo(state.parent)
|
||||||
|
self.updateCoaMarkerSize()
|
||||||
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
|
|
||||||
# Can bring object to you by dragging across half the screen
|
|
||||||
distToMove = targetVector * (2.0 * direct.dr.mouseDeltaY)
|
|
||||||
direct.camera.setPosHpr(direct.camera,
|
|
||||||
distToMove[0],
|
|
||||||
distToMove[1],
|
|
||||||
distToMove[2],
|
|
||||||
(0.5 * direct.dr.mouseDeltaX *
|
|
||||||
direct.dr.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 / direct.dr.near)
|
|
||||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
|
||||||
|
|
||||||
def XZTranslateOrHPPanTask(self, state):
|
|
||||||
if direct.fShift:
|
|
||||||
direct.camera.setHpr(direct.camera,
|
|
||||||
(0.5 * direct.dr.mouseDeltaX *
|
|
||||||
direct.dr.fovH),
|
|
||||||
(-0.5 * direct.dr.mouseDeltaY *
|
|
||||||
direct.dr.fovV),
|
|
||||||
0.0)
|
|
||||||
else:
|
|
||||||
direct.camera.setPos(direct.camera,
|
|
||||||
(-0.5 * direct.dr.mouseDeltaX *
|
|
||||||
direct.dr.nearWidth *
|
|
||||||
state.scaleFactor),
|
|
||||||
0.0,
|
|
||||||
(-0.5 * direct.dr.mouseDeltaY *
|
|
||||||
direct.dr.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 / direct.dr.near)
|
|
||||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
|
||||||
|
|
||||||
def XZTranslateTask(self,state):
|
|
||||||
direct.camera.setPos(direct.camera,
|
|
||||||
(-0.5 * direct.dr.mouseDeltaX *
|
|
||||||
direct.dr.nearWidth *
|
|
||||||
state.scaleFactor),
|
|
||||||
0.0,
|
|
||||||
(-0.5 * direct.dr.mouseDeltaY *
|
|
||||||
direct.dr.nearHeight *
|
|
||||||
state.scaleFactor))
|
|
||||||
return Task.cont
|
|
||||||
|
|
||||||
def spawnMouseRotateTask(self):
|
|
||||||
# Kill any existing tasks
|
|
||||||
taskMgr.removeTasksNamed('manipulateCamera')
|
|
||||||
# Set at markers position in render coordinates
|
|
||||||
self.camManipRef.setPos(self.coaMarkerPos)
|
|
||||||
self.camManipRef.setHpr(direct.camera, self.zeroPoint)
|
|
||||||
t = Task.Task(self.mouseRotateTask)
|
|
||||||
t.wrtMat = direct.camera.getMat( self.camManipRef )
|
|
||||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
|
||||||
|
|
||||||
def mouseRotateTask(self, state):
|
|
||||||
wrtMat = state.wrtMat
|
|
||||||
self.camManipRef.setHpr(self.camManipRef,
|
|
||||||
(-0.5 * direct.dr.mouseDeltaX * 180.0),
|
|
||||||
(0.5 * direct.dr.mouseDeltaY * 180.0),
|
|
||||||
0.0)
|
|
||||||
direct.camera.setMat(self.camManipRef, 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):
|
|
||||||
direct.camera.setHpr(direct.camera,
|
|
||||||
(0.5 * direct.dr.mouseDeltaX *
|
|
||||||
direct.dr.fovH),
|
|
||||||
(-0.5 * direct.dr.mouseDeltaY *
|
|
||||||
direct.dr.fovV),
|
|
||||||
0.0)
|
|
||||||
return Task.cont
|
|
||||||
|
|
||||||
def fitOnWidget(self):
|
def fitOnWidget(self):
|
||||||
# Fit the node on the screen
|
# Fit the node on the screen
|
||||||
@ -444,6 +521,39 @@ class DirectCameraControl(PandaObject):
|
|||||||
fitTask.parent = parent
|
fitTask.parent = parent
|
||||||
fitTask.uponDeath = self.reparentCam
|
fitTask.uponDeath = self.reparentCam
|
||||||
|
|
||||||
|
def moveToFit(self):
|
||||||
|
# How bit is the active widget?
|
||||||
|
widgetScale = direct.widget.scalingNode.getScale(render)
|
||||||
|
maxScale = max(widgetScale[0], widgetScale[1], widgetScale[2])
|
||||||
|
# At what distance does the widget fill 50% of the screen?
|
||||||
|
camY = ((2 * direct.dr.near * (1.5 * maxScale)) /
|
||||||
|
min(direct.dr.nearWidth, direct.dr.nearHeight))
|
||||||
|
# Find a point this distance along the Y axis
|
||||||
|
# MRM: This needs to be generalized to support non uniform frusta
|
||||||
|
centerVec = Y_AXIS * camY
|
||||||
|
# Before moving, record the relationship between the selected nodes
|
||||||
|
# and the widget, so that this can be maintained
|
||||||
|
direct.selected.getWrtAll()
|
||||||
|
# Push state onto undo stack
|
||||||
|
direct.pushUndo(direct.selected)
|
||||||
|
# Remove the task to keep the widget attached to the object
|
||||||
|
taskMgr.removeTasksNamed('followSelectedNodePath')
|
||||||
|
# Spawn a task to keep the selected objects with the widget
|
||||||
|
taskMgr.spawnMethodNamed(self.stickToWidgetTask, 'stickToWidget')
|
||||||
|
# Spawn a task to move the widget
|
||||||
|
t = direct.widget.lerpPos(Point3(centerVec),
|
||||||
|
CAM_MOVE_DURATION,
|
||||||
|
other = direct.camera,
|
||||||
|
blendType = 'easeInOut',
|
||||||
|
task = 'moveToFitTask')
|
||||||
|
t.uponDeath = lambda state: taskMgr.removeTasksNamed('stickToWidget')
|
||||||
|
|
||||||
|
def stickToWidgetTask(self, state):
|
||||||
|
# Move the objects with the widget
|
||||||
|
direct.selected.moveWrtWidgetAll()
|
||||||
|
# Continue
|
||||||
|
return Task.cont
|
||||||
|
|
||||||
def enableMouseFly(self):
|
def enableMouseFly(self):
|
||||||
# disable C++ fly interface
|
# disable C++ fly interface
|
||||||
base.disableMouse()
|
base.disableMouse()
|
||||||
|
@ -86,6 +86,45 @@ def ROUND_TO(value, divisor):
|
|||||||
return round(value/float(divisor)) * divisor
|
return round(value/float(divisor)) * divisor
|
||||||
def ROUND_INT(val):
|
def ROUND_INT(val):
|
||||||
return int(round(val))
|
return int(round(val))
|
||||||
|
def CLAMP(val, min, max):
|
||||||
|
if val < min:
|
||||||
|
return min
|
||||||
|
elif val > max:
|
||||||
|
return max
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
def getNearProjectionPoint(nodePath):
|
||||||
|
# Find the position of the projection of the specified node path
|
||||||
|
# on the near plane
|
||||||
|
origin = nodePath.getPos(direct.camera)
|
||||||
|
# project this onto near plane
|
||||||
|
if origin[1] != 0.0:
|
||||||
|
return origin * (direct.dr.near / origin[1])
|
||||||
|
else:
|
||||||
|
# Object is coplaner with camera, just return something reasonable
|
||||||
|
return Point3(0, direct.dr.near, 0)
|
||||||
|
|
||||||
|
def getScreenXY(nodePath):
|
||||||
|
# Where does the node path's projection fall on the near plane
|
||||||
|
nearVec = getNearProjectionPoint(nodePath)
|
||||||
|
# Clamp these coordinates to visible screen
|
||||||
|
nearX = CLAMP(nearVec[0], direct.dr.left, direct.dr.right)
|
||||||
|
nearY = CLAMP(nearVec[2], direct.dr.bottom, direct.dr.top)
|
||||||
|
# What percentage of the distance across the screen is this?
|
||||||
|
percentX = (nearX - direct.dr.left)/direct.dr.nearWidth
|
||||||
|
percentY = (nearY - direct.dr.bottom)/direct.dr.nearHeight
|
||||||
|
# Map this percentage to the same -1 to 1 space as the mouse
|
||||||
|
screenXY = Vec3((2 * percentX) - 1.0,nearVec[1],(2 * percentY) - 1.0)
|
||||||
|
# Return the resulting value
|
||||||
|
return screenXY
|
||||||
|
|
||||||
|
def getCrankAngle(center):
|
||||||
|
# Used to compute current angle of mouse (relative to the coa's
|
||||||
|
# origin) in screen space
|
||||||
|
x = direct.dr.mouseX - center[0]
|
||||||
|
y = direct.dr.mouseY - center[2]
|
||||||
|
return (180 + rad2Deg(math.atan2(y,x)))
|
||||||
|
|
||||||
# Set direct drawing style for an object
|
# Set direct drawing style for an object
|
||||||
# Never light object or draw in wireframe
|
# Never light object or draw in wireframe
|
||||||
|
@ -28,6 +28,7 @@ class DirectManipulationControl(PandaObject):
|
|||||||
self.actionEvents = [
|
self.actionEvents = [
|
||||||
['handleMouse1', self.manipulationStart],
|
['handleMouse1', self.manipulationStart],
|
||||||
['handleMouse1Up', self.manipulationStop],
|
['handleMouse1Up', self.manipulationStop],
|
||||||
|
['space', self.toggleObjectHandlesMode],
|
||||||
['.', self.objectHandles.multiplyScalingFactorBy, 2.0],
|
['.', self.objectHandles.multiplyScalingFactorBy, 2.0],
|
||||||
['>', self.objectHandles.multiplyScalingFactorBy, 2.0],
|
['>', self.objectHandles.multiplyScalingFactorBy, 2.0],
|
||||||
[',', self.objectHandles.multiplyScalingFactorBy, 0.5],
|
[',', self.objectHandles.multiplyScalingFactorBy, 0.5],
|
||||||
@ -137,8 +138,6 @@ class DirectManipulationControl(PandaObject):
|
|||||||
# We had been scaling, need to reset object handles
|
# We had been scaling, need to reset object handles
|
||||||
self.objectHandles.transferObjectHandlesScale()
|
self.objectHandles.transferObjectHandlesScale()
|
||||||
self.fScaling = 0
|
self.fScaling = 0
|
||||||
if self.fSetCoa:
|
|
||||||
self.objectHandles.manipModeColor()
|
|
||||||
direct.selected.highlightAll()
|
direct.selected.highlightAll()
|
||||||
self.objectHandles.showAllHandles()
|
self.objectHandles.showAllHandles()
|
||||||
self.objectHandles.hideGuides()
|
self.objectHandles.hideGuides()
|
||||||
@ -188,6 +187,13 @@ class DirectManipulationControl(PandaObject):
|
|||||||
if item in self.unpickable:
|
if item in self.unpickable:
|
||||||
self.unpickable.remove(item)
|
self.unpickable.remove(item)
|
||||||
|
|
||||||
|
def toggleObjectHandlesMode(self):
|
||||||
|
self.fSetCoa = 1 - self.fSetCoa
|
||||||
|
if self.fSetCoa:
|
||||||
|
self.objectHandles.coaModeColor()
|
||||||
|
else:
|
||||||
|
self.objectHandles.manipModeColor()
|
||||||
|
|
||||||
def removeManipulateObjectTask(self):
|
def removeManipulateObjectTask(self):
|
||||||
taskMgr.removeTasksNamed('manipulateObject')
|
taskMgr.removeTasksNamed('manipulateObject')
|
||||||
|
|
||||||
@ -206,20 +212,10 @@ class DirectManipulationControl(PandaObject):
|
|||||||
self.objectHandles.showGuides()
|
self.objectHandles.showGuides()
|
||||||
self.objectHandles.hideAllHandles()
|
self.objectHandles.hideAllHandles()
|
||||||
self.objectHandles.showHandle(self.constraint)
|
self.objectHandles.showHandle(self.constraint)
|
||||||
if self.fSetCoa:
|
|
||||||
self.objectHandles.coaModeColor()
|
|
||||||
|
|
||||||
# Record relationship between selected nodes and widget
|
# Record relationship between selected nodes and widget
|
||||||
direct.selected.getWrtAll()
|
direct.selected.getWrtAll()
|
||||||
|
|
||||||
# hide the bbox of the selected objects during interaction
|
# hide the bbox of the selected objects during interaction
|
||||||
direct.selected.dehighlightAll()
|
direct.selected.dehighlightAll()
|
||||||
|
|
||||||
"""
|
|
||||||
# Push the undo dcs for the selected objects
|
|
||||||
direct.undo.push(
|
|
||||||
(direct.selected, 'dcs'))
|
|
||||||
"""
|
|
||||||
# Manipulate the real object with the constraint
|
# Manipulate the real object with the constraint
|
||||||
# The constraint is passed as the name of the node
|
# The constraint is passed as the name of the node
|
||||||
self.spawnManipulateObjectTask()
|
self.spawnManipulateObjectTask()
|
||||||
@ -350,13 +346,6 @@ class DirectManipulationControl(PandaObject):
|
|||||||
y + self.initY * dr.mouseDeltaY,
|
y + self.initY * dr.mouseDeltaY,
|
||||||
z)
|
z)
|
||||||
|
|
||||||
def getCrankAngle(self):
|
|
||||||
# Used to compute current angle of mouse (relative to the widget's
|
|
||||||
# origin) in screen space
|
|
||||||
x = direct.dr.mouseX - self.rotationCenter[0]
|
|
||||||
y = direct.dr.mouseY - self.rotationCenter[2]
|
|
||||||
return (180 + rad2Deg(math.atan2(y,x)))
|
|
||||||
|
|
||||||
def widgetCheck(self,type):
|
def widgetCheck(self,type):
|
||||||
# Utility to see if we are looking at the top or bottom of
|
# Utility to see if we are looking at the top or bottom of
|
||||||
# a 2D planar widget or if we are looking at a 2D planar widget
|
# a 2D planar widget or if we are looking at a 2D planar widget
|
||||||
@ -388,27 +377,6 @@ class DirectManipulationControl(PandaObject):
|
|||||||
# Check angle between two vectors
|
# Check angle between two vectors
|
||||||
return(abs(widgetDir.dot(widgetAxis)) < .2)
|
return(abs(widgetDir.dot(widgetAxis)) < .2)
|
||||||
|
|
||||||
def getWidgetsNearProjectionPoint(self):
|
|
||||||
# Find the position of the projection of the specified node path
|
|
||||||
# on the near plane
|
|
||||||
widgetOrigin = direct.widget.getPos(direct.camera)
|
|
||||||
# project this onto near plane
|
|
||||||
return widgetOrigin * (direct.dr.near / widgetOrigin[1])
|
|
||||||
|
|
||||||
def getScreenXY(self):
|
|
||||||
# Where does the widget's projection fall on the near plane
|
|
||||||
nearVec = self.getWidgetsNearProjectionPoint()
|
|
||||||
# Clamp these coordinates to visible screen
|
|
||||||
nearX = self.clamp(nearVec[0], direct.dr.left, direct.dr.right)
|
|
||||||
nearY = self.clamp(nearVec[2], direct.dr.bottom, direct.dr.top)
|
|
||||||
# What percentage of the distance across the screen is this?
|
|
||||||
percentX = (nearX - direct.dr.left)/direct.dr.nearWidth
|
|
||||||
percentY = (nearY - direct.dr.bottom)/direct.dr.nearHeight
|
|
||||||
# Map this percentage to the same -1 to 1 space as the mouse
|
|
||||||
screenXY = Vec3((2 * percentX) - 1.0,nearVec[1],(2 * percentY) - 1.0)
|
|
||||||
# Return the resulting value
|
|
||||||
return screenXY
|
|
||||||
|
|
||||||
def rotate1D(self):
|
def rotate1D(self):
|
||||||
# Constrained 1D rotation about the widget's main axis (X,Y, or Z)
|
# Constrained 1D rotation about the widget's main axis (X,Y, or Z)
|
||||||
# Rotation depends upon circular motion of the mouse about the
|
# Rotation depends upon circular motion of the mouse about the
|
||||||
@ -421,11 +389,11 @@ class DirectManipulationControl(PandaObject):
|
|||||||
self.fHitInit = 0
|
self.fHitInit = 0
|
||||||
self.rotateAxis = self.constraint[:1]
|
self.rotateAxis = self.constraint[:1]
|
||||||
self.fWidgetTop = self.widgetCheck('top?')
|
self.fWidgetTop = self.widgetCheck('top?')
|
||||||
self.rotationCenter = self.getScreenXY()
|
self.rotationCenter = getScreenXY(direct.widget)
|
||||||
self.lastCrankAngle = self.getCrankAngle()
|
self.lastCrankAngle = getCrankAngle(self.rotationCenter)
|
||||||
|
|
||||||
# Rotate widget based on how far cursor has swung around origin
|
# Rotate widget based on how far cursor has swung around origin
|
||||||
newAngle = self.getCrankAngle()
|
newAngle = getCrankAngle(self.rotationCenter)
|
||||||
deltaAngle = self.lastCrankAngle - newAngle
|
deltaAngle = self.lastCrankAngle - newAngle
|
||||||
if self.fWidgetTop:
|
if self.fWidgetTop:
|
||||||
deltaAngle = -1 * deltaAngle
|
deltaAngle = -1 * deltaAngle
|
||||||
@ -491,14 +459,6 @@ class DirectManipulationControl(PandaObject):
|
|||||||
)
|
)
|
||||||
direct.widget.setScale(currScale)
|
direct.widget.setScale(currScale)
|
||||||
|
|
||||||
def clamp(self, val, min, max):
|
|
||||||
if val < min:
|
|
||||||
return min
|
|
||||||
elif val > max:
|
|
||||||
return max
|
|
||||||
else:
|
|
||||||
return val
|
|
||||||
|
|
||||||
|
|
||||||
class ObjectHandles(NodePath,PandaObject):
|
class ObjectHandles(NodePath,PandaObject):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -82,7 +82,8 @@ class DirectSession(PandaObject):
|
|||||||
'escape', 'space', 'delete',
|
'escape', 'space', 'delete',
|
||||||
'shift', 'shift-up', 'alt', 'alt-up',
|
'shift', 'shift-up', 'alt', 'alt-up',
|
||||||
'control', 'control-up',
|
'control', 'control-up',
|
||||||
'page_up', 'page_down',
|
'page_up', 'page_down', 'tab',
|
||||||
|
'[', '{', ']', '}',
|
||||||
'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
|
'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
|
||||||
self.mouseEvents = ['mouse1', 'mouse1-up',
|
self.mouseEvents = ['mouse1', 'mouse1-up',
|
||||||
'mouse2', 'mouse2-up',
|
'mouse2', 'mouse2-up',
|
||||||
@ -190,21 +191,27 @@ class DirectSession(PandaObject):
|
|||||||
self.downAncestry()
|
self.downAncestry()
|
||||||
elif input == 'escape':
|
elif input == 'escape':
|
||||||
self.deselectAll()
|
self.deselectAll()
|
||||||
|
elif input == 'delete':
|
||||||
|
self.removeAllSelected()
|
||||||
|
elif input == 'tab':
|
||||||
|
self.toggleWidgetVis()
|
||||||
|
elif input == 'b':
|
||||||
|
base.toggleBackface()
|
||||||
elif input == 'l':
|
elif input == 'l':
|
||||||
self.lights.toggle()
|
self.lights.toggle()
|
||||||
elif input == 's':
|
elif input == 's':
|
||||||
if self.selected.last:
|
if self.selected.last:
|
||||||
self.select(self.selected.last)
|
self.select(self.selected.last)
|
||||||
elif input == 'delete':
|
|
||||||
self.removeAllSelected()
|
|
||||||
elif input == 'v':
|
|
||||||
self.selected.toggleVisAll()
|
|
||||||
elif input == 'b':
|
|
||||||
base.toggleBackface()
|
|
||||||
elif input == 't':
|
elif input == 't':
|
||||||
base.toggleTexture()
|
base.toggleTexture()
|
||||||
|
elif input == 'v':
|
||||||
|
self.selected.toggleVisAll()
|
||||||
elif input == 'w':
|
elif input == 'w':
|
||||||
base.toggleWireframe()
|
base.toggleWireframe()
|
||||||
|
elif (input == '[') | (input == '{'):
|
||||||
|
self.undo()
|
||||||
|
elif (input == ']') | (input == '}'):
|
||||||
|
self.redo()
|
||||||
|
|
||||||
def select(self, nodePath, fMultiselect = 0, fResetAncestry = 1):
|
def select(self, nodePath, fMultiselect = 0, fResetAncestry = 1):
|
||||||
dnp = self.selected.select(nodePath, fMultiselect)
|
dnp = self.selected.select(nodePath, fMultiselect)
|
||||||
@ -219,7 +226,7 @@ class DirectSession(PandaObject):
|
|||||||
self.readout.reparentTo(render2d)
|
self.readout.reparentTo(render2d)
|
||||||
self.readout.setText(dnp.name)
|
self.readout.setText(dnp.name)
|
||||||
# Show the manipulation widget
|
# Show the manipulation widget
|
||||||
self.widget.reparentTo(direct.group)
|
self.reparentWidgetTo('direct')
|
||||||
# Update camera controls coa to this point
|
# Update camera controls coa to this point
|
||||||
# Coa2Camera = Coa2Dnp * Dnp2Camera
|
# Coa2Camera = Coa2Dnp * Dnp2Camera
|
||||||
mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(self.camera)
|
mCoa2Camera = dnp.mCoa2Dnp * dnp.getMat(self.camera)
|
||||||
@ -250,7 +257,7 @@ class DirectSession(PandaObject):
|
|||||||
dnp = self.selected.deselect(nodePath)
|
dnp = self.selected.deselect(nodePath)
|
||||||
if dnp:
|
if dnp:
|
||||||
# Hide the manipulation widget
|
# Hide the manipulation widget
|
||||||
self.widget.reparentTo(hidden)
|
self.reparentWidgetTo('hidden')
|
||||||
self.readout.reparentTo(hidden)
|
self.readout.reparentTo(hidden)
|
||||||
self.readout.setText(' ')
|
self.readout.setText(' ')
|
||||||
taskMgr.removeTasksNamed('followSelectedNodePath')
|
taskMgr.removeTasksNamed('followSelectedNodePath')
|
||||||
@ -261,7 +268,7 @@ class DirectSession(PandaObject):
|
|||||||
def deselectAll(self):
|
def deselectAll(self):
|
||||||
self.selected.deselectAll()
|
self.selected.deselectAll()
|
||||||
# Hide the manipulation widget
|
# Hide the manipulation widget
|
||||||
self.widget.reparentTo(hidden)
|
self.reparentWidgetTo('hidden')
|
||||||
self.readout.reparentTo(hidden)
|
self.readout.reparentTo(hidden)
|
||||||
self.readout.setText(' ')
|
self.readout.setText(' ')
|
||||||
taskMgr.removeTasksNamed('followSelectedNodePath')
|
taskMgr.removeTasksNamed('followSelectedNodePath')
|
||||||
@ -384,7 +391,7 @@ class DirectSession(PandaObject):
|
|||||||
# Now record group
|
# Now record group
|
||||||
self.undoList.append(undoGroup)
|
self.undoList.append(undoGroup)
|
||||||
# Truncate list
|
# Truncate list
|
||||||
self.undoList = self.undoList[-5:]
|
self.undoList = self.undoList[-25:]
|
||||||
# Alert anyone who cares
|
# Alert anyone who cares
|
||||||
messenger.send('pushUndo')
|
messenger.send('pushUndo')
|
||||||
if fResetRedo & (nodePathList != []):
|
if fResetRedo & (nodePathList != []):
|
||||||
@ -413,7 +420,7 @@ class DirectSession(PandaObject):
|
|||||||
# Now record redo group
|
# Now record redo group
|
||||||
self.redoList.append(redoGroup)
|
self.redoList.append(redoGroup)
|
||||||
# Truncate list
|
# Truncate list
|
||||||
self.redoList = self.redoList[-5:]
|
self.redoList = self.redoList[-25:]
|
||||||
# Alert anyone who cares
|
# Alert anyone who cares
|
||||||
messenger.send('pushRedo')
|
messenger.send('pushRedo')
|
||||||
|
|
||||||
@ -462,6 +469,20 @@ class DirectSession(PandaObject):
|
|||||||
def hideReadout(self):
|
def hideReadout(self):
|
||||||
self.readout.reparentTo(hidden)
|
self.readout.reparentTo(hidden)
|
||||||
|
|
||||||
|
def reparentWidgetTo(self, parent):
|
||||||
|
if parent == 'direct':
|
||||||
|
self.widget.reparentTo(direct.group)
|
||||||
|
self.widgetParent = 'direct'
|
||||||
|
else:
|
||||||
|
self.widget.reparentTo(hidden)
|
||||||
|
self.widgetParent = 'hidden'
|
||||||
|
|
||||||
|
def toggleWidgetVis(self):
|
||||||
|
if self.widgetParent == 'direct':
|
||||||
|
self.reparentWidgetTo('hidden')
|
||||||
|
else:
|
||||||
|
self.reparentWidgetTo('direct')
|
||||||
|
|
||||||
class DisplayRegionList:
|
class DisplayRegionList:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.displayRegionList = []
|
self.displayRegionList = []
|
||||||
|
@ -113,12 +113,46 @@ class Messenger:
|
|||||||
"""
|
"""
|
||||||
self.dict.clear()
|
self.dict.clear()
|
||||||
|
|
||||||
|
def listAllEvents(self):
|
||||||
|
str = 'Messenger\n'
|
||||||
|
str = str + '='*50 + '\n'
|
||||||
|
keys = self.dict.keys()
|
||||||
|
keys.sort()
|
||||||
|
for event in keys:
|
||||||
|
str = str + 'Event: ' + event + '\n'
|
||||||
|
str = str + '='*50 + '\n'
|
||||||
|
print str
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
"""__repr__(self)
|
"""__repr__(self)
|
||||||
Print out the table in a readable format
|
Print out the table in a readable format
|
||||||
"""
|
"""
|
||||||
str = 'Messenger\n'
|
str = 'Messenger\n'
|
||||||
str = str + '='*50 + '\n'
|
str = str + '='*50 + '\n'
|
||||||
|
keys = self.dict.keys()
|
||||||
|
keys.sort()
|
||||||
|
for event in keys:
|
||||||
|
acceptorDict = self.dict[event]
|
||||||
|
str = str + 'Event: ' + event + '\n'
|
||||||
|
for object in acceptorDict.keys():
|
||||||
|
method, extraArgs, persistent = acceptorDict[object]
|
||||||
|
className = object.__class__.__name__
|
||||||
|
methodName = method.__name__
|
||||||
|
str = (str + '\t' +
|
||||||
|
'Acceptor: ' + className + ' instance' + '\n\t' +
|
||||||
|
'Method: ' + methodName + '\n\t' +
|
||||||
|
'Extra Args: ' + `extraArgs` + '\n\t' +
|
||||||
|
'Persistent: ' + `persistent` + '\n\n'
|
||||||
|
)
|
||||||
|
str = str + '='*50 + '\n'
|
||||||
|
return str
|
||||||
|
|
||||||
|
def __reprehensible__(self):
|
||||||
|
"""__repr__(self)
|
||||||
|
Old way to print out the table in a readable format
|
||||||
|
"""
|
||||||
|
str = 'Messenger\n'
|
||||||
|
str = str + '='*50 + '\n'
|
||||||
for event in self.dict.keys():
|
for event in self.dict.keys():
|
||||||
acceptorDict = self.dict[event]
|
acceptorDict = self.dict[event]
|
||||||
str = str + event + '\n'
|
str = str + event + '\n'
|
||||||
@ -129,3 +163,7 @@ class Messenger:
|
|||||||
return str
|
return str
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user