Added support for multiple windows

This commit is contained in:
Gyedo Jeon 2009-08-28 06:41:07 +00:00
parent 8b77da64df
commit 0ad1e310d3
4 changed files with 428 additions and 90 deletions

View File

@ -30,7 +30,8 @@ SKIP_HIDDEN = 1
SKIP_BACKFACE = 2 SKIP_BACKFACE = 2
SKIP_CAMERA = 4 SKIP_CAMERA = 4
SKIP_UNPICKABLE = 8 SKIP_UNPICKABLE = 8
SKIP_ALL = SKIP_HIDDEN | SKIP_BACKFACE | SKIP_CAMERA | SKIP_UNPICKABLE SKIP_WIDGET = 16
SKIP_ALL = SKIP_HIDDEN | SKIP_BACKFACE | SKIP_CAMERA | SKIP_UNPICKABLE | SKIP_WIDGET
# bit flags for indicating how editable an object is # bit flags for indicating how editable an object is
EDIT_TYPE_UNMOVABLE = 1 EDIT_TYPE_UNMOVABLE = 1

View File

@ -30,10 +30,12 @@ class DirectManipulationControl(DirectObject):
['DIRECT-mouse1', self.manipulationStart], ['DIRECT-mouse1', self.manipulationStart],
['DIRECT-mouse1Up', self.manipulationStop], ['DIRECT-mouse1Up', self.manipulationStop],
['tab', self.toggleObjectHandlesMode], ['tab', 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],
['<', self.objectHandles.multiplyScalingFactorBy, 0.5], ## ['<', self.objectHandles.multiplyScalingFactorBy, 0.5],
['DIRECT-widgetScaleUp', self.scaleWidget, 2.0],
['DIRECT-widgetScaleDown', self.scaleWidget, 0.5],
['shift-f', self.objectHandles.growToFit], ['shift-f', self.objectHandles.growToFit],
['i', self.plantSelectedNodePath], ['i', self.plantSelectedNodePath],
] ]
@ -41,8 +43,48 @@ class DirectManipulationControl(DirectObject):
self.optionalSkipFlags = 0 self.optionalSkipFlags = 0
self.unmovableTagList = [] self.unmovableTagList = []
# [gjeon] to enable selection while other manipulation is disabled # [gjeon] flag to enable selection while other manipulation is disabled
self.fAllowSelectionOnly = 0 self.fAllowSelectionOnly = 0
# [gjeon] flag to enable marquee selection feature
self.fAllowMarquee = 0
self.marquee = None
# [gjeon] for new LE's multi-view support
self.fMultiView = 0
def scaleWidget(self, factor):
if hasattr(base.direct, 'widget'):
base.direct.widget.multiplyScalingFactorBy(factor)
else:
self.objectHandles.multiplyScalingFactorBy(factor)
def supportMultiView(self):
if self.fMultiView:
return
self.objectHandles.hide(BitMask32.bit(0))
self.objectHandles.hide(BitMask32.bit(1))
self.objectHandles.hide(BitMask32.bit(2))
self.topViewWidget = ObjectHandles('topViewWidget')
self.frontViewWidget = ObjectHandles('frontViewWidget')
self.leftViewWidget = ObjectHandles('leftViewWidget')
self.widgetList = [self.topViewWidget, self.frontViewWidget, self.leftViewWidget, self.objectHandles]
self.topViewWidget.hide(BitMask32.bit(1))
self.topViewWidget.hide(BitMask32.bit(2))
self.topViewWidget.hide(BitMask32.bit(3))
self.frontViewWidget.hide(BitMask32.bit(0))
self.frontViewWidget.hide(BitMask32.bit(2))
self.frontViewWidget.hide(BitMask32.bit(3))
self.leftViewWidget.hide(BitMask32.bit(0))
self.leftViewWidget.hide(BitMask32.bit(1))
self.leftViewWidget.hide(BitMask32.bit(3))
self.fMultiView = 1
def manipulationStart(self, modifiers): def manipulationStart(self, modifiers):
# Start out in select mode # Start out in select mode
@ -55,7 +97,7 @@ class DirectManipulationControl(DirectObject):
return return
# Check for a widget hit point # Check for a widget hit point
entry = base.direct.iRay.pickWidget() entry = base.direct.iRay.pickWidget(skipFlags = SKIP_WIDGET)
# Did we hit a widget? # Did we hit a widget?
if entry: if entry:
# Yes! # Yes!
@ -67,21 +109,33 @@ class DirectManipulationControl(DirectObject):
# Nope, off the widget, no constraint # Nope, off the widget, no constraint
self.constraint = None self.constraint = None
# [gjeon] to prohibit unwanted object movement while direct window doesn't have focus # [gjeon] to prohibit unwanted object movement while direct window doesn't have focus
if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers): if base.direct.cameraControl.useMayaCamControls and not base.direct.gotControl(modifiers) \
and not self.fAllowMarquee:
return return
if not base.direct.gotAlt(modifiers): if not base.direct.gotAlt(modifiers):
# Check to see if we are moving the object if entry:
# We are moving the object if we either wait long enough # Check to see if we are moving the object
taskMgr.doMethodLater(MANIPULATION_MOVE_DELAY, # We are moving the object if we either wait long enough
self.switchToMoveMode, taskMgr.doMethodLater(MANIPULATION_MOVE_DELAY,
'manip-move-wait') self.switchToMoveMode,
# Or we move far enough 'manip-move-wait')
self.moveDir = None # Or we move far enough
watchMouseTask = Task.Task(self.watchMouseTask) self.moveDir = None
watchMouseTask.initX = base.direct.dr.mouseX watchMouseTask = Task.Task(self.watchMouseTask)
watchMouseTask.initY = base.direct.dr.mouseY watchMouseTask.initX = base.direct.dr.mouseX
taskMgr.add(watchMouseTask, 'manip-watch-mouse') watchMouseTask.initY = base.direct.dr.mouseY
taskMgr.add(watchMouseTask, 'manip-watch-mouse')
else:
if base.direct.fControl:
self.mode = 'move'
self.manipulateObject()
elif not base.direct.fAlt and self.fAllowMarquee:
self.moveDir = None
watchMarqueeTask = Task.Task(self.watchMarqueeTask)
watchMarqueeTask.initX = base.direct.dr.mouseX
watchMarqueeTask.initY = base.direct.dr.mouseY
taskMgr.add(watchMarqueeTask, 'manip-marquee-mouse')
def switchToMoveMode(self, state): def switchToMoveMode(self, state):
taskMgr.remove('manip-watch-mouse') taskMgr.remove('manip-watch-mouse')
@ -99,10 +153,47 @@ class DirectManipulationControl(DirectObject):
else: else:
return Task.cont return Task.cont
def watchMarqueeTask(self, state):
taskMgr.remove('manip-watch-mouse')
taskMgr.remove('manip-move-wait')
self.mode = 'select'
self.drawMarquee(state.initX, state.initY)
return Task.cont
def drawMarquee(self, startX, startY):
if self.marquee:
self.marquee.remove()
self.marquee = None
if base.direct.cameraControl.useMayaCamControls and base.direct.fAlt:
return
endX = base.direct.dr.mouseX
endY = base.direct.dr.mouseY
if (((abs (endX - startX)) < 0.01) and
((abs (endY - startY)) < 0.01)):
return
self.marquee = LineNodePath(render2d, 'marquee', 0.5, VBase4(.8, .6, .6, 1))
self.marqueeInfo = (startX, startY, endX, endY)
self.marquee.drawLines([
[(startX, 0, startY), (startX, 0, endY)],
[(startX, 0, endY), (endX, 0, endY)],
[(endX, 0, endY), (endX, 0, startY)],
[(endX, 0, startY), (startX, 0, startY)]])
self.marquee.create()
if self.fMultiView:
for i in range(4):
if i != base.camList.index(NodePath(base.direct.camNode)):
self.marquee.hide(BitMask32.bit(i))
def manipulationStop(self): def manipulationStop(self):
taskMgr.remove('manipulateObject') taskMgr.remove('manipulateObject')
taskMgr.remove('manip-move-wait') taskMgr.remove('manip-move-wait')
taskMgr.remove('manip-watch-mouse') taskMgr.remove('manip-watch-mouse')
taskMgr.remove('manip-marquee-mouse')
# depending on flag..... # depending on flag.....
if self.mode == 'select': if self.mode == 'select':
# Check for object under mouse # Check for object under mouse
@ -111,17 +202,123 @@ class DirectManipulationControl(DirectObject):
skipFlags = self.defaultSkipFlags | self.optionalSkipFlags skipFlags = self.defaultSkipFlags | self.optionalSkipFlags
# Skip camera (and its children), unless control key is pressed # Skip camera (and its children), unless control key is pressed
skipFlags |= SKIP_CAMERA * (1 - base.getControl()) skipFlags |= SKIP_CAMERA * (1 - base.getControl())
entry = base.direct.iRay.pickGeom(skipFlags = skipFlags)
if entry: if self.marquee:
# Record hit point information self.marquee.remove()
self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath())) self.marquee = None
self.hitPtDist = Vec3(self.hitPt).length()
# Select it
base.direct.select(entry.getIntoNodePath(), base.direct.fShift)
else:
base.direct.deselectAll() base.direct.deselectAll()
startX = self.marqueeInfo[0]
startY = self.marqueeInfo[1]
endX = self.marqueeInfo[2]
endY = self.marqueeInfo[3]
fll = Point3(0, 0, 0)
flr = Point3(0, 0, 0)
fur = Point3(0, 0, 0)
ful = Point3(0, 0, 0)
nll = Point3(0, 0, 0)
nlr = Point3(0, 0, 0)
nur = Point3(0, 0, 0)
nul = Point3(0, 0, 0)
lens = base.direct.cam.node().getLens()
lens.extrude((startX, startY), nul, ful)
lens.extrude((endX, startY), nur, fur)
lens.extrude((endX, endY), nlr, flr)
lens.extrude((startX, endY), nll, fll)
marqueeFrustum = BoundingHexahedron(fll, flr, fur, ful, nll, nlr, nur, nul);
marqueeFrustum.xform(base.direct.cam.getNetTransform().getMat())
base.marqueeFrustum = marqueeFrustum
def findTaggedNodePath(nodePath):
# Select tagged object if present
for tag in base.direct.selected.tagList:
if nodePath.hasNetTag(tag):
nodePath = nodePath.findNetTag(tag)
return nodePath
return None
selectionList = []
for geom in render.findAllMatches("**/+GeomNode"):
if (skipFlags & SKIP_HIDDEN) and geom.isHidden():
# Skip if hidden node
continue
## elif (skipFlags & SKIP_BACKFACE) and base.direct.iRay.isEntryBackfacing():
## # Skip, if backfacing poly
## pass
elif ((skipFlags & SKIP_CAMERA) and
(camera in geom.getAncestors())):
# Skip if parented to a camera.
continue
# Can pick unpickable, use the first visible node
elif ((skipFlags & SKIP_UNPICKABLE) and
(geom.getName() in base.direct.iRay.unpickable)):
# Skip if in unpickable list
continue
nodePath = findTaggedNodePath(geom)
if nodePath in selectionList:
continue
bb = geom.getBounds()
bbc = bb.makeCopy()
bbc.xform(geom.getParent().getNetTransform().getMat())
boundingSphereTest = marqueeFrustum.contains(bbc)
if boundingSphereTest > 1:
if boundingSphereTest == 7:
print "boundingSphere is all in, selecting ", geom
if nodePath not in selectionList:
selectionList.append(nodePath)
else:
tMat = Mat4(geom.getMat())
geom.clearMat()
# Get bounds
min = Point3(0)
max = Point3(0)
geom.calcTightBounds(min, max)
# Restore transform
geom.setMat(tMat)
fll = Point3(min[0], max[1], min[2])
flr = Point3(max[0], max[1], min[2])
fur = max
ful = Point3(min[0], max[1], max[2])
nll = min
nlr = Point3(max[0], min[1], min[2])
nur = Point3(max[0], min[1], max[2])
nul = Point3(min[0], min[1], max[2])
tbb = BoundingHexahedron(fll, flr, fur, ful, nll, nlr, nur, nul)
tbb.xform(geom.getNetTransform().getMat())
tightBoundTest = marqueeFrustum.contains(tbb)
if tightBoundTest > 1:
if nodePath not in selectionList:
selectionList.append(nodePath)
for nodePath in selectionList:
base.direct.select(nodePath, 1)
else:
entry = base.direct.iRay.pickGeom(skipFlags = skipFlags)
if entry:
# Record hit point information
self.hitPt.assign(entry.getSurfacePoint(entry.getFromNodePath()))
self.hitPtDist = Vec3(self.hitPt).length()
# Select it
base.direct.select(entry.getIntoNodePath(), base.direct.fShift)
else:
base.direct.deselectAll()
elif self.mode == 'move': elif self.mode == 'move':
self.manipulateObjectCleanup() self.manipulateObjectCleanup()
self.mode = None self.mode = None
def manipulateObjectCleanup(self): def manipulateObjectCleanup(self):
@ -161,7 +358,11 @@ class DirectManipulationControl(DirectObject):
taskMgr.add(t, 'followSelectedNodePath') taskMgr.add(t, 'followSelectedNodePath')
def followSelectedNodePathTask(self, state): def followSelectedNodePathTask(self, state):
base.direct.widget.setPosHpr(state.base, state.pos, state.hpr) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setPosHpr(state.base, state.pos, state.hpr)
else:
base.direct.widget.setPosHpr(state.base, state.pos, state.hpr)
return Task.cont return Task.cont
def enableManipulation(self): def enableManipulation(self):
@ -293,17 +494,22 @@ class DirectManipulationControl(DirectObject):
# Widget takes precedence # Widget takes precedence
if self.constraint: if self.constraint:
type = self.constraint[2:] type = self.constraint[2:]
if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE:
# [gjeon] to enable non-uniform scaling if type == 'post':
if base.direct.fControl and not self.currEditTypes & EDIT_TYPE_UNSCALABLE: # [gjeon] non-uniform scaling
self.fScaling = 1 self.fScaling = 1
self.scale1D(state) self.scale1D(state)
else: else:
# [gjeon] uniform scaling
self.fScaling = 1
self.scale3D(state)
else:
if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
self.xlate1D(state) self.xlate1D(state)
elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE:
self.xlate2D(state) self.xlate2D(state)
elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE:
self.rotate1D(state) self.rotate1D(state)
# No widget interaction, determine free manip mode # No widget interaction, determine free manip mode
elif self.fFreeManip: elif self.fFreeManip:
# If we've been scaling and changed modes, reset object handles # If we've been scaling and changed modes, reset object handles
@ -362,7 +568,11 @@ class DirectManipulationControl(DirectObject):
else: else:
# Move widget to keep hit point as close to mouse as possible # Move widget to keep hit point as close to mouse as possible
offset = self.hitPt - self.prevHit offset = self.hitPt - self.prevHit
base.direct.widget.setPos(base.direct.widget, offset) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setPos(widget, offset)
else:
base.direct.widget.setPos(base.direct.widget, offset)
def xlate2D(self, state): def xlate2D(self, state):
# Constrained 2D (planar) translation # Constrained 2D (planar) translation
@ -378,7 +588,11 @@ class DirectManipulationControl(DirectObject):
self.prevHit.assign(self.hitPt) self.prevHit.assign(self.hitPt)
else: else:
offset = self.hitPt - self.prevHit offset = self.hitPt - self.prevHit
base.direct.widget.setPos(base.direct.widget, offset) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setPos(widget, offset)
else:
base.direct.widget.setPos(base.direct.widget, offset)
def rotate1D(self, state): def rotate1D(self, state):
# 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)
@ -401,11 +615,23 @@ class DirectManipulationControl(DirectObject):
if self.fWidgetTop: if self.fWidgetTop:
deltaAngle = -1 * deltaAngle deltaAngle = -1 * deltaAngle
if self.rotateAxis == 'x': if self.rotateAxis == 'x':
base.direct.widget.setP(base.direct.widget, deltaAngle) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setP(widget, deltaAngle)
else:
base.direct.widget.setP(base.direct.widget, deltaAngle)
elif self.rotateAxis == 'y': elif self.rotateAxis == 'y':
base.direct.widget.setR(base.direct.widget, deltaAngle) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setR(widget, deltaAngle)
else:
base.direct.widget.setR(base.direct.widget, deltaAngle)
elif self.rotateAxis == 'z': elif self.rotateAxis == 'z':
base.direct.widget.setH(base.direct.widget, deltaAngle) if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.setH(widget, deltaAngle)
else:
base.direct.widget.setH(base.direct.widget, deltaAngle)
# Record crank angle for next time around # Record crank angle for next time around
self.lastCrankAngle = newAngle self.lastCrankAngle = newAngle
@ -611,13 +837,13 @@ class DirectManipulationControl(DirectObject):
[base.direct.selected.getSelectedAsList()]) [base.direct.selected.getSelectedAsList()])
class ObjectHandles(NodePath, DirectObject): class ObjectHandles(NodePath, DirectObject):
def __init__(self): def __init__(self, name='objectHandles'):
# Initialize the superclass # Initialize the superclass
NodePath.__init__(self) NodePath.__init__(self)
# Load up object handles model and assign it to self # Load up object handles model and assign it to self
self.assign(loader.loadModel('models/misc/objectHandles')) self.assign(loader.loadModel('models/misc/objectHandles'))
self.setName('objectHandles') self.setName(name)
self.scalingNode = self.getChild(0) self.scalingNode = self.getChild(0)
self.scalingNode.setName('ohScalingNode') self.scalingNode.setName('ohScalingNode')
self.ohScalingFactor = 1.0 self.ohScalingFactor = 1.0
@ -668,6 +894,24 @@ class ObjectHandles(NodePath, DirectObject):
self.createGuideLines() self.createGuideLines()
self.hideGuides() self.hideGuides()
# tag with name so they can skipped during iRay selection
self.xPostCollision.setTag('WidgetName',name)
self.yPostCollision.setTag('WidgetName',name)
self.zPostCollision.setTag('WidgetName',name)
self.xRingCollision.setTag('WidgetName',name)
self.yRingCollision.setTag('WidgetName',name)
self.zRingCollision.setTag('WidgetName',name)
self.xDiscCollision.setTag('WidgetName',name)
self.yDiscCollision.setTag('WidgetName',name)
self.zDiscCollision.setTag('WidgetName',name)
# name disc geoms so they can be added to unpickables
self.xDisc.find("**/+GeomNode").setName('x-disc-geom')
self.yDisc.find("**/+GeomNode").setName('y-disc-geom')
self.zDisc.find("**/+GeomNode").setName('z-disc-geom')
# Start with widget handles hidden # Start with widget handles hidden
self.fActive = 1 self.fActive = 1
self.toggleWidget() self.toggleWidget()
@ -686,10 +930,19 @@ class ObjectHandles(NodePath, DirectObject):
def toggleWidget(self): def toggleWidget(self):
if self.fActive: if self.fActive:
self.deactivate() if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.deactivate()
else:
self.deactivate()
else: else:
self.activate() if hasattr(base.direct, "manipulationControl") and base.direct.manipulationControl.fMultiView:
for widget in base.direct.manipulationControl.widgetList:
widget.activate()
widget.showWidgetIfActive()
else:
self.activate()
def activate(self): def activate(self):
self.scalingNode.reparentTo(self) self.scalingNode.reparentTo(self)
self.fActive = 1 self.fActive = 1
@ -697,7 +950,7 @@ class ObjectHandles(NodePath, DirectObject):
def deactivate(self): def deactivate(self):
self.scalingNode.reparentTo(hidden) self.scalingNode.reparentTo(hidden)
self.fActive = 0 self.fActive = 0
def showWidgetIfActive(self): def showWidgetIfActive(self):
if self.fActive: if self.fActive:
self.reparentTo(base.direct.group) self.reparentTo(base.direct.group)
@ -707,7 +960,7 @@ class ObjectHandles(NodePath, DirectObject):
def hideWidget(self): def hideWidget(self):
self.reparentTo(hidden) self.reparentTo(hidden)
def enableHandles(self, handles): def enableHandles(self, handles):
if type(handles) == types.ListType: if type(handles) == types.ListType:
for handle in handles: for handle in handles:
@ -886,15 +1139,30 @@ class ObjectHandles(NodePath, DirectObject):
lines = LineNodePath(self.xPost) lines = LineNodePath(self.xPost)
lines.setColor(VBase4(1, 0, 0, 1)) lines.setColor(VBase4(1, 0, 0, 1))
lines.setThickness(5) lines.setThickness(5)
lines.moveTo(0, 0, 0) #lines.moveTo(0, 0, 0)
lines.drawTo(1.5, 0, 0) #lines.drawTo(1.5, 0, 0)
lines.create() lines.moveTo(1.5, 0, 0)
lines = LineNodePath(self.xPost) #lines.create()
lines.setColor(VBase4(1, 0, 0, 1)) #lines = LineNodePath(self.xPost)
lines.setThickness(1.5) #lines.setColor(VBase4(1, 0, 0, 1))
lines.moveTo(0, 0, 0) #lines.setThickness(1.5)
#lines.moveTo(0, 0, 0)
lines.drawTo(-1.5, 0, 0) lines.drawTo(-1.5, 0, 0)
arrowInfo0 = 1.3
arrowInfo1 = 0.1
#lines.setThickness(5)
lines.moveTo(1.5, 0, 0)
lines.drawTo(arrowInfo0, arrowInfo1, arrowInfo1)
lines.moveTo(1.5, 0, 0)
lines.drawTo(arrowInfo0, arrowInfo1, -1 * arrowInfo1)
lines.moveTo(1.5, 0, 0)
lines.drawTo(arrowInfo0, -1 * arrowInfo1, arrowInfo1)
lines.moveTo(1.5, 0, 0)
lines.drawTo(arrowInfo0, -1 * arrowInfo1, -1 * arrowInfo1)
lines.create() lines.create()
lines.setName('x-post-line')
# X ring # X ring
self.xRing = self.xRingGroup.attachNewNode('x-ring-visible') self.xRing = self.xRingGroup.attachNewNode('x-ring-visible')
@ -907,21 +1175,34 @@ class ObjectHandles(NodePath, DirectObject):
math.cos(deg2Rad(ang)), math.cos(deg2Rad(ang)),
math.sin(deg2Rad(ang))) math.sin(deg2Rad(ang)))
lines.create() lines.create()
lines.setName('x-ring-line')
# Y post # Y post
self.yPost = self.yPostGroup.attachNewNode('y-post-visible') self.yPost = self.yPostGroup.attachNewNode('y-post-visible')
lines = LineNodePath(self.yPost) lines = LineNodePath(self.yPost)
lines.setColor(VBase4(0, 1, 0, 1)) lines.setColor(VBase4(0, 1, 0, 1))
lines.setThickness(5) lines.setThickness(5)
lines.moveTo(0, 0, 0) #lines.moveTo(0, 0, 0)
lines.drawTo(0, 1.5, 0) #lines.drawTo(0, 1.5, 0)
lines.create() lines.moveTo(0, 1.5, 0)
lines = LineNodePath(self.yPost) #lines.create()
lines.setColor(VBase4(0, 1, 0, 1)) #lines = LineNodePath(self.yPost)
lines.setThickness(1.5) #lines.setColor(VBase4(0, 1, 0, 1))
lines.moveTo(0, 0, 0) #lines.setThickness(1.5)
#lines.moveTo(0, 0, 0)
lines.drawTo(0, -1.5, 0) lines.drawTo(0, -1.5, 0)
#lines.setThickness(5)
lines.moveTo(0, 1.5, 0)
lines.drawTo(arrowInfo1, arrowInfo0, arrowInfo1)
lines.moveTo(0, 1.5, 0)
lines.drawTo(arrowInfo1, arrowInfo0, -1 * arrowInfo1)
lines.moveTo(0, 1.5, 0)
lines.drawTo(-1 * arrowInfo1, arrowInfo0, arrowInfo1)
lines.moveTo(0, 1.5, 0)
lines.drawTo(-1 * arrowInfo1, arrowInfo0, -1 * arrowInfo1)
lines.create() lines.create()
lines.setName('y-post-line')
# Y ring # Y ring
self.yRing = self.yRingGroup.attachNewNode('y-ring-visible') self.yRing = self.yRingGroup.attachNewNode('y-ring-visible')
@ -934,21 +1215,35 @@ class ObjectHandles(NodePath, DirectObject):
0, 0,
math.sin(deg2Rad(ang))) math.sin(deg2Rad(ang)))
lines.create() lines.create()
lines.setName('y-ring-line')
# Z post # Z post
self.zPost = self.zPostGroup.attachNewNode('z-post-visible') self.zPost = self.zPostGroup.attachNewNode('z-post-visible')
lines = LineNodePath(self.zPost) lines = LineNodePath(self.zPost)
lines.setColor(VBase4(0, 0, 1, 1)) lines.setColor(VBase4(0, 0, 1, 1))
lines.setThickness(5) lines.setThickness(5)
lines.moveTo(0, 0, 0) #lines.moveTo(0, 0, 0)
lines.drawTo(0, 0, 1.5) #lines.drawTo(0, 0, 1.5)
lines.create() lines.moveTo(0, 0, 1.5)
lines = LineNodePath(self.zPost) #lines.create()
lines.setColor(VBase4(0, 0, 1, 1)) #lines = LineNodePath(self.zPost)
lines.setThickness(1.5) #lines.setColor(VBase4(0, 0, 1, 1))
lines.moveTo(0, 0, 0) #lines.setThickness(1.5)
#lines.moveTo(0, 0, 0)
lines.drawTo(0, 0, -1.5) lines.drawTo(0, 0, -1.5)
#lines.setThickness(5)
lines.moveTo(0, 0, 1.5)
lines.drawTo(arrowInfo1, arrowInfo1, arrowInfo0)
lines.moveTo(0, 0, 1.5)
lines.drawTo(arrowInfo1, -1 * arrowInfo1, arrowInfo0)
lines.moveTo(0, 0, 1.5)
lines.drawTo(-1 * arrowInfo1, arrowInfo1, arrowInfo0)
lines.moveTo(0, 0, 1.5)
lines.drawTo(-1 * arrowInfo1, -1 * arrowInfo1, arrowInfo0)
lines.create() lines.create()
lines.setName('z-post-line')
# Z ring # Z ring
self.zRing = self.zRingGroup.attachNewNode('z-ring-visible') self.zRing = self.zRingGroup.attachNewNode('z-ring-visible')
@ -961,6 +1256,7 @@ class ObjectHandles(NodePath, DirectObject):
math.sin(deg2Rad(ang)), math.sin(deg2Rad(ang)),
0) 0)
lines.create() lines.create()
lines.setName('z-ring-line')
def createGuideLines(self): def createGuideLines(self):
self.guideLines = self.attachNewNode('guideLines') self.guideLines = self.attachNewNode('guideLines')

