*** empty log message ***

This commit is contained in:
Mark Mine 2001-06-01 03:46:46 +00:00
parent 21933936d5
commit 11cdb8a6be
6 changed files with 214 additions and 83 deletions

View File

@ -55,7 +55,10 @@ class DirectJoybox(PandaObject):
self.refCS = direct.cameraControl.coaMarker self.refCS = direct.cameraControl.coaMarker
self.tempCS = direct.group.attachNewNode('JoyboxTempCS') self.tempCS = direct.group.attachNewNode('JoyboxTempCS')
# Text object to display current mode # 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 # List of functions to cycle through
self.modeList = [self.joeMode, self.driveMode, self.orbitMode] self.modeList = [self.joeMode, self.driveMode, self.orbitMode]
# Pick initial mode # Pick initial mode

View File

@ -8,10 +8,11 @@ Y_AXIS = Vec3(0,1,0)
class DirectCameraControl(PandaObject): class DirectCameraControl(PandaObject):
def __init__(self): def __init__(self):
# Create the grid # Create the grid
self.startT = 0.0
self.startF = 0
self.orthoViewRoll = 0.0 self.orthoViewRoll = 0.0
self.lastView = 0 self.lastView = 0
self.coa = Point3(0,100,0) self.coa = Point3(0,100,0)
self.coaDist = 100
self.coaMarker = loader.loadModel('models/misc/sphere') self.coaMarker = loader.loadModel('models/misc/sphere')
self.coaMarker.setName('DirectCameraCOAMarker') self.coaMarker.setName('DirectCameraCOAMarker')
self.coaMarker.setTransparency(1) self.coaMarker.setTransparency(1)
@ -19,7 +20,10 @@ class DirectCameraControl(PandaObject):
self.coaMarker.setPos(0,100,0) self.coaMarker.setPos(0,100,0)
useDirectRenderStyle(self.coaMarker) useDirectRenderStyle(self.coaMarker)
self.coaMarkerPos = Point3(0) 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') self.camManipRef = direct.group.attachNewNode('camManipRef')
t = CAM_MOVE_DURATION t = CAM_MOVE_DURATION
self.actionEvents = [ self.actionEvents = [
@ -64,13 +68,9 @@ 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()
# Check for a hit point based on # Record time of start of mouse interaction
# current mouse position self.startT= globalClock.getFrameTime()
# Allow intersection with unpickable objects self.startF = globalClock.getFrameCount()
# And then spawn task to determine mouse mode
node, hitPt, hitPtDist = direct.iRay.pickGeom(
fIntersectUnpickable = 1)
self.computeCOA(node, hitPt, hitPtDist)
# Start manipulation # Start manipulation
self.spawnXZTranslateOrHPanYZoom() self.spawnXZTranslateOrHPanYZoom()
# END MOUSE IN CENTRAL REGION # END MOUSE IN CENTRAL REGION
@ -85,6 +85,24 @@ class DirectCameraControl(PandaObject):
def mouseFlyStop(self): def mouseFlyStop(self):
taskMgr.removeTasksNamed('manipulateCamera') 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 # Show the marker
self.coaMarker.show() self.coaMarker.show()
# Resize it # Resize it
@ -96,7 +114,8 @@ class DirectCameraControl(PandaObject):
# Spawn the new task # Spawn the new task
t = Task.Task(self.XZTranslateOrHPanYZoomTask) t = Task.Task(self.XZTranslateOrHPanYZoomTask)
# For HPanYZoom # 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') taskMgr.spawnTaskNamed(t, 'manipulateCamera')
def spawnXZTranslateOrHPPan(self): def spawnXZTranslateOrHPPan(self):
@ -117,7 +136,8 @@ class DirectCameraControl(PandaObject):
taskMgr.removeTasksNamed('manipulateCamera') taskMgr.removeTasksNamed('manipulateCamera')
# Spawn new task # Spawn new task
t = Task.Task(self.HPanYZoomTask) 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') taskMgr.spawnTaskNamed(t, 'manipulateCamera')
def spawnHPPan(self): def spawnHPPan(self):
@ -155,15 +175,17 @@ class DirectCameraControl(PandaObject):
def HPanYZoomTask(self,state): def HPanYZoomTask(self,state):
if direct.fControl: if direct.fControl:
moveDir = Vec3(Y_AXIS)
else:
moveDir = Vec3(self.coaMarker.getPos(direct.camera)) moveDir = Vec3(self.coaMarker.getPos(direct.camera))
# If marker is behind camera invert vector # If marker is behind camera invert vector
if moveDir[1] < 0.0: if moveDir[1] < 0.0:
moveDir.assign(moveDir * -1) moveDir.assign(moveDir * -1)
moveDir.normalize() moveDir.normalize()
else:
moveDir = Vec3(Y_AXIS)
moveDir.assign(moveDir * (-2.0 * direct.dr.mouseDeltaY * moveDir.assign(moveDir * (-2.0 * direct.dr.mouseDeltaY *
state.zoomSF)) state.zoomSF))
if direct.dr.mouseDeltaY > 0.0:
moveDir.setY(moveDir[1] * 1.0)
direct.camera.setPosHpr(direct.camera, direct.camera.setPosHpr(direct.camera,
moveDir[0], moveDir[0],
moveDir[1], moveDir[1],
@ -247,54 +269,85 @@ class DirectCameraControl(PandaObject):
return Task.cont return Task.cont
def lockCOA(self): def lockCOA(self):
self.fUpdateCOA = 0 self.fLockCOA = 1
direct.message('COA Lock On')
def unlockCOA(self): def unlockCOA(self):
self.fUpdateCOA = 1 self.fLockCOA = 0
direct.message('COA Lock Off')
def toggleCOALock(self): 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): def pickNextCOA(self):
""" Cycle through collision handler entries """ """ Cycle through collision handler entries """
node, hitPt, hitPtDist = direct.iRay.pickNext() if self.cqEntries:
self.computeCOA(node, hitPt, hitPtDist) # 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): def computeCOA(self, node, hitPt, hitPtDist):
coa = Point3(0) coa = Point3(0)
if self.fUpdateCOA and node: if self.fLockCOA:
# Set center of action # COA is locked, use existing point
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:
# Use existing point # Use existing point
coa.assign(self.coaMarker.getPos(direct.camera)) coa.assign(self.coaMarker.getPos(direct.camera))
# 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:
# 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() coaDist = Vec3(coa - ZERO_POINT).length()
# Check again its not to close
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 # Update coa and marker
self.updateCoa(coa, coaDist) self.updateCoa(coa, coaDist = coaDist)
def updateCoa(self, cam2point, coaDist = None): def updateCoa(self, ref2point, coaDist = None, ref = None):
self.coa.set(cam2point[0], cam2point[1], cam2point[2]) self.coa.set(ref2point[0], ref2point[1], ref2point[2])
if coaDist: if not coaDist:
self.coaDist = coaDist coaDist = Vec3(self.coa - ZERO_POINT).length()
else:
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) if ref == None:
ref = base.cam
self.coaMarker.setPos(ref, self.coa)
# Resize it # Resize it
self.updateCoaMarkerSize(coaDist) self.updateCoaMarkerSize(coaDist)
# Record marker pos in render space # Record marker pos in render space

View File

@ -231,7 +231,7 @@ class DirectManipulationControl(PandaObject):
else: else:
# Mouse started in central region, xlate # Mouse started in central region, xlate
# Mode depends on shift key # Mode depends on shift key
if direct.fShift: if direct.fShift or direct.fControl:
self.xlateCamXY(state) self.xlateCamXY(state)
else: else:
self.xlateCamXZ(state) self.xlateCamXZ(state)
@ -367,7 +367,11 @@ class DirectManipulationControl(PandaObject):
def xlateCamXY(self, state): def xlateCamXY(self, state):
"""Constrained 2D motion perpendicular to camera's image plane """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 # Now, where is the widget relative to current camera view
vWidget2Camera = direct.widget.getPos(direct.camera) vWidget2Camera = direct.widget.getPos(direct.camera)
# If this is first time around, record initial y distance # 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 # Get widget's current xy coords in screen space
coaCenter = getNearProjectionPoint(direct.widget) coaCenter = getNearProjectionPoint(direct.widget)
self.deltaNearX = coaCenter[0] - direct.dr.nearVec[0] self.deltaNearX = coaCenter[0] - direct.dr.nearVec[0]
# Reset scaling init flag # Which way do we move the object?
self.fScaleInit = 1 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 # Move selected objects
dr = direct.dr dr = direct.dr
# Move object in y axis based on mouse motion # Scale move dir
newY = vWidget2Camera[1] + self.xlateSF * dr.mouseDeltaY moveDir.assign(moveDir * (2.0 * dr.mouseDeltaY * self.xlateSF))
# Put object at same relative point to mouse in X # Add it to current widget offset
newX = (direct.dr.nearVec[0] + self.deltaNearX) * (newY/dr.near) vWidget2Camera += moveDir
direct.widget.setPos(direct.camera, newX, newY, vWidget2Camera[2]) # 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): def rotate2D(self, state):
""" Virtual trackball rotation of widget """ """ Virtual trackball rotation of widget """

View File

@ -403,6 +403,8 @@ class SelectionRay:
self.ct = CollisionTraverser( RenderRelation.getClassType() ) self.ct = CollisionTraverser( RenderRelation.getClassType() )
# Let the traverser know about the queue and the collision node # Let the traverser know about the queue and the collision node
self.ct.addCollider(self.rayCollisionNode, self.cq ) 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 # List of objects that can't be selected
self.unpickable = UNPICKABLE self.unpickable = UNPICKABLE
@ -414,7 +416,8 @@ class SelectionRay:
if item in self.unpickable: if item in self.unpickable:
self.unpickable.remove(item) self.unpickable.remove(item)
def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0): def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0,
fIgnoreCamera = 0):
self.collideWithGeom() self.collideWithGeom()
self.pick(targetNodePath, self.pick(targetNodePath,
direct.dr.mouseX, direct.dr.mouseX,
@ -425,9 +428,13 @@ class SelectionRay:
for i in range(0,self.numEntries): for i in range(0,self.numEntries):
entry = self.cq.getEntry(i) entry = self.cq.getEntry(i)
node = entry.getIntoNode() node = entry.getIntoNode()
nodePath = render.findPathDownTo(node)
# Don't pick hidden nodes # Don't pick hidden nodes
if node.isHidden(): if node.isHidden():
pass 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 # Can pick unpickable, use the first visible node
elif fIntersectUnpickable: elif fIntersectUnpickable:
self.cqIndex = i self.cqIndex = i
@ -448,7 +455,8 @@ class SelectionRay:
if(self.cqIndex >= 0): if(self.cqIndex >= 0):
# Yes! # Yes!
# Find hit point in parent's space # 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() hitPtDist = Vec3(hitPt - ZERO_POINT).length()
return (node, hitPt, hitPtDist) return (node, hitPt, hitPtDist)
else: else:
@ -465,7 +473,8 @@ class SelectionRay:
# Entry 0 is the closest hit point if multiple hits # Entry 0 is the closest hit point if multiple hits
minPt = 0 minPt = 0
# Find hit point in parent's space # Find hit point in parent's space
hitPt = self.parentToHitPt(minPt) entry = self.cq.getEntry(minPt)
hitPt = self.parentToHitPt(entry)
hitPtDist = Vec3(hitPt).length() hitPtDist = Vec3(hitPt).length()
# Get the associated collision queue object # Get the associated collision queue object
entry = self.cq.getEntry(minPt) entry = self.cq.getEntry(minPt)
@ -483,15 +492,18 @@ class SelectionRay:
self.ct.traverse( targetNodePath.node() ) self.ct.traverse( targetNodePath.node() )
self.numEntries = self.cq.getNumEntries() self.numEntries = self.cq.getNumEntries()
self.cq.sortEntries() self.cq.sortEntries()
# Record cam's current position (used for cycling through
# other hit points)
self.collisionRef.iPosHprScale(base.cam)
return self.numEntries return self.numEntries
def pickNext(self): def getHitPt(self, entry):
if self.cqIndex >= 0: if self.cqIndex >= 0:
self.cqIndex = (self.cqIndex + 1) % self.numEntries self.cqIndex = (self.cqIndex + 1) % self.numEntries
entry = self.cq.getEntry(self.cqIndex) entry = self.cq.getEntry(self.cqIndex)
node = entry.getIntoNode() node = entry.getIntoNode()
# Find hit point in parent's space # Find hit point in parent's space
hitPt = self.parentToHitPt(self.cqIndex) hitPt = self.parentToHitPt(entry)
hitPtDist = Vec3(hitPt - ZERO_POINT).length() hitPtDist = Vec3(hitPt - ZERO_POINT).length()
return (node, hitPt, hitPtDist) return (node, hitPt, hitPtDist)
else: else:
@ -530,7 +542,8 @@ class SelectionRay:
if(self.cqIndex >= 0): if(self.cqIndex >= 0):
# Yes! # Yes!
# Find hit point in parent's space # 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() hitPtDist = Vec3(hitPt - ZERO_POINT).length()
return (node, hitPt, hitPtDist) return (node, hitPt, hitPtDist)
else: else:
@ -561,9 +574,8 @@ class SelectionRay:
def objectToHitPt(self, index): def objectToHitPt(self, index):
return self.cq.getEntry(index).getIntoIntersectionPoint() return self.cq.getEntry(index).getIntoIntersectionPoint()
def parentToHitPt(self, index): def parentToHitPt(self, entry):
# Get the specified entry # Get hit point
entry = self.cq.getEntry(index)
hitPt = entry.getIntoIntersectionPoint() hitPt = entry.getIntoIntersectionPoint()
# Convert point from object local space to parent's space # Convert point from object local space to parent's space
return entry.getInvWrtSpace().xformPoint(hitPt) return entry.getInvWrtSpace().xformPoint(hitPt)

View File

@ -23,6 +23,10 @@ class DirectSession(PandaObject):
# Establish a global pointer to the direct object early on # Establish a global pointer to the direct object early on
# so dependant classes can access it in their code # so dependant classes can access it in their code
__builtin__.direct = self __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.fEnabled = 0
self.drList = DisplayRegionList() self.drList = DisplayRegionList()
self.iRayList = map(lambda x: x.iRay, self.drList) self.iRayList = map(lambda x: x.iRay, self.drList)
@ -30,7 +34,6 @@ class DirectSession(PandaObject):
self.camera = self.dr.camera self.camera = self.dr.camera
self.iRay = self.dr.iRay self.iRay = self.dr.iRay
self.group = render.attachNewNode('DIRECT')
self.cameraControl = DirectCameraControl() self.cameraControl = DirectCameraControl()
self.manipulationControl = DirectManipulationControl() self.manipulationControl = DirectManipulationControl()
self.useObjectHandles() self.useObjectHandles()
@ -51,18 +54,28 @@ class DirectSession(PandaObject):
self.selectedNPReadout = OnscreenText.OnscreenText( self.selectedNPReadout = OnscreenText.OnscreenText(
pos = (-1.0, -0.9), bg=Vec4(1,1,1,1), 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 # Make sure readout is never lit or drawn in wireframe
useDirectRenderStyle(self.selectedNPReadout) useDirectRenderStyle(self.selectedNPReadout)
self.selectedNPReadout.reparentTo( hidden ) self.selectedNPReadout.reparentTo( hidden )
self.activeParentReadout = OnscreenText.OnscreenText( self.activeParentReadout = OnscreenText.OnscreenText(
pos = (-1.0, -0.975), bg=Vec4(1,1,1,1), 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 # Make sure readout is never lit or drawn in wireframe
useDirectRenderStyle(self.activeParentReadout) useDirectRenderStyle(self.activeParentReadout)
self.activeParentReadout.reparentTo( hidden ) 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 # Create a vrpn client vrpn-server or default
if base.config.GetBool('want-vrpn', 0): if base.config.GetBool('want-vrpn', 0):
from DirectDeviceManager import * from DirectDeviceManager import *
@ -291,6 +304,7 @@ class DirectSession(PandaObject):
self.selectedNPReadout.reparentTo(aspect2d) self.selectedNPReadout.reparentTo(aspect2d)
self.selectedNPReadout.setText( self.selectedNPReadout.setText(
'Selected:' + dnp.name) 'Selected:' + dnp.name)
self.selectedNPReadout.adjustAllPriorities(100)
# Show the manipulation widget # Show the manipulation widget
self.widget.showWidget() self.widget.showWidget()
# Update camera controls coa to this point # Update camera controls coa to this point
@ -346,6 +360,7 @@ class DirectSession(PandaObject):
self.activeParentReadout.reparentTo(aspect2d) self.activeParentReadout.reparentTo(aspect2d)
self.activeParentReadout.setText( self.activeParentReadout.setText(
'Active Parent:' + nodePath.getName()) 'Active Parent:' + nodePath.getName())
self.activeParentReadout.adjustAllPriorities(100)
# Alert everyone else # Alert everyone else
messenger.send('DIRECT_activeParent', [self.activeParent]) messenger.send('DIRECT_activeParent', [self.activeParent])
@ -577,6 +592,23 @@ class DirectSession(PandaObject):
messenger.send('DIRECT_redo') messenger.send('DIRECT_redo')
# UTILITY FUNCTIONS # 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): def useObjectHandles(self):
self.widget = self.manipulationControl.objectHandles self.widget = self.manipulationControl.objectHandles
self.widget.reparentTo(direct.group) self.widget.reparentTo(direct.group)

View File

@ -35,7 +35,10 @@ Central Region:
Up/Down/Left/Right: Moves object in plane parallel to camera's image Up/Down/Left/Right: Moves object in plane parallel to camera's image
plane plane
Shift + LMB: 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 Left/Right: Moves object parallel to camera's X axis
Alt + LMB (off of widget): Alt + LMB (off of widget):
Away from COA: scale object up 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). All camera manipulation performed with middle mouse button (MMB).
Window is divided up into three regions: an outer frame, central region, and Camera manipulation depends on where mouse interaction begins and the
the four corners. Camera manipulation depends on where mouse interaction current center of action (COA).
begins.
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: Central Region:
MMB: MMB:
@ -85,15 +104,12 @@ Central Region:
Up/Down/Left/Right: shifts camera in image plane Up/Down/Left/Right: shifts camera in image plane
Outer Region: Outer Region:
MMB: MMB:
Up/Down/Left/Right: Rotates about current COA. The COA is set every Up/Down/Left/Right: Rotates about current COA. If mouse stays within
time you press the MMB in the central region. It is defined as the outer frame, motion about COA is constrained to a single axis.
intersection point of the ray from the camera's origin, through (parallel to camera's X axis when in left and right part of the frame
the mouse with the model (if no intersection, no change in the COA and parallel to the camera's Z axis when in the top or bottom part of
will result). If mouse stays within outer frame, motion about COA the frame)
is constrained to a single axis. (parallel to camera's X axis when Shift + MMB:
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 Up/Down: Pitch about camera's X axis
Left/Right: Yaw about camera's Z axis Left/Right: Yaw about camera's Z axis
Four corners: Four corners: