Browse Source

*** empty log message ***

Mark Mine 25 years ago
parent
commit
be68df86d3

+ 5 - 7
direct/src/directtools/DirectCameraControl.py

@@ -1,7 +1,7 @@
 from PandaObject import *
 from PandaObject import *
 from DirectGeometry import *
 from DirectGeometry import *
 
 
-CAM_MOVE_DURATION = 1.0
+CAM_MOVE_DURATION = 1.2
 COA_MARKER_SF = 0.0075
 COA_MARKER_SF = 0.0075
 Y_AXIS = Vec3(0,1,0)
 Y_AXIS = Vec3(0,1,0)
 
 
@@ -454,12 +454,10 @@ class DirectCameraControl(PandaObject):
         direct.camera.wrtReparentTo(state.parent)
         direct.camera.wrtReparentTo(state.parent)
         self.updateCoaMarkerSize()
         self.updateCoaMarkerSize()
 
 
-    def fitOnWidget(self):
+    def fitOnWidget(self, nodePath = 'None Given'):
         # Fit the node on the screen
         # Fit the node on the screen
-        
         # stop any ongoing tasks
         # stop any ongoing tasks
         taskMgr.removeTasksNamed('manipulateCamera')
         taskMgr.removeTasksNamed('manipulateCamera')
-
         # How big is the node?
         # How big is the node?
         nodeScale = direct.widget.scalingNode.getScale(render)
         nodeScale = direct.widget.scalingNode.getScale(render)
         maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
         maxScale = max(nodeScale[0],nodeScale[1],nodeScale[2])
@@ -484,9 +482,9 @@ class DirectCameraControl(PandaObject):
 	parent = direct.camera.getParent()
 	parent = direct.camera.getParent()
 	direct.camera.wrtReparentTo(self.camManipRef)
 	direct.camera.wrtReparentTo(self.camManipRef)
 	fitTask = direct.camera.lerpPos(Point3(0,0,0),
 	fitTask = direct.camera.lerpPos(Point3(0,0,0),
-                                      CAM_MOVE_DURATION,
-                                      blendType = 'easeInOut',
-                                      task = 'manipulateCamera')
+                                        CAM_MOVE_DURATION,
+                                        blendType = 'easeInOut',
+                                        task = 'manipulateCamera')
         # Upon death, reparent Cam to parent
         # Upon death, reparent Cam to parent
         fitTask.parent = parent
         fitTask.parent = parent
         fitTask.uponDeath = self.reparentCam                                
         fitTask.uponDeath = self.reparentCam                                

+ 0 - 8
direct/src/directtools/DirectManipulation.py

@@ -147,14 +147,6 @@ class DirectManipulationControl(PandaObject):
         for event in self.actionEvents:
         for event in self.actionEvents:
             self.ignore(event[0])
             self.ignore(event[0])
 
 
-    def addUnpickable(self, item):
-        if item not in self.unpickable:
-            self.unpickable.append(item)
-
-    def removeUnpickable(self, item):
-        if item in self.unpickable:
-            self.unpickable.remove(item)
-
     def toggleObjectHandlesMode(self):
     def toggleObjectHandlesMode(self):
         self.fSetCoa = 1 - self.fSetCoa
         self.fSetCoa = 1 - self.fSetCoa
         if self.fSetCoa:
         if self.fSetCoa:

+ 8 - 0
direct/src/directtools/DirectSelection.py

@@ -400,6 +400,14 @@ class SelectionRay:
         # List of objects that can't be selected
         # List of objects that can't be selected
         self.unpickable = UNPICKABLE
         self.unpickable = UNPICKABLE
 
 
+    def addUnpickable(self, item):
+        if item not in self.unpickable:
+            self.unpickable.append(item)
+
+    def removeUnpickable(self, item):
+        if item in self.unpickable:
+            self.unpickable.remove(item)
+
     def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0):
     def pickGeom(self, targetNodePath = render, fIntersectUnpickable = 0):
         self.collideWithGeom()
         self.collideWithGeom()
         numEntries = self.pick(targetNodePath,
         numEntries = self.pick(targetNodePath,

+ 21 - 1
direct/src/directtools/DirectSession.py

@@ -21,6 +21,7 @@ class DirectSession(PandaObject):
         __builtin__.direct = self
         __builtin__.direct = self
         self.fEnabled = 0
         self.fEnabled = 0
         self.drList = DisplayRegionList()
         self.drList = DisplayRegionList()
+        self.iRayList = map(lambda x: x.iRay, self.drList)
         self.dr = self.drList[0]
         self.dr = self.drList[0]
         self.camera = self.dr.camera
         self.camera = self.dr.camera
         self.iRay = self.dr.iRay
         self.iRay = self.dr.iRay
@@ -79,6 +80,7 @@ class DirectSession(PandaObject):
             ['SGENodePath_Isolate', self.isolate],
             ['SGENodePath_Isolate', self.isolate],
             ['SGENodePath_Toggle Vis', self.toggleVis],
             ['SGENodePath_Toggle Vis', self.toggleVis],
             ['SGENodePath_Show All', self.showAllDescendants],
             ['SGENodePath_Show All', self.showAllDescendants],
+            ['SGENodePath_Fit', self.fitOnNodePath],
             ['SGENodePath_Place', Placer.place],
             ['SGENodePath_Place', Placer.place],
             ['SGENodePath_Delete', self.removeNodePath],
             ['SGENodePath_Delete', self.removeNodePath],
             ]
             ]
@@ -87,7 +89,7 @@ class DirectSession(PandaObject):
                           'shift', 'shift-up', 'alt', 'alt-up',
                           'shift', 'shift-up', 'alt', 'alt-up',
                           'page_up', 'page_down', 'tab',
                           'page_up', 'page_down', 'tab',
                           '[', '{', ']', '}',
                           '[', '{', ']', '}',
-                          'b', 'c', 'f', 'l', 's', 't', 'v', 'w']
+                          'b', 'l', 's', 't', 'v', 'w']
         self.mouseEvents = ['mouse1', 'mouse1-up',
         self.mouseEvents = ['mouse1', 'mouse1-up',
                             'mouse2', 'mouse2-up',
                             'mouse2', 'mouse2-up',
                             'mouse3', 'mouse3-up']
                             'mouse3', 'mouse3-up']
@@ -329,6 +331,16 @@ class DirectSession(PandaObject):
         else:
         else:
             state.nodePath.clearColor()
             state.nodePath.clearColor()
 
 
+    def fitOnNodePath(self, nodePath = 'None Given'):
+        if nodePath == 'None Given':
+            # If nothing specified, try selected node path
+            nodePath = self.selected.last
+        direct.select(nodePath)
+        def fitTask(state, self = self):
+            self.cameraControl.fitOnWidget()
+            return Task.done
+        taskMgr.doMethodLater(0.1, fitTask, 'manipulateCamera')
+
     def isolate(self, nodePath = 'None Given'):
     def isolate(self, nodePath = 'None Given'):
         """ Show a node path and hide its siblings """
         """ Show a node path and hide its siblings """
         # First kill the flashing task to avoid complications
         # First kill the flashing task to avoid complications
