diff --git a/direct/src/directtools/DirectCameraControl.py b/direct/src/directtools/DirectCameraControl.py index 126fb5ed8b..7167c6f7dc 100644 --- a/direct/src/directtools/DirectCameraControl.py +++ b/direct/src/directtools/DirectCameraControl.py @@ -15,7 +15,7 @@ class DirectCameraControl(PandaObject): self.coaMarker = loader.loadModel('models/misc/sphere') self.coaMarker.setName('DirectCameraCOAMarker') self.coaMarker.setColor(1,0,0) - self.coaMarker.setPos(0,0,0) + self.coaMarker.setPos(0,100,0) useDirectRenderStyle(self.coaMarker) self.coaMarkerPos = Point3(0) self.camManipRef = direct.group.attachNewNode('camManipRef') @@ -56,27 +56,15 @@ class DirectCameraControl(PandaObject): self.coaMarker.hide() # Check for a hit point based on # current mouse position + # Allow intersection with unpickable objects # And then spawn task to determine mouse mode - numEntries = direct.iRay.pickGeom( - render,direct.dr.mouseX,direct.dr.mouseY) - # Then filter out hidden nodes from entry list - indexList = [] - for i in range(0,numEntries): - entry = direct.iRay.cq.getEntry(i) - node = entry.getIntoNode() - if node.isHidden(): - pass - else: - # Not one of the widgets, use it - indexList.append(i) + node, hitPt, hitPtDist = direct.iRay.pickGeom( + fIntersectUnpickable = 1) coa = Point3(0) - if(indexList): - # Grab first point (it should be the closest) - minPt = indexList[0] - # Find hit point in camera's space - hitPt = direct.iRay.camToHitPt(minPt) - coa.set(hitPt[0],hitPt[1],hitPt[2]) - coaDist = Vec3(coa - ZERO_POINT).length() + if node: + # Set center of action + coa.assign(hitPt) + coaDist = hitPtDist # Handle case of bad coa point (too close or too far) if ((coaDist < (1.1 * direct.dr.near)) | (coaDist > direct.dr.far)): diff --git a/direct/src/directtools/DirectManipulation.py b/direct/src/directtools/DirectManipulation.py index 8742c29d21..28325f2db6 100644 --- a/direct/src/directtools/DirectManipulation.py +++ b/direct/src/directtools/DirectManipulation.py @@ -2,8 +2,6 @@ from PandaObject import * from DirectGeometry import * MANIPULATION_MOVE_DELAY = 0.65 -UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible', - 'GridBack'] class DirectManipulationControl(PandaObject): def __init__(self): @@ -24,7 +22,6 @@ class DirectManipulationControl(PandaObject): self.fWidgetTop = 0 self.fFreeManip = 1 self.fScaling = 0 - self.unpickable = UNPICKABLE self.mode = None self.actionEvents = [ ['handleMouse1', self.manipulationStart], @@ -35,26 +32,19 @@ class DirectManipulationControl(PandaObject): [',', self.objectHandles.multiplyScalingFactorBy, 0.5], ['<', self.objectHandles.multiplyScalingFactorBy, 0.5], ['F', self.objectHandles.growToFit], + ['p', self.plantSelectedNodePath], ] def manipulationStart(self): # Start out in select mode self.mode = 'select' # Check for a widget hit point - numEntries = direct.iRay.pickWidget( - render,direct.dr.mouseX,direct.dr.mouseY) + node, hitPt, hitPtDist = direct.iRay.pickWidget() # Did we hit a widget? - if(numEntries): + if node: # Yes! - # Entry 0 is the closest hit point if multiple hits - minPt = 0 - # Find hit point in camera's space - self.hitPt = direct.iRay.camToHitPt(minPt) - self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length() - # Get the associated collision queue object - entry = direct.iRay.cq.getEntry(minPt) - # Extract the node - node = entry.getIntoNode() + self.hitPt.assign(hitPt) + self.hitPtDist = hitPtDist # Constraint determined by nodes name self.constraint = node.getName() else: @@ -97,32 +87,11 @@ class DirectManipulationControl(PandaObject): # depending on flag..... if self.mode == 'select': # Check for object under mouse - numEntries = direct.iRay.pickGeom( - render,direct.dr.mouseX,direct.dr.mouseY) - # Pick out the closest object that isn't a widget - index = -1 - for i in range(0,numEntries): - entry = direct.iRay.cq.getEntry(i) - node = entry.getIntoNode() - if node.isHidden(): - pass - # Is it a named node?, If so, see if it has a name - elif issubclass(node.__class__, NamedNode): - name = node.getName() - if name in self.unpickable: - pass - else: - index = i - break - else: - # Not hidden and not one of the widgets, use it - index = i - # Did we hit an object? - if(index >= 0): - # Yes! - # Find hit point in camera's space - self.hitPt = direct.iRay.camToHitPt(index) - self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length() + node, hitPt, hitPtDist = direct.iRay.pickGeom() + if node: + # Record hit point information + self.hitPt.assign(hitPt) + self.hitPtDist = hitPtDist # Find the node path from the node found above nodePath = render.findPathDownTo(node) # Select it @@ -479,15 +448,32 @@ class DirectManipulationControl(PandaObject): self.initScaleMag) ) direct.widget.setScale(currScale) - + + ## Utility functions ## + def plantSelectedNodePath(self): + """ Move selected object to intersection point of cursor on scene """ + # Check for intersection + node, hitPt, hitPtDist = direct.iRay.pickGeom( + fIntersectUnpickable = 1) + # MRM: Need to handle moving COA + if (node != None) & (direct.selected.last != None): + # Record undo point + direct.pushUndo(direct.selected) + # Record wrt matrix + direct.selected.getWrtAll() + # Move selected + direct.widget.setPos(direct.camera, hitPt) + # Move all the selected objects with widget + # Move the objects with the widget + direct.selected.moveWrtWidgetAll() + # Let everyone know that something was moved + messenger.send('manipulateObjectCleanup') class ObjectHandles(NodePath,PandaObject): def __init__(self): # Initialize the superclass NodePath.__init__(self) - # Starts off deactivated - self.fActive = 0 # Load up object handles model and assign it to self self.assign(loader.loadModel('models/misc/objectHandles')) self.node().setName('objectHandles') @@ -540,6 +526,10 @@ class ObjectHandles(NodePath,PandaObject): self.createGuideLines() self.hideGuides() + # Start with widget handles hidden + self.fActive = 1 + self.toggleWidget() + # Make sure object handles are never lit or drawn in wireframe useDirectRenderStyle(self) @@ -551,10 +541,10 @@ class ObjectHandles(NodePath,PandaObject): def toggleWidget(self): if self.fActive: - self.reparentTo(hidden) + self.scalingNode.reparentTo(hidden) self.fActive = 0 else: - self.reparentTo(direct.group) + self.scalingNode.reparentTo(self) self.fActive = 1 def showWidgetIfActive(self): diff --git a/direct/src/directtools/DirectSelection.py b/direct/src/directtools/DirectSelection.py index 352c57edea..53b3acfc4c 100644 --- a/direct/src/directtools/DirectSelection.py +++ b/direct/src/directtools/DirectSelection.py @@ -2,6 +2,9 @@ from PandaObject import * from DirectGeometry import * from DirectSelection import * +UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible', + 'GridBack'] + # 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 @@ -394,14 +397,70 @@ class SelectionRay: self.ct = CollisionTraverser( RenderRelation.getClassType() ) # Let the traverser know about the queue and the collision node self.ct.addCollider(self.rayCollisionNode, self.cq ) + # List of objects that can't be selected + self.unpickable = UNPICKABLE - def pickGeom(self, targetNodePath, mouseX, mouseY): + def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0): self.collideWithGeom() - return self.pick(targetNodePath, mouseX, mouseY) + numEntries = self.pick(targetNodePath, + direct.dr.mouseX, + direct.dr.mouseY) + # Init index + index = -1 + # Pick out the closest object that isn't a widget + for i in range(0,numEntries): + entry = direct.iRay.cq.getEntry(i) + node = entry.getIntoNode() + # Don't pick hidden nodes + if node.isHidden(): + pass + # Can pick unpickable, use the first visible node + elif fIntersectUnpickable: + index = i + break + # Is it a named node?, If so, see if it has a name + elif issubclass(node.__class__, NamedNode): + name = node.getName() + if name in self.unpickable: + pass + else: + index = i + break + # Not hidden and not one of the widgets, use it + else: + index = i + break + # Did we hit an object? + if(index >= 0): + # Yes! + # Find hit point in camera's space + hitPt = direct.iRay.camToHitPt(index) + hitPtDist = Vec3(hitPt - ZERO_POINT).length() + return (node, hitPt, hitPtDist) + else: + return (None, ZERO_POINT, 0) - def pickWidget(self, targetNodePath, mouseX, mouseY): + def pickWidget(self, targetNodePath = render): self.collideWithWidget() - return self.pick(targetNodePath, mouseX, mouseY) + numEntries = self.pick(targetNodePath, + direct.dr.mouseX, + direct.dr.mouseY) + # Did we hit a widget? + if numEntries: + # Yes! + # Entry 0 is the closest hit point if multiple hits + minPt = 0 + # Find hit point in camera's space + hitPt = direct.iRay.camToHitPt(minPt) + hitPtDist = Vec3(hitPt).length() + # Get the associated collision queue object + entry = direct.iRay.cq.getEntry(minPt) + # Extract the node + node = entry.getIntoNode() + # Return info + return (node, hitPt, hitPtDist) + else: + return (None, ZERO_POINT, 0) def pick(self, targetNodePath, mouseX, mouseY): # Determine ray direction based upon the mouse coordinates diff --git a/direct/src/directtools/DirectSession.py b/direct/src/directtools/DirectSession.py index a709552a2f..5787783e77 100644 --- a/direct/src/directtools/DirectSession.py +++ b/direct/src/directtools/DirectSession.py @@ -79,9 +79,8 @@ class DirectSession(PandaObject): ['SGENodePath_Delete', self.removeNodePath], ] self.keyEvents = ['left', 'right', 'up', 'down', - 'escape', 'space', 'delete', + 'escape', 'delete', 'control', 'control-up', 'shift', 'shift-up', 'alt', 'alt-up', - 'control', 'control-up', 'page_up', 'page_down', 'tab', '[', '{', ']', '}', 'b', 'c', 'f', 'l', 's', 't', 'v', 'w'] @@ -213,8 +212,8 @@ class DirectSession(PandaObject): elif (input == ']') | (input == '}'): self.redo() - def select(self, nodePath, fMultiselect = 0, fResetAncestry = 1): - dnp = self.selected.select(nodePath, fMultiselect) + def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1): + dnp = self.selected.select(nodePath, fMultiSelect) if dnp: messenger.send('preSelectNodePath', [dnp]) if fResetAncestry: @@ -465,6 +464,7 @@ class DirectSession(PandaObject): # UTILITY FUNCTIONS def useObjectHandles(self): self.widget = self.manipulationControl.objectHandles + self.widget.reparentTo(direct.group) def hideReadout(self): self.readout.reparentTo(hidden) diff --git a/direct/src/ffi/FFIRename.py b/direct/src/ffi/FFIRename.py index 14ba4e0330..850ebb5b71 100644 --- a/direct/src/ffi/FFIRename.py +++ b/direct/src/ffi/FFIRename.py @@ -60,6 +60,7 @@ classRenameDictionary = { 'LVecBase2f' : 'VBase2', 'LVector2f' : 'Vec2', 'LPoint2f' : 'Point2', + 'LQuaternionf' : 'Quat', 'LMatrix4d' : 'Mat4D', 'LMatrix3d' : 'Mat3D', 'LVecBase4d' : 'VBase4D', @@ -71,6 +72,7 @@ classRenameDictionary = { 'LVecBase2d' : 'VBase2D', 'LVector2d' : 'Vec2D', 'LPoint2d' : 'Point2D', + 'LQuaterniond' : 'QuatD', 'Plane' : 'PlaneBase', 'Planef' : 'Plane', 'Planed' : 'PlaneD', diff --git a/direct/src/tkpanels/ParticlePanel.py b/direct/src/tkpanels/ParticlePanel.py index 0d960a3688..d5643443f1 100644 --- a/direct/src/tkpanels/ParticlePanel.py +++ b/direct/src/tkpanels/ParticlePanel.py @@ -59,23 +59,23 @@ class ParticlePanel(AppShell): ## SYSTEM PAGE ## # Create system floaters systemFloaterDefs = ( - ('System Pool size', + ('System Pool Size', 'Size of particle pool', self.setSystemPoolSize, 1.0, 1.0), - ('System Birth rate', + ('System Birth Rate', 'Seconds between particle births', self.setSystemBirthRate, 0.0, None), - ('System Litter size', + ('System Litter Size', 'Number of particle created at each birth', self.setSystemLitterSize, 1.0, 1.0), - ('System Litter spread', + ('System Litter Spread', 'Variation in litter size', self.setSystemLitterSpread, 0.0, 1.0), - ('System lifespan', + ('System Lifespan', 'Age in seconds at which system should die', self.setSystemLifespan, 0.0, None) @@ -83,17 +83,17 @@ class ParticlePanel(AppShell): self.createFloaters(systemPage, systemFloaterDefs) # Checkboxes self.systemLocalVelocity = self.createCheckbutton( - systemPage, 'Local velocity', + systemPage, 'System Local Velocity', self.toggleSystemLocalVelocity, 0) self.systemGrowsOlder = self.createCheckbutton( - systemPage, 'System grows older', + systemPage, 'System Grows Older', self.toggleSystemGrowsOlder, 0) # Vector widgets - pos = self.createVector3Entry(systemPage, 'Pos', + pos = self.createVector3Entry(systemPage, 'System Pos', 'Particle system position', command = self.setSystemPos) pos.addMenuItem('Popup Placer Panel', Placer.Placer) - hpr = self.createVector3Entry(systemPage, 'Hpr', + hpr = self.createVector3Entry(systemPage, 'System Hpr', 'Particle system orientation', fGroup_labels = ('H', 'P', 'R'), command = self.setSystemHpr) @@ -107,27 +107,27 @@ class ParticlePanel(AppShell): ('Point', 'Z Spin', 'Oriented'), self.selectFactoryType) factoryWidgets = ( - ('Life span', + ('Factory Life Span', 'Average lifespan in seconds', self.setFactoryLifeSpan, 0.0, None), - ('Life span spread', + ('Factory Life Span Spread', 'Variation in lifespan', self.setFactoryLifeSpanSpread, 0.0, None), - ('Mass', + ('Factory Mass', 'Average particle mass', self.setFactoryParticleMass, 0.0, None), - ('Mass spread', + ('Factory Mass Spread', 'Variation in particle mass', self.setFactoryParticleMassSpread, 0.0, None), - ('Terminal velocity', + ('Factory Terminal Velocity', 'Average particle terminal velocity', self.setFactoryTerminalVelocity, 0.0, None), - ('Terminal vel. spread', + ('Factory Terminal Vel. Spread', 'Variation in terminal velocity', self.setFactoryTerminalVelocitySpread, 0.0, None)) @@ -138,13 +138,13 @@ class ParticlePanel(AppShell): factoryPointPage = self.factoryNotebook.add('Point') # Z spin page # zSpinPage = self.factoryNotebook.add('Z Spin') - self.createAngleDial(zSpinPage, 'Initial angle', + self.createAngleDial(zSpinPage, 'Z Spin Initial Angle', 'Starting angle in degrees', command = self.setFactoryZSpinInitialAngle) - self.createAngleDial(zSpinPage, 'Final angle', + self.createAngleDial(zSpinPage, 'Z Spin Final Angle', 'Final angle in degrees', command = self.setFactoryZSpinFinalAngle) - self.createAngleDial(zSpinPage, 'Angle spread', + self.createAngleDial(zSpinPage, 'Z Spin Angle Spread', 'Spread of the final angle', command = self.setFactoryZSpinAngleSpread) # Oriented page # @@ -164,18 +164,19 @@ class ParticlePanel(AppShell): self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None) # Box page # boxPage = self.emitterNotebook.add('Box') - self.createVector3Entry(boxPage, 'Point 1', - 'Point defining emitter box', + self.createVector3Entry(boxPage, 'Box Emitter Min', + 'Min point defining emitter box', command = self.setEmitterBoxPoint1) - self.createVector3Entry(boxPage, 'Point 2', - 'Point defining emitter box', + self.createVector3Entry(boxPage, 'Box Emitter Max', + 'Max point defining emitter box', command = self.setEmitterBoxPoint2, initialValue = (1.0, 1.0, 1.0)) self.createVector3Entry(boxPage, 'Velocity vector', - 'Initial particle velocity vector', + 'Initial particle velocity vector', command = self.setEmitterBoxVelocityVector) # Disc page # discPage = self.emitterNotebook.add('Disc') + self.emitter self.createFloater(discPage, 'Radius', 'Radius of disc', command = self.setEmitterDiscRadius) self.createAngleDial(discPage, 'Inner angle', @@ -195,23 +196,24 @@ class ParticlePanel(AppShell): self.toggleEmitterDiscCubicLerping, 0) # Line page # linePage = self.emitterNotebook.add('Line') - self.createVector3Entry(linePage, 'Point 1', - 'Point defining emitter line', + self.createVector3Entry(linePage, 'Line Emitter Min', + 'Min point defining emitter line', command = self.setEmitterLinePoint1) - self.createVector3Entry(linePage, 'Point 2', - 'Point defining emitter line', + self.createVector3Entry(linePage, 'Line Emitter Max', + 'Max point defining emitter line', command = self.setEmitterLinePoint2, initialValue = (1.0, 0.0, 0.0)) - self.createVector3Entry(linePage, 'Velocity Vector', + self.createVector3Entry(linePage, 'Line Emitter Velocity', 'Initial particle velocity vector', command = self.setEmitterLineVelocityVector, initialValue = (0.0, 0.0, 1.0)) # Point page # emitterPointPage = self.emitterNotebook.add('Point') - self.createVector3Entry(emitterPointPage, 'Position', + self.createVector3Entry(emitterPointPage, 'Point Emitter Position', 'Position of emitter point', command = self.setEmitterPointPosition) - self.createVector3Entry(emitterPointPage, 'Velocity vector', + self.createVector3Entry(emitterPointPage, + 'Point Emitter Velocity', 'Initial particle velocity vector', command = self.setEmitterPointVelocityVector, initialValue = (0.0, 0.0, 1.0)) @@ -374,11 +376,12 @@ class ParticlePanel(AppShell): def createCheckbutton(self, parent, text, command, initialState): bool = BooleanVar() bool.set(initialState) - cb = Checkbutton(parent, text = text, anchor = W, + widget = Checkbutton(parent, text = text, anchor = W, variable = bool) # Do this after the widget so command isn't called on creation - cb.command = command - cb.pack(fill = X) + widget['command'] = command + widget.pack(fill = X) + self.widgetDict['text'] = widget return bool def createFloaters(self, parent, widgetDefinitions): @@ -412,6 +415,7 @@ class ParticlePanel(AppShell): widget['command'] = command widget.pack(fill = X) self.bind(widget, balloonHelp) + self.widgetDict['text'] = widget return widget def createVector3Entry(self, parent, text, balloonHelp, @@ -423,6 +427,7 @@ class ParticlePanel(AppShell): widget['command'] = command widget.pack(fill = X) self.bind(widget, balloonHelp) + self.widgetDict['text'] = widget return widget def createColorEntry(self, parent, text, balloonHelp, @@ -434,6 +439,7 @@ class ParticlePanel(AppShell): widget['command'] = command widget.pack(fill = X) self.bind(widget, balloonHelp) + self.widgetDict['text'] = widget return widget def createOptionMenu(self, parent, text, balloonHelp, items, command): @@ -447,6 +453,7 @@ class ParticlePanel(AppShell): widget['command'] = command widget.pack(fill = X) self.bind(widget.component('menubutton'), balloonHelp) + self.widgetDict['text'] = widget return optionVar ### PARTICLE SYSTEM COMMANDS ### @@ -500,6 +507,39 @@ class ParticlePanel(AppShell): def selectEmitterType(self, type): self.emitterNotebook.selectpage(type) self.particles.setEmitter(type) + self.updateEmitterWidgets() + + def updateEmitterWidgets(self): + emitter = self.particles.emitter + if isinstance(emitter, BoxEmitter): + min = emitter.getMinBound() + self.emitterBoxPoint1VectorEntry.set( + [min[0], min[1], min[2]]) + max = emitter.getMaxBound() + self.emitterBoxPoint2VectorEntry.set( + [max[0], max[1], max[2]]) + elif isinstance(emitter, DiscEmitter): + radius = emitter.getRadius() + cubicLerping = emitter.getCubicLerping() + innerAngle = emitter.getInnerAngle() + getInnerMagnitude + getOuterAngle + getOuterMagnitude + elif isinstance(emitter, LineEmitter): + pass + elif isinstance(emitter, PointEmitter): + pass + elif isinstance(emitter, RectangleEmitter): + pass + elif isinstance(emitter, RingEmitter): + pass + elif isinstance(emitter, SphereVolumeEmitter): + pass + elif isinstance(emitter, SphereSurfaceEmitter): + pass + elif isinstance(emitter, TangentRingEmitter): + pass + # Box # def setEmitterBoxPoint1(self, point): self.particles.emitter.setMinBound(Point3(point[0], diff --git a/direct/src/tkpanels/Placer.py b/direct/src/tkpanels/Placer.py index b507c452c6..eda1a12ae4 100644 --- a/direct/src/tkpanels/Placer.py +++ b/direct/src/tkpanels/Placer.py @@ -64,6 +64,7 @@ class Placer(AppShell): self.initPos = Vec3(0) self.initHpr = Vec3(0) self.initScale = Vec3(1) + self.deltaHpr = Vec3(0) # Offset for orbital mode self.posOffset = Vec3(0) @@ -450,7 +451,7 @@ class Placer(AppShell): else: if name == 'widget': # Record relationship between selected nodes and widget - direct.selected.getWrtAll() + direct.selected.getWrtAll() # Update active node path self.setActiveNodePath(nodePath) @@ -459,10 +460,19 @@ class Placer(AppShell): if self['nodePath']: self.nodePathMenuEntry.configure( background = self.nodePathMenuBG) + # Check to see if node path and ref node path are the same + if ((self.refCS != None) & + (self.refCS.id() == self['nodePath'].id())): + # Yes they are, use temp CS as ref + # This calls updatePlacer + self.setReferenceNodePath(self.tempCS) + # update listbox accordingly + self.refNodePathMenu.selectitem('self') + else: + # Record initial value and initialize the widgets + self.updatePlacer() # Record initial position self.updateResetValues(self['nodePath']) - # Record initial value and initialize the widgets - self.updatePlacer() else: # Flash entry self.nodePathMenuEntry.configure(background = 'Pink') @@ -494,7 +504,12 @@ class Placer(AppShell): # Clear bogus entry from listbox listbox = self.refNodePathMenu.component('scrolledlist') listbox.setlist(self.refNodePathNames) - # Update ref node path accordingly + # Check to see if node path and ref node path are the same + if (nodePath != None) & (nodePath.id() == self['nodePath'].id()): + # Yes they are, use temp CS and update listbox accordingly + nodePath = self.tempCS + self.refNodePathMenu.selectitem('self') + # Update ref node path self.setReferenceNodePath(nodePath) def setReferenceNodePath(self, nodePath): @@ -594,6 +609,8 @@ class Placer(AppShell): taskMgr.removeTasksNamed('followSelectedNodePath') # Record relationship between selected nodes and widget direct.selected.getWrtAll() + # Record initial state + self.deltaHpr = self['nodePath'].getHpr(self.refCS) # Update placer to reflect new state self.updatePlacer() @@ -609,7 +626,6 @@ class Placer(AppShell): def xformRelative(self, value, axis): nodePath = self['nodePath'] - if (nodePath != None) & (self.refCS != None): if axis == 'x': nodePath.setX(self.refCS, value) @@ -617,12 +633,15 @@ class Placer(AppShell): nodePath.setY(self.refCS, value) elif axis == 'z': nodePath.setZ(self.refCS, value) - elif axis == 'h': - nodePath.setH(self.refCS, value) - elif axis == 'p': - nodePath.setP(self.refCS, value) - elif axis == 'r': - nodePath.setR(self.refCS, value) + else: + if axis == 'h': + self.deltaHpr.setX(value) + elif axis == 'p': + self.deltaHpr.setY(value) + elif axis == 'r': + self.deltaHpr.setZ(value) + # Put node path at new hpr + nodePath.setHpr(self.refCS, self.deltaHpr) def xformOrbit(self, value, axis): nodePath = self['nodePath'] diff --git a/direct/src/tkwidgets/VectorWidgets.py b/direct/src/tkwidgets/VectorWidgets.py index 4f3c65aac8..1f87457daa 100644 --- a/direct/src/tkwidgets/VectorWidgets.py +++ b/direct/src/tkwidgets/VectorWidgets.py @@ -163,11 +163,11 @@ class VectorEntry(Pmw.MegaWidget): def getAt(self,index): return self._value[index] - def set(self, value): + def set(self, value, fCommand = 0): for i in range(self['dim']): self._value[i] = value[i] self.variableList[i].set(self.entryFormat % value[i]) - self.action() + self.action(fCommand) def setAt(self, index, value): self.variableList[index].set(self.entryFormat % value) @@ -207,9 +207,9 @@ class VectorEntry(Pmw.MegaWidget): if self._floaters: self._floaters.set(self._value, 0) - def action(self): + def action(self, fCommand = 0): self._refreshFloaters() - if self['command']: + if fCommand & (self['command'] != None): self['command'](self._value) def reset(self):