diff --git a/direct/src/interval/LerpInterval.py b/direct/src/interval/LerpInterval.py index 7697751800..e654e5a0aa 100644 --- a/direct/src/interval/LerpInterval.py +++ b/direct/src/interval/LerpInterval.py @@ -17,7 +17,7 @@ class LerpNodePathInterval(CLerpNodePathInterval): # affect a property on a NodePath, like pos or hpr. lerpNodePathNum = 1 - def __init__(self, name, duration, blendType, node, other): + def __init__(self, name, duration, blendType, bakeInStart, node, other): if name == None: name = '%s-%d' % (self.__class__.__name__, self.lerpNodePathNum) LerpNodePathInterval.lerpNodePathNum += 1 @@ -29,7 +29,7 @@ class LerpNodePathInterval(CLerpNodePathInterval): other = NodePath() CLerpNodePathInterval.__init__(self, name, duration, blendType, - node, other) + bakeInStart, node, other) def anyCallable(self, *params): # 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 -## 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): 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, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(pos, startPos) @@ -92,9 +101,10 @@ class LerpPosInterval(LerpNodePathInterval): class LerpHprInterval(LerpNodePathInterval): 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, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(hpr, startHpr) @@ -117,9 +127,10 @@ class LerpHprInterval(LerpNodePathInterval): class LerpScaleInterval(LerpNodePathInterval): 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, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(scale, startScale) if self.paramSetup: @@ -142,9 +153,10 @@ class LerpScaleInterval(LerpNodePathInterval): class LerpPosHprInterval(LerpNodePathInterval): def __init__(self, node, duration, pos, hpr, startPos = None, startHpr = None, - other = None, blendType = 'noBlend', name = None): + other = None, blendType = 'noBlend', + bakeInStart = 1, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr) if self.paramSetup: @@ -174,9 +186,10 @@ class LerpPosHprInterval(LerpNodePathInterval): class LerpHprScaleInterval(LerpNodePathInterval): def __init__(self, node, duration, hpr, scale, startHpr = None, startScale = None, - other = None, blendType = 'noBlend', name = None): + other = None, blendType = 'noBlend', + bakeInStart = 1, name = None): LerpNodePathInterval.__init__(self, name, duration, blendType, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(hpr, startHpr, scale, startScale) @@ -207,9 +220,10 @@ class LerpHprScaleInterval(LerpNodePathInterval): class LerpPosHprScaleInterval(LerpNodePathInterval): def __init__(self, node, duration, pos, hpr, scale, 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, - node, other) + bakeInStart, node, other) # Check for functors in the input parameters. self.paramSetup = self.anyCallable(pos, startPos, hpr, startHpr, scale, startScale) if self.paramSetup: @@ -245,18 +259,20 @@ class LerpPosHprScaleInterval(LerpNodePathInterval): class LerpColorScaleInterval(LerpNodePathInterval): 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, - node, other) + bakeInStart, node, other) self.setEndColorScale(colorScale) if startColorScale != None: self.setStartColorScale(startColorScale) class LerpColorInterval(LerpNodePathInterval): 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, - node, other) + bakeInStart, node, other) self.setEndColor(color) if startColor != None: self.setStartColor(startColor) diff --git a/direct/src/interval/cLerpNodePathInterval.cxx b/direct/src/interval/cLerpNodePathInterval.cxx index 2b64525eb1..66d224bf88 100644 --- a/direct/src/interval/cLerpNodePathInterval.cxx +++ b/direct/src/interval/cLerpNodePathInterval.cxx @@ -41,16 +41,33 @@ TypeHandle CLerpNodePathInterval::_type_handle; // set_start_pos(), etc.; otherwise, the starting value // is taken from the actual node's value at the time the // 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(const string &name, double duration, CLerpInterval::BlendType blend_type, + bool bake_in_start, const NodePath &node, const NodePath &other) : CLerpInterval(name, duration, blend_type), _node(node), _other(other), _flags(0) { + if (bake_in_start) { + _flags |= F_bake_in_start; + } _prev_d = 0.0; } @@ -123,7 +140,13 @@ priv_step(double t) { if ((_flags & F_start_pos) != 0) { 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 { + // "smart" lerp from the current pos to the new pos. pos = transform->get_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) { 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 { hpr = transform->get_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) { 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 { scale = transform->get_scale(); lerp_value_from_prev(scale, d, _prev_d, scale, _end_scale); diff --git a/direct/src/interval/cLerpNodePathInterval.h b/direct/src/interval/cLerpNodePathInterval.h index 5e8d90d0b0..5cc47e3a75 100644 --- a/direct/src/interval/cLerpNodePathInterval.h +++ b/direct/src/interval/cLerpNodePathInterval.h @@ -31,7 +31,7 @@ class EXPCL_DIRECT CLerpNodePathInterval : public CLerpInterval { PUBLISHED: CLerpNodePathInterval(const string &name, double duration, - BlendType blend_type, + BlendType blend_type, bool bake_in_start, const NodePath &node, const NodePath &other); INLINE const NodePath &get_node() const; @@ -74,9 +74,11 @@ private: F_start_scale = 0x0400, F_start_color = 0x0800, F_start_color_scale = 0x1000, + + F_bake_in_start = 0x8000, }; - int _flags; + unsigned int _flags; LPoint3f _start_pos, _end_pos; LVecBase3f _start_hpr, _end_hpr; LVecBase3f _start_scale, _end_scale;