Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
e5ab222f36

+ 8 - 20
direct/src/directtools/DirectCameraControl.py

@@ -15,7 +15,7 @@ class DirectCameraControl(PandaObject):
         self.coaMarker = loader.loadModel('models/misc/sphere')
         self.coaMarker = loader.loadModel('models/misc/sphere')
         self.coaMarker.setName('DirectCameraCOAMarker')
         self.coaMarker.setName('DirectCameraCOAMarker')
         self.coaMarker.setColor(1,0,0)
         self.coaMarker.setColor(1,0,0)
-        self.coaMarker.setPos(0,0,0)
+        self.coaMarker.setPos(0,100,0)
         useDirectRenderStyle(self.coaMarker)
         useDirectRenderStyle(self.coaMarker)
         self.coaMarkerPos = Point3(0)
         self.coaMarkerPos = Point3(0)
 	self.camManipRef = direct.group.attachNewNode('camManipRef')
 	self.camManipRef = direct.group.attachNewNode('camManipRef')
@@ -56,27 +56,15 @@ class DirectCameraControl(PandaObject):
             self.coaMarker.hide()
             self.coaMarker.hide()
             # Check for a hit point based on
             # Check for a hit point based on
             # current mouse position
             # current mouse position
+            # Allow intersection with unpickable objects
             # And then spawn task to determine mouse mode
             # And then spawn task to determine mouse mode
-            numEntries = direct.iRay.pickGeom(
-                render,direct.dr.mouseX,direct.dr.mouseY)
-            # Then filter out hidden nodes from entry list
-            indexList = []
-            for i in range(0,numEntries):
-                entry = direct.iRay.cq.getEntry(i)
-                node = entry.getIntoNode()
-                if node.isHidden():
-                    pass
-                else:
-                    # Not one of the widgets, use it
-                    indexList.append(i)
+            node, hitPt, hitPtDist = direct.iRay.pickGeom(
+                fIntersectUnpickable = 1)
             coa = Point3(0)
             coa = Point3(0)
-            if(indexList):
-                # Grab first point (it should be the closest)
-                minPt = indexList[0]
-                # Find hit point in camera's space
-                hitPt = direct.iRay.camToHitPt(minPt)
-                coa.set(hitPt[0],hitPt[1],hitPt[2])
-                coaDist = Vec3(coa - ZERO_POINT).length()
+            if node:
+                # Set center of action
+                coa.assign(hitPt)
+                coaDist = hitPtDist
                 # Handle case of bad coa point (too close or too far)
                 # Handle case of bad coa point (too close or too far)
                 if ((coaDist < (1.1 * direct.dr.near)) |
                 if ((coaDist < (1.1 * direct.dr.near)) |
                     (coaDist > direct.dr.far)):
                     (coaDist > direct.dr.far)):

+ 36 - 46
direct/src/directtools/DirectManipulation.py

@@ -2,8 +2,6 @@ from PandaObject import *
 from DirectGeometry import *
 from DirectGeometry import *
 
 
 MANIPULATION_MOVE_DELAY = 0.65
 MANIPULATION_MOVE_DELAY = 0.65
-UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
-              'GridBack']
 
 
 class DirectManipulationControl(PandaObject):
 class DirectManipulationControl(PandaObject):
     def __init__(self):
     def __init__(self):
@@ -24,7 +22,6 @@ class DirectManipulationControl(PandaObject):
         self.fWidgetTop = 0
         self.fWidgetTop = 0
         self.fFreeManip = 1
         self.fFreeManip = 1
         self.fScaling = 0
         self.fScaling = 0
-        self.unpickable = UNPICKABLE
         self.mode = None
         self.mode = None
         self.actionEvents = [
         self.actionEvents = [
             ['handleMouse1', self.manipulationStart],
             ['handleMouse1', self.manipulationStart],
@@ -35,26 +32,19 @@ class DirectManipulationControl(PandaObject):
             [',', self.objectHandles.multiplyScalingFactorBy, 0.5],
             [',', self.objectHandles.multiplyScalingFactorBy, 0.5],
             ['<', self.objectHandles.multiplyScalingFactorBy, 0.5],
             ['<', self.objectHandles.multiplyScalingFactorBy, 0.5],
             ['F', self.objectHandles.growToFit],
             ['F', self.objectHandles.growToFit],
+            ['p', self.plantSelectedNodePath],
             ]
             ]
 
 
     def manipulationStart(self):
     def manipulationStart(self):
         # Start out in select mode
         # Start out in select mode
         self.mode = 'select'
         self.mode = 'select'
         # Check for a widget hit point
         # Check for a widget hit point
-        numEntries = direct.iRay.pickWidget(
-            render,direct.dr.mouseX,direct.dr.mouseY)
+        node, hitPt, hitPtDist = direct.iRay.pickWidget()
         # Did we hit a widget?
         # Did we hit a widget?
-        if(numEntries):
+        if node:
             # Yes!
             # Yes!
