Browse Source

implement copy_bundle()

David Rose 19 years ago
parent
commit
f7265d310a

+ 51 - 9
panda/src/chan/animBundle.cxx

@@ -27,6 +27,39 @@
 
 
 TypeHandle AnimBundle::_type_handle;
 TypeHandle AnimBundle::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimBundle::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimBundle, just like this one, without
+//               copying any children.  The new copy is added to the
+//               indicated parent.  Intended to be called by
+//               make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimBundle::
+AnimBundle(AnimGroup *parent, const AnimBundle &copy) : 
+  AnimGroup(parent, copy),
+  _fps(copy._fps),
+  _num_frames(copy._num_frames)
+{
+  nassertv(_root == (AnimBundle *)NULL);
+  _root = this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimBundle::copy_bundle
+//       Access: Published
+//  Description: Returns a full copy of the bundle and its entire tree
+//               of nested AnimGroups.  However, the actual data
+//               stored in the leaves--that is, animation tables, such
+//               as those stored in an AnimChannelMatrixXfmTable--will
+//               be shared.
+////////////////////////////////////////////////////////////////////
+PT(AnimBundle) AnimBundle::
+copy_bundle() const {
+  PT(AnimGroup) group = copy_subtree((AnimGroup *)NULL);
+  return DCAST(AnimBundle, group.p());
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimBundle::output
 //     Function: AnimBundle::output
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -38,6 +71,19 @@ output(ostream &out) const {
       << " frames at " << get_base_frame_rate() << " fps";
       << " frames at " << get_base_frame_rate() << " fps";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimBundle::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimBundle::
+make_copy(AnimGroup *parent) const {
+  return new AnimBundle(parent, *this);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimBundle::write_datagram
 //     Function: AnimBundle::write_datagram
 //       Access: Public
 //       Access: Public
@@ -45,8 +91,7 @@ output(ostream &out) const {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimBundle::
 void AnimBundle::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   AnimGroup::write_datagram(manager, me);
   AnimGroup::write_datagram(manager, me);
   me.add_float32(_fps);
   me.add_float32(_fps);
   me.add_uint16(_num_frames);
   me.add_uint16(_num_frames);
@@ -61,8 +106,7 @@ write_datagram(BamWriter *manager, Datagram &me)
 //               place
 //               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimBundle::
 void AnimBundle::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
+fillin(DatagramIterator &scan, BamReader *manager) {
   AnimGroup::fillin(scan, manager);
   AnimGroup::fillin(scan, manager);
   _fps = scan.get_float32();
   _fps = scan.get_float32();
   _num_frames = scan.get_uint16();
   _num_frames = scan.get_uint16();
@@ -73,9 +117,8 @@ fillin(DatagramIterator& scan, BamReader* manager)
 //       Access: Protected
 //       Access: Protected
 //  Description: Factory method to generate a AnimBundle object
 //  Description: Factory method to generate a AnimBundle object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-TypedWritable* AnimBundle::
-make_AnimBundle(const FactoryParams &params)
-{
+TypedWritable *AnimBundle::
+make_AnimBundle(const FactoryParams &params) {
   AnimBundle *me = new AnimBundle;
   AnimBundle *me = new AnimBundle;
   DatagramIterator scan;
   DatagramIterator scan;
   BamReader *manager;
   BamReader *manager;
@@ -91,8 +134,7 @@ make_AnimBundle(const FactoryParams &params)
 //  Description: Factory method to generate a AnimBundle object
 //  Description: Factory method to generate a AnimBundle object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimBundle::
 void AnimBundle::
-register_with_read_factory()
-{
+register_with_read_factory() {
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimBundle);
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimBundle);
 }
 }
 
 

+ 8 - 0
panda/src/chan/animBundle.h

@@ -33,9 +33,14 @@ class FactoryParams;
 //               channels in the hierarchy (which must all match).
 //               channels in the hierarchy (which must all match).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimBundle : public AnimGroup {
 class EXPCL_PANDA AnimBundle : public AnimGroup {
+protected:
+  AnimBundle(AnimGroup *parent, const AnimBundle &copy);
+
 PUBLISHED:
 PUBLISHED:
   INLINE AnimBundle(const string &name, float fps, int num_frames);
   INLINE AnimBundle(const string &name, float fps, int num_frames);
 
 
+  PT(AnimBundle) copy_bundle() const;
+
   INLINE double get_base_frame_rate() const;
   INLINE double get_base_frame_rate() const;
   INLINE int get_num_frames() const;
   INLINE int get_num_frames() const;
 
 
@@ -44,6 +49,9 @@ PUBLISHED:
 protected:
 protected:
   INLINE AnimBundle();
   INLINE AnimBundle();
 
 
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+
+private:
   float _fps;
   float _fps;
   int _num_frames;
   int _num_frames;
 
 

+ 15 - 0
panda/src/chan/animChannel.I

@@ -38,6 +38,21 @@ AnimChannel(const string &name)
   : AnimChannelBase(name) {
   : AnimChannelBase(name) {
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannel::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannel, just like this one,
+//               without copying any children.  The new copy is added
+//               to the indicated parent.  Intended to be called by
+//               make_copy() only.
+////////////////////////////////////////////////////////////////////
+template<class SwitchType>
+INLINE AnimChannel<SwitchType>::
+AnimChannel(AnimGroup *parent, const AnimChannel &copy) : 
+  AnimChannelBase(parent, copy)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannel::Constructor
 //     Function: AnimChannel::Constructor
 //       Access: Public
 //       Access: Public

+ 1 - 0
panda/src/chan/animChannel.h

@@ -38,6 +38,7 @@ protected:
   // you must first create an AnimBundle, and use that to create any
   // you must first create an AnimBundle, and use that to create any
   // subsequent children.
   // subsequent children.
   INLINE AnimChannel(const string &name = "");
   INLINE AnimChannel(const string &name = "");
+  INLINE AnimChannel(AnimGroup *parent, const AnimChannel &copy);
 public:
 public:
   typedef TYPENAME SwitchType::ValueType ValueType;
   typedef TYPENAME SwitchType::ValueType ValueType;
 
 

+ 15 - 0
panda/src/chan/animChannelBase.I

@@ -31,6 +31,21 @@ AnimChannelBase(const string &name)
   _last_frame = -1;
   _last_frame = -1;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelBase::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelBase, just like this one,
+//               without copying any children.  The new copy is added
+//               to the indicated parent.  Intended to be called by
+//               make_copy() only.
+////////////////////////////////////////////////////////////////////
+INLINE AnimChannelBase::
+AnimChannelBase(AnimGroup *parent, const AnimChannelBase &copy) : 
+  AnimGroup(parent, copy),
+  _last_frame(copy._last_frame)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelBase::Constructor
 //     Function: AnimChannelBase::Constructor
 //       Access: Public
 //       Access: Public

+ 2 - 4
panda/src/chan/animChannelBase.cxx

@@ -46,8 +46,7 @@ has_changed(double, double) {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelBase::
 void AnimChannelBase::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   AnimGroup::write_datagram(manager, me);
   AnimGroup::write_datagram(manager, me);
   me.add_uint16(_last_frame);
   me.add_uint16(_last_frame);
 }
 }
@@ -61,8 +60,7 @@ write_datagram(BamWriter *manager, Datagram &me)
 //               place
 //               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimChannelBase::
 void AnimChannelBase::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
+fillin(DatagramIterator &scan, BamReader *manager) {
   AnimGroup::fillin(scan, manager);
   AnimGroup::fillin(scan, manager);
   _last_frame = scan.get_uint16();
   _last_frame = scan.get_uint16();
 }
 }

+ 1 - 0
panda/src/chan/animChannelBase.h

@@ -41,6 +41,7 @@ protected:
   // you must first create an AnimBundle, and use that to create any
   // you must first create an AnimBundle, and use that to create any
   // subsequent children.
   // subsequent children.
   INLINE AnimChannelBase(const string &name = "");
   INLINE AnimChannelBase(const string &name = "");
+  INLINE AnimChannelBase(AnimGroup *parent, const AnimChannelBase &copy);
 
 
 public:
 public:
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);
   INLINE AnimChannelBase(AnimGroup *parent, const string &name);

+ 16 - 0
panda/src/chan/animChannelFixed.I

@@ -19,6 +19,22 @@
 template<class SwitchType>
 template<class SwitchType>
 TypeHandle AnimChannelFixed<SwitchType>::_type_handle;
 TypeHandle AnimChannelFixed<SwitchType>::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelFixed::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelFixed, just like this one,
+//               without copying any children.  The new copy is added
+//               to the indicated parent.  Intended to be called by
+//               make_copy() only.
+////////////////////////////////////////////////////////////////////
+template<class SwitchType>
+INLINE AnimChannelFixed<SwitchType>::
+AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed<SwitchType> &copy) : 
+  AnimChannel<SwitchType>(parent, copy),
+  _value(copy._value)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelFixed::Constructor
 //     Function: AnimChannelFixed::Constructor
 //       Access: Public
 //       Access: Public

+ 4 - 0
panda/src/chan/animChannelFixed.h

@@ -38,6 +38,10 @@ class AnimChannelFixed : public AnimChannel<SwitchType> {
 public:
 public:
   typedef TYPENAME AnimChannel<SwitchType>::ValueType ValueType;
   typedef TYPENAME AnimChannel<SwitchType>::ValueType ValueType;
 
 
+protected:
+  INLINE AnimChannelFixed(AnimGroup *parent, const AnimChannelFixed<SwitchType> &copy);
+
+public:
   INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value);
   INLINE AnimChannelFixed(AnimGroup *parent, const string &name, const ValueType &value);
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
   INLINE AnimChannelFixed(const string &name, const ValueType &value);
 
 

+ 39 - 9
panda/src/chan/animChannelMatrixDynamic.cxx

@@ -29,6 +29,32 @@
 
 
 TypeHandle AnimChannelMatrixDynamic::_type_handle;
 TypeHandle AnimChannelMatrixDynamic::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixDynamic::Constructor
+//       Access: Protected
+//  Description: For use only with the bam reader.
+/////////////////////////////////////////////////////////////
+AnimChannelMatrixDynamic::
+AnimChannelMatrixDynamic() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixDynamic::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelMatrixDynamic, just like
+//               this one, without copying any children.  The new copy
+//               is added to the indicated parent.  Intended to be
+//               called by make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimChannelMatrixDynamic::
+AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic &copy) : 
+  AnimChannelMatrix(parent, copy),
+  _value_node(copy._value_node),
+  _value(copy._value),
+  _last_value(NULL)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixDynamic::Constructor
 //     Function: AnimChannelMatrixDynamic::Constructor
 //       Access: Public
 //       Access: Public
@@ -43,15 +69,6 @@ AnimChannelMatrixDynamic(AnimGroup *parent, const string &name)
                        // always return true the first time.
                        // always return true the first time.
 }
 }
 
 
-////////////////////////////////////////////////////////////////////
-//     Function: AnimChannelMatrixDynamic::Constructor
-//       Access: Protected
-//  Description: For use only with the bam reader.
-/////////////////////////////////////////////////////////////
-AnimChannelMatrixDynamic::
-AnimChannelMatrixDynamic() {
-}
-
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixDynamic::has_changed
 //     Function: AnimChannelMatrixDynamic::has_changed
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -213,6 +230,19 @@ set_value_node(PandaNode *value_node) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixDynamic::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimChannelMatrixDynamic::
+make_copy(AnimGroup *parent) const {
+  return new AnimChannelMatrixDynamic(parent, *this);
+}
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixDynamic::write_datagram
 //     Function: AnimChannelMatrixDynamic::write_datagram

+ 7 - 3
panda/src/chan/animChannelMatrixDynamic.h

@@ -39,13 +39,13 @@
 //               each frame.
 //               each frame.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimChannelMatrixDynamic : public AnimChannelMatrix {
 class EXPCL_PANDA AnimChannelMatrixDynamic : public AnimChannelMatrix {
-public:
-  AnimChannelMatrixDynamic(AnimGroup *parent, const string &name);
-
 protected:
 protected:
   AnimChannelMatrixDynamic();
   AnimChannelMatrixDynamic();
+  AnimChannelMatrixDynamic(AnimGroup *parent, const AnimChannelMatrixDynamic &copy);
 
 
 public:
 public:
+  AnimChannelMatrixDynamic(AnimGroup *parent, const string &name);
+
   virtual bool has_changed(double last_frame, double this_frame);
   virtual bool has_changed(double last_frame, double this_frame);
   virtual void get_value(int frame, LMatrix4f &mat);
   virtual void get_value(int frame, LMatrix4f &mat);
 
 
@@ -64,6 +64,10 @@ PUBLISHED:
   INLINE const TransformState *get_value_transform() const;
   INLINE const TransformState *get_value_transform() const;
   INLINE PandaNode *get_value_node() const;
   INLINE PandaNode *get_value_node() const;
 
 
+protected:
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+
+
 private:
 private:
   // This is filled in only if we are using the set_value_node()
   // This is filled in only if we are using the set_value_node()
   // interface to get an implicit value from the transform on the
   // interface to get an implicit value from the transform on the

+ 20 - 0
panda/src/chan/animChannelMatrixFixed.cxx

@@ -21,6 +21,26 @@
 
 
 TypeHandle AnimChannelMatrixFixed::_type_handle;
 TypeHandle AnimChannelMatrixFixed::_type_handle;
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixFixed::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelMatrixFixed, just like this
+//               one, without copying any children.  The new copy is
+//               added to the indicated parent.  Intended to be called
+//               by make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimChannelMatrixFixed::
+AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed &copy) : 
+  AnimChannelFixed<ACMatrixSwitchType>(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)
+{
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixFixed::Constructor
 //     Function: AnimChannelMatrixFixed::Constructor
 //       Access: Public
 //       Access: Public

+ 3 - 0
panda/src/chan/animChannelMatrixFixed.h

@@ -32,6 +32,9 @@ EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, AnimChannelFixed<ACMatrixSwitchT
 //               special matrix component operations.
 //               special matrix component operations.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannelFixed<ACMatrixSwitchType> {
 class EXPCL_PANDA AnimChannelMatrixFixed : public AnimChannelFixed<ACMatrixSwitchType> {
+protected:
+  AnimChannelMatrixFixed(AnimGroup *parent, const AnimChannelMatrixFixed &copy);
+
 public:
 public:
   AnimChannelMatrixFixed(const string &name, const LMatrix4f &value);
   AnimChannelMatrixFixed(const string &name, const LMatrix4f &value);
 
 

+ 38 - 10
panda/src/chan/animChannelMatrixXfmTable.cxx

@@ -34,21 +34,36 @@ TypeHandle AnimChannelMatrixXfmTable::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixXfmTable::Constructor
 //     Function: AnimChannelMatrixXfmTable::Constructor
-//       Access: Public
-//  Description:
+//       Access: Protected
+//  Description: Used only for bam loader.
+/////////////////////////////////////////////////////////////
+AnimChannelMatrixXfmTable::
+AnimChannelMatrixXfmTable() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixXfmTable::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelMatrixXfmTable, just like
+//               this one, without copying any children.  The new copy
+//               is added to the indicated parent.  Intended to be
+//               called by make_copy() only.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AnimChannelMatrixXfmTable::
 AnimChannelMatrixXfmTable::
-AnimChannelMatrixXfmTable(AnimGroup *parent, const string &name)
-  : AnimChannelMatrix(parent, name) {
+AnimChannelMatrixXfmTable(AnimGroup *parent, const AnimChannelMatrixXfmTable &copy) : 
+  AnimChannelMatrix(parent, copy),
+  _tables(copy._tables)
+{
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixXfmTable::Constructor
 //     Function: AnimChannelMatrixXfmTable::Constructor
-//       Access: Protected
-//  Description: Used only for bam loader.
-/////////////////////////////////////////////////////////////
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
 AnimChannelMatrixXfmTable::
 AnimChannelMatrixXfmTable::
-AnimChannelMatrixXfmTable() {
+AnimChannelMatrixXfmTable(AnimGroup *parent, const string &name)
+  : AnimChannelMatrix(parent, name) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -299,13 +314,26 @@ write(ostream &out, int indent_level) const {
   out << "\n";
   out << "\n";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelMatrixXfmTable::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimChannelMatrixXfmTable::
+make_copy(AnimGroup *parent) const {
+  return new AnimChannelMatrixXfmTable(parent, *this);
+}
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelMatrixXfmTable::get_table_index
 //     Function: AnimChannelMatrixXfmTable::get_table_index
 //       Access: Protected, Static
 //       Access: Protected, Static
 //  Description: Returns the table index number, a value between 0 and
 //  Description: Returns the table index number, a value between 0 and
-//               num_matrix_components, that corresponds to the indicate table
-//               id.  Returns -1 if the table id is invalid.
+//               num_matrix_components, that corresponds to the
+//               indicated table id.  Returns -1 if the table id is
+//               invalid.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int AnimChannelMatrixXfmTable::
 int AnimChannelMatrixXfmTable::
 get_table_index(char table_id) {
 get_table_index(char table_id) {

+ 5 - 3
panda/src/chan/animChannelMatrixXfmTable.h

@@ -36,13 +36,13 @@
 //               transform: scale, rotate, translate.
 //               transform: scale, rotate, translate.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimChannelMatrixXfmTable : public AnimChannelMatrix {
 class EXPCL_PANDA AnimChannelMatrixXfmTable : public AnimChannelMatrix {
-public:
-  AnimChannelMatrixXfmTable(AnimGroup *parent, const string &name);
 protected:
 protected:
   AnimChannelMatrixXfmTable();
   AnimChannelMatrixXfmTable();
+  AnimChannelMatrixXfmTable(AnimGroup *parent, const AnimChannelMatrixXfmTable &copy);
 
 
 public:
 public:
-  ~AnimChannelMatrixXfmTable();
+  AnimChannelMatrixXfmTable(AnimGroup *parent, const string &name);
+  virtual ~AnimChannelMatrixXfmTable();
   
   
 
 
   virtual bool has_changed(double last_frame, double this_frame);
   virtual bool has_changed(double last_frame, double this_frame);
@@ -69,6 +69,8 @@ public:
   virtual void write(ostream &out, int indent_level) const;
   virtual void write(ostream &out, int indent_level) const;
 
 
 protected:
 protected:
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+
   INLINE static char get_table_id(int table_index);
   INLINE static char get_table_id(int table_index);
   static int get_table_index(char table_id);
   static int get_table_index(char table_id);
   INLINE static float get_default_value(int table_index);
   INLINE static float get_default_value(int table_index);

+ 42 - 8
panda/src/chan/animChannelScalarDynamic.cxx

@@ -31,23 +31,44 @@ TypeHandle AnimChannelScalarDynamic::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelScalarDynamic::Constructor
 //     Function: AnimChannelScalarDynamic::Constructor
-//       Access: Public
-//  Description:
+//       Access: Protected
+//  Description: For use only with the bam reader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AnimChannelScalarDynamic::
 AnimChannelScalarDynamic::
-AnimChannelScalarDynamic(AnimGroup *parent, const string &name)
-  : AnimChannelScalar(parent, name) 
+AnimChannelScalarDynamic() {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelScalarDynamic::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelScalarDynamic, just like
+//               this one, without copying any children.  The new copy
+//               is added to the indicated parent.  Intended to be
+//               called by make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimChannelScalarDynamic::
+AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic &copy) : 
+  AnimChannelScalar(parent, copy),
+  _value_node(copy._value_node),
+  _value(copy._value),
+  _last_value(NULL),
+  _value_changed(true),
+  _float_value(copy._float_value)
 {
 {
-  _last_value = _value = TransformState::make_identity();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelScalarDynamic::Constructor
 //     Function: AnimChannelScalarDynamic::Constructor
-//       Access: Protected
-//  Description: For use only with the bam reader.
+//       Access: Public
+//  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AnimChannelScalarDynamic::
 AnimChannelScalarDynamic::
-AnimChannelScalarDynamic() {
+AnimChannelScalarDynamic(AnimGroup *parent, const string &name)
+  : AnimChannelScalar(parent, name) 
+{
+  _last_value = _value = TransformState::make_identity();
+  _value_changed = true;
+  _float_value = 0.0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -120,6 +141,19 @@ set_value_node(PandaNode *value_node) {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelScalarDynamic::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimChannelScalarDynamic::
+make_copy(AnimGroup *parent) const {
+  return new AnimChannelScalarDynamic(parent, *this);
+}
+
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelScalarDynamic::write_datagram
 //     Function: AnimChannelScalarDynamic::write_datagram

+ 6 - 2
panda/src/chan/animChannelScalarDynamic.h

@@ -39,12 +39,13 @@ class TransformState;
 //               scalar each frame.
 //               scalar each frame.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimChannelScalarDynamic : public AnimChannelScalar {
 class EXPCL_PANDA AnimChannelScalarDynamic : public AnimChannelScalar {
-public:
-  AnimChannelScalarDynamic(AnimGroup *parent, const string &name);
 protected:
 protected:
   AnimChannelScalarDynamic();
   AnimChannelScalarDynamic();
+  AnimChannelScalarDynamic(AnimGroup *parent, const AnimChannelScalarDynamic &copy);
 
 
 public:
 public:
+  AnimChannelScalarDynamic(AnimGroup *parent, const string &name);
+
   virtual bool has_changed(double last_frame, double this_frame);
   virtual bool has_changed(double last_frame, double this_frame);
   virtual void get_value(int frame, float &value);
   virtual void get_value(int frame, float &value);
 
 
@@ -52,6 +53,9 @@ PUBLISHED:
   void set_value(float value);
   void set_value(float value);
   void set_value_node(PandaNode *node);
   void set_value_node(PandaNode *node);
 
 
+protected:
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+
 private:
 private:
   // This is filled in only if we are using the set_value_node()
   // This is filled in only if we are using the set_value_node()
   // interface to get an implicit value from the transform on the
   // interface to get an implicit value from the transform on the

+ 32 - 4
panda/src/chan/animChannelScalarTable.cxx

@@ -32,12 +32,26 @@ TypeHandle AnimChannelScalarTable::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelScalarTable::Constructor
 //     Function: AnimChannelScalarTable::Constructor
-//       Access: Public
+//       Access: Protected
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AnimChannelScalarTable::
 AnimChannelScalarTable::
-AnimChannelScalarTable(AnimGroup *parent, const string &name)
-  : AnimChannelScalar(parent, name) {
+AnimChannelScalarTable(){
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelScalarTable::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimChannelScalarTable, just like
+//               this one, without copying any children.  The new copy
+//               is added to the indicated parent.  Intended to be
+//               called by make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimChannelScalarTable::
+AnimChannelScalarTable(AnimGroup *parent, const AnimChannelScalarTable &copy) : 
+  AnimChannelScalar(parent, copy),
+  _table(copy._table)
+{
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -46,7 +60,8 @@ AnimChannelScalarTable(AnimGroup *parent, const string &name)
 //  Description:
 //  Description:
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 AnimChannelScalarTable::
 AnimChannelScalarTable::
-AnimChannelScalarTable(){
+AnimChannelScalarTable(AnimGroup *parent, const string &name)
+  : AnimChannelScalar(parent, name) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -124,6 +139,19 @@ write(ostream &out, int indent_level) const {
   out << "\n";
   out << "\n";
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimChannelScalarTable::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimChannelScalarTable::
+make_copy(AnimGroup *parent) const {
+  return new AnimChannelScalarTable(parent, *this);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimChannelScalarTable::write_datagram
 //     Function: AnimChannelScalarTable::write_datagram
 //       Access: Public
 //       Access: Public

+ 7 - 1
panda/src/chan/animChannelScalarTable.h

@@ -33,6 +33,10 @@
 //               an egg file.
 //               an egg file.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimChannelScalarTable : public AnimChannelScalar {
 class EXPCL_PANDA AnimChannelScalarTable : public AnimChannelScalar {
+protected:
+  AnimChannelScalarTable();
+  AnimChannelScalarTable(AnimGroup *parent, const AnimChannelScalarTable &copy);
+
 public:
 public:
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
   AnimChannelScalarTable(AnimGroup *parent, const string &name);
 
 
@@ -49,7 +53,9 @@ public:
   virtual void write(ostream &out, int indent_level) const;
   virtual void write(ostream &out, int indent_level) const;
 
 
 protected:
 protected:
-  AnimChannelScalarTable();
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+
+protected:
   CPTA_float _table;
   CPTA_float _table;
 
 
 public:
 public:

+ 73 - 19
panda/src/chan/animGroup.cxx

@@ -35,6 +35,37 @@
 TypeHandle AnimGroup::_type_handle;
 TypeHandle AnimGroup::_type_handle;
 
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimGroup::Default Constructor
+//       Access: Protected
+//  Description: The default constructor is protected: don't try to
+//               create an AnimGroup without a parent.  To create an
+//               AnimChannel hierarchy, you must first create an
+//               AnimBundle, and use that to create any subsequent
+//               children.
+////////////////////////////////////////////////////////////////////
+AnimGroup::
+AnimGroup(const string &name) : Namable(name) {
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimGroup::Copy Constructor
+//       Access: Protected
+//  Description: Creates a new AnimGroup, just like this one, without
+//               copying any children.  The new copy is added to the
+//               indicated parent.  Intended to be called by
+//               make_copy() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup::
+AnimGroup(AnimGroup *parent, const AnimGroup &copy) : Namable(copy) {
+  if (parent != (AnimGroup *)NULL) {
+    parent->_children.push_back(this);
+    _root = parent->_root;
+  } else {
+    _root = NULL;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimGroup::Constructor
 //     Function: AnimGroup::Constructor
 //       Access: Public
 //       Access: Public
@@ -277,6 +308,39 @@ write_descendants(ostream &out, int indent_level) const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: AnimGroup::make_copy
+//       Access: Protected, Virtual
+//  Description: Returns a copy of this object, and attaches it to the
+//               indicated parent (which may be NULL only if this is
+//               an AnimBundle).  Intended to be called by
+//               copy_subtree() only.
+////////////////////////////////////////////////////////////////////
+AnimGroup *AnimGroup::
+make_copy(AnimGroup *parent) const {
+  return new AnimGroup(parent, *this);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: AnimGroup::copy_subtree
+//       Access: Protected
+//  Description: Returns a full copy of the subtree at this node and
+//               below.
+////////////////////////////////////////////////////////////////////
+PT(AnimGroup) AnimGroup::
+copy_subtree(AnimGroup *parent) const {
+  PT(AnimGroup) new_group = make_copy(parent);
+  nassertr(new_group->get_type() == get_type(), (AnimGroup *)this);
+
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    (*ci)->copy_subtree(new_group);
+  }
+
+  return new_group;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: AnimGroup::write_datagram
 //     Function: AnimGroup::write_datagram
 //       Access: Public
 //       Access: Public
@@ -284,14 +348,12 @@ write_descendants(ostream &out, int indent_level) const {
 //               the particular object to a Datagram
 //               the particular object to a Datagram
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimGroup::
 void AnimGroup::
-write_datagram(BamWriter *manager, Datagram &me)
-{
+write_datagram(BamWriter *manager, Datagram &me) {
   me.add_string(get_name());
   me.add_string(get_name());
   //Write out the root
   //Write out the root
   manager->write_pointer(me, this->_root);
   manager->write_pointer(me, this->_root);
   me.add_uint16(_children.size());
   me.add_uint16(_children.size());
-  for(int i = 0; i < (int)_children.size(); i++)
-  {
+  for(int i = 0; i < (int)_children.size(); i++) {
     manager->write_pointer(me, _children[i]);
     manager->write_pointer(me, _children[i]);
   }
   }
 }
 }
@@ -305,8 +367,7 @@ write_datagram(BamWriter *manager, Datagram &me)
 //               place
 //               place
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimGroup::
 void AnimGroup::
-fillin(DatagramIterator& scan, BamReader* manager)
-{
+fillin(DatagramIterator &scan, BamReader *manager) {
   set_name(scan.get_string());
   set_name(scan.get_string());
   manager->read_pointer(scan);
   manager->read_pointer(scan);
   _num_children = scan.get_uint16();
   _num_children = scan.get_uint16();
@@ -324,19 +385,14 @@ fillin(DatagramIterator& scan, BamReader* manager)
 //               pointers that this object made to BamReader.
 //               pointers that this object made to BamReader.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int AnimGroup::
 int AnimGroup::
-complete_pointers(TypedWritable **p_list, BamReader*)
-{
+complete_pointers(TypedWritable **p_list, BamReader *) {
   nassertr(p_list[0] != TypedWritable::Null, 0);
   nassertr(p_list[0] != TypedWritable::Null, 0);
   _root = DCAST(AnimBundle, p_list[0]);
   _root = DCAST(AnimBundle, p_list[0]);
-  for(int i = 1; i < _num_children+1; i++)
-  {
-    if (p_list[i] == TypedWritable::Null)
-    {
+  for(int i = 1; i < _num_children+1; i++) {
+    if (p_list[i] == TypedWritable::Null) {
       chan_cat->warning() << get_type().get_name()
       chan_cat->warning() << get_type().get_name()
                           << " Ignoring null child" << endl;
                           << " Ignoring null child" << endl;
-    }
-    else
-    {
+    } else {
       _children.push_back(DCAST(AnimGroup, p_list[i]));
       _children.push_back(DCAST(AnimGroup, p_list[i]));
     }
     }
   }
   }
@@ -349,8 +405,7 @@ complete_pointers(TypedWritable **p_list, BamReader*)
 //  Description: Factory method to generate a AnimGroup object
 //  Description: Factory method to generate a AnimGroup object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 TypedWritable* AnimGroup::
 TypedWritable* AnimGroup::
-make_AnimGroup(const FactoryParams &params)
-{
+make_AnimGroup(const FactoryParams &params) {
   AnimGroup *me = new AnimGroup;
   AnimGroup *me = new AnimGroup;
   DatagramIterator scan;
   DatagramIterator scan;
   BamReader *manager;
   BamReader *manager;
@@ -366,8 +421,7 @@ make_AnimGroup(const FactoryParams &params)
 //  Description: Factory method to generate a AnimGroup object
 //  Description: Factory method to generate a AnimGroup object
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void AnimGroup::
 void AnimGroup::
-register_with_read_factory()
-{
+register_with_read_factory() {
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimGroup);
   BamReader::get_factory()->register_factory(get_class_type(), make_AnimGroup);
 }
 }
 
 

+ 5 - 5
panda/src/chan/animGroup.h

@@ -38,11 +38,8 @@ class FactoryParams;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA AnimGroup : public TypedWritableReferenceCount, public Namable {
 class EXPCL_PANDA AnimGroup : public TypedWritableReferenceCount, public Namable {
 protected:
 protected:
-  // The default constructor is protected: don't try to create an
-  // AnimGroup without a parent.  To create an AnimChannel hierarchy,
-  // you must first create an AnimBundle, and use that to create any
-  // subsequent children.
-  AnimGroup(const string &name = "") : Namable(name) { }
+  AnimGroup(const string &name = "");
+  AnimGroup(AnimGroup *parent, const AnimGroup &copy);
 
 
 public:
 public:
   // This is the normal AnimGroup constructor.
   // This is the normal AnimGroup constructor.
@@ -68,6 +65,9 @@ PUBLISHED:
 protected:
 protected:
   void write_descendants(ostream &out, int indent_level) const;
   void write_descendants(ostream &out, int indent_level) const;
 
 
+  virtual AnimGroup *make_copy(AnimGroup *parent) const;
+  PT(AnimGroup) copy_subtree(AnimGroup *parent) const;
+  
 protected:
 protected:
   typedef pvector< PT(AnimGroup) > Children;
   typedef pvector< PT(AnimGroup) > Children;
   Children _children;
   Children _children;