View File

@ -560,6 +560,14 @@ class SelectionQueue(CollisionHandlerQueue):
(nodePath.getName() in self.unpickable)): (nodePath.getName() in self.unpickable)):
# Skip if in unpickable list # Skip if in unpickable list
pass pass
elif ((skipFlags & SKIP_WIDGET) and
(nodePath.getTag('WidgetName') != base.direct.widget.getName())):
# Skip if this widget part is not belong to current widget
pass
elif ((skipFlags & SKIP_WIDGET) and base.direct.fControl and
(nodePath.getName()[2:] == 'ring')):
# Skip when ununiformly scale in ortho view
pass
else: else:
self.setCurrentIndex(i) self.setCurrentIndex(i)
self.setCurrentEntry(entry) self.setCurrentEntry(entry)

View File

@ -156,6 +156,7 @@ class DirectSession(DirectObject):
['SGE_Fit', self.fitOnNodePath], ['SGE_Fit', self.fitOnNodePath],
['SGE_Delete', self.removeNodePath], ['SGE_Delete', self.removeNodePath],
['SGE_Set Name', self.getAndSetName], ['SGE_Set Name', self.getAndSetName],
['DIRECT-delete', self.removeAllSelected],
] ]
if base.wantTk: if base.wantTk:
@ -175,18 +176,22 @@ class DirectSession(DirectObject):
keyList.extend(map(chr, range(48, 58))) keyList.extend(map(chr, range(48, 58)))
keyList.extend(["`", "-", "=", "[", "]", ";", "'", ",", ".", "/", "\\"]) keyList.extend(["`", "-", "=", "[", "]", ";", "'", ",", ".", "/", "\\"])
def addCtrl(a):
return "control-%s"%a
def addShift(a): def addShift(a):
return "shift-%s"%a return "shift-%s"%a
self.keyList = keyList[:] self.keyEvents = keyList[:]
self.keyList.extend(map(addShift, keyList)) self.keyEvents.extend(map(addCtrl, keyList))
self.keyList.extend(['escape', 'delete', 'page_up', 'page_down']) self.keyEvents.extend(map(addShift, keyList))
self.keyEvents.extend(['escape', 'delete', 'page_up', 'page_down'])
self.keyEvents = ['escape', 'delete', 'page_up', 'page_down', ## self.keyEvents = ['escape', 'delete', 'page_up', 'page_down',
'[', '{', ']', '}', ## '[', '{', ']', '}',
'shift-a', 'b', 'control-f', ## 'shift-a', 'b', 'control-f',
'l', 'shift-l', 'o', 'p', 'r', ## 'l', 'shift-l', 'o', 'p', 'r',
'shift-r', 's', 't', 'v', 'w'] ## 'shift-r', 's', 't', 'v', 'w']
self.mouseEvents = ['mouse1', 'mouse1-up', self.mouseEvents = ['mouse1', 'mouse1-up',
'shift-mouse1', 'shift-mouse1-up', 'shift-mouse1', 'shift-mouse1-up',
'control-mouse1', 'control-mouse1-up', 'control-mouse1', 'control-mouse1-up',
@ -225,6 +230,9 @@ class DirectSession(DirectObject):
'+': 'DIRECT-zoomInCam', '+': 'DIRECT-zoomInCam',
'_': 'DIRECT-zoomOutCam', '_': 'DIRECT-zoomOutCam',
'-': 'DIRECT-zoomOutCam', '-': 'DIRECT-zoomOutCam',
'delete': 'DIRECT-delete',
'.': 'DIRECT-widgetScaleUp',
',': 'DIRECT-widgetScaleDown',
} }
self.passThroughKeys = ['v','b','l','p', 'r', 'shift-r', 's', 't','shift-a', 'w'] self.passThroughKeys = ['v','b','l','p', 'r', 'shift-r', 's', 't','shift-a', 'w']
@ -404,9 +412,6 @@ class DirectSession(DirectObject):
for event in self.keyEvents: for event in self.keyEvents:
self.accept(event, self.inputHandler, [event]) self.accept(event, self.inputHandler, [event])
for event in self.keyList:
self.accept(event, self.inputHandler, [event])
def enableMouseEvents(self): def enableMouseEvents(self):
for event in self.mouseEvents: for event in self.mouseEvents:
self.accept(event, self.inputHandler, [event]) self.accept(event, self.inputHandler, [event])
@ -441,6 +446,8 @@ class DirectSession(DirectObject):
base.direct.iRay = base.direct.dr.iRay base.direct.iRay = base.direct.dr.iRay
base.mouseWatcher = winCtrl.mouseWatcher base.mouseWatcher = winCtrl.mouseWatcher
base.mouseWatcherNode = winCtrl.mouseWatcher.node() base.mouseWatcherNode = winCtrl.mouseWatcher.node()
if base.direct.manipulationControl.fMultiView:
base.direct.widget = base.direct.manipulationControl.widgetList[base.camList.index(NodePath(winCtrl.camNode))]
break break
# Deal with keyboard and mouse input # Deal with keyboard and mouse input
@ -491,8 +498,8 @@ class DirectSession(DirectObject):
self.downAncestry() self.downAncestry()
elif input == 'escape': elif input == 'escape':
self.deselectAll() self.deselectAll()
elif input == 'delete': ## elif input == 'delete':
self.removeAllSelected() ## self.removeAllSelected()
elif input == 'v': elif input == 'v':
self.toggleWidgetVis() self.toggleWidgetVis()
elif input == 'b': elif input == 'b':
@ -566,9 +573,19 @@ class DirectSession(DirectObject):
if not taskMgr.hasTaskNamed('resizeObjectHandles'): if not taskMgr.hasTaskNamed('resizeObjectHandles'):
dnp = self.selected.last dnp = self.selected.last
if dnp: if dnp:
nodeCamDist = Vec3(dnp.getPos(direct.camera)).length() if self.manipulationControl.fMultiView:
sf = 0.075 * nodeCamDist * math.tan(deg2Rad(direct.drList.getCurrentDr().fovV)) for i in range(3):
self.widget.setDirectScalingFactor(sf) sf = 30.0 * direct.drList[i].orthoFactor
self.manipulationControl.widgetList[i].setDirectScalingFactor(sf)
nodeCamDist = Vec3(dnp.getPos(base.camList[3])).length()
sf = 0.075 * nodeCamDist * math.tan(deg2Rad(direct.drList[3].fovV))
self.manipulationControl.widgetList[3].setDirectScalingFactor(sf)
else:
nodeCamDist = Vec3(dnp.getPos(direct.camera)).length()
sf = 0.075 * nodeCamDist * math.tan(deg2Rad(direct.drList.getCurrentDr().fovV))
self.widget.setDirectScalingFactor(sf)
return Task.cont return Task.cont
def select(self, nodePath, fMultiSelect = 0, def select(self, nodePath, fMultiSelect = 0,
@ -585,7 +602,11 @@ class DirectSession(DirectObject):
self.selectedNPReadout.setText( self.selectedNPReadout.setText(
'Selected:' + dnp.getName()) 'Selected:' + dnp.getName())
# Show the manipulation widget # Show the manipulation widget
self.widget.showWidget() if self.manipulationControl.fMultiView:
for widget in self.manipulationControl.widgetList:
widget.showWidget()
else:
self.widget.showWidget()
editTypes = self.manipulationControl.getEditTypes([dnp]) editTypes = self.manipulationControl.getEditTypes([dnp])
if (editTypes & EDIT_TYPE_UNEDITABLE == EDIT_TYPE_UNEDITABLE): if (editTypes & EDIT_TYPE_UNEDITABLE == EDIT_TYPE_UNEDITABLE):
self.manipulationControl.disableWidgetMove() self.manipulationControl.disableWidgetMove()
@ -601,8 +622,12 @@ class DirectSession(DirectObject):
# This uses the additional scaling factor used to grow and # This uses the additional scaling factor used to grow and
# shrink the widget # shrink the widget
if not self.fScaleWidgetByCam: # [gjeon] for not scaling widget by distance from camera if not self.fScaleWidgetByCam: # [gjeon] for not scaling widget by distance from camera
self.widget.setScalingFactor(dnp.getRadius()) if self.manipulationControl.fMultiView:
for widget in self.manipulationControl.widgetList:
widget.setScalingFactor(dnp.getRadius())
else:
self.widget.setScalingFactor(dnp.getRadius())
# Spawn task to have object handles follow the selected object # Spawn task to have object handles follow the selected object
taskMgr.remove('followSelectedNodePath') taskMgr.remove('followSelectedNodePath')
t = Task.Task(self.followSelectedNodePathTask) t = Task.Task(self.followSelectedNodePathTask)
@ -624,7 +649,11 @@ class DirectSession(DirectObject):
dnp = self.selected.deselect(nodePath) dnp = self.selected.deselect(nodePath)
if dnp: if dnp:
# Hide the manipulation widget # Hide the manipulation widget
self.widget.hideWidget() if self.manipulationControl.fMultiView:
for widget in self.manipulationControl.widgetList:
widget.hideWidget()
else:
self.widget.hideWidget()
self.selectedNPReadout.reparentTo(hidden) self.selectedNPReadout.reparentTo(hidden)
self.selectedNPReadout.setText(' ') self.selectedNPReadout.setText(' ')
taskMgr.remove('followSelectedNodePath') taskMgr.remove('followSelectedNodePath')
@ -635,7 +664,11 @@ class DirectSession(DirectObject):
def deselectAll(self): def deselectAll(self):
self.selected.deselectAll() self.selected.deselectAll()
# Hide the manipulation widget # Hide the manipulation widget
self.widget.hideWidget() if self.manipulationControl.fMultiView:
for widget in self.manipulationControl.widgetList:
widget.hideWidget()
else:
self.widget.hideWidget()
self.selectedNPReadout.reparentTo(hidden) self.selectedNPReadout.reparentTo(hidden)
self.selectedNPReadout.setText(' ') self.selectedNPReadout.setText(' ')
taskMgr.remove('followSelectedNodePath') taskMgr.remove('followSelectedNodePath')