from pandac.PandaModules import * from direct.particles.ParticleManagerGlobal import * from direct.showbase.PhysicsManagerGlobal import * from pandac import ParticleSystem from pandac import BaseParticleFactory from pandac import PointParticleFactory from pandac import ZSpinParticleFactory #import OrientedParticleFactory from pandac import BaseParticleRenderer from pandac import PointParticleRenderer from pandac import LineParticleRenderer from pandac import GeomParticleRenderer from pandac import SparkleParticleRenderer from pandac import SpriteParticleRenderer from pandac import BaseParticleEmitter from pandac import BoxEmitter from pandac import DiscEmitter from pandac import LineEmitter from pandac import PointEmitter from pandac import RectangleEmitter from pandac import RingEmitter from pandac import SphereSurfaceEmitter from pandac import SphereVolumeEmitter from pandac import TangentRingEmitter import string import os from direct.directnotify import DirectNotifyGlobal import sys class Particles(ParticleSystem.ParticleSystem): notify = DirectNotifyGlobal.directNotify.newCategory('Particles') id = 1 def __init__(self, name=None, poolSize=1024): """__init__(name, poolSize)""" if (name == None): self.name = 'particles-%d' % Particles.id Particles.id += 1 else: self.name = name ParticleSystem.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() 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): """enable()""" if (self.fEnabled == 0): physicsMgr.attachPhysical(self) particleMgr.attachParticlesystem(self) self.fEnabled = 1 def disable(self): """disable()""" if (self.fEnabled == 1): physicsMgr.removePhysical(self) particleMgr.removeParticlesystem(self) self.fEnabled = 0 def isEnabled(self): return self.fEnabled def getNode(self): return self.node def setFactory(self, type): """setFactory(type)""" if (self.factoryType == type): return None if (self.factory): self.factory = None self.factoryType = type if (type == "PointParticleFactory"): self.factory = PointParticleFactory.PointParticleFactory() elif (type == "ZSpinParticleFactory"): self.factory = ZSpinParticleFactory.ZSpinParticleFactory() elif (type == "OrientedParticleFactory"): self.factory = OrientedParticleFactory.OrientedParticleFactory() else: print "unknown factory type: %s" % type return None self.factory.setLifespanBase(0.5) ParticleSystem.ParticleSystem.setFactory(self, self.factory) def setRenderer(self, type): """setRenderer(type)""" if (self.rendererType == type): return None if (self.renderer): self.renderer = None self.rendererType = type if (type == "PointParticleRenderer"): self.renderer = PointParticleRenderer.PointParticleRenderer() self.renderer.setPointSize(1.0) elif (type == "LineParticleRenderer"): self.renderer = LineParticleRenderer.LineParticleRenderer() elif (type == "GeomParticleRenderer"): self.renderer = GeomParticleRenderer.GeomParticleRenderer() npath = NodePath('default-geom') # This was moved here because we do not want to download # the direct tools with toontown. from direct.directtools import DirectSelection bbox = DirectSelection.DirectBoundingBox(npath) self.renderer.setGeomNode(bbox.lines.node()) elif (type == "SparkleParticleRenderer"): self.renderer = SparkleParticleRenderer.SparkleParticleRenderer() elif (type == "SpriteParticleRenderer"): self.renderer = SpriteParticleRenderer.SpriteParticleRenderer() if (self.renderer.getSourceType() == SpriteParticleRenderer.SpriteParticleRenderer.STTexture): # Use current default texture # See sourceTextureName SpriteParticleRenderer-extensions.py self.renderer.setTextureFromFile() else: # Use current default model file and node # See sourceFileName and sourceNodeName in SpriteParticleRenderer-extensions.py self.renderer.setTextureFromNode() else: print "unknown renderer type: %s" % type return None ParticleSystem.ParticleSystem.setRenderer(self, self.renderer) def setEmitter(self, type): """setEmitter(type)""" if (self.emitterType == type): return None if (self.emitter): self.emitter = None self.emitterType = type if (type == "BoxEmitter"): self.emitter = BoxEmitter.BoxEmitter() elif (type == "DiscEmitter"): self.emitter = DiscEmitter.DiscEmitter() elif (type == "LineEmitter"): self.emitter = LineEmitter.LineEmitter() elif (type == "PointEmitter"): self.emitter = PointEmitter.PointEmitter() elif (type == "RectangleEmitter"): self.emitter = RectangleEmitter.RectangleEmitter() elif (type == "RingEmitter"): self.emitter = RingEmitter.RingEmitter() elif (type == "SphereSurfaceEmitter"): self.emitter = SphereSurfaceEmitter.SphereSurfaceEmitter() elif (type == "SphereVolumeEmitter"): self.emitter = SphereVolumeEmitter.SphereVolumeEmitter() self.emitter.setRadius(1.0) elif (type == "TangentRingEmitter"): self.emitter = TangentRingEmitter.TangentRingEmitter() else: print "unknown emitter type: %s" % type return None ParticleSystem.ParticleSystem.setEmitter(self, self.emitter) def addForce(self, force): """addForce(force)""" if (force.isLinear()): self.addLinearForce(force) else: self.addAngularForce(force) def removeForce(self, force): """removeForce(force)""" if (force == None): self.notify.warning('removeForce() - force == None!') return if (force.isLinear()): self.removeLinearForce(force) else: self.removeAngularForce(force) def setRenderNodePath(self, nodePath): self.setRenderParent(nodePath.node()) ## Getters ## def getName(self): """getName()""" return self.name def getFactory(self): """getFactory()""" return self.factory def getEmitter(self): """getEmitter()""" return self.emitter def getRenderer(self): """getRenderer()""" return self.renderer def printParams(self, file = sys.stdout, targ = 'self'): """printParams(file, targ)""" i1=" " i2=i1+i1 file.write(i2+'# Particles parameters\n') file.write(i2+targ + '.setFactory(\"' + self.factoryType + '\")\n') file.write(i2+targ + '.setRenderer(\"' + self.rendererType + '\")\n') file.write(i2+targ + '.setEmitter(\"' + self.emitterType + '\")\n') # System parameters file.write(i2+targ + ('.setPoolSize(%d)\n' % int(self.getPoolSize()))) file.write(i2+targ + ('.setBirthRate(%.4f)\n' % self.getBirthRate())) file.write(i2+targ + ('.setLitterSize(%d)\n' % int(self.getLitterSize()))) file.write(i2+targ + ('.setLitterSpread(%d)\n' % self.getLitterSpread())) file.write(i2+targ + ('.setSystemLifespan(%.4f)\n' % self.getSystemLifespan())) file.write(i2+targ + ('.setLocalVelocityFlag(%d)\n' % self.getLocalVelocityFlag())) file.write(i2+targ + ('.setSystemGrowsOlderFlag(%d)\n' % self.getSystemGrowsOlderFlag())) file.write(i2+'# Factory parameters\n') file.write(i2+targ + ('.factory.setLifespanBase(%.4f)\n' % self.factory.getLifespanBase())) file.write(i2+targ + '.factory.setLifespanSpread(%.4f)\n' % \ self.factory.getLifespanSpread()) file.write(i2+targ + '.factory.setMassBase(%.4f)\n' % \ self.factory.getMassBase()) file.write(i2+targ + '.factory.setMassSpread(%.4f)\n' % \ self.factory.getMassSpread()) file.write(i2+targ + '.factory.setTerminalVelocityBase(%.4f)\n' % \ self.factory.getTerminalVelocityBase()) file.write(i2+targ + '.factory.setTerminalVelocitySpread(%.4f)\n' % \ self.factory.getTerminalVelocitySpread()) if (self.factoryType == "PointParticleFactory"): file.write(i2+'# Point factory parameters\n') elif (self.factoryType == "ZSpinParticleFactory"): file.write(i2+'# Z Spin factory parameters\n') file.write(i2+targ + '.factory.setInitialAngle(%.4f)\n' % \ self.factory.getInitialAngle()) file.write(i2+targ + '.factory.setInitialAngleSpread(%.4f)\n' % \ self.factory.getInitialAngleSpread()) file.write(i2+targ + '.factory.enableAngularVelocity(%d)\n' % \ self.factory.getAngularVelocityEnabled()) if(self.factory.getAngularVelocityEnabled()): file.write(i2+targ + '.factory.setAngularVelocity(%.4f)\n' % \ self.factory.getAngularVelocity()) file.write(i2+targ + '.factory.setAngularVelocitySpread(%.4f)\n' % \ self.factory.getAngularVelocitySpread()) else: file.write(i2+targ + '.factory.setFinalAngle(%.4f)\n' % \ self.factory.getFinalAngle()) file.write(i2+targ + '.factory.setFinalAngleSpread(%.4f)\n' % \ self.factory.getFinalAngleSpread()) elif (self.factoryType == "OrientedParticleFactory"): file.write(i2+'# Oriented factory parameters\n') file.write(i2+targ + '.factory.setInitialOrientation(%.4f)\n' % \ self.factory.getInitialOrientation()) file.write(i2+targ + '.factory.setFinalOrientation(%.4f)\n' % \ self.factory.getFinalOrientation()) file.write(i2+'# Renderer parameters\n') alphaMode = self.renderer.getAlphaMode() aMode = "PRALPHANONE" if (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHANONE): aMode = "PRALPHANONE" elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAOUT): aMode = "PRALPHAOUT" elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAIN): aMode = "PRALPHAIN" elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAUSER): aMode = "PRALPHAUSER" file.write(i2+targ + '.renderer.setAlphaMode(BaseParticleRenderer.' + aMode + ')\n') file.write(i2+targ + '.renderer.setUserAlpha(%.2f)\n' % \ self.renderer.getUserAlpha()) if (self.rendererType == "PointParticleRenderer"): file.write(i2+'# Point parameters\n') file.write(i2+targ + '.renderer.setPointSize(%.2f)\n' % \ self.renderer.getPointSize()) sColor = self.renderer.getStartColor() file.write(i2+(targ + '.renderer.setStartColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getEndColor() file.write(i2+(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.PointParticleRenderer.PPONECOLOR): bType = "PPONECOLOR" elif (blendType == PointParticleRenderer.PointParticleRenderer.PPBLENDLIFE): bType = "PPBLENDLIFE" elif (blendType == PointParticleRenderer.PointParticleRenderer.PPBLENDVEL): bType = "PPBLENDVEL" file.write(i2+targ + '.renderer.setBlendType(PointParticleRenderer.' + bType + ')\n') blendMethod = self.renderer.getBlendMethod() bMethod = "PPNOBLEND" if (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPNOBLEND): bMethod = "PPNOBLEND" elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDLINEAR): bMethod = "PPBLENDLINEAR" elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDCUBIC): bMethod = "PPBLENDCUBIC" file.write(i2+targ + '.renderer.setBlendMethod(BaseParticleRenderer.' + bMethod + ')\n') elif (self.rendererType == "LineParticleRenderer"): file.write(i2+'# Line parameters\n') sColor = self.renderer.getHeadColor() file.write(i2+(targ + '.renderer.setHeadColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getTailColor() file.write(i2+(targ + '.renderer.setTailColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) elif (self.rendererType == "GeomParticleRenderer"): file.write(i2+'# Geom parameters\n') node = self.renderer.getGeomNode() file.write(i2+targ + '.renderer.setGeomNode(' + node.getName() + ')\n') elif (self.rendererType == "SparkleParticleRenderer"): file.write(i2+'# Sparkle parameters\n') sColor = self.renderer.getCenterColor() file.write(i2+(targ + '.renderer.setCenterColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) sColor = self.renderer.getEdgeColor() file.write(i2+(targ + '.renderer.setEdgeColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) file.write(i2+targ + '.renderer.setBirthRadius(%.4f)\n' % self.renderer.getBirthRadius()) file.write(i2+targ + '.renderer.setDeathRadius(%.4f)\n' % self.renderer.getDeathRadius()) lifeScale = self.renderer.getLifeScale() lScale = "SPNOSCALE" if (lifeScale == SparkleParticleRenderer.SparkleParticleRenderer.SPSCALE): lScale = "SPSCALE" file.write(i2+targ + '.renderer.setLifeScale(SparkleParticleRenderer.' + lScale + ')\n') elif (self.rendererType == "SpriteParticleRenderer"): file.write(i2+'# Sprite parameters\n') if (self.renderer.getSourceType() == SpriteParticleRenderer.SpriteParticleRenderer.STTexture): tex = self.renderer.getTexture() file.write(i2+targ + '.renderer.setTexture(loader.loadTexture(\'' + tex.getFilename().getFullpath() + '\'))\n') else: modelName = self.renderer.getSourceFileName() nodeName = self.renderer.getSourceNodeName() file.write(i2+targ + '.renderer.setTextureFromNode("%s", "%s")\n' % (modelName, nodeName)) sColor = self.renderer.getColor() file.write(i2+(targ + '.renderer.setColor(Vec4(%.2f, %.2f, %.2f, %.2f))\n' % (sColor[0], sColor[1], sColor[2], sColor[3]))) file.write(i2+targ + '.renderer.setXScaleFlag(%d)\n' % self.renderer.getXScaleFlag()) file.write(i2+targ + '.renderer.setYScaleFlag(%d)\n' % self.renderer.getYScaleFlag()) file.write(i2+targ + '.renderer.setAnimAngleFlag(%d)\n' % self.renderer.getAnimAngleFlag()) file.write(i2+targ + '.renderer.setInitialXScale(%.4f)\n' % self.renderer.getInitialXScale()) file.write(i2+targ + '.renderer.setFinalXScale(%.4f)\n' % self.renderer.getFinalXScale()) file.write(i2+targ + '.renderer.setInitialYScale(%.4f)\n' % self.renderer.getInitialYScale()) file.write(i2+targ + '.renderer.setFinalYScale(%.4f)\n' % self.renderer.getFinalYScale()) file.write(i2+targ + '.renderer.setNonanimatedTheta(%.4f)\n' % self.renderer.getNonanimatedTheta()) blendMethod = self.renderer.getAlphaBlendMethod() bMethod = "PPNOBLEND" if (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPNOBLEND): bMethod = "PPNOBLEND" elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDLINEAR): bMethod = "PPBLENDLINEAR" elif (blendMethod == BaseParticleRenderer.BaseParticleRenderer.PPBLENDCUBIC): bMethod = "PPBLENDCUBIC" file.write(i2+targ + '.renderer.setAlphaBlendMethod(BaseParticleRenderer.' + bMethod + ')\n') file.write(i2+targ + '.renderer.setAlphaDisable(%d)\n' % self.renderer.getAlphaDisable()) file.write(i2+'# Emitter parameters\n') emissionType = self.emitter.getEmissionType() eType = "ETEXPLICIT" if (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETEXPLICIT): eType = "ETEXPLICIT" elif (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETRADIATE): eType = "ETRADIATE" elif (emissionType == BaseParticleEmitter.BaseParticleEmitter.ETCUSTOM): eType = "ETCUSTOM" file.write(i2+targ + '.emitter.setEmissionType(BaseParticleEmitter.' + eType + ')\n') file.write(i2+targ + '.emitter.setAmplitude(%.4f)\n' % self.emitter.getAmplitude()) file.write(i2+targ + '.emitter.setAmplitudeSpread(%.4f)\n' % self.emitter.getAmplitudeSpread()) oForce = self.emitter.getOffsetForce() file.write(i2+(targ + '.emitter.setOffsetForce(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2]))) oForce = self.emitter.getExplicitLaunchVector() file.write(i2+(targ + '.emitter.setExplicitLaunchVector(Vec3(%.4f, %.4f, %.4f))\n' % (oForce[0], oForce[1], oForce[2]))) orig = self.emitter.getRadiateOrigin() file.write(i2+(targ + '.emitter.setRadiateOrigin(Point3(%.4f, %.4f, %.4f))\n' % (orig[0], orig[1], orig[2]))) if (self.emitterType == "BoxEmitter"): file.write(i2+'# Box parameters\n') bound = self.emitter.getMinBound() file.write(i2+(targ + '.emitter.setMinBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2]))) bound = self.emitter.getMaxBound() file.write(i2+(targ + '.emitter.setMaxBound(Point3(%.4f, %.4f, %.4f))\n' % (bound[0], bound[1], bound[2]))) elif (self.emitterType == "DiscEmitter"): file.write(i2+'# Disc parameters\n') file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) if (eType == "ETCUSTOM"): file.write(i2+targ + '.emitter.setOuterAngle(%.4f)\n' % self.emitter.getOuterAngle()) file.write(i2+targ + '.emitter.setInnerAngle(%.4f)\n' % self.emitter.getInnerAngle()) file.write(i2+targ + '.emitter.setOuterMagnitude(%.4f)\n' % self.emitter.getOuterMagnitude()) file.write(i2+targ + '.emitter.setInnerMagnitude(%.4f)\n' % self.emitter.getInnerMagnitude()) file.write(i2+targ + '.emitter.setCubicLerping(%d)\n' % self.emitter.getCubicLerping()) elif (self.emitterType == "LineEmitter"): file.write(i2+'# Line parameters\n') point = self.emitter.getEndpoint1() file.write(i2+(targ + '.emitter.setEndpoint1(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) point = self.emitter.getEndpoint2() file.write(i2+(targ + '.emitter.setEndpoint2(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) elif (self.emitterType == "PointEmitter"): file.write(i2+'# Point parameters\n') point = self.emitter.getLocation() file.write(i2+(targ + '.emitter.setLocation(Point3(%.4f, %.4f, %.4f))\n' % (point[0], point[1], point[2]))) elif (self.emitterType == "RectangleEmitter"): file.write(i2+'# Rectangle parameters\n') point = self.emitter.getMinBound() file.write(i2+(targ + '.emitter.setMinBound(Point2(%.4f, %.4f))\n' % (point[0], point[1]))) point = self.emitter.getMaxBound() file.write(i2+(targ + '.emitter.setMaxBound(Point2(%.4f, %.4f))\n' % (point[0], point[1]))) elif (self.emitterType == "RingEmitter"): file.write(i2+'# Ring parameters\n') file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) if (eType == "ETCUSTOM"): file.write(i2+targ + '.emitter.setAngle(%.4f)\n' % self.emitter.getAngle()) elif (self.emitterType == "SphereSurfaceEmitter"): file.write(i2+'# Sphere Surface parameters\n') file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) elif (self.emitterType == "SphereVolumeEmitter"): file.write(i2+'# Sphere Volume parameters\n') file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius()) elif (self.emitterType == "TangentRingEmitter"): file.write(i2+'# Tangent Ring parameters\n') file.write(i2+targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())