Source code for direct.particles.Particles

"""The Python specialization of the particle system.

See the :ref:`particle-effects` section in the manual for an explanation
of the particle system.
"""

from acron.core import ColorBlendAttrib, NodePath

from acron.physics import PhysicalNode
from acron.physics import ParticleSystem
from acron.physics import PointParticleFactory
from acron.physics import ZSpinParticleFactory
#from acron.physics import OrientedParticleFactory
from acron.physics import BaseParticleRenderer
from acron.physics import PointParticleRenderer
from acron.physics import LineParticleRenderer
from acron.physics import GeomParticleRenderer
from acron.physics import SparkleParticleRenderer
#from acron.physics import SpriteParticleRenderer
from acron.physics import BaseParticleEmitter
from acron.physics import ArcEmitter
from acron.physics import BoxEmitter
from acron.physics import DiscEmitter
from acron.physics import LineEmitter
from acron.physics import PointEmitter
from acron.physics import RectangleEmitter
from acron.physics import RingEmitter
from acron.physics import SphereSurfaceEmitter
from acron.physics import SphereVolumeEmitter
from acron.physics import TangentRingEmitter
from acron.physics import SpriteAnim

from . import SpriteParticleRendererExt

from direct.directnotify.DirectNotifyGlobal import directNotify
import sys


