Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
81cbc5013f

+ 13 - 0
direct/src/directutil/DirectGeometry.py

@@ -1,5 +1,16 @@
+from PandaModules import *
 from PandaObject import *
 
+X_AXIS = Vec3(1,0,0)
+Y_AXIS = Vec3(0,1,0)
+Z_AXIS = Vec3(0,0,1)
+NEG_X_AXIS = Vec3(-1,0,0)
+NEG_Y_AXIS = Vec3(0,-1,0)
+NEG_Z_AXIS = Vec3(0,0,-1)
+ZERO_VEC = ORIGIN = Vec3(0)
+UNIT_VEC = Vec3(1)
+ZERO_POINT = Point3(0)
+
 class LineNodePath(NodePath):
     def __init__(self, parent = None, **kw):
 
@@ -71,3 +82,5 @@ def planeIntersect (lineOrigin, lineDir, planeOrigin, normal):
     hitPt = lineDir * t
     return hitPt + lineOrigin
 
+def roundTo(value, divisor):
+    return round(value/float(divisor)) * divisor

+ 25 - 10
direct/src/directutil/DirectGrid.py

@@ -43,8 +43,10 @@ class DirectGrid(NodePath,PandaObject):
 
 	# Initialize Grid characteristics
         self.fXyzSnap = 1
+        self.fHprSnap = 1
 	self.gridSize = 100.0
 	self.gridSpacing = 5.0
+        self.snapAngle = 15.0
         self.enable()
 
     def enable(self):
@@ -96,24 +98,28 @@ class DirectGrid(NodePath,PandaObject):
         minor.create()
         major.create()
         self.gridBack.setScale(scaledSize)
-
-    def roundTo(self, value, divisor):
-        return round(value/float(divisor)) * divisor
-
+        
     def setXyzSnap(self, fSnap):
         self.fXyzSnap = fSnap
 
     def getXyzSnap(self):
         return self.fXyzSnap
 
-    def snapToGrid(self, point):
+    def setHprSnap(self, fSnap):
+        self.fHprSnap = fSnap
+
+    def getHprSnap(self):
+        return self.fHprSnap
+
+    def computeSnapPoint(self, point):
+        # Start of with current point
+        self.snapPos.assign(point)
+        # Snap if necessary
         if self.fXyzSnap:
             self.snapPos.set(
-                roundTo(point[0], self.gridSpacing),
-                roundTo(point[1], self.gridSpacing),
-                roundTo(point[2], self.gridSpacing))
-        else:
-            self.snapPos.assign(point)
+                roundTo(self.snapPos[0], self.gridSpacing),
+                roundTo(self.snapPos[1], self.gridSpacing),
+                roundTo(self.snapPos[2], self.gridSpacing))
             
 	# Move snap marker to this point
 	self.snapMarker.setPos(self.snapPos)
@@ -121,6 +127,15 @@ class DirectGrid(NodePath,PandaObject):
 	# Return the hit point
 	return self.snapPos
 
+    def computeSnapAngle(self, angle):
+        return roundTo(angle, self.snapAngle)
+
+    def setSnapAngle(self, angle):
+        self.snapAngle = angle
+
+    def getSnapAngle(self):
+        return self.snapAngle
+
     def setGridSpacing(self, spacing):
         self.gridSpacing = spacing
         self.updateGrid()

+ 10 - 7
direct/src/directutil/DirectSelection.py

@@ -18,12 +18,10 @@ class DirectNodePath(NodePath):
         # and its center of action (COA)
         self.mCoa2Dnp = Mat4()
         self.mCoa2Dnp.assign(Mat4.identMat())
-        self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
+        # self.mCoa2Dnp.setRow(3, Vec4(center[0], center[1], center[2], 1))
         # Transform from nodePath to widget
         self.mDnp2Widget = Mat4()
         self.mDnp2Widget.assign(Mat4.identMat())