@@ -490,6 +502,14 @@ class DirectSession(PandaObject):
     def isEnabled(self):
     def isEnabled(self):
         return self.fEnabled
         return self.fEnabled
 
 
+    def addUnpickable(self, item):
+        for iRay in self.iRayList:
+            iRay.addUnpickable(item)
+
+    def removeUnpickable(self, item):
+        for iRay in self.iRayList:
+            iRay.removeUnpickable(item)
+
 class DisplayRegionList:
 class DisplayRegionList:
     def __init__(self):
     def __init__(self):
         self.displayRegionList = []
         self.displayRegionList = []

+ 2 - 3
direct/src/leveleditor/LevelEditor.py

@@ -1297,7 +1297,7 @@ class LevelEditor(NodePath, PandaObject):
 	map.setColor(Vec4(1,1,1,.4))
 	map.setColor(Vec4(1,1,1,.4))
         self.mapDictionary[neighborhood] = map
         self.mapDictionary[neighborhood] = map
         # Make sure this item isn't pickable
         # Make sure this item isn't pickable
-        direct.manipulationControl.addUnpickable(neighborhood + '_layout')
+        direct.addUnpickable(neighborhood + '_layout')
 
 
     def selectMap(self, neighborhood):
     def selectMap(self, neighborhood):
         if self.activeMap:
         if self.activeMap:
@@ -1408,7 +1408,7 @@ class LevelEditor(NodePath, PandaObject):
 	if ((abs(handlesToCam[0]) > (direct.dr.nearWidth * 0.4)) |
 	if ((abs(handlesToCam[0]) > (direct.dr.nearWidth * 0.4)) |
             (abs(handlesToCam[2]) > (direct.dr.nearHeight * 0.4))):
             (abs(handlesToCam[2]) > (direct.dr.nearHeight * 0.4))):
             taskMgr.removeTasksNamed('manipulateCamera')
             taskMgr.removeTasksNamed('manipulateCamera')
