Procházet zdrojové kódy

new bakeInStart parameter to intervals

David Rose před 23 roky
rodič
revize
7852efabfb

+ 39 - 23
direct/src/interval/LerpInterval.py

@@ -17,7 +17,7 @@ class LerpNodePathInterval(CLerpNodePathInterval):
     # affect a property on a NodePath, like pos or hpr.
     # affect a property on a NodePath, like pos or hpr.
     lerpNodePathNum = 1
     lerpNodePathNum = 1
 
 
-    def __init__(self, name, duration, blendType, node, other):
+    def __init__(self, name, duration, blendType, bakeInStart, node, other):
         if name == None:
         if name == None:
             name = '%s-%d' % (self.__class__.__name__, self.lerpNodePathNum)
             name = '%s-%d' % (self.__class__.__name__, self.lerpNodePathNum)
             LerpNodePathInterval.lerpNodePathNum += 1
             LerpNodePathInterval.lerpNodePathNum += 1
@@ -29,7 +29,7 @@ class LerpNodePathInterval(CLerpNodePathInterval):
             other = NodePath()
             other = NodePath()
 
 
         CLerpNodePathInterval.__init__(self, name, duration, blendType,
         CLerpNodePathInterval.__init__(self, name, duration, blendType,
-                                       node, other)
+                                       bakeInStart, node, other)
 
 
     def anyCallable(self, *params):
     def anyCallable(self, *params):
         # Returns true if any of the parameters listed is a callable
         # Returns true if any of the parameters listed is a callable
@@ -55,20 +55,29 @@ class LerpNodePathInterval(CLerpNodePathInterval):
 
 
 #####################################################################
 #####################################################################
 ##
 ##
-##  It is legal to pass in a functor for the any of the pos, hpr,
-##  or scale parameters in the intervals below.  These will be
-##  evaluated at the time the interval starts in order to determine
-##  the actual final position.  However, doing so forces the entire
+##  It is legal to pass in a functor (a callable Python function that
+##  returns an appropriate value) for the any of the pos, hpr, or
+##  scale parameters in the intervals below.  These will be evaluated
+##  at the time the interval starts in order to determine the actual
+##  final (or initial) position.  However, doing so forces the entire
 ##  LerpInterval to be executed up in Python, instead of down in the
 ##  LerpInterval to be executed up in Python, instead of down in the