-            # Entry 0 is the closest hit point if multiple hits
-            minPt = 0
-            # Find hit point in camera's space
-            self.hitPt = direct.iRay.camToHitPt(minPt)
-            self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length()
-            # Get the associated collision queue object
-            entry = direct.iRay.cq.getEntry(minPt)
-            # Extract the node
-            node = entry.getIntoNode()
+            self.hitPt.assign(hitPt)
+            self.hitPtDist = hitPtDist
             # Constraint determined by nodes name
             # Constraint determined by nodes name
             self.constraint = node.getName()
             self.constraint = node.getName()
         else:
         else:
@@ -97,32 +87,11 @@ class DirectManipulationControl(PandaObject):
         # depending on flag.....
         # depending on flag.....
         if self.mode == 'select':
         if self.mode == 'select':
             # Check for object under mouse
             # Check for object under mouse
-            numEntries = direct.iRay.pickGeom(
-                render,direct.dr.mouseX,direct.dr.mouseY)
-            # Pick out the closest object that isn't a widget
-            index = -1
-            for i in range(0,numEntries):
-                entry = direct.iRay.cq.getEntry(i)
-                node = entry.getIntoNode()
-                if node.isHidden():
-                    pass
-                # Is it a named node?, If so, see if it has a name
-                elif issubclass(node.__class__, NamedNode):
-                    name = node.getName()
-                    if name in self.unpickable:
-                        pass
-                    else:
-                        index = i
-                        break
-                else:
-                    # Not hidden and not one of the widgets, use it
-                    index = i
-            # Did we hit an object?
-            if(index >= 0):
-                # Yes!
-                # Find hit point in camera's space
-                self.hitPt = direct.iRay.camToHitPt(index)
-                self.hitPtDist = Vec3(self.hitPt - ZERO_POINT).length()
+            node, hitPt, hitPtDist = direct.iRay.pickGeom()
+            if node:
+                # Record hit point information
+                self.hitPt.assign(hitPt)
+                self.hitPtDist = hitPtDist
                 # Find the node path from the node found above
                 # Find the node path from the node found above
                 nodePath = render.findPathDownTo(node)
                 nodePath = render.findPathDownTo(node)
                 # Select it
                 # Select it
@@ -479,15 +448,32 @@ class DirectManipulationControl(PandaObject):
              self.initScaleMag)
              self.initScaleMag)
             )
             )
         direct.widget.setScale(currScale)
         direct.widget.setScale(currScale)
-        
+
+    ## Utility functions ##
+    def plantSelectedNodePath(self):
+	""" Move selected object to intersection point of cursor on scene """
+        # Check for intersection
+        node, hitPt, hitPtDist = direct.iRay.pickGeom(
+            fIntersectUnpickable = 1)
+        # MRM: Need to handle moving COA
+        if (node != None) & (direct.selected.last != None):
+            # Record undo point
+            direct.pushUndo(direct.selected)
+            # Record wrt matrix
+            direct.selected.getWrtAll()
+            # Move selected
+            direct.widget.setPos(direct.camera, hitPt)
+            # Move all the selected objects with widget
+            # Move the objects with the widget
+            direct.selected.moveWrtWidgetAll()
+            # Let everyone know that something was moved
+            messenger.send('manipulateObjectCleanup')
 
 
 class ObjectHandles(NodePath,PandaObject):
 class ObjectHandles(NodePath,PandaObject):
     def __init__(self):
     def __init__(self):
         # Initialize the superclass
         # Initialize the superclass
         NodePath.__init__(self)
         NodePath.__init__(self)
 
 
-        # Starts off deactivated
-        self.fActive = 0
         # Load up object handles model and assign it to self
         # Load up object handles model and assign it to self
         self.assign(loader.loadModel('models/misc/objectHandles'))
         self.assign(loader.loadModel('models/misc/objectHandles'))
         self.node().setName('objectHandles')
         self.node().setName('objectHandles')
@@ -540,6 +526,10 @@ class ObjectHandles(NodePath,PandaObject):
         self.createGuideLines()
         self.createGuideLines()
         self.hideGuides()
         self.hideGuides()
 
 
+        # Start with widget handles hidden
+        self.fActive = 1
+        self.toggleWidget()
+
         # Make sure object handles are never lit or drawn in wireframe
         # Make sure object handles are never lit or drawn in wireframe
         useDirectRenderStyle(self)
         useDirectRenderStyle(self)
 
 
@@ -551,10 +541,10 @@ class ObjectHandles(NodePath,PandaObject):
 
 
     def toggleWidget(self):
     def toggleWidget(self):
         if self.fActive:
         if self.fActive:
-            self.reparentTo(hidden)
+            self.scalingNode.reparentTo(hidden)
             self.fActive = 0
             self.fActive = 0
         else:
         else:
-            self.reparentTo(direct.group)
+            self.scalingNode.reparentTo(self)
             self.fActive = 1
             self.fActive = 1
 
 
     def showWidgetIfActive(self):
     def showWidgetIfActive(self):