-            direct.cameraControl.centerCamIn(direct.dr, 0.5)
+            direct.cameraControl.centerCamIn(0.5)
 
 
     def autoPositionCleanup(self,state):
     def autoPositionCleanup(self,state):
         direct.grid.setPosHpr(state.selectedNode, state.deltaPos,
         direct.grid.setPosHpr(state.selectedNode, state.deltaPos,
@@ -2910,7 +2910,6 @@ class LevelEditorPanel(Pmw.MegaToplevel):
 
 
         self.sceneGraphExplorer = SceneGraphExplorer(
         self.sceneGraphExplorer = SceneGraphExplorer(
             parent = sceneGraphPage,
             parent = sceneGraphPage,
-            root = self.levelEditor,
             menuItems = ['Set Parent', 'Reparent', 'Add Group',
             menuItems = ['Set Parent', 'Reparent', 'Add Group',
                          'Add Vis Group', 'Set Color',
                          'Add Vis Group', 'Set Color',
                          'Set Name'])
                          'Set Name'])

+ 1 - 1
direct/src/showbase/Particles.py

@@ -111,7 +111,7 @@ class Particles(ParticleSystem.ParticleSystem):
 	    self.renderer = SparkleParticleRenderer.SparkleParticleRenderer()
 	    self.renderer = SparkleParticleRenderer.SparkleParticleRenderer()
 	elif (type == "SpriteParticleRenderer"):
 	elif (type == "SpriteParticleRenderer"):
 	    self.renderer = SpriteParticleRenderer.SpriteParticleRenderer()
 	    self.renderer = SpriteParticleRenderer.SpriteParticleRenderer()
-	    t = loader.loadTexture("I:/beta/toons/install/maps/evil_eye.rgb")
+	    t = loader.loadTexture('phase_3/maps/eyes.jpg')
 	    if (t == None):
 	    if (t == None):
 		print "Couldn't find default texture: evil_eye.rgb!"
 		print "Couldn't find default texture: evil_eye.rgb!"
 		return None
 		return None

+ 10 - 1
direct/src/task/Task.py

@@ -43,6 +43,10 @@ def doLater(delayTime, task, taskName):
     # make a sequence out of the delay and the task
     # make a sequence out of the delay and the task
     seq = sequence(pause(delayTime), task)
     seq = sequence(pause(delayTime), task)
     return seq
     return seq
+
+def spawnMethodNamed(self, func, name):
+        task = Task(func)
+        self.spawnTaskNamed(task, name)
     
     
 def pause(delayTime):
 def pause(delayTime):
     def func(self):
     def func(self):
@@ -192,7 +196,7 @@ class TaskManager:
 
 
     def spawnMethodNamed(self, func, name):
     def spawnMethodNamed(self, func, name):
         task = Task(func)
         task = Task(func)
-        self.spawnTaskNamed(task, name)
+        return self.spawnTaskNamed(task, name)
         
         
     def spawnTaskNamed(self, task, name):
     def spawnTaskNamed(self, task, name):
         TaskManager.notify.debug('spawning task named: ' + name)
         TaskManager.notify.debug('spawning task named: ' + name)
@@ -201,6 +205,11 @@ class TaskManager:
         self.taskList.append(task)
         self.taskList.append(task)
         return task
         return task
 
 
+    def doMethodLater(self, delayTime, func, taskName):
+        task = Task(func)
+        seq = doLater(delayTime, task, taskName)
+        return self.spawnTaskNamed(seq, 'doLater-' + taskName)
+
     def removeAllTasks(self):
     def removeAllTasks(self):
         # Make a shallow copy so we do not modify the list in place
         # Make a shallow copy so we do not modify the list in place
         taskListCopy = self.taskList[:]
         taskListCopy = self.taskList[:]

+ 237 - 61
direct/src/tkpanels/ParticlePanel.py

@@ -6,6 +6,7 @@ from Tkinter import *
 import Pmw
 import Pmw
 import Dial
 import Dial
 import Floater
 import Floater
+import EntryScale
 import VectorWidgets
 import VectorWidgets
 import Placer
 import Placer
 import Particles
 import Particles
@@ -14,9 +15,10 @@ class ParticlePanel(AppShell):
     # Override class variables
     # Override class variables
     appname = 'Particle Panel'
     appname = 'Particle Panel'
     frameWidth  = 400
     frameWidth  = 400
-    frameHeight = 600
+    frameHeight = 660
     usecommandarea = 0
     usecommandarea = 0
     usestatusarea  = 0
     usestatusarea  = 0
+    balloonState = 'both'
     
     
     def __init__(self, particles, **kw):
     def __init__(self, particles, **kw):
         INITOPT = Pmw.INITOPT
         INITOPT = Pmw.INITOPT
@@ -42,6 +44,13 @@ class ParticlePanel(AppShell):
         # Handle to the toplevels hull
         # Handle to the toplevels hull
         interior = self.interior()
         interior = self.interior()
 
 
+        self.menuBar.addmenu('Particles', 'Particle Panel Operations')
+        self.menuBar.addmenuitem(
+            'Particles', 'command',
+            'Print Particle System Parameters',
+            label = 'Print Params',
+            command = lambda s = self: s.particles.printParams())
+
         # Combo box to switch between particle systems
         # Combo box to switch between particle systems
         self.systemSelector = Pmw.ComboBox(self.menuFrame,
         self.systemSelector = Pmw.ComboBox(self.menuFrame,
                                      labelpos = W,
                                      labelpos = W,
@@ -52,6 +61,11 @@ class ParticlePanel(AppShell):
         self.systemSelector.selectitem('system 0')
         self.systemSelector.selectitem('system 0')
         self.systemSelector.pack(side = 'left', expand = 0)
         self.systemSelector.pack(side = 'left', expand = 0)
 
 
+        self.systemActive = self.createCheckbutton(
+            self.menuFrame, 'System', 'Active',
+            'Turn particle systems on/off',
+            self.toggleParticleSystem, 1)
+
         # Create the notebook pages
         # Create the notebook pages
         self.mainNotebook = Pmw.NoteBook(interior)
         self.mainNotebook = Pmw.NoteBook(interior)
         self.mainNotebook.pack(fill = BOTH, expand = 1)
         self.mainNotebook.pack(fill = BOTH, expand = 1)
@@ -66,7 +80,7 @@ class ParticlePanel(AppShell):
         # Create system floaters
         # Create system floaters
         systemFloaterDefs = (
         systemFloaterDefs = (
             ('System', 'Pool Size',
             ('System', 'Pool Size',
-             'Size of particle pool',
+             'Max number of simultaneous particles',
              self.setSystemPoolSize,
              self.setSystemPoolSize,
              1.0, 1.0),
              1.0, 1.0),
             ('System', 'Birth Rate',
             ('System', 'Birth Rate',
@@ -82,7 +96,7 @@ class ParticlePanel(AppShell):
              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 the system (vs. particles) should die',
              self.setSystemLifespan,
              self.setSystemLifespan,
              0.0, None)
              0.0, None)
             )
             )
@@ -90,9 +104,11 @@ class ParticlePanel(AppShell):
         # Checkboxes
         # Checkboxes
         self.systemLocalVelocity = self.createCheckbutton(
         self.systemLocalVelocity = self.createCheckbutton(
             systemPage, 'System', 'Local Velocity',
             systemPage, 'System', 'Local Velocity',
+            'On: velocities are absolute; Off: velocities are relative',
             self.toggleSystemLocalVelocity, 0)
             self.toggleSystemLocalVelocity, 0)
         self.systemGrowsOlder = self.createCheckbutton(
         self.systemGrowsOlder = self.createCheckbutton(
-            systemPage, 'System', 'Grows Older', 
+            systemPage, 'System', 'Grows Older',
+            'On: system has a lifespan',
             self.toggleSystemGrowsOlder, 0)
             self.toggleSystemGrowsOlder, 0)
         # Vector widgets
         # Vector widgets
         pos = self.createVector3Entry(systemPage, 'System', 'Pos',
         pos = self.createVector3Entry(systemPage, 'System', 'Pos',
@@ -115,7 +131,7 @@ class ParticlePanel(AppShell):
             self.selectFactoryType)
             self.selectFactoryType)
         factoryWidgets = (
         factoryWidgets = (
             ('Factory', 'Life Span',
             ('Factory', 'Life Span',
-             'Average lifespan in seconds',
+             'Average particle lifespan in seconds',
              self.setFactoryLifeSpan,
              self.setFactoryLifeSpan,
              0.0, None),
              0.0, None),
             ('Factory', 'Life Span Spread',
             ('Factory', 'Life Span Spread',
@@ -131,7 +147,7 @@ class ParticlePanel(AppShell):
              self.setFactoryParticleMassSpread,
              self.setFactoryParticleMassSpread,
              0.0, None),
              0.0, None),
             ('Factory', 'Terminal Velocity',
             ('Factory', 'Terminal Velocity',
-             'Average particle terminal velocity',
+             'Cap on average particle velocity',
              self.setFactoryTerminalVelocity,
              self.setFactoryTerminalVelocity,
              0.0, None),
              0.0, None),
             ('Factory', 'Terminal Vel. Spread',
             ('Factory', 'Terminal Vel. Spread',
@@ -143,23 +159,29 @@ class ParticlePanel(AppShell):
         self.factoryNotebook = Pmw.NoteBook(factoryPage, tabpos = None)
         self.factoryNotebook = Pmw.NoteBook(factoryPage, tabpos = None)
         # Point page #
         # Point page #
         factoryPointPage = self.factoryNotebook.add('PointParticleFactory')
         factoryPointPage = self.factoryNotebook.add('PointParticleFactory')
-        Label(factoryPointPage, text = "").pack()
         # Z spin page #
         # Z spin page #
         zSpinPage = self.factoryNotebook.add('ZSpinParticleFactory')
         zSpinPage = self.factoryNotebook.add('ZSpinParticleFactory')
         self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
         self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
                              'Starting angle in degrees',
                              'Starting angle in degrees',
                              command = self.setFactoryZSpinInitialAngle)
                              command = self.setFactoryZSpinInitialAngle)
+        self.createAngleDial(
+            zSpinPage, 'Z Spin Factory',
+            'Initial Angle Spread',
+            'Spread of the initial angle',
+            command = self.setFactoryZSpinInitialAngleSpread)
         self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Final Angle',
         self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Final Angle',
                              'Final angle in degrees',
                              'Final angle in degrees',
                              command = self.setFactoryZSpinFinalAngle)
                              command = self.setFactoryZSpinFinalAngle)
-        self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Angle Spread',
-                             'Spread of the final angle',
-                             command = self.setFactoryZSpinAngleSpread)
+        self.createAngleDial(
+            zSpinPage, 'Z Spin Factory',
+            'Final Angle Spread',
+            'Spread of the final angle',
+            command = self.setFactoryZSpinFinalAngleSpread)
         # Oriented page #
         # Oriented page #
         orientedPage = self.factoryNotebook.add('OrientedParticleFactory')
         orientedPage = self.factoryNotebook.add('OrientedParticleFactory')
         Label(orientedPage, text = 'Not implemented').pack(expand = 1,
         Label(orientedPage, text = 'Not implemented').pack(expand = 1,
                                                            fill = BOTH)
                                                            fill = BOTH)
-        #self.factoryNotebook.pack(expand = 1, fill = BOTH)
+        self.factoryNotebook.pack(expand = 1, fill = BOTH)
 
 
         ## EMITTER PAGE ##
         ## EMITTER PAGE ##
         self.emitterTypeMenu = self.createOptionMenu(
         self.emitterTypeMenu = self.createOptionMenu(
@@ -170,6 +192,57 @@ class ParticlePanel(AppShell):
              'RectangleEmitter', 'RingEmitter', 'SphereVolumeEmitter',
              'RectangleEmitter', 'RingEmitter', 'SphereVolumeEmitter',
              'SphereSurfaceEmitter', 'TangentRingEmitter'),
              'SphereSurfaceEmitter', 'TangentRingEmitter'),
             self.selectEmitterType)
             self.selectEmitterType)
+
+        # Emitter modes
+        self.emissionType = StringVar()
+        self.emissionType.set('ETCUSTOM')
+        emissionFrame = Frame(emitterPage)
+        self.createRadiobutton(
+            emissionFrame, 'left',
+            'Emitter', 'Explicit Emission',
+            'particles are all emitted in parallel, in the same direction',
+            self.emissionType, BaseParticleEmitter.ETEXPLICIT,
+            self.setEmissionType)
+        self.createRadiobutton(
+            emissionFrame, 'left',
+            'Emitter', 'Radiate Emission',
+            'particles are emitted away from a specific point',
+            self.emissionType, BaseParticleEmitter.ETRADIATE,
+            self.setEmissionType)
+        self.createRadiobutton(
+            emissionFrame, 'left',
+            'Emitter', 'Custom Emission',
+            ('particles are emitted with a velocity that ' +
+             'is determined by the particular emitter'),
+            self.emissionType, BaseParticleEmitter.ETCUSTOM,
+            self.setEmissionType)
+        emissionFrame.pack(fill = 'x', expand = 0)
+        
+        self.createFloater(
+            emitterPage, 'Emitter', 'Velocity Amplitude',
+            'launch velocity multiplier (all emission modes)',
+            command = self.setEmitterAmplitude,
+            min = None)
+        
+        self.createFloater(
+            emitterPage, 'Emitter', 'Velocity Amplitude Spread',
+            'spread for launch velocity multiplier (all emission modes)',
+            command = self.setEmitterAmplitudeSpread)
+        
+        self.createVector3Entry(
+            emitterPage, 'Emitter', 'Offset Force',
+            'Velocity vector applied to all particles',
+            command = self.setEmitterOffsetForce)
+        
+        self.createVector3Entry(
+            emitterPage, 'Emitter', 'Radiate Origin',
+            'particles launch away from this point in Radiate mode',
+            command = self.setEmitterRadiateOrigin)
+        
+        self.createVector3Entry(
+            emitterPage, 'Emitter', 'Explicit Launch Vector',
+            'all particles launch with this velocity in Explicit mode',
+            command = self.setEmitterExplicitLaunchVector)
         
         
         self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
         self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
         # Box page #
         # Box page #
@@ -181,14 +254,12 @@ class ParticlePanel(AppShell):
                                 'Max point defining emitter box',
                                 '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, 'Box Emitter', 'Velocity vector',
-                                'Initial particle velocity vector',
-                                command = self.setEmitterBoxVelocityVector)
         # Disc page #
         # Disc page #
         discPage = self.emitterNotebook.add('DiscEmitter')
         discPage = self.emitterNotebook.add('DiscEmitter')
         self.createFloater(discPage, 'Disc Emitter', 'Radius',
         self.createFloater(discPage, 'Disc Emitter', 'Radius',
                            'Radius of disc',
                            'Radius of disc',
-                           command = self.setEmitterDiscRadius)
+                           command = self.setEmitterDiscRadius,
+                           min = 0.01)
         self.createAngleDial(discPage, 'Disc Emitter', 'Inner Angle',
         self.createAngleDial(discPage, 'Disc Emitter', 'Inner Angle',
                              'Particle launch angle at center of disc',
                              'Particle launch angle at center of disc',
                              command = self.setEmitterDiscInnerAngle)
                              command = self.setEmitterDiscInnerAngle)
