*** empty log message ***

This commit is contained in:
Mark Mine 2001-01-29 07:16:14 +00:00
parent d05141e448
commit bb0fcbdd72
6 changed files with 636 additions and 196 deletions

View File

@ -4,7 +4,7 @@ from PhysicsManagerGlobal import *
import ForceNode import ForceNode
class Forces(DirectObject): class ForceGroup(DirectObject):
forceNum = 1 forceNum = 1
@ -12,13 +12,14 @@ class Forces(DirectObject):
"""__init__(self)""" """__init__(self)"""
if (name == None): if (name == None):
self.name = 'Forces-%d' % self.forceNum self.name = 'ForceGroup-%d' % self.forceNum
self.forceNum = self.forceNum + 1 self.forceNum = self.forceNum + 1
else: else:
self.name = name self.name = name
self.node = ForceNode.ForceNode(self.name) self.node = ForceNode.ForceNode(self.name)
self.nodePath = hidden.attachNewNode(self.node) self.nodePath = hidden.attachNewNode(self.node)
self.fEnabled = 0
def enable(self): def enable(self):
"""enable(self)""" """enable(self)"""
@ -28,6 +29,7 @@ class Forces(DirectObject):
physicsMgr.addLinearForce(f) physicsMgr.addLinearForce(f)
else: else:
physicsMgr.addAngularForce(f) physicsMgr.addAngularForce(f)
self.fEnabled = 1
def disable(self): def disable(self):
"""disable(self)""" """disable(self)"""
@ -37,6 +39,10 @@ class Forces(DirectObject):
physicsMgr.removeLinearForce(f) physicsMgr.removeLinearForce(f)
else: else:
physicsMgr.removeAngularForce(f) physicsMgr.removeAngularForce(f)
self.fEnabled = 0
def isEnabled(self):
return self.fEnabled
def addForce(self, force): def addForce(self, force):
"""addForce(self, force)""" """addForce(self, force)"""
@ -44,6 +50,11 @@ class Forces(DirectObject):
# Physics manager will need an angular integrator # Physics manager will need an angular integrator
base.addAngularIntegrator() base.addAngularIntegrator()
self.node.addForce(force) self.node.addForce(force)
if self.fEnabled:
if (force.isLinear() == 1):
physicsMgr.addLinearForce(force)
else:
physicsMgr.addAngularForce(force)
def removeForce(self, force): def removeForce(self, force):
"""removeForce(self, force)""" """removeForce(self, force)"""
@ -61,7 +72,7 @@ class Forces(DirectObject):
return self.nodePath return self.nodePath
# Utility functions # Utility functions
def __getItem__(self, index): def __getitem__(self, index):
"""__getItem__(self, index)""" """__getItem__(self, index)"""
return self.node.getForce(index) return self.node.getForce(index)
@ -72,7 +83,7 @@ class Forces(DirectObject):
def asList(self): def asList(self):
"""asList(self)""" """asList(self)"""
l = [] l = []
for i in self.node.getNumForces(): for i in range(self.node.getNumForces()):
l.append(self.node.getForce(i)) l.append(self.node.getForce(i))
return l return l

View File

@ -2,7 +2,7 @@ from PandaObject import *
from DirectObject import * from DirectObject import *
import Particles import Particles
import Forces import ForceGroup
class ParticleEffect(NodePath): class ParticleEffect(NodePath):
def __init__(self, name = 'ParticleEffect'): def __init__(self, name = 'ParticleEffect'):
@ -11,37 +11,48 @@ class ParticleEffect(NodePath):
self.assign(hidden.attachNewNode(name)) self.assign(hidden.attachNewNode(name))
# Record particle effect name # Record particle effect name
self.name = name self.name = name
# Dictionary of particles and forces # Enabled flag
self.fEnabled = 0
# Dictionary of particles and forceGroups
self.particlesDict = {} self.particlesDict = {}
self.forcesDict = {} self.forceGroupDict = {}
# The effect's particle system # The effect's particle system
self.addParticles(Particles.Particles()) self.addParticles(Particles.Particles())
def enable(self): def enable(self):
"""enable()""" """enable()"""
for f in self.forcesDict.values(): for f in self.forceGroupDict.values():
f.enable() f.enable()
for p in self.particlesDict.values(): for p in self.particlesDict.values():
p.enable() p.enable()
self.fEnabled = 1
def disable(self): def disable(self):
"""disable()""" """disable()"""
for f in self.forcesDict.values(): for f in self.forceGroupDict.values():
f.disable() f.disable()
for p in self.particlesDict.values(): for p in self.particlesDict.values():
p.disable() p.disable()
self.fEnabled = 0
def addForces(self, forces): def isEnabled(self):
"""addForces(forces)""" """
forces.nodePath.reparentTo(self) isEnabled()
self.forcesDict[forces.getName()] = forces Note: this may be misleading if enable(),disable() not used
"""
return self.fEnabled
def addForceGroup(self, forceGroup):
"""addForceGroup(forceGroup)"""
forceGroup.nodePath.reparentTo(self)
self.forceGroupDict[forceGroup.getName()] = forceGroup
def addParticles(self, particles): def addParticles(self, particles):
"""addParticles(particles)""" """addParticles(particles)"""
particles.nodePath.reparentTo(self) particles.nodePath.reparentTo(self)
self.particlesDict[particles.getName()] = particles self.particlesDict[particles.getName()] = particles
def getParticles(self): def getParticlesList(self):
"""getParticles()""" """getParticles()"""
return self.particlesDict.values() return self.particlesDict.values()
@ -53,15 +64,15 @@ class ParticleEffect(NodePath):
"""getParticlesDict()""" """getParticlesDict()"""
return self.particlesDict return self.particlesDict
def getForces(self): def getForceGroupList(self):
"""getForces()""" """getForceGroup()"""
return self.forcesDict.values() return self.forceGroupDict.values()
def getForcesNamed(self, name): def getForceGroupNamed(self, name):
"""getForcesNamed(name)""" """getForceGroupNamed(name)"""
return self.forcesDict.get(name, None) return self.forceGroupDict.get(name, None)
def getForcesDict(self): def getForceGroupDict(self):
"""getForces()""" """getForceGroup()"""
return self.forcesDict return self.forceGroupDict

