Updated to be compatible with new LE multi view control
This commit is contained in:
parent
34a80d821b
commit
7f6b94eba1
|
|
@ -2,6 +2,7 @@ from direct.showbase.DirectObject import DirectObject
|
|||
from DirectUtil import *
|
||||
from DirectGeometry import *
|
||||
from DirectGlobals import *
|
||||
from DirectSelection import SelectionRay
|
||||
from direct.interval.IntervalGlobal import Sequence, Func
|
||||
from direct.directnotify import DirectNotifyGlobal
|
||||
from direct.task import Task
|
||||
|
|
@ -124,8 +125,8 @@ class DirectCameraControl(DirectObject):
|
|||
self.startT= globalClock.getFrameTime()
|
||||
self.startF = globalClock.getFrameCount()
|
||||
# If the cam is orthogonal, spawn differentTask
|
||||
if (hasattr(base.direct.cam.node(), "getLens") and
|
||||
base.direct.cam.node().getLens().__class__.__name__ == "OrthographicLens"):
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
|
||||
base.direct.camera.getName() != 'persp':
|
||||
self.spawnOrthoZoom()
|
||||
else:
|
||||
# Start manipulation
|
||||
|
|
@ -144,7 +145,12 @@ class DirectCameraControl(DirectObject):
|
|||
self.startT= globalClock.getFrameTime()
|
||||
self.startF = globalClock.getFrameCount()
|
||||
# Start manipulation
|
||||
self.spawnXZTranslate()
|
||||
# If the cam is orthogonal, spawn differentTask
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
|
||||
base.direct.camera.getName() != 'persp':
|
||||
self.spawnOrthoTranslate()
|
||||
else:
|
||||
self.spawnXZTranslate()
|
||||
self.altDown = 1
|
||||
elif not self.useMayaCamControls:
|
||||
# Where are we in the display region?
|
||||
|
|
@ -231,6 +237,12 @@ class DirectCameraControl(DirectObject):
|
|||
# Spawn new task
|
||||
taskMgr.add(self.XZTranslateTask, 'manipulateCamera')
|
||||
|
||||
def spawnOrthoTranslate(self):
|
||||
# Kill any existing tasks
|
||||
taskMgr.remove('manipulateCamera')
|
||||
# Spawn new task
|
||||
taskMgr.add(self.OrthoTranslateTask, 'manipulateCamera')
|
||||
|
||||
def spawnHPanYZoom(self):
|
||||
# Kill any existing tasks
|
||||
taskMgr.remove('manipulateCamera')
|
||||
|
|
@ -279,6 +291,21 @@ class DirectCameraControl(DirectObject):
|
|||
xlateSF))
|
||||
return Task.cont
|
||||
|
||||
def OrthoTranslateTask(self, state):
|
||||
# create ray from the camera to detect 3d position
|
||||
iRay = SelectionRay(base.direct.camera)
|
||||
iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY)
|
||||
iRay.collideWithBitMask(1)
|
||||
iRay.ct.traverse(base.direct.grid)
|
||||
|
||||
entry = iRay.getEntry(0)
|
||||
hitPt = entry.getSurfacePoint(entry.getFromNodePath())
|
||||
del iRay
|
||||
if hasattr(state, 'prevPt'):
|
||||
base.direct.camera.setPos(base.direct.camera, (state.prevPt - hitPt))
|
||||
state.prevPt = hitPt
|
||||
return Task.cont
|
||||
|
||||
def HPanYZoomTask(self, state):
|
||||
# If the cam is orthogonal, don't rotate or zoom.
|
||||
if (hasattr(base.direct.cam.node(), "getLens") and
|
||||
|
|
@ -324,6 +351,8 @@ class DirectCameraControl(DirectObject):
|
|||
x = base.direct.dr.getWidth()
|
||||
y = base.direct.dr.getHeight()
|
||||
base.direct.dr.orthoFactor -= factor
|
||||
if base.direct.dr.orthoFactor < 0:
|
||||
base.direct.dr.orthoFactor = 0.0001
|
||||
base.direct.dr.updateFilmSize(x, y)
|
||||
return Task.cont
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from direct.showbase.DirectObject import DirectObject
|
|||
from DirectGlobals import *
|
||||
from DirectUtil import *
|
||||
from DirectGeometry import *
|
||||
from DirectSelection import SelectionRay
|
||||
from direct.task import Task
|
||||
import types
|
||||
|
||||
|
|
@ -11,6 +12,10 @@ class DirectManipulationControl(DirectObject):
|
|||
self.objectHandles = ObjectHandles()
|
||||
self.hitPt = Point3(0)
|
||||
self.prevHit = Vec3(0)
|
||||
|
||||
self.hitPtScale = Point3(0) # [gjeon] to be used in new LE's camera control
|
||||
self.prevHitScale = Vec3(0) # [gjeon] to be used in new LE's camera control
|
||||
|
||||
self.rotationCenter = Point3(0)
|
||||
self.initScaleMag = 1
|
||||
self.manipRef = base.direct.group.attachNewNode('manipRef')
|
||||
|
|
@ -21,9 +26,11 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fSetCoa = 0
|
||||
self.fHitInit = 1
|
||||
self.fScaleInit = 1
|
||||
self.fScaleInit1 = 1 # [gjeon] to be used in new LE's camera control
|
||||
self.fWidgetTop = 0
|
||||
self.fFreeManip = 1
|
||||
self.fScaling = 0
|
||||
self.fScaling3D = 0
|
||||
self.fScaling1D = 0
|
||||
self.fMovable = 1
|
||||
self.mode = None
|
||||
self.actionEvents = [
|
||||
|
|
@ -99,23 +106,28 @@ class DirectManipulationControl(DirectObject):
|
|||
if self.fAllowSelectionOnly:
|
||||
return
|
||||
|
||||
# Check for a widget hit point
|
||||
entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET)
|
||||
# Did we hit a widget?
|
||||
if entry:
|
||||
# Yes!
|
||||
self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath()))
|
||||
self.hitPtDist = Vec3(self.hitPt).length()
|
||||
# Constraint determined by nodes name
|
||||
self.constraint = entry.getIntoNodePath().getName()
|
||||
if self.fScaling1D == 0 and\
|
||||
self.fScaling3D == 0:
|
||||
|
||||
# Check for a widget hit point
|
||||
entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET)
|
||||
# Did we hit a widget?
|
||||
if entry:
|
||||
# Yes!
|
||||
self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath()))
|
||||
self.hitPtDist = Vec3(self.hitPt).length()
|
||||
# Constraint determined by nodes name
|
||||
self.constraint = entry.getIntoNodePath().getName()
|
||||
else:
|
||||
# Nope, off the widget, no constraint
|
||||
self.constraint = None
|
||||
# [gjeon] to prohibit unwanted object movement while direct window doesn't have focus
|
||||
if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers) \
|
||||
and not self.fAllowMarquee:
|
||||
return
|
||||
else:
|
||||
# Nope, off the widget, no constraint
|
||||
self.constraint = None
|
||||
# [gjeon] to prohibit unwanted object movement while direct window doesn't have focus
|
||||
if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers) \
|
||||
and not self.fAllowMarquee:
|
||||
return
|
||||
|
||||
entry = None
|
||||
|
||||
if not base.direct.gotAlt(modifiers):
|
||||
if entry:
|
||||
# Check to see if we are moving the object
|
||||
|
|
@ -170,6 +182,8 @@ class DirectManipulationControl(DirectObject):
|
|||
|
||||
if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
|
||||
return
|
||||
if base.direct.fControl:
|
||||
return
|
||||
|
||||
endX = base.direct.dr.mouseX
|
||||
endY = base.direct.dr.mouseY
|
||||
|
|
@ -315,22 +329,33 @@ class DirectManipulationControl(DirectObject):
|
|||
base.direct.select(entry.getIntoNodePath(), base.direct.fShift)
|
||||
else:
|
||||
base.direct.deselectAll()
|
||||
elif self.mode == 'move':
|
||||
self.manipulateObjectCleanup()
|
||||
#elif self.mode == 'move':
|
||||
self.manipulateObjectCleanup()
|
||||
|
||||
self.mode = None
|
||||
|
||||
def manipulateObjectCleanup(self):
|
||||
if self.fScaling:
|
||||
if self.fScaling3D or self.fScaling1D:
|
||||
# We had been scaling, need to reset object handles
|
||||
self.objectHandles.transferObjectHandlesScale()
|
||||
self.fScaling = 0
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.transferObjectHandlesScale()
|
||||
else:
|
||||
self.objectHandles.transferObjectHandlesScale()
|
||||
self.fScaling3D = 0
|
||||
self.fScaling1D = 0
|
||||
base.direct.selected.highlightAll()
|
||||
self.objectHandles.showAllHandles()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.showAllHandles()
|
||||
else:
|
||||
self.objectHandles.showAllHandles()
|
||||
if base.direct.clusterMode == 'client':
|
||||
cluster(
|
||||
'base.direct.manipulationControl.objectHandles.showAllHandles()')
|
||||
self.objectHandles.hideGuides()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.hideGuides()
|
||||
else:
|
||||
self.objectHandles.hideGuides()
|
||||
|
||||
# Restart followSelectedNodePath task
|
||||
self.spawnFollowSelectedNodePathTask()
|
||||
messenger.send('DIRECT_manipulateObjectCleanup',
|
||||
|
|
@ -394,11 +419,20 @@ class DirectManipulationControl(DirectObject):
|
|||
self.fSetCoa = 1 - self.fSetCoa
|
||||
|
||||
if self.fSetCoa:
|
||||
self.objectHandles.coaModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.coaModeColor()
|
||||
else:
|
||||
self.objectHandles.coaModeColor()
|
||||
else:
|
||||
self.objectHandles.manipModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.manipModeColor()
|
||||
else:
|
||||
self.objectHandles.manipModeColor()
|
||||
else:
|
||||
self.objectHandles.disabledModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.disabledModeColor()
|
||||
else:
|
||||
self.objectHandles.disabledModeColor()
|
||||
|
||||
def removeManipulateObjectTask(self):
|
||||
taskMgr.remove('manipulateObject')
|
||||
|
|
@ -406,13 +440,22 @@ class DirectManipulationControl(DirectObject):
|
|||
def enableWidgetMove(self):
|
||||
self.fMovable = 1
|
||||
if self.fSetCoa:
|
||||
self.objectHandles.coaModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.coaModeColor()
|
||||
else:
|
||||
self.objectHandles.coaModeColor()
|
||||
else:
|
||||
self.objectHandles.manipModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.manipModeColor()
|
||||
else:
|
||||
self.objectHandles.manipModeColor()
|
||||
|
||||
def disableWidgetMove(self):
|
||||
self.fMovable = 0
|
||||
self.objectHandles.disabledModeColor()
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.disableModeColor()
|
||||
else:
|
||||
self.objectHandles.disabledModeColor()
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# Function: get edit types list for specified objects which indicate
|
||||
|
|
@ -452,9 +495,14 @@ class DirectManipulationControl(DirectObject):
|
|||
# Record undo point
|
||||
base.direct.pushUndo(base.direct.selected)
|
||||
# Update object handles visibility
|
||||
self.objectHandles.showGuides()
|
||||
self.objectHandles.hideAllHandles()
|
||||
self.objectHandles.showHandle(self.constraint)
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.showGuides()
|
||||
base.direct.widget.hideAllHandles()
|
||||
base.direct.widget.showHandle(self.constraint)
|
||||
else:
|
||||
self.objectHandles.showGuides()
|
||||
self.objectHandles.hideAllHandles()
|
||||
self.objectHandles.showHandle(self.constraint)
|
||||
if base.direct.clusterMode == 'client':
|
||||
oh = 'base.direct.manipulationControl.objectHandles'
|
||||
cluster(oh + '.showGuides()', 0)
|
||||
|
|
@ -474,6 +522,9 @@ class DirectManipulationControl(DirectObject):
|
|||
# reset hit-pt flag
|
||||
self.fHitInit = 1
|
||||
self.fScaleInit = 1
|
||||
if not self.fScaling1D and\
|
||||
not self.fScaling3D:
|
||||
self.fScaleInit1 = 1
|
||||
# record initial offset between widget and camera
|
||||
t = Task.Task(self.manipulateObjectTask)
|
||||
t.fMouseX = abs(base.direct.dr.mouseX) > 0.9
|
||||
|
|
@ -490,56 +541,66 @@ class DirectManipulationControl(DirectObject):
|
|||
taskMgr.add(t, 'manipulateObject')
|
||||
|
||||
def manipulateObjectTask(self, state):
|
||||
# Widget takes precedence
|
||||
if self.constraint:
|
||||
type = self.constraint[2:]
|
||||
if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
|
||||
if type == 'post':
|
||||
# [gjeon] non-uniform scaling
|
||||
self.fScaling = 1
|
||||
self.scale1D(state)
|
||||
if self.fScaling1D:
|
||||
self.scale1D(state)
|
||||
elif self.fScaling3D:
|
||||
self.scale3D(state)
|
||||
else:
|
||||
# Widget takes precedence
|
||||
if self.constraint:
|
||||
type = self.constraint[2:]
|
||||
if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
|
||||
if type == 'post':
|
||||
# [gjeon] non-uniform scaling
|
||||
self.fScaling1D = 1
|
||||
self.scale1D(state)
|
||||
else:
|
||||
# [gjeon] uniform scaling
|
||||
self.fScaling3D = 1
|
||||
self.scale3D(state)
|
||||
else:
|
||||
# [gjeon] uniform scaling
|
||||
self.fScaling = 1
|
||||
self.scale3D(state)
|
||||
else:
|
||||
if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
self.xlate1D(state)
|
||||
elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
self.xlate2D(state)
|
||||
elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
|
||||
self.rotate1D(state)
|
||||
# No widget interaction, determine free manip mode
|
||||
elif self.fFreeManip:
|
||||
# If we've been scaling and changed modes, reset object handles
|
||||
if 0 and self.fScaling and (not base.direct.fAlt):
|
||||
self.objectHandles.transferObjectHandlesScale()
|
||||
self.fScaling = 0
|
||||
# Alt key switches to a scaling mode
|
||||
if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
|
||||
self.fScaling = 1
|
||||
self.scale3D(state)
|
||||
# Otherwise, manip mode depends on where you started
|
||||
elif state.fMouseX and state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
|
||||
# In the corner, spin around camera's axis
|
||||
self.rotateAboutViewVector(state)
|
||||
elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
# Mouse started elsewhere in the outer frame, rotate
|
||||
self.rotate2D(state)
|
||||
elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
# Mouse started in central region, xlate
|
||||
# Mode depends on shift key
|
||||
if base.direct.fShift or base.direct.fControl:
|
||||
self.xlateCamXY(state)
|
||||
else:
|
||||
self.xlateCamXZ(state)
|
||||
if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
self.xlate1D(state)
|
||||
elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
self.xlate2D(state)
|
||||
elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
|
||||
self.rotate1D(state)
|
||||
# No widget interaction, determine free manip mode
|
||||
elif self.fFreeManip:
|
||||
# If we've been scaling and changed modes, reset object handles
|
||||
if 0 and (self.fScaling1D or self.fScaling3D) and (not base.direct.fAlt):
|
||||
if hasattr(base.direct, 'widget'):
|
||||
base.direct.widget.transferObjectHandleScale()
|
||||
else:
|
||||
self.objectHandles.transferObjectHandlesScale()
|
||||
|
||||
self.fScaling1D = 0
|
||||
self.fScaling3D = 0
|
||||
# Alt key switches to a scaling mode
|
||||
if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
|
||||
self.fScaling3D = 1
|
||||
self.scale3D(state)
|
||||
# Otherwise, manip mode depends on where you started
|
||||
elif state.fMouseX and state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
|
||||
# In the corner, spin around camera's axis
|
||||
self.rotateAboutViewVector(state)
|
||||
elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
# Mouse started elsewhere in the outer frame, rotate
|
||||
self.rotate2D(state)
|
||||
elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
|
||||
# Mouse started in central region, xlate
|
||||
# Mode depends on shift key
|
||||
if base.direct.fShift or base.direct.fControl:
|
||||
self.xlateCamXY(state)
|
||||
else:
|
||||
self.xlateCamXZ(state)
|
||||
if self.fSetCoa:
|
||||
# Update coa based on current widget position
|
||||
base.direct.selected.last.mCoa2Dnp.assign(
|
||||
base.direct.widget.getMat(base.direct.selected.last))
|
||||
else:
|
||||
# Move the objects with the widget
|
||||
base.direct.selected.moveWrtWidgetAll()
|
||||
base.direct.selected.moveWrtWidgetAll()
|
||||
# Continue
|
||||
return Task.cont
|
||||
|
||||
|
|
@ -550,39 +611,45 @@ class DirectManipulationControl(DirectObject):
|
|||
def removeTag(self, tag):
|
||||
self.unmovableTagList.remove(tag)
|
||||
|
||||
def gridSnapping(self, offset):
|
||||
offsetX = offset.getX()
|
||||
offsetY = offset.getY()
|
||||
offsetZ = offset.getZ()
|
||||
if math.fabs(offsetX) < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetX = 0
|
||||
def gridSnapping(self, nodePath, offset):
|
||||
offsetX = nodePath.getX() + offset.getX()
|
||||
offsetY = nodePath.getY() + offset.getY()
|
||||
offsetZ = nodePath.getZ() + offset.getZ()
|
||||
|
||||
if offsetX < 0.0:
|
||||
signX = -1.0
|
||||
else:
|
||||
if offsetX < 0:
|
||||
offsetX = -1 * base.direct.grid.gridSpacing
|
||||
else:
|
||||
offsetX = base.direct.grid.gridSpacing
|
||||
|
||||
if math.fabs(offsetY) < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetY = 0
|
||||
signX = 1.0
|
||||
modX = math.fabs(offsetX) % base.direct.grid.gridSpacing
|
||||
floorX = math.floor(math.fabs(offsetX) / base.direct.grid.gridSpacing)
|
||||
if modX < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetX = signX * floorX * base.direct.grid.gridSpacing
|
||||
else:
|
||||
if offsetY < 0:
|
||||
offsetY = -1 * base.direct.grid.gridSpacing
|
||||
else:
|
||||
offsetY = base.direct.grid.gridSpacing
|
||||
offsetX = signX * (floorX + 1) * base.direct.grid.gridSpacing
|
||||
|
||||
if math.fabs(offsetZ) < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetZ = 0
|
||||
if offsetY < 0.0:
|
||||
signY = -1.0
|
||||
else:
|
||||
if offsetZ < 0:
|
||||
offsetZ = -1 * base.direct.grid.gridSpacing
|
||||
else:
|
||||
offsetZ = base.direct.grid.gridSpacing
|
||||
signY = 1.0
|
||||
modY = math.fabs(offsetY) % base.direct.grid.gridSpacing
|
||||
floorY = math.floor(math.fabs(offsetY) / base.direct.grid.gridSpacing)
|
||||
if modY < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetY = signY * floorY * base.direct.grid.gridSpacing
|
||||
else:
|
||||
offsetY = signY * (floorY + 1) * base.direct.grid.gridSpacing
|
||||
|
||||
offset.setX(offsetX)
|
||||
offset.setY(offsetY)
|
||||
offset.setZ(offsetZ)
|
||||
if offsetZ < 0.0:
|
||||
signZ = -1.0
|
||||
else:
|
||||
signZ = 1.0
|
||||
modZ = math.fabs(offsetZ) % base.direct.grid.gridSpacing
|
||||
floorZ = math.floor(math.fabs(offsetZ) / base.direct.grid.gridSpacing)
|
||||
if modZ < base.direct.grid.gridSpacing / 2.0:
|
||||
offsetZ = signZ * floorZ * base.direct.grid.gridSpacing
|
||||
else:
|
||||
offsetZ = signZ * (floorZ + 1) * base.direct.grid.gridSpacing
|
||||
|
||||
return offset
|
||||
return Point3(offsetX, offsetY, offsetZ)
|
||||
|
||||
### WIDGET MANIPULATION METHODS ###
|
||||
def xlate1D(self, state):
|
||||
|
|
@ -601,14 +668,19 @@ class DirectManipulationControl(DirectObject):
|
|||
# Move widget to keep hit point as close to mouse as possible
|
||||
offset = self.hitPt - self.prevHit
|
||||
|
||||
if self.fGridSnap:
|
||||
offset = self.gridSnapping(offset)
|
||||
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
|
||||
for widget in base.direct.manipulationControl.widgetList:
|
||||
widget.setPos(widget, offset)
|
||||
if self.fGridSnap:
|
||||
widget.setPos(self.gridSnapping(widget, offset))
|
||||
else:
|
||||
widget.setPos(widget, offset)
|
||||
if base.direct.camera.getName() != 'persp':
|
||||
self.prevHit.assign(self.hitPt)
|
||||
else:
|
||||
base.direct.widget.setPos(base.direct.widget, offset)
|
||||
if self.fGridSnap:
|
||||
base.direct.widget.setPos(self.gridSnapping(base.direct.widget, offset))
|
||||
else:
|
||||
base.direct.widget.setPos(base.direct.widget, offset)
|
||||
|
||||
def xlate2D(self, state):
|
||||
# Constrained 2D (planar) translation
|
||||
|
|
@ -617,6 +689,7 @@ class DirectManipulationControl(DirectObject):
|
|||
# This point tracks all subsequent mouse movements
|
||||
self.hitPt.assign(self.objectHandles.getWidgetIntersectPt(
|
||||
base.direct.widget, self.constraint[:1]))
|
||||
|
||||
# use it to see how far to move the widget
|
||||
if self.fHitInit:
|
||||
# First time through just record hit point
|
||||
|
|
@ -625,14 +698,19 @@ class DirectManipulationControl(DirectObject):
|
|||
else:
|
||||
offset = self.hitPt - self.prevHit
|
||||
|
||||
if self.fGridSnap:
|
||||
offset = self.gridSnapping(offset)
|
||||
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
|
||||
for widget in base.direct.manipulationControl.widgetList:
|
||||
widget.setPos(widget, offset)
|
||||
if self.fGridSnap:
|
||||
widget.setPos(self.gridSnapping(widget, offset))
|
||||
else:
|
||||
widget.setPos(widget, offset)
|
||||
if base.direct.camera.getName() != 'persp':
|
||||
self.prevHit.assign(self.hitPt)
|
||||
else:
|
||||
base.direct.widget.setPos(base.direct.widget, offset)
|
||||
if self.fGridSnap:
|
||||
base.direct.widget.setPos(self.gridSnapping(base.direct.widget, offset))
|
||||
else:
|
||||
base.direct.widget.setPos(base.direct.widget, offset)
|
||||
|
||||
def rotate1D(self, state):
|
||||
# Constrained 1D rotation about the widget's main axis (X, Y, or Z)
|
||||
|
|
@ -722,6 +800,7 @@ class DirectManipulationControl(DirectObject):
|
|||
# Move widget (and objects) based upon mouse motion
|
||||
# Scaled up accordingly based upon widget distance
|
||||
dr = base.direct.dr
|
||||
|
||||
base.direct.widget.setX(
|
||||
base.direct.camera,
|
||||
x + 0.5 * dr.mouseDeltaX * dr.nearWidth * (y/dr.near))
|
||||
|
|
@ -764,6 +843,7 @@ class DirectManipulationControl(DirectObject):
|
|||
# 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
|
||||
base.direct.widget.setPos(base.direct.camera, vWidget2Camera)
|
||||
|
||||
|
|
@ -801,6 +881,38 @@ class DirectManipulationControl(DirectObject):
|
|||
relHpr(base.direct.widget, base.direct.camera, 0, 0, -deltaAngle)
|
||||
|
||||
def scale1D(self, state):
|
||||
print self.constraint
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
|
||||
self.hitPtScale.assign(self.objectHandles.getMouseIntersectPt())
|
||||
|
||||
if self.fScaleInit1:
|
||||
# First time through just record hit point
|
||||
self.fScaleInit1 = 0
|
||||
self.prevHitScale.assign(self.hitPtScale)
|
||||
else:
|
||||
widgetPos = base.direct.widget.getPos()
|
||||
d0 = (self.prevHitScale - widgetPos).length()
|
||||
d1 = (self.hitPtScale - widgetPos).length()
|
||||
offset = d1 - d0
|
||||
currScale = base.direct.widget.getScale()
|
||||
|
||||
# Scale factor is ratio current mag with init mag
|
||||
if self.constraint[:1] == 'x':
|
||||
currScale = Vec3(currScale.getX() + offset, currScale.getY(), currScale.getZ())
|
||||
if currScale.getX() < 0.0:
|
||||
currScale.setX(0.01)
|
||||
elif self.constraint[:1] == 'y':
|
||||
currScale = Vec3(currScale.getX(), currScale.getY() + offset, currScale.getZ())
|
||||
if currScale.getY() < 0.0:
|
||||
currScale.setY(0.01)
|
||||
elif self.constraint[:1] == 'z':
|
||||
currScale = Vec3(currScale.getX(), currScale.getY(), currScale.getZ() + offset)
|
||||
if currScale.getZ() < 0.0:
|
||||
currScale.setZ(0.01)
|
||||
base.direct.widget.setScale(currScale)
|
||||
self.prevHitScale.assign(self.hitPtScale)
|
||||
return
|
||||
|
||||
# [gjeon] Constrained 1D scale of the selected node based upon up down mouse motion
|
||||
if self.fScaleInit:
|
||||
self.fScaleInit = 0
|
||||
|
|
@ -830,6 +942,27 @@ class DirectManipulationControl(DirectObject):
|
|||
base.direct.widget.setScale(currScale)
|
||||
|
||||
def scale3D(self, state):
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
|
||||
self.hitPtScale.assign(self.objectHandles.getMouseIntersectPt())
|
||||
|
||||
if self.fScaleInit1:
|
||||
# First time through just record hit point
|
||||
self.fScaleInit1 = 0
|
||||
self.prevHitScale.assign(self.hitPtScale)
|
||||
else:
|
||||
widgetPos = base.direct.widget.getPos()
|
||||
d0 = (self.prevHitScale - widgetPos).length()
|
||||
d1 = (self.hitPtScale - widgetPos).length()
|
||||
offset = d1 - d0
|
||||
currScale = base.direct.widget.getScale()
|
||||
currScale += offset
|
||||
if currScale.getX() < 0.0 and\
|
||||
currScale.getY() < 0.0 and\
|
||||
currScale.getZ() < 0.0:
|
||||
currScale = VBase3(0.01, 0.01, 0.01)
|
||||
base.direct.widget.setScale(currScale)
|
||||
self.prevHitScale.assign(self.hitPtScale)
|
||||
return
|
||||
# Scale the selected node based upon up down mouse motion
|
||||
# Mouse motion from edge to edge results in a factor of 4 scaling
|
||||
# From midpoint to edge doubles or halves objects scale
|
||||
|
|
@ -1328,6 +1461,35 @@ class ObjectHandles(NodePath, DirectObject):
|
|||
lines.setName('z-guide')
|
||||
|
||||
def getAxisIntersectPt(self, axis):
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
|
||||
base.direct.camera.getName() != 'persp':
|
||||
# create ray from the camera to detect 3d position
|
||||
iRay = SelectionRay(base.direct.camera)
|
||||
iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY)
|
||||
iRay.collideWithBitMask(1)
|
||||
iRay.ct.traverse(base.direct.grid)
|
||||
|
||||
entry = iRay.getEntry(0)
|
||||
hitPt = entry.getSurfacePoint(entry.getFromNodePath())
|
||||
|
||||
# create a temp nodePath to get the position
|
||||
np = NodePath('temp')
|
||||
np.setPos(base.direct.camera, hitPt)
|
||||
self.hitPt.assign(np.getPos())
|
||||
np.remove()
|
||||
del iRay
|
||||
if axis == 'x':
|
||||
# We really only care about the nearest point on the axis
|
||||
self.hitPt.setY(0)
|
||||
self.hitPt.setZ(0)
|
||||
elif axis == 'y':
|
||||
self.hitPt.setX(0)
|
||||
self.hitPt.setZ(0)
|
||||
elif axis == 'z':
|
||||
self.hitPt.setX(0)
|
||||
self.hitPt.setY(0)
|
||||
return self.hitPt
|
||||
|
||||
# Calc the xfrom from camera to widget
|
||||
mCam2Widget = base.direct.camera.getMat(base.direct.widget)
|
||||
lineDir = Vec3(mCam2Widget.xformVec(base.direct.dr.nearVec))
|
||||
|
|
@ -1372,7 +1534,31 @@ class ObjectHandles(NodePath, DirectObject):
|
|||
self.hitPt.setY(0)
|
||||
return self.hitPt
|
||||
|
||||
def getMouseIntersectPt(self):
|
||||
# create ray from the camera to detect 3d position
|
||||
iRay = SelectionRay(base.direct.camera)
|
||||
iRay.collider.setFromLens(base.direct.camNode, base.direct.dr.mouseX, base.direct.dr.mouseY)
|
||||
iRay.collideWithBitMask(1)
|
||||
iRay.ct.traverse(base.direct.grid)
|
||||
|
||||
entry = iRay.getEntry(0)
|
||||
hitPt = entry.getSurfacePoint(entry.getFromNodePath())
|
||||
|
||||
# create a temp nodePath to get the position
|
||||
np = NodePath('temp')
|
||||
np.setPos(base.direct.camera, hitPt)
|
||||
resultPt = Point3(0)
|
||||
resultPt.assign(np.getPos())
|
||||
np.remove()
|
||||
del iRay
|
||||
return resultPt
|
||||
|
||||
def getWidgetIntersectPt(self, nodePath, plane):
|
||||
if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView and\
|
||||
base.direct.camera.getName() != 'persp':
|
||||
self.hitPt.assign(self.getMouseIntersectPt())
|
||||
return self.hitPt
|
||||
|
||||
# Find out the point of interection of the ray passing though the mouse
|
||||
# with the plane containing the 2D xlation or 1D rotation widgets
|
||||
|
||||
|
|
@ -1399,6 +1585,7 @@ class ObjectHandles(NodePath, DirectObject):
|
|||
elif plane == 'z':
|
||||
self.hitPt.assign(planeIntersect(
|
||||
lineOrigin, lineDir, ORIGIN, Z_AXIS))
|
||||
|
||||
return self.hitPt
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ class DirectSession(DirectObject):
|
|||
self.fEnabled = 0
|
||||
self.fEnabledLight = 0
|
||||
self.fScaleWidgetByCam = 0 # [gjeon] flag for scaling widget by distance from the camera
|
||||
self.fIgnoreDirectOnlyKeyMap = 0 # [gjeon] to skip old direct controls in new LE
|
||||
|
||||
self.drList = DisplayRegionList()
|
||||
self.iRayList = map(lambda x: x.iRay, self.drList)
|
||||
self.dr = self.drList[0]
|
||||
|
|
@ -161,6 +163,9 @@ class DirectSession(DirectObject):
|
|||
['SGE_Delete', self.removeNodePath],
|
||||
['SGE_Set Name', self.getAndSetName],
|
||||
['DIRECT-delete', self.removeAllSelected],
|
||||
['DIRECT-Undo', self.undo],
|
||||
['DIRECT-Redo', self.redo],
|
||||
['DIRECT-OOBE', self.oobe],
|
||||
]
|
||||
|
||||
if base.wantTk:
|
||||
|
|
@ -207,13 +212,7 @@ class DirectSession(DirectObject):
|
|||
'alt-mouse3', 'alt-mouse3-up',
|
||||
]
|
||||
|
||||
self.hotKeyMap = {
|
||||
'c': ('Center Camera', 0, 'DIRECT-centerCamIn'),
|
||||
'f': ('Fit on Widget', 0, 'DIRECT-fitOnWidget'),
|
||||
'h': ('Move Camera to ', 0, 'DIRECT-homeCam'),
|
||||
'shift-v': ('Toggle Marker', 0, 'DIRECT-toggleMarkerVis'),
|
||||
'm': ('Move to fit', 0, 'DIRECT-moveToFit'),
|
||||
'n': ('Pick Next COA', 0, 'DIRECT-pickNextCOA'),
|
||||
self.directOnlyKeyMap = {
|
||||
'u': ('Orbit Upright Camera', 0, 'DIRECT-orbitUprightCam'),
|
||||
'shift-u': ('Upright Camera', 0, 'DIRECT-uprightCam'),
|
||||
'1': ('Move Camera to View 1', 0, 'DIRECT-spwanMoveToView-1'),
|
||||
|
|
@ -231,10 +230,23 @@ class DirectSession(DirectObject):
|
|||
'shift-=': ('Zoom In', 0, 'DIRECT-zoomInCam'),
|
||||
'shift-_': ('Zoom Out', 0, 'DIRECT-zoomOutCam'),
|
||||
'-': ('Zoom Out', 0, 'DIRECT-zoomOutCam'),
|
||||
'o': ('Toggle OOBE', 0, 'DIRECT-OOBE'),
|
||||
'[': ('DIRECT-Undo', 0, 'DIRECT-Undo'),
|
||||
'shift-[': ('DIRECT-Undo', 0, 'DIRECT-Undo'),
|
||||
']': ('DIRECT-Redo', 0, 'DIRECT-Redo'),
|
||||
'shift-]': ('DIRECT-Redo', 0, 'DIRECT-Redo'),
|
||||
}
|
||||
|
||||
self.hotKeyMap = {
|
||||
'c': ('Center Camera', 0, 'DIRECT-centerCamIn'),
|
||||
'f': ('Fit on Widget', 0, 'DIRECT-fitOnWidget'),
|
||||
'h': ('Move Camera to ', 0, 'DIRECT-homeCam'),
|
||||
'shift-v': ('Toggle Marker', 0, 'DIRECT-toggleMarkerVis'),
|
||||
'm': ('Move to fit', 0, 'DIRECT-moveToFit'),
|
||||
'n': ('Pick Next COA', 0, 'DIRECT-pickNextCOA'),
|
||||
'delete': ('Delete', 0, 'DIRECT-delete'),
|
||||
'.': ('Scale Up Widget', 0, 'DIRECT-widgetScaleUp'),
|
||||
',': ('Scale Down Widget', 0, 'DIRECT-widgetScaleDown'),
|
||||
|
||||
'page_up': ('Up Ancestry', 'self.upAncestry()', 0),
|
||||
'page_down': ('Down Ancestry', 'self.downAncestry()', 0),
|
||||
'escape': ('Deselect All', 'self.deselectAll()', 0),
|
||||
|
|
@ -243,7 +255,6 @@ class DirectSession(DirectObject):
|
|||
'control-f': ('Flash', 'self.flash(last)', 0),
|
||||
'l': ('Toggle lights', 'self.lights.toggle()', 0),
|
||||
'shift-l': ('Toggle COA Lock', 'self.cameraControl.toggleCOALock()', 0),
|
||||
'o': ('Toggle OOBE', 'self.oobe()', 0),
|
||||
'p': ('Set Active Parent', 'self.doSetActiveParent()', 0),
|
||||
'r': ('Wrt Reparent', 'self.doWrtReparent()', 0),
|
||||
'shift-r': ('Reparent', 'self.doReparent()', 0),
|
||||
|
|
@ -251,10 +262,6 @@ class DirectSession(DirectObject):
|
|||
't': ('Toggle Textures', 'base.toggleTexture()', 0),
|
||||
'shift-a': ('Toggle Vis all', 'self.selected.toggleVisAll()', 0),
|
||||
'w': ('Toggle Wireframe', 'base.toggleWireframe()', 0),
|
||||
'[': ('DIRECT-Undo', 'self.undo()', 0),
|
||||
'shift-[': ('DIRECT-Undo', 'self.undo()', 0),
|
||||
']': ('DIRECT-Redo', 'DIRECT-self.redo()', 0),
|
||||
'shift-]': ('DIRECT-Redo', 'self.redo()', 0),
|
||||
'control-z': ('Undo', 0, 'LE-Undo'),
|
||||
'shift-z' : ('Redo', 0, 'LE-Redo'),
|
||||
}
|
||||
|
|
@ -508,6 +515,8 @@ class DirectSession(DirectObject):
|
|||
self.trueCamera = self.camera
|
||||
self.cam = NodePath(winCtrl.camNode)
|
||||
self.camNode = winCtrl.camNode
|
||||
if hasattr(winCtrl, 'grid'):
|
||||
base.direct.grid = winCtrl.grid
|
||||
base.direct.dr = base.direct.drList[base.camList.index(NodePath(winCtrl.camNode))]
|
||||
base.direct.iRay = base.direct.dr.iRay
|
||||
base.mouseWatcher = winCtrl.mouseWatcher
|
||||
|
|
@ -530,7 +539,15 @@ class DirectSession(DirectObject):
|
|||
messenger.send(keyDesc[2])
|
||||
else: # [gjeon] when we need to call a function
|
||||
eval(keyDesc[1])
|
||||
|
||||
elif input in self.directOnlyKeyMap.keys():
|
||||
if self.fIgnoreDirectOnlyKeyMap:
|
||||
return
|
||||
keyDesc = self.directOnlyKeyMap[input]
|
||||
if len(keyDesc) == 3:
|
||||
if keyDesc[1] == 0: # [gjeon] when we need to send a message
|
||||
messenger.send(keyDesc[2])
|
||||
else: # [gjeon] when we need to call a function
|
||||
eval(keyDesc[1])
|
||||
elif input == 'mouse1-up':
|
||||
self.fMouse1 = 0 # [gjeon] to update alt key information while mouse1 is pressed
|
||||
messenger.send('DIRECT-mouse1Up')
|
||||
|
|
|
|||
Loading…
Reference in New Issue