@@ -203,6 +274,7 @@ class ParticlePanel(AppShell):
                            command = self.setEmitterDiscOuterVelocity)
                            command = self.setEmitterDiscOuterVelocity)
         self.emitterDiscCubicLerping = self.createCheckbutton(
         self.emitterDiscCubicLerping = self.createCheckbutton(
             discPage, 'Disc Emitter', 'Cubic Lerping',
             discPage, 'Disc Emitter', 'Cubic Lerping',
+            'On: magnitude/angle interpolation from center',
             self.toggleEmitterDiscCubicLerping, 0)
             self.toggleEmitterDiscCubicLerping, 0)
         # Line page #
         # Line page #
         linePage = self.emitterNotebook.add('LineEmitter')
         linePage = self.emitterNotebook.add('LineEmitter')
@@ -213,20 +285,11 @@ class ParticlePanel(AppShell):
                                 'Max point defining emitter line',
                                 '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, 'Line Emitter', 'Velocity',
-                               'Initial particle velocity vector',
-                                command = self.setEmitterLineVelocityVector,
-                                initialValue = (0.0, 0.0, 1.0))
         # Point page #
         # Point page #
         emitterPointPage = self.emitterNotebook.add('PointEmitter')
         emitterPointPage = self.emitterNotebook.add('PointEmitter')
         self.createVector3Entry(emitterPointPage, 'Point Emitter', 'Position',
         self.createVector3Entry(emitterPointPage, 'Point Emitter', 'Position',
                                'Position of emitter point',
                                'Position of emitter point',
                                 command = self.setEmitterPointPosition)
                                 command = self.setEmitterPointPosition)
-        self.createVector3Entry(emitterPointPage,
-                                'Point Emitter', 'Velocity',
-                               'Initial particle velocity vector',
-                                command = self.setEmitterPointVelocityVector,
-                                initialValue = (0.0, 0.0, 1.0))
         # Rectangle #
         # Rectangle #
         rectanglePage = self.emitterNotebook.add('RectangleEmitter')
         rectanglePage = self.emitterNotebook.add('RectangleEmitter')
         self.createVector2Entry(rectanglePage,
         self.createVector2Entry(rectanglePage,
@@ -237,38 +300,34 @@ class ParticlePanel(AppShell):
                                 'Rectangle Emitter', 'Max',
                                 'Rectangle Emitter', 'Max',
                                'Point defining rectangle',
                                'Point defining rectangle',
                                 command = self.setEmitterRectanglePoint2)
                                 command = self.setEmitterRectanglePoint2)
-        self.createVector3Entry(
-            rectanglePage, 'Rectangle Emitter', 'Velocity Vector',
-            'Initial particle velocity vector',
-            command = self.setEmitterRectangleVelocityVector,
-            initialValue = (0.0, 0.0, 1.0))
         # Ring #
         # Ring #
         ringPage = self.emitterNotebook.add('RingEmitter')
         ringPage = self.emitterNotebook.add('RingEmitter')
         self.createFloater(ringPage, 'Ring Emitter', 'Radius',
         self.createFloater(ringPage, 'Ring Emitter', 'Radius',
                            'Radius of ring',
                            'Radius of ring',
-                           command = self.setEmitterRingRadius)
+                           command = self.setEmitterRingRadius,
+                           min = 0.01)
         self.createAngleDial(ringPage, 'Ring Emitter', 'Angle',
         self.createAngleDial(ringPage, 'Ring Emitter', 'Angle',
                              'Particle launch angle',
                              'Particle launch angle',
                              command = self.setEmitterRingLaunchAngle)
                              command = self.setEmitterRingLaunchAngle)