+ 63 - 4
direct/src/directtools/DirectSelection.py

@@ -2,6 +2,9 @@ from PandaObject import *
 from DirectGeometry import *
 from DirectGeometry import *
 from DirectSelection import *
 from DirectSelection import *
 
 
+UNPICKABLE = ['x-disc-visible', 'y-disc-visible', 'z-disc-visible',
+              'GridBack']
+
 # MRM: To do: handle broken node paths in selected and deselected dicts
 # MRM: To do: handle broken node paths in selected and deselected dicts
 class DirectNodePath(NodePath):
 class DirectNodePath(NodePath):
     # A node path augmented with info, bounding box, and utility methods
     # A node path augmented with info, bounding box, and utility methods
@@ -394,14 +397,70 @@ class SelectionRay:
         self.ct = CollisionTraverser( RenderRelation.getClassType() )
         self.ct = CollisionTraverser( RenderRelation.getClassType() )
         # Let the traverser know about the queue and the collision node
         # Let the traverser know about the queue and the collision node
         self.ct.addCollider(self.rayCollisionNode, self.cq )
         self.ct.addCollider(self.rayCollisionNode, self.cq )
+        # List of objects that can't be selected
+        self.unpickable = UNPICKABLE
 
 
-    def pickGeom(self, targetNodePath, mouseX, mouseY):
+    def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0):
         self.collideWithGeom()
         self.collideWithGeom()
-        return self.pick(targetNodePath, mouseX, mouseY)
+        numEntries = self.pick(targetNodePath,
+                               direct.dr.mouseX,
+                               direct.dr.mouseY)
+        # Init index
+        index = -1
+        # Pick out the closest object that isn't a widget
+        for i in range(0,numEntries):
+            entry = direct.iRay.cq.getEntry(i)
+            node = entry.getIntoNode()
+            # Don't pick hidden nodes
+            if node.isHidden():
+                pass
+            # Can pick unpickable, use the first visible node
+            elif fIntersectUnpickable:
+                index = i
+                break
+            # Is it a named node?, If so, see if it has a name
+            elif issubclass(node.__class__, NamedNode):
+                name = node.getName()
+                if name in self.unpickable:
+                    pass
+                else:
+                    index = i
+                    break
+            # Not hidden and not one of the widgets, use it
+            else:
+                index = i
+                break
+        # Did we hit an object?
+        if(index >= 0):
+            # Yes!
+            # Find hit point in camera's space
+            hitPt = direct.iRay.camToHitPt(index)
+            hitPtDist = Vec3(hitPt - ZERO_POINT).length()
+            return (node, hitPt, hitPtDist)
+        else:
+            return (None, ZERO_POINT, 0)
 
 
-    def pickWidget(self, targetNodePath, mouseX, mouseY):
+    def pickWidget(self, targetNodePath = render):
         self.collideWithWidget()
         self.collideWithWidget()
-        return self.pick(targetNodePath, mouseX, mouseY)
+        numEntries = self.pick(targetNodePath,
+                               direct.dr.mouseX,
+                               direct.dr.mouseY)
+        # Did we hit a widget?
+        if numEntries:
+            # Yes!
+            # Entry 0 is the closest hit point if multiple hits
+            minPt = 0
+            # Find hit point in camera's space
+            hitPt = direct.iRay.camToHitPt(minPt)
+            hitPtDist = Vec3(hitPt).length()
+            # Get the associated collision queue object
+            entry = direct.iRay.cq.getEntry(minPt)
+            # Extract the node
+            node = entry.getIntoNode()
+            # Return info
+            return (node, hitPt, hitPtDist)
+        else:
+            return (None, ZERO_POINT, 0)
 
 
     def pick(self, targetNodePath, mouseX, mouseY):
     def pick(self, targetNodePath, mouseX, mouseY):
         # Determine ray direction based upon the mouse coordinates
         # Determine ray direction based upon the mouse coordinates

+ 4 - 4
direct/src/directtools/DirectSession.py

