diff --git a/direct/src/particles/Particles.py b/direct/src/particles/Particles.py index d89716cb02..f36df3bbd9 100644 --- a/direct/src/particles/Particles.py +++ b/direct/src/particles/Particles.py @@ -52,13 +52,13 @@ class Particles(ParticleSystem.ParticleSystem): self.setRenderParent(self.node) self.node.addPhysical(self) - self.factory = None + self.factory = None self.factoryType = "undefined" self.setFactory("PointParticleFactory") - self.renderer = None + self.renderer = None self.rendererType = "undefined" self.setRenderer("PointParticleRenderer") - self.emitter = None + self.emitter = None self.emitterType = "undefined" self.setEmitter("SphereVolumeEmitter") @@ -106,7 +106,7 @@ class Particles(ParticleSystem.ParticleSystem): self.factory = None self.factoryType = type if (type == "PointParticleFactory"): - self.factory = PointParticleFactory.PointParticleFactory() + self.factory = PointParticleFactory.PointParticleFactory() elif (type == "ZSpinParticleFactory"): self.factory = ZSpinParticleFactory.ZSpinParticleFactory() elif (type == "OrientedParticleFactory"): @@ -263,31 +263,40 @@ class Particles(ParticleSystem.ParticleSystem): file.write('# Z Spin factory parameters\n') file.write(targ + '.factory.setInitialAngle(%.4f)\n' % \ self.factory.getInitialAngle()) - file.write(targ + '.factory.setFinalAngle(%.4f)\n' % \ - self.factory.getFinalAngle()) file.write(targ + '.factory.setInitialAngleSpread(%.4f)\n' % \ self.factory.getInitialAngleSpread()) - file.write(targ + '.factory.setFinalAngleSpread(%.4f)\n' % \ + 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()) + self.factory.getInitialOrientation()) file.write(targ + '.factory.setFinalOrientation(%.4f)\n' % \ self.factory.getFinalOrientation()) file.write('# Renderer parameters\n') alphaMode = self.renderer.getAlphaMode() - aMode = "PRALPHANONE" + aMode = "PRALPHANONE" if (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHANONE): aMode = "PRALPHANONE" - elif (alphaMode == + elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAOUT): aMode = "PRALPHAOUT" - elif (alphaMode == + elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAIN): aMode = "PRALPHAIN" - elif (alphaMode == + elif (alphaMode == BaseParticleRenderer.BaseParticleRenderer.PRALPHAUSER): aMode = "PRALPHAUSER" file.write(targ + '.renderer.setAlphaMode(BaseParticleRenderer.' + aMode + ')\n') @@ -298,9 +307,9 @@ class Particles(ParticleSystem.ParticleSystem): 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]))) + 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]))) + 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.PointParticleRenderer.PPONECOLOR): diff --git a/direct/src/tkpanels/ParticlePanel.py b/direct/src/tkpanels/ParticlePanel.py index ec4ad24f64..a52686b340 100644 --- a/direct/src/tkpanels/ParticlePanel.py +++ b/direct/src/tkpanels/ParticlePanel.py @@ -214,7 +214,7 @@ class ParticlePanel(AppShell): 0.0, None) ) self.createFloaters(systemPage, systemFloaterDefs) - + # Checkboxes self.createCheckbutton( systemPage, 'System', 'Render Space Velocities', @@ -225,7 +225,7 @@ class ParticlePanel(AppShell): systemPage, 'System', 'System Grows Older', 'On: system has a lifespan', self.toggleSystemGrowsOlder, 0) - + # Vector widgets pos = self.createVector3Entry(systemPage, 'System', 'Pos', 'Particle system position', @@ -269,7 +269,8 @@ class ParticlePanel(AppShell): ('Factory', 'Terminal Vel. Spread', 'Variation in terminal velocity', self.setFactoryTerminalVelocitySpread, - 0.0, None)) + 0.0, None), + ) self.createFloaters(factoryPage, factoryWidgets) self.factoryNotebook = Pmw.NoteBook(factoryPage, tabpos = None) @@ -277,6 +278,23 @@ class ParticlePanel(AppShell): 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 = 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, @@ -338,33 +356,33 @@ class ParticlePanel(AppShell): 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') @@ -399,7 +417,7 @@ class ParticlePanel(AppShell): 'On: magnitude/angle interpolation from center', self.toggleEmitterDiscCubicLerping, 0) customPage.pack(fill = BOTH, expand = 1) - + # Line page # linePage = self.emitterNotebook.add('LineEmitter') self.createVector3Entry(linePage, 'Line Emitter', 'Min', @@ -435,7 +453,7 @@ class ParticlePanel(AppShell): 'Particle launch angle', command = self.setEmitterRingLaunchAngle) self.ringCustomFrame.pack(fill = BOTH, expand = 1) - + # Sphere volume # sphereVolumePage = self.emitterNotebook.add('SphereVolumeEmitter') self.createFloater(sphereVolumePage, 'Sphere Volume Emitter', 'Radius', @@ -449,7 +467,7 @@ class ParticlePanel(AppShell): 'Radius of sphere', command = self.setEmitterSphereSurfaceRadius, min = 0.01) - # Tangent ring # + # Tangent ring # tangentRingPage = self.emitterNotebook.add('TangentRingEmitter') self.createFloater(tangentRingPage, 'Tangent Ring Emitter', 'Radius', 'Radius of ring', @@ -471,12 +489,12 @@ class ParticlePanel(AppShell): "alpha setting over particles' lifetime", ('NO_ALPHA','ALPHA_OUT','ALPHA_IN','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) # Line page # linePage = self.rendererNotebook.add('LineParticleRenderer') @@ -666,7 +684,7 @@ class ParticlePanel(AppShell): # 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', @@ -688,14 +706,14 @@ class ParticlePanel(AppShell): # Notebook to hold force widgets as the are added self.forceGroupNotebook = Pmw.NoteBook(self.forceFrame, tabpos = None) self.forceGroupNotebook.pack(fill = X) - + self.factoryNotebook.setnaturalsize() self.emitterNotebook.setnaturalsize() self.rendererNotebook.setnaturalsize() self.forceGroupNotebook.setnaturalsize() self.mainNotebook.setnaturalsize() - - # Make sure input variables processed + + # Make sure input variables processed self.initialiseoptions(ParticlePanel) ### WIDGET UTILITY FUNCTIONS ### @@ -712,7 +730,7 @@ class ParticlePanel(AppShell): self.widgetDict[category + '-' + text] = widget self.variableDict[category + '-' + text] = bool return widget - + def createRadiobutton(self, parent, side, category, text, balloonHelp, variable, value, command): @@ -724,7 +742,7 @@ class ParticlePanel(AppShell): self.bind(widget, balloonHelp) self.widgetDict[category + '-' + text] = widget return widget - + def createFloaters(self, parent, widgetDefinitions): widgets = [] for category, label, balloonHelp, command, min, resolution in widgetDefinitions: @@ -864,7 +882,7 @@ class ParticlePanel(AppShell): self.forceGroupLabel['text'] = self.forceGroup.getName() else: self.forceGroupLabel['text'] = 'Force Group' - + def updateMenus(self): self.updateEffectsMenus() self.updateParticlesMenus() @@ -878,7 +896,7 @@ class ParticlePanel(AppShell): # Add in a checkbutton for each effect (to toggle on/off) keys = self.effectsDict.keys() keys.sort() - for name in keys: + for name in keys: effect = self.effectsDict[name] self.effectsLabelMenu.add_command( label = effect.getName(), @@ -966,7 +984,7 @@ class ParticlePanel(AppShell): effect.enable() else: effect.disable() - + def selectParticlesNamed(self, name): particles = self.particleEffect.getParticlesNamed(name) if particles != None: @@ -997,13 +1015,13 @@ class ParticlePanel(AppShell): 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 = getParticlePath() @@ -1083,7 +1101,7 @@ class ParticlePanel(AppShell): self.particleEffect.enable() else: self.particleEffect.disable() - + ## SYSTEM PAGE ## def updateSystemWidgets(self): poolSize = self.particles.getPoolSize() @@ -1133,7 +1151,7 @@ class ParticlePanel(AppShell): def selectFactoryPage(self): pass - + def updateFactoryWidgets(self): factory = self.particles.factory lifespan = factory.getLifespanBase() @@ -1149,7 +1167,7 @@ class ParticlePanel(AppShell): 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): @@ -1172,6 +1190,10 @@ class ParticlePanel(AppShell): 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): @@ -1183,7 +1205,7 @@ class ParticlePanel(AppShell): 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()) @@ -1371,7 +1393,7 @@ class ParticlePanel(AppShell): self.rendererNotebook.selectpage(type) self.particles.setRenderer(type) self.updateRendererWidgets() - + def updateRendererWidgets(self): renderer = self.particles.renderer alphaMode = renderer.getAlphaMode() @@ -1571,8 +1593,8 @@ class ParticlePanel(AppShell): self.rendererSpriteFileEntry['state'] = 'disabled' self.rendererSpriteNodeEntry['state'] = 'disabled' self.rendererSpriteTextureEntry['background'] = 'SystemWindow' - self.rendererSpriteFileEntry['background'] = '#C0C0C0' - self.rendererSpriteNodeEntry['background'] = '#C0C0C0' + self.rendererSpriteFileEntry['background'] = '#C0C0C0' + self.rendererSpriteNodeEntry['background'] = '#C0C0C0' else: self.rendererSpriteTextureEntry['state'] = 'disabled' self.rendererSpriteFileEntry['state'] = 'normal' @@ -1599,6 +1621,11 @@ class ParticlePanel(AppShell): 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): @@ -1623,7 +1650,7 @@ class ParticlePanel(AppShell): def toggleRendererSpriteAlphaDisable(self): self.particles.renderer.setAlphaDisable( self.getVariable('Sprite Renderer', 'Alpha Disable').get()) - + ## FORCEGROUP COMMANDS ## def updateForceWidgets(self): # Select appropriate notebook page diff --git a/panda/src/particlesystem/zSpinParticle.I b/panda/src/particlesystem/zSpinParticle.I index 77c72bb46d..0fd6d9fa7d 100644 --- a/panda/src/particlesystem/zSpinParticle.I +++ b/panda/src/particlesystem/zSpinParticle.I @@ -51,3 +51,25 @@ INLINE float ZSpinParticle:: get_final_angle(void) const { return _final_angle; } + +INLINE float ZSpinParticle:: +get_angular_velocity(void) const { + return _angular_velocity; +} + +INLINE void ZSpinParticle:: +set_angular_velocity(float v) { + _angular_velocity = v; +} + +INLINE void ZSpinParticle:: +enable_angular_velocity(bool bEnabled) { + _bUseAngularVelocity = bEnabled; +} + +INLINE bool ZSpinParticle:: +get_angular_velocity_enabled(void) const { + return _bUseAngularVelocity; +} + + diff --git a/panda/src/particlesystem/zSpinParticle.cxx b/panda/src/particlesystem/zSpinParticle.cxx index b06e952c18..5af8f577ad 100644 --- a/panda/src/particlesystem/zSpinParticle.cxx +++ b/panda/src/particlesystem/zSpinParticle.cxx @@ -29,6 +29,8 @@ ZSpinParticle(void) : _initial_angle = 0.0f; _final_angle = 0.0f; _cur_angle = 0.0f; + _angular_velocity = 0.0f; + _bUseAngularVelocity = false; } //////////////////////////////////////////////////////////////////// @@ -42,6 +44,8 @@ ZSpinParticle(const ZSpinParticle ©) : _initial_angle = copy._initial_angle; _final_angle = copy._final_angle; _cur_angle = copy._cur_angle; + _angular_velocity = copy._angular_velocity; + _bUseAngularVelocity = copy._bUseAngularVelocity; } //////////////////////////////////////////////////////////////////// @@ -79,17 +83,23 @@ init(void) { //////////////////////////////////////////////////////////////////// void ZSpinParticle:: update(void) { - float t = get_parameterized_age(); + // if using final_angle, want age to range from [0,1] over lifespan, so use parameterized_age + // for angular velocity, should be allowed to range freely upward, use regular age - // interpolate the current orientation - _cur_angle = _initial_angle + (t * (_final_angle - _initial_angle)); + if(_bUseAngularVelocity) { + // interpolate the current orientation + _cur_angle = _initial_angle + (get_age() * _angular_velocity); + } else { + _cur_angle = _initial_angle + (get_parameterized_age() * (_final_angle - _initial_angle)); + } // normalize the result to [0..360) _cur_angle = fmod(_cur_angle, 360.0f); // if _cur_angle was negative, it is still negative after fmod, - // but greater than -360. // wrap it around by adding 360 + + // is this really necessary? should be in range of sin/cos if(_cur_angle < 0.0f) _cur_angle += 360.0f; } diff --git a/panda/src/particlesystem/zSpinParticle.h b/panda/src/particlesystem/zSpinParticle.h index 414c34a68b..f29c0aae8f 100644 --- a/panda/src/particlesystem/zSpinParticle.h +++ b/panda/src/particlesystem/zSpinParticle.h @@ -34,6 +34,8 @@ private: float _initial_angle; float _final_angle; float _cur_angle; + float _angular_velocity; + bool _bUseAngularVelocity; public: ZSpinParticle(void); @@ -53,6 +55,14 @@ public: INLINE void set_final_angle(float t); INLINE float get_final_angle(void) const; + + // 'set_final_angle' and 'angular_velocity' are mutually exclusive apis + // if angular-velocity is specified, final_angle is ignored + INLINE void set_angular_velocity(float v); + INLINE float get_angular_velocity(void) const; + + INLINE void enable_angular_velocity(bool bEnabled); + INLINE bool get_angular_velocity_enabled(void) const; }; #include "zSpinParticle.I" diff --git a/panda/src/particlesystem/zSpinParticleFactory.I b/panda/src/particlesystem/zSpinParticleFactory.I index ef415553ba..b3e44c9589 100644 --- a/panda/src/particlesystem/zSpinParticleFactory.I +++ b/panda/src/particlesystem/zSpinParticleFactory.I @@ -88,3 +88,39 @@ INLINE float ZSpinParticleFactory:: get_final_angle_spread(void) const { return _final_angle_spread; } + +//////////////////////////////////////////////////////////////////// +// Function : get_angular_velocity +// Access : public +//////////////////////////////////////////////////////////////////// +INLINE float ZSpinParticleFactory:: +get_angular_velocity(void) const { + return _angular_velocity; +} + +INLINE void ZSpinParticleFactory:: +set_angular_velocity(float v) { + _angular_velocity = v; +} + +INLINE float ZSpinParticleFactory:: +get_angular_velocity_spread(void) const { + return _angular_velocity_spread; +} + +INLINE void ZSpinParticleFactory:: +set_angular_velocity_spread(float spread) { + _angular_velocity_spread = spread; +} + + +INLINE void ZSpinParticleFactory:: +enable_angular_velocity(bool bEnabled) { + _bUseAngularVelocity = bEnabled; +} + +INLINE bool ZSpinParticleFactory:: +get_angular_velocity_enabled(void) const { + return _bUseAngularVelocity; +} + diff --git a/panda/src/particlesystem/zSpinParticleFactory.cxx b/panda/src/particlesystem/zSpinParticleFactory.cxx index d6de0aaa23..61f7d5988d 100644 --- a/panda/src/particlesystem/zSpinParticleFactory.cxx +++ b/panda/src/particlesystem/zSpinParticleFactory.cxx @@ -31,6 +31,9 @@ ZSpinParticleFactory(void) : _final_angle = 0.0f; _initial_angle_spread = 0.0f; _final_angle_spread = 0.0f; + _angular_velocity = 0.0f; + _angular_velocity_spread = 0.0f; + _bUseAngularVelocity = false; } //////////////////////////////////////////////////////////////////// @@ -45,6 +48,9 @@ ZSpinParticleFactory(const ZSpinParticleFactory ©) : _final_angle = copy._final_angle; _initial_angle_spread = copy._initial_angle_spread; _final_angle_spread = copy._final_angle_spread; + _angular_velocity = copy._angular_velocity; + _angular_velocity_spread = copy._angular_velocity_spread; + _bUseAngularVelocity = copy._bUseAngularVelocity; } //////////////////////////////////////////////////////////////////// @@ -77,4 +83,6 @@ populate_child_particle(BaseParticle *bp) const { zsp->set_initial_angle(_initial_angle + SPREAD(_initial_angle_spread)); zsp->set_final_angle(_final_angle + SPREAD(_final_angle_spread)); + zsp->set_angular_velocity(_angular_velocity + SPREAD(_angular_velocity_spread)); + zsp->enable_angular_velocity(_bUseAngularVelocity); } diff --git a/panda/src/particlesystem/zSpinParticleFactory.h b/panda/src/particlesystem/zSpinParticleFactory.h index 73b4cb660f..5ae43089c0 100644 --- a/panda/src/particlesystem/zSpinParticleFactory.h +++ b/panda/src/particlesystem/zSpinParticleFactory.h @@ -31,10 +31,11 @@ private: virtual void populate_child_particle(BaseParticle *bp) const; virtual BaseParticle *alloc_particle(void) const; - float _initial_angle; - float _final_angle; - float _initial_angle_spread; - float _final_angle_spread; + float _initial_angle,_initial_angle_spread; + float _final_angle,_final_angle_spread; + float _angular_velocity,_angular_velocity_spread; + bool _bUseAngularVelocity; + PUBLISHED: ZSpinParticleFactory(void); @@ -50,6 +51,15 @@ PUBLISHED: INLINE float get_final_angle(void) const; INLINE float get_initial_angle_spread(void) const; INLINE float get_final_angle_spread(void) const; + + INLINE void set_angular_velocity(float v); + INLINE float get_angular_velocity(void) const; + + INLINE void set_angular_velocity_spread(float spread); + INLINE float get_angular_velocity_spread(void) const; + + INLINE void enable_angular_velocity(bool bEnabled); + INLINE bool get_angular_velocity_enabled(void) const; }; #include "zSpinParticleFactory.I"