-        # Use value of this pointer as unique ID
-        self.id = self.node().this
 
     def highlight(self):
         self.bbox.show()
@@ -65,7 +63,7 @@ class SelectedNodePaths(PandaObject):
             self.deselectAll()
 
         # Get this pointer
-        id = nodePath.node().this
+        id = nodePath.id()
         # First see if its already in the selected dictionary
         dnp = self.selectedDict.get(id, None)
         # If so, we're done
@@ -84,14 +82,14 @@ class SelectedNodePaths(PandaObject):
                 # Show its bounding box
                 dnp.highlight()
             # Add it to the selected dictionary
-            self.selectedDict[dnp.id] = dnp
+            self.selectedDict[dnp.id()] = dnp
         # And update last
         self.last = dnp
         return dnp
 
     def deselect(self, nodePath):
         # Get this pointer
-        id = nodePath.node().this
+        id = nodePath.id()
         # See if it is in the selected dictionary
         dnp = self.selectedDict.get(id, None)
         if dnp:
@@ -108,11 +106,16 @@ class SelectedNodePaths(PandaObject):
         list = []
         for key in self.selectedDict.keys():
             list.append(self.selectedDict[key])
+        return list
+
+    def __getitem__(self,index):
+        return self.selectedAsList()[index]
 
     def deselectedAsList(self):
         list = []
         for key in self.deselectedDict.keys():
             list.append(self.deselectedDict[key])
+        return list
 
     def forEachSelectedNodePathDo(self, func):
         duplicateKeys = self.selectedDict.keys()[:]
@@ -171,7 +174,7 @@ class SelectedNodePaths(PandaObject):
 
     def getDirectNodePath(self, nodePath):
         # Get this pointer
-        id = nodePath.node().this
+        id = nodePath.id()
         # First check selected dict
         dnp = self.selectedDict.get(id, None)
         if dnp:

+ 7 - 2
direct/src/directutil/DirectSession.py

@@ -43,6 +43,10 @@ class DirectSession(PandaObject):
         self.iRay = self.iRayList[0]
         self.hitPt = Point3(0.0)
 