@@ -79,9 +79,8 @@ class DirectSession(PandaObject):
             ['SGENodePath_Delete', self.removeNodePath],
             ['SGENodePath_Delete', self.removeNodePath],
             ]
             ]
         self.keyEvents = ['left', 'right', 'up', 'down',
         self.keyEvents = ['left', 'right', 'up', 'down',
-                          'escape', 'space', 'delete',
+                          'escape', 'delete', 'control', 'control-up',
                           'shift', 'shift-up', 'alt', 'alt-up',
                           'shift', 'shift-up', 'alt', 'alt-up',
-                          'control', 'control-up',
                           'page_up', 'page_down', 'tab',
                           'page_up', 'page_down', 'tab',
                           '[', '{', ']', '}',
                           '[', '{', ']', '}',
                           'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
                           'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
@@ -213,8 +212,8 @@ class DirectSession(PandaObject):
         elif (input == ']') | (input == '}'):
         elif (input == ']') | (input == '}'):
             self.redo()
             self.redo()
         
         
-    def select(self, nodePath, fMultiselect = 0, fResetAncestry = 1):
-        dnp = self.selected.select(nodePath, fMultiselect)
+    def select(self, nodePath, fMultiSelect = 0, fResetAncestry = 1):
+        dnp = self.selected.select(nodePath, fMultiSelect)
         if dnp:
         if dnp:
             messenger.send('preSelectNodePath', [dnp])
             messenger.send('preSelectNodePath', [dnp])
             if fResetAncestry:
             if fResetAncestry:
@@ -465,6 +464,7 @@ class DirectSession(PandaObject):
     # UTILITY FUNCTIONS
     # UTILITY FUNCTIONS
     def useObjectHandles(self):
     def useObjectHandles(self):
         self.widget = self.manipulationControl.objectHandles
         self.widget = self.manipulationControl.objectHandles
+        self.widget.reparentTo(direct.group)
 
 
     def hideReadout(self):
     def hideReadout(self):
 	self.readout.reparentTo(hidden)
 	self.readout.reparentTo(hidden)

+ 2 - 0
direct/src/ffi/FFIRename.py

@@ -60,6 +60,7 @@ classRenameDictionary = {
     'LVecBase2f'                : 'VBase2',
     'LVecBase2f'                : 'VBase2',
     'LVector2f'                 : 'Vec2',
     'LVector2f'                 : 'Vec2',
     'LPoint2f'                  : 'Point2',
     'LPoint2f'                  : 'Point2',
+    'LQuaternionf'              : 'Quat',
     'LMatrix4d'                 : 'Mat4D',
     'LMatrix4d'                 : 'Mat4D',
     'LMatrix3d'                 : 'Mat3D',
     'LMatrix3d'                 : 'Mat3D',
     'LVecBase4d'                : 'VBase4D',
     'LVecBase4d'                : 'VBase4D',
@@ -71,6 +72,7 @@ classRenameDictionary = {
     'LVecBase2d'                : 'VBase2D',
     'LVecBase2d'                : 'VBase2D',
     'LVector2d'                 : 'Vec2D',
     'LVector2d'                 : 'Vec2D',
     'LPoint2d'                  : 'Point2D',
     'LPoint2d'                  : 'Point2D',
+    'LQuaterniond'              : 'QuatD',
     'Plane'                     : 'PlaneBase',
     'Plane'                     : 'PlaneBase',
     'Planef'                    : 'Plane',
     'Planef'                    : 'Plane',
     'Planed'                    : 'PlaneD',
     'Planed'                    : 'PlaneD',

+ 73 - 33
direct/src/tkpanels/ParticlePanel.py

@@ -59,23 +59,23 @@ class ParticlePanel(AppShell):
         ## SYSTEM PAGE ##
         ## SYSTEM PAGE ##
         # Create system floaters
         # Create system floaters
         systemFloaterDefs = (
         systemFloaterDefs = (
-            ('System Pool size',
+            ('System Pool Size',
              'Size of particle pool',
              'Size of particle pool',
              self.setSystemPoolSize,
              self.setSystemPoolSize,
              1.0, 1.0),
              1.0, 1.0),
-            ('System Birth rate',
+            ('System Birth Rate',
              'Seconds between particle births',
              'Seconds between particle births',
              self.setSystemBirthRate,
              self.setSystemBirthRate,
              0.0, None),
              0.0, None),
-            ('System Litter size',
+            ('System Litter Size',
              'Number of particle created at each birth',
              'Number of particle created at each birth',
              self.setSystemLitterSize,
              self.setSystemLitterSize,
              1.0, 1.0),
              1.0, 1.0),
-            ('System Litter spread',
+            ('System Litter Spread',
              'Variation in litter size',
              'Variation in litter size',
              self.setSystemLitterSpread,
              self.setSystemLitterSpread,
              0.0, 1.0),
              0.0, 1.0),
-            ('System lifespan',
+            ('System Lifespan',
              'Age in seconds at which system should die',
              'Age in seconds at which system should die',
              self.setSystemLifespan,
              self.setSystemLifespan,
              0.0, None)
              0.0, None)
@@ -83,17 +83,17 @@ class ParticlePanel(AppShell):
         self.createFloaters(systemPage, systemFloaterDefs)
         self.createFloaters(systemPage, systemFloaterDefs)
         # Checkboxes
         # Checkboxes
         self.systemLocalVelocity = self.createCheckbutton(
         self.systemLocalVelocity = self.createCheckbutton(
-            systemPage, 'Local velocity',
+            systemPage, 'System Local Velocity',
             self.toggleSystemLocalVelocity, 0)
             self.toggleSystemLocalVelocity, 0)
         self.systemGrowsOlder = self.createCheckbutton(
         self.systemGrowsOlder = self.createCheckbutton(
-            systemPage, 'System grows older', 
+            systemPage, 'System Grows Older', 
             self.toggleSystemGrowsOlder, 0)
             self.toggleSystemGrowsOlder, 0)
         # Vector widgets
         # Vector widgets
-        pos = self.createVector3Entry(systemPage, 'Pos',
+        pos = self.createVector3Entry(systemPage, 'System Pos',
                                       'Particle system position',
                                       'Particle system position',
                                       command = self.setSystemPos)
                                       command = self.setSystemPos)
         pos.addMenuItem('Popup Placer Panel', Placer.Placer)
         pos.addMenuItem('Popup Placer Panel', Placer.Placer)
-        hpr = self.createVector3Entry(systemPage, 'Hpr',
+        hpr = self.createVector3Entry(systemPage, 'System Hpr',
                                      'Particle system orientation',
                                      'Particle system orientation',
                                       fGroup_labels = ('H', 'P', 'R'),
                                       fGroup_labels = ('H', 'P', 'R'),
                                       command = self.setSystemHpr)
                                       command = self.setSystemHpr)
@@ -107,27 +107,27 @@ class ParticlePanel(AppShell):
             ('Point', 'Z Spin', 'Oriented'),
             ('Point', 'Z Spin', 'Oriented'),
             self.selectFactoryType)
             self.selectFactoryType)
         factoryWidgets = (
         factoryWidgets = (
-            ('Life span',
+            ('Factory Life Span',
              'Average lifespan in seconds',
              'Average lifespan in seconds',
              self.setFactoryLifeSpan,
              self.setFactoryLifeSpan,
              0.0, None),
              0.0, None),
-            ('Life span spread',
+            ('Factory Life Span Spread',
              'Variation in lifespan',
              'Variation in lifespan',
              self.setFactoryLifeSpanSpread,
              self.setFactoryLifeSpanSpread,
              0.0, None),
              0.0, None),
-            ('Mass',
+            ('Factory Mass',
              'Average particle mass',
              'Average particle mass',
              self.setFactoryParticleMass,
              self.setFactoryParticleMass,
              0.0, None),
              0.0, None),
-            ('Mass spread',
+            ('Factory Mass Spread',
              'Variation in particle mass',
              'Variation in particle mass',
              self.setFactoryParticleMassSpread,
              self.setFactoryParticleMassSpread,
              0.0, None),
              0.0, None),
-            ('Terminal velocity',
+            ('Factory Terminal Velocity',
              'Average particle terminal velocity',
              'Average particle terminal velocity',
              self.setFactoryTerminalVelocity,
              self.setFactoryTerminalVelocity,
              0.0, None),
              0.0, None),
-            ('Terminal vel. spread',
+            ('Factory Terminal Vel. Spread',
              'Variation in terminal velocity',
              'Variation in terminal velocity',
              self.setFactoryTerminalVelocitySpread,
              self.setFactoryTerminalVelocitySpread,
              0.0, None))
              0.0, None))
@@ -138,13 +138,13 @@ class ParticlePanel(AppShell):
         factoryPointPage = self.factoryNotebook.add('Point')
         factoryPointPage = self.factoryNotebook.add('Point')
         # Z spin page #
         # Z spin page #
         zSpinPage = self.factoryNotebook.add('Z Spin')
         zSpinPage = self.factoryNotebook.add('Z Spin')
-        self.createAngleDial(zSpinPage, 'Initial angle',
+        self.createAngleDial(zSpinPage, 'Z Spin Initial Angle',
                              'Starting angle in degrees',
                              'Starting angle in degrees',
                              command = self.setFactoryZSpinInitialAngle)
                              command = self.setFactoryZSpinInitialAngle)
-        self.createAngleDial(zSpinPage, 'Final angle',
+        self.createAngleDial(zSpinPage, 'Z Spin Final Angle',
                              'Final angle in degrees',
                              'Final angle in degrees',
                              command = self.setFactoryZSpinFinalAngle)
                              command = self.setFactoryZSpinFinalAngle)
-        self.createAngleDial(zSpinPage, 'Angle spread',
+        self.createAngleDial(zSpinPage, 'Z Spin Angle Spread',
                              'Spread of the final angle',
                              'Spread of the final angle',
                              command = self.setFactoryZSpinAngleSpread)
                              command = self.setFactoryZSpinAngleSpread)
         # Oriented page #
         # Oriented page #
@@ -164,18 +164,19 @@ class ParticlePanel(AppShell):
         self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
         self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
         # Box page #
         # Box page #
         boxPage = self.emitterNotebook.add('Box')
         boxPage = self.emitterNotebook.add('Box')
-        self.createVector3Entry(boxPage, 'Point 1',
-                               'Point defining emitter box',
+        self.createVector3Entry(boxPage, 'Box Emitter Min',
+                                'Min point defining emitter box',
                                 command = self.setEmitterBoxPoint1)
                                 command = self.setEmitterBoxPoint1)
-        self.createVector3Entry(boxPage, 'Point 2',
-                               'Point defining emitter box',
+        self.createVector3Entry(boxPage, 'Box Emitter Max',
+                                'Max point defining emitter box',
                                 command = self.setEmitterBoxPoint2,
                                 command = self.setEmitterBoxPoint2,
                                 initialValue = (1.0, 1.0, 1.0))
                                 initialValue = (1.0, 1.0, 1.0))
         self.createVector3Entry(boxPage, 'Velocity vector',
         self.createVector3Entry(boxPage, 'Velocity vector',
-                               'Initial particle velocity vector',
+                                'Initial particle velocity vector',
                                 command = self.setEmitterBoxVelocityVector)
                                 command = self.setEmitterBoxVelocityVector)
         # Disc page #
         # Disc page #
         discPage = self.emitterNotebook.add('Disc')
         discPage = self.emitterNotebook.add('Disc')
+        self.emitter
         self.createFloater(discPage, 'Radius', 'Radius of disc',
         self.createFloater(discPage, 'Radius', 'Radius of disc',
                            command = self.setEmitterDiscRadius)
                            command = self.setEmitterDiscRadius)
         self.createAngleDial(discPage, 'Inner angle',
         self.createAngleDial(discPage, 'Inner angle',
@@ -195,23 +196,24 @@ class ParticlePanel(AppShell):
             self.toggleEmitterDiscCubicLerping, 0)
             self.toggleEmitterDiscCubicLerping, 0)
         # Line page #
         # Line page #
         linePage = self.emitterNotebook.add('Line')
         linePage = self.emitterNotebook.add('Line')
-        self.createVector3Entry(linePage, 'Point 1',
-                               'Point defining emitter line',
+        self.createVector3Entry(linePage, 'Line Emitter Min',
+                                'Min point defining emitter line',
                                 command = self.setEmitterLinePoint1)
                                 command = self.setEmitterLinePoint1)
-        self.createVector3Entry(linePage, 'Point 2',
-                               'Point defining emitter line',
+        self.createVector3Entry(linePage, 'Line Emitter Max',
+                                'Max point defining emitter line',
                                 command = self.setEmitterLinePoint2,
                                 command = self.setEmitterLinePoint2,
                                 initialValue = (1.0, 0.0, 0.0))
                                 initialValue = (1.0, 0.0, 0.0))
-        self.createVector3Entry(linePage, 'Velocity Vector',
+        self.createVector3Entry(linePage, 'Line Emitter Velocity',
                                'Initial particle velocity vector',
                                'Initial particle velocity vector',
                                 command = self.setEmitterLineVelocityVector,
                                 command = self.setEmitterLineVelocityVector,
                                 initialValue = (0.0, 0.0, 1.0))
                                 initialValue = (0.0, 0.0, 1.0))
         # Point page #
         # Point page #
         emitterPointPage = self.emitterNotebook.add('Point')
         emitterPointPage = self.emitterNotebook.add('Point')
-        self.createVector3Entry(emitterPointPage, 'Position',
+        self.createVector3Entry(emitterPointPage, 'Point Emitter Position',
                                'Position of emitter point',
                                'Position of emitter point',
                                 command = self.setEmitterPointPosition)
                                 command = self.setEmitterPointPosition)
-        self.createVector3Entry(emitterPointPage, 'Velocity vector',
+        self.createVector3Entry(emitterPointPage,
+                                'Point Emitter Velocity',
                                'Initial particle velocity vector',
                                'Initial particle velocity vector',
                                 command = self.setEmitterPointVelocityVector,
                                 command = self.setEmitterPointVelocityVector,
                                 initialValue = (0.0, 0.0, 1.0))
                                 initialValue = (0.0, 0.0, 1.0))
@@ -374,11 +376,12 @@ class ParticlePanel(AppShell):
     def createCheckbutton(self, parent, text, command, initialState):
     def createCheckbutton(self, parent, text, command, initialState):
         bool = BooleanVar()
         bool = BooleanVar()
         bool.set(initialState)
         bool.set(initialState)
-        cb = Checkbutton(parent, text = text, anchor = W,
+        widget = Checkbutton(parent, text = text, anchor = W,
                          variable = bool)
                          variable = bool)
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation
-        cb.command = command
-        cb.pack(fill = X)
+        widget['command'] = command
+        widget.pack(fill = X)
+        self.widgetDict['text'] = widget
         return bool
         return bool
         
         
     def createFloaters(self, parent, widgetDefinitions):
     def createFloaters(self, parent, widgetDefinitions):
@@ -412,6 +415,7 @@ class ParticlePanel(AppShell):
         widget['command'] = command
         widget['command'] = command
         widget.pack(fill = X)
         widget.pack(fill = X)
         self.bind(widget, balloonHelp)
         self.bind(widget, balloonHelp)
+        self.widgetDict['text'] = widget
         return widget
         return widget
 
 
     def createVector3Entry(self, parent, text, balloonHelp,
     def createVector3Entry(self, parent, text, balloonHelp,
@@ -423,6 +427,7 @@ class ParticlePanel(AppShell):
         widget['command'] = command
         widget['command'] = command
         widget.pack(fill = X)
         widget.pack(fill = X)
         self.bind(widget, balloonHelp)
         self.bind(widget, balloonHelp)
+        self.widgetDict['text'] = widget
         return widget
         return widget
 
 
     def createColorEntry(self, parent, text, balloonHelp,
     def createColorEntry(self, parent, text, balloonHelp,
@@ -434,6 +439,7 @@ class ParticlePanel(AppShell):
         widget['command'] = command
         widget['command'] = command
         widget.pack(fill = X)
         widget.pack(fill = X)
         self.bind(widget, balloonHelp)
         self.bind(widget, balloonHelp)
+        self.widgetDict['text'] = widget
         return widget
         return widget
 
 
     def createOptionMenu(self, parent, text, balloonHelp, items, command):
     def createOptionMenu(self, parent, text, balloonHelp, items, command):
@@ -447,6 +453,7 @@ class ParticlePanel(AppShell):
         widget['command'] = command
         widget['command'] = command
         widget.pack(fill = X)
         widget.pack(fill = X)
         self.bind(widget.component('menubutton'), balloonHelp)
         self.bind(widget.component('menubutton'), balloonHelp)
+        self.widgetDict['text'] = widget
         return optionVar
         return optionVar
 
 
     ### PARTICLE SYSTEM COMMANDS ###
     ### PARTICLE SYSTEM COMMANDS ###
@@ -500,6 +507,39 @@ class ParticlePanel(AppShell):
     def selectEmitterType(self, type):
     def selectEmitterType(self, type):
         self.emitterNotebook.selectpage(type)
         self.emitterNotebook.selectpage(type)
 	self.particles.setEmitter(type)
 	self.particles.setEmitter(type)
+        self.updateEmitterWidgets()
+        
+    def updateEmitterWidgets(self):
+        emitter = self.particles.emitter
+        if isinstance(emitter, BoxEmitter):
+            min = emitter.getMinBound()
+            self.emitterBoxPoint1VectorEntry.set(
+                [min[0], min[1], min[2]])
+            max = emitter.getMaxBound()
+            self.emitterBoxPoint2VectorEntry.set(
+                [max[0], max[1], max[2]])
+        elif isinstance(emitter, DiscEmitter):
+            radius = emitter.getRadius()
+            cubicLerping = emitter.getCubicLerping()
+            innerAngle = emitter.getInnerAngle()
+            getInnerMagnitude
+            getOuterAngle    
+            getOuterMagnitude
+        elif isinstance(emitter, LineEmitter):
+            pass
+        elif isinstance(emitter, PointEmitter):
+            pass
+        elif isinstance(emitter, RectangleEmitter):
+            pass
+        elif isinstance(emitter, RingEmitter):
+            pass
+        elif isinstance(emitter, SphereVolumeEmitter):
+            pass
+        elif isinstance(emitter, SphereSurfaceEmitter):
+            pass
+        elif isinstance(emitter, TangentRingEmitter):
+            pass
+        
     # Box #
     # Box #
     def setEmitterBoxPoint1(self, point):
     def setEmitterBoxPoint1(self, point):
 	self.particles.emitter.setMinBound(Point3(point[0],
 	self.particles.emitter.setMinBound(Point3(point[0],

+ 30 - 11
direct/src/tkpanels/Placer.py

@@ -64,6 +64,7 @@ class Placer(AppShell):
         self.initPos = Vec3(0)
         self.initPos = Vec3(0)
         self.initHpr = Vec3(0)
         self.initHpr = Vec3(0)
         self.initScale = Vec3(1)
         self.initScale = Vec3(1)
+        self.deltaHpr = Vec3(0)
 
 
         # Offset for orbital mode
         # Offset for orbital mode
         self.posOffset = Vec3(0)
         self.posOffset = Vec3(0)
@@ -450,7 +451,7 @@ class Placer(AppShell):
             else:
             else:
                 if name == 'widget':
                 if name == 'widget':
                     # Record relationship between selected nodes and widget
                     # Record relationship between selected nodes and widget
-                    direct.selected.getWrtAll()
+                    direct.selected.getWrtAll()                    
         # Update active node path
         # Update active node path
         self.setActiveNodePath(nodePath)
         self.setActiveNodePath(nodePath)
 
 
@@ -459,10 +460,19 @@ class Placer(AppShell):
         if self['nodePath']:
         if self['nodePath']:
             self.nodePathMenuEntry.configure(
             self.nodePathMenuEntry.configure(
                 background = self.nodePathMenuBG)
                 background = self.nodePathMenuBG)
+            # Check to see if node path and ref node path are the same
+            if ((self.refCS != None) &
+                (self.refCS.id() == self['nodePath'].id())):
+                # Yes they are, use temp CS as ref
+                # This calls updatePlacer
+                self.setReferenceNodePath(self.tempCS)
+                # update listbox accordingly
+                self.refNodePathMenu.selectitem('self')
+            else:
+                # Record initial value and initialize the widgets
+                self.updatePlacer()
             # Record initial position
             # Record initial position
             self.updateResetValues(self['nodePath'])
             self.updateResetValues(self['nodePath'])
-            # Record initial value and initialize the widgets
-            self.updatePlacer()
         else:
         else:
             # Flash entry
             # Flash entry
             self.nodePathMenuEntry.configure(background = 'Pink')
             self.nodePathMenuEntry.configure(background = 'Pink')
@@ -494,7 +504,12 @@ class Placer(AppShell):
                     # Clear bogus entry from listbox
                     # Clear bogus entry from listbox
                     listbox = self.refNodePathMenu.component('scrolledlist')
                     listbox = self.refNodePathMenu.component('scrolledlist')
                     listbox.setlist(self.refNodePathNames)
                     listbox.setlist(self.refNodePathNames)
-        # Update ref node path accordingly
+        # Check to see if node path and ref node path are the same
+        if (nodePath != None) & (nodePath.id() == self['nodePath'].id()):
+            # Yes they are, use temp CS and update listbox accordingly
+            nodePath = self.tempCS
+            self.refNodePathMenu.selectitem('self')
+        # Update ref node path
         self.setReferenceNodePath(nodePath)
         self.setReferenceNodePath(nodePath)
 
 
     def setReferenceNodePath(self, nodePath):
     def setReferenceNodePath(self, nodePath):
@@ -594,6 +609,8 @@ class Placer(AppShell):
             taskMgr.removeTasksNamed('followSelectedNodePath')
             taskMgr.removeTasksNamed('followSelectedNodePath')
             # Record relationship between selected nodes and widget
             # Record relationship between selected nodes and widget
             direct.selected.getWrtAll()
             direct.selected.getWrtAll()
+        # Record initial state
+        self.deltaHpr = self['nodePath'].getHpr(self.refCS)
         # Update placer to reflect new state
         # Update placer to reflect new state
         self.updatePlacer()
         self.updatePlacer()
         
         
@@ -609,7 +626,6 @@ class Placer(AppShell):
 
 
     def xformRelative(self, value, axis):
     def xformRelative(self, value, axis):
         nodePath = self['nodePath']
         nodePath = self['nodePath']
-        
         if (nodePath != None) & (self.refCS != None):
         if (nodePath != None) & (self.refCS != None):
             if axis == 'x':
             if axis == 'x':
                 nodePath.setX(self.refCS, value)
                 nodePath.setX(self.refCS, value)
@@ -617,12 +633,15 @@ class Placer(AppShell):
                 nodePath.setY(self.refCS, value)
                 nodePath.setY(self.refCS, value)
             elif axis == 'z':
             elif axis == 'z':
                 nodePath.setZ(self.refCS, value)
                 nodePath.setZ(self.refCS, value)
-            elif axis == 'h':
-                nodePath.setH(self.refCS, value)
-            elif axis == 'p':
-                nodePath.setP(self.refCS, value)
-            elif axis == 'r':
-                nodePath.setR(self.refCS, value)
+            else:
+                if axis == 'h':
+                    self.deltaHpr.setX(value)
+                elif axis == 'p':
+                    self.deltaHpr.setY(value)
+                elif axis == 'r':
+                    self.deltaHpr.setZ(value)
+                # Put node path at new hpr
+                nodePath.setHpr(self.refCS, self.deltaHpr)
 
 
     def xformOrbit(self, value, axis):
     def xformOrbit(self, value, axis):
         nodePath = self['nodePath']
         nodePath = self['nodePath']

+ 4 - 4
direct/src/tkwidgets/VectorWidgets.py

@@ -163,11 +163,11 @@ class VectorEntry(Pmw.MegaWidget):
     def getAt(self,index):
     def getAt(self,index):
         return self._value[index]
         return self._value[index]
                                                                                       
                                                                                       
-    def set(self, value):
+    def set(self, value, fCommand = 0):
         for i in range(self['dim']):
         for i in range(self['dim']):
             self._value[i] = value[i]
             self._value[i] = value[i]
             self.variableList[i].set(self.entryFormat % value[i])
             self.variableList[i].set(self.entryFormat % value[i])
-        self.action()
+        self.action(fCommand)
 
 
     def setAt(self, index, value):
     def setAt(self, index, value):
         self.variableList[index].set(self.entryFormat % value)
         self.variableList[index].set(self.entryFormat % value)
@@ -207,9 +207,9 @@ class VectorEntry(Pmw.MegaWidget):
         if self._floaters:
         if self._floaters:
             self._floaters.set(self._value, 0)
             self._floaters.set(self._value, 0)
         
         
-    def action(self):
+    def action(self, fCommand = 0):
         self._refreshFloaters()
         self._refreshFloaters()
-        if self['command']:
+        if fCommand & (self['command'] != None):
             self['command'](self._value)        
             self['command'](self._value)        
         
         
     def reset(self):
     def reset(self):