-        self.createFloater(ringPage, 'Ring Emitter', 'Magnitude',
-                           'Launch velocity multiplier at outer edge of ring',
-                           command = self.setEmitterRingVelocityMultiplier)
         # Sphere volume #
         # Sphere volume #
         sphereVolumePage = self.emitterNotebook.add('SphereVolumeEmitter')
         sphereVolumePage = self.emitterNotebook.add('SphereVolumeEmitter')
         self.createFloater(sphereVolumePage, 'Sphere Volume Emitter', 'Radius',
         self.createFloater(sphereVolumePage, 'Sphere Volume Emitter', 'Radius',
                            'Radius of sphere',
                            'Radius of sphere',
-                           command = self.setEmitterSphereVolumeRadius)
+                           command = self.setEmitterSphereVolumeRadius,
+                           min = 0.01)
         # Sphere surface #
         # Sphere surface #
         sphereSurfacePage = self.emitterNotebook.add('SphereSurfaceEmitter')
         sphereSurfacePage = self.emitterNotebook.add('SphereSurfaceEmitter')
         self.createFloater(sphereSurfacePage, 'Sphere Surface Emitter',
         self.createFloater(sphereSurfacePage, 'Sphere Surface Emitter',
                            'Radius',
                            'Radius',
                            'Radius of sphere',
                            'Radius of sphere',
-                           command = self.setEmitterSphereSurfaceRadius)
+                           command = self.setEmitterSphereSurfaceRadius,
+                           min = 0.01)
         # Tangent ring # 
         # Tangent ring # 
         tangentRingPage = self.emitterNotebook.add('TangentRingEmitter')
         tangentRingPage = self.emitterNotebook.add('TangentRingEmitter')
         self.createFloater(tangentRingPage, 'Tangent Ring Emitter', 'Radius',
         self.createFloater(tangentRingPage, 'Tangent Ring Emitter', 'Radius',
                            'Radius of ring',
                            'Radius of ring',
-                           command = self.setEmitterTangentRingRadius)
+                           command = self.setEmitterTangentRingRadius,
+                           min = 0.01)
         self.emitterNotebook.pack(fill = X)
         self.emitterNotebook.pack(fill = X)
 
 
         ## RENDERER PAGE ##
         ## RENDERER PAGE ##
@@ -279,6 +338,18 @@ class ParticlePanel(AppShell):
              'PointParticleRenderer', 'SparkleParticleRenderer',
              'PointParticleRenderer', 'SparkleParticleRenderer',
              'SpriteParticleRenderer'),
              'SpriteParticleRenderer'),
             self.selectRendererType)
             self.selectRendererType)
+
+        self.createOptionMenu(rendererPage,
+                              'Renderer', 'Alpha Mode',
+                              "alpha setting over particles' lifetime",
+                              ('NO_ALPHA','ALPHA_OUT','ALPHA_IN','ALPHA_USER'),
+                              self.setRendererAlphaMode)
+        
+        self.createEntryScale(
+            rendererPage, 'Renderer', 'User Alpha',
+            'alpha value for ALPHA_USER alpha mode',
+            command = self.setRendererUserAlpha)
+        
         self.rendererNotebook = Pmw.NoteBook(rendererPage, tabpos = None)
         self.rendererNotebook = Pmw.NoteBook(rendererPage, tabpos = None)
 	# Line page #
 	# Line page #
 	linePage = self.rendererNotebook.add('LineParticleRenderer')
 	linePage = self.rendererNotebook.add('LineParticleRenderer')
@@ -353,6 +424,7 @@ class ParticlePanel(AppShell):
         f.pack(fill = X)
         f.pack(fill = X)
         Label(f, width = 12, text = 'Texture').pack(side = LEFT)
         Label(f, width = 12, text = 'Texture').pack(side = LEFT)
         self.rendererSpriteTexture = StringVar()
         self.rendererSpriteTexture = StringVar()
+        self.rendererSpriteTexture.set('phase_3/maps/eyes.jpg')
         self.rendererSpriteTextureEntry = Entry(
         self.rendererSpriteTextureEntry = Entry(
             f, width = 12,
             f, width = 12,
             textvariable = self.rendererSpriteTexture)
             textvariable = self.rendererSpriteTexture)
@@ -362,12 +434,18 @@ class ParticlePanel(AppShell):
             side = LEFT, expand = 1, fill = X)
             side = LEFT, expand = 1, fill = X)
         self.rendererSpriteXScale = self.createCheckbutton(
         self.rendererSpriteXScale = self.createCheckbutton(
             spritePage, 'Sprite Renderer', 'X Scale',
             spritePage, 'Sprite Renderer', 'X Scale',
+            ("On: x scale is interpolated over particle's life; " +
+             "Off: stays as start_X_Scale"),
             self.toggleRendererSpriteXScale, 0)
             self.toggleRendererSpriteXScale, 0)
         self.rendererSpriteYScale = self.createCheckbutton(
         self.rendererSpriteYScale = self.createCheckbutton(
             spritePage, 'Sprite Renderer', 'Y Scale',
             spritePage, 'Sprite Renderer', 'Y Scale',
+            ("On: y scale is interpolated over particle's life; " +
+             "Off: stays as start_Y_Scale"),
             self.toggleRendererSpriteYScale, 0)
             self.toggleRendererSpriteYScale, 0)
         self.rendererSpriteAnimAngle = self.createCheckbutton(
         self.rendererSpriteAnimAngle = self.createCheckbutton(
             spritePage, 'Sprite Renderer', 'Anim Angle',
             spritePage, 'Sprite Renderer', 'Anim Angle',
+            ("On: particles that are set to spin on the Z axis will " +
+             "spin appropriately"),
             self.toggleRendererSpriteAnimAngle, 0)
             self.toggleRendererSpriteAnimAngle, 0)
         self.createFloater(spritePage, 'Sprite Renderer',
         self.createFloater(spritePage, 'Sprite Renderer',
                            'Initial X Scale',
                            'Initial X Scale',
@@ -375,7 +453,7 @@ class ParticlePanel(AppShell):
                            command = self.setRendererSpriteInitialXScale)
                            command = self.setRendererSpriteInitialXScale)
         self.createFloater(spritePage, 'Sprite Renderer',
         self.createFloater(spritePage, 'Sprite Renderer',
                            'Final X Scale',
                            'Final X Scale',
-                           'Final X scaling factor',
+                           'Final X scaling factor, if xScale enabled',
                            command = self.setRendererSpriteFinalXScale)
                            command = self.setRendererSpriteFinalXScale)
         self.createFloater(spritePage, 'Sprite Renderer',
         self.createFloater(spritePage, 'Sprite Renderer',
                            'Initial Y Scale',
                            'Initial Y Scale',
@@ -383,11 +461,12 @@ class ParticlePanel(AppShell):
                            command = self.setRendererSpriteInitialYScale)
                            command = self.setRendererSpriteInitialYScale)
         self.createFloater(spritePage, 'Sprite Renderer',
         self.createFloater(spritePage, 'Sprite Renderer',
                            'Final Y Scale',
                            'Final Y Scale',
-                           'Final Y scaling factor',
+                           'Final Y scaling factor, if yScale enabled',
                            command = self.setRendererSpriteFinalYScale)
                            command = self.setRendererSpriteFinalYScale)
         self.createAngleDial(spritePage, 'Sprite Renderer',
         self.createAngleDial(spritePage, 'Sprite Renderer',
                              'Non Animated Theta',
                              'Non Animated Theta',
-                             'Counter clockwise Z rotation of all sprites',
+                             ('If animAngle is false: counter clockwise ' +
+                              'Z rotation of all sprites'),
                              command = self.setRendererSpriteNonAnimatedTheta)
                              command = self.setRendererSpriteNonAnimatedTheta)
         self.createOptionMenu(spritePage, 'Sprite Renderer',
         self.createOptionMenu(spritePage, 'Sprite Renderer',
                               'Blend Type',
                               'Blend Type',
@@ -396,6 +475,7 @@ class ParticlePanel(AppShell):
                               self.setRendererSpriteBlendMethod)
                               self.setRendererSpriteBlendMethod)
         self.rendererSpriteAlphaDisable = self.createCheckbutton(
         self.rendererSpriteAlphaDisable = self.createCheckbutton(
             spritePage, 'Sprite Renderer', 'Alpha Disable',
             spritePage, 'Sprite Renderer', 'Alpha Disable',
+            'On: alpha blending is disabled',
             self.toggleRendererSpriteAlphaDisable, 0)
             self.toggleRendererSpriteAlphaDisable, 0)
         self.rendererNotebook.pack(fill = X)
         self.rendererNotebook.pack(fill = X)
         
         
