Source code for direct.particles.ParticleEffect


from panda3d.core import *

# Leave these imports in, they may be used by ptf files.
from panda3d.physics import * # pylint: disable=unused-import
from . import Particles # pylint: disable=unused-import
from . import ForceGroup # pylint: disable=unused-import

from direct.directnotify import DirectNotifyGlobal


[docs]class ParticleEffect(NodePath): notify = DirectNotifyGlobal.directNotify.newCategory('ParticleEffect') pid = 1
[docs] def __init__(self, name=None, particles=None): if name is None: name = 'particle-effect-%d' % ParticleEffect.pid ParticleEffect.pid += 1 NodePath.__init__(self, name) # Record particle effect name self.name = name # Enabled flag self.fEnabled = 0 # Dictionary of particles and forceGroups self.particlesDict = {} self.forceGroupDict = {} # The effect's particle system if particles is not None: self.addParticles(particles) self.renderParent = None
[docs] def birthLitter(self): for p in self.particlesDict.values(): p.birthLitter()
[docs] def cleanup(self): self.removeNode() self.disable() if self.__isValid(): for f in self.forceGroupDict.values(): f.cleanup() for p in self.particlesDict.values(): p.cleanup() del self.forceGroupDict del self.particlesDict del self.renderParent
[docs] def getName(self): # override NodePath.getName() return self.name
[docs] def reset(self): self.removeAllForces() self.removeAllParticles() self.forceGroupDict = {} self.particlesDict = {}
[docs] def start(self, parent=None, renderParent=None): assert self.notify.debug('start() - name: %s' % self.name) self.renderParent = renderParent self.enable() if parent is not None: self.reparentTo(parent)
[docs] def enable(self): # band-aid added for client crash - grw if self.__isValid(): if self.renderParent: for p in self.particlesDict.values(): p.setRenderParent(self.renderParent.node()) for f in self.forceGroupDict.values(): f.enable() for p in self.particlesDict.values(): p.enable() self.fEnabled = 1
[docs] def disable(self): self.detachNode() # band-aid added for client crash - grw if self.__isValid(): for p in self.particlesDict.values(): p.setRenderParent(p.node) for f in self.forceGroupDict.values(): f.disable() for p in self.particlesDict.values(): p.disable() self.fEnabled = 0
[docs] def isEnabled(self): """ Note: this may be misleading if enable(), disable() not used """ return self.fEnabled
[docs] def addForceGroup(self, forceGroup): forceGroup.nodePath.reparentTo(self) forceGroup.particleEffect = self self.forceGroupDict[forceGroup.getName()] = forceGroup # Associate the force group with all particles for force in forceGroup: self.addForce(force)
[docs] def addForce(self, force): for p in list(self.particlesDict.values()): p.addForce(force)
[docs] def removeForceGroup(self, forceGroup): # Remove forces from all particles for force in forceGroup: self.removeForce(force) forceGroup.nodePath.removeNode() forceGroup.particleEffect = None self.forceGroupDict.pop(forceGroup.getName(), None)
[docs] def removeForce(self, force): for p in list(self.particlesDict.values()): p.removeForce(force)
[docs] def removeAllForces(self): for fg in list(self.forceGroupDict.values()): self.removeForceGroup(fg)
[docs] def addParticles(self, particles): particles.nodePath.reparentTo(self) self.particlesDict[particles.getName()] = particles # Associate all forces in all force groups with the particles for fg in list(self.forceGroupDict.values()): for force in fg: particles.addForce(force)
[docs] def removeParticles(self, particles): if particles is None: self.notify.warning('removeParticles() - particles is None!') return particles.nodePath.detachNode() self.particlesDict.pop(particles.getName(), None) # Remove all forces from the particles for fg in list(self.forceGroupDict.values()): for f in fg: particles.removeForce(f)
[docs] def removeAllParticles(self): for p in list(self.particlesDict.values()): self.removeParticles(p)
[docs] def getParticlesList(self): return list(self.particlesDict.values())
[docs] def getParticlesNamed(self, name): return self.particlesDict.get(name, None)
[docs] def getParticlesDict(self): return self.particlesDict
[docs] def getForceGroupList(self): return list(self.forceGroupDict.values())
[docs] def getForceGroupNamed(self, name): return self.forceGroupDict.get(name, None)
[docs] def getForceGroupDict(self): return self.forceGroupDict
[docs] def saveConfig(self, filename): filename = Filename(filename) with open(filename.toOsSpecific(), 'w') as f: # Add a blank line f.write('\n') # Make sure we start with a clean slate f.write('self.reset()\n') pos = self.getPos() hpr = self.getHpr() scale = self.getScale() f.write('self.setPos(%0.3f, %0.3f, %0.3f)\n' % (pos[0], pos[1], pos[2])) f.write('self.setHpr(%0.3f, %0.3f, %0.3f)\n' % (hpr[0], hpr[1], hpr[2])) f.write('self.setScale(%0.3f, %0.3f, %0.3f)\n' % (scale[0], scale[1], scale[2])) # Save all the particles to file num = 0 for p in list(self.particlesDict.values()): target = 'p%d' % num num = num + 1 f.write(target + ' = Particles.Particles(\'%s\')\n' % p.getName()) p.printParams(f, target) f.write('self.addParticles(%s)\n' % target) # Save all the forces to file num = 0 for fg in list(self.forceGroupDict.values()): target = 'f%d' % num num = num + 1 f.write(target + ' = ForceGroup.ForceGroup(\'%s\')\n' % \ fg.getName()) fg.printParams(f, target) f.write('self.addForceGroup(%s)\n' % target)
[docs] def loadConfig(self, filename): fn = Filename(filename) vfs = VirtualFileSystem.getGlobalPtr() try: if not vfs.resolveFilename(fn, getModelPath().value) and not fn.isRegularFile(): raise FileNotFoundError("could not find particle file: %s" % (filename)) data = vfs.readFile(fn, True) data = data.replace(b'\r', b'') exec(data) except: self.notify.warning('loadConfig: failed to load particle file: '+ repr(filename)) raise
[docs] def accelerate(self,time,stepCount = 1,stepTime=0.0): for particles in self.getParticlesList(): particles.accelerate(time,stepCount,stepTime)
[docs] def clearToInitial(self): for particles in self.getParticlesList(): particles.clearToInitial()
[docs] def softStop(self): for particles in self.getParticlesList(): particles.softStop()
[docs] def softStart(self, firstBirthDelay=None): if self.__isValid(): for particles in self.getParticlesList(): if firstBirthDelay is not None: particles.softStart(br=-1, first_birth_delay=firstBirthDelay) else: particles.softStart() else: # Not asserting here since we want to crash live clients for more expedient bugfix # (Sorry, live clients) self.notify.error('Trying to start effect(%s) after cleanup.' % (self.getName(),))
def __isValid(self): return hasattr(self, 'forceGroupDict') and \ hasattr(self, 'particlesDict') # Snake-case aliases. is_enabled = isEnabled add_force_group = addForceGroup add_force = addForce remove_force_group = removeForceGroup remove_force = removeForce remove_all_forces = removeAllForces add_particles = addParticles remove_particles = removeParticles remove_all_particles = removeAllParticles get_particles_list = getParticlesList get_particles_named = getParticlesNamed get_particles_dict = getParticlesDict get_force_group_list = getForceGroupList get_force_group_named = getForceGroupNamed get_force_group_dict = getForceGroupDict save_config = saveConfig load_config = loadConfig clear_to_initial = clearToInitial soft_stop = softStop soft_start = softStart birth_litter = birthLitter