diff --git a/direct/src/directutil/DirectCameraControl.py b/direct/src/directutil/DirectCameraControl.py index a7b7d318d7..80820e66d8 100644 --- a/direct/src/directutil/DirectCameraControl.py +++ b/direct/src/directutil/DirectCameraControl.py @@ -59,8 +59,6 @@ class DirectCameraControl(PandaObject): # And then spawn task to determine mouse mode numEntries = direct.iRay.pickGeom( render,direct.dr.mouseX,direct.dr.mouseY) - # Sort intersection points - direct.iRay.cq.sortEntries() # Then filter out hidden nodes from entry list indexList = [] for i in range(0,numEntries): @@ -79,19 +77,6 @@ class DirectCameraControl(PandaObject): hitPt = direct.iRay.camToHitPt(minPt) coa.set(hitPt[0],hitPt[1],hitPt[2]) coaDist = Vec3(coa - ZERO_POINT).length() - """ - # Check other intersection points, sorting them - # TBD: Use TBS C++ function to do this - if len(indexList) > 1: - for i in range(1,len(indexList)): - entryNum = indexList[i] - hitPt = direct.iRay.camToHitPt(entryNum) - dist = Vec3(hitPt - ZERO_POINT).length() - if (dist < coaDist): - coaDist = dist - coa.set(hitPt[0],hitPt[1],hitPt[2]) - minPt = i - """ # Handle case of bad coa point (too close or too far) if ((coaDist < (1.1 * direct.dr.near)) | (coaDist > direct.dr.far)): @@ -167,10 +152,10 @@ class DirectCameraControl(PandaObject): taskMgr.spawnMethodNamed(self.HPPanTask, 'manipulateCamera') def XZTranslateOrHPanYZoomTask(self, state): - if direct.fShift: - return self.XZTranslateTask(state) - else: + if direct.fShift | direct.fControl: return self.HPanYZoomTask(state) + else: + return self.XZTranslateTask(state) def XZTranslateOrHPPanTask(self, state): if direct.fShift: @@ -194,14 +179,14 @@ class DirectCameraControl(PandaObject): return Task.cont def HPanYZoomTask(self,state): - if direct.fControl: - moveDir = Vec3(Y_AXIS) - else: + if direct.fShift: moveDir = Vec3(self.coaMarker.getPos(direct.camera)) # If marker is behind camera invert vector if moveDir[1] < 0.0: moveDir.assign(moveDir * -1) moveDir.normalize() + else: + moveDir = Vec3(Y_AXIS) moveDir.assign(moveDir * (-2.0 * direct.dr.mouseDeltaY * state.zoomSF)) direct.camera.setPosHpr(direct.camera, diff --git a/direct/src/directutil/DirectGeometry.py b/direct/src/directutil/DirectGeometry.py index 41ef5706a4..cc9bb6d394 100644 --- a/direct/src/directutil/DirectGeometry.py +++ b/direct/src/directutil/DirectGeometry.py @@ -126,6 +126,28 @@ def getCrankAngle(center): y = direct.dr.mouseY - center[2] return (180 + rad2Deg(math.atan2(y,x))) +def relHpr(nodePath, base, h, p, r): + # Compute nodePath2newNodePath relative to base coordinate system + # nodePath2base + mNodePath2Base = nodePath.getMat(base) + # delta scale, orientation, and position matrix + mBase2NewBase = Mat4() + composeMatrix(mBase2NewBase, UNIT_VEC, VBase3(h,p,r), ZERO_VEC, + CSDefault) + # base2nodePath + mBase2NodePath = base.getMat(nodePath) + # nodePath2 Parent + mNodePath2Parent = nodePath.getMat() + # Compose the result + resultMat = mNodePath2Base * mBase2NewBase + resultMat = resultMat * mBase2NodePath + resultMat = resultMat * mNodePath2Parent + # Extract and apply the hpr + hpr = Vec3(0) + decomposeMatrix(resultMat, VBase3(), hpr, VBase3(), + CSDefault) + nodePath.setHpr(hpr) + # Set direct drawing style for an object # Never light object or draw in wireframe def useDirectRenderStyle(nodePath): diff --git a/direct/src/directutil/DirectManipulation.py b/direct/src/directutil/DirectManipulation.py index 122fcafcc9..8742c29d21 100644 --- a/direct/src/directutil/DirectManipulation.py +++ b/direct/src/directutil/DirectManipulation.py @@ -269,9 +269,9 @@ class DirectManipulationControl(PandaObject): # Mouse starte in central region, xlate # Mode depends on shift key if direct.fShift: - self.xlateCamXZ(state) - else: self.xlateCamXY(state) + else: + self.xlateCamXZ(state) if self.fSetCoa: # Update coa based on current widget position direct.selected.last.mCoa2Dnp.assign( @@ -440,8 +440,8 @@ class DirectManipulationControl(PandaObject): deltaX = direct.dr.mouseDeltaX deltaY = direct.dr.mouseDeltaY # Mouse motion edge to edge of display region results in one full turn - self.relHpr(direct.camera, deltaX * tumbleRate, - -deltaY * tumbleRate, 0) + relHpr(direct.widget, direct.camera, deltaX * tumbleRate, + -deltaY * tumbleRate, 0) def rotateAboutViewVector(self, state): # Reset init flag in case we switch to another mode @@ -453,25 +453,7 @@ class DirectManipulationControl(PandaObject): deltaAngle = angle - state.lastAngle state.lastAngle = angle # Mouse motion edge to edge of display region results in one full turn - self.relHpr(direct.camera, 0, 0, deltaAngle) - - def relHpr(self, base, h, p, r): - # Compute widget2newWidget relative to base coordinate system - mWidget2Base = direct.widget.getMat(base) - mBase2NewBase = Mat4() - composeMatrix(mBase2NewBase, UNIT_VEC, VBase3(h,p,r), ZERO_VEC, - CSDefault) - mBase2Widget = base.getMat(direct.widget) - mWidget2Parent = direct.widget.getMat() - # Compose the result - resultMat = mWidget2Base * mBase2NewBase - resultMat = resultMat * mBase2Widget - resultMat = resultMat * mWidget2Parent - # Extract and apply the hpr - hpr = Vec3(0) - decomposeMatrix(resultMat, VBase3(), hpr, VBase3(), - CSDefault) - direct.widget.setHpr(hpr) + relHpr(direct.widget, direct.camera, 0, 0, deltaAngle) def scale3D(self, state): # Scale the selected node based upon up down mouse motion diff --git a/direct/src/tkpanels/Placer.py b/direct/src/tkpanels/Placer.py index 56536ed44e..7a3d30b51e 100644 --- a/direct/src/tkpanels/Placer.py +++ b/direct/src/tkpanels/Placer.py @@ -1,24 +1,31 @@ -"DIRECT Nine DoF Placer demonstration" +""" DIRECT Nine DoF Manipulation Panel """ # Import Tkinter, Pmw, and the dial code from this directory tree. from PandaObject import * from Tkinter import * +from AppShell import * +from DirectGeometry import relHpr import Pmw import Dial import Floater """ TODO: -Orbital mode Task to monitor pose """ ZERO_VEC = Vec3(0) UNIT_VEC = Vec3(1) -class Placer(Pmw.MegaToplevel, PandaObject): - def __init__(self, parent = None, **kw): +class Placer(AppShell): + # Override class variables here + appname = 'Placer Panel' + frameWidth = 625 + frameHeight = 290 + usecommandarea = 1 + usestatusarea = 0 + def __init__(self, parent = None, **kw): INITOPT = Pmw.INITOPT optiondefs = ( ('title', 'Placer Panel', None), @@ -26,29 +33,32 @@ class Placer(Pmw.MegaToplevel, PandaObject): ) self.defineoptions(kw, optiondefs) - # Initialize the superclass - Pmw.MegaToplevel.__init__(self, parent) + # Call superclass initialization function + AppShell.__init__(self) + + self.initialiseoptions(Placer) + def appInit(self): # Initialize state self.tempCS = direct.group.attachNewNode('placerTempCS') self.orbitFromCS = direct.group.attachNewNode( 'placerOrbitFromCS') self.orbitToCS = direct.group.attachNewNode('placerOrbitToCS') self.refCS = self.tempCS - self.undoList = [] - self.redoList = [] # Dictionary keeping track of all node paths manipulated so far self.nodePathDict = {} self.nodePathDict['camera'] = direct.camera - self.nodePathNames = ['selected', 'camera'] + self.nodePathDict['widget'] = direct.widget + self.nodePathNames = ['camera', 'widget', 'selected'] self.refNodePathDict = {} self.refNodePathDict['parent'] = self['nodePath'].getParent() self.refNodePathDict['render'] = render self.refNodePathDict['camera'] = direct.camera + self.refNodePathDict['widget'] = direct.widget self.refNodePathNames = ['self', 'parent', 'render', - 'camera', 'selected', 'coa'] + 'camera', 'widget', 'selected'] # Initial state self.initPos = Vec3(0) @@ -71,46 +81,36 @@ class Placer(Pmw.MegaToplevel, PandaObject): # Init movement mode self.movementMode = 'Relative To:' - # Create panel - # Handle to the toplevels hull - hull = self.component('hull') - - menuFrame = Frame(hull, relief = GROOVE, bd = 2) - menuFrame.pack(fill = X, expand = 1) - - balloon = self.balloon = Pmw.Balloon() - # Start with balloon help disabled - self.balloon.configure(state = 'none') - - menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon) - menuBar.pack(side = LEFT, expand = 1, fill = X) - menuBar.addmenu('Placer', 'Placer Panel Operations') - menuBar.addmenuitem('Placer', 'command', + def createInterface(self): + # The interior of the toplevel panel + interior = self.interior() + # Add placer commands to menubar + self.menuBar.addmenu('Placer', 'Placer Panel Operations') + self.menuBar.addmenuitem('Placer', 'command', 'Zero Node Path', label = 'Zero All', command = self.zeroAll) - menuBar.addmenuitem('Placer', 'command', + self.menuBar.addmenuitem('Placer', 'command', 'Reset Node Path', label = 'Reset All', command = self.resetAll) - menuBar.addmenuitem('Placer', 'command', + self.menuBar.addmenuitem('Placer', 'command', 'Print Node Path Info', label = 'Print Info', command = self.printNodePathInfo) - menuBar.addmenuitem('Placer', 'command', - 'Exit Placer Panel', - label = 'Exit', - command = self.destroy) - - menuBar.addmenu('Help', 'Placer Panel Help Operations') - self.toggleBalloonVar = IntVar() - self.toggleBalloonVar.set(0) - menuBar.addmenuitem('Help', 'checkbutton', - 'Toggle balloon help', - label = 'Balloon Help', - variable = self.toggleBalloonVar, - command = self.toggleBalloon) - + self.menuBar.addmenuitem( + 'Placer', 'command', + 'Toggle widget visability', + label = 'Toggle Widget Vis', + command = direct.toggleWidgetVis) + self.menuBar.addmenuitem( + 'Placer', 'command', + 'Toggle widget manipulation mode', + label = 'Toggle Widget Mode', + command = direct.manipulationControl.toggleObjectHandlesMode) + + # Get a handle to the menu frame + menuFrame = self.menuFrame self.nodePathMenu = Pmw.ComboBox( menuFrame, labelpos = W, label_text = 'Node Path:', entry_width = 20, @@ -121,7 +121,8 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.nodePathMenu.component('entryfield_entry')) self.nodePathMenuBG = ( self.nodePathMenuEntry.configure('background')[3]) - self.nodePathMenu.pack(side = 'left', expand = 0) + self.nodePathMenu.pack(side = 'left', fill = 'x', expand = 1) + self.bind(self.nodePathMenu, 'Select node path to manipulate') modeMenu = Pmw.OptionMenu(menuFrame, items = ('Relative To:', @@ -130,6 +131,7 @@ class Placer(Pmw.MegaToplevel, PandaObject): command = self.setMovementMode, menubutton_width = 8) modeMenu.pack(side = 'left', expand = 0) + self.bind(modeMenu, 'Select manipulation mode') self.refNodePathMenu = Pmw.ComboBox( menuFrame, entry_width = 16, @@ -138,19 +140,29 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.refNodePathMenu.selectitem('self') self.refNodePathMenuEntry = ( self.refNodePathMenu.component('entryfield_entry')) - self.refNodePathMenu.pack(side = 'left', expand = 0) + self.refNodePathMenu.pack(side = 'left', fill = 'x', expand = 1) + self.bind(self.refNodePathMenu, 'Select relative node path') self.undoButton = Button(menuFrame, text = 'Undo', - state = 'disabled', command = direct.undo) + if direct.undoList: + self.undoButton['state'] = 'normal' + else: + self.undoButton['state'] = 'disabled' self.undoButton.pack(side = 'left', expand = 0) + self.bind(self.undoButton, 'Undo last operation') + self.redoButton = Button(menuFrame, text = 'Redo', - state = 'disabled', command = direct.redo) + if direct.redoList: + self.redoButton['state'] = 'normal' + else: + self.redoButton['state'] = 'disabled' self.redoButton.pack(side = 'left', expand = 0) + self.bind(self.redoButton, 'Redo last operation') # The master frame for the dials - dialFrame = Frame(hull) + dialFrame = Frame(interior) dialFrame.pack(fill = 'both', expand = 1) # Create and pack the Pos Controls @@ -159,8 +171,9 @@ class Placer(Pmw.MegaToplevel, PandaObject): tag_text = 'Position', tag_font=('MSSansSerif', 14, 'bold'), tag_activebackground = '#909090', - ring_relief = 'raised') + ring_relief = 'flat') posMenubutton = posGroup.component('tag') + self.bind(posMenubutton, 'Position menu operations') posMenu = Menu(posMenubutton) posMenu.add_command(label = 'Set to zero', command = self.zeroPos) posMenu.add_command(label = 'Reset initial', @@ -178,11 +191,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.posX['command'] = self.xform self.posX['commandData'] = ['x'] self.posX['callbackData'] = ['x'] - self.posX.onReturn = self.pushUndo + self.posX.onReturn = self.xformStart self.posX.onReturnRelease = self.xformStop self.posX.onPress = self.xformStart self.posX.onRelease = self.xformStop - self.posX.pack(expand=1,fill='x') + self.posX.pack(expand=1,fill='both') self.posY = self.createcomponent('posY', (), None, Floater.Floater, (posInterior,), @@ -192,11 +205,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.posY['command'] = self.xform self.posY['commandData'] = ['y'] self.posY['callbackData'] = ['y'] - self.posY.onReturn = self.pushUndo + self.posY.onReturn = self.xformStart self.posY.onReturnRelease = self.xformStop self.posY.onPress = self.xformStart self.posY.onRelease = self.xformStop - self.posY.pack(expand=1,fill='x') + self.posY.pack(expand=1,fill='both') self.posZ = self.createcomponent('posZ', (), None, Floater.Floater, (posInterior,), @@ -206,11 +219,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.posZ['command'] = self.xform self.posZ['commandData'] = ['z'] self.posZ['callbackData'] = ['z'] - self.posZ.onReturn = self.pushUndo + self.posZ.onReturn = self.xformStart self.posZ.onReturnRelease = self.xformStop self.posZ.onPress = self.xformStart self.posZ.onRelease = self.xformStop - self.posZ.pack(expand=1,fill='x') + self.posZ.pack(expand=1,fill='both') # Create and pack the Hpr Controls hprGroup = Pmw.Group(dialFrame, @@ -218,8 +231,9 @@ class Placer(Pmw.MegaToplevel, PandaObject): tag_text = 'Orientation', tag_font=('MSSansSerif', 14, 'bold'), tag_activebackground = '#909090', - ring_relief = 'raised') + ring_relief = 'flat') hprMenubutton = hprGroup.component('tag') + self.bind(hprMenubutton, 'Orientation menu operations') hprMenu = Menu(hprMenubutton) hprMenu.add_command(label = 'Set to zero', command = self.zeroHpr) hprMenu.add_command(label = 'Reset initial', command = self.resetHpr) @@ -237,11 +251,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.hprH['command'] = self.xform self.hprH['commandData'] = ['h'] self.hprH['callbackData'] = ['h'] - self.hprH.onReturn = self.pushUndo + self.hprH.onReturn = self.xformStart self.hprH.onReturnRelease = self.xformStop self.hprH.onPress = self.xformStart self.hprH.onRelease = self.xformStop - self.hprH.pack(expand=1,fill='x') + self.hprH.pack(expand=1,fill='both') self.hprP = self.createcomponent('hprP', (), None, Dial.Dial, (hprInterior,), @@ -252,11 +266,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.hprP['command'] = self.xform self.hprP['commandData'] = ['p'] self.hprP['callbackData'] = ['p'] - self.hprP.onReturn = self.pushUndo + self.hprP.onReturn = self.xformStart self.hprP.onReturnRelease = self.xformStop self.hprP.onPress = self.xformStart self.hprP.onRelease = self.xformStop - self.hprP.pack(expand=1,fill='x') + self.hprP.pack(expand=1,fill='both') self.hprR = self.createcomponent('hprR', (), None, Dial.Dial, (hprInterior,), @@ -267,11 +281,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.hprR['command'] = self.xform self.hprR['commandData'] = ['r'] self.hprR['callbackData'] = ['r'] - self.hprR.onReturn = self.pushUndo + self.hprR.onReturn = self.xformStart self.hprR.onReturnRelease = self.xformStop self.hprR.onPress = self.xformStart self.hprR.onRelease = self.xformStop - self.hprR.pack(expand=1,fill='x') + self.hprR.pack(expand=1,fill='both') # Create and pack the Scale Controls # The available scaling modes @@ -283,8 +297,9 @@ class Placer(Pmw.MegaToplevel, PandaObject): tag_pyclass = Menubutton, tag_font=('MSSansSerif', 14, 'bold'), tag_activebackground = '#909090', - ring_relief = 'raised') + ring_relief = 'flat') self.scaleMenubutton = scaleGroup.component('tag') + self.bind(self.scaleMenubutton, 'Scale menu operations') self.scaleMenubutton['textvariable'] = self.scalingMode # Scaling menu @@ -313,11 +328,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.scaleX['command'] = self.xform self.scaleX['commandData'] = ['sx'] self.scaleX['callbackData'] = ['sx'] - self.scaleX.onReturn = self.pushUndo + self.scaleX.onReturn = self.xformStart self.scaleX.onReturnRelease = self.xformStop self.scaleX.onPress = self.xformStart self.scaleX.onRelease = self.xformStop - self.scaleX.pack(expand=1,fill='x') + self.scaleX.pack(expand=1,fill='both') self.scaleY = self.createcomponent('scaleY', (), None, Dial.Dial, (scaleInterior,), @@ -327,11 +342,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.scaleY['command'] = self.xform self.scaleY['commandData'] = ['sy'] self.scaleY['callbackData'] = ['sy'] - self.scaleY.onReturn = self.pushUndo + self.scaleY.onReturn = self.xformStart self.scaleY.onReturnRelease = self.xformStop self.scaleY.onPress = self.xformStart self.scaleY.onRelease = self.xformStop - self.scaleY.pack(expand=1,fill='x') + self.scaleY.pack(expand=1,fill='both') self.scaleZ = self.createcomponent('scaleZ', (), None, Dial.Dial, (scaleInterior,), @@ -341,11 +356,11 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.scaleZ['command'] = self.xform self.scaleZ['commandData'] = ['sz'] self.scaleZ['callbackData'] = ['sz'] - self.scaleZ.onReturn = self.pushUndo + self.scaleZ.onReturn = self.xformStart self.scaleZ.onReturnRelease = self.xformStop self.scaleZ.onPress = self.xformStart self.scaleZ.onRelease = self.xformStop - self.scaleZ.pack(expand=1,fill='x') + self.scaleZ.pack(expand=1,fill='both') # Make sure appropriate labels are showing self.setMovementMode('Relative To:') @@ -353,11 +368,34 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.selectNodePathNamed('init') # Clean up things when you destroy the panel - self.bind('', self.onDestroy) + interior.bind('', self.onDestroy) - # Make sure input variables processed - self.initialiseoptions(Placer) + self.createButtons() + def createButtons(self): + self.buttonAdd('Zero All', + helpMessage='Zero Node Path', + statusMessage='Zero Node Path', + command=self.zeroAll) + self.buttonAdd('Reset All', + helpMessage='Reset Node Path', + statusMessage='Reset Node Path', + command=self.resetAll) + self.buttonAdd('Print Info', + helpMessage='Print Node Path Info', + statusMessage='Print Node Path Info', + command=self.printNodePathInfo) + self.buttonAdd('Toggle Widget Viz', + helpMessage='Toggle Object Handles Visability', + statusMessage='Toggle Object Handles Visability', + command=direct.toggleWidgetVis) + self.buttonAdd( + 'Toggle Widget Mode', + helpMessage='Toggle Widget Move/COA Mode', + statusMessage='Toggle Widget Move/COA Mode', + command=direct.manipulationControl.toggleObjectHandlesMode) + + ### WIDGET OPERATIONS ### def setMovementMode(self, movementMode): # Set prefix namePrefix = '' @@ -406,6 +444,10 @@ class Placer(Pmw.MegaToplevel, PandaObject): # Clear bogus entry from listbox listbox = self.nodePathMenu.component('scrolledlist') listbox.setlist(self.nodePathNames) + else: + if name == 'widget': + # Record relationship between selected nodes and widget + direct.selected.getWrtAll() # Update active node path self.setActiveNodePath(nodePath) @@ -430,11 +472,6 @@ class Placer(Pmw.MegaToplevel, PandaObject): nodePath = direct.selected.last # Add Combo box entry for this selected object self.addRefNodePath(nodePath) - elif name == 'coa': - if direct.selected.last: - nodePath = self.tempCS - else: - nodePath = None elif name == 'parent': nodePath = self['nodePath'].getParent() else: @@ -518,15 +555,7 @@ class Placer(Pmw.MegaToplevel, PandaObject): def updateAuxiliaryCoordinateSystems(self): # Temp CS - if ((self.refNodePathMenuEntry.get() == 'coa') & - (direct.selected.last != None)): - pos = Vec3(0) - hpr = Vec3(0) - decomposeMatrix(direct.selected.last.mCoa2Dnp, - VBase3(0), hpr, pos, CSDefault) - self.tempCS.setPosHpr(direct.selected.last, pos, hpr) - else: - self.tempCS.setPosHpr(self['nodePath'], 0,0,0,0,0,0) + self.tempCS.setPosHpr(self['nodePath'], 0,0,0,0,0,0) # Orbit CS # At reference self.orbitFromCS.setPos(self.refCS, 0,0,0) @@ -537,6 +566,7 @@ class Placer(Pmw.MegaToplevel, PandaObject): # Get offset from origin self.posOffset.assign(self['nodePath'].getPos(self.orbitFromCS)) + ### NODE PATH TRANSFORMATION OPERATIONS ### def xform(self, value, axis): if axis in ['sx', 'sy', 'sz']: self.xformScale(value,axis) @@ -544,11 +574,23 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.xformRelative(value, axis) elif self.movementMode == 'Orbit:': self.xformOrbit(value, axis) + if self.nodePathMenu.get() == 'widget': + if direct.manipulationControl.fSetCoa: + # Update coa based on current widget position + direct.selected.last.mCoa2Dnp.assign( + direct.widget.getMat(direct.selected.last)) + else: + # Move the objects with the widget + direct.selected.moveWrtWidgetAll() def xformStart(self, data): # Record undo point self.pushUndo() - # Record initial scale + # If moving widget kill follow task and update wrts + if self.nodePathMenu.get() == 'widget': + taskMgr.removeTasksNamed('followSelectedNodePath') + # Record relationship between selected nodes and widget + direct.selected.getWrtAll() # Update placer to reflect new state self.updatePlacer() @@ -557,6 +599,10 @@ class Placer(Pmw.MegaToplevel, PandaObject): messenger.send('manipulateObjectCleanup') # Update placer to reflect new state self.updatePlacer() + # If moving widget restart follow task + if self.nodePathMenu.get() == 'widget': + # Restart followSelectedNodePath task + direct.manipulationControl.spawnFollowSelectedNodePathTask() def xformRelative(self, value, axis): nodePath = self['nodePath'] @@ -631,18 +677,26 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.scaleZ.set(scale[2]) def zeroAll(self): - self.zeroPos() - self.zeroHpr() - self.unitScale() + self.xformStart(None) + self.updatePosWidgets(ZERO_VEC) + self.updateHprWidgets(ZERO_VEC) + self.updateScaleWidgets(UNIT_VEC) + self.xformStop(None) def zeroPos(self): + self.xformStart(None) self.updatePosWidgets(ZERO_VEC) + self.xformStop(None) def zeroHpr(self): + self.xformStart(None) self.updateHprWidgets(ZERO_VEC) + self.xformStop(None) def unitScale(self): + self.xformStart(None) self.updateScaleWidgets(UNIT_VEC) + self.xformStop(None) def updateResetValues(self, nodePath): self.initPos.assign(nodePath.getPos()) @@ -651,21 +705,28 @@ class Placer(Pmw.MegaToplevel, PandaObject): def resetAll(self): if self['nodePath']: + self.xformStart(None) self['nodePath'].setPosHprScale( self.initPos, self.initHpr, self.initScale) - self.updatePlacer() + self.xformStop(None) def resetPos(self): - self['nodePath'].setPos(self.initPos) - self.updatePlacer() + if self['nodePath']: + self.xformStart(None) + self['nodePath'].setPos(self.initPos) + self.xformStop(None) def resetHpr(self): - self['nodePath'].setHpr(self.initHpr) - self.updatePlacer() + if self['nodePath']: + self.xformStart(None) + self['nodePath'].setHpr(self.initHpr) + self.xformStop(None) def resetScale(self): - self['nodePath'].setScale(self.initScale) - self.updatePlacer() + if self['nodePath']: + self.xformStart(None) + self['nodePath'].setScale(self.initScale) + self.xformStop(None) def pushUndo(self, fResetRedo = 1): direct.pushUndo([self['nodePath']]) @@ -721,15 +782,7 @@ class Placer(Pmw.MegaToplevel, PandaObject): self.tempCS.removeNode() self.orbitFromCS.removeNode() self.orbitToCS.removeNode() - # Only do this once - self.unbind('') - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - def place(nodePath): return Placer(nodePath = nodePath) diff --git a/direct/src/tkwidgets/Floater.py b/direct/src/tkwidgets/Floater.py index e1954dc203..c2ed74e72c 100644 --- a/direct/src/tkwidgets/Floater.py +++ b/direct/src/tkwidgets/Floater.py @@ -2,7 +2,7 @@ Floater Class: Velocity style controller for floating point values with a label, entry (validated), and scale """ - +from PandaObject import * from Tkinter import * import Pmw import string @@ -128,16 +128,15 @@ class Floater(Pmw.MegaWidget): def _startFloaterTask(self,event): self._fFloaterTask = 1 apply(self.onPress,self['callbackData']) - self._floaterTask() + taskMgr.spawnMethodNamed(self._floaterTask, 'floaterTask') - def _floaterTask(self): + def _floaterTask(self, state): if self.velocity != 0.0: self.set( self.value + self.velocity ) - if self._fFloaterTask: - self.after(50, self._floaterTask) + return Task.cont def _floaterReset(self, event): - self._fFloaterTask = 0 + taskMgr.removeTasksNamed('floaterTask') self.velocity = 0.0 self.scale.set(0.0) apply(self.onRelease, self['callbackData'])