@@ -408,7 +488,8 @@ class ParticlePanel(AppShell):
         self.initialiseoptions(ParticlePanel)
         self.initialiseoptions(ParticlePanel)
 
 
     ### WIDGET UTILITY FUNCTIONS ###
     ### WIDGET UTILITY FUNCTIONS ###
-    def createCheckbutton(self, parent, category, text, command, initialState):
+    def createCheckbutton(self, parent, category, text,
+                          balloonHelp, command, initialState):
         bool = BooleanVar()
         bool = BooleanVar()
         bool.set(initialState)
         bool.set(initialState)
         widget = Checkbutton(parent, text = text, anchor = W,
         widget = Checkbutton(parent, text = text, anchor = W,
@@ -416,9 +497,22 @@ class ParticlePanel(AppShell):
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation
         widget['command'] = command
         widget['command'] = command
         widget.pack(fill = X)
         widget.pack(fill = X)
+        self.bind(widget, balloonHelp)
         self.widgetDict[category + '-' + text] = widget
         self.widgetDict[category + '-' + text] = widget
         return bool
         return bool
         
         
+    def createRadiobutton(self, parent, side, category, text,
+                          balloonHelp, variable, value,
+                          command):
+        widget = Radiobutton(parent, text = text, anchor = W,
+                             variable = variable, value = value)
+        # Do this after the widget so command isn't called on creation
+        widget['command'] = command
+        widget.pack(side = side, fill = X)
+        self.bind(widget, balloonHelp)
+        self.widgetDict[category + '-' + text] = widget
+        return widget
+        
     def createFloaters(self, parent, widgetDefinitions):
     def createFloaters(self, parent, widgetDefinitions):
         widgets = []
         widgets = []
         for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
         for category, label, balloonHelp, command, min, resolution in widgetDefinitions:
@@ -432,7 +526,10 @@ class ParticlePanel(AppShell):
                       command = None, min = 0.0, resolution = None, **kw):
                       command = None, min = 0.0, resolution = None, **kw):
         kw['text'] = text
         kw['text'] = text
         kw['min'] = min
         kw['min'] = min
-        kw['initialValue'] = min
+        if min != None:
+            kw['initialValue'] = min
+        else:
+            kw['initialValue'] = 0.0
         kw['resolution'] = resolution
         kw['resolution'] = resolution
         widget = apply(Floater.Floater, (parent,), kw)
         widget = apply(Floater.Floater, (parent,), kw)
         # Do this after the widget so command isn't called on creation
         # Do this after the widget so command isn't called on creation
@@ -453,6 +550,22 @@ class ParticlePanel(AppShell):
         self.widgetDict[category + '-' + text] = widget
         self.widgetDict[category + '-' + text] = widget
         return widget
         return widget
 
 
+    def createEntryScale(self, parent, category, text, balloonHelp,
+                         command = None, min = 0.0, max = 1.0,
+                         resolution = None, **kw):
+        kw['text'] = text
+        kw['min'] = min
+        kw['max'] = max
+        kw['initialValue'] = min
+        kw['resolution'] = resolution
+        widget = apply(EntryScale.EntryScale, (parent,), kw)
+        # Do this after the widget so command isn't called on creation
+        widget['command'] = command
+        widget.pack(fill = X)
+        self.bind(widget, balloonHelp)
+        self.widgetDict[category + '-' + text] = widget
+        return widget
+
     def createVector2Entry(self, parent, category, text, balloonHelp,
     def createVector2Entry(self, parent, category, text, balloonHelp,
                            command = None, **kw):
                            command = None, **kw):
         # Set label's text
         # Set label's text
@@ -520,6 +633,12 @@ class ParticlePanel(AppShell):
         elif page == 'Renderer':
         elif page == 'Renderer':
             self.selectRendererPage()
             self.selectRendererPage()
             self.updateRendererWidgets()
             self.updateRendererWidgets()
+
+    def toggleParticleSystem(self):
+        if self.systemActive.get():
+            self.particles.start()
+        else:
+            self.particles.stop()
             
             
     ## SYSTEM PAGE ##
     ## SYSTEM PAGE ##
     def updateSystemWidgets(self):
     def updateSystemWidgets(self):
@@ -599,9 +718,11 @@ class ParticlePanel(AppShell):
     # Z Spin Page #
     # Z Spin Page #
     def setFactoryZSpinInitialAngle(self, angle):
     def setFactoryZSpinInitialAngle(self, angle):
 	self.particles.factory.setInitialAngle(angle)
 	self.particles.factory.setInitialAngle(angle)
+    def setFactoryZSpinInitialAngleSpread(self, spread):
+	self.particles.factory.setInitialAngleSpread(spread)
     def setFactoryZSpinFinalAngle(self, angle):
     def setFactoryZSpinFinalAngle(self, angle):
 	self.particles.factory.setFinaleAngle(angle)
 	self.particles.factory.setFinaleAngle(angle)