-##  low-level C++ code, at a significant performance cost.
+##  low-level C++ code, at some performance cost.
+##
+##  If bakeInStart is true, the starting values (if unspecified) are
+##  computed at the time the interval runs for the first time, and
+##  then stored.  If bakeInStart is false, the starting values are
+##  recomputed each frame based on the current value and the time
+##  delta since the last time the interval ran, which allows show code
+##  to manipulate the node even while it is being lerped.
 ##
 ##
 #####################################################################
 #####################################################################
 
 
 class LerpPosInterval(LerpNodePathInterval):
 class LerpPosInterval(LerpNodePathInterval):
     def __init__(self, node, duration, pos, startPos = None,
     def __init__(self, node, duration, pos, startPos = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
 
 
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(pos, startPos)
         self.paramSetup = self.anyCallable(pos, startPos)
@@ -92,9 +101,10 @@ class LerpPosInterval(LerpNodePathInterval):
 
 
 class LerpHprInterval(LerpNodePathInterval):
 class LerpHprInterval(LerpNodePathInterval):
     def __init__(self, node, duration, hpr, startHpr = None,
     def __init__(self, node, duration, hpr, startHpr = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
 
 
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(hpr, startHpr)
         self.paramSetup = self.anyCallable(hpr, startHpr)
@@ -117,9 +127,10 @@ class LerpHprInterval(LerpNodePathInterval):
 
 
 class LerpScaleInterval(LerpNodePathInterval):
 class LerpScaleInterval(LerpNodePathInterval):
     def __init__(self, node, duration, scale, startScale = None,
     def __init__(self, node, duration, scale, startScale = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(scale, startScale)
         self.paramSetup = self.anyCallable(scale, startScale)
         if self.paramSetup:
         if self.paramSetup:
@@ -142,9 +153,10 @@ class LerpScaleInterval(LerpNodePathInterval):
 class LerpPosHprInterval(LerpNodePathInterval):
 class LerpPosHprInterval(LerpNodePathInterval):
     def __init__(self, node, duration, pos, hpr,
     def __init__(self, node, duration, pos, hpr,
                  startPos = None, startHpr = None,
                  startPos = None, startHpr = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr)
         self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr)
         if self.paramSetup:
         if self.paramSetup:
@@ -174,9 +186,10 @@ class LerpPosHprInterval(LerpNodePathInterval):
 class LerpHprScaleInterval(LerpNodePathInterval):
 class LerpHprScaleInterval(LerpNodePathInterval):
     def __init__(self, node, duration, hpr, scale,
     def __init__(self, node, duration, hpr, scale,
                  startHpr = None, startScale = None,
                  startHpr = None, startScale = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
 
 
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(hpr, startHpr, scale, startScale)
         self.paramSetup = self.anyCallable(hpr, startHpr, scale, startScale)
@@ -207,9 +220,10 @@ class LerpHprScaleInterval(LerpNodePathInterval):
 class LerpPosHprScaleInterval(LerpNodePathInterval):
 class LerpPosHprScaleInterval(LerpNodePathInterval):
     def __init__(self, node, duration, pos, hpr, scale,
     def __init__(self, node, duration, pos, hpr, scale,
                  startPos = None, startHpr = None, startScale = None,
                  startPos = None, startHpr = None, startScale = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
         # Check for functors in the input parameters.
         # Check for functors in the input parameters.
         self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale)
         self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale)
         if self.paramSetup:
         if self.paramSetup:
@@ -245,18 +259,20 @@ class LerpPosHprScaleInterval(LerpNodePathInterval):
 
 
 class LerpColorScaleInterval(LerpNodePathInterval):
 class LerpColorScaleInterval(LerpNodePathInterval):
     def __init__(self, node, duration, colorScale, startColorScale = None,
     def __init__(self, node, duration, colorScale, startColorScale = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
         self.setEndColorScale(colorScale)
         self.setEndColorScale(colorScale)
         if startColorScale != None:
         if startColorScale != None:
             self.setStartColorScale(startColorScale)
             self.setStartColorScale(startColorScale)
 
 
 class LerpColorInterval(LerpNodePathInterval):
 class LerpColorInterval(LerpNodePathInterval):
     def __init__(self, node, duration, color, startColor = None,
     def __init__(self, node, duration, color, startColor = None,
-                 other = None, blendType = 'noBlend', name = None):
+                 other = None, blendType = 'noBlend',
+                 bakeInStart = 1, name = None):
         LerpNodePathInterval.__init__(self, name, duration, blendType,
         LerpNodePathInterval.__init__(self, name, duration, blendType,
-                                      node, other)
+                                      bakeInStart, node, other)
         self.setEndColor(color)
         self.setEndColor(color)
         if startColor != None:
         if startColor != None:
             self.setStartColor(startColor)
             self.setStartColor(startColor)

+ 31 - 0
direct/src/interval/cLerpNodePathInterval.cxx

@@ -41,16 +41,33 @@ TypeHandle CLerpNodePathInterval::_type_handle;
 //               set_start_pos(), etc.; otherwise, the starting value
 //               set_start_pos(), etc.; otherwise, the starting value
 //               is taken from the actual node's value at the time the
 //               is taken from the actual node's value at the time the
 //               lerp is performed.
 //               lerp is performed.
+//
+//               The starting values may be explicitly specified or
+//               omitted.  The value of bake_in_start determines the
+//               behavior if the starting values are omitted.  If
+//               bake_in_start is true, the values are obtained the
+//               first time the lerp runs, and thenceforth are stored
+//               within the interval.  If bake_in_start is false, the
+//               starting value is computed each frame, based on
+//               assuming the current value represents the value set
+//               from the last time the interval was run.  This
+//               "smart" behavior allows code to manipulate the object
+//               event while it is being lerped, and the lerp
+//               continues to apply in a sensible way.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 CLerpNodePathInterval::
 CLerpNodePathInterval::
 CLerpNodePathInterval(const string &name, double duration, 
 CLerpNodePathInterval(const string &name, double duration, 
                       CLerpInterval::BlendType blend_type,
                       CLerpInterval::BlendType blend_type,
+                      bool bake_in_start,
                       const NodePath &node, const NodePath &other) :
                       const NodePath &node, const NodePath &other) :
   CLerpInterval(name, duration, blend_type),
   CLerpInterval(name, duration, blend_type),
   _node(node),
   _node(node),
   _other(other),
   _other(other),
   _flags(0)
   _flags(0)
 {
 {
+  if (bake_in_start) {
+    _flags |= F_bake_in_start;
+  }
   _prev_d = 0.0;
   _prev_d = 0.0;
 }
 }
 
 
@@ -123,7 +140,13 @@ priv_step(double t) {
       if ((_flags & F_start_pos) != 0) {
       if ((_flags & F_start_pos) != 0) {
         lerp_value(pos, d, _start_pos, _end_pos);
         lerp_value(pos, d, _start_pos, _end_pos);
 
 
+      } else if ((_flags & F_bake_in_start) != 0) {
+        // Get the current starting pos, and bake it in.
+        set_start_pos(transform->get_pos());
+        lerp_value(pos, d, _start_pos, _end_pos);
+
       } else {
       } else {
+        // "smart" lerp from the current pos to the new pos.
         pos = transform->get_pos();
         pos = transform->get_pos();
         lerp_value_from_prev(pos, d, _prev_d, pos, _end_pos);
         lerp_value_from_prev(pos, d, _prev_d, pos, _end_pos);
       }
       }
@@ -132,6 +155,10 @@ priv_step(double t) {
       if ((_flags & F_start_hpr) != 0) {
       if ((_flags & F_start_hpr) != 0) {
         lerp_value(hpr, d, _start_hpr, _end_hpr);
         lerp_value(hpr, d, _start_hpr, _end_hpr);
 
 
+      } else if ((_flags & F_bake_in_start) != 0) {
+        set_start_hpr(transform->get_hpr());
+        lerp_value(hpr, d, _start_hpr, _end_hpr);
+
       } else {
       } else {
         hpr = transform->get_hpr();
         hpr = transform->get_hpr();
         lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr);
         lerp_value_from_prev(hpr, d, _prev_d, hpr, _end_hpr);
@@ -141,6 +168,10 @@ priv_step(double t) {
       if ((_flags & F_start_scale) != 0) {
       if ((_flags & F_start_scale) != 0) {
         lerp_value(scale, d, _start_scale, _end_scale);
         lerp_value(scale, d, _start_scale, _end_scale);
 
 
+      } else if ((_flags & F_bake_in_start) != 0) {
+        set_start_scale(transform->get_scale());
+        lerp_value(scale, d, _start_scale, _end_scale);
+
       } else {
       } else {
         scale = transform->get_scale();
         scale = transform->get_scale();
         lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale);
         lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale);

+ 4 - 2
direct/src/interval/cLerpNodePathInterval.h

@@ -31,7 +31,7 @@
 class EXPCL_DIRECT CLerpNodePathInterval : public CLerpInterval {
 class EXPCL_DIRECT CLerpNodePathInterval : public CLerpInterval {
 PUBLISHED:
 PUBLISHED:
   CLerpNodePathInterval(const string &name, double duration, 
   CLerpNodePathInterval(const string &name, double duration, 
-                        BlendType blend_type,
+                        BlendType blend_type, bool bake_in_start,
                         const NodePath &node, const NodePath &other);
                         const NodePath &node, const NodePath &other);
 
 
   INLINE const NodePath &get_node() const;
   INLINE const NodePath &get_node() const;
@@ -74,9 +74,11 @@ private:
     F_start_scale        = 0x0400,
     F_start_scale        = 0x0400,
     F_start_color        = 0x0800,
     F_start_color        = 0x0800,
     F_start_color_scale  = 0x1000,
     F_start_color_scale  = 0x1000,
+
+    F_bake_in_start      = 0x8000,
   };
   };
   
   
-  int _flags;
+  unsigned int _flags;
   LPoint3f _start_pos, _end_pos;
   LPoint3f _start_pos, _end_pos;
   LVecBase3f _start_hpr, _end_hpr;
   LVecBase3f _start_hpr, _end_hpr;
   LVecBase3f _start_scale, _end_scale;
   LVecBase3f _start_scale, _end_scale;