mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
*** empty log message ***
This commit is contained in:
parent
21933936d5
commit
11cdb8a6be
@ -55,7 +55,10 @@ class DirectJoybox(PandaObject):
|
||||
self.refCS = direct.cameraControl.coaMarker
|
||||
self.tempCS = direct.group.attachNewNode('JoyboxTempCS')
|
||||
# Text object to display current mode
|
||||
self.readout = OnscreenText.OnscreenText( pos = (-0.9, 0.95) )
|
||||
self.readout = OnscreenText.OnscreenText(
|
||||
pos = (-0.9, 0.95),
|
||||
font = direct.font,
|
||||
mayChange = 1)
|
||||
# List of functions to cycle through
|
||||
self.modeList = [self.joeMode, self.driveMode, self.orbitMode]
|
||||
# Pick initial mode
|
||||
|
@ -8,10 +8,11 @@ Y_AXIS = Vec3(0,1,0)
|
||||
class DirectCameraControl(PandaObject):
|
||||
def __init__(self):
|
||||
# Create the grid
|
||||
self.startT = 0.0
|
||||
self.startF = 0
|
||||
self.orthoViewRoll = 0.0
|
||||
self.lastView = 0
|
||||
self.coa = Point3(0,100,0)
|
||||
self.coaDist = 100
|
||||
self.coaMarker = loader.loadModel('models/misc/sphere')
|
||||
self.coaMarker.setName('DirectCameraCOAMarker')
|
||||
self.coaMarker.setTransparency(1)
|
||||
@ -19,7 +20,10 @@ class DirectCameraControl(PandaObject):
|
||||
self.coaMarker.setPos(0,100,0)
|
||||
useDirectRenderStyle(self.coaMarker)
|
||||
self.coaMarkerPos = Point3(0)
|
||||
self.fUpdateCOA = 1
|
||||
self.fLockCOA = 1
|
||||
self.nullHitPtCount = 0
|
||||
self.cqEntries = []
|
||||
self.coaMarkerRef = direct.group.attachNewNode('coaMarkerRef')
|
||||
self.camManipRef = direct.group.attachNewNode('camManipRef')
|
||||
t = CAM_MOVE_DURATION
|
||||
self.actionEvents = [
|
||||
@ -64,13 +68,9 @@ class DirectCameraControl(PandaObject):
|
||||
# MOUSE IS IN CENTRAL REGION
|
||||
# Hide the marker for this kind of motion
|
||||
self.coaMarker.hide()
|
||||
# Check for a hit point based on
|
||||
# current mouse position
|
||||
# Allow intersection with unpickable objects
|
||||
# And then spawn task to determine mouse mode
|
||||
node, hitPt, hitPtDist = direct.iRay.pickGeom(
|
||||
fIntersectUnpickable = 1)
|
||||
self.computeCOA(node, hitPt, hitPtDist)
|
||||
# Record time of start of mouse interaction
|
||||
self.startT= globalClock.getFrameTime()
|
||||
self.startF = globalClock.getFrameCount()
|
||||
# Start manipulation
|
||||
self.spawnXZTranslateOrHPanYZoom()
|
||||
# END MOUSE IN CENTRAL REGION
|
||||
@ -85,6 +85,24 @@ class DirectCameraControl(PandaObject):
|
||||
|
||||
def mouseFlyStop(self):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
stopT = globalClock.getFrameTime()
|
||||
deltaT = stopT - self.startT
|
||||
stopF = globalClock.getFrameCount()
|
||||
deltaF = stopF - self.startF
|
||||
if (deltaT <= 0.25) or (deltaF <= 1):
|
||||
# Check for a hit point based on
|
||||
# current mouse position
|
||||
# Allow intersection with unpickable objects
|
||||
# And then spawn task to determine mouse mode
|
||||
node, hitPt, hitPtDist = direct.iRay.pickGeom(
|
||||
fIntersectUnpickable = 1, fIgnoreCamera = 1)
|
||||
self.computeCOA(node, hitPt, hitPtDist)
|
||||
# Record reference point
|
||||
self.coaMarkerRef.iPosHprScale(direct.iRay.collisionRef)
|
||||
# Record entries
|
||||
self.cqEntries = []
|
||||
for i in range(direct.iRay.cq.getNumEntries()):
|
||||
self.cqEntries.append(direct.iRay.cq.getEntry(i))
|
||||
# Show the marker
|
||||
self.coaMarker.show()
|
||||
# Resize it
|
||||
@ -96,7 +114,8 @@ class DirectCameraControl(PandaObject):
|
||||
# Spawn the new task
|
||||
t = Task.Task(self.XZTranslateOrHPanYZoomTask)
|
||||
# For HPanYZoom
|
||||
t.zoomSF = Vec3(self.coa).length()
|
||||
coaDist = Vec3(self.coaMarker.getPos(direct.camera)).length()
|
||||
t.zoomSF = (coaDist / direct.dr.near)
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def spawnXZTranslateOrHPPan(self):
|
||||
@ -117,7 +136,8 @@ class DirectCameraControl(PandaObject):
|
||||
taskMgr.removeTasksNamed('manipulateCamera')
|
||||
# Spawn new task
|
||||
t = Task.Task(self.HPanYZoomTask)
|
||||
t.zoomSF = Vec3(self.coa).length()
|
||||
coaDist = Vec3(self.coaMarker.getPos(direct.camera)).length()
|
||||
t.zoomSF = (coaDist / direct.dr.near)
|
||||
taskMgr.spawnTaskNamed(t, 'manipulateCamera')
|
||||
|
||||
def spawnHPPan(self):
|
||||
@ -155,15 +175,17 @@ class DirectCameraControl(PandaObject):
|
||||
|
||||
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()
|
||||
else:
|
||||
moveDir = Vec3(Y_AXIS)
|
||||
moveDir.assign(moveDir * (-2.0 * direct.dr.mouseDeltaY *
|
||||
state.zoomSF))
|
||||
if direct.dr.mouseDeltaY > 0.0:
|
||||
moveDir.setY(moveDir[1] * 1.0)
|
||||
direct.camera.setPosHpr(direct.camera,
|
||||
moveDir[0],
|
||||
moveDir[1],
|
||||
@ -247,54 +269,85 @@ class DirectCameraControl(PandaObject):
|
||||
return Task.cont
|
||||
|
||||
def lockCOA(self):
|
||||
self.fUpdateCOA = 0
|
||||
|
||||
self.fLockCOA = 1
|
||||
direct.message('COA Lock On')
|
||||
|
||||
def unlockCOA(self):
|
||||
self.fUpdateCOA = 1
|
||||
self.fLockCOA = 0
|
||||
direct.message('COA Lock Off')
|
||||
|
||||
def toggleCOALock(self):
|
||||
self.fUpdateCOA = 1 - self.fUpdateCOA
|
||||
self.fLockCOA = 1 - self.fLockCOA
|
||||
if self.fLockCOA:
|
||||
direct.message('COA Lock On')
|
||||
else:
|
||||
direct.message('COA Lock Off')
|
||||
|
||||
def pickNextCOA(self):
|
||||
""" Cycle through collision handler entries """
|
||||
node, hitPt, hitPtDist = direct.iRay.pickNext()
|
||||
self.computeCOA(node, hitPt, hitPtDist)
|
||||
if self.cqEntries:
|
||||
# Get next entry and rotate entries
|
||||
entry = self.cqEntries[0]
|
||||
self.cqEntries = self.cqEntries[1:] + self.cqEntries[:1]
|
||||
# Filter out object's under camera
|
||||
node = entry.getIntoNode()
|
||||
nodePath = render.findPathDownTo(node)
|
||||
if camera not in nodePath.getAncestry():
|
||||
# Compute hit point
|
||||
hitPt = direct.iRay.parentToHitPt(entry)
|
||||
# Move coa marker to new point
|
||||
self.updateCoa(hitPt, ref = self.coaMarkerRef)
|
||||
else:
|
||||
# Remove offending entry
|
||||
self.cqEntries = self.cqEntries[:-1]
|
||||
self.pickNextCOA()
|
||||
|
||||
def computeCOA(self, node, hitPt, hitPtDist):
|
||||
coa = Point3(0)
|
||||
if self.fUpdateCOA and node:
|
||||
# Set center of action
|
||||
coa.assign(hitPt)
|
||||
coaDist = hitPtDist
|
||||
# Handle case of bad coa point (too close or too far)
|
||||
if ((coaDist < (1.1 * direct.dr.near)) or
|
||||
(coaDist > direct.dr.far)):
|
||||
# Just use existing point
|
||||
coa.assign(self.coaMarker.getPos(direct.camera))
|
||||
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||
if coaDist < (1.1 * direct.dr.near):
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
else:
|
||||
# If no intersection point or COA is locked:
|
||||
if self.fLockCOA:
|
||||
# COA is locked, use existing point
|
||||
# Use existing point
|
||||
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)
|
||||
|
||||
def updateCoa(self, cam2point, coaDist = None):
|
||||
self.coa.set(cam2point[0], cam2point[1], cam2point[2])
|
||||
if coaDist:
|
||||
self.coaDist = coaDist
|
||||
# Reset hit point count
|
||||
self.nullHitPointCount = 0
|
||||
elif node:
|
||||
# Got a hit point (hit point is in camera coordinates)
|
||||
# Set center of action
|
||||
coa.assign(hitPt)
|
||||
# Handle case of bad coa point (too close or too far)
|
||||
if ((hitPtDist < (1.1 * direct.dr.near)) or
|
||||
(hitPtDist > direct.dr.far)):
|
||||
# Just use existing point
|
||||
coa.assign(self.coaMarker.getPos(direct.camera))
|
||||
# Reset hit point count
|
||||
self.nullHitPointCount = 0
|
||||
else:
|
||||
self.coaDist = Vec3(self.coa - ZERO_POINT).length()
|
||||
# Increment null hit point count
|
||||
self.nullHitPointCount = (self.nullHitPointCount + 1) % 7
|
||||
# No COA lock and no intersection point
|
||||
# Use a point out in front of camera
|
||||
# Distance to point increases on multiple null hit points
|
||||
# MRM: Would be nice to be able to control this
|
||||
# At least display it
|
||||
dist = pow(10.0, self.nullHitPointCount)
|
||||
direct.message('COA Distance: ' + `dist`)
|
||||
coa.set(0,dist,0)
|
||||
# Compute COA Dist
|
||||
coaDist = Vec3(coa - ZERO_POINT).length()
|
||||
if coaDist < (1.1 * direct.dr.near):
|
||||
coa.set(0,100,0)
|
||||
coaDist = 100
|
||||
# Update coa and marker
|
||||
self.updateCoa(coa, coaDist = coaDist)
|
||||
|
||||
def updateCoa(self, ref2point, coaDist = None, ref = None):
|
||||
self.coa.set(ref2point[0], ref2point[1], ref2point[2])
|
||||
if not coaDist:
|
||||
coaDist = Vec3(self.coa - ZERO_POINT).length()
|
||||
# Place the marker in render space
|
||||
self.coaMarker.setPos(direct.camera,self.coa)
|
||||
if ref == None:
|
||||
ref = base.cam
|
||||
self.coaMarker.setPos(ref, self.coa)
|
||||
# Resize it
|
||||
self.updateCoaMarkerSize(coaDist)
|
||||
# Record marker pos in render space
|
||||
|
@ -231,7 +231,7 @@ class DirectManipulationControl(PandaObject):
|
||||
else:
|
||||
# Mouse started in central region, xlate
|
||||
# Mode depends on shift key
|
||||
if direct.fShift:
|
||||
if direct.fShift or direct.fControl:
|
||||
self.xlateCamXY(state)
|
||||
else:
|
||||
self.xlateCamXZ(state)
|
||||
@ -367,7 +367,11 @@ class DirectManipulationControl(PandaObject):
|
||||
|
||||
def xlateCamXY(self, state):
|
||||
"""Constrained 2D motion perpendicular to camera's image plane
|
||||
This moves the object in the camera's XY plane"""
|
||||
This moves the object in the camera's XY plane if shift is held
|
||||
Moves object toward camera if control is held
|
||||
"""
|
||||
# Reset scaling init flag
|
||||
self.fScaleInit = 1
|
||||
# Now, where is the widget relative to current camera view
|
||||
vWidget2Camera = direct.widget.getPos(direct.camera)
|
||||
# If this is first time around, record initial y distance
|
||||
@ -378,15 +382,26 @@ class DirectManipulationControl(PandaObject):
|
||||
# Get widget's current xy coords in screen space
|
||||
coaCenter = getNearProjectionPoint(direct.widget)
|
||||
self.deltaNearX = coaCenter[0] - direct.dr.nearVec[0]
|
||||
# Reset scaling init flag
|
||||
self.fScaleInit = 1
|
||||
# Which way do we move the object?
|
||||
if direct.fControl:
|
||||
moveDir = Vec3(vWidget2Camera)
|
||||
# If widget is behind camera invert vector
|
||||
if moveDir[1] < 0.0:
|
||||
moveDir.assign(moveDir * -1)
|
||||
moveDir.normalize()
|
||||
else:
|
||||
moveDir = Vec3(Y_AXIS)
|
||||
# Move selected objects
|
||||
dr = direct.dr
|
||||
# Move object in y axis based on mouse motion
|
||||
newY = vWidget2Camera[1] + self.xlateSF * dr.mouseDeltaY
|
||||
# Put object at same relative point to mouse in X
|
||||
newX = (direct.dr.nearVec[0] + self.deltaNearX) * (newY/dr.near)
|
||||
direct.widget.setPos(direct.camera, newX, newY, vWidget2Camera[2])
|
||||
# Scale move dir
|
||||
moveDir.assign(moveDir * (2.0 * dr.mouseDeltaY * self.xlateSF))
|
||||
# Add it to current widget offset
|
||||
vWidget2Camera += moveDir
|
||||
# The object, however, stays at the same relative point to mouse in X
|
||||
vWidget2Camera.setX((dr.nearVec[0] + self.deltaNearX) *
|
||||
(vWidget2Camera[1]/dr.near))
|
||||
# Move widget
|
||||
direct.widget.setPos(direct.camera, vWidget2Camera)
|
||||
|
||||
def rotate2D(self, state):
|
||||
""" Virtual trackball rotation of widget """
|
||||
|
@ -403,6 +403,8 @@ class SelectionRay:
|
||||
self.ct = CollisionTraverser( RenderRelation.getClassType() )
|
||||
# Let the traverser know about the queue and the collision node
|
||||
self.ct.addCollider(self.rayCollisionNode, self.cq )
|
||||
# Reference node path (for picking next)
|
||||
self.collisionRef = direct.group.attachNewNode('collisionRef')
|
||||
# List of objects that can't be selected
|
||||
self.unpickable = UNPICKABLE
|
||||
|
||||
@ -414,7 +416,8 @@ class SelectionRay:
|
||||
if item in self.unpickable:
|
||||
self.unpickable.remove(item)
|
||||
|
||||
def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0):
|
||||
def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0,
|
||||
fIgnoreCamera = 0):
|
||||
self.collideWithGeom()
|
||||
self.pick(targetNodePath,
|
||||
direct.dr.mouseX,
|
||||
@ -425,9 +428,13 @@ class SelectionRay:
|
||||
for i in range(0,self.numEntries):
|
||||
entry = self.cq.getEntry(i)
|
||||
node = entry.getIntoNode()
|
||||
nodePath = render.findPathDownTo(node)
|
||||
# Don't pick hidden nodes
|
||||
if node.isHidden():
|
||||
pass
|
||||
elif fIgnoreCamera and (camera in nodePath.getAncestry()):
|
||||
# This avoids things parented to a camera. Good idea?
|
||||
pass
|
||||
# Can pick unpickable, use the first visible node
|
||||
elif fIntersectUnpickable:
|
||||
self.cqIndex = i
|
||||
@ -448,7 +455,8 @@ class SelectionRay:
|
||||
if(self.cqIndex >= 0):
|
||||
# Yes!
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(self.cqIndex)
|
||||
entry = self.cq.getEntry(self.cqIndex)
|
||||
hitPt = self.parentToHitPt(entry)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
@ -465,7 +473,8 @@ class SelectionRay:
|
||||
# Entry 0 is the closest hit point if multiple hits
|
||||
minPt = 0
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(minPt)
|
||||
entry = self.cq.getEntry(minPt)
|
||||
hitPt = self.parentToHitPt(entry)
|
||||
hitPtDist = Vec3(hitPt).length()
|
||||
# Get the associated collision queue object
|
||||
entry = self.cq.getEntry(minPt)
|
||||
@ -483,15 +492,18 @@ class SelectionRay:
|
||||
self.ct.traverse( targetNodePath.node() )
|
||||
self.numEntries = self.cq.getNumEntries()
|
||||
self.cq.sortEntries()
|
||||
# Record cam's current position (used for cycling through
|
||||
# other hit points)
|
||||
self.collisionRef.iPosHprScale(base.cam)
|
||||
return self.numEntries
|
||||
|
||||
def pickNext(self):
|
||||
def getHitPt(self, entry):
|
||||
if self.cqIndex >= 0:
|
||||
self.cqIndex = (self.cqIndex + 1) % self.numEntries
|
||||
entry = self.cq.getEntry(self.cqIndex)
|
||||
node = entry.getIntoNode()
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(self.cqIndex)
|
||||
hitPt = self.parentToHitPt(entry)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
@ -530,7 +542,8 @@ class SelectionRay:
|
||||
if(self.cqIndex >= 0):
|
||||
# Yes!
|
||||
# Find hit point in parent's space
|
||||
hitPt = self.parentToHitPt(self.cqIndex)
|
||||
entry = self.cq.getEntry(self.cqIndex)
|
||||
hitPt = self.parentToHitPt(entry)
|
||||
hitPtDist = Vec3(hitPt - ZERO_POINT).length()
|
||||
return (node, hitPt, hitPtDist)
|
||||
else:
|
||||
@ -561,9 +574,8 @@ class SelectionRay:
|
||||
def objectToHitPt(self, index):
|
||||
return self.cq.getEntry(index).getIntoIntersectionPoint()
|
||||
|
||||
def parentToHitPt(self, index):
|
||||
# Get the specified entry
|
||||
entry = self.cq.getEntry(index)
|
||||
def parentToHitPt(self, entry):
|
||||
# Get hit point
|
||||
hitPt = entry.getIntoIntersectionPoint()
|
||||
# Convert point from object local space to parent's space
|
||||
return entry.getInvWrtSpace().xformPoint(hitPt)
|
||||
|
@ -23,6 +23,10 @@ class DirectSession(PandaObject):
|
||||
# Establish a global pointer to the direct object early on
|
||||
# so dependant classes can access it in their code
|
||||
__builtin__.direct = self
|
||||
# These come early since they are used later on
|
||||
self.group = render.attachNewNode('DIRECT')
|
||||
self.font = loader.loadFont("models/fonts/Comic")
|
||||
|
||||
self.fEnabled = 0
|
||||
self.drList = DisplayRegionList()
|
||||
self.iRayList = map(lambda x: x.iRay, self.drList)
|
||||
@ -30,7 +34,6 @@ class DirectSession(PandaObject):
|
||||
self.camera = self.dr.camera
|
||||
self.iRay = self.dr.iRay
|
||||
|
||||
self.group = render.attachNewNode('DIRECT')
|
||||
self.cameraControl = DirectCameraControl()
|
||||
self.manipulationControl = DirectManipulationControl()
|
||||
self.useObjectHandles()
|
||||
@ -51,18 +54,28 @@ class DirectSession(PandaObject):
|
||||
|
||||
self.selectedNPReadout = OnscreenText.OnscreenText(
|
||||
pos = (-1.0, -0.9), bg=Vec4(1,1,1,1),
|
||||
scale = 0.05, align = TMALIGNLEFT)
|
||||
scale = 0.05, align = TMALIGNLEFT,
|
||||
mayChange = 1, font = self.font)
|
||||
# Make sure readout is never lit or drawn in wireframe
|
||||
useDirectRenderStyle(self.selectedNPReadout)
|
||||
self.selectedNPReadout.reparentTo( hidden )
|
||||
|
||||
self.activeParentReadout = OnscreenText.OnscreenText(
|
||||
pos = (-1.0, -0.975), bg=Vec4(1,1,1,1),
|
||||
scale = 0.05, align = TMALIGNLEFT)
|
||||
scale = 0.05, align = TMALIGNLEFT,
|
||||
mayChange = 1, font = self.font)
|
||||
# Make sure readout is never lit or drawn in wireframe
|
||||
useDirectRenderStyle(self.activeParentReadout)
|
||||
self.activeParentReadout.reparentTo( hidden )
|
||||
|
||||
self.directMessageReadout = OnscreenText.OnscreenText(
|
||||
pos = (-1.0, 0.9), bg=Vec4(1,1,1,1),
|
||||
scale = 0.05, align = TMALIGNLEFT,
|
||||
mayChange = 1, font = self.font)
|
||||
# Make sure readout is never lit or drawn in wireframe
|
||||
useDirectRenderStyle(self.directMessageReadout)
|
||||
self.directMessageReadout.reparentTo( hidden )
|
||||
|
||||
# Create a vrpn client vrpn-server or default
|
||||
if base.config.GetBool('want-vrpn', 0):
|
||||
from DirectDeviceManager import *
|
||||
@ -291,6 +304,7 @@ class DirectSession(PandaObject):
|
||||
self.selectedNPReadout.reparentTo(aspect2d)
|
||||
self.selectedNPReadout.setText(
|
||||
'Selected:' + dnp.name)
|
||||
self.selectedNPReadout.adjustAllPriorities(100)
|
||||
# Show the manipulation widget
|
||||
self.widget.showWidget()
|
||||
# Update camera controls coa to this point
|
||||
@ -346,6 +360,7 @@ class DirectSession(PandaObject):
|
||||
self.activeParentReadout.reparentTo(aspect2d)
|
||||
self.activeParentReadout.setText(
|
||||
'Active Parent:' + nodePath.getName())
|
||||
self.activeParentReadout.adjustAllPriorities(100)
|
||||
# Alert everyone else
|
||||
messenger.send('DIRECT_activeParent', [self.activeParent])
|
||||
|
||||
@ -577,6 +592,23 @@ class DirectSession(PandaObject):
|
||||
messenger.send('DIRECT_redo')
|
||||
|
||||
# UTILITY FUNCTIONS
|
||||
def message(self, text):
|
||||
taskMgr.removeTasksNamed('hideDirectMessage')
|
||||
taskMgr.removeTasksNamed('hideDirectMessageLater')
|
||||
self.directMessageReadout.reparentTo(aspect2d)
|
||||
self.directMessageReadout.setText(text)
|
||||
self.directMessageReadout.adjustAllPriorities(100)
|
||||
self.hideDirectMessageLater()
|
||||
|
||||
def hideDirectMessageLater(self):
|
||||
seq = Task.doLater(3.0, Task.Task(self.hideDirectMessage),
|
||||
'hideDirectMessage')
|
||||
t = taskMgr.spawnTaskNamed(seq, 'hideDirectMessageLater')
|
||||
|
||||
def hideDirectMessage(self, state):
|
||||
self.directMessageReadout.reparentTo(hidden)
|
||||
return Task.done
|
||||
|
||||
def useObjectHandles(self):
|
||||
self.widget = self.manipulationControl.objectHandles
|
||||
self.widget.reparentTo(direct.group)
|
||||
|
@ -35,7 +35,10 @@ Central Region:
|
||||
Up/Down/Left/Right: Moves object in plane parallel to camera's image
|
||||
plane
|
||||
Shift + LMB:
|
||||
Up/Down: Moves object's COA towards camera
|
||||
Up/Down: Moves object's COA in camera's XY plane
|
||||
Left/Right: Moves object parallel to camera's X axis
|
||||
Control + LMB:
|
||||
Up/Down: Moves object's COA toward Camera (in Y and Z)
|
||||
Left/Right: Moves object parallel to camera's X axis
|
||||
Alt + LMB (off of widget):
|
||||
Away from COA: scale object up
|
||||
@ -70,9 +73,25 @@ COA. Hit 'Tab' again to return to normal object manipulation mode.
|
||||
|
||||
All camera manipulation performed with middle mouse button (MMB).
|
||||
|
||||
Window is divided up into three regions: an outer frame, central region, and
|
||||
the four corners. Camera manipulation depends on where mouse interaction
|
||||
begins.
|
||||
Camera manipulation depends on where mouse interaction begins and the
|
||||
current center of action (COA).
|
||||
|
||||
The window is divided up into three regions: an outer frame, central region,
|
||||
and the four corners. A different manipulation mode is defined for each
|
||||
region and is described below.
|
||||
|
||||
The camera center of action (COA) determines the center of rotation of any
|
||||
rotation moves and the scale factor for any translation moves.
|
||||
|
||||
The COA is set by quickly clicking (less than .25 second or 1 frame) with
|
||||
the MMB in the central region. It is defined as the intersection point of
|
||||
the ray from the camera's origin, through the mouse with the model. If no
|
||||
intersection occurs, the COA is put out along the camera's Y axis. Each
|
||||
time the MMB is clicked with no intersection the COA moves further out
|
||||
along the Y axis.
|
||||
|
||||
Pressing 'L' toggles COA lock, when on, the COA is locked in its current
|
||||
location.
|
||||
|
||||
Central Region:
|
||||
MMB:
|
||||
@ -85,15 +104,12 @@ Central Region:
|
||||
Up/Down/Left/Right: shifts camera in image plane
|
||||
Outer Region:
|
||||
MMB:
|
||||
Up/Down/Left/Right: Rotates about current COA. The COA is set every
|
||||
time you press the MMB in the central region. It is defined as the
|
||||
intersection point of the ray from the camera's origin, through
|
||||
the mouse with the model (if no intersection, no change in the COA
|
||||
will result). If mouse stays within outer frame, motion about COA
|
||||
is constrained to a single axis. (parallel to camera's X axis when
|
||||
in left and right part of the frame and parallel to the camera's Z
|
||||
axis when in the top or bottom part of the frame)
|
||||
Shift MMB:
|
||||
Up/Down/Left/Right: Rotates about current COA. If mouse stays within
|
||||
outer frame, motion about COA is constrained to a single axis.
|
||||
(parallel to camera's X axis when in left and right part of the frame
|
||||
and parallel to the camera's Z axis when in the top or bottom part of
|
||||
the frame)
|
||||
Shift + MMB:
|
||||
Up/Down: Pitch about camera's X axis
|
||||
Left/Right: Yaw about camera's Z axis
|
||||
Four corners:
|
||||
|
Loading…
x
Reference in New Issue
Block a user