-    def setFactoryZSpinAngleSpread(self, spread):
+    def setFactoryZSpinFinalAngleSpread(self, spread):
 	self.particles.factory.setInitialAngleSpread(spread)
 	self.particles.factory.setInitialAngleSpread(spread)
 
 
     ## EMITTER PAGE ##
     ## EMITTER PAGE ##
@@ -617,6 +738,20 @@ class ParticlePanel(AppShell):
         
         
     def updateEmitterWidgets(self):
     def updateEmitterWidgets(self):
         emitter = self.particles.emitter
         emitter = self.particles.emitter
+        self.emissionType.set(self.particles.emitter.getEmissionType())
+        amp = emitter.getAmplitude()
+        self.getWidget('Emitter', 'Velocity Amplitude').set(amp)
+        spread = emitter.getAmplitudeSpread()
+        self.getWidget('Emitter', 'Velocity Amplitude Spread').set(spread)
+        vec = emitter.getOffsetForce()
+        self.getWidget('Emitter', 'Offset Force').set(
+            [vec[0], vec[1], vec[2]], 0)
+        vec = emitter.getRadiateOrigin()
+        self.getWidget('Emitter', 'Radiate Origin').set(
+            [vec[0], vec[1], vec[2]], 0)
+        vec = emitter.getExplicitLaunchVector()
+        self.getWidget('Emitter', 'Explicit Launch Vector').set(
+            [vec[0], vec[1], vec[2]], 0)
         if isinstance(emitter, BoxEmitter):
         if isinstance(emitter, BoxEmitter):
             min = emitter.getMinBound()
             min = emitter.getMinBound()
             self.getWidget('Box Emitter', 'Min').set(
             self.getWidget('Box Emitter', 'Min').set(
@@ -671,6 +806,29 @@ class ParticlePanel(AppShell):
         elif isinstance(emitter, TangentRingEmitter):
         elif isinstance(emitter, TangentRingEmitter):
             radius = emitter.getRadius()
             radius = emitter.getRadius()
             self.getWidget('Tangent Ring Emitter', 'Radius').set(radius, 0)
             self.getWidget('Tangent Ring Emitter', 'Radius').set(radius, 0)
+    # All #
+    def setEmissionType(self):
+        self.particles.emitter.setEmissionType(
+            int(self.emissionType.get()))
+
+    def setEmitterAmplitude(self, value):
+        self.particles.emitter.setAmplitude(value)
+
+    def setEmitterAmplitudeSpread(self, value):
+        self.particles.emitter.setAmplitudeSpread(value)
+
+    def setEmitterOffsetForce(self, vec):
+        self.particles.emitter.setOffsetForce(
+            Vec3(vec[0], vec[1], vec[2]))
+
+    def setEmitterRadiateOrigin(self, origin):
+        self.particles.emitter.setRadiateOrigin(
+            Point3(origin[0], origin[1], origin[2]))
+
+    def setEmitterExplicitLaunchVector(self, vec):
+        self.particles.emitter.setExplicitLaunchVector(
+            Vec3(vec[0], vec[1], vec[2]))
+
     # Box #
     # Box #
     def setEmitterBoxPoint1(self, point):
     def setEmitterBoxPoint1(self, point):
 	self.particles.emitter.setMinBound(Point3(point[0],
 	self.particles.emitter.setMinBound(Point3(point[0],
@@ -680,19 +838,17 @@ class ParticlePanel(AppShell):
 	self.particles.emitter.setMaxBound(Point3(point[0],
 	self.particles.emitter.setMaxBound(Point3(point[0],
                                                   point[1],
                                                   point[1],
                                                   point[2]))
                                                   point[2]))
-    def setEmitterBoxVelocityVector(self, vec):
-        print 'Emitter box velocity vector:', vec
     # Disc #
     # Disc #
     def setEmitterDiscRadius(self, radius):
     def setEmitterDiscRadius(self, radius):
 	self.particles.emitter.setRadius(radius)
 	self.particles.emitter.setRadius(radius)
     def setEmitterDiscInnerAngle(self, angle):
     def setEmitterDiscInnerAngle(self, angle):
 	self.particles.emitter.setInnerAngle(angle)
 	self.particles.emitter.setInnerAngle(angle)
     def setEmitterDiscInnerVelocity(self, velocity):
     def setEmitterDiscInnerVelocity(self, velocity):
-        print 'Emitter disc inner velocity:', velocity
+        self.particles.emitter.setInnerMagnitude(velocity)
     def setEmitterDiscOuterAngle(self, angle):
     def setEmitterDiscOuterAngle(self, angle):
 	self.particles.emitter.setOuterAngle(angle)
 	self.particles.emitter.setOuterAngle(angle)
     def setEmitterDiscOuterVelocity(self, velocity):
     def setEmitterDiscOuterVelocity(self, velocity):
-        print 'Emitter disc outer velocity:', velocity
+        self.particles.emitter.setOuterMagnitude(velocity)
     def toggleEmitterDiscCubicLerping(self):
     def toggleEmitterDiscCubicLerping(self):
 	self.particles.emitter.setCubicLerping(
 	self.particles.emitter.setCubicLerping(
             self.emitterDiscCubicLerping.get())
             self.emitterDiscCubicLerping.get())
@@ -705,27 +861,19 @@ class ParticlePanel(AppShell):
 	self.particles.emitter.setEndpoint2(Point3(point[0],
 	self.particles.emitter.setEndpoint2(Point3(point[0],
                                                    point[1],
                                                    point[1],
                                                    point[2]))
                                                    point[2]))
-    def setEmitterLineVelocityVector(self, vec):
-        print 'Emitter line velocity vector:', vec
     # Point #
     # Point #
     def setEmitterPointPosition(self, pos):
     def setEmitterPointPosition(self, pos):
 	self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2]))
 	self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2]))
-    def setEmitterPointVelocityVector(self, velocity):
-        print 'Emitter point velocity:', velocity
     # Rectangle #
     # Rectangle #
     def setEmitterRectanglePoint1(self, point):
     def setEmitterRectanglePoint1(self, point):
 	self.particles.emitter.setMinBound(Point2(point[0], point[1]))
 	self.particles.emitter.setMinBound(Point2(point[0], point[1]))
     def setEmitterRectanglePoint2(self, point):
     def setEmitterRectanglePoint2(self, point):
 	self.particles.emitter.setMaxBound(Point2(point[0], point[1]))
 	self.particles.emitter.setMaxBound(Point2(point[0], point[1]))
-    def setEmitterRectangleVelocityVector(self, vec):
-        print 'Emitter rectangle velocity vector:', vec
     # Ring #
     # Ring #
     def setEmitterRingRadius(self, radius):
     def setEmitterRingRadius(self, radius):
 	self.particles.emitter.setRadius(radius)
 	self.particles.emitter.setRadius(radius)
     def setEmitterRingLaunchAngle(self, angle):
     def setEmitterRingLaunchAngle(self, angle):
 	self.particles.emitter.setAngle(angle)
 	self.particles.emitter.setAngle(angle)
