From f16d63d6eabafcf2dc9ae35fe1bb7c00ed05ad0a Mon Sep 17 00:00:00 2001 From: Mark Mine Date: Tue, 17 Oct 2000 18:14:09 +0000 Subject: [PATCH] *** empty log message *** --- direct/src/configfiles/direct.init | 1 + direct/src/directutil/DirectSession.py | 103 ++++++ direct/src/showbase/PythonUtil.py | 61 ++++ direct/src/showbase/ShowBase.py | 1 + direct/src/showbase/ShowBaseGlobal.py | 6 +- direct/src/tkpanels/animPanel.py | 345 ------------------ direct/src/tkpanels/fsmInspector.py | 469 ------------------------- direct/src/tkpanels/particlePanel.py | 350 ------------------ direct/src/tkpanels/placer.py | 389 -------------------- direct/src/tkwidgets/dial.py | 458 ------------------------ direct/src/tkwidgets/floater.py | 344 ------------------ direct/src/tkwidgets/vectorWidgets.py | 286 --------------- 12 files changed, 168 insertions(+), 2645 deletions(-) create mode 100644 direct/src/directutil/DirectSession.py delete mode 100644 direct/src/tkpanels/animPanel.py delete mode 100644 direct/src/tkpanels/fsmInspector.py delete mode 100644 direct/src/tkpanels/particlePanel.py delete mode 100644 direct/src/tkpanels/placer.py delete mode 100644 direct/src/tkwidgets/dial.py delete mode 100644 direct/src/tkwidgets/floater.py delete mode 100644 direct/src/tkwidgets/vectorWidgets.py diff --git a/direct/src/configfiles/direct.init b/direct/src/configfiles/direct.init index e078d0667b..db9006df61 100644 --- a/direct/src/configfiles/direct.init +++ b/direct/src/configfiles/direct.init @@ -7,5 +7,6 @@ MODREL PYTHONPATH src/ffi MODREL PYTHONPATH src/actor MODREL PYTHONPATH src/distributed MODREL PYTHONPATH src/showbase +MODREL PYTHONPATH src/directutil MODREL PYTHONPATH src/tkwidgets MODREL PYTHONPATH src/tkpanels diff --git a/direct/src/directutil/DirectSession.py b/direct/src/directutil/DirectSession.py new file mode 100644 index 0000000000..4399667517 --- /dev/null +++ b/direct/src/directutil/DirectSession.py @@ -0,0 +1,103 @@ +from PandaObject import * + +class DisplayRegionContext(PandaObject): + def __init__(self, win, camera): + self.win = win + self.camera = camera + self.cam = camera.getChild(0) + self.camNode = self.cam.getNode(0) + self.mouseData = win.getMouseData(0) + self.mouseX = 0.0 + self.mouseY = 0.0 + #self.spawnContextTask() + + def __getitem__(self,key): + return self.__dict__[key] + + def spawnContextTask(self): + # First kill the existing task + #taskMgr.removeTasksNamed('DIRECTContextTask') + taskMgr.spawnTaskNamed(Task.Task(self.contextTask), + 'DIRECTContextTask') + + def contextTask(self, state): + # Window Data + self.width = self.win.getWidth() + self.height = self.win.getHeight() + self.near = self.camNode.getNear() + self.far = self.camNode.getFar() + self.fovH = self.camNode.getHfov() + self.fovV = self.camNode.getVfov() + self.nearWidth = math.tan(deg2Rad(self.fovH / 2.0)) * self.near * 2.0 + self.nearHeight = math.tan(deg2Rad(self.fovV / 2.0)) * self.near * 2.0 + # Mouse Data + # Last frame + self.mouseLastX = self.mouseX + self.mouseLastY = self.mouseY + # This frame + self.mousePixelX = self.mouseData.getX() + self.mousePixelY = self.mouseData.getY() + self.mouseX = ((self.mousePixelX / float(self.width)) * 2.0) - 1.0 + self.mouseY = ((self.mousePixelY / float(self.height)) * -2.0) + 1.0 + self.mouseDeltaX = self.mouseX - self.mouseLastX + self.mouseDeltaY = self.mouseY - self.mouseLastY + print self.mouseX, self.mouseY + # Continue the task + return Task.cont + +class DirectSession(PandaObject): + def __init__(self): + self.contextList = [] + self.contextList.append(DisplayRegionContext(self.win, self.camera)) + + # Initialize the collection of selected nodePaths + self.selectedNodePaths = {} + self.lastSelected = None + + self.bboxList = [] + + self.fControl = 0 + self.fAlt = 0 + self.fShift = 0 + + """" + def createBBox(self): + bbox = hidden.attachNewNode(NamedNode()) + bbox.setName('bbox') + bboxLines = GridLine new: bbox. + bboxLines color: (VBase4 new: 1.0 y: 0.0 z: 0.0 w: 1.0). + bboxLines thickness: 0.5. + + "Bottom face" + bboxLines moveTo: 0.0 y: 0.0 z: 0.0. + bboxLines drawTo: 1.0 y: 0.0 z: 0.0. + bboxLines drawTo: 1.0 y: 1.0 z: 0.0. + bboxLines drawTo: 0.0 y: 1.0 z: 0.0. + bboxLines drawTo: 0.0 y: 0.0 z: 0.0. + + "Front Edge/Top face" + bboxLines drawTo: 0.0 y: 0.0 z: 1.0. + bboxLines drawTo: 1.0 y: 0.0 z: 1.0. + bboxLines drawTo: 1.0 y: 1.0 z: 1.0. + bboxLines drawTo: 0.0 y: 1.0 z: 1.0. + bboxLines drawTo: 0.0 y: 0.0 z: 1.0. + + "Three remaining edges" + bboxLines moveTo: 1.0 y: 0.0 z: 0.0. + bboxLines drawTo: 1.0 y: 0.0 z: 1.0. + bboxLines moveTo: 1.0 y: 1.0 z: 0.0. + bboxLines drawTo: 1.0 y: 1.0 z: 1.0. + bboxLines moveTo: 0.0 y: 1.0 z: 0.0. + bboxLines drawTo: 0.0 y: 1.0 z: 1.0. + + bboxLines create: bboxLines lineNode.! ! + """ + +class Line(LineSegs): + def __init__(self): + LineSegs.__init__(self) + + + + + diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 1e880549d8..4b8db606d1 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -1,3 +1,5 @@ +import types +import re def ifAbsentPut(dict, key, newValue): """ @@ -19,4 +21,63 @@ def indent(stream, numIndents, str): indentString = ' ' stream.write(indentString * numIndents + str) +def apropos(obj, str = None, fOverloaded = 0, width = None, + fTruncate = 1, lineWidth = 75): + if type(obj) == types.InstanceType: + print "***************************INSTANCE INFO*****************************" + dict = obj.__dict__ + if width: + maxWidth = width + else: + maxWidth = 10 + keyWidth = 0 + aproposKeys = [] + privateKeys = [] + overloadedKeys = [] + remainingKeys = [] + for key in dict.keys(): + if not width: + keyWidth = len(key) + if str: + if re.search(str, key, re.I): + aproposKeys.append(key) + if (not width) & (keyWidth > maxWidth): + maxWidth = keyWidth + else: + if key[:2] == '__': + privateKeys.append(key) + if (not width) & (keyWidth > maxWidth): + maxWidth = keyWidth + elif (key[:10] == 'overloaded'): + if fOverloaded: + overloadedKeys.append(key) + if (not width) & (keyWidth > maxWidth): + maxWidth = keyWidth + else: + remainingKeys.append(key) + if (not width) & (keyWidth > maxWidth): + maxWidth = keyWidth + # Sort appropriate keys + if str: + aproposKeys.sort() + else: + privateKeys.sort() + remainingKeys.sort() + overloadedKeys.sort() + # Print out results + keys = aproposKeys + privateKeys + remainingKeys + overloadedKeys + format = '%-' + `maxWidth` + 's' + for key in keys: + value = `dict[key]` + if fTruncate: + # Cut off line (keeping at least 1 char) + value = value[:max(1,lineWidth - maxWidth)] + print (format % key)[:maxWidth] + '\t' + value + if type(obj) == types.InstanceType: + print "*****************************CLASS INFO******************************" + apropos(obj.__class__, str = str ) + +def aproposAll(obj): + apropos(obj, fOverloaded = 1, fTruncate = 0) + diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 77937ad652..b71e89a3fe 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -5,6 +5,7 @@ from MessengerGlobal import * from TaskManagerGlobal import * from EventManagerGlobal import * from AudioManagerGlobal import * +from PythonUtil import * import Task import EventManager diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 9a0bddd6a6..dd79b70292 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -1,8 +1,8 @@ """instantiate global ShowBase object""" -import ShowBase +from ShowBase import * -base = ShowBase.ShowBase() +base = ShowBase() # Make some global aliases for convenience render2d = base.render2d @@ -10,7 +10,5 @@ render = base.render hidden = base.hidden camera = base.camera loader = base.loader -messenger = base.messenger -taskMgr = base.taskMgr run = base.run tkroot = base.tkroot diff --git a/direct/src/tkpanels/animPanel.py b/direct/src/tkpanels/animPanel.py deleted file mode 100644 index 5c5695975d..0000000000 --- a/direct/src/tkpanels/animPanel.py +++ /dev/null @@ -1,345 +0,0 @@ -"DIRECT Animation Control Panel" - -# Import Tkinter, Pmw, and the floater code from this directory tree. -from Tkinter import * -from tkSimpleDialog import askfloat -import Pmw -import string -import math - -FRAMES = 0 -SECONDS = 1 - -class AnimPanel(Pmw.MegaToplevel): - def __init__(self, parent = None, **kw): - - INITOPT = Pmw.INITOPT - optiondefs = ( - ('title', 'Anim Panel', None), - ('actorList', (), None), - ('Actor_label_width', 12, None), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the superclass - Pmw.MegaToplevel.__init__(self, parent) - - # Handle to the toplevels hull - hull = self.component('hull') - - # A handy little help balloon - balloon = self.balloon = Pmw.Balloon() - # Start with balloon help disabled - self.balloon.configure(state = 'none') - - menuFrame = Frame(hull, relief = GROOVE, bd = 2) - - menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon) - menuBar.pack(side = LEFT, expand = 1, fill = X) - menuBar.addmenu('AnimPanel', 'Anim Panel Operations') - # Actor control status - menuBar.addcascademenu('AnimPanel', 'Control Status', - 'Enable/disable actor control panels') - menuBar.addmenuitem('Control Status', 'command', - 'Enable all actor controls', - label = 'Enable all', - command = self.enableActorControls) - menuBar.addmenuitem('Control Status', 'command', - 'Disable all actor controls', - label = 'Disable all', - command = self.disableActorControls) - # Frame Slider units - menuBar.addcascademenu('AnimPanel', 'Display Units', - 'Select display units') - menuBar.addmenuitem('Display Units', 'command', - 'Display frame counts', label = 'Frame count', - command = self.displayFrameCounts) - menuBar.addmenuitem('Display Units', 'command', - 'Display seconds', label = 'Seconds', - command = self.displaySeconds) - # Reset all actor controls - menuBar.addmenuitem('AnimPanel', 'command', - 'Reset Actor controls', - label = 'Reset all', - command = self.resetAll) - # Exit panel - menuBar.addmenuitem('AnimPanel', 'command', - 'Exit Anim Panel', - label = 'Exit', - command = self.destroy) - - menuBar.addmenu('Help', 'Anim 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) - menuFrame.pack(fill = X) - - # Create a frame to hold all the actor controls - actorFrame = Frame(hull) - - # Create a control for each actor - index = 0 - self.actorControlList = [] - for actor in self['actorList']: - ac = self.createcomponent( - 'actorControl%d' % index, (), 'Actor', - ActorControl, (actorFrame,)) - ac.pack(expand = 1, fill = X) - self.actorControlList.append(ac) - index = index + 1 - - # Now pack the actor frame - actorFrame.pack(expand = 1, fill = BOTH) - - # Create a frame to hold the playback controls - controlFrame = Frame(hull) - self.playPauseVar = IntVar() - self.playPauseVar.set(0) - self.playPauseButton = self.createcomponent( - 'playPause', (), None, - Checkbutton, (controlFrame,), - text = 'Play', width = 8, - variable = self.playPauseVar, - indicatoron = FALSE) - self.playPauseButton.pack(side = LEFT, expand = 1, fill = X) - - self.resetButton = self.createcomponent( - 'reset', (), None, - Button, (controlFrame,), - text = 'Reset All', - width = 8, - command = self.resetAll) - self.resetButton.pack(side = LEFT, expand = 1, fill = X) - - self.loopVar = IntVar() - self.loopVar.set(0) - self.loopButton = self.createcomponent( - 'loopButton', (), None, - Checkbutton, (controlFrame,), - text = 'Loop', width = 8, - variable = self.loopVar) - self.loopButton.pack(side = LEFT, expand = 1, fill = X) - - controlFrame.pack(fill = X) - - # Execute option callbacks - self.initialiseoptions(AnimPanel) - - def getActorControlAt(self, index): - return self.actorControlList[index] - - def enableActorControlAt(self,index): - self.getActorControlAt(index).enableControl() - - def enableActorControls(self): - for actorControl in self.actorControlList: - actorControl.enableControl() - - def disableActorControls(self): - for actorControl in self.actorControlList: - actorControl.disableControl() - - def disableActorControlAt(self,index): - self.getActorControlAt(index).disableControl() - - def displayFrameCounts(self): - for actorControl in self.actorControlList: - actorControl.displayFrameCounts() - - def displaySeconds(self): - for actorControl in self.actorControlList: - actorControl.displaySeconds() - - def resetAll(self): - for actorControl in self.actorControlList: - actorControl.reset() - - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - -class ActorControl(Pmw.MegaWidget): - def __init__(self, parent = None, **kw): - - INITOPT = Pmw.INITOPT - DEFAULT_FONT = (('MS', 'Sans', 'Serif'), 12, 'bold') - DEFAULT_ANIMS = ('neutral', 'run', 'walk') - optiondefs = ( - ('text', 'Actor', self._updateLabelText), - ('actor', None, None), - ('animList', DEFAULT_ANIMS, None), - ('sLabel_width', 5, None), - ('sLabel_font', DEFAULT_FONT, None), - ) - self.defineoptions(kw, optiondefs) - self.addoptions( - (('active', self['animList'][0], None),) - ) - - # Initialize the superclass - Pmw.MegaWidget.__init__(self, parent) - - # Handle to the toplevels hull - interior = self.interior() - interior.configure(relief = RAISED, bd = 2) - - # Instance variables - self.offset = 0.0 - self.fps = 24.0 - self.maxFrame = 120 - self.maxSeconds = self.maxFrame / self.fps - - # Create component widgets - self._label = self.createcomponent( - 'label', (), None, - Menubutton, (interior,), - font=('MSSansSerif', 14, 'bold'), - relief = RAISED, bd = 1, - activebackground = '#909090', - text = self['text']) - # Top level menu - labelMenu = Menu(self._label, tearoff = 0 ) - - # Menu to select display mode - self.unitsVar = IntVar() - self.unitsVar.set(FRAMES) - displayMenu = Menu(labelMenu, tearoff = 0 ) - displayMenu.add_radiobutton(label = 'Frame count', - value = FRAMES, - variable = self.unitsVar, - command = self.updateDisplay) - displayMenu.add_radiobutton(label = 'Seconds', - value = SECONDS, - variable = self.unitsVar, - command = self.updateDisplay) - # Items for top level menu - labelMenu.add_cascade(label = 'Display Units', menu = displayMenu) - labelMenu.add_command(label = 'Set Offset', command = self.setOffset) - labelMenu.add_command(label = 'Reset', command = self.reset) - # Now associate menu with menubutton - self._label['menu'] = labelMenu - self._label.pack(side = LEFT, fill = X) - - # Combo box to select current animation - animMenu = self.createcomponent( - 'animMenu', (), None, - Pmw.ComboBox, (interior,), - labelpos = W, label_text = 'Anim:', - entry_width = 12, selectioncommand = self.selectAnimNamed, - scrolledlist_items = self['animList']) - animMenu.selectitem(self['active']) - animMenu.pack(side = 'left', padx = 5, expand = 0) - - # Combo box to select frame rate - fpsList = (1,2,4,8,12,15,24,30) - fpsMenu = self.createcomponent( - 'fpsMenu', (), None, - Pmw.ComboBox, (interior,), - labelpos = W, label_text = 'at:', - entry_width = 4, selectioncommand = self.setFrameRate, - scrolledlist_items = fpsList) - fpsMenu.selectitem('24') - fpsMenu.pack(side = LEFT, padx = 5, expand = 0) - - # A label - fpsLabel = Label(interior, text = "fps") - fpsLabel.pack(side = LEFT) - - # Scale to control animation - frameFrame = Frame(interior, relief = SUNKEN, bd = 1) - self.minLabel = self.createcomponent( - 'minLabel', (), 'sLabel', - Label, (frameFrame,), - text = 0) - self.minLabel.pack(side = LEFT) - - self.frameControl = self.createcomponent( - 'scale', (), None, - Scale, (frameFrame,), - from_ = 0.0, to = self.maxFrame, resolution = 1.0, - orient = HORIZONTAL, showvalue = 1) - self.frameControl.pack(side = LEFT, expand = 1) - - self.maxLabel = self.createcomponent( - 'maxLabel', (), 'sLabel', - Label, (frameFrame,), - text = self.maxFrame) - self.maxLabel.pack(side = LEFT) - frameFrame.pack(side = LEFT, expand = 1, fill = X) - - # Checkbutton to enable/disable control - self.frameActiveVar = IntVar() - self.frameActiveVar.set(1) - frameActive = self.createcomponent( - 'checkbutton', (), None, - Checkbutton, (interior,), - variable = self.frameActiveVar) - frameActive.pack(side = LEFT, expand = 1) - - # Execute option callbacks - self.initialiseoptions(ActorControl) - - def _updateLabelText(self): - self._label['text'] = self['text'] - - def updateDisplay(self): - # Switch between showing frame counts and seconds - if self.unitsVar.get() == FRAMES: - newMin = int(math.floor(self.offset * self.fps)) - newMax = int(math.ceil(self.offset * self.fps)) + self.maxFrame - self.minLabel['text'] = newMin - self.maxLabel['text'] = newMax - self.frameControl.configure(to = newMax, resolution = 1.0) - else: - newMin = self.offset - newMax = self.offset + self.maxSeconds - self.minLabel['text'] = "%.1f" % newMin - self.maxLabel['text'] = "%.1f" % newMax - print newMin, newMax - self.frameControl.configure(to = newMax, resolution = 0.1) - - def selectAnimNamed(self, name): - print 'Selected Anim: ' + name - - def setFrameRate(self, rate): - self.fps = string.atof(rate) - self.maxSeconds = self.maxFrame / self.fps - self.updateDisplay() - - def setOffset(self): - newOffset = askfloat(title = self['text'], - prompt = 'Start offset (seconds):') - if newOffset: - self.offset = newOffset - self.updateDisplay() - - def enableControl(self): - self.frameActiveVar.set(1) - - def disableControl(self): - self.frameActiveVar.set(0) - - def displayFrameCounts(self): - self.unitsVar.set(FRAMES) - self.updateDisplay() - - def displaySeconds(self): - self.unitsVar.set(SECONDS) - self.updateDisplay() - - def reset(self): - self.offset = 0.0 - self.frameControl.set(0.0) - self.updateDisplay() -###################################################################### - -# Create demo in root window for testing. -if __name__ == '__main__': - widget = AnimPanel(actorList = (1,2,3)) - diff --git a/direct/src/tkpanels/fsmInspector.py b/direct/src/tkpanels/fsmInspector.py deleted file mode 100644 index 929e0e0082..0000000000 --- a/direct/src/tkpanels/fsmInspector.py +++ /dev/null @@ -1,469 +0,0 @@ -from Tkinter import * -from tkSimpleDialog import askstring -import Pmw -import math -import operator - -DELTA = (5.0 / 360.) * 2.0 * math.pi - -class FSMInspector(Pmw.MegaToplevel): - def __init__(self, parent = None, **kw): - # Initialize instance variables - self.stateInspectorDict = {} - - #define the megawidget options - INITOPT = Pmw.INITOPT - optiondefs = ( - ('title', 'FSM Viewer', None), - ('currentFSM', (), None), - ('gridSize', '0.25i', self._setGridSize), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the toplevel widget - Pmw.MegaToplevel.__init__(self, parent) - - # Create the components - oldInterior = Pmw.MegaToplevel.interior(self) - # The Menu Bar - balloon = self.balloon = Pmw.Balloon() - # Start with balloon help disabled - balloon.configure(state = 'none') - menubar = self._menubar = self.createcomponent('menubar', - (), None, - Pmw.MenuBar, (oldInterior,), - balloon = balloon) - menubar.pack(fill=X) - # FSM Menu - menubar.addmenu('FSM', 'FSM Operations') - menubar.addmenuitem('FSM', 'command', - 'Input grid spacing', - label = 'Grid spacing...', - command = self.popupGridDialog) - # Create the checkbutton variable - self._fGridSnap = IntVar() - self._fGridSnap.set(1) - menubar.addmenuitem('FSM', 'checkbutton', - 'Enable/disable grid', - label = 'Snap to grid', - variable = self._fGridSnap, - command = self.toggleGridSnap) - menubar.addmenuitem('FSM', 'command', - 'Print out FSM layout', - label = 'Print FSM layout', - command = self.printLayout) - menubar.addmenuitem('FSM', 'command', - 'Exit the FSM Inspector', - label = 'Exit', - command = self._exit) - - # States Menu - menubar.addmenu('States', 'State Inspector Operations') - menubar.addcascademenu('States', 'Font Size', - 'Set state label size', tearoff = 1) - for size in (8, 10, 12, 14, 18, 24): - menubar.addmenuitem('Font Size', 'command', - 'Set font to: ' + `size` + ' Pts', label = `size` + ' Pts', - command = lambda s = self, sz = size: s.setFontSize(sz)) - menubar.addcascademenu('States', 'Marker Size', - 'Set state marker size', tearoff = 1) - for size in ('Small', 'Medium', 'Large'): - sizeDict = {'Small': '0.25i', 'Medium': '0.375i', 'Large' : '0.5i'} - menubar.addmenuitem('Marker Size', 'command', - size + ' markers', label = size + ' Markers', - command = lambda s = self, sz = size, d = sizeDict: - s.setMarkerSize(d[sz])) - - # The Help menu - menubar.addmenu('Help', 'FSM 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) - - # The Scrolled Canvas - self._scrolledCanvas = self.createcomponent('scrolledCanvas', - (), None, - Pmw.ScrolledCanvas, (oldInterior,), - hull_width = 400, hull_height = 400, - usehullsize = 1) - self._canvas = self._scrolledCanvas.component('canvas') - self._canvas['scrollregion'] = ('-2i', '-2i', '2i', '2i') - self._scrolledCanvas.resizescrollregion() - self._scrolledCanvas.pack(padx = 5, pady = 5, expand=1, fill = BOTH) - - """ - # The Buttons - buttonBox = Frame(oldInterior) - #Button(buttonBox, text = 'Inspect Target').pack(side=LEFT,expand=1,fill=X) - Button(buttonBox, text = 'Print Layout', - command = self.printLayout).pack(side=LEFT,expand=1,fill=X) - Button(buttonBox, text = 'Quit', - command = self._exit).pack(side=LEFT,expand=1,fill=X) - buttonBox.pack(fill=X) - """ - - # Update lines - self._canvas.bind('', self.drawConnections) - self._canvas.bind('', self.mouse2Down) - self._canvas.bind('', self.mouse2Motion) - self._canvas.bind('', - lambda e, sc = self._scrolledCanvas: - sc.resizescrollregion()) - - self.createStateInspectors() - - self.initialiseoptions(FSMInspector) - - def scrolledCanvas(self): - return self._scrolledCanvas - - def canvas(self): - return self._canvas - - def setFontSize(self, size): - self._canvas.itemconfigure('labels', font = ('MS Sans Serif', size)) - - def setMarkerSize(self, size): - for key in self.stateInspectorDict.keys(): - self.stateInspectorDict[key].setRadius(size) - self.drawConnections() - - def drawConnections(self, event = None): - # Get rid of existing arrows - self._canvas.delete('arrow') - for key in self.stateInspectorDict.keys(): - si = self.stateInspectorDict[key] - state = si.state - if state.transitionArray: - for name in state.transitionArray: - self.connectStates(si, self.getStateInspector(name)) - - def connectStates(self, fromState, toState): - endpts = self.computeEndpoints(fromState, toState) - line = self._canvas.create_line(endpts, tags = ('arrow',), - arrow = 'last') - - def computeEndpoints(self, fromState, toState): - # Compute angle between two points - fromCenter = fromState.center() - toCenter = toState.center() - angle = self.findAngle(fromCenter, toCenter) - - # Compute offset fromState point - newFromPt = map(operator.__add__, - fromCenter, - self.computePoint( fromState.radius, - angle + DELTA)) - - # Compute offset toState point - newToPt = map(operator.__sub__, - toCenter, - self.computePoint( toState.radius, - angle - DELTA)) - return newFromPt + newToPt - - def computePoint(self, radius, angle): - x = radius * math.cos(angle) - y = radius * math.sin(angle) - return (x, y) - - def findAngle(self, fromPoint, toPoint): - dx = toPoint[0] - fromPoint[0] - dy = toPoint[1] - fromPoint[1] - return math.atan2(dy, dx) - - def mouse2Down(self, event): - self._width = 1.0 * self._canvas.winfo_width() - self._height = 1.0 * self._canvas.winfo_height() - xview = self._canvas.xview() - yview = self._canvas.yview() - self._left = xview[0] - self._top = yview[0] - self._dxview = xview[1] - xview[0] - self._dyview = yview[1] - yview[0] - self._2lx = event.x - self._2ly = event.y - - def mouse2Motion(self,event): - newx = self._left - ((event.x - self._2lx)/self._width) * self._dxview - self._canvas.xview_moveto(newx) - newy = self._top - ((event.y - self._2ly)/self._height) * self._dyview - self._canvas.yview_moveto(newy) - self._2lx = event.x - self._2ly = event.y - self._left = self._canvas.xview()[0] - self._top = self._canvas.yview()[0] - - def createStateInspectors(self): - fsm = self['currentFSM'] - # Number of rows/cols needed to fit inspectors in a grid - dim = int(math.ceil(math.sqrt(len(fsm)))) - # Separation between nodes - spacing = 2.5 * self._canvas.canvasx('0.375i') - count = 0 - for state in self['currentFSM']: - si = self.addState(state) - if state.defaultPosition: - si.setPos(state.defaultPosition[0], state.defaultPosition[1]) - else: - row = int(math.floor(count / dim)) - col = count % dim - si.setPos(col * spacing, row * spacing + - 0.5 * (0, spacing)[col % 2]) - count = count + 1 - self.drawConnections() - - def getStateInspector(self, name): - return self.stateInspectorDict.get(name, None) - - def addState(self, state): - si = self.stateInspectorDict[state.name] = StateInspector(self, state) - return si - - def enteredState(self, stateName): - si = self.stateInspectorDict.get(stateName,None) - if si: - si.enteredState() - - def exitedState(self, stateName): - si = self.stateInspectorDict.get(stateName,None) - if si: - si.exitedState() - - def _setGridSize(self): - self._gridSize = self['gridSize'] - self.setGridSize(self._gridSize) - - def setGridSize(self, size): - for key in self.stateInspectorDict.keys(): - self.stateInspectorDict[key].setGridSize(size) - - def popupGridDialog(self): - spacing = askstring('FSM Grid Spacing', 'Grid Spacing:') - if spacing: - self.setGridSize(spacing) - self._gridSize = spacing - - def toggleGridSnap(self): - if self._fGridSnap.get(): - self.setGridSize(self._gridSize) - else: - self.setGridSize(0) - - def printLayout(self): - dict = self.stateInspectorDict - keys = dict.keys() - keys.sort - print '{ ' - for key in keys[:-1]: - si = dict[key] - center = si.center() - print "'%s' : (%.3f, %.3f)," % \ - (si.state.name, center[0], center[1]) - for key in keys[-1:]: - si = dict[key] - center = si.center() - print "'%s' : (%.3f, %.3f)," % \ - (si.state.name, center[0], center[1]) - print '}' - - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - - def _exit(self): - self.destroy() - -class StateInspector(Pmw.MegaArchetype): - def __init__(self, inspector, state, **kw): - - # Record state - self.state = state - # Create a unique tag which you can use to move a marker and - # and its corresponding text around together - self.tag = state.name - - # Pointers to the inspector's components - self.scrolledCanvas = inspector.component('scrolledCanvas') - self._canvas = self.scrolledCanvas.component('canvas') - - #define the megawidget options - optiondefs = ( - ('radius', '0.375i', self._setRadius), - ('gridSize', '0.25i', self._setGridSize), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the parent class - Pmw.MegaArchetype.__init__(self) - - # Draw the oval - self.x = 0 - self.y = 0 - half = self._canvas.winfo_fpixels(self['radius']) - self.marker = self._canvas.create_oval((self.x - half), - (self.y - half), - (self.x + half), - (self.y + half), - fill = 'CornflowerBlue', - tags = (self.tag,'markers')) - self.text = self._canvas.create_text(0, 0, text = state.name, - justify = CENTER, - tags = (self.tag,'labels')) - # Is this state contain a sub machine? - if state.fsmArray: - # reduce half by sqrt of 2.0 - half = half * 0.707106 - self.rect = self._canvas.create_rectangle((- half), (- half), - half, half, - tags = (self.tag,)) - - - # The Popup State Menu - self._popupMenu = Menu(self._canvas, tearoff = 0) - self._popupMenu.add_command(label = 'Request transistion to ' + - state.name, - command = self.transitionTo) - if state.fsmArray: - self._popupMenu.add_command(label = 'Inspect ' + state.name + - ' submachine', - command = self.inspectSubMachine) - - self.scrolledCanvas.resizescrollregion() - - # Add bindings - self._canvas.tag_bind(self.tag, '', self.mouseEnter) - self._canvas.tag_bind(self.tag, '', self.mouseLeave) - self._canvas.tag_bind(self.tag, '', self.mouseDown) - self._canvas.tag_bind(self.tag, '', self.mouseMotion) - self._canvas.tag_bind(self.tag, '', self.mouseRelease) - self._canvas.tag_bind(self.tag, '', self.popupStateMenu) - - self.initialiseoptions(StateInspector) - - # Utility methods - def _setRadius(self): - self.setRadius(self['radius']) - - def setRadius(self, size): - half = self.radius = self._canvas.winfo_fpixels(size) - c = self.center() - self._canvas.coords(self.marker, - c[0] - half, c[1] - half, c[0] + half, c[1] + half) - if self.state.fsmArray: - half = self.radius * 0.707106 - self._canvas.coords(self.rect, - c[0] - half, c[1] - half, c[0] + half, c[1] + half) - - def _setGridSize(self): - self.setGridSize(self['gridSize']) - - def setGridSize(self, size): - self.gridSize = self._canvas.winfo_fpixels(size) - if self.gridSize == 0: - self.fGridSnap = 0 - else: - self.fGridSnap = 1 - - def setText(self, text = None): - self._canvas.itemconfigure(self.text, text = text) - - def setPos(self, x, y, snapToGrid = 0): - if self.fGridSnap: - self.x = round(x / self.gridSize) * self.gridSize - self.y = round(y / self.gridSize) * self.gridSize - else: - self.x = x - self.y = y - # How far do we have to move? - cx, cy = self.center() - self._canvas.move(self.tag, self.x - cx, self.y - cy) - - def center(self): - c = self._canvas.coords(self.marker) - return (c[0] + c[2])/2.0, (c[1] + c[3])/2.0 - - # Event Handlers - def mouseEnter(self, event): - self._canvas.itemconfig(self.marker, width = 2) - - def mouseLeave(self, event): - self._canvas.itemconfig(self.marker, width = 1) - - def mouseDown(self, event): - self._canvas.lift(self.tag) - self.startx, self.starty = self.center() - self.lastx = self._canvas.canvasx(event.x) - self.lasty = self._canvas.canvasy(event.y) - - def mouseMotion(self, event): - dx = self._canvas.canvasx(event.x) - self.lastx - dy = self._canvas.canvasy(event.y) - self.lasty - newx, newy = map(operator.__add__,(self.startx, self.starty), (dx, dy)) - self.setPos(newx, newy) - - def mouseRelease(self,event): - self.scrolledCanvas.resizescrollregion() - - def popupStateMenu(self, event): - self._popupMenu.post(event.widget.winfo_pointerx(), - event.widget.winfo_pointery()) - - def transitionTo(self): - print 'transition to ' + self.tag - - def inspectSubMachine(self): - print 'inspect ' + self.tag + ' subMachine' - - def enteredState(self): - self._canvas.itemconfigure(self.marker, fill = 'Red') - - def exitedState(self): - self._canvas.itemconfigure(self.marker, fill = 'CornflowerBlue') - -class dummyState: - def __init__(self, name = None, transitionArray = None, fsmArray = 0): - self.name = name - self.transitionArray = transitionArray - self.fsmArray = fsmArray - self.defaultPosition = None - def hasChildFSMs(self): - return fsmArray - -class dummyFSM: - def __init__(self, stateCollection = (), layout = {}): - self.stateCollection = stateCollection - if layout: - for state in self.stateCollection: - pos = layout.get(state.name, None) - if pos: - state.defaultPosition= pos - def __getitem__(self, item): - return self.stateCollection[item] - def __len__(self): - return len(self.stateCollection) - -if __name__ == '__main__': - s0 = dummyState('state-0', ('state-1',)) - s1 = dummyState('state-1', ('state-2', 'state-3')) - s2 = dummyState('state-2', ('state-0', 'state-4', 'state-5'), fsmArray = 1) - s3 = dummyState('state-3', ('state-6',)) - s4 = dummyState('state-4', ('state-2','state-0')) - s5 = dummyState('state-5', ('state-0',), fsmArray = 1) - s6 = dummyState('state-6', ('state-3', 'state-0')) - fsm = dummyFSM((s0, s1, s2, s3, s4, s5, s6), - layout = {'state-0' : (167.83, 0.0), - 'state-1' : (95.91, 143.86), - 'state-2' : (167.83, 287.72), - 'state-3' : (23.98, 263.74), - 'state-4' : (335.67, 143.86), - 'state-5' : (239.76, 143.86), - 'state-6' : (23.98, 71.93)}) - fsmi = FSMInspector(title = 'My Little Viewer', currentFSM = fsm) - mainloop() diff --git a/direct/src/tkpanels/particlePanel.py b/direct/src/tkpanels/particlePanel.py deleted file mode 100644 index 47bcc21638..0000000000 --- a/direct/src/tkpanels/particlePanel.py +++ /dev/null @@ -1,350 +0,0 @@ -"PANDA3D Particle Panel" - -# Import Tkinter, Pmw, and the floater code from this directory tree. -from Tkinter import * -import Pmw -import dial -import floater -import vectorWidgets - -class ParticlePanel(Pmw.MegaToplevel): - def __init__(self, parent = None, **kw): - - INITOPT = Pmw.INITOPT - optiondefs = ( - ('title', 'Particle Panel', None), - ) - self.defineoptions(kw, optiondefs) - - Pmw.MegaToplevel.__init__(self, parent, title = self['title']) - - # Handle to the toplevels hull - hull = self.component('hull') - - 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) - - menuBar = Pmw.MenuBar(menuFrame, hotkeys = 1, balloon = balloon) - menuBar.pack(side = LEFT, expand = 1, fill = X) - menuBar.addmenu('Particles', 'Particle Panel Operations') - menuBar.addmenuitem('Particles', 'command', - 'Exit Particles Panel', - label = 'Exit', - command = self.destroy) - - menuBar.addmenu('Help', 'Particle 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.systemSelector = Pmw.ComboBox(menuFrame, - labelpos = W, - label_text = 'Particle System:', - entry_width = 16, - selectioncommand = self.selectSystemNamed, - scrolledlist_items = ('system 0',)) - self.systemSelector.selectitem('system 0') - self.systemSelector.pack(side = 'left', expand = 0) - - # Create the notebook pages - notebook = Pmw.NoteBook(hull) - notebook.pack(fill = BOTH, expand = 1) - systemPage = notebook.add('System') - factoryPage = notebook.add('Factory') - emitterPage = notebook.add('Emitter') - rendererPage = notebook.add('Renderer') - - # System page - systemWidgets = ( - ('Pool size', 'Size of particle pool', 0.0, 1.0), - ('Birth rate', 'Seconds between particle births', 0.0, None), - ('Litter size', 'Number of particle created at each birth', 1.0, 1.0), - ('Litter spread', 'Variation in litter size', 0.0, 1.0), - ('System lifespan', 'Age in seconds at which system should die', 0.0, None) - ) - self.createFloaters(systemPage, systemWidgets) - Checkbutton(systemPage, text = 'Local velocity',anchor = W).pack( - fill = X) - Checkbutton(systemPage, text = 'System grows older',anchor = W).pack( - fill = X) - pos = self.createVector3Entry(systemPage, 'Pos', - 'Particle system position') - pos.addMenuItem('Popup 3DoF Panel') - hpr = self.createVector3Entry(systemPage, 'Hpr', - 'Particle system orientation', - floaterGroup_labels = ('H', 'P', 'R')) - hpr.addMenuItem('Popup 3DoF Panel') - - # FACTORY PAGE - self.createOptionMenu(factoryPage, 'Factory type:', - 'Select type of particle factory', - ('Point', 'Z Spin', 'Oriented'), - self.selectFactoryType) - factoryWidgets = ( - ('Life span', 'Average lifespan in seconds', 0.0, None), - ('Life span spread', 'Variation in lifespan', 0.0, None), - ('Mass', 'Average particle mass', 0.0, None), - ('Mass spread', 'Variation in particle mass', 0.0, None), - ('Terminal velocity', 'Average particle terminal velocity', 0.0, None), - ('Terminal vel. spread', 'Variation in terminal velocity', 0.0, None)) - self.createFloaters(factoryPage, factoryWidgets) - - self.factoryNotebook = Pmw.NoteBook(factoryPage, tabpos = None) - pointPage = self.factoryNotebook.add('Point') - zSpinPage = self.factoryNotebook.add('Z Spin') - self.createAngleDial(zSpinPage, 'Initial angle', - 'Starting angle in degrees') - self.createAngleDial(zSpinPage, 'Final angle', - 'Final angle in degrees') - self.createAngleDial(zSpinPage, 'Angle spread', - 'Spread of the final angle') - orientedPage = self.factoryNotebook.add('Oriented') - Label(orientedPage, text = 'Not implemented').pack(expand = 1, - fill = BOTH) - self.factoryNotebook.pack(expand = 1, fill = BOTH) - - # EMITTER PAGE - self.createOptionMenu(emitterPage, 'Emitter type:', - 'Select type of particle emitter', - ('Box', 'Disc', 'Line', 'Point', 'Rectangle', - 'Ring', 'Sphere Surface', 'Sphere Volume', - 'Tangent Ring'), - self.selectEmitterType) - self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None) - pointPage = self.emitterNotebook.add('Box') - self.createVector3Entry(pointPage, 'Point 1', - 'Point defining emitter box') - self.createVector3Entry(pointPage, 'Point 2', - 'Point defining emitter box', - initialValue = (1.0, 1.0, 1.0)) - self.createVector3Entry(pointPage, 'Launch vector', - 'Initial particle velocity vector') - - discPage = self.emitterNotebook.add('Disc') - self.createFloater(discPage, 'Radius', 'Radius of disc') - self.createAngleDial(discPage, 'Inner angle', - 'Particle launch angle at center of disc') - self.createFloater(discPage, 'Inner magnitude', - 'Launch velocity multiplier at center of disc') - self.createAngleDial(discPage, 'Outer angle', - 'Particle launch angle at outer edge of disc') - self.createFloater(discPage, 'Outer magnitude', - 'Launch velocity multiplier at edge of disc') - - Checkbutton(discPage, text = 'Cubic Lerping').pack( - side = LEFT, expand = 1, fill = X) - - linePage = self.emitterNotebook.add('Line') - self.createVector3Entry(linePage, 'Point 1', - 'Point defining emitter line') - self.createVector3Entry(linePage, 'Point 2', - 'Point defining emitter line', - initialValue = (1.0, 0.0, 0.0)) - self.createVector3Entry(linePage, 'Launch Vector', - 'Initial particle velocity vector', - initialValue = (0.0, 0.0, 1.0)) - - pointPage = self.emitterNotebook.add('Point') - self.createVector3Entry(pointPage, 'Location', - 'Location of emitter point') - self.createVector3Entry(pointPage, 'Launch vector', - 'Initial particle velocity vector', - initialValue = (0.0, 0.0, 1.0)) - - rectanglePage = self.emitterNotebook.add('Rectangle') - self.createVector3Entry(rectanglePage, 'Point 1', - 'Point defining rectangle') - self.createVector3Entry(rectanglePage, 'Point 2', - 'Point defining rectangle') - self.createVector3Entry(rectanglePage, 'Launch vector', - 'Initial particle velocity vector', - initialValue = (0.0, 0.0, 1.0)) - - ringPage = self.emitterNotebook.add('Ring') - self.createFloater(ringPage, 'Radius', 'Radius of ring') - self.createAngleDial(ringPage, 'Angle', 'Particle launch angle') - self.createFloater(ringPage, 'Magnitude', - 'Launch velocity multiplier at outer edge of ring') - - sphereSurfacePage = self.emitterNotebook.add('Sphere Surface') - self.createFloater(sphereSurfacePage, 'Radius', - 'Radius of sphere') - - sphereVolumePage = self.emitterNotebook.add('Sphere Volume') - self.createFloater(sphereVolumePage, 'Radius', - 'Radius of sphere') - - tangentRingPage = self.emitterNotebook.add('Tangent Ring') - self.createFloater(tangentRingPage, 'Radius', - 'Radius of ring') - - self.emitterNotebook.pack(fill = X) - - # RENDERER PAGE - self.createOptionMenu(rendererPage, 'Renderer type:', - 'Select type of particle renderer', - ('Geom', 'Point', 'Sparkle', 'Sprite'), - self.selectRendererType) - self.rendererNotebook = Pmw.NoteBook(rendererPage, tabpos = None) - geomPage = self.rendererNotebook.add('Geom') - f = Frame(geomPage) - f.pack(fill = X) - Label(f, width = 12, text = 'Geom node:').pack(side = LEFT) - Entry(f, width = 12).pack(side = LEFT, expand = 1, fill = X) - - pointPage = self.rendererNotebook.add('Point') - self.createFloater(pointPage, 'Point size', - 'Width and height of points in pixels') - self.createColorEntry(pointPage, 'Start color', - 'Starting color of point') - self.createColorEntry(pointPage, 'End color', - 'Ending color of point') - self.createOptionMenu(pointPage, 'Blend type:', - 'Type of color blending used for particle', - ('ONE_COLOR', 'BLEND_LIFE', 'BLEND_VEL'), - self.selectBlendType) - self.createOptionMenu(pointPage, 'Blend method:', - 'Interpolation method between colors', - ('LINEAR', 'CUBIC'), - self.selectBlendMethod) - - sparklePage = self.rendererNotebook.add('Sparkle') - self.createColorEntry(sparklePage, 'Center color', - 'Color of sparkle center') - self.createColorEntry(sparklePage, 'Edge color', - 'Color of sparkle line endpoints') - self.createFloater(sparklePage, 'Birth radius', - 'Initial sparkle radius') - self.createFloater(sparklePage, 'Death radius', - 'Final sparkle radius') - self.createOptionMenu(pointPage, 'Life scale:', - 'Does particle scale over its lifetime?', - ('NO_SCALE', 'SCALE'), - self.selectBlendMethod) - - spritePage = self.rendererNotebook.add('Sprite') - f = Frame(spritePage) - f.pack(fill = X) - Label(f, width = 12, text = 'Texture:').pack(side = LEFT) - Entry(f, width = 12).pack(side = LEFT, expand = 1, fill = X) - - Checkbutton(spritePage, text = 'xScale',anchor = W).pack(fill = X) - Checkbutton(spritePage, text = 'yScale',anchor = W).pack(fill = X) - Checkbutton(spritePage, text = 'animAngle',anchor = W).pack(fill = X) - self.createFloater(spritePage, 'Initial X Scale', - 'Initial X scaling factor') - self.createFloater(spritePage, 'Final X Scale', - 'Final X scaling factor') - self.createFloater(spritePage, 'Initial Y Scale', - 'Initial Y scaling factor') - self.createFloater(spritePage, 'Final Y Scale', - 'Final Y scaling factor') - self.createAngleDial(spritePage, 'Non Animated Theta', - 'Counter clockwise Z rotation of all sprites') - self.createOptionMenu(spritePage, 'Blend Type', - 'Interpolation blend type for X and Y scaling', - ('LINEAR', 'CUBIC'), - self.selectBlendMethod) - Checkbutton(spritePage, text = 'alphaDisable',anchor = W).pack(fill = X) - - - self.rendererNotebook.pack(fill = X) - - self.factoryNotebook.setnaturalsize() - self.emitterNotebook.setnaturalsize() - self.rendererNotebook.setnaturalsize() - notebook.setnaturalsize() - - # Make sure input variables processed - self.initialiseoptions(ParticlePanel) - - def createFloaters(self, parent, widgetDefinitions): - for label, balloonHelp, min, resolution in widgetDefinitions: - self.createFloater(parent, label, balloonHelp, min, resolution) - - def createFloater(self, parent, text, balloonHelp, - min = 0.0, resolution = None, **kw): - kw['text'] = text - kw['min'] = min - kw['initialValue'] = min - kw['resolution'] = resolution - widget = apply(floater.Floater, (parent,), kw) - widget.pack(fill = X) - self.balloon.bind(widget, balloonHelp) - return widget - - def createAngleDial(self, parent, text, balloonHelp, **kw): - kw['text'] = text - widget = apply(dial.AngleDial,(parent,), kw) - widget.pack(fill = X) - self.balloon.bind(widget, balloonHelp) - return widget - - def createVector3Entry(self, parent, text, balloonHelp, **kw): - # Set label's text - kw['text'] = text - widget = apply(vectorWidgets.Vector3Entry, (parent,), kw) - widget.pack(fill = X) - self.balloon.bind(widget, balloonHelp) - return widget - - def createColorEntry(self, parent, text, balloonHelp, **kw): - # Set label's text - kw['text'] = text - widget = apply(vectorWidgets.ColorEntry, (parent,) ,kw) - widget.pack(fill = X) - self.balloon.bind(widget, balloonHelp) - return widget - - def createOptionMenu(self, parent, text, balloonHelp, items, command): - optionVar = StringVar() - optionVar.set(items[0]) - widget = Pmw.OptionMenu(parent, labelpos = W, label_text = text, - label_width = 12, menu_tearoff = 1, - menubutton_textvariable = optionVar, - items = items, - command = command) - widget.pack(fill = X) - self.balloon.bind(widget.component('menubutton'), balloonHelp) - return optionVar - - def selectFactoryType(self, type): - self.factoryNotebook.selectpage(type) - - def selectEmitterType(self, type): - self.emitterNotebook.selectpage(type) - - def selectRendererType(self, type): - self.rendererNotebook.selectpage(type) - - def selectBlendType(self, type): - print type - - def selectBlendMethod(self, method): - print method - - def selectSystemNamed(self, name): - print name - - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - -###################################################################### - -# Create demo in root window for testing. -if __name__ == '__main__': - root = Pmw.initialise() - pp = ParticlePanel() - #ve = VectorEntry(Toplevel(), relief = GROOVE) - #ve.pack() diff --git a/direct/src/tkpanels/placer.py b/direct/src/tkpanels/placer.py deleted file mode 100644 index dca3b3cd83..0000000000 --- a/direct/src/tkpanels/placer.py +++ /dev/null @@ -1,389 +0,0 @@ -"DIRECT Nine DoF Placer demonstration" - -# Import Tkinter, Pmw, and the floater code from this directory tree. -from Tkinter import * -import Pmw -import floater -import dial - -class Placer(Pmw.MegaToplevel): - def __init__(self, parent = None, **kw): - - INITOPT = Pmw.INITOPT - optiondefs = ( - ('title', 'Placer Panel', None), - ('nodePath', None, None), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the superclass - Pmw.MegaToplevel.__init__(self, parent) - - # 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.addcascademenu('Placer', 'Axis', - 'Control axis visibility', - tearoff = 1) - self.axisViz = StringVar() - self.axisViz.set('Show Axis') - menuBar.component('Axis-menu').add_radiobutton( - label = 'Show Axis', - variable = self.axisViz, - value = 'Show Axis', - command = lambda s = self: s._updateAxisViz()) - menuBar.component('Axis-menu').add_radiobutton( - label = 'Hide Axis', - variable = self.axisViz, - value = 'Hide Axis', - command = lambda s = self: s._updateAxisViz()) - menuBar.component('Axis-menu').add_radiobutton( - label = 'Auto Axis', - variable = self.axisViz, - value = 'Auto Axis', - command = lambda s = self: s._updateAxisViz()) - - menuBar.addmenuitem('Placer', 'command', - 'Exit Placer Panel', - label = 'Exit', - command = self.destroy) - menuBar.addmenu('NodePath', 'Node Path Operations') - menuBar.addmenuitem('NodePath', 'command', - 'Undo Pos/Hpr/Scale', - label = 'Undo All', - command = self._undoAll) - menuBar.addmenuitem('NodePath', 'command', - 'Redo Pos/Hpr/Scale', - label = 'Redo All', - command = self._redoAll) - menuBar.addmenuitem('NodePath', 'command', - 'Reset Node Path', - label = 'Reset All', - command = self._resetAll) - menuBar.addmenuitem('NodePath', 'command', - 'Print Node Path Info', - label = 'Print Info', - command = self.printNodePathInfo) - - 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) - - nodePathMenu = Pmw.ComboBox(menuFrame, - labelpos = W, - label_text = 'Node Path:', - entry_width = 12, - selectioncommand = self.selectNodePathNamed, - scrolledlist_items = ('selected', - 'hot point', - 'camera')) - nodePathMenu.selectitem('selected') - nodePathMenu.pack(side = 'left', expand = 0) - - mode = StringVar() - mode.set('Drive') - modeMenu = Pmw.OptionMenu(menuFrame, - menubutton_textvariable=mode, - items = ('Drive', 'Orbit', - 'Absolute', 'Relative'), - command = self._updateFloaterLabels, - menubutton_width = 8) - modeMenu.pack(side = 'left', expand = 0) - - self.wrtMenu = Pmw.ComboBox(menuFrame, - labelpos = W, - label_text = 'WRT:', - entry_width = 12, - selectioncommand = self.selectNodePathNamed, - scrolledlist_items = ('render', - 'selected', - 'camera')) - self.wrtMenu.selectitem('render') - self.wrtMenu.pack(side = 'left', expand = 0) - - # The master frame for the dials - dialFrame = Frame(hull) - dialFrame.pack(fill = 'both', expand = 1) - - # Create and pack the Pos Controls - posGroup = Pmw.Group(dialFrame, - tag_pyclass = Menubutton, - tag_text = 'Position', - tag_font=('MSSansSerif', 14, 'bold'), - tag_activebackground = '#909090', - ring_relief = 'raised') - posMenubutton = posGroup.component('tag') - posMenu = Menu(posMenubutton) - posMenu.add_command(label = 'Undo', command = self._undoPos) - posMenu.add_command(label = 'Redo', command = self._redoPos) - posMenu.add_command(label = 'Set to zero', command = self._zeroPos) - posMenu.add_command(label = 'Restore initial', command = self._resetPos) - posMenubutton['menu'] = posMenu - posGroup.pack(side='left',fill = 'both', expand = 1) - posInterior = posGroup.interior() - - # Create the floaters - self.posX = self.createcomponent('posX', (), None, - dial.Dial, (posInterior,), - text = 'X', - label_foreground = 'Red') - self.posX['command'] = self.printCommand - self.posX.pack(expand=1,fill='x') - - self.posY = self.createcomponent('posY', (), None, - dial.Dial, (posInterior,), - text = 'Y', - label_foreground = '#00A000') - self.posY['command'] = self.printCommand - self.posY.pack(expand=1,fill='x') - - self.posZ = self.createcomponent('posZ', (), None, - dial.Dial, (posInterior,), - text = 'Z', - label_foreground = 'Blue') - self.posZ['command'] = self.printCommand - self.posZ.pack(expand=1,fill='x') - - # Create and pack the Hpr Controls - hprGroup = Pmw.Group(dialFrame, - tag_pyclass = Menubutton, - tag_text = 'Orientation', - tag_font=('MSSansSerif', 14, 'bold'), - tag_activebackground = '#909090', - ring_relief = 'raised') - hprMenubutton = hprGroup.component('tag') - hprMenu = Menu(hprMenubutton) - hprMenu.add_command(label = 'Undo', command = self._undoHpr) - hprMenu.add_command(label = 'Redo', command = self._redoHpr) - hprMenu.add_command(label = 'Set to zero', command = self._zeroHpr) - hprMenu.add_command(label = 'Restore initial', command = self._resetHpr) - hprMenubutton['menu'] = hprMenu - hprGroup.pack(side='left',fill = 'both', expand = 1) - hprInterior = hprGroup.interior() - - # Create the floaters - self.hprH = self.createcomponent('hprH', (), None, - dial.Dial, (hprInterior,), - text = 'H', fRollover = 0, - max = 360.0, numTicks = 12, - label_foreground = 'blue') - self.hprH['command'] = self.printCommand - self.hprH.pack(expand=1,fill='x') - - self.hprP = self.createcomponent('hprP', (), None, - dial.Dial, (hprInterior,), - text = 'P', fRollover = 0, - max = 360.0, numTicks = 12, - label_foreground = 'red') - self.hprP['command'] = self.printCommand - self.hprP.pack(expand=1,fill='x') - - self.hprR = self.createcomponent('hprR', (), None, - dial.Dial, (hprInterior,), - text = 'R', fRollover = 0, - max = 360.0, numTicks = 12, - label_foreground = '#00A000') - self.hprR['command'] = self.printCommand - self.hprR.pack(expand=1,fill='x') - - # Create and pack the Scale Controls - scaleGroup = Pmw.Group(dialFrame, - tag_text = 'Scale', - tag_pyclass = Menubutton, - tag_font=('MSSansSerif', 14, 'bold'), - tag_activebackground = '#909090', - ring_relief = 'raised') - scaleMenubutton = scaleGroup.component('tag') - scaleMenu = Menu(scaleMenubutton) - scaleModeMenu = Menu(scaleMenu) - # The available scaling modes - self.scalingMode = StringVar() - self.scalingMode.set('Free') - scaleModeMenu.add_radiobutton(label = 'Free', - variable = self.scalingMode) - scaleModeMenu.add_radiobutton(label = 'Uniform', - variable = self.scalingMode) - scaleModeMenu.add_radiobutton(label = 'Proportional', - variable = self.scalingMode) - - # First level scaling menu - scaleMenu.add_command(label = 'Undo', command = self._undoScale) - scaleMenu.add_command(label = 'Redo', command = self._redoScale) - scaleMenu.add_command(label = 'Set to unity', - command = self._unitScale) - scaleMenu.add_command(label = 'Restore initial', - command = self._resetScale) - scaleMenu.add_cascade(label = 'Scaling mode...', - menu = scaleModeMenu) - scaleMenubutton['menu'] = scaleMenu - scaleGroup.pack(side='left',fill = 'both', expand = 1) - scaleInterior = scaleGroup.interior() - - # Create the floaters - self.scaleX = self.createcomponent('scaleX', (), None, - dial.Dial, (scaleInterior,), - text = 'X Scale', - initialValue = 1.0, - label_foreground = 'Red') - self.scaleX['command'] = self.printCommand - self.scaleX.pack(expand=1,fill='x') - - self.scaleY = self.createcomponent('scaleY', (), None, - dial.Dial, (scaleInterior,), - text = 'Y Scale', - initialValue = 1.0, - label_foreground = '#00A000') - self.scaleY['command'] = self.printCommand - self.scaleY.pack(expand=1,fill='x') - - self.scaleZ = self.createcomponent('scaleZ', (), None, - dial.Dial, (scaleInterior,), - text = 'Z Scale', - initialValue = 1.0, - label_foreground = 'Blue') - self.scaleZ['command'] = self.printCommand - self.scaleZ.pack(expand=1,fill='x') - - # Make sure appropriate labels are showing - self._updateFloaterLabels('Drive') - - # Make sure input variables processed - self.initialiseoptions(Placer) - - - def printCommand(self, val): - print 'Current value: %s' % val - - def selectNodePathNamed(self, name): - print 'Selected Node Path: ' + name - - def printNodePathInfo(self): - print 'Print Node Path info here' - - def _updateAxisViz(self): - self.updateAxisViz(self.axisViz.get()) - - def updateAxisViz(self, mode): - print mode - - def _undoPos(self): - print 'undo pos' - - def _redoPos(self): - print 'redo pos' - - def _resetPos(self): - self.posX.reset() - self.posY.reset() - self.posZ.reset() - - def _zeroPos(self): - self.posX.set(0.0) - self.posY.set(0.0) - self.posZ.set(0.0) - - def _undoHpr(self): - print 'undo hpr' - - def _redoHpr(self): - print 'redo hpr' - - def _resetHpr(self): - self.hprH.reset() - self.hprP.reset() - self.hprR.reset() - - def _zeroHpr(self): - self.hprH.set(0.0) - self.hprP.set(0.0) - self.hprR.set(0.0) - - def _resetScale(self): - self.scaleX.reset() - self.scaleY.reset() - self.scaleZ.reset() - - def _undoScale(self): - print 'undo scale' - - def _redoScale(self): - print 'redo scale' - - def _unitScale(self): - self.scaleX.set(1.0) - self.scaleY.set(1.0) - self.scaleZ.set(1.0) - - def _undoAll(self): - self._undoPos() - self._undoHpr() - self._undoScale() - - def _redoAll(self): - self._redoPos() - self._redoHpr() - self._redoScale() - - def _resetAll(self): - self._resetPos() - self._resetHpr() - self._resetScale() - - def _updateFloaterLabels(self, movementMode): - namePrefix = '' - self.movementMode = movementMode - if (movementMode == 'Drive'): - namePrefix = 'Drive delta ' - elif (movementMode == 'Orbit'): - namePrefix = 'Orbit ' - elif (movementMode == 'Absolute'): - namePrefix = 'Absolute ' - elif (movementMode == 'Relative'): - namePrefix = 'Relative ' - - if(movementMode == 'Relative'): - self.wrtMenu.configure(entry_foreground = 'Black') - self.wrtMenu.configure(entry_background = 'SystemWindow') - else: - self.wrtMenu.configure(entry_foreground = 'gray50') - self.wrtMenu.configure(entry_background = '#E0E0E0') - - self.posX['text'] = namePrefix + 'X' - self.posY['text'] = namePrefix + 'Y' - self.posZ['text'] = namePrefix + 'Z' - - if (movementMode == 'Orbit'): - namePrefix = 'Orbit delta ' - - self.hprH['text'] = namePrefix + 'H' - self.hprP['text'] = namePrefix + 'P' - self.hprR['text'] = namePrefix + 'R' - - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - -###################################################################### - -# Create demo in root window for testing. -if __name__ == '__main__': - root = Pmw.initialise() - widget = Placer() - diff --git a/direct/src/tkwidgets/dial.py b/direct/src/tkwidgets/dial.py deleted file mode 100644 index f8e5de0f4f..0000000000 --- a/direct/src/tkwidgets/dial.py +++ /dev/null @@ -1,458 +0,0 @@ -from Tkinter import * -from tkSimpleDialog import askfloat -import Pmw -import math -import string -import operator - -# TODO: -# More standardized use of 'max' and 'min' -# Better floater style action -# New option? 'delta'? 'repeatVal'? 'modulus' - -TWO_PI = 2.0 * math.pi -ONEPOINTFIVE_PI = 1.5 * math.pi -POINTFIVE_PI = 0.5 * math.pi -INNER_SF = 0.175 -MAX_EXP = 5 - -class Dial(Pmw.MegaWidget): - def __init__(self, parent = None, **kw): - #define the megawidget options - INITOPT = Pmw.INITOPT - optiondefs = ( - # Widget relief - ('relief', GROOVE, INITOPT), - # Widget borderwidth - ('borderwidth', 2, INITOPT), - # Relief of dial inset - ('canvas_relief', GROOVE, INITOPT), - # Borderwidth of dial inset - ('canvas_bd', 2, INITOPT), - # Size of edge of dial inset - ('edgeLength', 50, INITOPT), - ('initialValue', 0.0, INITOPT), - # Snap to angle on/off - ('fSnap', 0, None), - # Do values rollover (i.e. accumulate) with multiple revolutions - ('fRollover', 1, None), - ('command', None, None), - ('text', 'Dial Widget', self.updateLabel), - ('numTicks', 10, self.createTicks), - ('numDigits', 2, self.updateEntryFormat), - ('min', 0.0, self.setScaleFactor), - ('max', 1.0, self.setScaleFactor), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the superclass - Pmw.MegaWidget.__init__(self, parent) - - # Set up some local and instance variables - dim = self['edgeLength'] - self.sfGridDelta = dim / 10 - half = self.half = int(dim/2.0) - radius = self.radius = half - 2 - - # Running total which increments/decrements every time around dial - self.baseVal = 0.0 - # Determines value of one dial revolution - self.scaleFactor = 1.0 - self.dialAngle = None - # Current value - self.value = self['initialValue'] - - # Create the components - interior = self.interior() - interior.configure(relief = self['relief'], bd = self['borderwidth']) - - # The canvas - self._canvas = self.createcomponent('canvas', (), None, - Canvas, (interior,), - width = dim + 12, height = dim, - scrollregion = ((- half),(- half), - half, half)) - self._canvas.grid(rowspan = 2, columnspan = 2) - - # The dial face - self._canvas.create_oval(-radius, -radius, radius, radius, - fill = 'white', tags = ('dial',)) - self.createTicks() - - # The velocity knob - self._canvas.create_oval(-radius * INNER_SF, -radius * INNER_SF, - radius * INNER_SF, radius * INNER_SF, - fill = '#909090', tags = ('velocityKnob',)) - - # The indicator - self._canvas.create_line(0, 0, 0, (- radius), width = 2, - tags = ('indicator', 'dial')) - - # The Scale Factor marker - self._canvas.create_polygon( half + 4, - 4, half + 12, 0, - half + 4, + 4, fill = '#A0A0A0', - tags = ('sfMarker',)) - self.sfy = 0 - - # The Dial's label - self._label = self.createcomponent('label', (), None, - Label, (interior,), - text = self['text'], - font = ('MS Sans Serif', 12, 'bold'), - anchor = CENTER) - self._label.grid(row = 0, col = 2, sticky = EW) - - # The entry - self._entryVal = StringVar() - self._entry = self.createcomponent('entry', (), None, - Entry, (interior,), - justify = RIGHT, - textvariable = self._entryVal) - self._entry.grid(row = 1, col = 2, sticky = EW) - self._entry.bind('', self.validateEntryInput) - self._entryBackground = self._entry.cget('background') - interior.columnconfigure(2, weight = 1) - - # The popup menu - self._popupMenu = Menu(interior, tearoff = 0) - self._fAngleSnap = IntVar() - self._fAngleSnap.set(self['fSnap']) - self._popupMenu.add_checkbutton(label = 'Angle snap', - variable = self._fAngleSnap, - command = self.setAngleSnap) - self._fRollover = IntVar() - self._fRollover.set(self['fRollover']) - self._popupMenu.add_checkbutton(label = 'Rollover', - variable = self._fRollover, - command = self.setRollover) - - sfMenu = Menu(interior, tearoff = 1) - self.expVar = DoubleVar() - self.expVar.set(0) - for exp in range (MAX_EXP, -(MAX_EXP + 1), -1): - sf = "%g" % math.pow(10, exp) - sfMenu.add_radiobutton(label = sf, value = exp, - variable = self.expVar, - command = self.setScaleFactor) - sfMenu.add_command(label = 'Scale Factor...', - command = self.getScaleFactor) - self._popupMenu.add_cascade(label = 'Scale Factor', - menu = sfMenu) - self._popupMenu.add_command(label = 'Reset Dial', - command = self.reset) - - # Add event bindings - self._canvas.tag_bind('dial', '', self.mouseDown) - self._canvas.tag_bind('dial', '', self.mouseMotion) - self._canvas.tag_bind('dial', '', self.shiftMouseMotion) - self._canvas.tag_bind('sfMarker', '', self.highlightSFMarker) - self._canvas.tag_bind('sfMarker', '', self.restoreSFMarker) - self._canvas.tag_bind('velocityKnob', '', self.highlightKnob) - self._canvas.tag_bind('velocityKnob', '', self.restoreKnob) - self._canvas.tag_bind('sfMarker', '', self.sfMouseDown) - self._canvas.tag_bind('sfMarker', '', self.sfMouseMotion) - self._canvas.tag_bind('sfMarker', '', self.sfMouseUp) - self._canvas.tag_bind('velocityKnob', '', self.knobMouseDown) - self._canvas.tag_bind('velocityKnob', '', self.knobMouseMotion) - self._canvas.tag_bind('velocityKnob', '', self.knobMouseUp) - self._canvas.bind('', self.popupDialMenu) - self._canvas.bind('', self.mouseReset) - self._canvas.bind('', self.expUp) - self._canvas.bind('', self.expDown) - - # Make sure input variables processed - self.initialiseoptions(Dial) - - def updateLabel(self): - self._label['text'] = self['text'] - - def createTicks(self): - self._canvas.delete('ticks') - # Based upon input snap angle, how many ticks - numTicks = self['numTicks'] - # Compute snapAngle (radians) - self.snapAngle = snapAngle = TWO_PI / numTicks - # Create the ticks at the snap angles - for ticknum in range(numTicks): - angle = snapAngle * ticknum - # convert to canvas coords - angle = angle - POINTFIVE_PI - # Compute tick endpoints - startx = math.cos(angle) * self.radius - starty = math.sin(angle) * self.radius - # Elongate ticks at 90 degree points - if (angle % POINTFIVE_PI) == 0.0: - sf = 0.6 - else: - sf = 0.8 - endx = startx * sf - endy = starty * sf - self._canvas.create_line(startx, starty, endx, endy, - tags = ('ticks','dial')) - - def mouseDown(self,event): - self.lastAngle = dialAngle = self.computeDialAngle(event) - self.computeValueFromAngle(dialAngle) - - def shiftMouseMotion(self,event): - self.mouseMotion(event, 1) - - def mouseMotion(self, event, fShift = 0): - dialAngle = self.computeDialAngle(event, fShift) - self.computeValueFromAngle(dialAngle) - - def computeDialAngle(self,event, fShift = 0): - x = self._canvas.canvasx(event.x) - y = self._canvas.canvasy(event.y) - rawAngle = math.atan2(y,x) - # Snap to grid - # Convert to dial coords to do snapping - dialAngle = rawAngle + POINTFIVE_PI - if operator.xor(self['fSnap'], fShift): - dialAngle = round(dialAngle / self.snapAngle) * self.snapAngle - return dialAngle - - def computeValueFromAngle(self, dialAngle): - delta = self.delta - dialAngle = dialAngle % TWO_PI - # Check for rollover, if necessary - if (self.lastAngle > ONEPOINTFIVE_PI) & (dialAngle < POINTFIVE_PI): - self.baseVal = self.baseVal + delta - elif (self.lastAngle < POINTFIVE_PI) & (dialAngle > ONEPOINTFIVE_PI): - self.baseVal = self.baseVal - delta - self.lastAngle = dialAngle - # Update value and entry - newValue = self['min'] + self.baseVal + delta * (dialAngle / TWO_PI) - self.dialAngle = dialAngle - self.set(newValue) - - def get(self): - return self.value - - def set(self, value): - if not self['fRollover']: - if value > self['max']: - self.baseVal = 0.0 - value = ((value - self['min']) % - (self['max'] - self['min'])) + self['min'] - self.updateEntry(value) - if self.dialAngle: - self.updateIndicatorRadians(self.dialAngle) - self.dialAngle = None - else: - self.updateIndicator(value) - if self['command']: - self['command'](value) - - def updateIndicator(self, value): - # compute new indicator angle - delta = self.delta - factors = divmod(value - self['min'], delta) - self.baseVal = factors[0] * delta - self.updateIndicatorRadians( (factors[1]/delta) * TWO_PI ) - - def updateIndicatorDegrees(self, degAngle): - self.updateIndicatorRadians(degAngle * (math.pi/180.0)) - - def updateIndicatorRadians(self,dialAngle): - rawAngle = dialAngle - POINTFIVE_PI - # Compute end points - endx = math.cos(rawAngle) * self.radius - endy = math.sin(rawAngle) * self.radius - # Draw new indicator - self._canvas.coords('indicator', endx * INNER_SF, endy * INNER_SF, - endx, endy) - - def updateEntry(self, value): - self._entryVal.set(self.entryFormat % value) - - def updateEntryFormat(self): - self.entryFormat = "%." + "%df" % self['numDigits'] - self.updateEntry(self.value) - - def validateEntryInput(self, event): - input = self._entryVal.get() - try: - newValue = string.atof(input) - self.set(newValue) - self._entry.configure(background = self._entryBackground) - except ValueError: - self._entry.configure(background = 'Pink') - - def sfMouseDown(self, event): - # Record marker starting position - self.starty = self.sfy - # Record mouse starting position (convert to canvas coords) - self.lasty = self._canvas.canvasy(event.y) - - def sfMouseMotion(self, event): - # How far did the mouse move? - dy = self._canvas.canvasy(event.y) - self.lasty - # Apply this delta to the marker - newy = self.starty + dy - # Compute new exponent based upon current position - exp = self.sfComputeExp(newy) - # Set resulting scale factor - self.setScaleFactorExp(exp) - - def sfMouseUp(self, event): - self._canvas.delete('sfText') - - # Compute exponent based on current marker position - def sfComputeExp(self, y, fSnap = 1): - # Force marker to stay visible - newy = max( -self.half, min( self.half, y ) ) - # Snap it - gridDelta = self.sfGridDelta - if fSnap: - newy = round( newy / gridDelta ) * gridDelta - # Compute resulting exponent - return (-(newy / gridDelta)) - - def setScaleFactorExp(self, exp, showText = 1, fUpdateIndicator = 1): - self.exp = exp - # Update popup scale factor menu to nearest exponent - self.expVar.set(int(round(exp))) - # Compute new scale factor - self.scaleFactor = math.pow(10, exp) - # Compute resulting delta - self.delta = self.scaleFactor * (self['max'] - self['min']) - # Update indicator to reflect new scale factor - if fUpdateIndicator: - self.updateIndicator(self.value) - # Move marker to correct position - self.updateScaleFactorMarker(-exp*self.sfGridDelta, showText) - - def expUp(self,event): - self.setScaleFactorExp(min(MAX_EXP, self.exp + 1), 0) - - def expDown(self,event): - self.setScaleFactorExp(max(-MAX_EXP, self.exp - 1), 0) - - def knobMouseDown(self,event): - self.lasty = self._canvas.canvasy(event.y) - self.updateIndicatorRadians(0.0) - self.velocityTask = self.after(100, self.computeVelocity) - - def knobMouseMotion(self, event): - # How far is the mouse from the origin? - dx = self._canvas.canvasx(event.x) - self.lasty = self._canvas.canvasy(event.y) - exp = -5 + dx/20.0 - exp = max( -5, min( 5, exp ) ) - # Set resulting scale factor - self.setScaleFactorExp(exp, 0, fUpdateIndicator = 0) - - def knobMouseUp(self, event): - self.after_cancel(self.velocityTask) - # reset indicator - self.updateIndicator(self.value) - - def computeVelocity(self): - if self.lasty < 0: - sign = -1.0 - else: - sign = 1.0 - lasty = abs(self.lasty) - if lasty > 5: - lasty = lasty - 5 - sf = min(100, lasty)/100.0 - sf = pow(sf, 3.0) - newVal = self.value - sign * sf * self.delta - self.dialAngle = - sign * sf * POINTFIVE_PI - self.set(newVal) - self.velocityTask = self.after(100, self.computeVelocity) - - def updateScaleFactorMarker(self, newy, showText = 1): - # Move marker - self._canvas.move('sfMarker', 0, newy - self.sfy) - self.sfy = newy - - # Show current scaling factor - if showText: - sfText = '%g' % (self.delta / 10.0,) - self._canvas.delete('sfText') - self._canvas.create_rectangle( self.half - 40, newy - 6, - self.half, newy + 7, - fill = 'white', - tags = ('sfText',)) - self._canvas.create_text( self.half, newy, - justify = RIGHT, - anchor = E, - text = sfText, - fill = 'Red', - tags = ('sfText',)) - - # The following routines are used to handle the popup menu - def popupDialMenu(self,event): - self._popupMenu.post(event.widget.winfo_pointerx(), - event.widget.winfo_pointery()) - - # This is called by the scale factor popup menu and when the user - # changes the dial 'delta' value - def setScaleFactor(self): - exp = self.expVar.get() - self.setScaleFactorExp(exp, showText = 0) - - # This handles the popup scale factor dialog - def getScaleFactor(self): - sf = askfloat('Dial Scale Factor', 'Scale Factor:', - parent = self.interior()) - if sf: - self.setScaleFactorExp(math.log10(sf), showText = 0) - - # Turn angle snap on/off - def setAngleSnap(self): - self['fSnap'] = self._fAngleSnap.get() - - # Turn rollover (accumulation of a sum) on/off - def setRollover(self): - self['fRollover'] = self._fRollover.get() - - def highlightSFMarker(self, event): - self._canvas.itemconfigure('sfMarker', fill = '#252525') - - def restoreSFMarker(self, event): - self._canvas.itemconfigure('sfMarker', fill = '#A0A0A0') - - def highlightKnob(self, event): - self._canvas.itemconfigure('velocityKnob', fill = '#252525') - - def restoreKnob(self, event): - self._canvas.itemconfigure('velocityKnob', fill = '#A0A0A0') - - # Reset dial to zero - def mouseReset(self,event): - if not self._canvas.find_withtag(CURRENT): - self.reset() - - def reset(self): - self.set(self['initialValue']) - # Should we do this? - self.setScaleFactorExp(0, showText = 0) - -class AngleDial(Dial): - def __init__(self, parent = None, **kw): - # Set the typical defaults for a 360 degree angle dial - optiondefs = ( - ('fRollover', 0, None), - ('numTicks', 12, None), - ('max', 360.0, None), - ) - self.defineoptions(kw, optiondefs) - # Initialize the superclass - Dial.__init__(self, parent) - # Needed because this method checks if self.__class__ is myClass - # where myClass is the argument passed into inialiseoptions - self.initialiseoptions(AngleDial) - -if __name__ == '__main__': - tl = Toplevel() - d = Dial(tl) - d2 = Dial(tl, numTicks = 12, max = 360, fRollover = 0, initialValue = 180) - d3 = Dial(tl, numTicks = 12, max = 90, min = -90, fRollover = 0) - d4 = Dial(tl, numTicks = 16, max = 256, fRollover = 0) - d.pack(expand = 1, fill = X) - d2.pack(expand = 1, fill = X) - d3.pack(expand = 1, fill = X) - d4.pack(expand = 1, fill = X) diff --git a/direct/src/tkwidgets/floater.py b/direct/src/tkwidgets/floater.py deleted file mode 100644 index c3e44ee93e..0000000000 --- a/direct/src/tkwidgets/floater.py +++ /dev/null @@ -1,344 +0,0 @@ -""" -Floater Class: Velocity style controller for floating point values with - a label, entry (validated), and scale -""" - -from Tkinter import * -import Pmw -import string - -class Floater(Pmw.MegaWidget): - "Velocity style floating point controller" - - def __init__(self, parent = None, **kw): - - # Define the megawidget options. - optiondefs = ( - ('initialValue', 0.0, Pmw.INITOPT), - ('resolution', None, None), - ('command', None, None), - ('maxVelocity', 100.0, None), - ('min', None, self._updateValidate), - ('max', None, self._updateValidate), - ('text', 'Floater', self._updateLabelText), - ('significantDigits', 2, self._setSigDigits), - ) - self.defineoptions(kw, optiondefs) - - # Initialise superclass - Pmw.MegaWidget.__init__(self, parent) - - # Initialize some class variables - self.value = self['initialValue'] - self.velocity = 0.0 - self.entryFormat = '%.2f' - - # Create the components. - - # Setup up container - interior = self.interior() - interior.configure(relief = GROOVE, borderwidth = 2) - - # Create a label and an entry - self.labelFrame = self.createcomponent('frame', (), None, - Frame, interior) - # Create an entry field to display and validate the floater's value - self.entryValue = StringVar() - self.entryValue.set(self['initialValue']) - self.entry = self.createcomponent('entryField', - # Access floaters entry using "entry" - (('entry', 'entryField_entry'),), - None, - Pmw.EntryField, self.labelFrame, - entry_width = 10, - validate = { 'validator' : 'real', - 'min' : self['min'], - 'max' : self['max'], - 'minstrict' : 0, - 'maxstrict' : 0}, - entry_justify = 'right', - entry_textvar = self.entryValue, - command = self._entryCommand) - self.entry.pack(side='left',padx = 4) - - # Create the Floater's label - self.label = self.createcomponent('label', (), None, - Label, self.labelFrame, - text = self['text'], - width = 12, - anchor = 'center', - font = "Arial 12 bold") - self.label.pack(side='left', expand = 1, fill = 'x') - - # Now pack the frame - self.labelFrame.pack(expand = 1, fill = 'both') - - # Create the scale component. - self.scale = self.createcomponent('scale', (), None, - Scale, interior, - command = self._scaleToVelocity, - orient = 'horizontal', - length = 150, - from_ = -1.0, - to = 1.0, - resolution = 0.001, - showvalue = 0) - self.scale.pack(expand = 1, fill = 'x') - # Set scale to the middle of its range - self.scale.set(0.0) - - # Add scale bindings: When interacting with mouse: - self.scale.bind('', self._startFloaterTask) - self.scale.bind('', self._floaterReset) - # In case you wish to interact using keys - self.scale.bind('', self._floaterKeyCommand) - self.scale.bind('', self._floaterReset) - self.scale.bind('', self._floaterKeyCommand) - self.scale.bind('', self._floaterReset) - - # Check keywords and initialise options based on input values. - self.initialiseoptions(Floater) - - def label(self): - return self.label - def scale(self): - return self.scale - def entry(self): - return self.entry - - def _updateLabelText(self): - self.label['text'] = self['text'] - - def _updateValidate(self): - self.configure(entryField_validate = { - 'validator' : 'real', - 'min' : self['min'], - 'max' : self['max'], - 'minstrict' : 0, - 'maxstrict' : 0}) - - def _scaleToVelocity(self, strVal): - # convert scale val to float - val = string.atof(strVal) - # Square val, but retain sign of velocity by only calling abs once - self.velocity = self['maxVelocity'] * val * abs(val) - - def _startFloaterTask(self,event): - self._fFloaterTask = 1 - self._floaterTask() - - def _floaterTask(self): - if self.velocity != 0.0: - self.set( self.value + self.velocity ) - if self._fFloaterTask: - self.after(50, self._floaterTask) - - def _floaterReset(self, event): - self._fFloaterTask = 0 - self.velocity = 0.0 - self.scale.set(0.0) - - def _floaterKeyCommand(self, event): - if self.velocity != 0.0: - self.set( self.value + self.velocity ) - - def _entryCommand(self, event = None): - try: - val = string.atof( self.entryValue.get() ) - self.set( val ) - except ValueError: - pass - - def _setSigDigits(self): - sd = self['significantDigits'] - self.entryFormat = '%.' + '%d' % sd + 'f' - # And reset value to reflect change - self.entryValue.set( self.entryFormat % self.value ) - - def get(self): - return self.value - - def set(self, newVal, fCommand = 1): - # Clamp value - if self['min'] is not None: - if newVal < self['min']: - newVal = self['min'] - if self['max'] is not None: - if newVal > self['max']: - newVal = self['max'] - # Round by resolution - if self['resolution'] is not None: - newVal = round(newVal / self['resolution']) * self['resolution'] - - # Update floater's value - self.value = newVal - # Update entry to reflect formatted value - self.entryValue.set( self.entryFormat % self.value ) - self.entry.checkentry() - - # execute command - if fCommand & (self['command'] is not None): - self['command']( newVal ) - - -class FloaterGroup(Pmw.MegaToplevel): - def __init__(self, parent = None, **kw): - - # Default group size - DEFAULT_DIM = 1 - # Default value depends on *actual* group size, test for user input - DEFAULT_VALUE = [0.0] * kw.get('dim', DEFAULT_DIM) - DEFAULT_LABELS = map(lambda x: 'v[%d]' % x, - range(kw.get('dim', DEFAULT_DIM))) - - #define the megawidget options - INITOPT = Pmw.INITOPT - optiondefs = ( - ('dim', DEFAULT_DIM, INITOPT), - ('side', TOP, INITOPT), - ('title', 'Floater Group', None), - # A tuple of initial values, one for each floater - ('initialValue', DEFAULT_VALUE, INITOPT), - # The command to be executed any time one of the floaters is updated - ('command', None, None), - # A tuple of labels, one for each floater - ('labels', DEFAULT_LABELS, self._updateLabels), - ) - self.defineoptions(kw, optiondefs) - - # Initialize the toplevel widget - Pmw.MegaToplevel.__init__(self, parent) - - # Create the components - interior = self.interior() - # Get a copy of the initial value (making sure its a list) - self._value = list(self['initialValue']) - - # The Menu Bar - self.balloon = Pmw.Balloon() - menubar = self.createcomponent('menubar',(), None, - Pmw.MenuBar, (interior,), - balloon = self.balloon) - menubar.pack(fill=X) - - # FloaterGroup Menu - menubar.addmenu('Floater Group', 'Floater Group Operations') - menubar.addmenuitem( - 'Floater Group', 'command', 'Reset the Floater Group panel', - label = 'Reset', - command = lambda s = self: s.reset()) - menubar.addmenuitem( - 'Floater Group', 'command', 'Dismiss Floater Group panel', - label = 'Dismiss', command = self.withdraw) - - menubar.addmenu('Help', 'Floater Group 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.floaterList = [] - for index in range(self['dim']): - # Add a group alias so you can configure the floaters via: - # fg.configure(Floater_XXX = YYY) - f = self.createcomponent( - 'floater%d' % index, (), 'Floater', Floater, - (interior,), initialValue = self._value[index], - text = self['labels'][index]) - # Do this separately so command doesn't get executed during construction - f['command'] = lambda val, s=self, i=index: s._floaterSetAt(i, val) - f.pack(side = self['side'], expand = 1, fill = X) - self.floaterList.append(f) - - # Make sure floaters are initialized - self.set(self['initialValue']) - - # Make sure input variables processed - self.initialiseoptions(FloaterGroup) - - def _updateLabels(self): - if self['labels']: - for index in range(self['dim']): - self.floaterList[index]['text'] = self['labels'][index] - - def toggleBalloon(self): - if self.toggleBalloonVar.get(): - self.balloon.configure(state = 'balloon') - else: - self.balloon.configure(state = 'none') - - def get(self): - return self._value - - def getAt(self,index): - return self._value[index] - - # This is the command is used to set the groups value - def set(self, value, fCommand = 1): - for i in range(self['dim']): - self._value[i] = value[i] - # Update floater, but don't execute its command - self.floaterList[i].set(value[i], 0) - if fCommand & (self['command'] is not None): - self['command'](self._value) - - def setAt(self, index, value): - # Update floater and execute its command - self.floaterList[index].set(value) - - # This is the command used by the floater - def _floaterSetAt(self, index, value): - self._value[index] = value - if self['command']: - self['command'](self._value) - - def reset(self): - self.set(self['initialValue']) - - - -## SAMPLE CODE -if __name__ == '__main__': - # Initialise Tkinter and Pmw. - root = Toplevel() - root.title('Pmw Floater demonstration') - - # Dummy command - def printVal(val): - print val - - # Create and pack a Floater megawidget. - mega1 = Floater(root, command = printVal) - mega1.pack(side = 'left', expand = 1, fill = 'x') - - """ - # These are things you can set/configure - # Starting value for floater - mega1['initialValue'] = 123.456 - mega1['text'] = 'Drive delta X' - mega1['min'] = 0.0 - mega1['max'] = 1000.0 - mega1['resolution'] = 1.0 - # To change the color of the label: - mega1.label['foreground'] = 'Red' - # Max change/update, default is 100 - # To have really fine control, for example - # mega1['maxVelocity'] = 0.1 - # Number of digits to the right of the decimal point, default = 2 - # mega1['significantDigits'] = 5 - """ - - # To create a floater group to set an RGBA value: - group1 = FloaterGroup(root, dim = 4, - title = 'Simple RGBA Panel', - labels = ('R', 'G', 'B', 'A'), - Floater_min = 0.0, - Floater_max = 255.0, - Floater_resolution = 1.0, - command = printVal) - - # Uncomment this if you aren't running in IDLE - #root.mainloop() diff --git a/direct/src/tkwidgets/vectorWidgets.py b/direct/src/tkwidgets/vectorWidgets.py deleted file mode 100644 index c32a8b6dc2..0000000000 --- a/direct/src/tkwidgets/vectorWidgets.py +++ /dev/null @@ -1,286 +0,0 @@ -from Tkinter import * -import Pmw -import floater -import string -import tkColorChooser - -class VectorEntry(Pmw.MegaWidget): - def __init__(self, parent = None, **kw): - - # Default vector size - DEFAULT_DIM = 3 - # Default value depends on *actual* vector size, test for user input - DEFAULT_VALUE = [0.0] * kw.get('dim', DEFAULT_DIM) - DEFAULT_LABELS = map(lambda x: 'v[%d]' % x, - range(kw.get('dim', DEFAULT_DIM))) - - # Process options - INITOPT = Pmw.INITOPT - optiondefs = ( - ('dim', DEFAULT_DIM, INITOPT), - ('initialValue', DEFAULT_VALUE, INITOPT), - ('label_width', 12, None), - ('command', None, None), - ('entryWidth', 8, self._updateEntryWidth), - ('relief', GROOVE, self._updateRelief), - ('bd', 2, self._updateBorderWidth), - ('text', 'Vector:', self._updateText), - ('min', None, self._updateValidate), - ('max', None, self._updateValidate), - ('significantDigits', 2, self._setSigDigits), - ) - self.defineoptions(kw, optiondefs) - - # Initialize superclass - Pmw.MegaWidget.__init__(self, parent) - - # Initialize value - # Make sure its a list (and as a byproduct, make a distinct copy) - self._value = list(self['initialValue']) - self._floaters = None - self.entryFormat = '%.2f' - - # Get a handle on the parent container - interior = self.interior() - - # This does double duty as a menu button - self._label = self.createcomponent('label', (), None, - Menubutton, (interior,), - text = self['text'], - activebackground = '#909090') - self.menu = self._label['menu'] = Menu(self._label) - self.menu.add_command(label = 'Reset', command = self.reset) - self.menu.add_command(label = 'Popup sliders', command = self.popupSliders) - self._label.pack(side = LEFT, fill = X, ipadx = 2) - - self.variableList = [] - self.entryList = [] - for index in range(self['dim']): - var = StringVar() - self.variableList.append(var) - # To set the configuration of all entrys in a vector use: - # ve.configure(Entry_XXX = YYY) - # To configure an individual entryfield's entry use: - # ve.configure(entry0_XXX = YYY) - entry = self.createcomponent( - 'entryField%d' % index, - (('entry%d' % index, - 'entryField%d_entry' % index),), - 'Entry', - Pmw.EntryField, (interior,), - entry_justify = RIGHT, - entry_textvariable = var, - command = lambda s = self, i = index: s._entryUpdateAt(i)) - entry.pack(side = LEFT, expand = 1, fill = X) - self.entryList.append(entry) - - # To configure the floaterGroup use: - # ve.configure(floaterGroup_XXX = YYY) - # ve.configure(fGroup_XXX = YYY) or - # To set the configuration all floaters in a group use: - # ve.configure(Floater_XXX = YYY) - # To configure an individual floater in a group use: - # ve.configure(floaterGroup_floater0_XXX = YYY) or - # ve.configure(fGroup_floater0_XXX = YYY) - self._floaters = self.createcomponent( - 'floaterGroup', - (('fGroup', 'floaterGroup'), - ('Floater', 'floaterGroup_Floater'),), None, - floater.FloaterGroup, (self.interior(),), - dim = self['dim'], title = self['text'], - command = self.set) - # Note: This means the 'X' on the menu bar doesn't really destroy - # the panel, just withdraws it. This is to avoid problems which occur - # if the user kills the floaterGroup and then tries to pop it open again - self._floaters.userdeletefunc(self._floaters.withdraw) - self._floaters.withdraw() - - - # Make sure entries are updated - self.set(self['initialValue']) - - # Make sure input variables processed - self.initialiseoptions(VectorEntry) - - def menu(self): - return self.menu - - def label(self): - return self._label - - def entry(self, index): - return self.entryList[index] - - def entryList(self): - return self.entryList - - def floaters(self): - return self._floaters - - def _clearFloaters(self): - self._floaters.withdraw() - - def _updateText(self): - self._label['text'] = self['text'] - - def _updateRelief(self): - self.interior()['relief'] = self['relief'] - - def _updateBorderWidth(self): - self.interior()['bd'] = self['bd'] - - def _updateEntryWidth(self): - self['Entry_entry_width'] = self['entryWidth'] - - def _setSigDigits(self): - sd = self['significantDigits'] - self.entryFormat = '%.' + '%d' % sd + 'f' - self.configure(Floater_significantDigits = sd) - # And refresh value to reflect change - for index in range(self['dim']): - self._refreshEntry(index) - - def _updateValidate(self): - # Update entry field to respect new limits - self.configure(Entry_validate = { - 'validator' : 'real', - 'min' : self['min'], - 'max' : self['max'], - 'minstrict' : 0, - 'maxstrict' : 0}) - # Reflect changes in floaters - self.configure(Floater_min = self['min'], - Floater_max = self['max']) - - def get(self): - return self._value - - def getAt(self,index): - return self._value[index] - - def set(self, value): - for i in range(self['dim']): - self._value[i] = value[i] - self.variableList[i].set(self.entryFormat % value[i]) - self.action() - - def setAt(self, index, value): - self.variableList[index].set(self.entryFormat % value) - self._value[index] = value - self.action() - - def _entryUpdateAt(self, index): - entryVar = self.variableList[index] - # Did we get a valid float? - try: - newVal = string.atof(entryVar.get()) - except ValueError: - return - - # Clamp value - if self['min'] is not None: - if newVal < self['min']: - newVal = self['min'] - if self['max'] is not None: - if newVal > self['max']: - newVal = self['max'] - - # Update vector's value - self._value[index] = newVal - - # refresh entry to reflect formatted value - self._refreshEntry(index) - - # Update the floaters and call the command - self.action() - - def _refreshEntry(self,index): - self.variableList[index].set( self.entryFormat % self._value[index] ) - self.entryList[index].checkentry() - - def _refreshFloaters(self): - if self._floaters: - self._floaters.set(self._value, 0) - - def action(self): - self._refreshFloaters() - if self['command']: - self['command'](self._value) - - def reset(self): - self.set(self['initialValue']) - - def addMenuItem(self, label = '', command = None): - self.menu.add_command(label = label, command = command) - - def popupSliders(self): - self._floaters.set(self.get()[:]) - self._floaters.show() - -class Vector3Entry(VectorEntry): - def __init__(self, parent = None, **kw): - # Initialize options for the class - optiondefs = ( - ('dim', 3, Pmw.INITOPT), - ('fGroup_labels', ('X','Y','Z'), None), - ) - self.defineoptions(kw, optiondefs) - # Initialize the superclass, make sure dim makes it to superclass - VectorEntry.__init__(self, parent, dim = self['dim']) - # Needed because this method checks if self.__class__ is myClass - # where myClass is the argument passed into inialiseoptions - self.initialiseoptions(Vector3Entry) - -class Vector4Entry(VectorEntry): - def __init__(self, parent = None, **kw): - # Initialize options for the class - optiondefs = ( - ('dim', 4, Pmw.INITOPT), - ('fGroup_labels', ('X','Y','Z','W'), None), - ) - self.defineoptions(kw, optiondefs) - # Initialize the superclass, make sure dim makes it to superclass - VectorEntry.__init__(self, parent, dim = self['dim']) - # Needed because this method checks if self.__class__ is myClass - # where myClass is the argument passed into inialiseoptions - self.initialiseoptions(Vector4Entry) - -class ColorEntry(VectorEntry): - def __init__(self, parent = None, **kw): - # Initialize options for the class (overriding some superclass options) - optiondefs = ( - ('dim', 4, Pmw.INITOPT), - ('fGroup_labels', ('R','G','B','A'), None), - ('min', 0.0, None), - ('max', 255.0, None), - ('significantDigits', 0, None), - ('Floater_resolution', 1.0, None), - ) - self.defineoptions(kw, optiondefs) - # Initialize the superclass, make sure dim makes it to superclass - VectorEntry.__init__(self, parent, dim = self['dim']) - # Add menu item to popup color picker - self.addMenuItem( - 'Popup color picker', - command = lambda s = self: s.popupColorPicker()) - # Needed because this method checks if self.__class__ is myClass - # where myClass is the argument passed into inialiseoptions - self.initialiseoptions(ColorEntry) - - def popupColorPicker(self): - # Can pass in current color with: color = (255, 0, 0) - color = tkColorChooser.askcolor( - parent = self.interior(), - # Initialize it to current color - initialcolor = tuple(self.get()[:3]))[0] - if color: - self.set((color[0], color[1], color[2], self.getAt(3))) - -if __name__ == '__main__': - root = Toplevel() - root.title('Vector Widget demo') - - ve = VectorEntry(root); ve.pack() - v3e = Vector3Entry(root); v3e.pack() - v4e = Vector4Entry(root); v4e.pack() - ce = ColorEntry(root); ce.pack()