View File

@ -2,21 +2,21 @@ from DirectSessionGlobal import *
import ParticleEffect import ParticleEffect
import ParticlePanel import ParticlePanel
import Forces import ForceGroup
# Showbase # Showbase
base.enableParticles() base.enableParticles()
# Forces # ForceGroup
gravity = LinearVectorForce(Vec3(0.0, 0.0, -10.0)) gravity = LinearVectorForce(Vec3(0.0, 0.0, -10.0))
f = Forces.Forces() fg = ForceGroup.ForceGroup()
f.addForce(gravity) fg.addForce(gravity)
# Particle effect # Particle effect
pe = ParticleEffect.ParticleEffect('particle-fx') pe = ParticleEffect.ParticleEffect('particle-fx')
pe.reparentTo(render) pe.reparentTo(render)
pe.setPos(0.0, 5.0, 4.0) pe.setPos(0.0, 5.0, 4.0)
pe.addForces(f) pe.addForceGroup(fg)
pe.enable() pe.enable()
# Particle Panel # Particle Panel

View File

@ -62,16 +62,22 @@ class Particles(ParticleSystem.ParticleSystem):
self.emitter = None self.emitter = None
self.emitterType = "undefined" self.emitterType = "undefined"
self.setEmitter("SphereVolumeEmitter") self.setEmitter("SphereVolumeEmitter")
self.fEnabled = 0
def enable(self): def enable(self):
"""enable()""" """enable()"""
physicsMgr.attachPhysical(self) physicsMgr.attachPhysical(self)
particleMgr.attachParticlesystem(self) particleMgr.attachParticlesystem(self)
self.fEnabled = 1
def disable(self): def disable(self):
"""disable()""" """disable()"""
physicsMgr.removePhysical(self) physicsMgr.removePhysical(self)
particleMgr.removeParticlesystem(self) particleMgr.removeParticlesystem(self)
self.fEnabled = 0
def isEnabled(self):
return self.fEnabled
def setFactory(self, type): def setFactory(self, type):
"""setFactory(type)""" """setFactory(type)"""

View File

@ -150,6 +150,18 @@ class ShowBase:
self.physicsMgrEnabled = 0 self.physicsMgrEnabled = 0
self.taskMgr.removeTasksNamed('manager-update') self.taskMgr.removeTasksNamed('manager-update')
def toggleParticles(self):
if self.particleMgrEnabled == 0:
self.enableParticles()
else:
self.disableParticles()
def isParticleMgrEnabled(self):
return self.particleMgrEnabled
def isPhysicsMgrEnabled(self):
return self.physicsMgrEnabled
def __updateManagers(self, state): def __updateManagers(self, state):
"""__updateManagers(self)""" """__updateManagers(self)"""
dt = min(globalClock.getDt(), 0.1) dt = min(globalClock.getDt(), 0.1)

View File