-    def setEmitterRingVelocityMultiplier(self, multiplier):
-        print 'Emitter ring velocity multiplier:', multiplier
     # Sphere surface #
     # Sphere surface #
     def setEmitterSphereSurfaceRadius(self, radius):
     def setEmitterSphereSurfaceRadius(self, radius):
 	self.particles.emitter.setRadius(radius)
 	self.particles.emitter.setRadius(radius)
@@ -744,6 +892,18 @@ class ParticlePanel(AppShell):
         
         
     def updateRendererWidgets(self):
     def updateRendererWidgets(self):
         renderer = self.particles.renderer
         renderer = self.particles.renderer
+        alphaMode = renderer.getAlphaMode()
+        if alphaMode == BaseParticleRenderer.PRALPHANONE:
+            aMode = 'NO_ALPHA'
+        elif alphaMode == BaseParticleRenderer.PRALPHAOUT:
+            aMode = 'ALPHA_OUT'
+        elif alphaMode == BaseParticleRenderer.PRALPHAIN:
+            aMode = 'ALPHA_IN'
+        elif alphaMode == BaseParticleRenderer.PRALPHAUSER:
+            aMode = 'ALPHA_USER'
+        self.getWidget('Renderer', 'Alpha Mode').set(aMode)
+        userAlpha = renderer.getUserAlpha()
+        self.getWidget('Renderer', 'User Alpha').set(userAlpha)
         if isinstance(renderer, LineParticleRenderer):
         if isinstance(renderer, LineParticleRenderer):
             headColor = renderer.getHeadColor() * 255.0
             headColor = renderer.getHeadColor() * 255.0
             self.getWidget('Line Renderer', 'Head Color').set(
             self.getWidget('Line Renderer', 'Head Color').set(
@@ -833,7 +993,22 @@ class ParticlePanel(AppShell):
         type = self.particles.renderer.__class__.__name__
         type = self.particles.renderer.__class__.__name__
         self.rendererNotebook.selectpage(type)
         self.rendererNotebook.selectpage(type)
         self.rendererTypeMenu.set(type)
         self.rendererTypeMenu.set(type)
-        
+
+    # All #
+    def setRendererAlphaMode(self, alphaMode):
+        if alphaMode == 'NO_ALPHA':
+            aMode = BaseParticleRenderer.PRALPHANONE
+        elif alphaMode == 'ALPHA_OUT':
+            aMode = BaseParticleRenderer.PRALPHAOUT
+        elif alphaMode == 'ALPHA_IN':
+            aMode = BaseParticleRenderer.PRALPHAIN
+        elif alphaMode == 'ALPHA_USER':
+            aMode = BaseParticleRenderer.PRALPHAUSER
+        self.particles.renderer.setAlphaMode(aMode)
+
+    def setRendererUserAlpha(self, alpha):
+        self.particles.renderer.setUserAlpha(alpha)
+
     # Line #
     # Line #
     def setRendererLineHeadColor(self, color):
     def setRendererLineHeadColor(self, color):
 	self.particles.renderer.setHeadColor(
 	self.particles.renderer.setHeadColor(
@@ -888,11 +1063,9 @@ class ParticlePanel(AppShell):
 	self.particles.renderer.setDeathRadius(radius)
 	self.particles.renderer.setDeathRadius(radius)
     def setRendererSparkleLifeScale(self, lifeScaleMethod):
     def setRendererSparkleLifeScale(self, lifeScaleMethod):
         if lifeScaleMethod == 'SP_NO_SCALE':
         if lifeScaleMethod == 'SP_NO_SCALE':
-            # lScale = SparkleParticleRenderer.SPNOSCALE
-            lScale = 0
+            lScale = SparkleParticleRenderer.SPNOSCALE
         else:
         else:
-            # lScale = SparkleParticleRenderer.SPSCALE
-            lScale = 1
+            lScale = SparkleParticleRenderer.SPSCALE
 	self.particles.renderer.setLifeScale(lScale)
 	self.particles.renderer.setLifeScale(lScale)
     # Sprite #
     # Sprite #
     def setRendererSpriteTexture(self, event):
     def setRendererSpriteTexture(self, event):
@@ -921,12 +1094,15 @@ class ParticlePanel(AppShell):
     def setRendererSpriteNonAnimatedTheta(self, theta):
     def setRendererSpriteNonAnimatedTheta(self, theta):
 	self.particles.renderer.setNonanimatedTheta(theta)
 	self.particles.renderer.setNonanimatedTheta(theta)
     def setRendererSpriteBlendMethod(self, blendMethod):
     def setRendererSpriteBlendMethod(self, blendMethod):
+        print blendMethod
         if blendMethod == 'PP_NO_BLEND':
         if blendMethod == 'PP_NO_BLEND':
             bMethod = BaseParticleRenderer.PPNOBLEND
             bMethod = BaseParticleRenderer.PPNOBLEND
-        if blendMethod == 'PP_BLEND_LINEAR':
+        elif blendMethod == 'PP_BLEND_LINEAR':
             bMethod = BaseParticleRenderer.PPBLENDLINEAR
             bMethod = BaseParticleRenderer.PPBLENDLINEAR
-        if blendMethod == 'PP_BLEND_CUBIC':
+        elif blendMethod == 'PP_BLEND_CUBIC':
             bMethod = BaseParticleRenderer.PPBLENDCUBIC
             bMethod = BaseParticleRenderer.PPBLENDCUBIC
+        else:
+            bMethod = BaseParticleRenderer.PPNOBLEND
 	self.particles.renderer.setAlphaBlendMethod(bMethod)
 	self.particles.renderer.setAlphaBlendMethod(bMethod)
     def toggleRendererSpriteAlphaDisable(self):
     def toggleRendererSpriteAlphaDisable(self):
 	self.particles.renderer.setAlphaDisable(
 	self.particles.renderer.setAlphaDisable(

+ 3 - 2
direct/src/tkwidgets/SceneGraphExplorer.py

@@ -3,8 +3,9 @@ from Tkinter import *
 from Tree import *
 from Tree import *
 import Pmw
 import Pmw
 
 
-DEFAULT_MENU_ITEMS = ['Select', 'Deselect', 'Flash', 'Toggle Vis',
-                      'Isolate', 'Show All', 'Place', 'Delete']
+DEFAULT_MENU_ITEMS = ['Select', 'Deselect', 'Flash', 
+                      'Isolate', 'Toggle Vis', 'Show All',
+                      'Fit', 'Place', 'Delete']
 
 
 class SceneGraphExplorer(Pmw.MegaWidget):
 class SceneGraphExplorer(Pmw.MegaWidget):
     "Graphical display of a scene graph"
     "Graphical display of a scene graph"