From 12c5c4e0f384a07bb815f92dbee00c4f105d6602 Mon Sep 17 00:00:00 2001 From: Justin Butler Date: Fri, 2 Dec 2005 22:30:25 +0000 Subject: [PATCH] Added ability to set color of selection box (if needed to be different than the default red). --- direct/src/directtools/DirectGlobals.py | 7 +++ direct/src/directtools/DirectManipulation.py | 46 ++++++++++++++------ direct/src/directtools/DirectSelection.py | 24 +++++++--- 3 files changed, 57 insertions(+), 20 deletions(-) diff --git a/direct/src/directtools/DirectGlobals.py b/direct/src/directtools/DirectGlobals.py index 0940f59fe1..dc9cc22504 100644 --- a/direct/src/directtools/DirectGlobals.py +++ b/direct/src/directtools/DirectGlobals.py @@ -31,3 +31,10 @@ SKIP_BACKFACE = 2 SKIP_CAMERA = 4 SKIP_UNPICKABLE = 8 SKIP_ALL = SKIP_HIDDEN | SKIP_BACKFACE | SKIP_CAMERA | SKIP_UNPICKABLE + +# bit flags for indicating how editable an object is +EDIT_TYPE_UNMOVABLE = 1 +EDIT_TYPE_UNSCALABLE = 2 +EDIT_TYPE_UNROTATABLE = 4 +EDIT_TYPE_UNEDITABLE = EDIT_TYPE_UNMOVABLE | EDIT_TYPE_UNSCALABLE | EDIT_TYPE_UNROTATABLE + diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index e9bf990199..ac0736ddd6 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -175,14 +175,34 @@ class DirectManipulationControl(PandaObject): def removeManipulateObjectTask(self): taskMgr.remove('manipulateObject') + #-------------------------------------------------------------------------- + # Function: get edit types list for specified objects which indicate + # how editable the objects are + # Parameters: object, list of object to get edit types for + # Changes: none + # Returns: list of edit types + #-------------------------------------------------------------------------- + def getEditTypes(self,objects): + # See if any of the selected in the don't manipulate tag list + editTypes = 0 + for tag in self.unmovableTagList: + for selected in objects: + unmovableTag = selected.getTag(tag) + if (unmovableTag): + # check value of unmovableTag to see if it is + # completely uneditable or if it allows only certain + # types of editing + editTypes |= int(unmovableTag) + return editTypes + def manipulateObject(self): # Only do this if something is selected selectedList = direct.selected.getSelectedAsList() - # See if any of the selected in the don't manipulate tag list - for tag in self.unmovableTagList: - for selected in selectedList: - if selected.hasTag(tag): - return + # See if any of the selected are completely uneditable + editTypes = self.getEditTypes(selectedList) + if (editTypes & EDIT_TYPE_UNEDITABLE == EDIT_TYPE_UNEDITABLE): + return + self.currEditTypes = editTypes if selectedList: # Remove the task to keep the widget attached to the object taskMgr.remove('followSelectedNodePath') @@ -234,11 +254,11 @@ class DirectManipulationControl(PandaObject): # Widget takes precedence if self.constraint: type = self.constraint[2:] - if type == 'post': + if type == 'post' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: self.xlate1D(state) - elif type == 'disc': + elif type == 'disc' and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: self.xlate2D(state) - elif type == 'ring': + elif type == 'ring' and not self.currEditTypes & EDIT_TYPE_UNROTATABLE: self.rotate1D(state) # No widget interaction, determine free manip mode elif self.fFreeManip: @@ -247,17 +267,17 @@ class DirectManipulationControl(PandaObject): self.objectHandles.transferObjectHandlesScale() self.fScaling = 0 # Alt key switches to a scaling mode - if direct.fControl: + if 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: + 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: + elif state.fMouseX or state.fMouseY and not self.currEditTypes & EDIT_TYPE_UNMOVABLE: # Mouse started elsewhere in the outer frame, rotate self.rotate2D(state) - else: + elif not self.currEditTypes & EDIT_TYPE_UNMOVABLE: # Mouse started in central region, xlate # Mode depends on shift key if direct.fShift or direct.fControl: @@ -281,6 +301,7 @@ class DirectManipulationControl(PandaObject): def removeTag(self, tag): self.unmovableTagList.remove(tag) + ### WIDGET MANIPULATION METHODS ### def xlate1D(self, state): # Constrained 1D Translation along widget axis @@ -962,4 +983,3 @@ class ObjectHandles(NodePath,PandaObject): return self.hitPt - diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 6c5a95959e..3fc17fdced 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -9,12 +9,12 @@ COA_CENTER = 1 # MRM: To do: handle broken node paths in selected and deselected dicts class DirectNodePath(NodePath): # A node path augmented with info, bounding box, and utility methods - def __init__(self, nodePath): + def __init__(self, nodePath, bboxColor=None): # Initialize the superclass NodePath.__init__(self) self.assign(nodePath) # Create a bounding box - self.bbox = DirectBoundingBox(self) + self.bbox = DirectBoundingBox(self, bboxColor) center = self.bbox.getCenter() # Create matrix to hold the offset between the nodepath # and its center of action (COA) @@ -69,7 +69,7 @@ class SelectedNodePaths(PandaObject): if not nodePath: print 'Nothing selected!!' return None - + # Reset selected objects and highlight if multiSelect is false if not fMultiSelect: self.deselectAll() @@ -244,13 +244,13 @@ class SelectedNodePaths(PandaObject): class DirectBoundingBox: - def __init__(self, nodePath): + def __init__(self, nodePath, bboxColor=None): # Record the node path self.nodePath = nodePath # Compute bounds, min, max, etc. self.computeTightBounds() # Generate the bounding box - self.lines = self.createBBoxLines() + self.lines = self.createBBoxLines(bboxColor) def recompute(self): # Compute bounds, min, max, etc. @@ -285,11 +285,14 @@ class DirectBoundingBox: self.min = Point3(self.center - Point3(self.radius)) self.max = Point3(self.center + Point3(self.radius)) - def createBBoxLines(self): + def createBBoxLines(self, bboxColor=None): # Create a line segments object for the bbox lines = LineNodePath(hidden) lines.node().setName('bboxLines') - lines.setColor(VBase4(1., 0., 0., 1.)) + if (bboxColor): + lines.setColor(VBase4(*bboxColor)) + else: + lines.setColor(VBase4(1., 0., 0., 1.)) lines.setThickness(0.5) minX = self.min[0] @@ -329,6 +332,13 @@ class DirectBoundingBox: return lines + def setBoxColorScale(self,r,g,b,a): + if (self.lines): + self.lines.reset() + self.lines = None + self.lines = self.createBBoxLines((r,g,b,a)) + self.show() + def updateBBoxLines(self): ls = self.lines.lineSegs