diff --git a/panda/src/chan/animChannelFixed.I b/panda/src/chan/animChannelFixed.I index 80f7da24a8..415e5c046c 100644 --- a/panda/src/chan/animChannelFixed.I +++ b/panda/src/chan/animChannelFixed.I @@ -38,23 +38,7 @@ AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed ©) : //////////////////////////////////////////////////////////////////// // Function: AnimChannelFixed::Constructor // Access: Public -// Description: This is the flavor of AnimChannelFixed that puts it -// in a hierarchy. -//////////////////////////////////////////////////////////////////// -template -INLINE AnimChannelFixed:: -AnimChannelFixed(AnimGroup *parent, const string &name, - const ValueType &value) - : AnimChannel(parent, name), - _value(value) { -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimChannelFixed::Constructor -// Access: Public -// Description: This flavor creates an AnimChannelFixed that is not -// in a hierarchy. +// Description: //////////////////////////////////////////////////////////////////// template INLINE AnimChannelFixed:: diff --git a/panda/src/chan/animChannelFixed.h b/panda/src/chan/animChannelFixed.h index 3858cf6f10..348126f410 100644 --- a/panda/src/chan/animChannelFixed.h +++ b/panda/src/chan/animChannelFixed.h @@ -42,7 +42,6 @@ protected: INLINE AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed ©); public: - INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value); INLINE AnimChannelFixed(const string &name, const ValueType &value); virtual bool has_changed(double last_frame, double this_frame); diff --git a/panda/src/chan/animChannelMatrixDynamic.cxx b/panda/src/chan/animChannelMatrixDynamic.cxx index 8c4ca823c1..2e821529da 100644 --- a/panda/src/chan/animChannelMatrixDynamic.cxx +++ b/panda/src/chan/animChannelMatrixDynamic.cxx @@ -61,8 +61,8 @@ AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic © // Description: //////////////////////////////////////////////////////////////////// AnimChannelMatrixDynamic:: -AnimChannelMatrixDynamic(AnimGroup *parent, const string &name) - : AnimChannelMatrix(parent, name) +AnimChannelMatrixDynamic(const string &name) + : AnimChannelMatrix(name) { _value = TransformState::make_identity(); _last_value = NULL; // This is impossible; thus, has_changed() will diff --git a/panda/src/chan/animChannelMatrixDynamic.h b/panda/src/chan/animChannelMatrixDynamic.h index 5a75115b27..35fbb5dac8 100644 --- a/panda/src/chan/animChannelMatrixDynamic.h +++ b/panda/src/chan/animChannelMatrixDynamic.h @@ -44,7 +44,7 @@ protected: AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic ©); public: - AnimChannelMatrixDynamic(AnimGroup *parent, const string &name); + AnimChannelMatrixDynamic(const string &name); virtual bool has_changed(double last_frame, double this_frame); virtual void get_value(int frame, LMatrix4f &mat); diff --git a/panda/src/chan/animChannelMatrixFixed.cxx b/panda/src/chan/animChannelMatrixFixed.cxx index d98fb95179..79780a8004 100644 --- a/panda/src/chan/animChannelMatrixFixed.cxx +++ b/panda/src/chan/animChannelMatrixFixed.cxx @@ -31,54 +31,44 @@ TypeHandle AnimChannelMatrixFixed::_type_handle; //////////////////////////////////////////////////////////////////// AnimChannelMatrixFixed:: AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed ©) : - AnimChannelFixed(parent, copy), - _value_no_scale_shear(copy._value_no_scale_shear), - _scale(copy._scale), - _hpr(copy._hpr), - _quat(copy._quat), - _pos(copy._pos), - _shear(copy._shear) + AnimChannel(parent, copy), + _transform(copy._transform) { } //////////////////////////////////////////////////////////////////// // Function: AnimChannelMatrixFixed::Constructor // Access: Public -// Description: This flavor creates an AnimChannelMatrixFixed that -// *is* in a hierarchy. +// Description: //////////////////////////////////////////////////////////////////// AnimChannelMatrixFixed:: -AnimChannelMatrixFixed(AnimGroup *parent, const string &name, - const LMatrix4f &value) - : AnimChannelFixed(parent, name, value) +AnimChannelMatrixFixed(const string &name, const TransformState *transform) : + AnimChannel(name), + _transform(transform) { - // Decompose the matrix into components in case we will be blending. - decompose_matrix(_value, _scale, _shear, _hpr, _pos); - compose_matrix(_value_no_scale_shear, LVecBase3f(1.0f, 1.0f, 1.0f), - _hpr, _pos); - - _quat.set_hpr(_hpr); } //////////////////////////////////////////////////////////////////// -// Function: AnimChannelMatrixFixed::Constructor -// Access: Public -// Description: This flavor creates an AnimChannelMatrixFixed that is not -// in a hierarchy. +// Function: AnimChannelFixed::has_changed +// Access: Public, Virtual +// Description: //////////////////////////////////////////////////////////////////// -AnimChannelMatrixFixed:: -AnimChannelMatrixFixed(const string &name, const LMatrix4f &value) - : AnimChannelFixed(name, value) -{ - // Decompose the matrix into components in case we will be blending. - decompose_matrix(_value, _scale, _shear, _hpr, _pos); - compose_matrix(_value_no_scale_shear, LVecBase3f(1.0f, 1.0f, 1.0f), - _hpr, _pos); - - _quat.set_hpr(_hpr); +bool AnimChannelMatrixFixed:: +has_changed(double, double) { + return false; } +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelFixed::get_value +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +get_value(int, LMatrix4f &value) { + value = _transform->get_mat(); +} + //////////////////////////////////////////////////////////////////// // Function: AnimChannelMatrixFixed::get_value_no_scale_shear // Access: Public, Virtual @@ -87,7 +77,12 @@ AnimChannelMatrixFixed(const string &name, const LMatrix4f &value) //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_value_no_scale_shear(int frame, LMatrix4f &mat) { - mat = _value_no_scale_shear; + if (_transform->has_scale() || _transform->has_shear()) { + compose_matrix(mat, LVecBase3f(1.0f, 1.0f, 1.0f), + _transform->get_hpr(), _transform->get_pos()); + } else { + mat = _transform->get_mat(); + } } //////////////////////////////////////////////////////////////////// @@ -97,7 +92,7 @@ get_value_no_scale_shear(int frame, LMatrix4f &mat) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_scale(int, LVecBase3f &scale) { - scale = _scale; + scale = _transform->get_scale(); } //////////////////////////////////////////////////////////////////// @@ -109,7 +104,7 @@ get_scale(int, LVecBase3f &scale) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_hpr(int, LVecBase3f &hpr) { - hpr = _hpr; + hpr = _transform->get_hpr(); } //////////////////////////////////////////////////////////////////// @@ -121,7 +116,7 @@ get_hpr(int, LVecBase3f &hpr) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_quat(int, LQuaternionf &quat) { - quat = _quat; + quat = _transform->get_quat(); } //////////////////////////////////////////////////////////////////// @@ -133,7 +128,7 @@ get_quat(int, LQuaternionf &quat) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_pos(int, LVecBase3f &pos) { - pos = _pos; + pos = _transform->get_pos(); } //////////////////////////////////////////////////////////////////// @@ -145,5 +140,16 @@ get_pos(int, LVecBase3f &pos) { //////////////////////////////////////////////////////////////////// void AnimChannelMatrixFixed:: get_shear(int, LVecBase3f &shear) { - shear = _shear; + shear = _transform->get_shear(); +} + +//////////////////////////////////////////////////////////////////// +// Function: AnimChannelFixed::output +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void AnimChannelMatrixFixed:: +output(ostream &out) const { + AnimChannel::output(out); + out << " = " << *_transform; } diff --git a/panda/src/chan/animChannelMatrixFixed.h b/panda/src/chan/animChannelMatrixFixed.h index 64706dcb90..c2fc1f61f2 100644 --- a/panda/src/chan/animChannelMatrixFixed.h +++ b/panda/src/chan/animChannelMatrixFixed.h @@ -21,25 +21,25 @@ #include "pandabase.h" -#include "animChannelFixed.h" +#include "animChannel.h" #include "luse.h" -EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannelFixed); +EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannel); //////////////////////////////////////////////////////////////////// // Class : AnimChannelMatrixFixed -// Description : A specialization on AnimChannelFixed to add all the +// Description : A specialization on AnimChannel to add all the // special matrix component operations. //////////////////////////////////////////////////////////////////// -class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannelFixed { +class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannel { protected: AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed ©); public: - AnimChannelMatrixFixed(AnimGroup *parent, const string &name, const LMatrix4f &value); - AnimChannelMatrixFixed(const string &name, const LMatrix4f &value); - + AnimChannelMatrixFixed(const string &name, const TransformState *transform); + virtual bool has_changed(double last_frame, double this_frame); + virtual void get_value(int frame, LMatrix4f &value); virtual void get_value_no_scale_shear(int frame, LMatrix4f &value); virtual void get_scale(int frame, LVecBase3f &scale); virtual void get_hpr(int frame, LVecBase3f &hpr); @@ -47,13 +47,10 @@ public: virtual void get_pos(int frame, LVecBase3f &pos); virtual void get_shear(int frame, LVecBase3f &shear); + virtual void output(ostream &out) const; + private: - LMatrix4f _value_no_scale_shear; - LVecBase3f _scale; - LVecBase3f _hpr; - LQuaternionf _quat; - LVecBase3f _pos; - LVecBase3f _shear; + CPT(TransformState) _transform; public: virtual TypeHandle get_type() const { @@ -64,9 +61,9 @@ public: return _type_handle; } static void init_type() { - AnimChannelFixed::init_type(); + AnimChannel::init_type(); register_type(_type_handle, "AnimChannelMatrixFixed", - AnimChannelFixed::get_class_type()); + AnimChannel::get_class_type()); } private: diff --git a/panda/src/chan/animChannelScalarDynamic.cxx b/panda/src/chan/animChannelScalarDynamic.cxx index 7c47df779d..9232a13449 100644 --- a/panda/src/chan/animChannelScalarDynamic.cxx +++ b/panda/src/chan/animChannelScalarDynamic.cxx @@ -63,8 +63,8 @@ AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic © // Description: //////////////////////////////////////////////////////////////////// AnimChannelScalarDynamic:: -AnimChannelScalarDynamic(AnimGroup *parent, const string &name) - : AnimChannelScalar(parent, name) +AnimChannelScalarDynamic(const string &name) + : AnimChannelScalar(name) { _last_value = _value = TransformState::make_identity(); _value_changed = true; diff --git a/panda/src/chan/animChannelScalarDynamic.h b/panda/src/chan/animChannelScalarDynamic.h index 28c40998ba..8c3f200e48 100644 --- a/panda/src/chan/animChannelScalarDynamic.h +++ b/panda/src/chan/animChannelScalarDynamic.h @@ -44,7 +44,7 @@ protected: AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic ©); public: - AnimChannelScalarDynamic(AnimGroup *parent, const string &name); + AnimChannelScalarDynamic(const string &name); virtual bool has_changed(double last_frame, double this_frame); virtual void get_value(int frame, float &value); diff --git a/panda/src/chan/animGroup.cxx b/panda/src/chan/animGroup.cxx index a2702235c2..8a2f6320e0 100644 --- a/panda/src/chan/animGroup.cxx +++ b/panda/src/chan/animGroup.cxx @@ -19,8 +19,6 @@ #include "animGroup.h" #include "animBundle.h" -#include "animChannelMatrixDynamic.h" -#include "animChannelScalarDynamic.h" #include "config_chan.h" #include "indent.h" @@ -145,116 +143,6 @@ find_child(const string &name) const { return (AnimGroup *)NULL; } -//////////////////////////////////////////////////////////////////// -// Function: AnimGroup::make_child_dynamic -// Access: Public -// Description: Finds the indicated child and replaces it with an -// AnimChannelMatrixDynamic or AnimChannelScalarDynamic, -// as appropriate, and returns the new channel. -// -// This may be called before binding the animation to a -// character to replace certain joints with -// dynamically-controlled ones. -// -// Returns NULL if the named child cannot be found. -//////////////////////////////////////////////////////////////////// -AnimGroup *AnimGroup:: -make_child_dynamic(const string &name) { - Children::iterator ci; - for (ci = _children.begin(); ci != _children.end(); ++ci) { - AnimGroup *child = (*ci); - if (child->get_name() == name) { - AnimGroup *new_child = NULL; - - if (child->is_of_type(AnimChannelMatrix::get_class_type())) { - AnimChannelMatrix *mchild = DCAST(AnimChannelMatrix, child); - AnimChannelMatrixDynamic *new_mchild = - new AnimChannelMatrixDynamic(this, name); - new_child = new_mchild; - - // Copy in the original value from frame 0. - LMatrix4f orig_value; - mchild->get_value(0, orig_value); - new_mchild->set_value(orig_value); - - } else if (child->is_of_type(AnimChannelScalar::get_class_type())) { - AnimChannelScalar *schild = DCAST(AnimChannelScalar, child); - AnimChannelScalarDynamic *new_schild = - new AnimChannelScalarDynamic(this, name); - new_child = new_schild; - - // Copy in the original value from frame 0. - float orig_value; - schild->get_value(0, orig_value); - new_schild->set_value(orig_value); - } - - if (new_child != (AnimGroup *)NULL) { - new_child->_children.swap(child->_children); - nassertr(_children.back() == new_child, NULL); - - // The new child was appended to the end of our children list - // by its constructor. Reposition it to replace the original - // child. - - // I would like to use these lines, but for some reason it - // crashes: - /* - { - (*ci) = new_child; - _children.pop_back(); - } - */ - - // But this longer way of achieving the same result works - // instead: - { - Children::iterator nci; - Children new_children; - for (nci = _children.begin(); nci != _children.end(); ++nci) { - if ((*nci) == child) { - new_children.push_back(new_child); - } else if ((*nci) != new_child) { - new_children.push_back(*nci); - } - } - new_children.swap(_children); - } - - return new_child; - } - } - AnimGroup *result = child->make_child_dynamic(name); - if (result != (AnimGroup *)NULL) { - return result; - } - } - - return (AnimGroup *)NULL; -} - - -//////////////////////////////////////////////////////////////////// -// Function: AnimGroup::fix_child -// Access: Public -// Description: replaces childs animation matrix with a fixed one -//////////////////////////////////////////////////////////////////// -void AnimGroup:: -fix_child(unsigned int index, const LMatrix4f &mat) { - AnimGroup *child = get_child(index); - AnimGroup *new_child = NULL; - if (child->is_of_type(AnimChannelMatrix::get_class_type())) { - AnimChannelMatrix *mchild = DCAST(AnimChannelMatrix, child); - AnimChannelMatrixFixed *new_mchild = new AnimChannelMatrixFixed(this, child->get_name(), mat); - new_child = new_mchild; - } - if(new_child != (AnimGroup*)NULL) { - new_child->_children.swap(child->_children); - nassertv(_children.back() == new_child); - _children[index] = new_child; - } -} - //////////////////////////////////////////////////////////////////// // Function: AnimGroup::get_value_type // Access: Public, Virtual diff --git a/panda/src/chan/animGroup.h b/panda/src/chan/animGroup.h index 6a1784124f..e88f88fca9 100644 --- a/panda/src/chan/animGroup.h +++ b/panda/src/chan/animGroup.h @@ -52,7 +52,6 @@ PUBLISHED: AnimGroup *get_child(int n) const; AnimGroup *find_child(const string &name) const; - AnimGroup *make_child_dynamic(const string &name); public: virtual TypeHandle get_value_type() const; @@ -81,8 +80,6 @@ public: static TypedWritable *make_AnimGroup(const FactoryParams ¶ms); - void fix_child(unsigned int index, LMatrix4f const & mat); - protected: void fillin(DatagramIterator& scan, BamReader* manager); diff --git a/panda/src/chan/movingPartBase.cxx b/panda/src/chan/movingPartBase.cxx index 1c59814110..663e1423ee 100644 --- a/panda/src/chan/movingPartBase.cxx +++ b/panda/src/chan/movingPartBase.cxx @@ -43,7 +43,36 @@ MovingPartBase(PartGroup *parent, const string &name) // Description: //////////////////////////////////////////////////////////////////// MovingPartBase:: -MovingPartBase(){ +MovingPartBase() { +} + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartBase::clear_forced_channel +// Access: Published, Virtual +// Description: Undoes the effect of a previous call to +// apply_freeze() or apply_control(). Returns true if +// the joint was modified, false otherwise. +//////////////////////////////////////////////////////////////////// +bool MovingPartBase:: +clear_forced_channel() { + if (_forced_channel != (AnimChannelBase *)NULL) { + _forced_channel.clear(); + return true; + } + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartBase::get_forced_channel +// Access: Published, Virtual +// Description: Returns the AnimChannelBase that has been forced to +// this joint by a previous call to apply_freeze() or +// apply_control(), or NULL if no such channel has been +// applied. +//////////////////////////////////////////////////////////////////// +AnimChannelBase *MovingPartBase:: +get_forced_channel() const { + return _forced_channel; } //////////////////////////////////////////////////////////////////// @@ -106,7 +135,10 @@ do_update(PartBundle *root, const CycleData *root_cdata, PartGroup *parent, // See if any of the channel values have changed since last time. - { + if (_forced_channel != (AnimChannelBase *)NULL) { + needs_update = _forced_channel->has_changed(0.0, 0.0); + + } else { const PartBundle::CData *cdata = (const PartBundle::CData *)root_cdata; PartBundle::ChannelBlend::const_iterator bci; for (bci = cdata->_blend.begin(); diff --git a/panda/src/chan/movingPartBase.h b/panda/src/chan/movingPartBase.h index bd2598f300..08e4cb42bf 100644 --- a/panda/src/chan/movingPartBase.h +++ b/panda/src/chan/movingPartBase.h @@ -51,6 +51,9 @@ public: virtual AnimChannelBase *make_initial_channel() const=0; PUBLISHED: + virtual bool clear_forced_channel(); + virtual AnimChannelBase *get_forced_channel() const; + virtual void write(ostream &out, int indent_level) const; virtual void write_with_value(ostream &out, int indent_level) const; virtual void output_value(ostream &out) const=0; @@ -76,9 +79,9 @@ protected: typedef pvector< PT(AnimChannelBase) > Channels; Channels _channels; + PT(AnimChannelBase) _forced_channel; public: - virtual TypeHandle get_type() const { return get_class_type(); } diff --git a/panda/src/chan/movingPartMatrix.cxx b/panda/src/chan/movingPartMatrix.cxx index 6046a9b7d7..8efa6827aa 100644 --- a/panda/src/chan/movingPartMatrix.cxx +++ b/panda/src/chan/movingPartMatrix.cxx @@ -18,6 +18,7 @@ #include "movingPartMatrix.h" +#include "animChannelMatrixDynamic.h" #include "animChannelMatrixFixed.h" #include "compose_matrix.h" #include "datagram.h" @@ -51,7 +52,7 @@ MovingPartMatrix:: //////////////////////////////////////////////////////////////////// AnimChannelBase *MovingPartMatrix:: make_initial_channel() const { - return new AnimChannelMatrixFixed(get_name(), _initial_value); + return new AnimChannelMatrixFixed(get_name(), TransformState::make_mat(_initial_value)); } //////////////////////////////////////////////////////////////////// @@ -63,6 +64,15 @@ make_initial_channel() const { //////////////////////////////////////////////////////////////////// void MovingPartMatrix:: get_blend_value(const PartBundle *root) { + // If a forced channel is set on this particular joint, we always + // return that value instead of performing the blend. Furthermore, + // the frame number is always 0 for the forced channel. + if (_forced_channel != (AnimChannelBase *)NULL) { + ChannelType *channel = DCAST(ChannelType, _forced_channel); + channel->get_value(0, _value); + return; + } + PartBundle::CDReader cdata(root->_cycler); if (cdata->_blend.empty()) { @@ -360,14 +370,43 @@ get_blend_value(const PartBundle *root) { } } +//////////////////////////////////////////////////////////////////// +// Function: MovingPartMatrix::apply_freeze +// Access: Public, Virtual +// Description: Freezes this particular joint so that it will always +// hold the specified transform. Returns true if this +// is a joint that can be so frozen, false otherwise. +// This is called internally by +// PartBundle::freeze_joint(). +//////////////////////////////////////////////////////////////////// +bool MovingPartMatrix:: +apply_freeze(const TransformState *transform) { + _forced_channel = new AnimChannelMatrixFixed(get_name(), transform); +} + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartMatrix::apply_control +// Access: Public, Virtual +// Description: Specifies a node to influence this particular joint +// so that it will always hold the node's transform. +// Returns true if this is a joint that can be so +// controlled, false otherwise. This is called +// internally by PartBundle::control_joint(). +//////////////////////////////////////////////////////////////////// +bool MovingPartMatrix:: +apply_control(PandaNode *node) { + AnimChannelMatrixDynamic *chan = new AnimChannelMatrixDynamic(get_name()); + chan->set_value_node(node); + _forced_channel = chan; +} + //////////////////////////////////////////////////////////////////// // Function: MovingPartMatrix::make_MovingPartMatrix // Access: Protected // Description: Factory method to generate a MovingPartMatrix object //////////////////////////////////////////////////////////////////// TypedWritable* MovingPartMatrix:: -make_MovingPartMatrix(const FactoryParams ¶ms) -{ +make_MovingPartMatrix(const FactoryParams ¶ms) { MovingPartMatrix *me = new MovingPartMatrix; DatagramIterator scan; BamReader *manager; @@ -383,7 +422,6 @@ make_MovingPartMatrix(const FactoryParams ¶ms) // Description: Factory method to generate a MovingPartMatrix object //////////////////////////////////////////////////////////////////// void MovingPartMatrix:: -register_with_read_factory() -{ +register_with_read_factory() { BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartMatrix); } diff --git a/panda/src/chan/movingPartMatrix.h b/panda/src/chan/movingPartMatrix.h index 3721a103b8..1d48792e2b 100644 --- a/panda/src/chan/movingPartMatrix.h +++ b/panda/src/chan/movingPartMatrix.h @@ -46,6 +46,9 @@ public: virtual AnimChannelBase *make_initial_channel() const; virtual void get_blend_value(const PartBundle *root); + virtual bool apply_freeze(const TransformState *transform); + virtual bool apply_control(PandaNode *node); + protected: INLINE MovingPartMatrix(); diff --git a/panda/src/chan/movingPartScalar.cxx b/panda/src/chan/movingPartScalar.cxx index 094d55c9a9..e1363179b3 100644 --- a/panda/src/chan/movingPartScalar.cxx +++ b/panda/src/chan/movingPartScalar.cxx @@ -18,6 +18,7 @@ #include "movingPartScalar.h" +#include "animChannelScalarDynamic.h" #include "datagram.h" #include "datagramIterator.h" #include "bamReader.h" @@ -48,6 +49,15 @@ MovingPartScalar:: //////////////////////////////////////////////////////////////////// void MovingPartScalar:: get_blend_value(const PartBundle *root) { + // If a forced channel is set on this particular scalar, we always + // return that value instead of performing the blend. Furthermore, + // the frame number is always 0 for the forced channel. + if (_forced_channel != (AnimChannelBase *)NULL) { + ChannelType *channel = DCAST(ChannelType, _forced_channel); + channel->get_value(0, _value); + return; + } + PartBundle::CDReader cdata(root->_cycler); if (cdata->_blend.empty()) { @@ -111,14 +121,43 @@ get_blend_value(const PartBundle *root) { } } +//////////////////////////////////////////////////////////////////// +// Function: MovingPartScalar::apply_freeze +// Access: Public, Virtual +// Description: Freezes this particular joint so that it will always +// hold the specified transform. Returns true if this +// is a joint that can be so frozen, false otherwise. +// This is called internally by +// PartBundle::freeze_joint(). +//////////////////////////////////////////////////////////////////// +bool MovingPartScalar:: +apply_freeze(const TransformState *transform) { + _forced_channel = new AnimChannelFixed(get_name(), transform->get_pos()[0]); +} + +//////////////////////////////////////////////////////////////////// +// Function: MovingPartScalar::apply_control +// Access: Public, Virtual +// Description: Specifies a node to influence this particular joint +// so that it will always hold the node's transform. +// Returns true if this is a joint that can be so +// controlled, false otherwise. This is called +// internally by PartBundle::control_joint(). +//////////////////////////////////////////////////////////////////// +bool MovingPartScalar:: +apply_control(PandaNode *node) { + AnimChannelScalarDynamic *chan = new AnimChannelScalarDynamic(get_name()); + chan->set_value_node(node); + _forced_channel = chan; +} + //////////////////////////////////////////////////////////////////// // Function: MovingPartScalar::make_MovingPartScalar // Access: Protected // Description: Factory method to generate a MovingPartScalar object //////////////////////////////////////////////////////////////////// TypedWritable* MovingPartScalar:: -make_MovingPartScalar(const FactoryParams ¶ms) -{ +make_MovingPartScalar(const FactoryParams ¶ms) { MovingPartScalar *me = new MovingPartScalar; DatagramIterator scan; BamReader *manager; @@ -134,8 +173,7 @@ make_MovingPartScalar(const FactoryParams ¶ms) // Description: Factory method to generate a MovingPartScalar object //////////////////////////////////////////////////////////////////// void MovingPartScalar:: -register_with_read_factory() -{ +register_with_read_factory() { BamReader::get_factory()->register_factory(get_class_type(), make_MovingPartScalar); } diff --git a/panda/src/chan/movingPartScalar.h b/panda/src/chan/movingPartScalar.h index 7ab42351d0..86a6192669 100644 --- a/panda/src/chan/movingPartScalar.h +++ b/panda/src/chan/movingPartScalar.h @@ -43,6 +43,9 @@ public: virtual void get_blend_value(const PartBundle *root); + virtual bool apply_freeze(const TransformState *transform); + virtual bool apply_control(PandaNode *node); + protected: INLINE MovingPartScalar(); diff --git a/panda/src/chan/partBundle.I b/panda/src/chan/partBundle.I index 29ae226eaa..6ed6b42ad4 100644 --- a/panda/src/chan/partBundle.I +++ b/panda/src/chan/partBundle.I @@ -206,39 +206,3 @@ get_control_effect(AnimControl *control) const { CDReader cdata(_cycler); return do_get_control_effect(control, cdata); } - -//////////////////////////////////////////////////////////////////// -// Function: PartBundle::get_modifies_anim_bundles -// Access: Published -// Description: getter for anim copying -//////////////////////////////////////////////////////////////////// -INLINE bool PartBundle:: -get_modifies_anim_bundles(){ - return _modifies_anim_bundles; -} - - -//////////////////////////////////////////////////////////////////// -// Function: PartBundle::set_modifies_anim_bundles -// Access: Published -// Description: setter for anim copying -//////////////////////////////////////////////////////////////////// -INLINE void PartBundle:: -set_modifies_anim_bundles(bool value){ - _modifies_anim_bundles = value; -} - - - -//////////////////////////////////////////////////////////////////// -// Function: PartGroup::freeze -// Access: Published -// Description: stores a joint freeze for later binding -//////////////////////////////////////////////////////////////////// -INLINE void PartBundle:: -freeze_joint(const string &joint_name, LMatrix4f const &transform) -{ - PT(PartGroup) pg = find_child(joint_name); - pg->freeze(transform); - _modifies_anim_bundles = true; -} diff --git a/panda/src/chan/partBundle.cxx b/panda/src/chan/partBundle.cxx index 270c45ea50..5a8c76c946 100644 --- a/panda/src/chan/partBundle.cxx +++ b/panda/src/chan/partBundle.cxx @@ -51,8 +51,7 @@ static ConfigVariableEnum anim_blend_type //////////////////////////////////////////////////////////////////// PartBundle:: PartBundle(const PartBundle ©) : - PartGroup(copy), - _modifies_anim_bundles(copy._modifies_anim_bundles) + PartGroup(copy) { CDWriter cdata(_cycler, true); CDReader cdata_from(copy._cycler); @@ -71,8 +70,7 @@ PartBundle(const PartBundle ©) : //////////////////////////////////////////////////////////////////// PartBundle:: PartBundle(const string &name) : - PartGroup(name), - _modifies_anim_bundles(false) + PartGroup(name) { } @@ -224,10 +222,6 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags, } } - if(_modifies_anim_bundles) { - ptanim = ptanim->copy_bundle(); - } - if (!check_hierarchy(anim, NULL, hierarchy_match_flags)) { return NULL; } @@ -250,6 +244,74 @@ bind_anim(AnimBundle *anim, int hierarchy_match_flags, return new AnimControl(this, anim, channel_index, bound_joints); } +//////////////////////////////////////////////////////////////////// +// Function: PartBundle::freeze_joint +// Access: Published +// Description: Specifies that the joint with the indicated name +// should be frozen with the specified transform. It +// will henceforth always hold this fixed transform, +// regardless of any animations that may subsequently be +// bound to the joint. +// +// Returns true if the joint is successfully frozen, or +// false if the named child is not a joint (or slider) +// or does not exist. +//////////////////////////////////////////////////////////////////// +bool PartBundle:: +freeze_joint(const string &joint_name, const TransformState *transform) { + PartGroup *child = find_child(joint_name); + if (child == (PartGroup *)NULL) { + return false; + } + + return child->apply_freeze(transform); +} + +//////////////////////////////////////////////////////////////////// +// Function: PartBundle::control_joint +// Access: Published +// Description: Specifies that the joint with the indicated name +// should be animated with the transform on the +// indicated node. It will henceforth always follow the +// node's transform, regardless of any animations that +// may subsequently be bound to the joint. +// +// Returns true if the joint is successfully controlled, +// or false if the named child is not a joint (or +// slider) or does not exist. +//////////////////////////////////////////////////////////////////// +bool PartBundle:: +control_joint(const string &joint_name, PandaNode *node) { + PartGroup *child = find_child(joint_name); + if (child == (PartGroup *)NULL) { + return false; + } + + return child->apply_control(node); +} + +//////////////////////////////////////////////////////////////////// +// Function: PartBundle::release_joint +// Access: Published +// Description: Releases the named joint from the effects of a +// previous call to freeze_joint() or control_joint(). +// It will henceforth once again follow whatever +// transforms are dictated by the animation. +// +// Returns true if the joint is released, or false if +// the named child was not previously controlled or +// frozen, or it does not exist. +//////////////////////////////////////////////////////////////////// +bool PartBundle:: +release_joint(const string &joint_name) { + PartGroup *child = find_child(joint_name); + if (child == (PartGroup *)NULL) { + return false; + } + + return child->clear_forced_channel(); +} + //////////////////////////////////////////////////////////////////// // Function: PartBundle::update // Access: Published @@ -498,7 +560,6 @@ void PartBundle:: write_datagram(BamWriter *manager, Datagram &dg) { PartGroup::write_datagram(manager, dg); manager->write_cdata(dg, _cycler); - dg.add_bool(_modifies_anim_bundles); } //////////////////////////////////////////////////////////////////// @@ -532,8 +593,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { if (manager->get_file_minor_ver() >= 10) { manager->read_cdata(scan, _cycler); } - if (manager->get_file_minor_ver() >= 11) { - _modifies_anim_bundles=scan.get_bool(); + if (manager->get_file_minor_ver() == 11) { + // No longer need the _modifies_anim_bundles flag + scan.get_bool(); } } diff --git a/panda/src/chan/partBundle.h b/panda/src/chan/partBundle.h index 6fe1ce949e..7fd5defd1b 100644 --- a/panda/src/chan/partBundle.h +++ b/panda/src/chan/partBundle.h @@ -36,6 +36,7 @@ class AnimBundle; class PartBundleNode; class PartBundleNode; +class TransformState; //////////////////////////////////////////////////////////////////// // Class : PartBundle @@ -120,14 +121,13 @@ PUBLISHED: int hierarchy_match_flags = 0, const PartSubset &subset = PartSubset()); - - INLINE void freeze_joint(const string &joint_name, LMatrix4f const &transform); + bool freeze_joint(const string &joint_name, const TransformState *transform); + bool control_joint(const string &joint_name, PandaNode *node); + bool release_joint(const string &joint_name); bool update(); bool force_update(); - INLINE bool get_modifies_anim_bundles(); - INLINE void set_modifies_anim_bundles(bool value); public: // The following functions aren't really part of the public // interface; they're just public so we don't have to declare a @@ -139,10 +139,6 @@ protected: virtual void remove_node(PartBundleNode *node); private: - - //this is used to determine when to copy the anim bundle - bool _modifies_anim_bundles; - class CData; void do_set_control_effect(AnimControl *control, float effect, CData *cdata); diff --git a/panda/src/chan/partGroup.I b/panda/src/chan/partGroup.I index 22b28e6a79..9d4a866bf0 100644 --- a/panda/src/chan/partGroup.I +++ b/panda/src/chan/partGroup.I @@ -27,8 +27,7 @@ INLINE PartGroup:: PartGroup(const string &name) : Namable(name), - _children(get_class_type()), - _frozen(0) + _children(get_class_type()) { } @@ -42,23 +41,8 @@ PartGroup(const string &name) : INLINE PartGroup:: PartGroup(const PartGroup ©) : Namable(copy), - _children(get_class_type()), - _frozen(copy._frozen), - _frozen_transform(copy._frozen_transform) + _children(get_class_type()) { // We don't copy children in the copy constructor. However, // copy_subgraph() will do this. } - - -//////////////////////////////////////////////////////////////////// -// Function: PartGroup::freeze -// Access: Published -// Description: stores a joint freeze for later binding -//////////////////////////////////////////////////////////////////// -INLINE void PartGroup:: -freeze(LMatrix4f const &transform) -{ - _frozen = true; - _frozen_transform=LMatrix4f(transform); -} diff --git a/panda/src/chan/partGroup.cxx b/panda/src/chan/partGroup.cxx index 2bf608ddc4..1b6c5b182f 100644 --- a/panda/src/chan/partGroup.cxx +++ b/panda/src/chan/partGroup.cxx @@ -46,7 +46,6 @@ PartGroup(PartGroup *parent, const string &name) : nassertv(parent != NULL); parent->_children.push_back(this); - _frozen = false; } //////////////////////////////////////////////////////////////////// @@ -139,6 +138,68 @@ find_child(const string &name) const { return (PartGroup *)NULL; } +//////////////////////////////////////////////////////////////////// +// Function: PartGroup::apply_freeze +// Access: Published, Virtual +// Description: Freezes this particular joint so that it will always +// hold the specified transform. Returns true if this +// is a joint that can be so frozen, false otherwise. +// +// This is normally only called internally by +// PartBundle::freeze_joint(), but you may also call it +// directly. +//////////////////////////////////////////////////////////////////// +bool PartGroup:: +apply_freeze(const TransformState *transform) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PartGroup::apply_control +// Access: Published, Virtual +// Description: Specifies a node to influence this particular joint +// so that it will always hold the node's transform. +// Returns true if this is a joint that can be so +// controlled, false otherwise. +// +// This is normally only called internally by +// PartBundle::control_joint(), but you may also call it +// directly. +//////////////////////////////////////////////////////////////////// +bool PartGroup:: +apply_control(PandaNode *node) { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PartGroup::clear_forced_channel +// Access: Published, Virtual +// Description: Undoes the effect of a previous call to +// apply_freeze() or apply_control(). Returns true if +// the joint was modified, false otherwise. +// +// This is normally only called internally by +// PartBundle::release_joint(), but you may also call it +// directly. +//////////////////////////////////////////////////////////////////// +bool PartGroup:: +clear_forced_channel() { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PartGroup::get_forced_channel +// Access: Published, Virtual +// Description: Returns the AnimChannelBase that has been forced to +// this joint by a previous call to apply_freeze() or +// apply_control(), or NULL if no such channel has been +// applied. +//////////////////////////////////////////////////////////////////// +AnimChannelBase *PartGroup:: +get_forced_channel() const { + return NULL; +} + //////////////////////////////////////////////////////////////////// // Function: PartGroup::get_value_type // Access: Public, Virtual @@ -192,9 +253,6 @@ sort_descendants() { // PartGroup::HierarchyMatchFlags values indicating // conditions that will be tolerated (but warnings will // still be issued). -// -// If there is a discrepancy, it is reported to the -// indicated output stream, if it is non-null. //////////////////////////////////////////////////////////////////// bool PartGroup:: check_hierarchy(const AnimGroup *anim, const PartGroup *, @@ -426,9 +484,6 @@ write_descendants_with_value(ostream &out, int indent_level) const { } } - - - //////////////////////////////////////////////////////////////////// // Function: PartGroup::pick_channel_index // Access: Protected, Virtual @@ -468,10 +523,6 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, while (i < part_num_children && j < anim_num_children) { PartGroup *pc = get_child(i); - if (pc->_frozen) { - anim->fix_child(j, pc->_frozen_transform); - } - AnimGroup *ac = anim->get_child(j); if (pc->get_name() < ac->get_name()) { @@ -510,15 +561,10 @@ bind_hierarchy(AnimGroup *anim, int channel_index, int &joint_index, // the particular object to a Datagram //////////////////////////////////////////////////////////////////// void PartGroup:: -write_datagram(BamWriter *manager, Datagram &me) -{ - int i; +write_datagram(BamWriter *manager, Datagram &me) { me.add_string(get_name()); - me.add_bool(_frozen); - _frozen_transform.write_datagram(me); me.add_uint16(_children.size()); - for(i = 0; i < (int)_children.size(); i++) - { + for (size_t i = 0; i < _children.size(); i++) { manager->write_pointer(me, _children[i]); } } @@ -532,46 +578,41 @@ write_datagram(BamWriter *manager, Datagram &me) // place //////////////////////////////////////////////////////////////////// void PartGroup:: -fillin(DatagramIterator& scan, BamReader* manager) -{ - int i; +fillin(DatagramIterator &scan, BamReader *manager) { set_name(scan.get_string()); - if (manager->get_file_minor_ver() >= 11) { - _frozen=scan.get_bool(); - _frozen_transform.read_datagram(scan); + + if (manager->get_file_minor_ver() == 11) { + // Skip over the old freeze-joint information, no longer stored here + scan.get_bool(); + LMatrix4f mat; + mat.read_datagram(scan); } - _num_children = scan.get_uint16(); - for(i = 0; i < _num_children; i++) - { + + int num_children = scan.get_uint16(); + _children.reserve(num_children); + for (int i = 0; i < num_children; i++) { manager->read_pointer(scan); + _children.push_back(NULL); } } //////////////////////////////////////////////////////////////////// // Function: PartGroup::complete_pointers // Access: Public -// Description: Takes in a vector of pointes to TypedWritable +// Description: Takes in a vector of pointers to TypedWritable // objects that correspond to all the requests for // pointers that this object made to BamReader. //////////////////////////////////////////////////////////////////// int PartGroup:: -complete_pointers(TypedWritable **p_list, BamReader*) -{ - int i; - for(i = 0; i < _num_children; i++) - { - if (p_list[i] == TypedWritable::Null) - { - chan_cat->warning() << get_type().get_name() - << " Ignoring null PartGroup" << endl; - } - else - { - _children.push_back(DCAST(PartGroup, p_list[i])); - } +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = TypedWritableReferenceCount::complete_pointers(p_list, manager); + + Children::iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + (*ci) = DCAST(PartGroup, p_list[pi++]); } - return _num_children; + return pi; } //////////////////////////////////////////////////////////////////// @@ -580,8 +621,7 @@ complete_pointers(TypedWritable **p_list, BamReader*) // Description: Factory method to generate a PartGroup object //////////////////////////////////////////////////////////////////// TypedWritable* PartGroup:: -make_PartGroup(const FactoryParams ¶ms) -{ +make_PartGroup(const FactoryParams ¶ms) { PartGroup *me = new PartGroup; DatagramIterator scan; BamReader *manager; @@ -597,8 +637,7 @@ make_PartGroup(const FactoryParams ¶ms) // Description: Factory method to generate a PartGroup object //////////////////////////////////////////////////////////////////// void PartGroup:: -register_with_read_factory() -{ +register_with_read_factory() { BamReader::get_factory()->register_factory(get_class_type(), make_PartGroup); } diff --git a/panda/src/chan/partGroup.h b/panda/src/chan/partGroup.h index f10198f21a..76fd0d0acc 100644 --- a/panda/src/chan/partGroup.h +++ b/panda/src/chan/partGroup.h @@ -37,6 +37,9 @@ class BamReader; class FactoryParams; class BitArray; class CycleData; +class TransformState; +class PandaNode; +class AnimChannelBase; //////////////////////////////////////////////////////////////////// // Class : PartGroup @@ -76,11 +79,14 @@ PUBLISHED: PartGroup *get_child(int n) const; PartGroup *find_child(const string &name) const; + virtual bool apply_freeze(const TransformState *transform); + virtual bool apply_control(PandaNode *node); + virtual bool clear_forced_channel(); + virtual AnimChannelBase *get_forced_channel() const; + virtual void write(ostream &out, int indent_level) const; virtual void write_with_value(ostream &out, int indent_level) const; - INLINE void freeze(LMatrix4f const &transform); - public: virtual TypeHandle get_value_type() const; @@ -118,14 +124,7 @@ public: protected: void fillin(DatagramIterator& scan, BamReader* manager); -private: - int _num_children; - - bool _frozen; - LMatrix4f _frozen_transform; - public: - virtual TypeHandle get_type() const { return get_class_type(); } @@ -141,13 +140,12 @@ public: TypedWritableReferenceCount::get_class_type()); } - private: static TypeHandle _type_handle; friend class Character; friend class CharacterJointBundle; - + friend class PartBundle; }; #include "partGroup.I" diff --git a/panda/src/char/characterJointBundle.cxx b/panda/src/char/characterJointBundle.cxx index fa6fa40b7b..711da1a008 100644 --- a/panda/src/char/characterJointBundle.cxx +++ b/panda/src/char/characterJointBundle.cxx @@ -89,6 +89,12 @@ remove_node(PartBundleNode *node) { //////////////////////////////////////////////////////////////////// void CharacterJointBundle:: r_set_character(PartGroup *group, Character *character) { + if (group == (PartGroup *)NULL) { + // This might happen if we are in the middle of reading the + // Character's hierarchy from the bam file. + return; + } + if (group->is_of_type(CharacterJoint::get_class_type())) { DCAST(CharacterJoint, group)->set_character(character); } diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index dbaac1ffdd..3a7e679f66 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -36,7 +36,7 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 5 on 5/6/05 for new Geom implementation. // Bumped to major version 6 on 2/11/06 to factor out PandaNode::CData. -static const unsigned short _bam_minor_ver = 11; +static const unsigned short _bam_minor_ver = 12; // Bumped to minor version 1 on 3/12/06 to add Texture::_compression. // Bumped to minor version 2 on 3/17/06 to add PandaNode::_draw_control_mask. // Bumped to minor version 3 on 3/21/06 to add Texture::_ram_images. @@ -48,6 +48,7 @@ static const unsigned short _bam_minor_ver = 11; // Bumped to minor version 9 on 5/15/07 to add PlaneNode::_clip_effect. // Bumped to minor version 10 on 6/19/07 to properly write PartBundles. // Bumped to minor version 11 on 6/20/07 to write frozen joints to PartGroups. +// Bumped to minor version 12 on 7/3/07 to rework control/frozen joints more. #endif