diff --git a/direct/src/directtools/DirectCameraControl.py b/direct/src/directtools/DirectCameraControl.py index e9bc9245b7..3ee59d4f29 100644 --- a/direct/src/directtools/DirectCameraControl.py +++ b/direct/src/directtools/DirectCameraControl.py @@ -21,8 +21,8 @@ class DirectCameraControl(PandaObject): self.camManipRef = direct.group.attachNewNode('camManipRef') t = CAM_MOVE_DURATION self.actionEvents = [ - ['handleMouse2', self.mouseFlyStart], - ['handleMouse2Up', self.mouseFlyStop], + ['DIRECT_mouse2', self.mouseFlyStart], + ['DIRECT_mouse2Up', self.mouseFlyStop], ['c', self.centerCamIn, 0.5], ['f', self.fitOnWidget], ['h', self.homeCam], @@ -259,7 +259,10 @@ class DirectCameraControl(PandaObject): angle = getCrankAngle(state.coaCenter) deltaAngle = angle - state.lastAngle state.lastAngle = angle - self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle) + if base.config.GetBool('temp-hpr-fix',0): + self.camManipRef.setHpr(self.camManipRef, 0, 0, deltaAngle) + else: + self.camManipRef.setHpr(self.camManipRef, 0, 0, -deltaAngle) direct.camera.setMat(self.camManipRef, wrtMat) return Task.cont diff --git a/direct/src/directtools/DirectLights.py b/direct/src/directtools/DirectLights.py index 15a0582dff..f0b8661cbd 100644 --- a/direct/src/directtools/DirectLights.py +++ b/direct/src/directtools/DirectLights.py @@ -89,7 +89,7 @@ class DirectLights(NodePath): # Turn it on as a default self.setOn(directLight) # Send an event to all watching objects - messenger.send('DirectLights_addLight', [directLight]) + messenger.send('DIRECT_addLight', [directLight]) # Return the new light return directLight @@ -101,6 +101,8 @@ class DirectLights(NodePath): """ Turn on all DIRECT lights """ base.initialState.setAttribute(LightTransition.getClassType(), self.la) + # Make sure there is a default material + render.setMaterial(Material()) def allOff(self): """ Turn off all DIRECT lights """ diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index 25cb0028cb..6efbad4886 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -24,8 +24,8 @@ class DirectManipulationControl(PandaObject): self.fScaling = 0 self.mode = None self.actionEvents = [ - ['handleMouse1', self.manipulationStart], - ['handleMouse1Up', self.manipulationStop], + ['DIRECT_mouse1', self.manipulationStart], + ['DIRECT_mouse1Up', self.manipulationStop], ['tab', self.toggleObjectHandlesMode], ['.', self.objectHandles.multiplyScalingFactorBy, 2.0], ['>', self.objectHandles.multiplyScalingFactorBy, 2.0], @@ -111,7 +111,7 @@ class DirectManipulationControl(PandaObject): self.objectHandles.hideGuides() # Restart followSelectedNodePath task self.spawnFollowSelectedNodePathTask() - messenger.send('manipulateObjectCleanup') + messenger.send('DIRECT_manipulateObjectCleanup') def spawnFollowSelectedNodePathTask(self): # If nothing selected, just return @@ -177,7 +177,7 @@ class DirectManipulationControl(PandaObject): # hide the bbox of the selected objects during interaction direct.selected.dehighlightAll() # Send event to signal start of manipulation - messenger.send('manipulateObjectStart') + messenger.send('DIRECT_manipulateObjectStart') # Manipulate the real object with the constraint # The constraint is passed as the name of the node self.spawnManipulateObjectTask() @@ -304,7 +304,10 @@ class DirectManipulationControl(PandaObject): elif self.rotateAxis == 'y': direct.widget.setR(direct.widget, -deltaAngle) elif self.rotateAxis == 'z': - direct.widget.setH(direct.widget, deltaAngle) + if base.config.GetBool('temp-hpr-fix',0): + direct.widget.setH(direct.widget, -deltaAngle) + else: + direct.widget.setH(direct.widget, deltaAngle) # Record crank angle for next time around self.lastCrankAngle = newAngle @@ -416,7 +419,10 @@ class DirectManipulationControl(PandaObject): deltaAngle = angle - state.lastAngle state.lastAngle = angle # Mouse motion edge to edge of display region results in one full turn - relHpr(direct.widget, direct.camera, 0, 0, deltaAngle) + if base.config.GetBool('temp-hpr-fix',0): + relHpr(direct.widget, direct.camera, 0, 0, -deltaAngle) + else: + relHpr(direct.widget, direct.camera, 0, 0, deltaAngle) def scale3D(self, state): # Scale the selected node based upon up down mouse motion @@ -461,7 +467,7 @@ class DirectManipulationControl(PandaObject): # Move the objects with the widget direct.selected.moveWrtWidgetAll() # Let everyone know that something was moved - messenger.send('manipulateObjectCleanup') + messenger.send('DIRECT_manipulateObjectCleanup') class ObjectHandles(NodePath,PandaObject): def __init__(self): diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 142515856b..ce466b51e7 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -107,7 +107,7 @@ class SelectedNodePaths(PandaObject): # And keep track of it in the deselected dictionary self.deselectedDict[id] = dnp # Send a message - messenger.send('deselectedNodePath', [dnp]) + messenger.send('DIRECT_deselectedNodePath', [dnp]) return dnp def getSelectedAsList(self): diff --git a/direct/src/directtools/DirectSession.py b/direct/src/directtools/DirectSession.py index 554b227377..515bf45004 100644 --- a/direct/src/directtools/DirectSession.py +++ b/direct/src/directtools/DirectSession.py @@ -7,7 +7,9 @@ from DirectGrid import * from DirectGeometry import * from DirectLights import * from DirectSessionPanel import * +from tkSimpleDialog import askstring import Placer +import EntryScale import OnscreenText import types import __builtin__ @@ -44,6 +46,7 @@ class DirectSession(PandaObject): # Ancestry of currently selected object self.ancestry = [] self.ancestryIndex = 0 + self.activeParent = None self.readout = OnscreenText.OnscreenText( pos = (0.1, -0.95), bg=Vec4(1,1,1,1)) # Make sure readout is never lit or drawn in wireframe @@ -90,15 +93,19 @@ class DirectSession(PandaObject): ['highlightAll', self.selected.highlightAll], ['preRemoveNodePath', self.deselect], # Scene graph explorer functions - ['SGENodePath_Select', self.select], - ['SGENodePath_Deselect', self.deselect], - ['SGENodePath_Flash', self.flash], - ['SGENodePath_Isolate', self.isolate], - ['SGENodePath_Toggle Vis', self.toggleVis], - ['SGENodePath_Show All', self.showAllDescendants], - ['SGENodePath_Fit', self.fitOnNodePath], - ['SGENodePath_Place', Placer.place], - ['SGENodePath_Delete', self.removeNodePath], + ['SGE_Select', self.select], + ['SGE_Deselect', self.deselect], + ['SGE_Set Parent', self.setActiveParent], + ['SGE_Reparent', self.reparent], + ['SGE_Flash', self.flash], + ['SGE_Isolate', self.isolate], + ['SGE_Toggle Vis', self.toggleVis], + ['SGE_Show All', self.showAllDescendants], + ['SGE_Fit', self.fitOnNodePath], + ['SGE_Place', Placer.place], + ['SGE_Set Color', EntryScale.rgbPanel], + ['SGE_Delete', self.removeNodePath], + ['SGE_Set Name', self.getAndSetName], ] self.keyEvents = ['escape', 'delete', 'control', 'control-up', 'shift', 'shift-up', 'alt', 'alt-up', @@ -195,17 +202,17 @@ class DirectSession(PandaObject): def inputHandler(self, input): # Deal with keyboard and mouse input if input == 'mouse1': - messenger.send('handleMouse1') + messenger.send('DIRECT_mouse1') elif input == 'mouse1-up': - messenger.send('handleMouse1Up') + messenger.send('DIRECT_mouse1Up') elif input == 'mouse2': - messenger.send('handleMouse2') + messenger.send('DIRECT_mouse2') elif input == 'mouse2-up': - messenger.send('handleMouse2Up') + messenger.send('DIRECT_mouse2Up') elif input == 'mouse3': - messenger.send('handleMouse3') + messenger.send('DIRECT_mouse3') elif input == 'mouse3-up': - messenger.send('handleMouse3Up') + messenger.send('DIRECT_mouse3Up') elif input == 'shift': self.fShift = 1 elif input == 'shift-up': @@ -249,7 +256,7 @@ class DirectSession(PandaObject): def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1): dnp = self.selected.select(nodePath, fMultiSelect) if dnp: - messenger.send('preSelectNodePath', [dnp]) + messenger.send('DIRECT_preSelectNodePath', [dnp]) if fResetAncestry: # Update ancestry self.ancestry = dnp.getAncestry() @@ -276,7 +283,7 @@ class DirectSession(PandaObject): t.dnp = dnp taskMgr.spawnTaskNamed(t, 'followSelectedNodePath') # Send an message marking the event - messenger.send('selectedNodePath', [dnp]) + messenger.send('DIRECT_selectedNodePath', [dnp]) def followSelectedNodePathTask(self, state): mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render) @@ -296,7 +303,7 @@ class DirectSession(PandaObject): taskMgr.removeTasksNamed('followSelectedNodePath') self.ancestry = [] # Send an message marking the event - messenger.send('deselectedNodePath', [dnp]) + messenger.send('DIRECT_deselectedNodePath', [dnp]) def deselectAll(self): self.selected.deselectAll() @@ -306,6 +313,20 @@ class DirectSession(PandaObject): self.readout.setText(' ') taskMgr.removeTasksNamed('followSelectedNodePath') + def setActiveParent(self, nodePath = None): + # Record new parent + self.activeParent = nodePath + # Alert everyone else + messenger.send('DIRECT_activeParent', [self.activeParent]) + + def reparent(self, nodePath = None): + if nodePath and self.activeParent: + oldParent = nodePath.getParent() + nodePath.reparentTo(self.activeParent) + # Alert everyone else + messenger.send('DIRECT_reparent', + [nodePath, oldParent, self.activeParent]) + def flash(self, nodePath = 'None Given'): """ Highlight an object by setting it red for a few seconds """ # Clean up any existing task @@ -421,6 +442,14 @@ class DirectSession(PandaObject): self.select(np, 0, 0) self.flash(np) + def getAndSetName(self, nodePath): + """ Prompt user for new node path name """ + newName = askstring('Node Path: ' + nodePath.getName(), + 'Enter new name:') + if newName: + nodePath.setName(newName) + messenger.send('DIRECT_nodePathSetName', [nodePath, newName]) + # UNDO REDO FUNCTIONS def pushUndo(self, nodePathList, fResetRedo = 1): # Assemble group of changes @@ -435,10 +464,10 @@ class DirectSession(PandaObject): # Truncate list self.undoList = self.undoList[-25:] # Alert anyone who cares - messenger.send('pushUndo') + messenger.send('DIRECT_pushUndo') if fResetRedo and (nodePathList != []): self.redoList = [] - messenger.send('redoListEmpty') + messenger.send('DIRECT_redoListEmpty') def popUndoGroup(self): # Get last item @@ -447,7 +476,7 @@ class DirectSession(PandaObject): self.undoList = self.undoList[:-1] # Update state of undo button if not self.undoList: - messenger.send('undoListEmpty') + messenger.send('DIRECT_undoListEmpty') # Return last item return undoGroup @@ -464,7 +493,7 @@ class DirectSession(PandaObject): # Truncate list self.redoList = self.redoList[-25:] # Alert anyone who cares - messenger.send('pushRedo') + messenger.send('DIRECT_pushRedo') def popRedoGroup(self): # Get last item @@ -473,7 +502,7 @@ class DirectSession(PandaObject): self.redoList = self.redoList[:-1] # Update state of redo button if not self.redoList: - messenger.send('redoListEmpty') + messenger.send('DIRECT_redoListEmpty') # Return last item return redoGroup @@ -489,7 +518,7 @@ class DirectSession(PandaObject): # Undo xform pose[0].setPosHprScale(pose[1], pose[2], pose[3]) # Alert anyone who cares - messenger.send('undo') + messenger.send('DIRECT_undo') def redo(self): if self.redoList: @@ -502,7 +531,7 @@ class DirectSession(PandaObject): for pose in redoGroup: pose[0].setPosHprScale(pose[1], pose[2], pose[3]) # Alert anyone who cares - messenger.send('redo') + messenger.send('DIRECT_redo') # UTILITY FUNCTIONS def useObjectHandles(self): diff --git a/direct/src/directtools/DirectSessionGlobal.py b/direct/src/directtools/DirectSessionGlobal.py deleted file mode 100644 index 50938dde4a..0000000000 --- a/direct/src/directtools/DirectSessionGlobal.py +++ /dev/null @@ -1,12 +0,0 @@ -from ShowBaseGlobal import * -import __builtin__ - -# If specified in the user's Configrc, create the direct session -if base.wantDIRECT: - from DirectSession import * - __builtin__.direct = base.direct = DirectSession() - direct.enable() -else: - # Otherwise set the values to None - __builtin__.direct = base.direct = None - diff --git a/direct/src/directtools/DirectUtil.py b/direct/src/directtools/DirectUtil.py index 85451d67b0..26370bc6c4 100644 --- a/direct/src/directtools/DirectUtil.py +++ b/direct/src/directtools/DirectUtil.py @@ -1,4 +1,11 @@ from PandaObject import * +from EntryScale import EntryScale + +def adjust(command = None, min = 0.0, max = 1.0, text = 'Adjust'): + tl = Toplevel() + tl.title('Parameter Adjust') + es = EntryScale(tl, command = command, min = min, max = max, text = text) + es.pack(expand = 1, fill = X) ## Background Color ## def setBackgroundColor(r,g,b): diff --git a/direct/src/extensions/NodePath-extensions.py b/direct/src/extensions/NodePath-extensions.py index 5a58d9bbc2..02482e4ef2 100644 --- a/direct/src/extensions/NodePath-extensions.py +++ b/direct/src/extensions/NodePath-extensions.py @@ -776,11 +776,40 @@ def place(self): base.wantDIRECT = 1 base.wantTk = 1 - from TkGlobal import * - from DirectSessionGlobal import * + from ShowBaseGlobal import * + import TkGlobal import Placer Placer.place(self) + def explore(self): + base.wantDIRECT = 1 + base.wantTk = 1 + from ShowBaseGlobal import * + import TkGlobal + import SceneGraphExplorer + SceneGraphExplorer.explore(self) + + def rgbPanel(self, cb = None): + base.wantDIRECT = 1 + base.wantTk = 1 + from ShowBaseGlobal import * + import TkGlobal + import EntryScale + EntryScale.rgbPanel(self, cb) + + def select(self): + base.wantDIRECT = 1 + base.wantTk = 1 + from ShowBaseGlobal import * + import TkGlobal + direct.select(self) + + def deselect(self): + base.wantDIRECT = 1 + base.wantTk = 1 + from ShowBaseGlobal import * + import TkGlobal + direct.deselect(self) diff --git a/direct/src/interval/IntervalTest.py b/direct/src/interval/IntervalTest.py index 2ea85957b4..27b46e73e8 100644 --- a/direct/src/interval/IntervalTest.py +++ b/direct/src/interval/IntervalTest.py @@ -1,5 +1,5 @@ from PandaModules import * -from DirectSessionGlobal import * +from ShowBaseGlobal import * from IntervalGlobal import * from Actor import * diff --git a/direct/src/leveleditor/LevelEditor.py b/direct/src/leveleditor/LevelEditor.py index f513293bd6..7c7a0deb2f 100644 --- a/direct/src/leveleditor/LevelEditor.py +++ b/direct/src/leveleditor/LevelEditor.py @@ -20,14 +20,13 @@ else: print "Loading LevelEditor for hoods: ", hoods -from DirectSessionGlobal import * +from ShowBaseGlobal import * from PandaObject import * from PieMenu import * from GuiGlobals import * from Tkinter import * from DirectGeometry import * from SceneGraphExplorer import * -from tkSimpleDialog import askstring from tkMessageBox import showinfo from tkFileDialog import * from whrandom import * @@ -39,7 +38,6 @@ import os import __builtin__ import whrandom import Floater -import EntryScale # Colors used by all color menus DEFAULT_COLORS = [ @@ -418,19 +416,19 @@ class LevelEditor(NodePath, PandaObject): # The list of events the level editor responds to self.actionEvents = [ - # Actions in response to DIRECT operations - ('selectedNodePath', self.selectedNodePathHook), - ('deselectedNodePath', self.deselectedNodePathHook), + # Node path events ('preRemoveNodePath', self.removeNodePathHook), - ('manipulateObjectCleanup', self.updateSelectedPose), - + # Actions in response to DIRECT operations + ('DIRECT_selectedNodePath', self.selectedNodePathHook), + ('DIRECT_deselectedNodePath', self.deselectedNodePathHook), + ('DIRECT_manipulateObjectCleanup', self.updateSelectedPose), + ('DIRECT_nodePathSetName', self.setName), + ('DIRECT_activeParent', self.setActiveParent), + ('DIRECT_reparent', self.reparent), + ('RGBPanel_setColor', self.setColor), # Actions in response to Level Editor Panel operations - ('SGENodePath_Set Name', self.getAndSetName), - ('SGENodePath_Set Parent', self.setActiveParent), - ('SGENodePath_Reparent', self.reparent), - ('SGENodePath_Add Group', self.addGroup), - ('SGENodePath_Add Vis Group', self.addVisGroup), - ('SGENodePath_Set Color', self.setNPColor), + ('SGE_Add Group', self.addGroup), + ('SGE_Add Vis Group', self.addVisGroup), # Actions in response to Pie Menu interaction ('select_building_style', self.setBuildingStyle), ('select_building_type', self.setBuildingType), @@ -515,6 +513,7 @@ class LevelEditor(NodePath, PandaObject): # BATTLE CELLS self.battleCellMarker = loader.loadModel('models/misc/sphere') + self.battleCellMarker.setName('battleCellMarker') self.battleCellMarker.setScale(1) self.currentBattleCellType = "20w 20l" @@ -676,19 +675,22 @@ class LevelEditor(NodePath, PandaObject): # Turn off player camera control base.disableMouse() # Handle mouse events for pie menus - self.accept('handleMouse3',self.levelHandleMouse3) - self.accept('handleMouse3Up',self.levelHandleMouse3Up) + self.accept('DIRECT_mouse3',self.levelHandleMouse3) + self.accept('DIRECT_mouse3Up',self.levelHandleMouse3Up) def disableMouse(self): """ Disable Pie Menu interaction """ # Disable handling of mouse events - self.ignore('handleMouse3') - self.ignore('handleMouse3Up') + self.ignore('DIRECT_mouse3') + self.ignore('DIRECT_mouse3Up') # LEVEL OBJECT MANAGEMENT FUNCTIONS def findDNANode(self, nodePath): """ Find node path's DNA Object in DNAStorage (if any) """ - return DNASTORE.findDNAGroup(nodePath.id()) + if nodePath: + return DNASTORE.findDNAGroup(nodePath.id()) + else: + return None def replaceSelected(self): if self.replaceSelectedEnabled: @@ -735,40 +737,35 @@ class LevelEditor(NodePath, PandaObject): nodePath.removeNode() def removeNodePathHook(self, nodePath): - if nodePath: - dnaNode = self.findDNANode(nodePath) - # Does the node path correspond to a DNA Object - if dnaNode: - for i in self.removeHookList: - i(dnaNode, nodePath) - # Get DNANode's parent - parentDNANode = dnaNode.getParent() - if parentDNANode: - # Remove DNANode from its parent - parentDNANode.remove(dnaNode) - # Delete DNA and associated Node Relations from DNA Store - DNASTORE.removeDNAGroup(dnaNode) + dnaNode = self.findDNANode(nodePath) + # Does the node path correspond to a DNA Object + if dnaNode: + for i in self.removeHookList: + i(dnaNode, nodePath) + # Get DNANode's parent + parentDNANode = dnaNode.getParent() + if parentDNANode: + # Remove DNANode from its parent + parentDNANode.remove(dnaNode) + # Delete DNA and associated Node Relations from DNA Store + DNASTORE.removeDNAGroup(dnaNode) - def reparent(self, nodePath): + def reparent(self, nodePath, oldParent, newParent): """ Move node path (and its DNA) to active parent """ - # Do we have a node path? - if nodePath: - dnaNode = self.findDNANode(nodePath) - # Does the node path correspond to a DNA Object - if dnaNode: - # Yes, get its parent and see if it has a DNA Object - parent = nodePath.getParent() - parentDNAObject = self.findDNANode(parent) - if parentDNAObject: - # Yes it does, move node path (and DNA) - # to new parent (if active parent set) - if ((self.NPParent != None) and - (self.DNAParent != None)): - nodePath.reparentTo(self.NPParent) - parentDNAObject.remove(dnaNode) - self.DNAParent.add(dnaNode) - # Update scene graph explorer to reflect change - # self.panel.sceneGraphExplorer.update() + # Does the node path correspond to a DNA Object + dnaNode = self.findDNANode(nodePath) + if dnaNode: + # Find old parent DNA + oldParentDNANode = self.findDNANode(oldParent) + # Remove DNA from old parent + if oldParentDNANode: + oldParentDNANode.remove(dnaNode) + if newParent: + # Update active parent just to be safe + self.setActiveParent(newParent) + # Move DNA to new parent (if active parent set) + if self.DNAParent != None: + self.DNAParent.add(dnaNode) def reparentSelected(self): for nodePath in direct.selected: @@ -776,9 +773,6 @@ class LevelEditor(NodePath, PandaObject): def setActiveParent(self, nodePath = None): """ Set NPParent and DNAParent to node path and its DNA """ - # If nothing passed in, try currently selected node path - if not nodePath: - nodePath = direct.selected.last # If we've got a valid node path if nodePath: # See if this is in the DNA database @@ -791,17 +785,9 @@ class LevelEditor(NodePath, PandaObject): else: print 'LevelEditor.setActiveParent: nodePath == None' - def getAndSetName(self, nodePath): - """ Prompt user for new node path name """ - newName = askstring('Node Path', 'Enter new name:') - if newName: - self.setName(nodePath, newName) - def setName(self, nodePath, newName): - """ Set name of a node path and its DNA (if it exists) """ - # First, set name of the node path - nodePath.setName(newName) - # Now find the DNA that corresponds to this node path + """ Set name of nodePath's DNA (if it exists) """ + # Find the DNA that corresponds to this node path dnaNode = self.findDNANode(nodePath) if dnaNode: # If it exists, set the name of the DNA Node @@ -834,30 +820,34 @@ class LevelEditor(NodePath, PandaObject): # Update DNA self.updatePose(dnaObject, selectedNode) else: - possiblePoint = self.findSuitPointMarker(selectedNode) - if possiblePoint: - point = self.getSuitPointFromNodePath(possiblePoint) - if point: - print "Found suit point!", point - # First snap selected node path to grid - pos = selectedNode.getPos(direct.grid) - snapPos = direct.grid.computeSnapPoint(pos) - if self.panel.fPlaneSnap.get(): - zheight = 0 - else: - zheight = snapPos[2] - selectedNode.setPos(direct.grid, - snapPos[0], snapPos[1], zheight) - newPos = selectedNode.getPos(self.NPToplevel) - point.setPos(newPos) + pointOrCell, type = self.findPointOrCell(selectedNode) + if pointOrCell and type: + # First snap selected node path to grid + pos = selectedNode.getPos(direct.grid) + snapPos = direct.grid.computeSnapPoint(pos) + if self.panel.fPlaneSnap.get(): + zheight = 0 + else: + zheight = snapPos[2] + selectedNode.setPos( + direct.grid, + snapPos[0], snapPos[1], zheight) + newPos = selectedNode.getPos(self.NPToplevel) + # Update DNA + pointOrCell.setPos(newPos) + if (type == 'suitPointMarker'): + print "Found suit point!", pointOrCell # Ok, now update all the lines into that node - for edge in self.point2edgeDict[point]: + for edge in self.point2edgeDict[pointOrCell]: oldEdgeLine = self.edgeDict[edge] del self.edgeDict[edge] oldEdgeLine.reset() del oldEdgeLine - newEdgeLine = self.drawSuitEdge(edge, self.NPParent) + newEdgeLine = self.drawSuitEdge( + edge, self.NPParent) self.edgeDict[edge] = newEdgeLine + elif (type == 'battleCellMarker'): + print "Found battle cell!", pointOrCell def updatePose(self, dnaObject, nodePath): """ @@ -1013,14 +1003,14 @@ class LevelEditor(NodePath, PandaObject): def addGroup(self, nodePath): """ Add a new DNA Node Group to the specified Node Path """ # Set the node path as the current parent - self.setActiveParent(nodePath) + direct.setActiveParent(nodePath) # Add a new group to the selected parent self.createNewGroup() def addVisGroup(self, nodePath): """ Add a new DNA Group to the specified Node Path """ # Set the node path as the current parent - self.setActiveParent(nodePath) + direct.setActiveParent(nodePath) # Add a new group to the selected parent self.createNewGroup(type = 'vis') @@ -1473,13 +1463,23 @@ class LevelEditor(NodePath, PandaObject): self.DNATarget.getHeight()) self.replaceSelected() - def setNPColor(self, nodePath): + def setColor(self, nodePath, r,g,b,a): """ This is used to set color of dnaNode subparts """ - def updateDNANodeColor(color, s = self, np = nodePath): - # Update node color in DNASTORE here - # dnaNode = s.findDNANode(np) - pass - esg = EntryScale.setColor(nodePath, updateDNANodeColor) + dnaNode = self.findDNANode(nodePath) + if dnaNode: + objClass = DNAGetClassType(dnaNode) + if ((objClass.eq(DNA_WALL)) or + (objClass.eq(DNA_WINDOWS)) or + (objClass.eq(DNA_DOOR)) or + (objClass.eq(DNA_CORNICE)) or + (objClass.eq(DNA_PROP)) or + (objClass.eq(DNA_SIGN)) or + (objClass.eq(DNA_SIGN_BASELINE)) or + (objClass.eq(DNA_SIGN_TEXT)) or + (objClass.eq(DNA_SIGN_GRAPHIC)) + ): + # Update dna information + dnaNode.setColor(VBase4(r/255.0, g/255.0, b/255.0, a/255.0)) # SELECTION FUNCTIONS def selectedNodePathHook(self, nodePath): @@ -1527,15 +1527,12 @@ class LevelEditor(NodePath, PandaObject): if DNAClassEqual(dnaNode, DNA_STREET): self.snapList = OBJECT_SNAP_POINTS[dnaNode.getCode()] else: - possiblePoint = self.findSuitPointMarker(nodePath) - if possiblePoint: - point = self.getSuitPointFromNodePath(possiblePoint) - if point: - print "Found suit point!", point - else: - pass - else: - pass + pointOrCell, type = self.findPointOrCell(nodePath) + if pointOrCell and (type == 'suitPointMarker'): + print "Found suit point!", pointOrCell + if pointOrCell and (type == 'battleCellMarker'): + print "Found battle cell!", pointOrCell + # Let others know that something new may be selected: for i in self.selectedNodePathHookHooks: i() @@ -1577,20 +1574,29 @@ class LevelEditor(NodePath, PandaObject): return self.findDNARoot(nodePath.getParent()) - def findSuitPointMarker(self, nodePath): - """ Walk up a node path's ancestry looking for its DNA Root """ + def findPointOrCell(self, nodePath): + """ + Walk up a node path's ancestry to see if its a suit point marker + or a battle cell marker + """ # Check current node's name for root marker if (nodePath.getName() == 'suitPointMarker'): - # Its a root! - return nodePath + # Its a suit point marker! + # See if point is in pointDict + point = self.getSuitPointFromNodePath(nodePath) + return point, 'suitPointMarker' + elif (nodePath.getName() == 'battleCellMarker'): + # Its a battle cell marker + # See if cell is in cell Dict + cell = self.getBattleCellFromNodePath(nodePath) + return cell, 'battleCellMarker' else: # If reached the top: fail if not nodePath.hasParent(): - return None + return None, None else: # Try parent - return self.findSuitPointMarker(nodePath.getParent()) - + return self.findPointOrCell(nodePath.getParent()) # MANIPULATION FUNCTIONS def keyboardRotateSelected(self, arrowDirection): @@ -2252,15 +2258,17 @@ class LevelEditor(NodePath, PandaObject): def placeSuitPoint(self): v = self.getGridSnapIntersectionPoint() - # get the absolute pos relative to the top level. That is what gets stored in the point + # get the absolute pos relative to the top level. + # That is what gets stored in the point mat = direct.grid.getMat(self.NPToplevel) absPos = Point3(mat.xformPoint(v)) print 'Suit point: ' + `absPos` - # Store the point in the DNA. If this point is already in there, it returns - # the existing point + # Store the point in the DNA. If this point is already in there, + # it returns the existing point suitPoint = DNASTORE.storeSuitPoint(self.currentSuitPointType, absPos) if not self.pointDict.has_key(suitPoint): - marker = self.drawSuitPoint(absPos, self.currentSuitPointType, self.NPToplevel) + marker = self.drawSuitPoint( + absPos, self.currentSuitPointType, self.NPToplevel) self.pointDict[suitPoint] = marker self.currentSuitPointIndex = suitPoint.getIndex() @@ -2269,9 +2277,10 @@ class LevelEditor(NodePath, PandaObject): # Make a new dna edge if DNAClassEqual(self.DNAParent, DNA_VIS_GROUP): zoneId = self.DNAParent.getName() - suitEdge = DNASuitEdge(self.startSuitPoint, self.endSuitPoint, zoneId) + suitEdge = DNASuitEdge( + self.startSuitPoint, self.endSuitPoint, zoneId) DNASTORE.storeSuitEdge(suitEdge) - # Add the edge to the current vis group so it can be written out + # Add edge to the current vis group so it can be written out self.DNAParent.addSuitEdge(suitEdge) # Draw a line to represent the edge edgeLine = self.drawSuitEdge(suitEdge, self.NPParent) @@ -2338,7 +2347,8 @@ class LevelEditor(NodePath, PandaObject): numPoints = DNASTORE.getNumSuitPoints() for i in range(numPoints): point = DNASTORE.getSuitPoint(i) - marker = self.drawSuitPoint(point.getPos(), point.getPointType(), self.NPToplevel) + marker = self.drawSuitPoint( + point.getPos(), point.getPointType(), self.NPToplevel) self.pointDict[point] = marker # Edges @@ -2359,7 +2369,6 @@ class LevelEditor(NodePath, PandaObject): else: self.point2edgeDict[point] = [edge] - def getSuitPointFromNodePath(self, nodePath): """ Given a node path, attempt to find the point,nodePath pair @@ -2421,6 +2430,18 @@ class LevelEditor(NodePath, PandaObject): for cell, marker in self.cellDict.items(): marker.show() + def getBattleCellFromNodePath(self, nodePath): + """ + Given a node path, attempt to find the battle cell, nodePath pair + in the cellDict. If it is there, return the cell. If we + cannot find it, return None. + TODO: a reverse lookup cellDict would speed this up quite a bit + """ + for cell, marker in self.cellDict.items(): + if marker.eq(nodePath): + return cell + return None + def colorZones(self): # Give each zone a random color to see them better visGroups = self.getDNAVisGroups(self.NPToplevel) @@ -3728,13 +3749,14 @@ class LevelEditorPanel(Pmw.MegaToplevel): self.fUpdateSelected = 1 # Handle to the toplevels hull hull = self.component('hull') - + hull.geometry('400x575') + balloon = self.balloon = Pmw.Balloon(hull) # Start with balloon help disabled self.balloon.configure(state = 'none') menuFrame = Frame(hull, relief = GROOVE, bd = 2) - menuFrame.pack(fill = X, expand = 1) + menuFrame.pack(fill = X) menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon) menuBar.pack(side = LEFT, expand = 1, fill = X) @@ -3809,7 +3831,7 @@ class LevelEditorPanel(Pmw.MegaToplevel): self.editMenu = Pmw.ComboBox( menuFrame, labelpos = W, - label_text = 'Edit Mode:', entry_width = 12, + label_text = 'Edit Mode:', entry_width = 18, selectioncommand = self.levelEditor.setEditMode, history = 0, scrolledlist_items = NEIGHBORHOODS) self.editMenu.selectitem(NEIGHBORHOODS[0]) @@ -4181,50 +4203,7 @@ class LevelEditorPanel(Pmw.MegaToplevel): variable = self.fGrid, command = self.toggleGrid) direct.gridButton.pack(side = 'left', expand = 1, fill = 'x') - - buttonFrame.pack(expand = 1, fill = 'x') - - buttonFrame2 = Frame(hull) - self.groupButton = Button( - buttonFrame2, - text = 'New Group', - command = self.levelEditor.createNewGroup) - self.groupButton.pack(side = 'left', expand = 1, fill = 'x') - - self.visGroupButton = Button( - buttonFrame2, - text = 'New Vis Group', - command = self.createNewVisGroup) - self.visGroupButton.pack(side = 'left', expand = 1, fill = 'x') - - self.setParentButton = Button( - buttonFrame2, - text = 'Set Parent', - command = self.levelEditor.setActiveParent) - self.setParentButton.pack(side = 'left', expand = 1, fill = 'x') - - self.reparentButton = Button( - buttonFrame2, - text = 'Re Parent', - command = self.levelEditor.reparentSelected) - self.reparentButton.pack(side = 'left', expand = 1, fill = 'x') - - buttonFrame2.pack(fill = 'x') - - buttonFrame3 = Frame(hull) - self.isolateButton = Button( - buttonFrame3, - text = 'Isolate Selected', - command = direct.isolate) - self.isolateButton.pack(side = 'left', expand = 1, fill = 'x') - - self.showAllButton = Button( - buttonFrame3, - text = 'Show All', - command = self.showAll) - self.showAllButton.pack(side = 'left', expand = 1, fill = 'x') - - buttonFrame3.pack(fill = 'x') + buttonFrame.pack(fill = X) buttonFrame4 = Frame(hull) self.driveMode = IntVar() @@ -4243,14 +4222,13 @@ class LevelEditorPanel(Pmw.MegaToplevel): variable = self.driveMode, command = self.levelEditor.useDirectFly) directModeButton.pack(side = 'left', expand = 1, fill = 'x') - buttonFrame4.pack(fill = 'x') + buttonFrame4.pack(fill = X) self.sceneGraphExplorer = SceneGraphExplorer( parent = sceneGraphPage, - menuItems = ['Set Parent', 'Reparent', 'Add Group', - 'Add Vis Group', 'Set Color', - 'Set Name']) - self.sceneGraphExplorer.pack(expand = 1, fill = 'both') + nodePath = self.levelEditor, + menuItems = ['Add Group', 'Add Vis Group', 'Set Color']) + self.sceneGraphExplorer.pack(expand = 1, fill = BOTH) # Make sure input variables processed self.initialiseoptions(LevelEditorPanel) @@ -4286,12 +4264,6 @@ class LevelEditorPanel(Pmw.MegaToplevel): def toggleMapVis(self): self.levelEditor.toggleMapVis(self.fMapVis.get()) - def showAll(self): - direct.showAll(self.levelEditor.NPToplevel) - - def createNewVisGroup(self): - self.levelEditor.createNewGroup(type = 'vis') - def setStreetModuleType(self,name): self.streetModuleType = 'street_' + name self.levelEditor.setCurrent('street_texture', self.streetModuleType) @@ -4699,8 +4671,8 @@ class LevelEditorPanel(Pmw.MegaToplevel): (objClass.eq(DNA_PROP)) or (objClass.eq(DNA_SIGN)) or (objClass.eq(DNA_SIGN_BASELINE)) or - (objClass.eq(DNA_SIGN_BASELINE_TEXT)) or - (objClass.eq(DNA_SIGN_BASELINE_GRAPHIC)) + (objClass.eq(DNA_SIGN_TEXT)) or + (objClass.eq(DNA_SIGN_GRAPHIC)) ): self.levelEditor.setDNATargetColor( VBase4((color[0]/255.0), diff --git a/direct/src/leveleditor/LevelEditorStart.py b/direct/src/leveleditor/LevelEditorStart.py index 6fe0a0347f..499cbbebe0 100644 --- a/direct/src/leveleditor/LevelEditorStart.py +++ b/direct/src/leveleditor/LevelEditorStart.py @@ -1,3 +1,3 @@ -from DirectSessionGlobal import * +from ShowBaseGlobal import * import LevelEditor l = LevelEditor.LevelEditor() diff --git a/direct/src/particles/ParticleTest.py b/direct/src/particles/ParticleTest.py index ffc9abb1ac..4c558898cd 100644 --- a/direct/src/particles/ParticleTest.py +++ b/direct/src/particles/ParticleTest.py @@ -1,4 +1,4 @@ -from DirectSessionGlobal import * +from ShowBaseGlobal import * import ParticleEffect import ParticlePanel diff --git a/direct/src/particles/Particles.py b/direct/src/particles/Particles.py index c11c3bd505..a5de73d712 100644 --- a/direct/src/particles/Particles.py +++ b/direct/src/particles/Particles.py @@ -179,6 +179,9 @@ class Particles(ParticleSystem.ParticleSystem): else: self.removeAngularForce(force) + def setRenderNodePath(self, nodePath): + self.setRenderParent(nodePath.node()) + ## Getters ## def getName(self): """getName()""" diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 60f4c97f20..fc1957a7f6 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -20,6 +20,15 @@ __builtin__.messenger = base.messenger __builtin__.config = base.config __builtin__.directNotify = directNotify +# Initialize DIRECT +if base.wantDIRECT: + from DirectSession import * + __builtin__.direct = base.direct = DirectSession() + direct.enable() +else: + # Otherwise set the values to None + __builtin__.direct = base.direct = None + # Set direct notify categories now that we have config directNotify.setDconfigLevels() diff --git a/direct/src/tkpanels/DirectSessionPanel.py b/direct/src/tkpanels/DirectSessionPanel.py index 418d73a7b0..407588d6ee 100644 --- a/direct/src/tkpanels/DirectSessionPanel.py +++ b/direct/src/tkpanels/DirectSessionPanel.py @@ -22,7 +22,7 @@ taskMgr page class DirectSessionPanel(AppShell): # Override class variables here appname = 'Direct Session Panel' - frameWidth = 550 + frameWidth = 600 frameHeight = 502 usecommandarea = 1 usestatusarea = 0 @@ -67,15 +67,16 @@ class DirectSessionPanel(AppShell): self.jbNodePathNames = ['camera', 'selected', 'none'] # Set up event hooks - self.actionEvents = [('undo', self.undoHook), - ('pushUndo', self.pushUndoHook), - ('undoListEmpty', self.undoListEmptyHook), - ('redo', self.redoHook), - ('pushRedo', self.pushRedoHook), - ('redoListEmpty', self.redoListEmptyHook), - ('selectedNodePath', self.selectedNodePathHook), - ('DirectLights_addLight', self.addLight), - ] + self.actionEvents = [ + ('DIRECT_undo', self.undoHook), + ('DIRECT_pushUndo', self.pushUndoHook), + ('DIRECT_undoListEmpty', self.undoListEmptyHook), + ('DIRECT_redo', self.redoHook), + ('DIRECT_pushRedo', self.pushRedoHook), + ('DIRECT_redoListEmpty', self.redoListEmptyHook), + ('DIRECT_selectedNodePath',self.selectedNodePathHook), + ('DIRECT_addLight', self.addLight), + ] for event, method in self.actionEvents: self.accept(event, method) @@ -139,20 +140,21 @@ class DirectSessionPanel(AppShell): # The master frame for the dials mainFrame = Frame(interior) + # Paned widget for dividing two halves + framePane = Pmw.PanedWidget(mainFrame, orient = HORIZONTAL) + sgeFrame = framePane.add('left', min = 250) + notebookFrame = framePane.add('right', min = 300) + # Scene Graph Explorer - sgeFrame = Frame(mainFrame) - self.sgeUpdate = Button(sgeFrame, text = 'Update Explorer') - self.sgeUpdate.pack(fill = X, expand = 0) self.SGE = SceneGraphExplorer.SceneGraphExplorer( sgeFrame, nodePath = render, - scrolledCanvas_hull_width = 200, + scrolledCanvas_hull_width = 250, scrolledCanvas_hull_height = 400) self.SGE.pack(fill = BOTH, expand = 0) - self.sgeUpdate['command'] = self.SGE.update sgeFrame.pack(side = LEFT, fill = 'both', expand = 0) # Create the notebook pages - notebook = Pmw.NoteBook(mainFrame) + notebook = Pmw.NoteBook(notebookFrame) notebook.pack(fill = BOTH, expand = 1) envPage = notebook.add('Environment') lightsPage = notebook.add('Lights') @@ -562,9 +564,9 @@ class DirectSessionPanel(AppShell): self.jbHprSF.pack(fill = X, expand = 0) self.bind(self.jbHprSF, 'Set joybox HPR speed multiplier') - notebook.setnaturalsize() - + + framePane.pack(expand = 1, fill = BOTH) mainFrame.pack(fill = 'both', expand = 1) # Create some buttons in the bottom tray diff --git a/direct/src/tkpanels/MopathRecorder.py b/direct/src/tkpanels/MopathRecorder.py index 76815c9a3a..4ab8dd3d62 100644 --- a/direct/src/tkpanels/MopathRecorder.py +++ b/direct/src/tkpanels/MopathRecorder.py @@ -153,16 +153,17 @@ class MopathRecorder(AppShell, PandaObject): self.iRay = SelectionRay(self.iRayCS) # Set up event hooks self.actionEvents = [ - ('undo', self.undoHook), - ('pushUndo', self.pushUndoHook), - ('undoListEmpty', self.undoListEmptyHook), - ('redo', self.redoHook), - ('pushRedo', self.pushRedoHook), - ('redoListEmpty', self.redoListEmptyHook), - ('selectedNodePath', self.selectedNodePathHook), - ('deselectedNodePath', self.deselectedNodePathHook), - ('manipulateObjectStart', self.manipulateObjectStartHook), - ('manipulateObjectCleanup', self.manipulateObjectCleanupHook), + ('DIRECT_undo', self.undoHook), + ('DIRECT_pushUndo', self.pushUndoHook), + ('DIRECT_undoListEmpty', self.undoListEmptyHook), + ('DIRECT_redo', self.redoHook), + ('DIRECT_pushRedo', self.pushRedoHook), + ('DIRECT_redoListEmpty', self.redoListEmptyHook), + ('DIRECT_selectedNodePath', self.selectedNodePathHook), + ('DIRECT_deselectedNodePath', self.deselectedNodePathHook), + ('DIRECT_manipulateObjectStart', self.manipulateObjectStartHook), + ('DIRECT_manipulateObjectCleanup', + self.manipulateObjectCleanupHook), ] for event, method in self.actionEvents: self.accept(event, method) diff --git a/direct/src/tkpanels/Placer.py b/direct/src/tkpanels/Placer.py index aeca5dc183..8a78d574f2 100644 --- a/direct/src/tkpanels/Placer.py +++ b/direct/src/tkpanels/Placer.py @@ -67,12 +67,12 @@ class Placer(AppShell): self.posOffset = Vec3(0) # Set up event hooks - self.undoEvents = [('undo', self.undoHook), - ('pushUndo', self.pushUndoHook), - ('undoListEmpty', self.undoListEmptyHook), - ('redo', self.redoHook), - ('pushRedo', self.pushRedoHook), - ('redoListEmpty', self.redoListEmptyHook)] + self.undoEvents = [('DIRECT_undo', self.undoHook), + ('DIRECT_pushUndo', self.pushUndoHook), + ('DIRECT_undoListEmpty', self.undoListEmptyHook), + ('DIRECT_redo', self.redoHook), + ('DIRECT_pushRedo', self.pushRedoHook), + ('DIRECT_redoListEmpty', self.redoListEmptyHook)] for event, method in self.undoEvents: self.accept(event, method) @@ -610,7 +610,7 @@ class Placer(AppShell): def xformStop(self, data): # Throw event to signal manipulation done - messenger.send('manipulateObjectCleanup') + messenger.send('DIRECT_manipulateObjectCleanup') # Update placer to reflect new state self.updatePlacer() # If moving widget restart follow task diff --git a/direct/src/tkwidgets/EntryScale.py b/direct/src/tkwidgets/EntryScale.py index ea04f66d01..ca6383828a 100644 --- a/direct/src/tkwidgets/EntryScale.py +++ b/direct/src/tkwidgets/EntryScale.py @@ -22,7 +22,7 @@ class EntryScale(Pmw.MegaWidget): ('initialValue', 0.0, Pmw.INITOPT), ('resolution', 0.001, None), ('command', None, None), - ('callbackData', [], None), + ('callbackData', [], None), ('min', 0.0, self._updateValidate), ('max', 100.0, self._updateValidate), ('text', 'EntryScale', self._updateLabelText), @@ -328,6 +328,12 @@ class EntryScaleGroup(Pmw.MegaToplevel): text = self['labels'][index]) # Do this separately so command doesn't get executed during construction f['command'] = lambda val, s=self, i=index: s._entryScaleSetAt(i, val) + f['callbackData'] = [self] + # Callbacks + f.onReturn = self.__onReturn + f.onReturnRelease = self.__onReturnRelease + f.onPress = self.__onPress + f.onRelease = self.__onRelease f.pack(side = self['side'], expand = 1, fill = X) self.entryScaleList.append(f) @@ -376,15 +382,80 @@ class EntryScaleGroup(Pmw.MegaToplevel): def reset(self): self.set(self['initialValue']) + def __onReturn(self, esg): + # Execute onReturn callback + apply(self.onReturn, esg.get()) -def setColor(nodePath, callback = None): + def onReturn(self, *args): + """ User redefinable callback executed on button press """ + pass + + def __onReturnRelease(self, esg): + # Execute onReturnRelease callback + apply(self.onReturnRelease, esg.get()) + + def onReturnRelease(self, *args): + """ User redefinable callback executed on button press """ + pass + + def __onPress(self, esg): + # Execute onPress callback + apply(self.onPress, esg.get()) + + def onPress(self, *args): + """ User redefinable callback executed on button press """ + pass + + def __onRelease(self, esg): + # Execute onRelease callback + apply(self.onRelease, esg.get()) + + def onRelease(self, *args): + """ User redefinable callback executed on button release """ + pass + +def rgbPanel(nodePath, callback = None): def setNodePathColor(color, np = nodePath, cb = callback): np.setColor(color[0]/255.0, color[1]/255.0, color[2]/255.0, color[3]/255.0) # Execute callback to pass along color info if cb: cb(color) - def popupColorPicker(): + # Check init color + if nodePath.hasColor(): + initColor = nodePath.getColor() * 255.0 + else: + initColor = Vec4(255) + # Create entry scale group + esg = EntryScaleGroup(title = 'RGBA Panel: ' + nodePath.getName(), + dim = 4, + labels = ['R','G','B','A'], + initialValue = [int(initColor[0]), + int(initColor[1]), + int(initColor[2]), + int(initColor[3])], + Valuator_max = 255, + Valuator_resolution = 1, + # Destroy not withdraw panel on dismiss + fDestroy = 1, + command = setNodePathColor) + # Update menu button + esg.component('menubar').component('EntryScale Group-button')['text'] = ( + 'RGBA Panel') + # Update menu + menu = esg.component('menubar').component('EntryScale Group-menu') + # Some helper functions + # Clear color + menu.insert_command(index = 1, label = 'Clear Color', + command = lambda np = nodePath: np.clearColor()) + # Set Clear Transparency + menu.insert_command(index = 2, label = 'Set Transparency', + command = lambda np = nodePath: np.setTransparency(1)) + menu.insert_command( + index = 3, label = 'Clear Transparency', + command = lambda np = nodePath: np.clearTransparency()) + # System color picker + def popupColorPicker(esg = esg): # Can pass in current color with: color = (255, 0, 0) color = tkColorChooser.askcolor( parent = esg.interior(), @@ -392,26 +463,13 @@ def setColor(nodePath, callback = None): initialcolor = tuple(esg.get()[:3]))[0] if color: esg.set((color[0], color[1], color[2], esg.getAt(3))) - if isinstance(nodePath, NodePath): - if nodePath.hasColor(): - initColor = nodePath.getColor() * 255.0 - else: - initColor = Vec4(255) - esg = EntryScaleGroup(title = 'RGBA Panel', - dim = 4, - labels = ['R','G','B','A'], - initialValue = [int(initColor[0]), - int(initColor[1]), - int(initColor[2]), - int(initColor[3])], - Valuator_max = 255, - Valuator_resolution = 1, - # Destroy not withdraw panel on dismiss - fDestroy = 1, - command = setNodePathColor) - menu = esg.component('menubar').component('EntryScale Group-menu') - menu.insert_command(index = 1, label = 'Popup Color Picker', - command = popupColorPicker) + menu.insert_command(index = 4, label = 'Popup Color Picker', + command = popupColorPicker) + + # Set callback + def onRelease(r,g,b,a, nodePath = nodePath): + messenger.send('RGBPanel_setColor', [nodePath, r,g,b,a]) + esg.onRelease = onRelease return esg ## SAMPLE CODE diff --git a/direct/src/tkwidgets/SceneGraphExplorer.py b/direct/src/tkwidgets/SceneGraphExplorer.py index f7365bd53d..c7188c259e 100644 --- a/direct/src/tkwidgets/SceneGraphExplorer.py +++ b/direct/src/tkwidgets/SceneGraphExplorer.py @@ -3,11 +3,19 @@ from Tkinter import * from Tree import * import Pmw -DEFAULT_MENU_ITEMS = ['Select', 'Deselect', 'Flash', - 'Isolate', 'Toggle Vis', 'Show All', - 'Fit', 'Place', 'Delete'] +DEFAULT_MENU_ITEMS = [ + 'Update Explorer', + 'Separator', + 'Select', 'Deselect', 'Set Parent', 'Reparent', 'Set Name', + 'Separator', + 'Delete', + 'Separator', + 'Fit', 'Flash', 'Isolate', 'Toggle Vis', 'Show All', + 'Separator', + 'Place', 'Set Color', + 'Separator'] -class SceneGraphExplorer(Pmw.MegaWidget): +class SceneGraphExplorer(Pmw.MegaWidget, PandaObject): "Graphical display of a scene graph" def __init__(self, parent = None, nodePath = render, **kw): # Define the megawidget options. @@ -53,6 +61,24 @@ class SceneGraphExplorer(Pmw.MegaWidget): DEFAULT_MENU_ITEMS + self['menuItems']) self._node.expand() + self._parentFrame = Frame(interior) + self._label = self.createcomponent( + 'parentLabel', + (), None, + Label, (interior,), + text = 'Active Parent: ', + anchor = W, justify = LEFT) + self._label.pack(expand = 1, fill = X) + + # Add update parent label + def updateLabel(nodePath = None, s = self): + s._label['text'] = 'Active Parent: ' + nodePath.getName() + self.accept('DIRECT_activeParent', updateLabel) + + # Add update hook + self.accept('SGE_Update Explorer', + lambda np, s = self: s.update()) + # Check keywords and initialise options based on input values. self.initialiseoptions(SceneGraphExplorer) @@ -118,10 +144,10 @@ class SceneGraphExplorerItem(TreeItem): return sublist def OnSelect(self): - messenger.send('SGENodePath_Flash', [self.nodePath]) + messenger.send('SGE_Flash', [self.nodePath]) def MenuCommand(self, command): - messenger.send('SGENodePath_' + command, [self.nodePath]) + messenger.send('SGE_' + command, [self.nodePath]) def explore(nodePath = render): diff --git a/direct/src/tkwidgets/Tree.py b/direct/src/tkwidgets/Tree.py index 89f0ef989e..1d43151020 100644 --- a/direct/src/tkwidgets/Tree.py +++ b/direct/src/tkwidgets/Tree.py @@ -45,16 +45,21 @@ class TreeNode: self.menuVar.set(0) self._popupMenu = None if self.menuList: + if self.menuList[-1] == 'Separator': + self.menuList = self.menuList[:-1] self._popupMenu = Menu(self.canvas, tearoff = 0) for i in range(len(self.menuList)): item = self.menuList[i] - self._popupMenu.add_radiobutton( - label = item, - variable = self.menuVar, - value = i, - indicatoron = 0, - command = self.popupMenuCommand) - + if item == 'Separator': + self._popupMenu.add_separator() + else: + self._popupMenu.add_radiobutton( + label = item, + variable = self.menuVar, + value = i, + indicatoron = 0, + command = self.popupMenuCommand) + def destroy(self): for key in self.kidKeys: c = self.children[key] @@ -120,8 +125,11 @@ class TreeNode: return "break" def popupMenuCommand(self): - self.item.MenuCommand(self.menuList[self.menuVar.get()]) - self.parent.update() + command = self.menuList[self.menuVar.get()] + self.item.MenuCommand(command) + if self.parent and (command != 'Update Explorer'): + # Update parent to try to keep explorer up to date + self.parent.update() def expand(self, event=None): if not self.item.IsExpandable():