@ -3,24 +3,28 @@
# Import Tkinter, Pmw, and the floater code from this directory tree. # Import Tkinter, Pmw, and the floater code from this directory tree.
from AppShell import * from AppShell import *
from Tkinter import * from Tkinter import *
from tkFileDialog import *
from tkSimpleDialog import askstring
import os
import Pmw import Pmw
import Dial import Dial
import Floater import Floater
import EntryScale import EntryScale
import VectorWidgets import VectorWidgets
import Placer import Placer
import ForceGroup
import Particles import Particles
import ParticleEffect import ParticleEffect
class ParticlePanel(AppShell): class ParticlePanel(AppShell):
# Override class variables # Override class variables
appname = 'Particle Panel' appname = 'Particle Panel'
frameWidth = 400 frameWidth = 375
frameHeight = 660 frameHeight = 775
usecommandarea = 0 usecommandarea = 0
usestatusarea = 0 usestatusarea = 0
balloonState = 'both' balloonState = 'both'
def __init__(self, particleEffect = None, **kw): def __init__(self, particleEffect = None, **kw):
INITOPT = Pmw.INITOPT INITOPT = Pmw.INITOPT
optiondefs = ( optiondefs = (
@ -33,7 +37,7 @@ class ParticlePanel(AppShell):
self.particleEffect = particleEffect self.particleEffect = particleEffect
else: else:
# Or create a new one if none given # Or create a new one if none given
pe = ParticleEffect.ParticleEffect('particle-fx') pe = ParticleEffect.ParticleEffect('effect-1')
self.particleEffect = pe self.particleEffect = pe
pe.reparentTo(render) pe.reparentTo(render)
pe.enable() pe.enable()
@ -45,42 +49,156 @@ class ParticlePanel(AppShell):
self.initialiseoptions(ParticlePanel) self.initialiseoptions(ParticlePanel)
# Update panel values to reflect particle effect's state # Update panel values to reflect particle effect's state
self.selectEffectNamed(self.effectDict.keys()[0]) self.selectEffectNamed(self.effectsDict.keys()[0])
# Make sure labels/menus reflect current state
self.updateMenusAndLabels()
# Make sure there is a page for each forceGroup objects
for forceGroup in self.particleEffect.getForceGroupList():
self.addForceGroupNotebookPage(self.particleEffect, forceGroup)
def appInit(self): def appInit(self):
# Create dictionaries to keep track of panel objects
self.widgetDict = {} self.widgetDict = {}
self.variableDict = {} self.variableDict = {}
self.effectDict = {} self.effectsDict = {}
self.effectDict[self.particleEffect.getName()] = ( self.effectsDict[self.particleEffect.getName()] = (
self.particleEffect) self.particleEffect)
self.forcePagesDict = {}
# Make sure particles are enabled
base.enableParticles()
def createInterface(self): def createInterface(self):
# Handle to the toplevels hull # Handle to the toplevels hull
interior = self.interior() interior = self.interior()
self.menuBar.addmenu('Particles', 'Particle Panel Operations') # Create particle panel menu items
self.menuBar.addmenuitem(
'Particles', 'command', ## MENUBAR ENTRIES ##
'Print Particle System Parameters', # FILE MENU
# Get a handle on the file menu so commands can be inserted
# before quit item
fileMenu = self.menuBar.component('File-menu')
# MRM: Need to add load and save effects methods
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Load Params',
command = self.loadParticleEffectFromFile)
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Save Params',
command = self.saveParticleEffectToFile)
fileMenu.insert_command(
fileMenu.index('Quit'),
label = 'Print Params', label = 'Print Params',
command = lambda s = self: s.particles.printParams()) command = lambda s = self: s.particles.printParams())
# Combo box to switch between particle systems # EFFECTS MENU
self.effectSelector = Pmw.ComboBox(self.menuFrame, self.menuBar.addmenu('Effects', 'Particle Effects Operations')
labelpos = W, # Get a handle on this menu
label_text = 'Particle System', effectsMenu = self.menuBar.component('Effects-menu')
entry_width = 16, # Create new particle effect
selectioncommand = self.selectEffectNamed, self.menuBar.addmenuitem(
scrolledlist_items = ('system 0',)) 'Effects', 'command',
self.effectSelector.selectitem('system 0') 'Create New Particle Effect',
self.effectSelector.pack(side = 'left', expand = 0) label = 'Create New Effect',
command = self.createNewEffect)
# Add cascade menus to view and enable, saving a handle
effectsConfigureMenu = Menu(effectsMenu, tearoff = 0)
effectsMenu.add_cascade(label = 'Configure',
menu = effectsConfigureMenu)
self.effectsEnableMenu = Menu(effectsMenu, tearoff = 0)
effectsMenu.add_cascade(label = 'Enable/Disable',
menu = self.effectsEnableMenu)
self.createCheckbutton( # PARTICLES MENU
self.menuFrame, 'System', 'Active', self.menuBar.addmenu('Particles', 'Particles Operations')
'Turn particle systems on/off', # Get a handle on this menu
self.toggleParticleSystem, 1) particlesMenu = self.menuBar.component('Particles-menu')
# Create new particles object
self.menuBar.addmenuitem(
'Particles', 'command',
'Create New Particles Object',
label = 'Create New Particles',
command = self.createNewParticles)
# Add cascade menus to view and enable, saving a handle
particlesConfigureMenu = Menu(particlesMenu, tearoff = 0)
particlesMenu.add_cascade(label = 'Configure',
menu = particlesConfigureMenu)
self.particlesEnableMenu = Menu(particlesMenu, tearoff = 0)
particlesMenu.add_cascade(label = 'Enable/Disable',
menu = self.particlesEnableMenu)
# Create the notebook pages # FORCE GROUP MENU
self.menuBar.addmenu('ForceGroup', 'ForceGroup Operations')
# Get a handle on this menu
forceGroupMenu = self.menuBar.component('ForceGroup-menu')
# Create new particle effect
self.menuBar.addmenuitem(
'ForceGroup', 'command',
'Create New ForceGroup Object',
label = 'Create New ForceGroup',
command = self.createNewForceGroup)
# Add cascade menus to view and enable, saving a handle
forceGroupConfigureMenu = Menu(forceGroupMenu, tearoff = 0)
forceGroupMenu.add_cascade(label = 'Configure',
menu = forceGroupConfigureMenu)
self.forceGroupEnableMenu = Menu(forceGroupMenu, tearoff = 0)
forceGroupMenu.add_cascade(label = 'Enable/Disable',
menu = self.forceGroupEnableMenu)
# PARTICLE MANAGER MENU
self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')
self.particleMgrActive = IntVar()
self.particleMgrActive.set(base.isParticleMgrEnabled())
self.menuBar.addmenuitem(
'ParticleMgr', 'checkbutton',
'Enable/Disable ParticleMgr',
label = 'Active',
variable = self.particleMgrActive,
command = self.toggleParticleMgr)
## MENUBUTTON LABELS ##
# Menubutton/label to identify the current objects being configured
labelFrame = Frame(interior)
# Current effect
self.effectsLabel = Menubutton(labelFrame, width = 10,
relief = RAISED,
borderwidth = 2,
font=('MSSansSerif', 14, 'bold'),
activebackground = '#909090')
effectsConfigureLabel = Menu(self.effectsLabel, tearoff = 0)
self.effectsLabel['menu'] = effectsConfigureLabel
self.effectsLabel.pack(side = LEFT, fill = 'x', expand = 0)
# Current particles
self.particlesLabel = Menubutton(labelFrame, width = 10,
relief = RAISED,
borderwidth = 2,
font=('MSSansSerif', 14, 'bold'),
activebackground = '#909090')
particlesConfigureLabel = Menu(self.particlesLabel, tearoff = 0)
self.particlesLabel['menu'] = particlesConfigureLabel
self.particlesLabel.pack(side = LEFT, fill = 'x', expand = 0)
# Current force
self.forceGroupLabel = Menubutton(labelFrame, width = 10,
relief = RAISED,
borderwidth = 2,
font=('MSSansSerif', 14, 'bold'),
activebackground = '#909090')
forceGroupConfigureLabel = Menu(self.forceGroupLabel, tearoff = 0)
self.forceGroupLabel['menu'] = forceGroupConfigureLabel
self.forceGroupLabel.pack(side = LEFT, fill = 'x', expand = 0)
# Pack labels
labelFrame.pack(fill = 'x', expand = 0)
# These get updated together
self.effectsConfigureMenus = [effectsConfigureMenu,
effectsConfigureLabel]
self.particlesConfigureMenus = [particlesConfigureMenu,
particlesConfigureLabel]
self.forceGroupConfigureMenus = [forceGroupConfigureMenu,
forceGroupConfigureLabel]
# Create the toplevel 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)
systemPage = self.mainNotebook.add('System') systemPage = self.mainNotebook.add('System')
@ -91,7 +209,7 @@ class ParticlePanel(AppShell):
# Put this here so it isn't called right away # Put this here so it isn't called right away
self.mainNotebook['raisecommand'] = self.updateInfo self.mainNotebook['raisecommand'] = self.updateInfo
## SYSTEM PAGE ## ## SYSTEM PAGE WIDGETS ##
# Create system floaters # Create system floaters
systemFloaterDefs = ( systemFloaterDefs = (
('System', 'Pool Size', ('System', 'Pool Size',
@ -116,17 +234,18 @@ class ParticlePanel(AppShell):
0.0, None) 0.0, None)
) )
self.createFloaters(systemPage, systemFloaterDefs) self.createFloaters(systemPage, systemFloaterDefs)
# Checkboxes # Checkboxes
# Note: Sense is reversed on this one
self.createCheckbutton( self.createCheckbutton(
systemPage, 'System', 'Render Relative Velocities', systemPage, 'System', 'Render Space Velocities',
('On: velocities are in render space; ' + ('On: velocities are in render space; ' +
'Off: velocities are in particle local space'), 'Off: velocities are in particle local space'),
self.toggleSystemLocalVelocity, 0) self.toggleSystemLocalVelocity, 0)
self.createCheckbutton( self.createCheckbutton(
systemPage, 'System', 'Grows Older', systemPage, 'System', 'System Grows Older',
'On: system has a lifespan', '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',
'Particle system position', 'Particle system position',
@ -138,7 +257,7 @@ class ParticlePanel(AppShell):
command = self.setSystemHpr) command = self.setSystemHpr)
hpr.addMenuItem('Popup Placer Panel', Placer.Placer) hpr.addMenuItem('Popup Placer Panel', Placer.Placer)
## FACTORY PAGE ## ## FACTORY PAGE WIDGETS ##
self.createOptionMenu( self.createOptionMenu(
factoryPage, factoryPage,
'Factory', 'Factory Type', 'Factory', 'Factory Type',
@ -200,7 +319,7 @@ class ParticlePanel(AppShell):
fill = BOTH) fill = BOTH)
self.factoryNotebook.pack(expand = 1, fill = BOTH) self.factoryNotebook.pack(expand = 1, fill = BOTH)
## EMITTER PAGE ## ## EMITTER PAGE WIDGETS ##
self.createOptionMenu( self.createOptionMenu(
emitterPage, 'Emitter', emitterPage, 'Emitter',
'Emitter Type', 'Emitter Type',
@ -354,7 +473,7 @@ class ParticlePanel(AppShell):
min = 0.01) min = 0.01)
self.emitterNotebook.pack(fill = X) self.emitterNotebook.pack(fill = X)
## RENDERER PAGE ## ## RENDERER PAGE WIDGETS ##
self.createOptionMenu( self.createOptionMenu(
rendererPage, 'Renderer', 'Renderer Type', rendererPage, 'Renderer', 'Renderer Type',
'Select type of particle renderer', 'Select type of particle renderer',
@ -503,77 +622,46 @@ class ParticlePanel(AppShell):
self.toggleRendererSpriteAlphaDisable, 0) self.toggleRendererSpriteAlphaDisable, 0)
self.rendererNotebook.pack(fill = X) self.rendererNotebook.pack(fill = X)
## FORCE PAGE ## ## FORCE PAGE WIDGETS ##
# Menu to select between differnt Forces self.addForceButton = Menubutton(forcePage, text = 'Add Force',
self.createOptionMenu( relief = RAISED,
forcePage, 'Force', borderwidth = 2,
'Active Force', font=('MSSansSerif', 14, 'bold'),
'Select force component', [], activebackground = '#909090')
self.selectForceType) forceMenu = Menu(self.addForceButton)
self.addForceButton['menu'] = forceMenu
forceFrame = Frame(forcePage, borderwidth = 2, relief = 'sunken') forceMenu.add_command(label = 'Add Linear Vector Force',
self.forcesButton = Menubutton(forceFrame, text = 'Forces',
font=('MSSansSerif', 14, 'bold'),
activebackground = '#909090')
forcesMenu = Menu(self.forcesButton)
forcesMenu.add_command(label = 'Add Linear Cylinder Vortex Force',
command = self.addLinearCylinderVortexForce)
forcesMenu.add_command(label = 'Add Linear Distance Force',
command = self.addLinearDistanceForce)
forcesMenu.add_command(label = 'Add Linear Friction Force',
command = self.addLinearFrictionForce)
forcesMenu.add_command(label = 'Add Linear Jitter Force',
command = self.addLinearJitterForce)
forcesMenu.add_command(label = 'Add Linear Noise Force',
command = self.addLinearNoiseForce)
forcesMenu.add_command(label = 'Add Linear Random Force',
command = self.addLinearRandomForce)
forcesMenu.add_command(label = 'Add Linear Sink Force',
command = self.addLinearSinkForce)
forcesMenu.add_command(label = 'Add Linear Source Force',
command = self.addLinearSourceForce)
forcesMenu.add_command(label = 'Add Linear User Defined Force',
command = self.addLinearUserDefinedForce)
forcesMenu.add_command(label = 'Add Linear Vector Force',
command = self.addLinearVectorForce) command = self.addLinearVectorForce)
self.forcesButton.pack(expand = 0) forceMenu.add_command(label = 'Add Linear Friction Force',
self.forcesButton['menu'] = forcesMenu command = self.addLinearFrictionForce)
"""
# Notebook pages for force specific controls forceMenu.add_command(label = 'Add Linear Cylinder Vortex Force',
self.forceNotebook = Pmw.NoteBook(forceFrame, tabpos = None, command = self.addLinearCylinderVortexForce)
borderwidth = 0) forceMenu.add_command(label = 'Add Linear Distance Force',
# Put this here so it isn't called right away command = self.addLinearDistanceForce)
self.forceNotebook['raisecommand'] = self.updateForceWidgets forceMenu.add_command(label = 'Add Linear Jitter Force',
command = self.addLinearJitterForce)
# Widget to select a force to configure forceMenu.add_command(label = 'Add Linear Noise Force',
nameList = map(lambda x: x.getName(), self.particleEffect.getForces()) command = self.addLinearNoiseForce)
forceMenuFrame = Frame(forceFrame) forceMenu.add_command(label = 'Add Linear Random Force',
self.forceMenu = Pmw.ComboBox( command = self.addLinearRandomForce)
forceMenuFrame, labelpos = W, label_text = 'Force:', forceMenu.add_command(label = 'Add Linear Sink Force',
entry_width = 20, command = self.addLinearSinkForce)
selectioncommand = self.selectForceNamed, forceMenu.add_command(label = 'Add Linear Source Force',
scrolledlist_items = nameList) command = self.addLinearSourceForce)
self.forceMenu.pack(side = 'left', fill = 'x', expand = 0) forceMenu.add_command(label = 'Add Linear User Defined Force',
self.bind(self.forceMenu, 'Select force to configure') command = self.addLinearUserDefinedForce)
"""
self.createCheckbutton( self.addForceButton.pack(expand = 0)
forceMenuFrame,
'Force', 'On/Off',
'Turn selected force on/off',
self.toggleActiveForce, 0)
# Pack force menu
forceMenuFrame.pack(fill = 'x', expand = 0, padx = 2)
self.forceNotebook.setnaturalsize()
self.forceNotebook.pack(expand = 1, fill = BOTH)
forceFrame.pack(expand = 1, fill = BOTH)
# Notebook to hold force widgets as the are added
self.forceGroupNotebook = Pmw.NoteBook(forcePage, tabpos = None)
self.forceGroupNotebook.pack(fill = X)
self.factoryNotebook.setnaturalsize() self.factoryNotebook.setnaturalsize()
self.emitterNotebook.setnaturalsize() self.emitterNotebook.setnaturalsize()
self.rendererNotebook.setnaturalsize() self.rendererNotebook.setnaturalsize()
self.forceGroupNotebook.setnaturalsize()
self.mainNotebook.setnaturalsize() self.mainNotebook.setnaturalsize()
# Make sure input variables processed # Make sure input variables processed
@ -715,28 +803,232 @@ class ParticlePanel(AppShell):
return optionVar return optionVar
def createComboBox(self, parent, category, text, balloonHelp, def createComboBox(self, parent, category, text, balloonHelp,
items, command): items, command, history = 0):
widget = Pmw.ComboBox(parent, widget = Pmw.ComboBox(parent,
labelpos = W, labelpos = W,
label_text = text, label_text = text,
label_anchor = 'w',
label_width = 12,
entry_width = 16, entry_width = 16,
history = history,
scrolledlist_items = items) scrolledlist_items = items)
# Don't allow user to edit entryfield
widget.configure(entryfield_entry_state = 'disabled')
# Select first item if it exists
if len(items) > 0: if len(items) > 0:
widget.selectitem(items[0]) widget.selectitem(items[0])
widget['command'] = command # Bind selection command
widget['selectioncommand'] = command
widget.pack(side = 'left', expand = 0) widget.pack(side = 'left', expand = 0)
self.bind(widget.component('menubutton'), balloonHelp) # Bind help
self.widgetDict[category + '-' + text] = optionVar self.bind(widget, balloonHelp)
# Record widget
self.widgetDict[category + '-' + text] = widget
return widget return widget
def updateMenusAndLabels(self):
self.updateMenus()
self.updateLabels()
def updateLabels(self):
self.effectsLabel['text'] = self.particleEffect.getName()
self.particlesLabel['text'] = self.particles.getName()
if self.forceGroup != None:
self.forceGroupLabel['text'] = self.forceGroup.getName()
else:
self.forceGroupLabel['text'] = ''
def updateMenus(self):
self.updateEffectsMenus()
self.updateParticlesMenus()
self.updateForceGroupMenus()
def updateEffectsMenus(self):
# Get rid of old effects entries if any
self.effectsEnableMenu.delete(0, 'end')
for menu in self.effectsConfigureMenus:
menu.delete(0, 'end')
# Add in a checkbutton for each effect (to toggle on/off)
keys = self.effectsDict.keys()
keys.sort()
for name in keys:
effect = self.effectsDict[name]
for menu in self.effectsConfigureMenus:
menu.add_command(
label = effect.getName(),
command = (lambda s = self,
e = effect: s.selectEffectNamed(e.getName()))
)
effectActive = IntVar()
effectActive.set(effect.isEnabled())
self.effectsEnableMenu.add_checkbutton(
label = effect.getName(),
variable = effectActive,
command = (lambda s = self,
e = effect,
v = effectActive: s.toggleEffect(e, v)))
def updateParticlesMenus(self):
# Get rid of old particles entries if any
self.particlesEnableMenu.delete(0, 'end')
for menu in self.particlesConfigureMenus:
menu.delete(0, 'end')
# Add in a checkbutton for each effect (to toggle on/off)
particles = self.particleEffect.getParticlesList()
names = map(lambda x: x.getName(), particles)
names.sort()
for name in names:
particle = self.particleEffect.getParticlesNamed(name)
for menu in self.particlesConfigureMenus:
menu.add_command(
label = name,
command = (lambda s = self,
n = name: s.selectParticlesNamed(n))
)
particleActive = IntVar()
particleActive.set(particle.isEnabled())
self.particlesEnableMenu.add_checkbutton(
label = name,
variable = particleActive,
command = (lambda s = self,
p = particle,
v = particleActive: s.toggleParticles(p, v)))
def updateForceGroupMenus(self):
# Get rid of old forceGroup entries if any
self.forceGroupEnableMenu.delete(0, 'end')
for menu in self.forceGroupConfigureMenus:
menu.delete(0, 'end')
# Add in a checkbutton for each effect (to toggle on/off)
forceGroupList = self.particleEffect.getForceGroupList()
names = map(lambda x: x.getName(), forceGroupList)
names.sort()
for name in names:
force = self.particleEffect.getForceGroupNamed(name)
for menu in self.forceGroupConfigureMenus:
menu.add_command(
label = name,
command = (lambda s = self,
n = name: s.selectForceGroupNamed(n))
)
forceActive = IntVar()
forceActive.set(force.isEnabled())
self.forceGroupEnableMenu.add_checkbutton(
label = name,
variable = forceActive,
command = (lambda s = self,
f = force,
v = forceActive: s.toggleForceGroup(f, v)))
def selectEffectNamed(self, name):
effect = self.effectsDict.get(name, None)
if effect != None:
self.particleEffect = effect
# Default to first particle in particlesDict
self.particles = self.particleEffect.getParticlesList()[0]
# See if particle effect has any forceGroup
forceGroupList = self.particleEffect.getForceGroupList()
if len(forceGroupList) > 0:
self.forceGroup = forceGroupList[0]
else:
self.forceGroup = None
self.mainNotebook.selectpage('System')
self.updateInfo('System')
else:
print 'ParticlePanel: No effect named ' + name
def toggleEffect(self, effect, var):
if var.get():
effect.enable()
else:
effect.disable()
def selectParticlesNamed(self, name):
particles = self.particleEffect.getParticlesNamed(name)
if particles != None:
self.particles = particles
self.updateInfo()
def toggleParticles(self, particles, var):
if var.get():
particles.enable()
else:
particles.disable()
def selectForceGroupNamed(self, name):
forceGroup = self.particleEffect.getForceGroupNamed(name)
if forceGroup != None:
self.forceGroup = forceGroup
self.updateInfo('Force')
def toggleForceGroup(self, forceGroup, var):
if var.get():
forceGroup.enable()
else:
forceGroup.disable()
def toggleForce(self, force, pagename, variableName):
v = self.getVariable(pagename, variableName)
if v.get():
if (force.isLinear() == 1):
physicsMgr.addLinearForce(force)
else:
physicsMgr.addAngularForce(force)
else:
if (force.isLinear() == 1):
physicsMgr.removeLinearForce(force)
else:
physicsMgr.removeAngularForce(force)
def getWidget(self, category, text): def getWidget(self, category, text):
return self.widgetDict[category + '-' + text] return self.widgetDict[category + '-' + text]
def getVariable(self, category, text): def getVariable(self, category, text):
return self.variableDict[category + '-' + text] return self.variableDict[category + '-' + text]
def loadParticleEffectFromFile(self):
# Find path to particle directory
path = getParticlePath().getDirectory(0).toOsSpecific()
if not os.path.isdir(path):
print 'LevelEditor Warning: Invalid default DNA directory!'
print 'Using: C:\\'
path = 'C:\\'
particleFilename = askopenfilename(
defaultextension = '.ptf',
filetypes = (('Particle Files', '*.ptf'),('All files', '*')),
initialdir = path,
title = 'Load Particle Effect',
parent = self.parent)
if particleFilename:
self.particles.loadConfig(Filename(particleFilename))
def saveParticleEffectToFile(self):
# Find path to particle directory
path = getParticlePath().getDirectory(0).toOsSpecific()
if not os.path.isdir(path):
print 'LevelEditor Warning: Invalid default DNA directory!'
print 'Using: C:\\'
path = 'C:\\'
particleFilename = asksaveasfilename(
defaultextension = '.ptf',
filetypes = (('Particle Files', '*.ptf'),('All files', '*')),
initialdir = path,
title = 'Save Particle Effect as',
parent = self.parent)
if particleFilename:
self.particles.saveConfig(Filename(particleFilename))
### PARTICLE EFFECTS COMMANDS ###
def toggleParticleMgr(self):
if self.particleMgrActive.get():
base.enableParticles()
else:
base.disableParticles()
### PARTICLE SYSTEM COMMANDS ### ### PARTICLE SYSTEM COMMANDS ###
def updateInfo(self, page = 'System'): def updateInfo(self, page = 'System'):
self.updateMenusAndLabels()
if page == 'System': if page == 'System':
self.updateSystemWidgets() self.updateSystemWidgets()
elif page == 'Factory': elif page == 'Factory':
@ -749,15 +1041,13 @@ class ParticlePanel(AppShell):
self.selectRendererPage() self.selectRendererPage()
self.updateRendererWidgets() self.updateRendererWidgets()
elif page == 'Force': elif page == 'Force':
self.selectForcePage()
self.updateForceWidgets() self.updateForceWidgets()
def toggleParticleSystem(self): def toggleParticleEffect(self):
if self.getWidget('System', 'Active').get(): if self.getVariable('Effect', 'Active').get():
self.particleEffect.enable() self.particleEffect.enable()
else: else:
self.particleEffect.disable() self.particleEffect.disable()
return None
## SYSTEM PAGE ## ## SYSTEM PAGE ##
def updateSystemWidgets(self): def updateSystemWidgets(self):
@ -775,9 +1065,9 @@ class ParticlePanel(AppShell):
self.getWidget('System', 'Pos').set([pos[0], pos[1], pos[2]], 0) self.getWidget('System', 'Pos').set([pos[0], pos[1], pos[2]], 0)
hpr = self.particles.nodePath.getHpr() hpr = self.particles.nodePath.getHpr()
self.getWidget('System', 'Hpr').set([hpr[0], hpr[1], hpr[2]], 0) self.getWidget('System', 'Hpr').set([hpr[0], hpr[1], hpr[2]], 0)
self.getVariable('System', 'Render Relative Velocities').set( self.getVariable('System', 'Render Space Velocities').set(
self.particles.getLocalVelocityFlag()) self.particles.getLocalVelocityFlag())
self.getVariable('System', 'Grows Older').set( self.getVariable('System', 'System Grows Older').set(
self.particles.getSystemGrowsOlderFlag()) self.particles.getSystemGrowsOlderFlag())
def setSystemPoolSize(self, value): def setSystemPoolSize(self, value):
self.particles.setPoolSize(int(value)) self.particles.setPoolSize(int(value))
@ -791,10 +1081,10 @@ class ParticlePanel(AppShell):
self.particles.setSystemLifespan(value) self.particles.setSystemLifespan(value)
def toggleSystemLocalVelocity(self): def toggleSystemLocalVelocity(self):
self.particles.setLocalVelocityFlag( self.particles.setLocalVelocityFlag(
self.getVariable('System', 'Render Relative Velocities').get()) self.getVariable('System', 'Render Space Velocities').get())
def toggleSystemGrowsOlder(self): def toggleSystemGrowsOlder(self):
self.particles.setSystemGrowsOlderFlag( self.particles.setSystemGrowsOlderFlag(
self.getVariable('System', 'Grows Older').get()) self.getVariable('System', 'System Grows Older').get())
def setSystemPos(self, pos): def setSystemPos(self, pos):
self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2])) self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2]))
def setSystemHpr(self, pos): def setSystemHpr(self, pos):
@ -1008,7 +1298,7 @@ class ParticlePanel(AppShell):
self.particles.emitter.setOuterMagnitude(velocity) self.particles.emitter.setOuterMagnitude(velocity)
def toggleEmitterDiscCubicLerping(self): def toggleEmitterDiscCubicLerping(self):
self.particles.emitter.setCubicLerping( self.particles.emitter.setCubicLerping(
self.emitterDiscCubicLerping.get()) self.getVariable('Disc Emitter', 'Cubic Lerping').get())
# Line # # Line #
def setEmitterLinePoint1(self, point): def setEmitterLinePoint1(self, point):
self.particles.emitter.setEndpoint1(Point3(point[0], self.particles.emitter.setEndpoint1(Point3(point[0],
@ -1272,79 +1562,189 @@ class ParticlePanel(AppShell):
self.particles.renderer.setAlphaDisable( self.particles.renderer.setAlphaDisable(
self.getVariable('Sprite Renderer', 'Alpha Disable').get()) self.getVariable('Sprite Renderer', 'Alpha Disable').get())
## FORCES COMMANDS ## ## FORCEGROUP COMMANDS ##
def selectForceNamed(self, name):
pass
def selectForceType(self, type):
self.forceNotebook.selectpage(type)
self.updateForceWidgets()
def selectForcePage(self):
if self.forces:
type = self.forces.__class__.__name__
self.forceNotebook.selectpage(type)
self.getVariable('Emitter', 'Emitter Type').set(type)
def toggleActiveForce(self):
pass
def updateForceWidgets(self): def updateForceWidgets(self):
pass # Select appropriate notebook page
if self.forceGroup != None:
self.forceGroupNotebook.pack(fill = X)
self.forcePageName = (self.particleEffect.getName() + '-' +
self.forceGroup.getName())
self.forcePage = self.forcePagesDict[self.forcePageName]
self.forceGroupNotebook.selectpage(self.forcePageName)
else:
self.forceGroupNotebook.pack_forget()
def addLinearCylinderVortexForce(self): def addLinearCylinderVortexForce(self):
f = LinearCylinderVortexForce() self.addForce(LinearCylinderVortexForce())
self.activeForce.addLinearForce(f)
def addLinearDistanceForce(self): def addLinearDistanceForce(self):
f = LinearDistanceForce() self.addForce(LinearDistanceForce())
self.activeForce.addLinearForce(f)
def addLinearFrictionForce(self): def addLinearFrictionForce(self):
f = LinearFrictionForce() self.addForce(LinearFrictionForce())
self.activeForce.addLinearForce(f)
def addLinearJitterForce(self): def addLinearJitterForce(self):
f = LinearJitterForce() self.addForce(LinearJitterForce())
self.activeForce.addLinearForce(f)
def addLinearNoiseForce(self): def addLinearNoiseForce(self):
f = LinearNoiseForce() self.addForce(LinearNoiseForce())
self.activeForce.addLinearForce(f)
def addLinearRandomForce(self): def addLinearRandomForce(self):
f = LinearRandomForce() self.addForce(LinearRandomForce())
self.activeForce.addLinearForce(f)
def addLinearSinkForce(self): def addLinearSinkForce(self):
f = LinearSingForce() self.addForce(LinearSingForce())
self.activeForce.addLinearForce(f)
def addLinearSourceForce(self): def addLinearSourceForce(self):
f = LinearSourceForce() self.addForce(LinearSourceForce())
self.activeForce.addLinearForce(f)
def addLinearUserDefinedForce(self): def addLinearUserDefinedForce(self):
f = LinearUserDefinedForce() self.addForce(LinearUserDefinedForce())
self.activeForce.addLinearForce(f)
def addLinearVectorForce(self): def addLinearVectorForce(self):
f = LinearVectorForce() self.addForce(LinearVectorForce())
self.activeForce.addLinearForce(f)
def addForce(self, f):
if self.forceGroup == None:
self.createNewForceGroup()
self.forceGroup.addForce(f)
self.addForceWidget(self.forceGroup,f)
## SYSTEM COMMANDS ## ## SYSTEM COMMANDS ##
def selectEffectNamed(self, name): def createNewEffect(self):
effect = self.effectDict.get(name, None) name = askstring('Particle Panel', 'Effect Name:',
if effect: parent = self.parent)
self.particleEffect = effect if name:
# Default to first particle in particlesDict effect = ParticleEffect.ParticleEffect(name)
self.particles = self.particleEffect.getParticles()[0] self.effectsDict[name] = effect
# See if particle effect has any forces self.updateMenusAndLabels()
forcesList = self.particleEffect.getForces() self.selectEffectNamed(name)
if len(forcesList) > 0: effect.reparentTo(render)
self.forces = forcesList[0] effect.enable()
else:
self.forces = None
self.mainNotebook.selectpage('System')
self.updateInfo('System')
else:
print 'ParticlePanel: No effect named ' + name
def createEffectNamed(self, name): def createNewParticles(self):
effect = ParticleEffect.ParticleEffect(name) name = askstring('Particle Panel', 'Particles Name:',
self.effectDict[name] = effect parent = self.parent)
self.selectEffectNamed(name) if name:
p = Particles.Particles(name)
self.particleEffect.addParticles(p)
self.updateParticlesMenus()
self.selectParticlesNamed(name)
p.enable()
def createNewForceGroup(self):
name = askstring('Particle Panel', 'ForceGroup Name:',
parent = self.parent)
if name:
forceGroup = ForceGroup.ForceGroup(name)
self.particleEffect.addForceGroup(forceGroup)
self.updateForceGroupMenus()
self.addForceGroupNotebookPage(self.particleEffect, forceGroup)
self.selectForceGroupNamed(name)
forceGroup.enable()
def addForceGroupNotebookPage(self, particleEffect, forceGroup):
self.forcePageName = (particleEffect.getName() + '-' +
forceGroup.getName())
self.forcePage = self.forceGroupNotebook.add(self.forcePageName)
self.forcePagesDict[self.forcePageName] = self.forcePage
for force in forceGroup.asList():
self.addForceWidget(forceGroup, force)
def addForceWidget(self, forceGroup, force):
forcePage = self.forcePage
pageName = self.forcePageName
# How many forces of the same type in the force group object
count = 0
for f in forceGroup.asList():
if f.getClassType().eq(force.getClassType()):
count += 1
if isinstance(force, LinearVectorForce):
# Vector
self.createLinearVectorForceWidget(
forcePage, pageName, count, force)
elif isinstance(force, LinearFrictionForce):
# Coef
self.createLinearFrictionForceWidget(
forcePage, pageName, count, force)
elif isinstance(force, LinearCylinderVortexForce):
# Coef, length, radius
self.createLinearCylinderVortexForceWidget(
forcePage, pageName, count, force)
elif isinstance(force, LinearDistanceForce):
# No constructor
# Falloff type, force center, radius
pass
elif isinstance(force, LinearJitterForce):
# Nothing
pass
elif isinstance(force, LinearNoiseForce):
# Nothing
pass
elif isinstance(force, LinearRandomForce):
# Nothing
pass
elif isinstance(force, LinearSinkForce):
# Nothing
pass
elif isinstance(force, LinearSourceForce):
# Nothing
pass
elif isinstance(force, LinearUserDefinedForce):
# Nothing
pass
self.forceGroupNotebook.setnaturalsize()
def createLinearVectorForceWidget(self, forcePage, pageName,
count, force):
name = 'Vector Force-' + `count`
cbName = name + ' Active'
def setVec(vec, f = force):
f.setVector(vec[0], vec[1], vec[2])
def toggle(s = self, f = force, p = pageName, n = cbName):
s.toggleForce(f, p, n)
frame = Frame(forcePage, relief = RAISED, borderwidth = 2)
self.createVector3Entry(frame, pageName, name,
'Set force direction and magnitude',
command = setVec)
self.createCheckbutton(frame, pageName, cbName,
'On: force is enabled; Off: force is disabled',
toggle, 1)
frame.pack(fill = 'x', expand =0)
def createLinearFrictionForceWidget(self, forcePage, pageName,
count, force):
name = 'Friction Force-' + `count`
cbName = name + ' Active'
def setCoef(coef, f = force):
f.setCoef(coef)
def toggle(s = self, f = force, p = pageName, n = cbName):
s.toggleForce(f, p, n)
frame = Frame(forcePage, relief = RAISED, borderwidth = 2)
self.createFloater(frame, pageName, name,
'Set linear friction force',
command = setCoef, min = None)
self.createCheckbutton(frame, pageName, cbName,
'On: force is enabled; Off: force is disabled',
toggle, 1)
frame.pack(fill = 'x', expand =0)
def createLinearCylinderVortexForceWidget(self, forcePage, pageName,
count, force):
cbName = 'Vortex Force-' + `count` + ' Active'
def setCoef(coef, f = force):
f.setCoef(coef)
def setLength(length, f = force):
f.setLength(length)
def setRadius(radius, f = force):
f.setRadius(radius)
def toggle(s = self, f = force, p = pageName, n = cbName):
s.toggleForce(f, p, n)
frame = Frame(forcePage, relief = RAISED, borderwidth = 2)
self.createFloater(frame, pageName, 'Coefficient',
'Set linear cylinder vortex coefficient',
command = setCoef)
self.createFloater(frame, pageName, 'Length',
'Set linear cylinder vortex length',
command = setLength)
self.createFloater(frame, pageName, 'Radius',
'Set linear cylinder vortex radius',
command = setRadius)
self.createCheckbutton(frame, pageName, cbName,
'On: force is enabled; Off: force is disabled',
toggle, 1)
frame.pack(fill = 'x', expand =0)
###################################################################### ######################################################################