+        # One run through the context task to init everything
+        for context in self.contextList:
+            context.contextTask(None)
+
         self.actionEvents = [('select', self.select),
                              ('deselect', self.deselect),
                              ('deselectAll', self.deselectAll),
@@ -89,8 +93,9 @@ class DirectSession(PandaObject):
 
     def followSelectedNodePathTask(self, state):
         mCoa2Render = state.dnp.mCoa2Dnp * state.dnp.getMat(render)
-        mCoa2Render.decomposeMatrix(
-            self.scale,self.hpr,self.pos,getDefaultCoordinateSystem())
+        decomposeMatrix(mCoa2Render,
+                        self.scale,self.hpr,self.pos,
+                        getDefaultCoordinateSystem())
         self.widget.setPosHpr(self.pos,self.hpr)
         return Task.cont
 

+ 6 - 1
direct/src/extensions/NodePath-extensions.py

@@ -4,6 +4,10 @@
     of the NodePath class
     """
 
+    def id(self):
+        """Returns the bottom node's this pointer as a unique id"""
+        return self.node().this
+
     def getNodePathName(self):
         from PandaModules import *
         # Initialize to a default value
@@ -70,7 +74,8 @@
 
     def getAncestry(self):
         from PandaObject import *
-        if self.node() != render.node():
+        node = self.node()
+        if ((node != render.node()) | (node != hidden.node())):
             ancestry = self.getParent().getAncestry()
             ancestry.append(self)
             return ancestry

+ 2 - 2
direct/src/ffi/generatePythonCode

@@ -14,10 +14,10 @@ Generates Python code for the C++ libraries listed.
 
 Example:
 Linux:
-  ppython -d generatePythonCode -v -d $DIRECT/lib/py -e $DIRECT/src/extensions -i libdtool libpandaexpress libpanda libdirect
+  ppython -d generatePythonCode -v -d $DIRECT/lib/py -e $DIRECT/src/extensions -i libdtool libpandaexpress libpanda libdirect libtoontown
 
 Windows:
-  ppython -d generatePythonCode -v -d `cygpath -w $DIRECT/lib/py` -e `cygpath -w $DIRECT/src/extensions` -i libdtool libpandaexpress libpanda libdirect
+  ppython -d generatePythonCode -v -d `cygpath -w $DIRECT/lib/py` -e `cygpath -w $DIRECT/src/extensions` -i libdtool libpandaexpress libpanda libdirect libtoontown
 
 
 Options:

File diff suppressed because it is too large
+ 262 - 574
direct/src/leveleditor/LevelEditor.py


+ 20 - 13
direct/src/leveleditor/PieMenu.py

@@ -4,28 +4,31 @@ from DirectGeometry import *
 class PieMenu(NodePath, PandaObject):
     def __init__(self, direct, menu, action = None, fUpdateOnlyOnChange = 1):
         NodePath.__init__(self)
-        # Become the menu
-        self.assign(menu)
+        # Create a toplevel node for aspect ratio scaling
+        self.assign(hidden.attachNewNode(NamedNode('PieMenu')))
+        # Attach the menu
+        self.menu = menu
+        self.menu.reparentTo(self)
         # Initialize instance variables
         self.direct = direct
-        self.numItems = self.getNumChildren()
+        self.numItems = self.menu.getNumChildren()
         self.degreesPerItem = 360.0/self.numItems
-        self.sfx = self.getSx()
-        self.sfz = self.getSz()
+        self.itemOffset = self.degreesPerItem / 2.0
+        self.sfx = self.menu.getSx()
+        self.sfz = self.menu.getSz()
         # Record target and action
         self.action = action
         self.initialState = None
         # Marking lines
-        self.lines = LineNodePath(self)
+        self.lines = LineNodePath(self.menu)
         self.lines.setColor(VBase4(1))
         self.lines.setThickness(1)
         # Set flags
         self.fUpdateOnlyOnChange = fUpdateOnlyOnChange
-        self.itemOffset = 0
 
     def performAction(self, value):
-        if action:
-            action(value)
+        if self.action:
+            self.action(value)
 
     def removePieMenuTask(self):
         taskMgr.removeTasksNamed('pieMenuTask')
@@ -43,7 +46,9 @@ class PieMenu(NodePath, PandaObject):
 	# Pop up menu
 	self.reparentTo(render2d)
 	self.setPos(self.originX,0.0,self.originY)
-
+        # Compensate for window aspect ratio
+        self.setScale(1.0, 1.0,1.0)
+        #self.direct.chan.width/float(self.direct.chan.height))
 	# Start drawing the selection line
 	self.lines.reset()
 	self.lines.moveTo(0,0,0)
@@ -62,7 +67,7 @@ class PieMenu(NodePath, PandaObject):
         deltaY = mouseY - self.originY
 
         # Update the line
-        self.lines.setVertex(1,(deltaX/sfx),0.0,(deltaY / sfz))
+        self.lines.setVertex(1,(deltaX/self.sfx),0.0,(deltaY/self.sfz))
 
         # How far from starting point has user moved the cursor?
         if ((abs(deltaX) < 0.1) & (abs(deltaY) < 0.1)):
@@ -74,15 +79,16 @@ class PieMenu(NodePath, PandaObject):
             else:
                 # Alway let use know mouse is in the center
                 self.performAction(-1)
-            
             self.currItem = -1
+        else:
+            # Outside of the center
             # Interacting with menu
             # subtract half a slice to effectively center item
             menuAngle = rad2Deg(math.atan2(deltaY, deltaX)) + self.itemOffset
             if menuAngle < 0.0:
                 menuAngle = menuAngle + 360.0
             menuAngle = menuAngle % 360.0
-            newItem = math.floor(menuAngle / self.degreesPerItem)
+            newItem = int(math.floor(menuAngle / self.degreesPerItem))
 
             if self.fUpdateOnlyOnChange:
                 if (self.currItem != newItem):
@@ -109,3 +115,4 @@ class PieMenu(NodePath, PandaObject):
 
     def setUpdateOnlyOnChange(self,flag):
 	self.fUpdateOnlyOnChange = flag
+

+ 232 - 97
direct/src/tkwidgets/Floater.py

@@ -1,87 +1,93 @@
-title = 'DIRECT Floater megawidget'
+"""
+Floater Class: Velocity style controller for floating point values with
+                a label, entry (validated), and scale
+"""
 
-import string
-import Tkinter 
+from Tkinter import *
 import Pmw
-
-OK = 1
-ERROR = 0
+import string
 
 class Floater(Pmw.MegaWidget):
-    """ Megawidget containing a label, an entry, and a scale.
-        Used as a velocity style controller for floating point values
-    """
+    "Velocity style floating point controller"
  
     def __init__(self, parent = None, **kw):
 
         # Define the megawidget options.
         optiondefs = (
-            ('command',           None,        None),
-            ('value',             0.0,         self._updateValue),
-            ('text',              '',          self._updateLabelText),
-            ('min',               None,        None),
-            ('max',               None,        None),
-            ('resolution',        None,        None),
-            ('maxVelocity',       100.0,       None),
-	    ('errorbackground',   'pink',      None),
-            ('significantDigits', 2,           self._setSigDigits),
+            ('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 base class (after defining options).
+        # Initialise superclass
         Pmw.MegaWidget.__init__(self, parent)
 
-        # Initialize some variables
-        self.value = 0.0
+        # Initialize some class variables
+        self.value = self['initialValue']
         self.velocity = 0.0
-        self.entryValue = Tkinter.StringVar()
         self.entryFormat = '%.2f'
-        self.normalBackground = None
 
         # Create the components.
+
+        # Setup up container
         interior = self.interior()
-        interior['relief'] = 'groove'
-        interior['borderwidth'] = 2
+        interior.configure(relief = GROOVE, borderwidth = 2)
 
-        self.infoFrame = self.createcomponent('frame',
-                                              (), None,
-                                              Tkinter.Frame, interior)
-        self.infoFrame.pack(expand = 1, fill = 'both')
- 
+        # 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,
-                                          Tkinter.Label, self.infoFrame,
+        self.label = self.createcomponent('label', (), None,
+                                          Label, self.labelFrame,
                                           text = self['text'],
-                                          anchor = 'center',
                                           width = 12,
+                                          anchor = 'center',
                                           font = "Arial 12 bold")
         self.label.pack(side='left', expand = 1, fill = 'x')
 
-        # Create an entry field to display and validate the floater's value
-        self.entry = self.createcomponent('entry',
-                                          (), None,
-                                          Tkinter.Entry, self.infoFrame,
-                                          width = 10,
-                                          justify = 'right',
-                                          textvar = self.entryValue)
-        self.entry.pack(side='left',padx = 4)
-        self.entry.bind('<Return>', self._entryCommand)
-                                          
+        # Now pack the frame
+        self.labelFrame.pack(expand = 1, fill = 'both')
+
         # Create the scale component.
-        self.scale = self.createcomponent('scale',
-                                          (), None,
-                                          Tkinter.Scale, interior,
+        self.scale = self.createcomponent('scale', (), None,
+                                          Scale, interior,
                                           command = self._scaleToVelocity,
                                           orient = 'horizontal',
                                           length = 150,
                                           from_ = -1.0,
                                           to = 1.0,
-                                          resolution = 0.01,
+                                          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)
-        # When interacting with mouse:
+        
+        # Add scale bindings: When interacting with mouse:
         self.scale.bind('<Button-1>', self._startFloaterTask)
         self.scale.bind('<ButtonRelease-1>', self._floaterReset)
         # In case you wish to interact using keys
@@ -90,17 +96,31 @@ class Floater(Pmw.MegaWidget):
         self.scale.bind('<KeyPress-Left>', self._floaterKeyCommand)
         self.scale.bind('<KeyRelease-Left>', self._floaterReset)
  
-        # Check keywords and initialise options.
+        # Check keywords and initialise options based on input values.
         self.initialiseoptions(Floater)
 
-        # Now that the widgets have been created, update significant digits
-        self._setSigDigits()
-        self._updateValue()
+    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)
-        # retain sign of velocity by only calling abs once
+        # Square val, but retain sign of velocity by only calling abs once
         self.velocity = self['maxVelocity'] * val * abs(val)
 
     def _startFloaterTask(self,event):
@@ -109,7 +129,7 @@ class Floater(Pmw.MegaWidget):
 
     def _floaterTask(self):
         if self.velocity != 0.0:
-            self.setValue( self.value + self.velocity )
+            self.set( self.value + self.velocity )
         if self._fFloaterTask:
             self.after(50, self._floaterTask)
 
@@ -120,90 +140,205 @@ class Floater(Pmw.MegaWidget):
 
     def _floaterKeyCommand(self, event):
         if self.velocity != 0.0:
-            self.setValue( self.value + self.velocity )
+            self.set( self.value + self.velocity )
 
     def _entryCommand(self, event = None):
         try:
             val = string.atof( self.entryValue.get() )
-            self.setValue( val )
+            self.set( val )
         except ValueError:
-            # invalid entry, ring bell set background to warning color
-            self.entry.bell()
-            if self.normalBackground is None:
-		self.normalBackground = self.entry.cget('background')
-		self.entry.configure( background = self['errorbackground'] )
-
-    def _updateValue(self):
-        self.setValue(self['value'])
-        
-    def setValue(self, newVal):
+            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 )
-        # Reset background
-        if self.normalBackground is not None:
-            self.entry.configure(background = self.normalBackground)
-            self.normalBackground = None
+        self.entry.checkentry()
+        
         # execute command
-        command = self['command']
-        if command is not None:
-            command( newVal )
+        if fCommand & (self['command'] is not None):
+            self['command']( newVal )
 
-    def _setSigDigits(self):
-        sd = self['significantDigits']
-        self.entryFormat = '%.' + '%d' % sd + 'f'
-        self.scale['resolution'] = 10 ** (-1.0 * sd)
-        # And reset value to reflect change
-        self.entryValue.set( self.entryFormat % self.value )
 
-    def _updateLabelText(self):
-        self.label['text'] = self['text']
+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'])
         
-Pmw.forwardmethods(Floater, Tkinter.Scale, 'scale')
+        # 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 = Pmw.initialise()
+    root = Toplevel()
     root.title('Pmw Floater demonstration')
 
     # Dummy command
     def printVal(val):
-        print `val`
+        print val
     
     # Create and pack a Floater megawidget.
-    mega1 = Floater(root)
+    mega1 = Floater(root, command = printVal)
     mega1.pack(side = 'left', expand = 1, fill = 'x')
 
+    """
     # These are things you can set/configure
-    mega1['command'] = printVal
+    # Starting value for floater    
+    mega1['initialValue'] = 123.456
     mega1['text'] = 'Drive delta X'
     mega1['min'] = 0.0
-    #mega1['max'] = 1000.0
+    mega1['max'] = 1000.0
     mega1['resolution'] = 1.0
-
-    # UNCOMMENT THESE TO CUSTOMIZE THE FLOATER
     # To change the color of the label:
-    # mega1.label['foreground'] = 'Red'
-    
+    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
+    """
 
-    # Starting value for floater
-    # mega1['value'] = 123.4557
-
-    # Let's go.
+    # 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()

Some files were not shown because too many files changed in this diff