Browse Source

MAJOR OVERHAUL: The particle interval now behaves like a normal interval. The particle system is removed from the global particle and physics managers and its stepping is controlled by the interval itself.

Josh Wilson 19 years ago
parent
commit
f75b83c440
1 changed files with 92 additions and 38 deletions
  1. 92 38
      direct/src/interval/ParticleInterval.py

+ 92 - 38
direct/src/interval/ParticleInterval.py

@@ -9,21 +9,52 @@ from Interval import Interval
 from direct.particles import ParticleEffect
 
 class ParticleInterval(Interval):
+    """
+    Use this interval when you want to have greater control over a
+    ParticleEffect.  The interval does not register the effect with
+    the global particle and physics managers, but it does call upon
+    them to perform its stepping.  You should NOT call
+    particleEffect.start() with an effect that is being controlled
+    by a ParticleInterval.
+    """
     # Name counter
     particleNum = 1
     # create ParticleInterval DirectNotify category
     notify = directNotify.newCategory('ParticleInterval')
     # Class methods
-    def __init__(self, particleEffect, parent, worldRelative=1, loop=0, 
-            duration=0.0, name=None):
+    def __init__(self,
+                 particleEffect,
+                 parent,
+                 worldRelative = 1,
+                 renderParent = None,
+                 duration = 0.0,
+                 softStopT = 0.0,
+                 cleanup = False,
+                 name = None):
         """
-        particleEffect is ??
-        parent is ??
-        worldRelative is a boolean
-        loop is a boolean
-        duration is a float for the time
-        name is ??
+        particleEffect is a ParticleEffect
+        parent is a NodePath: this is where the effect will be
+                              parented in the scenegraph
+        worldRelative is a boolean: this will override 'renderParent'
+                                    with render
+        renderParent is a NodePath: this is where the particles will
+                                    be rendered in the scenegraph
+                                    duration is a float for the time
+        softStopT is a float: no effect if 0.0,
+                              a positive value will count from the
+                              start of the interval,
+                              a negative value will count from the
+                              end of the interval
+                              
+        cleanup is a boolean: if True the effect will be destroyed
+                              and removed from the scenegraph upon
+                              interval completion
+                              set to False if planning on reusing
+                              the interval
+        name is a string: use this for unique intervals so that
+                          they can be easily found in the taskMgr
         """
+        
         # Generate unique name
         id = 'Particle-%d' % ParticleInterval.particleNum
         ParticleInterval.particleNum += 1
@@ -31,49 +62,72 @@ class ParticleInterval(Interval):
             name = id
         # Record instance variables
         self.particleEffect = particleEffect 
-        self.parent = parent
-        self.worldRelative = worldRelative
-        self.fLoop = loop
-        assert duration > 0.0 or loop == 1
+        self.cleanup = cleanup
+        
+        if parent != None:
+            self.particleEffect.reparentTo(parent)
+        if worldRelative:
+            renderParent = render
+        if renderParent:
+            for particles in self.particleEffect.getParticlesList():
+                particles.setRenderParent(renderParent.node())
+
+        if softStopT == 0.0:
+            self.softStopT = duration
+        elif softStopT < 0.0:
+            self.softStopT = duration+softStopT
+        else:
+            self.softStopT = softStopT
+            
         # Initialize superclass
         Interval.__init__(self, name, duration)
 
-    def __del__(self):
+    def __step(self,dt):
         if self.particleEffect:
-            self.particleEffect.cleanup()
-            self.particleEffect = None
+            self.particleEffect.accelerate(dt,1,0.05)
+
+    def __softStart(self):
+        if self.particleEffect:
+            self.particleEffect.softStart()
+        self.__softStopped = False
+
+    def __softStop(self):
+        if self.particleEffect:
+            self.particleEffect.softStop()
+        self.__softStopped = True
+
 
     def privInitialize(self, t):
-        renderParent = None
-        if self.worldRelative:
-            renderParent = render
+        if self.state != CInterval.SPaused:
+            # Restarting from a hard stop or just interrupting the
+            # current play
+            self.__softStart()
+            if self.particleEffect:
+                self.particleEffect.clearToInitial()
+            self.currT = 0
+
         if self.particleEffect:
-            self.particleEffect.start(self.parent, renderParent)
-        self.state = CInterval.SStarted
-        self.currT = t
+            for forceGroup in self.particleEffect.getForceGroupList():
+                forceGroup.enable()
+
+        Interval.privInitialize(self,t)
 
     def privStep(self, t):
-        if self.state == CInterval.SPaused:
+        if self.state == CInterval.SPaused or t < self.currT:
             # Restarting from a pause.
             self.privInitialize(t)
         else:
-            self.state = CInterval.SStarted
-            self.currT = t
+            if not self.__softStopped and t > self.softStopT:
+                self.__step(self.softStopT-self.currT)
+                self.__softStop()
+                self.__step(t-self.softStopT)
+            else:
+                self.__step(t-self.currT)
+            Interval.privStep(self,t)
 
     def privFinalize(self):
-        if self.particleEffect:
+        Interval.privFinalize(self)
+        if self.cleanup and self.particleEffect:
             self.particleEffect.cleanup()
             self.particleEffect = None
-        self.currT = self.getDuration()
-        self.state = CInterval.SFinal
-
-    def privInstant(self):
-        if self.particleEffect:
-            self.particleEffect.cleanup()
-            self.particleEffect = None
-        self.currT = self.getDuration()
-        self.state = CInterval.SFinal
-
-    def privInterrupt(self):
-        self.particleEffect.disable()
-        self.state = CInterval.SPaused
+