[docs] class Particles(ParticleSystem): notify = directNotify.newCategory('Particles') id = 1 def __init__(self, name=None, poolSize=1024): if name is None: self.name = 'particles-%d' % Particles.id Particles.id += 1 else: self.name = name ParticleSystem.__init__(self, poolSize) # self.setBirthRate(0.02) # self.setLitterSize(10) # self.setLitterSpread(0) # Set up a physical node self.node = PhysicalNode(self.name) self.nodePath = NodePath(self.node) self.setRenderParent(self.node) self.node.addPhysical(self) self.factory = None self.factoryType = "undefined" # self.setFactory("PointParticleFactory") self.renderer = None self.rendererType = "undefined" # self.setRenderer("PointParticleRenderer") self.emitter = None self.emitterType = "undefined" # self.setEmitter("SphereVolumeEmitter") # Enable particles by default self.fEnabled = 0 #self.enable() self.geomReference = "" def cleanup(self): self.disable() self.clearLinearForces() self.clearAngularForces() self.setRenderParent(self.node) self.node.removePhysical(self) self.nodePath.removeNode() del self.node del self.nodePath del self.factory del self.renderer del self.emitter def enable(self): if self.fEnabled == 0: base.physicsMgr.attachPhysical(self) base.particleMgr.attachParticlesystem(self) self.fEnabled = 1 def disable(self): if self.fEnabled == 1: base.physicsMgr.removePhysical(self) base.particleMgr.removeParticlesystem(self) self.fEnabled = 0 def isEnabled(self): return self.fEnabled def getNode(self): return self.node def setFactory(self, type): if self.factoryType == type: return None if self.factory: self.factory = None self.factoryType = type if type == "PointParticleFactory": self.factory = PointParticleFactory() elif type == "ZSpinParticleFactory": self.factory = ZSpinParticleFactory() #elif type == "OrientedParticleFactory": # self.factory = OrientedParticleFactory() else: print("unknown factory type: %s" % type) return None self.factory.setLifespanBase(0.5) ParticleSystem.setFactory(self, self.factory) def setRenderer(self, type): if self.rendererType == type: return None if self.renderer: self.renderer = None self.rendererType = type if type == "PointParticleRenderer": self.renderer = PointParticleRenderer() self.renderer.setPointSize(1.0) elif type == "LineParticleRenderer": self.renderer = LineParticleRenderer() elif type == "GeomParticleRenderer": self.renderer = GeomParticleRenderer() # This was moved here because we do not want to download # the direct tools with toontown. if __dev__: from direct.directtools import DirectSelection npath = NodePath('default-geom') bbox = DirectSelection.DirectBoundingBox(npath) self.renderer.setGeomNode(bbox.lines.node()) elif type == "SparkleParticleRenderer": self.renderer = SparkleParticleRenderer() elif type == "SpriteParticleRenderer": self.renderer = SpriteParticleRendererExt.SpriteParticleRendererExt() # self.renderer.setTextureFromFile() else: print("unknown renderer type: %s" % type) return None ParticleSystem.setRenderer(self, self.renderer) def setEmitter(self, type): if self.emitterType == type: return None if self.emitter: self.emitter = None self.emitterType = type if type == "ArcEmitter": self.emitter = ArcEmitter() elif type == "BoxEmitter": self.emitter = BoxEmitter() elif type == "DiscEmitter": self.emitter = DiscEmitter() elif type == "LineEmitter": self.emitter = LineEmitter() elif type == "PointEmitter": self.emitter = PointEmitter() elif type == "RectangleEmitter": self.emitter = RectangleEmitter() elif type == "RingEmitter": self.emitter = RingEmitter() elif type == "SphereSurfaceEmitter": self.emitter = SphereSurfaceEmitter() elif type == "SphereVolumeEmitter": self.emitter = SphereVolumeEmitter() self.emitter.setRadius(1.0) elif type == "TangentRingEmitter": self.emitter = TangentRingEmitter() else: print("unknown emitter type: %s" % type) return None ParticleSystem.setEmitter(self, self.emitter) def addForce(self, force): if force.isLinear(): self.addLinearForce(force) else: self.addAngularForce(force) def removeForce(self, force): if force is None: self.notify.warning('removeForce() - force is None!') return if force.isLinear(): self.removeLinearForce(force) else: self.removeAngularForce(force) def setRenderNodePath(self, nodePath): self.setRenderParent(nodePath.node()) ## Getters ## def getName(self): return self.name def getFactory(self): return self.factory def getEmitter(self): return self.emitter def getRenderer(self): return self.renderer def printParams(self, file = sys.stdout, targ = 'self'): file.write('# Particles parameters\n') file.write(targ + '.setFactory(\"' + self.factoryType + '\")\n') file.write(targ + '.setRenderer(\"' + self.rendererType + '\")\n') file.write(targ + '.setEmitter(\"' + self.emitterType + '\")\n') # System parameters file.write(targ + ('.setPoolSize(%d)\n' % int(self.getPoolSize()))) file.write(targ + ('.setBirthRate(%.4f)\n' % self.getBirthRate())) file.write(targ + ('.setLitterSize(%d)\n' % int(self.getLitterSize()))) file.write(targ + ('.setLitterSpread(%d)\n' % self.getLitterSpread())) file.write(targ + ('.setSystemLifespan(%.4f)\n' % self.getSystemLifespan())) file.write(targ + ('.setLocalVelocityFlag(%d)\n' % self.getLocalVelocityFlag())) file.write(targ + ('.setSystemGrowsOlderFlag(%d)\n' % self.getSystemGrowsOlderFlag())) file.write('# Factory parameters\n') file.write(targ + ('.factory.setLifespanBase(%.4f)\n' % self.factory.getLifespanBase())) file.write(targ + '.factory.setLifespanSpread(%.4f)\n' % \ self.factory.getLifespanSpread()) file.write(targ + '.factory.setMassBase(%.4f)\n' % \ self.factory.getMassBase()) file.write(targ + '.factory.setMassSpread(%.4f)\n' % \ self.factory.getMassSpread()) file.write(targ + '.factory.setTerminalVelocityBase(%.4f)\n' % \ self.factory.getTerminalVelocityBase()) file.write(targ + '.factory.setTerminalVelocitySpread(%.4f)\n' % \ self.factory.getTerminalVelocitySpread()) if self.factoryType == "PointParticleFactory": file.write('# Point factory parameters\n') elif self.factoryType == "ZSpinParticleFactory": file.write('# Z Spin factory parameters\n') file.write(targ + '.factory.setInitialAngle(%.4f)\n' % \ self.factory.getInitialAngle()) file.write(targ + '.factory.setInitialAngleSpread(%.4f)\n' % \ self.factory.getInitialAngleSpread()) file.write(targ + '.factory.enableAngularVelocity(%d)\n' % \ self.factory.getAngularVelocityEnabled()) if self.factory.getAngularVelocityEnabled(): file.write(targ + '.factory.setAngularVelocity(%.4f)\n' % \ self.factory.getAngularVelocity()) file.write(targ + '.factory.setAngularVelocitySpread(%.4f)\n' % \ self.factory.getAngularVelocitySpread()) else: file.write(targ + '.factory.setFinalAngle(%.4f)\n' % \ self.factory.getFinalAngle()) file.write(targ + '.factory.setFinalAngleSpread(%.4f)\n' % \ self.factory.getFinalAngleSpread()) elif self.factoryType == "OrientedParticleFactory": file.write('# Oriented factory parameters\n') file.write(targ + '.factory.setInitialOrientation(%.4f)\n' % \ self.factory.getInitialOrientation()) file.write(targ + '.factory.setFinalOrientation(%.4f)\n' % \ self.factory.getFinalOrientation()) file.write('# Renderer parameters\n') alphaMode = self.renderer.getAlphaMode() aMode = "PRALPHANONE" if alphaMode == BaseParticleRenderer.PRALPHANONE: aMode = "PRALPHANONE" elif alphaMode == BaseParticleRenderer.PRALPHAOUT: aMode = "PRALPHAOUT" elif alphaMode == BaseParticleRenderer.PRALPHAIN: aMode = "PRALPHAIN" elif alphaMode == BaseParticleRenderer.PRALPHAINOUT: aMode = "PRALPHAINOUT" elif alphaMode == BaseParticleRenderer.PRALPHAUSER: aMode = "PRALPHAUSER" file.write(targ + '.renderer.setAlphaMode(BaseParticleRenderer.' + aMode + ')\n') file.write(targ + '.renderer.setUserAlpha(%.2f)\n' % \ self.renderer.getUserAlpha()) if self.rendererType == "PointParticleRenderer": file.write('# Point parameters\n') file.write(targ + '.renderer.setPointSize(%.2f)\n' % \ self.renderer.getPointSize()) sColor = self.renderer.getStartColor() file.write((targ + '.renderer.setStartColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getEndColor() file.write((targ + '.renderer.setEndColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) blendType = self.renderer.getBlendType() bType = "PPONECOLOR" if blendType == PointParticleRenderer.PPONECOLOR: bType = "PPONECOLOR" elif blendType == PointParticleRenderer.PPBLENDLIFE: bType = "PPBLENDLIFE" elif blendType == PointParticleRenderer.PPBLENDVEL: bType = "PPBLENDVEL" file.write(targ + '.renderer.setBlendType(PointParticleRenderer.' + bType + ')\n') blendMethod = self.renderer.getBlendMethod() bMethod = "PPNOBLEND" if blendMethod == BaseParticleRenderer.PPNOBLEND: bMethod = "PPNOBLEND" elif blendMethod == BaseParticleRenderer.PPBLENDLINEAR: bMethod = "PPBLENDLINEAR" elif blendMethod == BaseParticleRenderer.PPBLENDCUBIC: bMethod = "PPBLENDCUBIC" file.write(targ + '.renderer.setBlendMethod(BaseParticleRenderer.' + bMethod + ')\n') elif self.rendererType == "LineParticleRenderer": file.write('# Line parameters\n') sColor = self.renderer.getHeadColor() file.write((targ + '.renderer.setHeadColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getTailColor() file.write((targ + '.renderer.setTailColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sf = self.renderer.getLineScaleFactor() file.write((targ + '.renderer.setLineScaleFactor(%.2f)\n' % (sf))) elif self.rendererType == "GeomParticleRenderer": file.write('# Geom parameters\n') node = self.renderer.getGeomNode() file.write('geomRef = loader.loadModel("' + self.geomReference + '")\n') file.write(targ + '.renderer.setGeomNode(geomRef.node())\n') file.write(targ + '.geomReference = "' + self.geomReference + '"\n') cbmLut = ('MNone','MAdd','MSubtract','MInvSubtract','MMin','MMax') cboLut = ('OZero','OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor', 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha', 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor', 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha', 'OIncomingColorSaturate') file.write(targ + '.renderer.setXScaleFlag(%d)\n' % self.renderer.getXScaleFlag()) file.write(targ + '.renderer.setYScaleFlag(%d)\n' % self.renderer.getYScaleFlag()) file.write(targ + '.renderer.setZScaleFlag(%d)\n' % self.renderer.getZScaleFlag()) file.write(targ + '.renderer.setInitialXScale(%.4f)\n' % self.renderer.getInitialXScale()) file.write(targ + '.renderer.setFinalXScale(%.4f)\n' % self.renderer.getFinalXScale()) file.write(targ + '.renderer.setInitialYScale(%.4f)\n' % self.renderer.getInitialYScale()) file.write(targ + '.renderer.setFinalYScale(%.4f)\n' % self.renderer.getFinalYScale()) file.write(targ + '.renderer.setInitialZScale(%.4f)\n' % self.renderer.getInitialZScale()) file.write(targ + '.renderer.setFinalZScale(%.4f)\n' % self.renderer.getFinalZScale()) cbAttrib = self.renderer.getRenderNode().getAttrib(ColorBlendAttrib.getClassType()) if cbAttrib: cbMode = cbAttrib.getMode() if cbMode > 0: if cbMode in (ColorBlendAttrib.MAdd, ColorBlendAttrib.MSubtract, ColorBlendAttrib.MInvSubtract): cboa = cbAttrib.getOperandA() cbob = cbAttrib.getOperandB() file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s, ColorBlendAttrib.%s, ColorBlendAttrib.%s)\n' % (cbmLut[cbMode], cboLut[cboa], cboLut[cbob])) else: file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s)\n' % cbmLut[cbMode]) cim = self.renderer.getColorInterpolationManager() segIdList = [int(seg) for seg in cim.getSegmentIdList().split()] for sid in segIdList: seg = cim.getSegment(sid) if seg.isEnabled(): t_b = seg.getTimeBegin() t_e = seg.getTimeEnd() mod = seg.isModulated() fun = seg.getFunction() typ = type(fun).__name__ if typ == 'ColorInterpolationFunctionConstant': c_a = fun.getColorA() file.write(targ+'.renderer.getColorInterpolationManager().addConstant('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),'+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionLinear': c_a = fun.getColorA() c_b = fun.getColorB() file.write(targ+'.renderer.getColorInterpolationManager().addLinear('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),'+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionStepwave': c_a = fun.getColorA() c_b = fun.getColorB() w_a = fun.getWidthA() w_b = fun.getWidthB() file.write(targ+'.renderer.getColorInterpolationManager().addStepwave('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),' + \ repr(w_a)+','+repr(w_b)+','+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionSinusoid': c_a = fun.getColorA() c_b = fun.getColorB() per = fun.getPeriod() file.write(targ+'.renderer.getColorInterpolationManager().addSinusoid('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),' + \ repr(per)+','+repr(mod)+')\n') elif self.rendererType == "SparkleParticleRenderer": file.write('# Sparkle parameters\n') sColor = self.renderer.getCenterColor() file.write((targ + '.renderer.setCenterColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getEdgeColor() file.write((targ + '.renderer.setEdgeColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) file.write(targ + '.renderer.setBirthRadius(%.4f)\n' % self.renderer.getBirthRadius()) file.write(targ + '.renderer.setDeathRadius(%.4f)\n' % self.renderer.getDeathRadius()) lifeScale = self.renderer.getLifeScale() lScale = "SPNOSCALE" if lifeScale == SparkleParticleRenderer.SPSCALE: lScale = "SPSCALE" file.write(targ + '.renderer.setLifeScale(SparkleParticleRenderer.' + lScale + ')\n') elif self.rendererType == "SpriteParticleRenderer": file.write('# Sprite parameters\n') if self.renderer.getAnimateFramesEnable(): file.write(targ + '.renderer.setAnimateFramesEnable(True)\n') rate = self.renderer.getAnimateFramesRate() if rate: file.write(targ + '.renderer.setAnimateFramesRate(%.3f)\n'%rate) animCount = self.renderer.getNumAnims() for x in range(animCount): anim = self.renderer.getAnim(x) if anim.getSourceType() == SpriteAnim.STTexture: file.write(targ + '.renderer.addTextureFromFile(\'%s\')\n' % (anim.getTexSource(),)) else: file.write(targ + '.renderer.addTextureFromNode(\'%s\',\'%s\')\n' % (anim.getModelSource(), anim.getNodeSource())) sColor = self.renderer.getColor() file.write((targ + '.renderer.setColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) file.write(targ + '.renderer.setXScaleFlag(%d)\n' % self.renderer.getXScaleFlag()) file.write(targ + '.renderer.setYScaleFlag(%d)\n' % self.renderer.getYScaleFlag()) file.write(targ + '.renderer.setAnimAngleFlag(%d)\n' % self.renderer.getAnimAngleFlag()) file.write(targ + '.renderer.setInitialXScale(%.4f)\n' % self.renderer.getInitialXScale()) file.write(targ + '.renderer.setFinalXScale(%.4f)\n' % self.renderer.getFinalXScale()) file.write(targ + '.renderer.setInitialYScale(%.4f)\n' % self.renderer.getInitialYScale()) file.write(targ + '.renderer.setFinalYScale(%.4f)\n' % self.renderer.getFinalYScale()) file.write(targ + '.renderer.setNonanimatedTheta(%.4f)\n' % self.renderer.getNonanimatedTheta()) blendMethod = self.renderer.getAlphaBlendMethod() bMethod = "PPNOBLEND" if blendMethod == BaseParticleRenderer.PPNOBLEND: bMethod = "PPNOBLEND" elif blendMethod == BaseParticleRenderer.PPBLENDLINEAR: bMethod = "PPBLENDLINEAR" elif blendMethod == BaseParticleRenderer.PPBLENDCUBIC: bMethod = "PPBLENDCUBIC" file.write(targ + '.renderer.setAlphaBlendMethod(BaseParticleRenderer.' + bMethod + ')\n') file.write(targ + '.renderer.setAlphaDisable(%d)\n' % self.renderer.getAlphaDisable()) # Save the color blending to file cbmLut = ('MNone','MAdd','MSubtract','MInvSubtract','MMin','MMax') cboLut = ('OZero','OOne','OIncomingColor','OOneMinusIncomingColor','OFbufferColor', 'OOneMinusFbufferColor','OIncomingAlpha','OOneMinusIncomingAlpha', 'OFbufferAlpha','OOneMinusFbufferAlpha','OConstantColor', 'OOneMinusConstantColor','OConstantAlpha','OOneMinusConstantAlpha', 'OIncomingColorSaturate') cbAttrib = self.renderer.getRenderNode().getAttrib(ColorBlendAttrib.getClassType()) if cbAttrib: cbMode = cbAttrib.getMode() if cbMode > 0: if cbMode in (ColorBlendAttrib.MAdd, ColorBlendAttrib.MSubtract, ColorBlendAttrib.MInvSubtract): cboa = cbAttrib.getOperandA() cbob = cbAttrib.getOperandB() file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s, ColorBlendAttrib.%s, ColorBlendAttrib.%s)\n' % (cbmLut[cbMode], cboLut[cboa], cboLut[cbob])) else: file.write(targ+'.renderer.setColorBlendMode(ColorBlendAttrib.%s)\n' % cbmLut[cbMode]) cim = self.renderer.getColorInterpolationManager() segIdList = [int(seg) for seg in cim.getSegmentIdList().split()] for sid in segIdList: seg = cim.getSegment(sid) if seg.isEnabled(): t_b = seg.getTimeBegin() t_e = seg.getTimeEnd() mod = seg.isModulated() fun = seg.getFunction() typ = type(fun).__name__ if typ == 'ColorInterpolationFunctionConstant': c_a = fun.getColorA() file.write(targ+'.renderer.getColorInterpolationManager().addConstant('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),'+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionLinear': c_a = fun.getColorA() c_b = fun.getColorB() file.write(targ+'.renderer.getColorInterpolationManager().addLinear('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),'+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionStepwave': c_a = fun.getColorA() c_b = fun.getColorB() w_a = fun.getWidthA() w_b = fun.getWidthB() file.write(targ+'.renderer.getColorInterpolationManager().addStepwave('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),' + \ repr(w_a)+','+repr(w_b)+','+repr(mod)+')\n') elif typ == 'ColorInterpolationFunctionSinusoid': c_a = fun.getColorA() c_b = fun.getColorB() per = fun.getPeriod() file.write(targ+'.renderer.getColorInterpolationManager().addSinusoid('+repr(t_b)+','+repr(t_e)+','+ \ 'Vec4('+repr(c_a[0])+','+repr(c_a[1])+','+repr(c_a[2])+','+repr(c_a[3])+'),' + \ 'Vec4('+repr(c_b[0])+','+repr(c_b[1])+','+repr(c_b[2])+','+repr(c_b[3])+'),' + \ repr(per)+','+repr(mod)+')\n') file.write('# Emitter parameters\n') emissionType = self.emitter.getEmissionType() eType = "ETEXPLICIT" if emissionType == BaseParticleEmitter.ETEXPLICIT: eType = "ETEXPLICIT" elif emissionType == BaseParticleEmitter.ETRADIATE: eType = "ETRADIATE" elif emissionType == BaseParticleEmitter.ETCUSTOM: eType = "ETCUSTOM" file.write(targ + '.emitter.setEmissionType(BaseParticleEmitter.' + eType + ')\n') file.write(targ + '.emitter.setAmplitude(%.4f)\n' % self.emitter.getAmplitude()) file.write(targ + '.emitter.setAmplitudeSpread(%.4f)\n' % self.emitter.getAmplitudeSpread()) oForce = self.emitter.getOffsetForce() file.write((targ + '.emitter.setOffsetForce(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2]))) oForce = self.emitter.getExplicitLaunchVector() file.write((targ + '.emitter.setExplicitLaunchVector(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2]))) orig = self.emitter.getRadiateOrigin() file.write((targ + '.emitter.setRadiateOrigin(Point3(%.4f, %.4f, %.4f))\n' % (orig[0], orig[1], orig[2]))) if self.emitterType == "BoxEmitter": file.write('# Box parameters\n') bound = self.emitter.getMinBound() file.write((targ + '.emitter.setMinBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2]))) bound = self.emitter.getMaxBound() file.write((targ + '.emitter.setMaxBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2]))) elif self.emitterType == "DiscEmitter": file.write('# Disc parameters\n') file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) if eType == "ETCUSTOM": file.write(targ + '.emitter.setOuterAngle(%.4f)\n' % self.emitter.getOuterAngle()) file.write(targ + '.emitter.setInnerAngle(%.4f)\n' % self.emitter.getInnerAngle()) file.write(targ + '.emitter.setOuterMagnitude(%.4f)\n' % self.emitter.getOuterMagnitude()) file.write(targ + '.emitter.setInnerMagnitude(%.4f)\n' % self.emitter.getInnerMagnitude()) file.write(targ + '.emitter.setCubicLerping(%d)\n' % self.emitter.getCubicLerping()) elif self.emitterType == "LineEmitter": file.write('# Line parameters\n') point = self.emitter.getEndpoint1() file.write((targ + '.emitter.setEndpoint1(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) point = self.emitter.getEndpoint2() file.write((targ + '.emitter.setEndpoint2(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) elif self.emitterType == "PointEmitter": file.write('# Point parameters\n') point = self.emitter.getLocation() file.write((targ + '.emitter.setLocation(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) elif self.emitterType == "RectangleEmitter": file.write('# Rectangle parameters\n') point = self.emitter.getMinBound() file.write((targ + '.emitter.setMinBound(Point2(%.4f, %.4f))\n' % (point[0], point[1]))) point = self.emitter.getMaxBound() file.write((targ + '.emitter.setMaxBound(Point2(%.4f, %.4f))\n' % (point[0], point[1]))) elif self.emitterType == "RingEmitter": file.write('# Ring parameters\n') file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) file.write(targ + '.emitter.setRadiusSpread(%.4f)\n' % self.emitter.getRadiusSpread()) if eType == "ETCUSTOM": file.write(targ + '.emitter.setAngle(%.4f)\n' % self.emitter.getAngle()) elif self.emitterType == "SphereSurfaceEmitter": file.write('# Sphere Surface parameters\n') file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) elif self.emitterType == "SphereVolumeEmitter": file.write('# Sphere Volume parameters\n') file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) elif self.emitterType == "TangentRingEmitter": file.write('# Tangent Ring parameters\n') file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) file.write(targ + '.emitter.setRadiusSpread(%.4f)\n' % self.emitter.getRadiusSpread()) def getPoolSizeRanges(self): litterRange = [max(1,self.getLitterSize()-self.getLitterSpread()), self.getLitterSize(), self.getLitterSize()+self.getLitterSpread()] lifespanRange = [self.factory.getLifespanBase()-self.factory.getLifespanSpread(), self.factory.getLifespanBase(), self.factory.getLifespanBase()+self.factory.getLifespanSpread()] birthRateRange = [self.getBirthRate()] * 3 print('Litter Ranges: %s' % litterRange) print('LifeSpan Ranges: %s' % lifespanRange) print('BirthRate Ranges: %s' % birthRateRange) return dict(zip(('min','median','max'),[l*s/b for l,s,b in zip(litterRange,lifespanRange,birthRateRange)])) def accelerate(self,time,stepCount = 1,stepTime=0.0): if time > 0.0: if stepTime == 0.0: stepTime = float(time)/stepCount remainder = 0.0 else: stepCount = int(float(time)/stepTime) remainder = time-stepCount*stepTime for step in range(stepCount): base.particleMgr.doParticles(stepTime,self,False) base.physicsMgr.doPhysics(stepTime,self) if remainder: base.particleMgr.doParticles(remainder,self,False) base.physicsMgr.doPhysics(remainder,self) self.render() # Snake-case aliases. is_enabled = isEnabled set_factory = setFactory set_renderer = setRenderer set_emitter = setEmitter add_force = addForce remove_force = removeForce set_render_node_path = setRenderNodePath get_factory = getFactory get_emitter = getEmitter get_renderer = getRenderer print_params = printParams get_pool_size_ranges = getPoolSizeRanges