| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929 |
- """PANDA3D Particle Panel"""
- __all__ = ['ParticlePanel']
- # Import Tkinter, Pmw, and the floater code from this directory tree.
- from panda3d.core import ColorBlendAttrib, ConfigVariableSearchPath, Filename, Point2, Point3, Vec3, Vec4, getModelPath
- from panda3d.physics import (
- BaseParticleEmitter,
- BaseParticleRenderer,
- BoxEmitter,
- ColorInterpolationFunctionConstant,
- ColorInterpolationFunctionLinear,
- ColorInterpolationFunctionSinusoid,
- ColorInterpolationFunctionStepwave,
- DiscEmitter,
- GeomParticleRenderer,
- LinearCylinderVortexForce,
- LinearDistanceForce,
- LinearFrictionForce,
- LinearJitterForce,
- LinearNoiseForce,
- LinearSinkForce,
- LinearSourceForce,
- LinearUserDefinedForce,
- LinearVectorForce,
- LineEmitter,
- LineParticleRenderer,
- PointEmitter,
- PointParticleRenderer,
- RectangleEmitter,
- RingEmitter,
- SparkleParticleRenderer,
- SphereSurfaceEmitter,
- SphereVolumeEmitter,
- SpriteAnim,
- SpriteParticleRenderer,
- TangentRingEmitter,
- )
- from direct.tkwidgets.AppShell import AppShell
- from direct.tkwidgets import Dial
- from direct.tkwidgets import Floater
- from direct.tkwidgets import Slider
- from direct.tkwidgets import VectorWidgets
- from direct.tkpanels import Placer
- from direct.particles import ForceGroup
- from direct.particles import Particles
- from direct.particles import ParticleEffect
- from tkinter.filedialog import askopenfilename, asksaveasfilename
- from tkinter.simpledialog import askstring
- import Pmw
- import os
- import tkinter as tk
- particlePath = ConfigVariableSearchPath("particle-path",
- "The directories to search for particle files to be loaded.")
- class ParticlePanel(AppShell):
- # Override class variables
- appname = 'Particle Panel'
- frameWidth = 375
- frameHeight = 675
- usecommandarea = 0
- usestatusarea = 0
- balloonState = 'both'
- def __init__(self, particleEffect = None, **kw):
- INITOPT = Pmw.INITOPT
- optiondefs = (
- ('title', self.appname, None),
- )
- self.defineoptions(kw, optiondefs)
- # Record particle effect
- if particleEffect is not None:
- self.particleEffect = particleEffect
- else:
- # Make sure particles are enabled
- base.enableParticles()
- # Or create a new one if none given
- particles = Particles.Particles()
- particles.setBirthRate(0.02)
- particles.setLitterSize(10)
- particles.setLitterSpread(0)
- particles.setFactory("PointParticleFactory")
- particles.setRenderer("PointParticleRenderer")
- particles.setEmitter("SphereVolumeEmitter")
- particles.enable()
- pe = ParticleEffect.ParticleEffect('effect-1', particles)
- self.particleEffect = pe
- pe.reparentTo(render)
- pe.enable()
- # Initialize application specific info
- AppShell.__init__(self)
- # Initialize panel Pmw options
- self.initialiseoptions(ParticlePanel)
- # Update panel values to reflect particle effect's state
- self.selectEffectNamed(next(iter(self.effectsDict)))
- # 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):
- # Create dictionaries to keep track of panel objects
- self.widgetDict = {}
- self.variableDict = {}
- self.effectsDict = {}
- self.effectsDict[self.particleEffect.getName()] = (
- self.particleEffect)
- self.forcePagesDict = {}
- def createInterface(self):
- # Handle to the toplevels hull
- interior = self.interior()
- # Create particle panel menu items
- ## MENUBAR ENTRIES ##
- # FILE MENU
- # Get a handle on the file menu, and delete the Quit item that AppShell
- # created so we can add it back after adding the other items.
- self.menuBar.deletemenuitems('File', 0, 0)
- self.menuBar.addmenuitem('File', 'command',
- label='Load Params',
- command=self.loadParticleEffectFromFile)
- self.menuBar.addmenuitem('File', 'command',
- label='Save Params',
- command=self.saveParticleEffectToFile)
- self.menuBar.addmenuitem('File', 'command',
- label='Print Params',
- command=lambda s=self:s.particles.printParams())
- self.menuBar.addmenuitem('File', 'command', 'Quit this application',
- label='Quit',
- command=self.quit)
- # PARTICLE MANAGER MENU
- self.menuBar.addmenu('ParticleMgr', 'ParticleMgr Operations')
- self.particleMgrActive = tk.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 = tk.Frame(interior)
- # Current effect
- self.effectsLabel = tk.Menubutton(labelFrame, width = 10,
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 12, 'bold'),
- activebackground = '#909090')
- self.effectsLabelMenu = tk.Menu(self.effectsLabel, tearoff = 0)
- self.effectsLabel['menu'] = self.effectsLabelMenu
- self.effectsLabel.pack(side = tk.LEFT, fill = 'x', expand = 1)
- self.bind(self.effectsLabel,
- 'Select effect to configure or create new effect')
- self.effectsLabelMenu.add_command(label = 'Create New Effect',
- command = self.createNewEffect)
- self.effectsLabelMenu.add_command(
- label = 'Select Particle Effect',
- command = lambda s = self: base.direct.select(s.particleEffect))
- self.effectsLabelMenu.add_command(
- label = 'Place Particle Effect',
- command = lambda s = self: Placer.place(s.particleEffect))
- def togglePEVis(s = self):
- if s.particleEffect.isHidden():
- s.particleEffect.show()
- else:
- s.particleEffect.hide()
- self.effectsLabelMenu.add_command(
- label = 'Toggle Effect Vis',
- command = togglePEVis)
- self.effectsEnableMenu = tk.Menu(self.effectsLabelMenu, tearoff = 0)
- self.effectsLabelMenu.add_cascade(label = 'Enable/Disable',
- menu = self.effectsEnableMenu)
- self.effectsLabelMenu.add_separator()
- # Current particles
- self.particlesLabel = tk.Menubutton(labelFrame, width = 10,
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 12, 'bold'),
- activebackground = '#909090')
- self.particlesLabelMenu = tk.Menu(self.particlesLabel, tearoff = 0)
- self.particlesLabel['menu'] = self.particlesLabelMenu
- self.particlesLabel.pack(side = tk.LEFT, fill = 'x', expand = 1)
- self.bind(self.particlesLabel,
- ('Select particles object to configure ' +
- 'or add new particles object to current effect'))
- self.particlesLabelMenu.add_command(label = 'Create New Particles',
- command = self.createNewParticles)
- self.particlesEnableMenu = tk.Menu(self.particlesLabelMenu, tearoff = 0)
- self.particlesLabelMenu.add_cascade(label = 'Enable/Disable',
- menu = self.particlesEnableMenu)
- self.particlesLabelMenu.add_separator()
- # Current force
- self.forceGroupLabel = tk.Menubutton(labelFrame, width = 10,
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 12, 'bold'),
- activebackground = '#909090')
- self.forceGroupLabelMenu = tk.Menu(self.forceGroupLabel, tearoff = 0)
- self.forceGroupLabel['menu'] = self.forceGroupLabelMenu
- self.forceGroupLabel.pack(side = tk.LEFT, fill = 'x', expand = 1)
- self.bind(self.forceGroupLabel,
- ('Select force group to configure ' +
- 'or add a new force group to current effect'))
- self.forceGroupLabelMenu.add_command(
- label = 'Create New ForceGroup',
- command = self.createNewForceGroup)
- self.forceGroupEnableMenu = tk.Menu(self.forceGroupLabelMenu, tearoff = 0)
- self.forceGroupLabelMenu.add_cascade(label = 'Enable/Disable',
- menu = self.forceGroupEnableMenu)
- self.forceGroupLabelMenu.add_separator()
- # Pack labels
- labelFrame.pack(fill = 'x', expand = 0)
- # Create the toplevel notebook pages
- self.mainNotebook = Pmw.NoteBook(interior)
- self.mainNotebook.pack(fill = tk.BOTH, expand = 1)
- systemPage = self.mainNotebook.add('System')
- factoryPage = self.mainNotebook.add('Factory')
- emitterPage = self.mainNotebook.add('Emitter')
- rendererPage = self.mainNotebook.add('Renderer')
- forcePage = self.mainNotebook.add('Force')
- # Put this here so it isn't called right away
- self.mainNotebook['raisecommand'] = self.updateInfo
- ## SYSTEM PAGE WIDGETS ##
- # Create system floaters
- systemFloaterDefs = (
- ('System', 'Pool Size',
- 'Max number of simultaneous particles',
- self.setSystemPoolSize,
- 1.0, 2000000, 1.0),
- ('System', 'Birth Rate',
- 'Seconds between particle births',
- self.setSystemBirthRate,
- 0.0, None, None),
- ('System', 'Litter Size',
- 'Number of particle created at each birth',
- self.setSystemLitterSize,
- 1.0, 0x7fffffff, 1.0),
- ('System', 'Litter Spread',
- 'Variation in litter size',
- self.setSystemLitterSpread,
- 0.0, 0x7fffffff, 1.0),
- ('System', 'Lifespan',
- 'Age in seconds at which the system (vs. particles) should die',
- self.setSystemLifespan,
- 0.0, None, None)
- )
- self.createFloaters(systemPage, systemFloaterDefs)
- # Checkboxes
- self.createCheckbutton(
- systemPage, 'System', 'Render Space Velocities',
- ('On: velocities are in render space; ' +
- 'Off: velocities are in particle local space'),
- self.toggleSystemLocalVelocity, 0)
- self.createCheckbutton(
- systemPage, 'System', 'System Grows Older',
- 'On: system has a lifespan',
- self.toggleSystemGrowsOlder, 0)
- # Vector widgets
- pos = self.createVector3Entry(systemPage, 'System', 'Pos',
- 'Particle system position',
- command = self.setSystemPos)
- pos.addMenuItem('Popup Placer Panel', Placer.Placer)
- hpr = self.createVector3Entry(systemPage, 'System', 'Hpr',
- 'Particle system orientation',
- fGroup_labels = ('H', 'P', 'R'),
- command = self.setSystemHpr)
- hpr.addMenuItem('Popup Placer Panel', Placer.Placer)
- ## FACTORY PAGE WIDGETS ##
- self.createOptionMenu(
- factoryPage,
- 'Factory', 'Factory Type',
- 'Select type of particle factory',
- ('PointParticleFactory', 'ZSpinParticleFactory',
- #'OrientedParticleFactory'
- ),
- self.selectFactoryType)
- factoryWidgets = (
- ('Factory', 'Life Span',
- 'Average particle lifespan in seconds',
- self.setFactoryLifeSpan,
- 0.0, None, None),
- ('Factory', 'Life Span Spread',
- 'Variation in lifespan',
- self.setFactoryLifeSpanSpread,
- 0.0, None, None),
- ('Factory', 'Mass',
- 'Average particle mass',
- self.setFactoryParticleMass,
- 0.001, None, None),
- ('Factory', 'Mass Spread',
- 'Variation in particle mass',
- self.setFactoryParticleMassSpread,
- 0.0, None, None),
- ('Factory', 'Terminal Velocity',
- 'Cap on average particle velocity',
- self.setFactoryTerminalVelocity,
- 0.0, None, None),
- ('Factory', 'Terminal Vel. Spread',
- 'Variation in terminal velocity',
- self.setFactoryTerminalVelocitySpread,
- 0.0, None, None),
- )
- self.createFloaters(factoryPage, factoryWidgets)
- self.factoryNotebook = Pmw.NoteBook(factoryPage, tabpos = None)
- # Point page #
- factoryPointPage = self.factoryNotebook.add('PointParticleFactory')
- # Z spin page #
- zSpinPage = self.factoryNotebook.add('ZSpinParticleFactory')
- self.createCheckbutton(
- zSpinPage, 'Z Spin Factory', 'Enable Angular Velocity',
- 'On: angular velocity is used; Off: final angle is used',
- self.toggleAngularVelocity, 0, side = tk.TOP)
- self.createFloater(
- zSpinPage, 'Z Spin Factory', 'Angular Velocity',
- 'How fast sprites rotate',
- command = self.setFactoryZSpinAngularVelocity)
- self.createFloater(
- zSpinPage, 'Z Spin Factory', 'Angular Velocity Spread',
- 'Variation in how fast sprites rotate',
- command = self.setFactoryZSpinAngularVelocitySpread)
- self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Initial Angle',
- 'Starting angle in degrees',
- fRollover = 1,
- command = self.setFactoryZSpinInitialAngle)
- self.createAngleDial(
- zSpinPage, 'Z Spin Factory',
- 'Initial Angle Spread',
- 'Spread of the initial angle',
- fRollover = 1,
- command = self.setFactoryZSpinInitialAngleSpread)
- self.createAngleDial(zSpinPage, 'Z Spin Factory', 'Final Angle',
- 'Final angle in degrees',
- fRollover = 1,
- command = self.setFactoryZSpinFinalAngle)
- self.createAngleDial(
- zSpinPage, 'Z Spin Factory',
- 'Final Angle Spread',
- 'Spread of the final angle',
- fRollover = 1,
- command = self.setFactoryZSpinFinalAngleSpread)
- # Oriented page #
- orientedPage = self.factoryNotebook.add('OrientedParticleFactory')
- tk.Label(orientedPage, text = 'Not implemented').pack(expand = 1,
- fill = tk.BOTH)
- self.factoryNotebook.pack(expand = 1, fill = tk.BOTH)
- ## EMITTER PAGE WIDGETS ##
- self.createOptionMenu(
- emitterPage, 'Emitter',
- 'Emitter Type',
- 'Select type of particle emitter',
- ('BoxEmitter', 'DiscEmitter', 'LineEmitter', 'PointEmitter',
- 'RectangleEmitter', 'RingEmitter', 'SphereVolumeEmitter',
- 'SphereSurfaceEmitter', 'TangentRingEmitter'),
- self.selectEmitterType)
- # Emitter modes
- self.emissionType = tk.IntVar()
- self.emissionType.set(BaseParticleEmitter.ETRADIATE)
- emissionFrame = tk.Frame(emitterPage)
- self.createRadiobutton(
- emissionFrame, 'left',
- 'Emitter', 'Explicit Emission',
- ('particles are all emitted in parallel, direction is based ' +
- 'on explicit velocity vector'),
- 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 Multiplier',
- 'launch velocity multiplier (all emission modes)',
- command = self.setEmitterAmplitude,
- min = None)
- self.createFloater(
- emitterPage, 'Emitter', 'Velocity Multiplier Spread',
- 'spread for launch velocity multiplier (all emission modes)',
- command = self.setEmitterAmplitudeSpread)
- self.createVector3Entry(
- emitterPage, 'Emitter', 'Offset Velocity',
- 'Velocity vector applied to all particles',
- command = self.setEmitterOffsetForce)
- self.createVector3Entry(
- emitterPage, 'Emitter', 'Explicit Velocity',
- 'all particles launch with this velocity in Explicit mode',
- command = self.setEmitterExplicitLaunchVector)
- self.createVector3Entry(
- emitterPage, 'Emitter', 'Radiate Origin',
- 'particles launch away from this point in Radiate mode',
- command = self.setEmitterRadiateOrigin)
- self.emitterNotebook = Pmw.NoteBook(emitterPage, tabpos = None)
- # Box page #
- boxPage = self.emitterNotebook.add('BoxEmitter')
- self.createVector3Entry(boxPage, 'Box Emitter', 'Min',
- 'Min point defining emitter box',
- command = self.setEmitterBoxPoint1)
- self.createVector3Entry(boxPage, 'Box Emitter', 'Max',
- 'Max point defining emitter box',
- command = self.setEmitterBoxPoint2,
- value = (1.0, 1.0, 1.0))
- # Disc page #
- discPage = self.emitterNotebook.add('DiscEmitter')
- self.createFloater(discPage, 'Disc Emitter', 'Radius',
- 'Radius of disc',
- command = self.setEmitterDiscRadius,
- min = 0.01)
- customPage = self.discCustomFrame = tk.Frame(discPage)
- self.createAngleDial(customPage, 'Disc Emitter', 'Inner Angle',
- 'Particle launch angle at center of disc',
- command = self.setEmitterDiscInnerAngle)
- self.createFloater(customPage, 'Disc Emitter', 'Inner Velocity',
- 'Launch velocity multiplier at center of disc',
- command = self.setEmitterDiscInnerVelocity)
- self.createAngleDial(customPage, 'Disc Emitter', 'Outer Angle',
- 'Particle launch angle at outer edge of disc',
- command = self.setEmitterDiscOuterAngle)
- self.createFloater(customPage, 'Disc Emitter', 'Outer Velocity',
- 'Launch velocity multiplier at edge of disc',
- command = self.setEmitterDiscOuterVelocity)
- self.createCheckbutton(
- customPage, 'Disc Emitter', 'Cubic Lerping',
- 'On: magnitude/angle interpolation from center',
- self.toggleEmitterDiscCubicLerping, 0)
- customPage.pack(fill = tk.BOTH, expand = 1)
- # Line page #
- linePage = self.emitterNotebook.add('LineEmitter')
- self.createVector3Entry(linePage, 'Line Emitter', 'Min',
- 'Min point defining emitter line',
- command = self.setEmitterLinePoint1)
- self.createVector3Entry(linePage, 'Line Emitter', 'Max',
- 'Max point defining emitter line',
- command = self.setEmitterLinePoint2,
- value = (1.0, 0.0, 0.0))
- # Point page #
- emitterPointPage = self.emitterNotebook.add('PointEmitter')
- self.createVector3Entry(emitterPointPage, 'Point Emitter', 'Position',
- 'Position of emitter point',
- command = self.setEmitterPointPosition)
- # Rectangle #
- rectanglePage = self.emitterNotebook.add('RectangleEmitter')
- self.createVector2Entry(rectanglePage,
- 'Rectangle Emitter', 'Min',
- 'Point defining rectangle',
- command = self.setEmitterRectanglePoint1)
- self.createVector2Entry(rectanglePage,
- 'Rectangle Emitter', 'Max',
- 'Point defining rectangle',
- command = self.setEmitterRectanglePoint2)
- # Ring #
- ringPage = self.emitterNotebook.add('RingEmitter')
- self.createFloater(ringPage, 'Ring Emitter', 'Radius',
- 'Radius of ring',
- command = self.setEmitterRingRadius,
- min = 0.01)
- self.createFloater(ringPage, 'Ring Emitter', 'Radius Spread',
- 'Variation in radius of ring',
- command = self.setEmitterRingRadiusSpread,
- min = 0.0)
- self.ringCustomFrame = tk.Frame(ringPage)
- self.createAngleDial(self.ringCustomFrame, 'Ring Emitter', 'Angle',
- 'Particle launch angle',
- command = self.setEmitterRingLaunchAngle)
- self.ringCustomFrame.pack(fill = tk.BOTH, expand = 1)
- # Sphere volume #
- sphereVolumePage = self.emitterNotebook.add('SphereVolumeEmitter')
- self.createFloater(sphereVolumePage, 'Sphere Volume Emitter', 'Radius',
- 'Radius of sphere',
- command = self.setEmitterSphereVolumeRadius,
- min = 0.01)
- # Sphere surface #
- sphereSurfacePage = self.emitterNotebook.add('SphereSurfaceEmitter')
- self.createFloater(sphereSurfacePage, 'Sphere Surface Emitter',
- 'Radius',
- 'Radius of sphere',
- command = self.setEmitterSphereSurfaceRadius,
- min = 0.01)
- # Tangent ring #
- tangentRingPage = self.emitterNotebook.add('TangentRingEmitter')
- self.createFloater(tangentRingPage, 'Tangent Ring Emitter', 'Radius',
- 'Radius of ring',
- command = self.setEmitterTangentRingRadius,
- min = 0.01)
- self.createFloater(tangentRingPage, 'Tangent Ring Emitter',
- 'Radius Spread',
- 'Variation in radius of ring',
- command = self.setEmitterTangentRingRadiusSpread)
- self.emitterNotebook.pack(fill = tk.X)
- ## RENDERER PAGE WIDGETS ##
- self.createOptionMenu(
- rendererPage, 'Renderer', 'Renderer Type',
- 'Select type of particle renderer',
- ('LineParticleRenderer', 'GeomParticleRenderer',
- 'PointParticleRenderer', 'SparkleParticleRenderer',
- 'SpriteParticleRenderer'),
- self.selectRendererType)
- self.createOptionMenu(rendererPage,
- 'Renderer', 'Alpha Mode',
- "alpha setting over particles' lifetime",
- ('NO_ALPHA','ALPHA_IN','ALPHA_OUT',
- 'ALPHA_IN_OUT', 'ALPHA_USER'),
- self.setRendererAlphaMode)
- self.createSlider(
- rendererPage, 'Renderer', 'User Alpha',
- 'alpha value for ALPHA_USER alpha mode',
- command = self.setRendererUserAlpha)
- self.rendererNotebook = Pmw.NoteBook(rendererPage, tabpos = None)
- self.rendererNotebook.pack(fill = tk.BOTH, expand = 1)
- # Line page #
- linePage = self.rendererNotebook.add('LineParticleRenderer')
- self.createColorEntry(linePage, 'Line Renderer', 'Head Color',
- 'Head color of line',
- command = self.setRendererLineHeadColor)
- self.createColorEntry(linePage, 'Line Renderer', 'Tail Color',
- 'Tail color of line',
- command = self.setRendererLineTailColor)
- self.createFloater(linePage, 'Line Renderer', 'Line Scale Factor',
- 'Scale Factor applied to length of line',
- command = self.setRendererLineScaleFactor)
- ############################################################################
- # GEOM PARTICLE RENDERER PAGE #
- ############################################################################
- geomPage = self.rendererNotebook.add('GeomParticleRenderer')
- f = tk.Frame(geomPage)
- f.pack(fill = tk.X)
- # Geom Node input field
- tk.Label(f, width = 12, text = 'Geom Node', pady = 3).pack(side = tk.LEFT)
- self.rendererGeomNode = tk.StringVar()
- self.rendererGeomNodeEntry = tk.Entry(f, width = 12,
- textvariable = self.rendererGeomNode)
- self.rendererGeomNodeEntry.bind('<Return>', self.setRendererGeomNode)
- self.rendererGeomNodeEntry.pack(side = tk.LEFT, expand = 1, fill = tk.X)
- # Setup frames
- f = tk.Frame(geomPage)
- f.pack(fill = tk.BOTH, expand = 1)
- rendererGeomNotebook = Pmw.NoteBook(f)
- rendererGeomNotebook.pack(fill = tk.BOTH, expand = 1)
- rendererGeomBlendPage = rendererGeomNotebook.add('Blend')
- rendererGeomScalePage = rendererGeomNotebook.add('Scale')
- rendererGeomInterpolationPage = rendererGeomNotebook.add('Interpolate')
- ############################################################################
- # Blend tab
- p = tk.Frame(rendererGeomBlendPage)
- p.pack(fill = tk.X)
- self.createOptionMenu(p, 'Geom Renderer',
- 'Color Blend',
- 'How to render semi-transparent colors',
- ('MNone','MAdd','MSubtract','MInvSubtract','MMin','MMax'),
- self.setRendererGeomColorBlendMethod)
- self.createOptionMenu(p, 'Geom Renderer',
- 'Incoming Op.',
- 'See ColorBlendAttrib.h for explanation',
- ('OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor',
- 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha',
- 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor',
- 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha',
- 'OIncomingColorSaturate','OZero'),
- self.setRendererGeomColorBlendIncomingOperand)
- self.getVariable('Geom Renderer','Incoming Op.').set('OIncomingAlpha')
- self.createOptionMenu(p, 'Geom Renderer',
- 'Fbuffer Op.',
- 'See ColorBlendAttrib.h for explanation',
- ('OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor',
- 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha',
- 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor',
- 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha',
- 'OZero'),
- self.setRendererGeomColorBlendFbufferOperand)
- self.getVariable('Geom Renderer','Fbuffer Op.').set('OOneMinusIncomingAlpha')
- ############################################################################
- # Scale tab
- p = tk.Frame(rendererGeomScalePage)
- p.pack(fill = tk.X)
- self.createCheckbutton(
- p, 'Geom Renderer', 'X Scale',
- ("On: x scale is interpolated over particle's life; " +
- "Off: stays as start_X_Scale"),
- self.toggleRendererGeomXScale, 0, side = tk.LEFT)
- self.createCheckbutton(
- p, 'Geom Renderer', 'Y Scale',
- ("On: y scale is interpolated over particle's life; " +
- "Off: stays as start_Y_Scale"),
- self.toggleRendererGeomYScale, 0, side = tk.LEFT)
- self.createCheckbutton(
- p, 'Geom Renderer', 'Z Scale',
- ("On: z scale is interpolated over particle's life; " +
- "Off: stays as start_Z_Scale"),
- self.toggleRendererGeomZScale, 0, side = tk.LEFT)
- p = tk.Frame(rendererGeomScalePage)
- p.pack(fill = tk.X)
- self.createFloater(p, 'Geom Renderer',
- 'Initial X Scale',
- 'Initial X scaling factor',
- command = self.setRendererGeomInitialXScale)
- self.createFloater(p, 'Geom Renderer',
- 'Final X Scale',
- 'Final X scaling factor, if xScale enabled',
- command = self.setRendererGeomFinalXScale)
- self.createFloater(p, 'Geom Renderer',
- 'Initial Y Scale',
- 'Initial Y scaling factor',
- command = self.setRendererGeomInitialYScale)
- self.createFloater(p, 'Geom Renderer',
- 'Final Y Scale',
- 'Final Y scaling factor, if yScale enabled',
- command = self.setRendererGeomFinalYScale)
- self.createFloater(p, 'Geom Renderer',
- 'Initial Z Scale',
- 'Initial Z scaling factor',
- command = self.setRendererGeomInitialZScale)
- self.createFloater(p, 'Geom Renderer',
- 'Final Z Scale',
- 'Final Z scaling factor, if zScale enabled',
- command = self.setRendererGeomFinalZScale)
- ############################################################################
- # Interpolate tab
- p = tk.Frame(rendererGeomInterpolationPage)
- p.pack(fill = tk.X)
- addSegmentButton = tk.Menubutton(p, text = 'Add Segment',
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 14, 'bold'),
- activebackground = '#909090')
- segmentMenu = tk.Menu(addSegmentButton)
- addSegmentButton['menu'] = segmentMenu
- segmentMenu.add_command(label = 'Add Constant segment',
- command = self.addConstantInterpolationSegment)
- segmentMenu.add_command(label = 'Add Linear segment',
- command = self.addLinearInterpolationSegment)
- segmentMenu.add_command(label = 'Add Stepwave segment',
- command = self.addStepwaveInterpolationSegment)
- segmentMenu.add_command(label = 'Add Sinusoid segment',
- command = self.addSinusoidInterpolationSegment)
- addSegmentButton.pack(expand = 0)
- sf = Pmw.ScrolledFrame(p, horizflex = 'elastic')
- sf.pack(fill = tk.BOTH, expand = 1)
- self.rendererGeomSegmentFrame = sf.interior()
- self.rendererGeomSegmentFrame.pack(fill = tk.BOTH, expand = 1)
- self.rendererSegmentWidgetList = []
- rendererGeomNotebook.setnaturalsize()
- ############################################################################
- # POINT PARTICLE RENDERER PAGE #
- ############################################################################
- rendererPointPage = self.rendererNotebook.add('PointParticleRenderer')
- self.createFloater(rendererPointPage, 'Point Renderer', 'Point Size',
- 'Width and height of points in pixels',
- command = self.setRendererPointSize)
- self.createColorEntry(rendererPointPage, 'Point Renderer',
- 'Start Color',
- 'Starting color of point',
- command = self.setRendererPointStartColor)
- self.createColorEntry(rendererPointPage, 'Point Renderer',
- 'End Color',
- 'Ending color of point',
- command = self.setRendererPointEndColor)
- self.createOptionMenu(rendererPointPage, 'Point Renderer',
- 'Blend Type',
- 'Type of color blending used for particle',
- ('PP_ONE_COLOR', 'PP_BLEND_LIFE',
- 'PP_BLEND_VEL'),
- self.rendererPointSelectBlendType)
- self.createOptionMenu(rendererPointPage, 'Point Renderer',
- 'Blend Method',
- 'Interpolation method between colors',
- ('PP_NO_BLEND', 'PP_BLEND_LINEAR',
- 'PP_BLEND_CUBIC'),
- self.rendererPointSelectBlendMethod)
- # Sparkle #
- sparklePage = self.rendererNotebook.add('SparkleParticleRenderer')
- self.createColorEntry(sparklePage, 'Sparkle Renderer',
- 'Center Color',
- 'Color of sparkle center',
- command = self.setRendererSparkleCenterColor)
- self.createColorEntry(sparklePage, 'Sparkle Renderer',
- 'Edge Color',
- 'Color of sparkle line endpoints',
- command = self.setRendererSparkleEdgeColor)
- self.createFloater(sparklePage, 'Sparkle Renderer',
- 'Birth Radius',
- 'Initial sparkle radius',
- command = self.setRendererSparkleBirthRadius)
- self.createFloater(sparklePage, 'Sparkle Renderer',
- 'Death Radius',
- 'Final sparkle radius',
- command = self.setRendererSparkleDeathRadius)
- self.createOptionMenu(sparklePage,
- 'Sparkle Renderer', 'Life Scale',
- 'Does particle scale over its lifetime?',
- ('SP_NO_SCALE', 'SP_SCALE'),
- self.setRendererSparkleLifeScale)
- # Sprite #
- spritePage = self.rendererNotebook.add('SpriteParticleRenderer')
- f = tk.Frame(spritePage)
- f.pack(fill = tk.BOTH, expand = 1)
- rendererSpriteNotebook = Pmw.NoteBook(f)
- rendererSpriteNotebook.pack(fill = tk.BOTH, expand = 1)
- rendererSpriteTexturePage = rendererSpriteNotebook.add('Texture')
- rendererSpriteScalePage = rendererSpriteNotebook.add('Scale')
- rendererSpriteBlendPage = rendererSpriteNotebook.add('Blend')
- rendererSpriteInterpolationPage = rendererSpriteNotebook.add('Interpolate')
- ##################################################################################
- p = tk.Frame(rendererSpriteTexturePage)
- p.pack(fill = tk.BOTH, expand = 1)
- bp = tk.Frame(p)
- bp.pack(expand = 0, side = tk.TOP)
- bbp = tk.Frame(bp)
- bbp.pack()
- self.createCheckbutton(
- bbp, 'Sprite Renderer', 'Enable Animation',
- ("On: Multitexture node will be animated; " +
- "Off: Only the first frame of a node is rendered"),
- self.setRendererSpriteAnimationEnable, 0, side = tk.LEFT)
- self.createFloater(bbp, 'Sprite Renderer', 'Frame Rate', 'Animation frame rate',
- command = self.setRendererSpriteAnimationFrameRate).pack(side = tk.LEFT)
- bbp = tk.Frame(bp)
- bbp.pack(pady=3)
- tk.Button(bbp, text = 'Add Texture',
- command = self.addRendererSpriteAnimationTexture).pack(pady = 3, padx = 15, side = tk.LEFT)
- tk.Button(bbp, text = 'Add Animation',
- command = self.addRendererSpriteAnimationFromNode).pack(pady = 3, padx = 15, side = tk.LEFT)
- pp = tk.Frame(p)
- pp.pack(fill = tk.BOTH, expand = 1, pady = 3)
- sf = Pmw.ScrolledFrame(pp, horizflex = 'elastic')
- sf.pack(fill = tk.BOTH, expand = 1)
- self.rendererSpriteAnimationFrame = sf.interior()
- self.rendererSpriteAnimationFrame.pack(fill = tk.BOTH, expand = 1)
- self.rendererSpriteAnimationWidgetList = []
- self.rendererSpriteTexture = tk.StringVar()
- self.rendererSpriteFile = tk.StringVar()
- self.rendererSpriteNode = tk.StringVar()
- ##################################################################################
- p = tk.Frame(rendererSpriteScalePage)
- p.pack(fill = tk.X)
- self.createCheckbutton(
- p, 'Sprite Renderer', 'X Scale',
- ("On: x scale is interpolated over particle's life; " +
- "Off: stays as start_X_Scale"),
- self.toggleRendererSpriteXScale, 0, side = tk.LEFT)
- self.createCheckbutton(
- p, 'Sprite Renderer', 'Y Scale',
- ("On: y scale is interpolated over particle's life; " +
- "Off: stays as start_Y_Scale"),
- self.toggleRendererSpriteYScale, 0, side = tk.LEFT)
- self.createCheckbutton(
- p, 'Sprite Renderer', 'Anim Angle',
- ("On: particles that are set to spin on the Z axis will " +
- "spin appropriately"),
- self.toggleRendererSpriteAnimAngle, 0, side = tk.LEFT)
- p = tk.Frame(rendererSpriteScalePage)
- p.pack(fill = tk.X)
- self.createFloater(p, 'Sprite Renderer',
- 'Initial X Scale',
- 'Initial X scaling factor',
- command = self.setRendererSpriteInitialXScale)
- self.createFloater(p, 'Sprite Renderer',
- 'Final X Scale',
- 'Final X scaling factor, if xScale enabled',
- command = self.setRendererSpriteFinalXScale)
- self.createFloater(p, 'Sprite Renderer',
- 'Initial Y Scale',
- 'Initial Y scaling factor',
- command = self.setRendererSpriteInitialYScale)
- self.createFloater(p, 'Sprite Renderer',
- 'Final Y Scale',
- 'Final Y scaling factor, if yScale enabled',
- command = self.setRendererSpriteFinalYScale)
- self.createAngleDial(p, 'Sprite Renderer',
- 'Non Animated Theta',
- ('If animAngle is false: counter clockwise ' +
- 'Z rotation of all sprites'),
- command = self.setRendererSpriteNonAnimatedTheta)
- p = tk.Frame(rendererSpriteBlendPage)
- p.pack(fill = tk.X)
- self.createOptionMenu(p, 'Sprite Renderer',
- 'Blend Type',
- 'Interpolation blend type for X and Y scaling',
- ('PP_NO_BLEND', 'PP_LINEAR', 'PP_CUBIC'),
- self.setRendererSpriteBlendMethod)
- self.createCheckbutton(
- p, 'Sprite Renderer', 'Alpha Disable',
- 'On: alpha blending is disabled',
- self.toggleRendererSpriteAlphaDisable, 0)
- self.createOptionMenu(p, 'Sprite Renderer',
- 'Color Blend',
- 'How to render semi-transparent colors',
- ('MNone','MAdd','MSubtract','MInvSubtract','MMin','MMax'),
- self.setRendererSpriteColorBlendMethod)
- self.createOptionMenu(p, 'Sprite Renderer',
- 'Incoming Op.',
- 'See ColorBlendAttrib.h for explanation',
- ('OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor',
- 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha',
- 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor',
- 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha',
- 'OIncomingColorSaturate','OZero'),
- self.setRendererSpriteColorBlendIncomingOperand)
- self.getVariable('Sprite Renderer','Incoming Op.').set('OIncomingAlpha')
- self.createOptionMenu(p, 'Sprite Renderer',
- 'Fbuffer Op.',
- 'See ColorBlendAttrib.h for explanation',
- ('OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor',
- 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha',
- 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor',
- 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha',
- 'OZero'),
- self.setRendererSpriteColorBlendFbufferOperand)
- self.getVariable('Sprite Renderer','Fbuffer Op.').set('OOneMinusIncomingAlpha')
- p = tk.Frame(rendererSpriteInterpolationPage)
- p.pack(fill = tk.BOTH, expand = 1)
- addSegmentButton = tk.Menubutton(p, text = 'Add Segment',
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 14, 'bold'),
- activebackground = '#909090')
- segmentMenu = tk.Menu(addSegmentButton)
- addSegmentButton['menu'] = segmentMenu
- segmentMenu.add_command(label = 'Add Constant segment',
- command = self.addConstantInterpolationSegment)
- segmentMenu.add_command(label = 'Add Linear segment',
- command = self.addLinearInterpolationSegment)
- segmentMenu.add_command(label = 'Add Stepwave segment',
- command = self.addStepwaveInterpolationSegment)
- segmentMenu.add_command(label = 'Add Sinusoid segment',
- command = self.addSinusoidInterpolationSegment)
- addSegmentButton.pack(expand = 0)
- pp = tk.Frame(p)
- pp.pack(fill = tk.BOTH, expand = 1, pady = 3)
- sf = Pmw.ScrolledFrame(pp, horizflex = 'elastic')
- sf.pack(fill = tk.BOTH, expand = 1)
- self.rendererSpriteSegmentFrame = sf.interior()
- self.rendererSpriteSegmentFrame.pack(fill = tk.BOTH, expand = 1)
- self.rendererSegmentWidgetList = []
- rendererSpriteNotebook.setnaturalsize()
- ##########################################################
- ## FORCE PAGE WIDGETS ##
- self.addForceButton = tk.Menubutton(forcePage, text = 'Add Force',
- relief = tk.RAISED,
- borderwidth = 2,
- font=('MSSansSerif', 14, 'bold'),
- activebackground = '#909090')
- forceMenu = tk.Menu(self.addForceButton)
- self.addForceButton['menu'] = forceMenu
- # DERIVED FROM LINEAR FORCE
- # This also has: setVector
- forceMenu.add_command(label = 'Add Linear Vector Force',
- command = self.addLinearVectorForce)
- # Parameters: setAmplitude, setMassDependent, setVectorMasks
- forceMenu.add_command(label = 'Add Linear Noise Force',
- command = self.addLinearNoiseForce)
- forceMenu.add_command(label = 'Add Linear Jitter Force',
- command = self.addLinearJitterForce)
- # This also has setCoef
- forceMenu.add_command(label = 'Add Linear Friction Force',
- command = self.addLinearFrictionForce)
- # This also has: setCoef, setLength, setRadius,
- forceMenu.add_command(label = 'Add Linear Cylinder Vortex Force',
- command = self.addLinearCylinderVortexForce)
- # DERIVED FROM LINEAR DISTANCE FORCE
- # Parameters: setFalloffType, setForceCenter, setRadius
- forceMenu.add_command(label = 'Add Linear Sink Force',
- command = self.addLinearSinkForce)
- forceMenu.add_command(label = 'Add Linear Source Force',
- command = self.addLinearSourceForce)
- """
- # Avoid for now
- forceMenu.add_command(label = 'Add Linear User Defined Force',
- command = self.addLinearUserDefinedForce)
- """
- self.addForceButton.pack(expand = 0)
- # Scrolled frame to hold force widgets
- self.sf = Pmw.ScrolledFrame(forcePage, horizflex = 'elastic')
- self.sf.pack(fill = 'both', expand = 1)
- self.forceFrame = self.sf.interior()
- # Notebook to hold force widgets as the are added
- self.forceGroupNotebook = Pmw.NoteBook(self.forceFrame, tabpos = None)
- self.forceGroupNotebook.pack(fill = tk.X)
- ########################################################################
- self.factoryNotebook.setnaturalsize()
- self.emitterNotebook.setnaturalsize()
- self.rendererNotebook.setnaturalsize()
- self.forceGroupNotebook.setnaturalsize()
- self.mainNotebook.setnaturalsize()
- # Make sure input variables processed
- self.initialiseoptions(ParticlePanel)
- ### WIDGET UTILITY FUNCTIONS ###
- def createCheckbutton(self, parent, category, text,
- balloonHelp, command, initialState, side = 'top'):
- bool = tk.BooleanVar()
- bool.set(initialState)
- widget = tk.Checkbutton(parent, text = text, anchor = tk.W,
- variable = bool)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X, side = side)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- self.variableDict[category + '-' + text] = bool
- return widget
- def createRadiobutton(self, parent, side, category, text,
- balloonHelp, variable, value,
- command):
- widget = tk.Radiobutton(parent, text = text, anchor = tk.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 = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createFloaters(self, parent, widgetDefinitions):
- widgets = []
- for category, label, balloonHelp, command, min, max, resolution in widgetDefinitions:
- widgets.append(
- self.createFloater(parent, category, label, balloonHelp,
- command, min, max, resolution)
- )
- return widgets
- def createFloater(self, parent, category, text, balloonHelp,
- command = None, min = 0.0, max = None, resolution = None,
- numDigits = None, **kw):
- kw['text'] = text
- kw['min'] = min
- if max is not None:
- kw['max'] = max
- kw['resolution'] = resolution
- if numDigits is None:
- # If this is apparently an integer setting, show no decimals.
- if resolution is not None and int(resolution) == resolution and \
- (min is None or int(min) == min) and \
- (max is None or int(max) == max):
- numDigits = 0
- else:
- numDigits = 3
- kw['numDigits'] = numDigits
- widget = Floater.Floater(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createAngleDial(self, parent, category, text, balloonHelp,
- command = None, **kw):
- kw['text'] = text
- kw['style'] = 'mini'
- widget = Dial.AngleDial(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createSlider(self, parent, category, text, balloonHelp,
- command = None, min = 0.0, max = 1.0,
- resolution = 0.001, **kw):
- kw['text'] = text
- kw['min'] = min
- kw['max'] = max
- kw['resolution'] = resolution
- widget = Slider.Slider(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createVector2Entry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = VectorWidgets.Vector2Entry(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createVector3Entry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = VectorWidgets.Vector3Entry(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createColorEntry(self, parent, category, text, balloonHelp,
- command = None, **kw):
- # Set label's text
- kw['text'] = text
- widget = VectorWidgets.ColorEntry(parent, **kw)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget, balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- return widget
- def createOptionMenu(self, parent, category, text, balloonHelp,
- items, command):
- optionVar = tk.StringVar()
- if len(items) > 0:
- optionVar.set(items[0])
- widget = Pmw.OptionMenu(parent, labelpos = tk.W, label_text = text,
- label_width = 12, menu_tearoff = 1,
- menubutton_textvariable = optionVar,
- items = items)
- # Do this after the widget so command isn't called on creation
- widget['command'] = command
- widget.pack(fill = tk.X)
- self.bind(widget.component('menubutton'), balloonHelp)
- self.widgetDict[category + '-' + text] = widget
- self.variableDict[category + '-' + text] = optionVar
- return optionVar
- def createComboBox(self, parent, category, text, balloonHelp,
- items, command, history = 0):
- widget = Pmw.ComboBox(parent,
- labelpos = tk.W,
- label_text = text,
- label_anchor = 'w',
- label_width = 12,
- entry_width = 16,
- history = history,
- 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:
- widget.selectitem(items[0])
- # Bind selection command
- widget['selectioncommand'] = command
- widget.pack(side = 'left', expand = 0)
- # Bind help
- self.bind(widget, balloonHelp)
- # Record widget
- self.widgetDict[category + '-' + text] = 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 is not None:
- self.forceGroupLabel['text'] = self.forceGroup.getName()
- else:
- self.forceGroupLabel['text'] = 'Force Group'
- 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')
- self.effectsLabelMenu.delete(5, 'end')
- self.effectsLabelMenu.add_separator()
- # Add in a checkbutton for each effect (to toggle on/off)
- keys = sorted(self.effectsDict.keys())
- for name in keys:
- effect = self.effectsDict[name]
- self.effectsLabelMenu.add_command(
- label = effect.getName(),
- command = (lambda s = self,
- e = effect: s.selectEffectNamed(e.getName()))
- )
- effectActive = tk.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')
- self.particlesLabelMenu.delete(2, 'end')
- self.particlesLabelMenu.add_separator()
- # Add in a checkbutton for each effect (to toggle on/off)
- particles = self.particleEffect.getParticlesList()
- for name in sorted(x.getName() for x in particles):
- particle = self.particleEffect.getParticlesNamed(name)
- self.particlesLabelMenu.add_command(
- label = name,
- command = (lambda s = self,
- n = name: s.selectParticlesNamed(n))
- )
- particleActive = tk.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')
- self.forceGroupLabelMenu.delete(2, 'end')
- self.forceGroupLabelMenu.add_separator()
- # Add in a checkbutton for each effect (to toggle on/off)
- forceGroupList = self.particleEffect.getForceGroupList()
- for name in sorted(x.getName() for x in forceGroupList):
- force = self.particleEffect.getForceGroupNamed(name)
- self.forceGroupLabelMenu.add_command(
- label = name,
- command = (lambda s = self,
- n = name: s.selectForceGroupNamed(n))
- )
- forceActive = tk.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 is not 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 is not 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 is not 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():
- force.setActive(1)
- else:
- force.setActive(0)
- def getWidget(self, category, text):
- return self.widgetDict[category + '-' + text]
- def getVariable(self, category, text):
- return self.variableDict[category + '-' + text]
- def loadParticleEffectFromFile(self):
- # Find path to particle directory
- pPath = particlePath
- if pPath.getNumDirectories() > 0:
- if repr(pPath.getDirectory(0)) == '.':
- path = '.'
- else:
- path = pPath.getDirectory(0).toOsSpecific()
- else:
- path = '.'
- if not os.path.isdir(path):
- print('ParticlePanel Warning: Invalid default DNA directory!')
- print('Using current directory')
- path = '.'
- particleFilename = askopenfilename(
- defaultextension = '.ptf',
- filetypes = (('Particle Files', '*.ptf'), ('All files', '*')),
- initialdir = path,
- title = 'Load Particle Effect',
- parent = self.parent)
- if particleFilename and particleFilename != 'None':
- # Delete existing particles and forces
- self.particleEffect.loadConfig(
- Filename.fromOsSpecific(particleFilename))
- self.selectEffectNamed(self.particleEffect.getName())
- # Enable effect
- self.particleEffect.enable()
- def saveParticleEffectToFile(self):
- # Find path to particle directory
- pPath = particlePath
- if pPath.getNumDirectories() > 0:
- if repr(pPath.getDirectory(0)) == '.':
- path = '.'
- else:
- path = pPath.getDirectory(0).toOsSpecific()
- else:
- path = '.'
- if not os.path.isdir(path):
- print('ParticlePanel Warning: Invalid default DNA directory!')
- print('Using current directory')
- path = '.'
- particleFilename = asksaveasfilename(
- defaultextension = '.ptf',
- filetypes = (('Particle Files', '*.ptf'), ('All files', '*')),
- initialdir = path,
- title = 'Save Particle Effect as',
- parent = self.parent)
- if particleFilename:
- self.particleEffect.saveConfig(Filename(particleFilename))
- ### PARTICLE EFFECTS COMMANDS ###
- def toggleParticleMgr(self):
- if self.particleMgrActive.get():
- base.enableParticles()
- else:
- base.disableParticles()
- ### PARTICLE SYSTEM COMMANDS ###
- def updateInfo(self, page = 'System'):
- self.updateMenusAndLabels()
- if page == 'System':
- self.updateSystemWidgets()
- elif page == 'Factory':
- self.selectFactoryPage()
- self.updateFactoryWidgets()
- elif page == 'Emitter':
- self.selectEmitterPage()
- self.updateEmitterWidgets()
- elif page == 'Renderer':
- self.selectRendererPage()
- self.updateRendererWidgets()
- elif page == 'Force':
- self.updateForceWidgets()
- def toggleParticleEffect(self):
- if self.getVariable('Effect', 'Active').get():
- self.particleEffect.enable()
- else:
- self.particleEffect.disable()
- ## SYSTEM PAGE ##
- def updateSystemWidgets(self):
- poolSize = self.particles.getPoolSize()
- self.getWidget('System', 'Pool Size').set(int(poolSize), 0)
- birthRate = self.particles.getBirthRate()
- self.getWidget('System', 'Birth Rate').set(birthRate, 0)
- litterSize = self.particles.getLitterSize()
- self.getWidget('System', 'Litter Size').set(int(litterSize), 0)
- litterSpread = self.particles.getLitterSpread()
- self.getWidget('System', 'Litter Spread').set(litterSpread, 0)
- systemLifespan = self.particles.getSystemLifespan()
- self.getWidget('System', 'Lifespan').set(systemLifespan, 0)
- pos = self.particles.nodePath.getPos()
- self.getWidget('System', 'Pos').set([pos[0], pos[1], pos[2]], 0)
- hpr = self.particles.nodePath.getHpr()
- self.getWidget('System', 'Hpr').set([hpr[0], hpr[1], hpr[2]], 0)
- self.getVariable('System', 'Render Space Velocities').set(
- self.particles.getLocalVelocityFlag())
- self.getVariable('System', 'System Grows Older').set(
- self.particles.getSystemGrowsOlderFlag())
- def setSystemPoolSize(self, value):
- self.particles.setPoolSize(int(value))
- def setSystemBirthRate(self, value):
- self.particles.setBirthRate(value)
- def setSystemLitterSize(self, value):
- self.particles.setLitterSize(int(value))
- def setSystemLitterSpread(self, value):
- self.particles.setLitterSpread(int(value))
- def setSystemLifespan(self, value):
- self.particles.setSystemLifespan(value)
- def toggleSystemLocalVelocity(self):
- self.particles.setLocalVelocityFlag(
- self.getVariable('System', 'Render Space Velocities').get())
- def toggleSystemGrowsOlder(self):
- self.particles.setSystemGrowsOlderFlag(
- self.getVariable('System', 'System Grows Older').get())
- def setSystemPos(self, pos):
- self.particles.nodePath.setPos(Vec3(pos[0], pos[1], pos[2]))
- def setSystemHpr(self, pos):
- self.particles.nodePath.setHpr(Vec3(pos[0], pos[1], pos[2]))
- ## FACTORY PAGE ##
- def selectFactoryType(self, type):
- self.factoryNotebook.selectpage(type)
- self.particles.setFactory(type)
- self.updateFactoryWidgets()
- def selectFactoryPage(self):
- pass
- def updateFactoryWidgets(self):
- factory = self.particles.factory
- lifespan = factory.getLifespanBase()
- self.getWidget('Factory', 'Life Span').set(lifespan, 0)
- lifespanSpread = factory.getLifespanSpread()
- self.getWidget('Factory', 'Life Span Spread').set(lifespanSpread, 0)
- mass = factory.getMassBase()
- self.getWidget('Factory', 'Mass').set(mass, 0)
- massSpread = factory.getMassSpread()
- self.getWidget('Factory', 'Mass Spread').set(massSpread, 0)
- terminalVelocity = factory.getTerminalVelocityBase()
- self.getWidget('Factory', 'Terminal Velocity').set(terminalVelocity, 0)
- terminalVelocitySpread = factory.getTerminalVelocitySpread()
- self.getWidget('Factory', 'Terminal Vel. Spread').set(
- terminalVelocitySpread, 0)
- def setFactoryLifeSpan(self, value):
- self.particles.factory.setLifespanBase(value)
- def setFactoryLifeSpanSpread(self, value):
- self.particles.factory.setLifespanSpread(value)
- def setFactoryParticleMass(self, value):
- self.particles.factory.setMassBase(value)
- def setFactoryParticleMassSpread(self, value):
- self.particles.factory.setMassSpread(value)
- def setFactoryTerminalVelocity(self, value):
- self.particles.factory.setTerminalVelocityBase(value)
- def setFactoryTerminalVelocitySpread(self, value):
- self.particles.factory.setTerminalVelocitySpread(value)
- # Point Page #
- # Z Spin Page #
- def setFactoryZSpinInitialAngle(self, angle):
- self.particles.factory.setInitialAngle(angle)
- def setFactoryZSpinInitialAngleSpread(self, spread):
- self.particles.factory.setInitialAngleSpread(spread)
- def setFactoryZSpinFinalAngle(self, angle):
- self.particles.factory.setFinalAngle(angle)
- def setFactoryZSpinFinalAngleSpread(self, spread):
- self.particles.factory.setFinalAngleSpread(spread)
- def setFactoryZSpinAngularVelocity(self, vel):
- self.particles.factory.setAngularVelocity(vel)
- def setFactoryZSpinAngularVelocitySpread(self, spread):
- self.particles.factory.setAngularVelocitySpread(spread)
- ## EMITTER PAGE ##
- def selectEmitterType(self, type):
- self.emitterNotebook.selectpage(type)
- self.particles.setEmitter(type)
- self.updateEmitterWidgets()
- def selectEmitterPage(self):
- type = self.particles.emitter.__class__.__name__
- self.emitterNotebook.selectpage(type)
- self.getVariable('Emitter', 'Emitter Type').set(type)
- def updateEmitterWidgets(self):
- emitter = self.particles.emitter
- self.setEmissionType(self.particles.emitter.getEmissionType())
- amp = emitter.getAmplitude()
- self.getWidget('Emitter', 'Velocity Multiplier').set(amp)
- spread = emitter.getAmplitudeSpread()
- self.getWidget('Emitter', 'Velocity Multiplier Spread').set(spread)
- vec = emitter.getOffsetForce()
- self.getWidget('Emitter', 'Offset Velocity').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 Velocity').set(
- [vec[0], vec[1], vec[2]], 0)
- if isinstance(emitter, BoxEmitter):
- min = emitter.getMinBound()
- self.getWidget('Box Emitter', 'Min').set(
- [min[0], min[1], min[2]], 0)
- max = emitter.getMaxBound()
- self.getWidget('Box Emitter', 'Max').set(
- [max[0], max[1], max[2]], 0)
- elif isinstance(emitter, DiscEmitter):
- radius = emitter.getRadius()
- self.getWidget('Disc Emitter', 'Radius').set(radius, 0)
- innerAngle = emitter.getInnerAngle()
- self.getWidget('Disc Emitter', 'Inner Angle').set(innerAngle, 0)
- innerMagnitude = emitter.getInnerMagnitude()
- self.getWidget('Disc Emitter', 'Inner Velocity').set(
- innerMagnitude, 0)
- outerAngle = emitter.getOuterAngle()
- self.getWidget('Disc Emitter', 'Outer Angle').set(outerAngle, 0)
- outerMagnitude = emitter.getOuterMagnitude()
- self.getWidget('Disc Emitter', 'Inner Velocity').set(
- outerMagnitude, 0)
- cubicLerping = emitter.getCubicLerping()
- self.getVariable('Disc Emitter', 'Cubic Lerping').set(cubicLerping)
- elif isinstance(emitter, LineEmitter):
- min = emitter.getEndpoint1()
- self.getWidget('Line Emitter', 'Min').set(
- [min[0], min[1], min[2]], 0)
- max = emitter.getEndpoint2()
- self.getWidget('Line Emitter', 'Max').set(
- [max[0], max[1], max[2]], 0)
- elif isinstance(emitter, PointEmitter):
- location = emitter.getLocation()
- self.getWidget('Point Emitter', 'Position').set(
- [location[0], location[1], location[2]], 0)
- elif isinstance(emitter, RectangleEmitter):
- min = emitter.getMinBound()
- self.getWidget('Rectangle Emitter', 'Min').set(
- [min[0], min[1]], 0)
- max = emitter.getMaxBound()
- self.getWidget('Rectangle Emitter', 'Max').set(
- [max[0], max[1]], 0)
- elif isinstance(emitter, RingEmitter):
- radius = emitter.getRadius()
- self.getWidget('Ring Emitter', 'Radius').set(radius, 0)
- radiusSpread = emitter.getRadiusSpread()
- self.getWidget('Ring Emitter', 'Radius Spread').set(radiusSpread, 0)
- angle = emitter.getAngle()
- self.getWidget('Ring Emitter', 'Angle').set(angle, 0)
- elif isinstance(emitter, SphereVolumeEmitter):
- radius = emitter.getRadius()
- self.getWidget('Sphere Volume Emitter', 'Radius').set(radius, 0)
- elif isinstance(emitter, SphereSurfaceEmitter):
- radius = emitter.getRadius()
- self.getWidget('Sphere Surface Emitter', 'Radius').set(radius, 0)
- elif isinstance(emitter, TangentRingEmitter):
- radius = emitter.getRadius()
- self.getWidget('Tangent Ring Emitter', 'Radius').set(radius, 0)
- radiusSpread = emitter.getRadiusSpread()
- self.getWidget('Tangent Ring Emitter', 'Radius Spread').set(
- radiusSpread, 0)
- # All #
- def setEmissionType(self, newType = None):
- if newType:
- type = newType
- self.emissionType.set(type)
- else:
- type = self.emissionType.get()
- self.particles.emitter.setEmissionType(type)
- if type == BaseParticleEmitter.ETEXPLICIT:
- self.getWidget(
- 'Emitter', 'Radiate Origin')['state'] = 'disabled'
- self.getWidget(
- 'Emitter', 'Explicit Velocity')['state'] = 'normal'
- # Hide custom widgets
- if isinstance(self.particles.emitter, DiscEmitter):
- self.discCustomFrame.pack_forget()
- elif isinstance(self.particles.emitter, RingEmitter):
- self.ringCustomFrame.pack_forget()
- elif type == BaseParticleEmitter.ETRADIATE:
- self.getWidget(
- 'Emitter', 'Radiate Origin')['state'] = 'normal'
- self.getWidget(
- 'Emitter', 'Explicit Velocity')['state'] = 'disabled'
- # Hide custom widgets
- if isinstance(self.particles.emitter, DiscEmitter):
- self.discCustomFrame.pack_forget()
- elif isinstance(self.particles.emitter, RingEmitter):
- self.ringCustomFrame.pack_forget()
- elif type == BaseParticleEmitter.ETCUSTOM:
- self.getWidget(
- 'Emitter', 'Radiate Origin')['state'] = 'disabled'
- self.getWidget(
- 'Emitter', 'Explicit Velocity')['state'] = 'disabled'
- # Show custom widgets
- if isinstance(self.particles.emitter, DiscEmitter):
- self.discCustomFrame.pack(fill = tk.BOTH, expand = 1)
- elif isinstance(self.particles.emitter, RingEmitter):
- self.ringCustomFrame.pack(fill = tk.BOTH, expand = 1)
- 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 #
- def setEmitterBoxPoint1(self, point):
- self.particles.emitter.setMinBound(Point3(point[0],
- point[1],
- point[2]))
- def setEmitterBoxPoint2(self, point):
- self.particles.emitter.setMaxBound(Point3(point[0],
- point[1],
- point[2]))
- # Disc #
- def setEmitterDiscRadius(self, radius):
- self.particles.emitter.setRadius(radius)
- def setEmitterDiscInnerAngle(self, angle):
- self.particles.emitter.setInnerAngle(angle)
- def setEmitterDiscInnerVelocity(self, velocity):
- self.particles.emitter.setInnerMagnitude(velocity)
- def setEmitterDiscOuterAngle(self, angle):
- self.particles.emitter.setOuterAngle(angle)
- def setEmitterDiscOuterVelocity(self, velocity):
- self.particles.emitter.setOuterMagnitude(velocity)
- def toggleEmitterDiscCubicLerping(self):
- self.particles.emitter.setCubicLerping(
- self.getVariable('Disc Emitter', 'Cubic Lerping').get())
- # Line #
- def setEmitterLinePoint1(self, point):
- self.particles.emitter.setEndpoint1(Point3(point[0],
- point[1],
- point[2]))
- def setEmitterLinePoint2(self, point):
- self.particles.emitter.setEndpoint2(Point3(point[0],
- point[1],
- point[2]))
- # Point #
- def setEmitterPointPosition(self, pos):
- self.particles.emitter.setLocation(Point3(pos[0], pos[1], pos[2]))
- # Rectangle #
- def setEmitterRectanglePoint1(self, point):
- self.particles.emitter.setMinBound(Point2(point[0], point[1]))
- def setEmitterRectanglePoint2(self, point):
- self.particles.emitter.setMaxBound(Point2(point[0], point[1]))
- # Ring #
- def setEmitterRingRadius(self, radius):
- self.particles.emitter.setRadius(radius)
- def setEmitterRingRadiusSpread(self, radiusSpread):
- self.particles.emitter.setRadiusSpread(radiusSpread)
- def setEmitterRingLaunchAngle(self, angle):
- self.particles.emitter.setAngle(angle)
- # Sphere surface #
- def setEmitterSphereSurfaceRadius(self, radius):
- self.particles.emitter.setRadius(radius)
- # Sphere volume #
- def setEmitterSphereVolumeRadius(self, radius):
- self.particles.emitter.setRadius(radius)
- # Tangent ring #
- def setEmitterTangentRingRadius(self, radius):
- self.particles.emitter.setRadius(radius)
- def setEmitterTangentRingRadiusSpread(self, radiusSpread):
- self.particles.emitter.setRadiusSpread(radiusSpread)
- ## RENDERER PAGE ##
- def selectRendererType(self, type):
- self.rendererNotebook.selectpage(type)
- self.particles.setRenderer(type)
- self.updateRendererWidgets()
- def updateRendererWidgets(self):
- 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.PRALPHAINOUT:
- aMode = 'ALPHA_IN_OUT'
- elif alphaMode == BaseParticleRenderer.PRALPHAUSER:
- aMode = 'ALPHA_USER'
- self.getVariable('Renderer', 'Alpha Mode').set(aMode)
- userAlpha = renderer.getUserAlpha()
- self.getWidget('Renderer', 'User Alpha').set(userAlpha)
- if isinstance(renderer, LineParticleRenderer):
- headColor = renderer.getHeadColor() * 255.0
- self.getWidget('Line Renderer', 'Head Color').set(
- [headColor[0], headColor[1], headColor[2], headColor[3]])
- tailColor = renderer.getTailColor() * 255.0
- self.getWidget('Line Renderer', 'Tail Color').set(
- [tailColor[0], tailColor[1], tailColor[2], tailColor[3]])
- self.getWidget('Line Renderer', 'Line Scale Factor').set(
- renderer.getLineScaleFactor())
- elif isinstance(renderer, GeomParticleRenderer):
- self.getVariable('Geom Renderer', 'X Scale').set(
- renderer.getXScaleFlag())
- self.getVariable('Geom Renderer', 'Y Scale').set(
- renderer.getYScaleFlag())
- self.getVariable('Geom Renderer', 'Z Scale').set(
- renderer.getZScaleFlag())
- initialXScale = renderer.getInitialXScale()
- self.getWidget('Geom Renderer', 'Initial X Scale').set(
- initialXScale)
- initialYScale = renderer.getInitialYScale()
- self.getWidget('Geom Renderer', 'Initial Y Scale').set(
- initialYScale)
- initialZScale = renderer.getInitialZScale()
- self.getWidget('Geom Renderer', 'Initial Z Scale').set(
- initialZScale)
- finalXScale = renderer.getFinalXScale()
- self.getWidget('Geom Renderer', 'Final X Scale').set(
- finalXScale)
- finalYScale = renderer.getFinalYScale()
- self.getWidget('Geom Renderer', 'Final Y Scale').set(
- finalYScale)
- finalZScale = renderer.getFinalZScale()
- self.getWidget('Geom Renderer', 'Final Z Scale').set(
- finalZScale)
- if self.getVariable('Geom Renderer','Color Blend').get() in ['MAdd','MSubtract','MInvSubtract']:
- self.getWidget('Geom Renderer','Incoming Op.').pack(fill = tk.X)
- self.getWidget('Geom Renderer','Fbuffer Op.').pack(fill = tk.X)
- else:
- self.getWidget('Geom Renderer','Incoming Op.').pack_forget()
- self.getWidget('Geom Renderer','Fbuffer Op.').pack_forget()
- for x in self.rendererSegmentWidgetList:
- x.pack_forget()
- x.destroy()
- self.rendererSegmentWidgetList = []
- for id in self.particles.renderer.getColorInterpolationManager().getSegmentIdList().split():
- self.createWidgetForExistingInterpolationSegment(eval(id))
- elif isinstance(renderer, PointParticleRenderer):
- pointSize = renderer.getPointSize()
- self.getWidget('Point Renderer', 'Point Size').set(pointSize)
- startColor = renderer.getStartColor() * 255.0
- self.getWidget('Point Renderer', 'Start Color').set(
- [startColor[0], startColor[1], startColor[2], startColor[3]])
- endColor = renderer.getEndColor() * 255.0
- self.getWidget('Point Renderer', 'End Color').set(
- [endColor[0], endColor[1], endColor[2], endColor[3]])
- blendType = renderer.getBlendType()
- if blendType == PointParticleRenderer.PPONECOLOR:
- bType = "PP_ONE_COLOR"
- elif blendType == PointParticleRenderer.PPBLENDLIFE:
- bType = "PP_BLEND_LIFE"
- elif blendType == PointParticleRenderer.PPBLENDVEL:
- bType = "PP_BLEND_VEL"
- self.getVariable('Point Renderer', 'Blend Type').set(bType)
- blendMethod = renderer.getBlendMethod()
- bMethod = "PP_NO_BLEND"
- if blendMethod == BaseParticleRenderer.PPNOBLEND:
- bMethod = "PP_NO_BLEND"
- elif blendMethod == BaseParticleRenderer.PPBLENDLINEAR:
- bMethod = "PP_BLEND_LINEAR"
- elif blendMethod == BaseParticleRenderer.PPBLENDCUBIC:
- bMethod = "PP_BLEND_CUBIC"
- self.getVariable('Point Renderer', 'Blend Method').set(bMethod)
- elif isinstance(renderer, SparkleParticleRenderer):
- centerColor = renderer.getCenterColor() * 255.0
- self.getWidget('Sparkle Renderer', 'Center Color').set(
- [centerColor[0], centerColor[1],
- centerColor[2], centerColor[3]])
- edgeColor = renderer.getEdgeColor() * 255.0
- self.getWidget('Sparkle Renderer', 'Edge Color').set(
- [edgeColor[0], edgeColor[1], edgeColor[2], edgeColor[3]])
- birthRadius = renderer.getBirthRadius()
- self.getWidget('Sparkle Renderer', 'Birth Radius').set(birthRadius)
- deathRadius = renderer.getDeathRadius()
- self.getWidget('Sparkle Renderer', 'Death Radius').set(deathRadius)
- lifeScale = renderer.getLifeScale()
- lScale = "SP_NO_SCALE"
- if lifeScale == SparkleParticleRenderer.SPSCALE:
- lScale = "SP_SCALE"
- self.getVariable('Sparkle Renderer', 'Life Scale').set(lScale)
- elif isinstance(renderer, SpriteParticleRenderer):
- self.getWidget('Sprite Renderer','Frame Rate').set(renderer.getAnimateFramesRate(), 0)
- self.getVariable('Sprite Renderer','Enable Animation').set(
- renderer.getAnimateFramesEnable())
- self.readSpriteRendererAnimations() # Updates widgets with renderer data.
- self.getVariable('Sprite Renderer', 'X Scale').set(
- renderer.getXScaleFlag())
- self.getVariable('Sprite Renderer', 'Y Scale').set(
- renderer.getYScaleFlag())
- self.getVariable('Sprite Renderer', 'Anim Angle').set(
- renderer.getAnimAngleFlag())
- initialXScale = renderer.getInitialXScale()
- self.getWidget('Sprite Renderer', 'Initial X Scale').set(
- initialXScale)
- initialYScale = renderer.getInitialYScale()
- self.getWidget('Sprite Renderer', 'Initial Y Scale').set(
- initialYScale)
- finalXScale = renderer.getFinalXScale()
- self.getWidget('Sprite Renderer', 'Final X Scale').set(
- finalXScale)
- finalYScale = renderer.getFinalYScale()
- self.getWidget('Sprite Renderer', 'Final Y Scale').set(
- finalYScale)
- nonanimatedTheta = renderer.getNonanimatedTheta()
- self.getWidget('Sprite Renderer', 'Non Animated Theta').set(
- nonanimatedTheta)
- blendMethod = renderer.getAlphaBlendMethod()
- bMethod = "PP_NO_BLEND"
- if blendMethod == BaseParticleRenderer.PPNOBLEND:
- bMethod = "PP_NO_BLEND"
- elif blendMethod == BaseParticleRenderer.PPBLENDLINEAR:
- bMethod = "PP_BLEND_LINEAR"
- elif blendMethod == BaseParticleRenderer.PPBLENDCUBIC:
- bMethod = "PP_BLEND_CUBIC"
- self.getVariable('Sprite Renderer', 'Alpha Disable').set(
- renderer.getAlphaDisable())
- if self.getVariable('Sprite Renderer','Color Blend').get() in ['MAdd','MSubtract','MInvSubtract']:
- self.getWidget('Sprite Renderer','Incoming Op.').pack(fill = tk.X)
- self.getWidget('Sprite Renderer','Fbuffer Op.').pack(fill = tk.X)
- else:
- self.getWidget('Sprite Renderer','Incoming Op.').pack_forget()
- self.getWidget('Sprite Renderer','Fbuffer Op.').pack_forget()
- for x in self.rendererSegmentWidgetList:
- x.pack_forget()
- x.destroy()
- self.rendererSegmentWidgetList = []
- for id in self.particles.renderer.getColorInterpolationManager().getSegmentIdList().split():
- self.createWidgetForExistingInterpolationSegment(eval(id))
- def selectRendererPage(self):
- type = self.particles.renderer.__class__.__name__
- if type == 'SpriteParticleRendererExt':
- type = 'SpriteParticleRenderer'
- self.rendererNotebook.selectpage(type)
- self.getVariable('Renderer', 'Renderer Type').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_IN_OUT':
- aMode = BaseParticleRenderer.PRALPHAINOUT
- elif alphaMode == 'ALPHA_USER':
- aMode = BaseParticleRenderer.PRALPHAUSER
- self.particles.renderer.setAlphaMode(aMode)
- def setRendererUserAlpha(self, alpha):
- self.particles.renderer.setUserAlpha(alpha)
- # Line #
- def setRendererLineHeadColor(self, color):
- self.particles.renderer.setHeadColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setRendererLineTailColor(self, color):
- self.particles.renderer.setTailColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setRendererLineScaleFactor(self, sf):
- self.particles.renderer.setLineScaleFactor(sf)
- # Geom #
- def setRendererGeomNode(self, event):
- node = None
- nodePath = base.loader.loadModel(self.rendererGeomNode.get())
- if nodePath is not None:
- node = nodePath.node()
- if node is not None:
- self.particles.geomReference = self.rendererGeomNode.get()
- self.particles.renderer.setGeomNode(node)
- # Point #
- def setRendererPointSize(self, size):
- self.particles.renderer.setPointSize(size)
- def setRendererPointStartColor(self, color):
- self.particles.renderer.setStartColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setRendererPointEndColor(self, color):
- self.particles.renderer.setEndColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def rendererPointSelectBlendType(self, blendType):
- if blendType == "PP_ONE_COLOR":
- bType = PointParticleRenderer.PPONECOLOR
- elif blendType == "PP_BLEND_LIFE":
- bType = PointParticleRenderer.PPBLENDLIFE
- elif blendType == "PP_BLEND_VEL":
- bType = PointParticleRenderer.PPBLENDVEL
- self.particles.renderer.setBlendType(bType)
- def rendererPointSelectBlendMethod(self, blendMethod):
- if blendMethod == "PP_NO_BLEND":
- bMethod = BaseParticleRenderer.PPNOBLEND
- elif blendMethod == "PP_BLEND_LINEAR":
- bMethod = BaseParticleRenderer.PPBLENDLINEAR
- elif blendMethod == "PP_BLEND_CUBIC":
- bMethod = BaseParticleRenderer.PPBLENDCUBIC
- self.particles.renderer.setBlendMethod(bMethod)
- # Sparkle #
- def setRendererSparkleCenterColor(self, color):
- self.particles.renderer.setCenterColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setRendererSparkleEdgeColor(self, color):
- self.particles.renderer.setEdgeColor(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setRendererSparkleBirthRadius(self, radius):
- self.particles.renderer.setBirthRadius(radius)
- def setRendererSparkleDeathRadius(self, radius):
- self.particles.renderer.setDeathRadius(radius)
- def setRendererSparkleLifeScale(self, lifeScaleMethod):
- if lifeScaleMethod == 'SP_NO_SCALE':
- lScale = SparkleParticleRenderer.SPNOSCALE
- else:
- lScale = SparkleParticleRenderer.SPSCALE
- self.particles.renderer.setLifeScale(lScale)
- # Sprite #
- def setSpriteSourceType(self):
- if self.rendererSpriteSourceType.get() == 0:
- self.rendererSpriteTextureEntry['state'] = 'normal'
- self.rendererSpriteFileEntry['state'] = 'disabled'
- self.rendererSpriteNodeEntry['state'] = 'disabled'
- self.rendererSpriteTextureEntry['background'] = '#FFFFFF'
- self.rendererSpriteFileEntry['background'] = '#C0C0C0'
- self.rendererSpriteNodeEntry['background'] = '#C0C0C0'
- else:
- self.rendererSpriteTextureEntry['state'] = 'disabled'
- self.rendererSpriteFileEntry['state'] = 'normal'
- self.rendererSpriteNodeEntry['state'] = 'normal'
- self.rendererSpriteTextureEntry['background'] = '#C0C0C0'
- self.rendererSpriteFileEntry['background'] = '#FFFFFF'
- self.rendererSpriteNodeEntry['background'] = '#FFFFFF'
- def setRendererSpriteAnimationFrameRate(self, rate):
- self.particles.renderer.setAnimateFramesRate(rate)
- def setRendererSpriteAnimationEnable(self):
- self.particles.renderer.setAnimateFramesEnable(
- self.getVariable('Sprite Renderer','Enable Animation').get())
- def addRendererSpriteAnimationTexture(self):
- ren = self.particles.getRenderer()
- parent = self.rendererSpriteAnimationFrame
- if ren.addTextureFromFile():
- animId = len([x for x in self.rendererSpriteAnimationWidgetList if x and x.valid])
- anim = ren.getAnim(animId)
- frameNum = len([x for x in self.rendererSpriteAnimationWidgetList if x])
- self.rendererSpriteAnimationWidgetList.append(
- self.createSpriteAnimationTextureWidget(parent, anim, repr(frameNum)))
- else:
- animId = len([x for x in self.rendererSpriteAnimationWidgetList if x and x.valid])
- anim = SpriteAnim.STTexture
- frameNum = len([x for x in self.rendererSpriteAnimationWidgetList if x])
- self.rendererSpriteAnimationWidgetList.append(
- self.createSpriteAnimationTextureWidget(parent, anim, repr(frameNum)))
- parent.pack(fill=tk.BOTH, expand=1)
- def addRendererSpriteAnimationFromNode(self):
- ren = self.particles.getRenderer()
- parent = self.rendererSpriteAnimationFrame
- if ren.addTextureFromNode():
- animId = len([x for x in self.rendererSpriteAnimationWidgetList if x and x.valid])
- anim = ren.getAnim(animId)
- frameNum = len([x for x in self.rendererSpriteAnimationWidgetList if x])
- self.rendererSpriteAnimationWidgetList.append(
- self.createSpriteAnimationNodeWidget(parent, anim, repr(frameNum)))
- else:
- animId = len([x for x in self.rendererSpriteAnimationWidgetList if x and x.valid])
- anim = SpriteAnim.STFromNode
- frameNum = len([x for x in self.rendererSpriteAnimationWidgetList if x])
- self.rendererSpriteAnimationWidgetList.append(
- self.createSpriteAnimationNodeWidget(parent, anim, repr(frameNum)))
- parent.pack(fill=tk.BOTH, expand=1)
- def toggleRendererSpriteXScale(self):
- self.particles.renderer.setXScaleFlag(
- self.getVariable('Sprite Renderer', 'X Scale').get())
- def toggleRendererSpriteYScale(self):
- self.particles.renderer.setYScaleFlag(
- self.getVariable('Sprite Renderer', 'Y Scale').get())
- def toggleRendererSpriteAnimAngle(self):
- self.particles.renderer.setAnimAngleFlag(
- self.getVariable('Sprite Renderer', 'Anim Angle').get())
- def toggleAngularVelocity(self):
- self.particles.factory.enableAngularVelocity(
- self.getVariable('Z Spin Factory', 'Enable Angular Velocity').get())
- def setRendererSpriteInitialXScale(self, xScale):
- self.particles.renderer.setInitialXScale(xScale)
- def setRendererSpriteFinalXScale(self, xScale):
- self.particles.renderer.setFinalXScale(xScale)
- def setRendererSpriteInitialYScale(self, yScale):
- self.particles.renderer.setInitialYScale(yScale)
- def setRendererSpriteFinalYScale(self, yScale):
- self.particles.renderer.setFinalYScale(yScale)
- def setRendererSpriteNonAnimatedTheta(self, theta):
- self.particles.renderer.setNonanimatedTheta(theta)
- def setRendererSpriteBlendMethod(self, blendMethod):
- if blendMethod == 'PP_NO_BLEND':
- bMethod = BaseParticleRenderer.PPNOBLEND
- elif blendMethod == 'PP_BLEND_LINEAR':
- bMethod = BaseParticleRenderer.PPBLENDLINEAR
- elif blendMethod == 'PP_BLEND_CUBIC':
- bMethod = BaseParticleRenderer.PPBLENDCUBIC
- else:
- bMethod = BaseParticleRenderer.PPNOBLEND
- def toggleRendererSpriteAlphaDisable(self):
- self.particles.renderer.setAlphaDisable(
- self.getVariable('Sprite Renderer', 'Alpha Disable').get())
- def setRendererColorBlendAttrib(self, rendererName, blendMethodStr, incomingOperandStr, fbufferOperandStr):
- self.particles.getRenderer().setColorBlendMode(getattr(ColorBlendAttrib, blendMethodStr),
- getattr(ColorBlendAttrib, incomingOperandStr),
- getattr(ColorBlendAttrib, fbufferOperandStr))
- if blendMethodStr in ['MAdd','MSubtract','MInvSubtract']:
- self.getWidget(rendererName,'Incoming Op.').pack(fill = tk.X)
- self.getWidget(rendererName,'Fbuffer Op.').pack(fill = tk.X)
- else:
- self.getWidget(rendererName,'Incoming Op.').pack_forget()
- self.getWidget(rendererName,'Fbuffer Op.').pack_forget()
- self.updateRendererWidgets()
- def setRendererSpriteColorBlendMethod(self, blendMethod):
- blendMethodStr = blendMethod
- incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get()
- fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get()
- self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- def setRendererSpriteColorBlendIncomingOperand(self, operand):
- blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get()
- incomingOperandStr = operand
- fbufferOperandStr = self.getVariable('Sprite Renderer','Fbuffer Op.').get()
- self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- def setRendererSpriteColorBlendFbufferOperand(self, operand):
- blendMethodStr = self.getVariable('Sprite Renderer','Color Blend').get()
- incomingOperandStr = self.getVariable('Sprite Renderer','Incoming Op.').get()
- fbufferOperandStr = operand
- self.setRendererColorBlendAttrib('Sprite Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- # GeomParticleRenderer Functionality
- def toggleRendererGeomXScale(self):
- self.particles.renderer.setXScaleFlag(
- self.getVariable('Geom Renderer', 'X Scale').get())
- def toggleRendererGeomYScale(self):
- self.particles.renderer.setYScaleFlag(
- self.getVariable('Geom Renderer', 'Y Scale').get())
- def toggleRendererGeomZScale(self):
- self.particles.renderer.setZScaleFlag(
- self.getVariable('Geom Renderer', 'Z Scale').get())
- def setRendererGeomInitialXScale(self, xScale):
- self.particles.renderer.setInitialXScale(xScale)
- def setRendererGeomFinalXScale(self, xScale):
- self.particles.renderer.setFinalXScale(xScale)
- def setRendererGeomInitialYScale(self, yScale):
- self.particles.renderer.setInitialYScale(yScale)
- def setRendererGeomFinalYScale(self, yScale):
- self.particles.renderer.setFinalYScale(yScale)
- def setRendererGeomInitialZScale(self, zScale):
- self.particles.renderer.setInitialZScale(zScale)
- def setRendererGeomFinalZScale(self, zScale):
- self.particles.renderer.setFinalZScale(zScale)
- def setRendererGeomColorBlendMethod(self, blendMethod):
- blendMethodStr = blendMethod
- incomingOperandStr = self.getVariable('Geom Renderer','Incoming Op.').get()
- fbufferOperandStr = self.getVariable('Geom Renderer','Fbuffer Op.').get()
- self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- def setRendererGeomColorBlendIncomingOperand(self, operand):
- blendMethodStr = self.getVariable('Geom Renderer','Color Blend').get()
- incomingOperandStr = operand
- fbufferOperandStr = self.getVariable('Geom Renderer','Fbuffer Op.').get()
- self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- def setRendererGeomColorBlendFbufferOperand(self, operand):
- blendMethodStr = self.getVariable('Geom Renderer','Color Blend').get()
- incomingOperandStr = self.getVariable('Geom Renderer','Incoming Op.').get()
- fbufferOperandStr = operand
- self.setRendererColorBlendAttrib('Geom Renderer', blendMethodStr, incomingOperandStr, fbufferOperandStr)
- def addConstantInterpolationSegment(self, id = None):
- ren = self.particles.getRenderer()
- cim = ren.getColorInterpolationManager()
- if id is None:
- seg = cim.getSegment(cim.addConstant())
- else:
- seg = cim.getSegment(id)
- if ren.__class__.__name__ == 'SpriteParticleRendererExt':
- parent = self.rendererSpriteSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Constant'
- self.rendererSegmentWidgetList.append(
- self.createConstantInterpolationSegmentWidget(parent, segName, seg))
- elif ren.__class__.__name__ == 'GeomParticleRenderer':
- parent = self.rendererGeomSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Constant'
- self.rendererSegmentWidgetList.append(
- self.createConstantInterpolationSegmentWidget(parent, segName, seg))
- parent.pack(fill=tk.BOTH, expand=1)
- def addLinearInterpolationSegment(self, id = None):
- ren = self.particles.getRenderer()
- cim = ren.getColorInterpolationManager()
- if id is None:
- seg = cim.getSegment(cim.addLinear())
- else:
- seg = cim.getSegment(id)
- if ren.__class__.__name__ == 'SpriteParticleRendererExt':
- parent = self.rendererSpriteSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Linear'
- self.rendererSegmentWidgetList.append(
- self.createLinearInterpolationSegmentWidget(parent, segName, seg))
- elif ren.__class__.__name__ == 'GeomParticleRenderer':
- parent = self.rendererGeomSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Linear'
- self.rendererSegmentWidgetList.append(
- self.createLinearInterpolationSegmentWidget(parent, segName, seg))
- parent.pack(fill=tk.BOTH, expand=1)
- def addStepwaveInterpolationSegment(self, id = None):
- ren = self.particles.getRenderer()
- cim = ren.getColorInterpolationManager()
- if id is None:
- seg = cim.getSegment(cim.addStepwave())
- else:
- seg = cim.getSegment(id)
- if ren.__class__.__name__ == 'SpriteParticleRendererExt':
- parent = self.rendererSpriteSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Stepwave'
- self.rendererSegmentWidgetList.append(
- self.createStepwaveInterpolationSegmentWidget(parent, segName, seg))
- elif ren.__class__.__name__ == 'GeomParticleRenderer':
- parent = self.rendererGeomSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Stepwave'
- self.rendererSegmentWidgetList.append(
- self.createStepwaveInterpolationSegmentWidget(parent, segName, seg))
- parent.pack(fill=tk.BOTH, expand=1)
- def addSinusoidInterpolationSegment(self, id = None):
- ren = self.particles.getRenderer()
- cim = ren.getColorInterpolationManager()
- if id is None:
- seg = cim.getSegment(cim.addSinusoid())
- else:
- seg = cim.getSegment(id)
- if ren.__class__.__name__ == 'SpriteParticleRendererExt':
- parent = self.rendererSpriteSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Sinusoid'
- self.rendererSegmentWidgetList.append(
- self.createSinusoidInterpolationSegmentWidget(parent, segName, seg))
- elif ren.__class__.__name__ == 'GeomParticleRenderer':
- parent = self.rendererGeomSegmentFrame
- segName = repr(len(self.rendererSegmentWidgetList))+':Sinusoid'
- self.rendererSegmentWidgetList.append(
- self.createSinusoidInterpolationSegmentWidget(parent, segName, seg))
- parent.pack(fill=tk.BOTH, expand=1)
- def createWidgetForExistingInterpolationSegment(self, id):
- ren = self.particles.getRenderer()
- cim = ren.getColorInterpolationManager()
- seg = cim.getSegment(id)
- assert seg
- fun = seg.getFunction()
- if isinstance(fun,ColorInterpolationFunctionSinusoid):
- self.addSinusoidInterpolationSegment(id)
- elif isinstance(fun,ColorInterpolationFunctionStepwave):
- self.addStepwaveInterpolationSegment(id)
- elif isinstance(fun,ColorInterpolationFunctionLinear):
- self.addLinearInterpolationSegment(id)
- elif isinstance(fun,ColorInterpolationFunctionConstant):
- self.addConstantInterpolationSegment(id)
- def createInterpolationSegmentFrame(self, parent, segName, seg):
- frame = tk.Frame(parent, relief = tk.RAISED, borderwidth = 2)
- lFrame = tk.Frame(frame, relief = tk.FLAT)
- def removeInterpolationSegmentFrame(s = self, seg = seg, fr = frame):
- s.particles.getRenderer().getColorInterpolationManager().clearSegment(seg.getId())
- fr.pack_forget()
- def setSegEnabled(s=self, n=segName):
- enabled = s.getVariable('Sprite Renderer', n+' Enabled')
- seg.setEnabled(enabled.get())
- def setIsModulated(s=self, n=segName):
- modulated = s.getVariable('Sprite Renderer', n+' isModulated')
- seg.setIsModulated(modulated.get())
- def setSegBegin(time):
- seg.setTimeBegin(time)
- def setSegEnd(time):
- seg.setTimeEnd(time)
- tk.Button(lFrame, text = 'X',
- command = removeInterpolationSegmentFrame).pack(side = tk.RIGHT, expand = 0)
- tk.Label(lFrame, text = segName,
- foreground = 'Blue',
- font = ('MSSansSerif', 12, 'bold'),
- ).pack(fill = tk.X, expand = 1)
- lFrame.pack(fill = tk.X, expand = 1)
- lFrame = tk.Frame(frame, relief = tk.FLAT)
- self.createCheckbutton(
- lFrame, 'Sprite Renderer', segName + ' Enabled',
- ('On: Enabled\n' +
- 'Off: Disabled'),
- command = setSegEnabled, initialState = seg.isEnabled())
- self.createCheckbutton(
- lFrame, 'Sprite Renderer', segName + ' isModulated',
- ('On: Modulate\n' +
- 'Off: Add'),
- command = setIsModulated, initialState = seg.isModulated())
- lFrame.pack(fill = tk.X, expand = 1)
- f = tk.Frame(frame)
- self.createSlider(f,
- 'Sprite Renderer', segName + ' Begin',
- '',
- command = setSegBegin,
- value = seg.getTimeBegin())
- self.createSlider(f,'Sprite Renderer', segName + ' End',
- '',
- command = setSegEnd,
- value = seg.getTimeEnd())
- f.pack(fill = tk.X, expand = 0)
- frame.pack(pady = 3, fill = tk.X, expand = 0)
- return frame
- def createConstantInterpolationSegmentWidget(self, parent, segName, segment):
- fun = segment.getFunction()
- def setSegColorA(color):
- fun.setColorA(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- frame = self.createInterpolationSegmentFrame(parent, segName, segment)
- f = tk.Frame(frame)
- c = fun.getColorA()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color A',
- '',
- command = setSegColorA,
- value = c)
- f.pack(fill = tk.X)
- return frame
- def createLinearInterpolationSegmentWidget(self, parent, segName, segment):
- fun = segment.getFunction()
- def setSegColorA(color):
- fun.setColorA(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setSegColorB(color):
- fun.setColorB(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- frame = self.createInterpolationSegmentFrame(parent, segName, segment)
- f = tk.Frame(frame)
- c = fun.getColorA()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color A',
- '',
- command = setSegColorA,
- value = c)
- c = fun.getColorB()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color B',
- '',
- command = setSegColorB,
- value = c)
- f.pack(fill = tk.X)
- return frame
- def createStepwaveInterpolationSegmentWidget(self, parent, segName, segment):
- fun = segment.getFunction()
- def setColorA(color):
- fun.setColorA(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setColorB(color):
- fun.setColorB(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setWidthA(width):
- fun.setWidthA(width)
- def setWidthB(width):
- fun.setWidthB(width)
- frame = self.createInterpolationSegmentFrame(parent, segName, segment)
- f = tk.Frame(frame)
- c = fun.getColorA()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color A',
- '',
- command = setColorA,
- value = c)
- c = fun.getColorB()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color B',
- '',
- command = setColorB,
- value = c)
- w = fun.getWidthA()
- self.createSlider(f,'Sprite Renderer', segName + ' Width A',
- '',
- command = setWidthA,
- value = w)
- w = fun.getWidthB()
- self.createSlider(f,'Sprite Renderer', segName + ' Width B',
- '',
- command = setWidthB,
- value = w)
- f.pack(fill = tk.X)
- return frame
- def createSinusoidInterpolationSegmentWidget(self, parent, segName, segment):
- fun = segment.getFunction()
- def setColorA(color):
- fun.setColorA(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setColorB(color):
- fun.setColorB(
- Vec4(color[0]/255.0, color[1]/255.0,
- color[2]/255.0, color[3]/255.0))
- def setPeriod(period):
- fun.setPeriod(period)
- frame = self.createInterpolationSegmentFrame(parent, segName, segment)
- f = tk.Frame(frame)
- c = fun.getColorA()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color A',
- '',
- command = setColorA,
- value = c)
- c = fun.getColorB()
- c = [c[0]*255.0, c[1]*255.0, c[2]*255.0, c[3]*255.0]
- self.createColorEntry(f,'Sprite Renderer', segName + ' Color B',
- '',
- command = setColorB,
- value = c)
- p = fun.getPeriod()
- self.createFloater(f,'Sprite Renderer', segName + ' Period',
- '',
- command = setPeriod,
- value = p)
- f.pack(fill = tk.X)
- return frame
- def createSpriteAnimationFrame(self, parent, anim, animName):
- ren = self.particles.getRenderer()
- frame = tk.Frame(parent, relief = tk.RAISED, borderwidth = 2)
- frame.pack(pady = 1, fill = tk.X, expand = 0)
- lFrame = tk.Frame(frame, relief = tk.FLAT)
- lFrame.pack(fill = tk.X, expand = 1)
- def delete(s = self, fr = frame):
- i = s.rendererSpriteAnimationWidgetList.index(fr)
- s.rendererSpriteAnimationWidgetList[i] = None
- fr.pack_forget()
- fr.destroy()
- s.writeSpriteRendererAnimations()
- s.readSpriteRendererAnimations()
- tk.Button(lFrame, text = 'X', foreground = 'Red', font = ('MSSansSerif', 8, 'bold'),
- command = delete).pack(side = tk.RIGHT, expand = 0)
- if anim == SpriteAnim.STTexture or anim == SpriteAnim.STFromNode:
- frame.valid = False
- frame.animSourceType = anim
- if anim == SpriteAnim.STTexture:
- type = 'Texture'
- else:
- type = 'From Node'
- else:
- frame.valid = True
- if anim.getSourceType() == SpriteAnim.STTexture:
- frame.animSourceType = SpriteAnim.STTexture
- type = 'Texture'
- else:
- frame.animSourceType = SpriteAnim.STFromNode
- type = 'From Node'
- tk.Label(lFrame, text = animName+': '+type,
- foreground = 'Blue',
- font = ('MSSansSerif', 12, 'bold'),
- ).pack(fill = tk.X, expand = 1)
- return frame
- def createSpriteAnimationTextureWidget(self, parent, anim, animName):
- ren = self.particles.getRenderer()
- frame = self.createSpriteAnimationFrame(parent, anim, animName)
- f = tk.Frame(frame)
- f.pack(fill=tk.X)
- tk.Label(f, text = 'Texture: ', font = ('MSSansSerif', 12), width=7).pack(side = tk.LEFT)
- strVar = tk.StringVar()
- entry = tk.Entry(f, textvariable = strVar).pack(padx=3, pady=3, side=tk.LEFT, fill=tk.X, expand=1)
- if frame.valid:
- strVar.set(anim.getTexSource())
- else:
- strVar.set('Base model path: ' + repr(getModelPath().getValue()))
- def checkForTexture(strVar = strVar):
- tex = base.loader.loadTexture(strVar.get())
- if tex:
- frame.valid = True
- else:
- frame.valid = False
- self.writeSpriteRendererAnimations()
- tk.Button(f, text = 'Update',
- command = checkForTexture).pack(side=tk.LEFT)
- self.variableDict['Sprite Renderer-'+animName+' Anim Texture'] = strVar
- self.widgetDict['Sprite Renderer-'+animName+' Anim Texture'] = entry
- return frame
- def createSpriteAnimationNodeWidget(self, parent, anim, animName):
- ren = self.particles.getRenderer()
- frame = self.createSpriteAnimationFrame(parent, anim, animName)
- f = tk.Frame(frame)
- f.pack(fill=tk.X)
- lf = tk.Frame(f)
- lf.pack(fill=tk.X, expand=1)
- tk.Label(lf, text = 'Model: ', font = ('MSSansSerif', 12), width=7).pack(side = tk.LEFT)
- mStrVar = tk.StringVar()
- entry = tk.Entry(lf, textvariable = mStrVar).pack(padx=3, pady=3, side=tk.LEFT, fill=tk.X, expand=1)
- if frame.valid:
- mStrVar.set(anim.getModelSource())
- else:
- mStrVar.set('Base model path: ' + repr(getModelPath().getValue()))
- mlf = lf
- self.variableDict['Sprite Renderer-'+animName+' Anim Model'] = mStrVar
- self.widgetDict['Sprite Renderer-'+animName+' Anim Model'] = entry
- lf = tk.Frame(f)
- lf.pack(fill=tk.X, expand=1)
- tk.Label(lf, text = 'Node: ', font = ('MSSansSerif', 12), width=7).pack(side = tk.LEFT)
- nStrVar = tk.StringVar()
- entry = tk.Entry(lf, textvariable = nStrVar).pack(padx=3, pady=3, side=tk.LEFT, fill=tk.X, expand=1)
- if frame.valid:
- nStrVar.set(anim.getNodeSource())
- else:
- nStrVar.set('**/*')
- nlf = lf
- self.variableDict['Sprite Renderer-'+animName+' Anim Node'] = nStrVar
- self.widgetDict['Sprite Renderer-'+animName+' Anim Node'] = entry
- def checkForNode(modelStrVar=mStrVar, nodeStrVar=nStrVar):
- mod = base.loader.loadModel(modelStrVar.get())
- if mod:
- node = mod.find(nodeStrVar.get())
- if node:
- frame.valid = True
- else:
- frame.valid = False
- else:
- frame.valid = False
- self.writeSpriteRendererAnimations()
- tk.Button(mlf, text = 'Update',
- command = checkForNode).pack(side=tk.LEFT)
- tk.Button(nlf, text = 'Update',
- command = checkForNode).pack(side=tk.LEFT)
- return frame
- # get animation info from renderer into panel
- def readSpriteRendererAnimations(self):
- ren = self.particles.getRenderer()
- for widget in self.rendererSpriteAnimationWidgetList:
- if widget:
- widget.pack_forget()
- widget.destroy()
- self.rendererSpriteAnimationWidgetList = []
- for anim in [ren.getAnim(x) for x in range(ren.getNumAnims())]:
- if anim.getSourceType() == SpriteAnim.STTexture:
- w = self.createSpriteAnimationTextureWidget(self.rendererSpriteAnimationFrame, anim, repr(len(self.rendererSpriteAnimationWidgetList)))
- else:
- w = self.createSpriteAnimationNodeWidget(self.rendererSpriteAnimationFrame, anim, repr(len(self.rendererSpriteAnimationWidgetList)))
- self.rendererSpriteAnimationWidgetList.append(w)
- # set animation info from panel into renderer
- def writeSpriteRendererAnimations(self):
- ren = self.particles.getRenderer()
- for x in range(ren.getNumAnims()):
- ren.removeAnimation(0)
- for x in range(len(self.rendererSpriteAnimationWidgetList)):
- widget = self.rendererSpriteAnimationWidgetList[x]
- if widget and widget.valid:
- if widget.animSourceType == SpriteAnim.STTexture:
- texSource = self.getVariable('Sprite Renderer', repr(x) + ' Anim Texture').get()
- ren.addTextureFromFile(texSource)
- else:
- modelSource = self.getVariable('Sprite Renderer', repr(x) + ' Anim Model').get()
- nodeSource = self.getVariable('Sprite Renderer', repr(x) + ' Anim Node').get()
- ren.addTextureFromNode(modelSource, nodeSource)
- ## FORCEGROUP COMMANDS ##
- def updateForceWidgets(self):
- # Select appropriate notebook page
- if self.forceGroup is not None:
- self.forceGroupNotebook.pack(fill = tk.X)
- self.forcePageName = (self.particleEffect.getName() + '-' +
- self.forceGroup.getName())
- self.forcePage = self.forcePagesDict.get(
- self.forcePageName, None)
- # Page doesn't exist, add it
- if self.forcePage is None:
- self.addForceGroupNotebookPage(
- self.particleEffect, self.forceGroup)
- self.forceGroupNotebook.selectpage(self.forcePageName)
- else:
- self.forceGroupNotebook.pack_forget()
- def addLinearVectorForce(self):
- self.addForce(LinearVectorForce())
- def addLinearFrictionForce(self):
- self.addForce(LinearFrictionForce())
- def addLinearJitterForce(self):
- self.addForce(LinearJitterForce())
- def addLinearNoiseForce(self):
- self.addForce(LinearNoiseForce())
- def addLinearSinkForce(self):
- self.addForce(LinearSinkForce())
- def addLinearSourceForce(self):
- self.addForce(LinearSourceForce())
- def addLinearCylinderVortexForce(self):
- self.addForce(LinearCylinderVortexForce())
- def addLinearUserDefinedForce(self):
- self.addForce(LinearUserDefinedForce())
- def addForce(self, f):
- if self.forceGroup is None:
- self.createNewForceGroup()
- self.forceGroup.addForce(f)
- self.addForceWidget(self.forceGroup, f)
- ## SYSTEM COMMANDS ##
- def createNewEffect(self):
- name = askstring('Particle Panel', 'Effect Name:',
- parent = self.parent)
- if name:
- particles = Particles.Particles()
- particles.setBirthRate(0.02)
- particles.setLitterSize(10)
- particles.setLitterSpread(0)
- particles.setFactory("PointParticleFactory")
- particles.setRenderer("PointParticleRenderer")
- particles.setEmitter("SphereVolumeEmitter")
- particles.enable()
- effect = ParticleEffect.ParticleEffect(name, particles)
- self.effectsDict[name] = effect
- self.updateMenusAndLabels()
- self.selectEffectNamed(name)
- effect.reparentTo(render)
- effect.enable()
- def createNewParticles(self):
- name = askstring('Particle Panel', 'Particles Name:',
- parent = self.parent)
- 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:
- 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:
- if f.getClassType() == force.getClassType():
- count += 1
- if isinstance(force, LinearVectorForce):
- self.createLinearVectorForceWidget(
- forcePage, pageName, count, force)
- elif isinstance(force, LinearNoiseForce):
- self.createLinearRandomForceWidget(
- forcePage, pageName, count, force, 'Noise')
- elif isinstance(force, LinearJitterForce):
- self.createLinearRandomForceWidget(
- forcePage, pageName, count, force, 'Jitter')
- elif isinstance(force, LinearFrictionForce):
- self.createLinearFrictionForceWidget(
- forcePage, pageName, count, force)
- elif isinstance(force, LinearCylinderVortexForce):
- self.createLinearCylinderVortexForceWidget(
- forcePage, pageName, count, force)
- elif isinstance(force, LinearSinkForce):
- self.createLinearDistanceForceWidget(
- forcePage, pageName, count, force, 'Sink')
- elif isinstance(force, LinearSourceForce):
- self.createLinearDistanceForceWidget(
- forcePage, pageName, count, force, 'Source')
- elif isinstance(force, LinearUserDefinedForce):
- # Nothing
- pass
- self.forceGroupNotebook.setnaturalsize()
- def createForceFrame(self, forcePage, forceName, force):
- frame = tk.Frame(forcePage, relief = tk.RAISED, borderwidth = 2)
- lFrame = tk.Frame(frame, relief = tk.FLAT)
- def removeForce(s = self, f = force, fr = frame):
- s.forceGroup.removeForce(f)
- fr.pack_forget()
- b = tk.Button(lFrame, text = 'X',
- command = removeForce)
- b.pack(side = 'right', expand = 0)
- tk.Label(lFrame, text = forceName,
- foreground = 'Blue',
- font=('MSSansSerif', 12, 'bold'),
- ).pack(expand = 1, fill = 'x')
- lFrame.pack(fill = 'x', expand =1)
- frame.pack(pady = 3, fill = 'x', expand =0)
- return frame
- def createLinearForceWidgets(self, frame, pageName, forceName, force):
- def setAmplitude(amp, f = force):
- f.setAmplitude(amp)
- def toggleMassDependent(s=self, f=force, p=pageName, n=forceName):
- v = s.getVariable(p, n+' Mass Dependent')
- f.setMassDependent(v.get())
- def setVectorMasks(s=self, f=force, p=pageName, n=forceName):
- xMask = s.getVariable(p, n+' Mask X').get()
- yMask = s.getVariable(p, n+' Mask Y').get()
- zMask = s.getVariable(p, n+' Mask Z').get()
- f.setVectorMasks(xMask, yMask, zMask)
- self.createFloater(frame, pageName, forceName + ' Amplitude',
- 'Force amplitude multiplier',
- command = setAmplitude,
- value = force.getAmplitude())
- cbf = tk.Frame(frame, relief = tk.FLAT)
- self.createCheckbutton(cbf, pageName, forceName + ' Mass Dependent',
- ('On: force depends on mass; ' +
- 'Off: force does not depend on mass'),
- toggleMassDependent,
- force.getMassDependent())
- self.createCheckbutton(cbf, pageName, forceName + ' Mask X',
- 'On: enable force along X axis',
- setVectorMasks, 1)
- self.createCheckbutton(cbf, pageName, forceName + ' Mask Y',
- 'On: enable force along X axis',
- setVectorMasks, 1)
- self.createCheckbutton(cbf, pageName, forceName + ' Mask Z',
- 'On: enable force along X axis',
- setVectorMasks, 1)
- cbf.pack(fill = 'x', expand = 0)
- def createForceActiveWidget(self, frame, pageName, forceName, force):
- cbName = forceName + ' Active'
- def toggle(s = self, f = force, p = pageName, n = cbName):
- s.toggleForce(f, p, n)
- self.createCheckbutton(frame, pageName, cbName,
- 'On: force is enabled; Off: force is disabled',
- toggle, 1)
- def createLinearVectorForceWidget(self, forcePage, pageName,
- count, force):
- def setVec(vec, f = force):
- f.setVector(vec[0], vec[1], vec[2])
- forceName = 'Vector Force-' + repr(count)
- frame = self.createForceFrame(forcePage, forceName, force)
- self.createLinearForceWidgets(frame, pageName, forceName, force)
- vec = force.getLocalVector()
- self.createVector3Entry(frame, pageName, forceName,
- 'Set force direction and magnitude',
- command = setVec,
- value = [vec[0], vec[1], vec[2]])
- self.createForceActiveWidget(frame, pageName, forceName, force)
- def createLinearRandomForceWidget(self, forcePage, pageName, count,
- force, type):
- forceName = type + ' Force-' + repr(count)
- frame = self.createForceFrame(forcePage, forceName, force)
- self.createLinearForceWidgets(frame, pageName, forceName, force)
- self.createForceActiveWidget(frame, pageName, forceName, force)
- def createLinearFrictionForceWidget(self, forcePage, pageName,
- count, force):
- def setCoef(coef, f = force):
- f.setCoef(coef)
- forceName = 'Friction Force-' + repr(count)
- frame = self.createForceFrame(forcePage, forceName, force)
- self.createLinearForceWidgets(frame, pageName, forceName, force)
- self.createFloater(frame, pageName, forceName + ' Coef',
- 'Set linear friction force',
- command = setCoef, min = None,
- value = force.getCoef())
- self.createForceActiveWidget(frame, pageName, forceName, force)
- def createLinearCylinderVortexForceWidget(self, forcePage, pageName,
- count, force):
- forceName = 'Vortex Force-' + repr(count)
- def setCoef(coef, f = force):
- f.setCoef(coef)
- def setLength(length, f = force):
- f.setLength(length)
- def setRadius(radius, f = force):
- f.setRadius(radius)
- frame = self.createForceFrame(forcePage, forceName, force)
- self.createLinearForceWidgets(frame, pageName, forceName, force)
- self.createFloater(frame, pageName, forceName + ' Coef',
- 'Set linear cylinder vortex coefficient',
- command = setCoef,
- value = force.getCoef())
- self.createFloater(frame, pageName, forceName + ' Length',
- 'Set linear cylinder vortex length',
- command = setLength,
- value = force.getLength())
- self.createFloater(frame, pageName, forceName + ' Radius',
- 'Set linear cylinder vortex radius',
- command = setRadius,
- value = force.getRadius())
- self.createForceActiveWidget(frame, pageName, forceName, force)
- def createLinearDistanceForceWidget(self, forcePage, pageName,
- count, force, type):
- def setFalloffType(type, f=force):
- if type == 'FT_ONE_OVER_R':
- #f.setFalloffType(LinearDistanceForce.FTONEOVERR)
- f.setFalloffType(0)
- if type == 'FT_ONE_OVER_R_SQUARED':
- #f.setFalloffType(LinearDistanceForce.FTONEOVERRSQUARED)
- f.setFalloffType(1)
- if type == 'FT_ONE_OVER_R_CUBED':
- #f.setFalloffType(LinearDistanceForce.FTONEOVERRCUBED)
- f.setFalloffType(2)
- if type == 'FT_ONE_OVER_R_OVER_DISTANCE':
- f.setFalloffType(3)
- if type == 'FT_ONE_OVER_R_OVER_DISTANCE_SQUARED':
- f.setFalloffType(4)
- if type == 'FT_ONE_OVER_R_OVER_DISTANCE_CUBED':
- f.setFalloffType(5)
- def setForceCenter(vec, f = force):
- f.setForceCenter(Point3(vec[0], vec[1], vec[2]))
- def setRadius(radius, f = force):
- f.setRadius(radius)
- forceName = type + ' Force-' + repr(count)
- frame = self.createForceFrame(forcePage, forceName, force)
- self.createLinearForceWidgets(frame, pageName, forceName, force)
- var = self.createOptionMenu(
- frame, pageName, forceName + ' Falloff',
- 'Set force falloff type',
- ('FT_ONE_OVER_R',
- 'FT_ONE_OVER_R_SQUARED',
- 'FT_ONE_OVER_R_CUBED',
- 'FT_ONE_OVER_R_OVER_DISTANCE',
- 'FT_ONE_OVER_R_OVER_DISTANCE_SQUARED',
- 'FT_ONE_OVER_R_OVER_DISTANCE_CUBED'),
- command = setFalloffType)
- self.getWidget(pageName, forceName + ' Falloff').configure(
- label_width = 16)
- falloff = force.getFalloffType()
- if falloff == LinearDistanceForce.FTONEOVERR:
- var.set('FT_ONE_OVER_R')
- elif falloff == LinearDistanceForce.FTONEOVERRSQUARED:
- var.set('FT_ONE_OVER_R_SQUARED')
- elif falloff == LinearDistanceForce.FTONEOVERRCUBED:
- var.set('FT_ONE_OVER_R_CUBED')
- elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCE:
- var.set('FT_ONE_OVER_R_OVER_DISTANCE')
- elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCESQUARED:
- var.set('FT_ONE_OVER_R_OVER_DISTANCE_SQUARED')
- elif falloff == LinearDistanceForce.FTONEOVERROVERDISTANCECUBED:
- var.set('FT_ONE_OVER_R_OVER_DISTANCE_CUBED')
- vec = force.getForceCenter()
- self.createVector3Entry(frame, pageName, forceName + ' Center',
- 'Set center of force',
- command = setForceCenter,
- label_width = 16,
- value = [vec[0], vec[1], vec[2]])
- self.createFloater(frame, pageName, forceName + ' Radius',
- 'Set falloff radius',
- command = setRadius,
- min = 0.01,
- value = force.getRadius())
- self.createForceActiveWidget(frame, pageName, forceName, force)
|