Browse Source

*** empty log message ***

David Rose 25 years ago
parent
commit
2b36b8e1a6
31 changed files with 1309 additions and 340 deletions
  1. 7 12
      pandatool/src/eggbase/Sources.pp
  2. 0 27
      pandatool/src/eggbase/eggCharacterData.I
  3. 0 82
      pandatool/src/eggbase/eggCharacterData.h
  4. 0 93
      pandatool/src/eggbase/eggJointData.cxx
  5. 33 0
      pandatool/src/eggcharbase/Sources.pp
  6. 18 0
      pandatool/src/eggcharbase/eggBackPointer.cxx
  7. 51 0
      pandatool/src/eggcharbase/eggBackPointer.h
  8. 50 0
      pandatool/src/eggcharbase/eggCharacterCollection.I
  9. 253 80
      pandatool/src/eggcharbase/eggCharacterCollection.cxx
  10. 93 0
      pandatool/src/eggcharbase/eggCharacterCollection.h
  11. 20 0
      pandatool/src/eggcharbase/eggCharacterData.I
  12. 76 0
      pandatool/src/eggcharbase/eggCharacterData.cxx
  13. 66 0
      pandatool/src/eggcharbase/eggCharacterData.h
  14. 17 16
      pandatool/src/eggcharbase/eggCharacterFilter.cxx
  15. 3 2
      pandatool/src/eggcharbase/eggCharacterFilter.h
  16. 49 0
      pandatool/src/eggcharbase/eggComponentData.I
  17. 87 0
      pandatool/src/eggcharbase/eggComponentData.cxx
  18. 59 0
      pandatool/src/eggcharbase/eggComponentData.h
  19. 0 0
      pandatool/src/eggcharbase/eggJointData.I
  20. 74 0
      pandatool/src/eggcharbase/eggJointData.cxx
  21. 6 28
      pandatool/src/eggcharbase/eggJointData.h
  22. 19 0
      pandatool/src/eggcharbase/eggJointPointer.cxx
  23. 47 0
      pandatool/src/eggcharbase/eggJointPointer.h
  24. 45 0
      pandatool/src/eggcharbase/eggMatrixTablePointer.cxx
  25. 52 0
      pandatool/src/eggcharbase/eggMatrixTablePointer.h
  26. 4 0
      pandatool/src/eggcharbase/eggSliderData.I
  27. 80 0
      pandatool/src/eggcharbase/eggSliderData.cxx
  28. 35 0
      pandatool/src/eggcharbase/eggSliderData.h
  29. 18 0
      pandatool/src/eggcharbase/eggVertexPointer.cxx
  30. 46 0
      pandatool/src/eggcharbase/eggVertexPointer.h
  31. 1 0
      pandatool/src/eggprogs/Sources.pp

+ 7 - 12
pandatool/src/eggbase/Sources.pp

@@ -7,24 +7,19 @@
 
 
   #define SOURCES \
   #define SOURCES \
     eggBase.cxx eggBase.h \
     eggBase.cxx eggBase.h \
-    eggCharacterData.cxx eggCharacterData.h eggCharacterData.I \
-    eggCharacterFilter.cxx eggCharacterFilter.h \
-    eggConverter.cxx eggConverter.h eggFilter.cxx \
-    eggFilter.h eggJointData.cxx eggJointData.h eggJointData.I \
+    eggConverter.cxx eggConverter.h \
+    eggFilter.cxx eggFilter.h \
     eggMultiBase.cxx eggMultiBase.h \
     eggMultiBase.cxx eggMultiBase.h \
     eggMultiFilter.cxx eggMultiFilter.h \
     eggMultiFilter.cxx eggMultiFilter.h \
     eggReader.cxx eggReader.h \
     eggReader.cxx eggReader.h \
-    eggToSomething.cxx \
-    eggToSomething.h eggWriter.cxx eggWriter.h somethingToEgg.cxx \
-    somethingToEgg.h
+    eggToSomething.cxx eggToSomething.h \
+    eggWriter.cxx eggWriter.h \
+    somethingToEgg.cxx somethingToEgg.h
 
 
   #define INSTALL_HEADERS \
   #define INSTALL_HEADERS \
-    eggBase.h eggCharacterData.h \
-    eggCharacterData.I eggCharacterFilter.h \
-    eggConverter.h eggFilter.h eggJointData.h eggJointData.I \
+    eggBase.h eggConverter.h eggFilter.h \
     eggMultiBase.h eggMultiFilter.h \
     eggMultiBase.h eggMultiFilter.h \
-    eggReader.h \
-    eggToSomething.h eggWriter.h somethingToEgg.h
+    eggReader.h eggToSomething.h eggWriter.h somethingToEgg.h
 
 
 #end ss_lib_target
 #end ss_lib_target
 
 

+ 0 - 27
pandatool/src/eggbase/eggCharacterData.I

@@ -1,27 +0,0 @@
-// Filename: eggCharacterData.I
-// Created by:  drose (23Feb01)
-// 
-////////////////////////////////////////////////////////////////////
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::get_num_eggs
-//       Access: Public
-//  Description: Returns the number of egg files that have
-//               successfully been added to the Character table.
-////////////////////////////////////////////////////////////////////
-INLINE int EggCharacterData::
-get_num_eggs() const {
-  return _eggs.size();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::get_egg
-//       Access: Public
-//  Description: Returns the ith egg file.
-////////////////////////////////////////////////////////////////////
-INLINE EggData *EggCharacterData::
-get_egg(int i) const {
-  nassertr(i >= 0 && i < (int)_eggs.size(), (EggData *)NULL);
-  return _eggs[i]._egg;
-}

+ 0 - 82
pandatool/src/eggbase/eggCharacterData.h

@@ -1,82 +0,0 @@
-// Filename: eggCharacterData.h
-// Created by:  drose (23Feb01)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef EGGCHARACTERDATA_H
-#define EGGCHARACTERDATA_H
-
-#include <pandatoolbase.h>
-
-#include <eggData.h>
-#include <eggNode.h>
-#include <pointerTo.h>
-
-class EggJointData;
-class EggTable;
-
-////////////////////////////////////////////////////////////////////
-// 	 Class : EggCharacterData
-// Description : Represents a set of characters, as read and collected
-//               from several models and animation files.  Each
-//               character is the root of a hierarchy of EggJointData
-//               nodes.
-////////////////////////////////////////////////////////////////////
-class EggCharacterData {
-public:
-  EggCharacterData();
-  virtual ~EggCharacterData();
-
-  bool add_egg(EggData *egg);
-
-  INLINE int get_num_eggs() const;
-  INLINE EggData *get_egg(int i) const;
-
-  virtual void write(ostream &out, int indent_level = 0) const;
-
-protected:
-  virtual EggJointData *make_joint_data();
-  EggJointData *get_root_joint(const string &character_name);
-
-  class EggInfo {
-  public:
-    PT(EggData) _egg;
-    typedef vector<PT(EggNode)> Models;
-    Models _models;
-  };
-  
-  typedef vector<EggInfo> Eggs;
-  Eggs _eggs;
-
-  class CharacterInfo {
-  public:
-    string _name;
-    EggJointData *_root_joint;
-  };
-
-  typedef vector<CharacterInfo> Characters;
-  Characters _characters;
-
-private:
-  bool scan_hierarchy(EggNode *egg_node);
-  void scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
-			   const string &character_name);
-  void scan_for_top_tables(EggTable *bundle, EggNode *model_root,
-			   const string &character_name);
-
-  typedef vector<EggNode *> EggNodeList;
-  typedef map<EggNode *, EggNodeList> TopEggNodes;
-  typedef map<string, TopEggNodes> TopEggNodesByName;
-  TopEggNodesByName _top_egg_nodes;
-
-  void match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
-		       int egg_index, int model_index);
-  void found_egg_node_match(EggJointData *data, EggNode *egg_node,
-			    int egg_index, int model_index);
-};
-
-#include "eggCharacterData.I"
-
-#endif
-
-

+ 0 - 93
pandatool/src/eggbase/eggJointData.cxx

@@ -1,93 +0,0 @@
-// Filename: eggJointData.cxx
-// Created by:  drose (23Feb01)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include "eggJointData.h"
-
-#include <indent.h>
-
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggJointData::Constructor
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-EggJointData::
-EggJointData() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggJointData::Destructor
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-EggJointData::
-~EggJointData() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggJointData::matches_name
-//       Access: Public
-//  Description: Returns true if the indicated name matches any name
-//               that was ever matched with this particular joint,
-//               false otherwise.
-////////////////////////////////////////////////////////////////////
-bool EggJointData::
-matches_name(const string &name) const {
-  return false;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggJointData::add_egg_node
-//       Access: Public
-//  Description: Adds the indicated model joint or anim table to the
-//               data.
-////////////////////////////////////////////////////////////////////
-void EggJointData::
-add_egg_node(int egg_index, int model_index, EggNode *egg_node) {
-  if (!has_name() && egg_node->has_name()) {
-    set_name(egg_node->get_name());
-  }
-
-  while ((int)_joints.size() <= egg_index) {
-    _joints.push_back(JointNodes());
-  }
-  JointNodes &nodes = _joints[egg_index];
-  while ((int)nodes.size() <= model_index) {
-    nodes.push_back((EggNode *)NULL);
-  }
-  nodes[model_index] = egg_node;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: EggJointData::write
-//       Access: Public, Virtual
-//  Description: 
-////////////////////////////////////////////////////////////////////
-void EggJointData::
-write(ostream &out, int indent_level) const {
-  indent(out, indent_level)
-    << "Joint " << get_name()
-    << " (models:";
-  for (size_t egg_index = 0; egg_index < _joints.size(); egg_index++) {
-    const JointNodes &nodes = _joints[egg_index];
-    if (nodes.size() == 1) {
-      out << " " << egg_index;
-    } else if (nodes.size() > 1) {
-      for (size_t model_index = 0; model_index < nodes.size(); model_index++) {
-	if (nodes[model_index] != (EggNode *)NULL) {
-	  out << " " << egg_index << "/" << model_index;
-	}
-      }
-    }
-  }
-  out << ") {\n";
-
-  Children::const_iterator ci;
-  for (ci = _children.begin(); ci != _children.end(); ++ci) {
-    (*ci)->write(out, indent_level + 2);
-  }
-
-  indent(out, indent_level) << "}\n";
-}

+ 33 - 0
pandatool/src/eggcharbase/Sources.pp

@@ -0,0 +1,33 @@
+#begin ss_lib_target
+  #define TARGET eggcharbase
+  #define LOCAL_LIBS \
+    eggbase progbase
+  #define OTHER_LIBS \
+    egg:c panda:m
+
+  #define SOURCES \
+    eggBackPointer.cxx eggBackPointer.h \
+    eggCharacterCollection.cxx eggCharacterCollection.h \
+    eggCharacterCollection.I \
+    eggCharacterData.cxx eggCharacterData.h eggCharacterData.I \
+    eggCharacterFilter.cxx eggCharacterFilter.h \
+    eggComponentData.cxx eggComponentData.h eggComponentData.I \
+    eggJointData.cxx eggJointData.h eggJointData.I \
+    eggJointPointer.cxx eggJointPointer.h \
+    eggMatrixTablePointer.cxx eggMatrixTablePointer.h \
+    eggSliderData.cxx eggSliderData.h eggSliderData.I \
+    eggVertexPointer.cxx eggVertexPointer.h
+
+  #define INSTALL_HEADERS \
+    eggBackPointer.h \
+    eggCharacterCollection.I eggCharacterCollection.h \
+    eggCharacterData.I eggCharacterData.h eggCharacterFilter.h \
+    eggComponentData.I eggComponentData.h \
+    eggJointData.h eggJointData.I \
+    eggJointPointer.h \
+    eggMatrixTablePointer.h \
+    eggSliderData.I eggSliderData.h \
+    eggVertexPointer.h
+
+#end ss_lib_target
+

+ 18 - 0
pandatool/src/eggcharbase/eggBackPointer.cxx

@@ -0,0 +1,18 @@
+// Filename: eggBackPointer.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggBackPointer.h"
+
+
+TypeHandle EggBackPointer::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggBackPointer::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggBackPointer::
+EggBackPointer() {
+}

+ 51 - 0
pandatool/src/eggcharbase/eggBackPointer.h

@@ -0,0 +1,51 @@
+// Filename: eggBackPointer.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGBACKPOINTER_H
+#define EGGBACKPOINTER_H
+
+#include <pandatoolbase.h>
+
+#include <typeHandle.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggBackPointer
+// Description : This stores a pointer from an EggJointData or
+//               EggSlider object back to the referencing data in an
+//               egg file.  One of these objects corresponds to each
+//               model appearing in an egg file, and may reference
+//               either a single node, or a table, or a slew of
+//               vertices and primitives, depending on the type of
+//               data stored.
+//
+//               This is just an abstract base class.  The actual
+//               details are stored in the various subclasses.
+////////////////////////////////////////////////////////////////////
+class EggBackPointer : public TypedObject {
+public:
+  EggBackPointer();
+
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedObject::init_type();
+    register_type(_type_handle, "EggBackPointer",
+		  TypedObject::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+ 
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+
+

+ 50 - 0
pandatool/src/eggcharbase/eggCharacterCollection.I

@@ -0,0 +1,50 @@
+// Filename: eggCharacterCollection.I
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_num_eggs
+//       Access: Public
+//  Description: Returns the number of egg files that have
+//               successfully been added to the Character table.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterCollection::
+get_num_eggs() const {
+  return _eggs.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_egg
+//       Access: Public
+//  Description: Returns the ith egg file.
+////////////////////////////////////////////////////////////////////
+INLINE EggData *EggCharacterCollection::
+get_egg(int i) const {
+  nassertr(i >= 0 && i < (int)_eggs.size(), (EggData *)NULL);
+  return _eggs[i]._egg;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_num_characters
+//       Access: Public
+//  Description: Returns the number of separate Characters that have
+//               been discovered in the various egg files added to the
+//               collection.
+////////////////////////////////////////////////////////////////////
+INLINE int EggCharacterCollection::
+get_num_characters() const {
+  return _characters.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::get_character
+//       Access: Public
+//  Description: Returns the ith character in the collection.
+////////////////////////////////////////////////////////////////////
+INLINE EggCharacterData *EggCharacterCollection::
+get_character(int i) const {
+  nassertr(i >= 0 && i < (int)_characters.size(), (EggCharacterData *)NULL);
+  return _characters[i];
+}

+ 253 - 80
pandatool/src/eggbase/eggCharacterData.cxx → pandatool/src/eggcharbase/eggCharacterCollection.cxx

@@ -1,44 +1,51 @@
-// Filename: eggCharacterData.cxx
-// Created by:  drose (23Feb01)
+// Filename: eggCharacterCollection.cxx
+// Created by:  drose (26Feb01)
 // 
 // 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
+#include "eggCharacterCollection.h"
 #include "eggCharacterData.h"
 #include "eggCharacterData.h"
 #include "eggJointData.h"
 #include "eggJointData.h"
-#include "eggGroup.h"
-#include "eggTable.h"
-
+#include "eggSliderData.h"
+
+#include <eggGroup.h>
+#include <eggTable.h>
+#include <eggPrimitive.h>
+#include <eggVertex.h>
+#include <eggMorphList.h>
+#include <eggSAnimData.h>
 #include <indirectCompareNames.h>
 #include <indirectCompareNames.h>
 #include <indent.h>
 #include <indent.h>
 
 
 #include <algorithm>
 #include <algorithm>
 
 
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::Constructor
+//     Function: EggCharacterCollection::Constructor
 //       Access: Public
 //       Access: Public
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggCharacterData::
-EggCharacterData() {
+EggCharacterCollection::
+EggCharacterCollection() {
+  _next_model_index = 0;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::Destructor
+//     Function: EggCharacterCollection::Destructor
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggCharacterData::
-~EggCharacterData() {
+EggCharacterCollection::
+~EggCharacterCollection() {
   Characters::iterator ci;
   Characters::iterator ci;
 
 
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
-    CharacterInfo &character_info = (*ci);
-    delete character_info._root_joint;
+    delete (*ci);
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::add_egg
+//     Function: EggCharacterCollection::add_egg
 //       Access: Public
 //       Access: Public
 //  Description: Adds a new egg file to the list of models and
 //  Description: Adds a new egg file to the list of models and
 //               animation files for this particular character.
 //               animation files for this particular character.
@@ -49,7 +56,7 @@ EggCharacterData::
 //               If the joint hierarchy does not match the existing
 //               If the joint hierarchy does not match the existing
 //               joint hierarchy, a best match is attempted.
 //               joint hierarchy, a best match is attempted.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool EggCharacterData::
+bool EggCharacterCollection::
 add_egg(EggData *egg) {
 add_egg(EggData *egg) {
   _top_egg_nodes.clear();
   _top_egg_nodes.clear();
 
 
@@ -68,16 +75,21 @@ add_egg(EggData *egg) {
   for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
   for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) {
     string character_name = (*tni).first;
     string character_name = (*tni).first;
     TopEggNodes &top_nodes = (*tni).second;
     TopEggNodes &top_nodes = (*tni).second;
+    EggCharacterData *char_data = make_character(character_name);
+    EggJointData *root_joint = char_data->get_root_joint();
     
     
     TopEggNodes::iterator ti;
     TopEggNodes::iterator ti;
     for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
     for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) {
-      EggNode *model = (*ti).first;
+      EggNode *model_root = (*ti).first;
       EggNodeList &egg_nodes = (*ti).second;
       EggNodeList &egg_nodes = (*ti).second;
       
       
-      int model_index = egg_info._models.size();
-      egg_info._models.push_back(model);
-      match_egg_nodes(get_root_joint(character_name), 
-		      egg_nodes, egg_index, model_index);
+      int model_index = _next_model_index++;
+      egg_info._models.push_back(model_root);
+      match_egg_nodes(char_data, root_joint, egg_nodes,
+		      egg_index, model_index);
+
+      scan_for_morphs(model_root, model_index, char_data);
+      scan_for_sliders(model_root, model_index, char_data);
     }
     }
   }
   }
 
 
@@ -85,50 +97,95 @@ add_egg(EggData *egg) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::get_root_joint
-//       Access: Protected
-//  Description: Returns the root of the joint hierarchy for the named
-//               character.  This is actually a fictitious node that
-//               does not correspond to any particular nodes in the
-//               character hierarchy; it exists to hold all of the top
-//               joints (if any) read from the character hierarchy.
-////////////////////////////////////////////////////////////////////
-EggJointData *EggCharacterData::
-get_root_joint(const string &character_name) {
-  // Does the named character exist yet?
-
-  Characters::iterator ci;
+//     Function: EggCharacterCollection::get_character_by_name
+//       Access: Public
+//  Description: Returns the Character with the indicated name, if it
+//               exists in the collection, or NULL if it does not.
+////////////////////////////////////////////////////////////////////
+EggCharacterData *EggCharacterCollection::
+get_character_by_name(const string &character_name) const {
+  Characters::const_iterator ci;
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
-    CharacterInfo &character_info = (*ci);
-    if (character_info._name == character_name) {
-      return character_info._root_joint;
+    EggCharacterData *char_data = (*ci);
+    if (char_data->get_name() == character_name) {
+      return char_data;
     }
     }
   }
   }
 
 
-  // Define a new character.
-  _characters.push_back(CharacterInfo());
-  CharacterInfo &character_info = _characters.back();
-  character_info._name = character_name;
-  character_info._root_joint = make_joint_data();
-  return character_info._root_joint;
+  return (EggCharacterData *)NULL;
 }
 }
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::make_joint_data
-//       Access: Protected, Virtual
-//  Description: Allocates and returns a new EggJointData structure.
-//               This is primarily intended as a hook so derived
-//               classes can customize the type of EggJointData nodes
-//               used to represent the joint hierarchy.
+//     Function: EggCharacterCollection::make_character_data
+//       Access: Public, Virtual
+//  Description: Allocates and returns a new EggCharacterData
+//               structure.  This is primarily intended as a hook so
+//               derived classes can customize the type of
+//               EggCharacterData nodes used to represent the
+//               characters in this collection.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggJointData *EggCharacterData::
-make_joint_data() {
-  return new EggJointData;
+EggCharacterData *EggCharacterCollection::
+make_character_data() {
+  return new EggCharacterData(this);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::scan_hierarchy
+//     Function: EggCharacterCollection::make_joint_data
+//       Access: Public, Virtual
+//  Description: Allocates and returns a new EggJointData structure
+//               for the given character.  This is primarily intended
+//               as a hook so derived classes can customize the type
+//               of EggJointData nodes used to represent the joint
+//               hierarchy.
+////////////////////////////////////////////////////////////////////
+EggJointData *EggCharacterCollection::
+make_joint_data(EggCharacterData *char_data) {
+  return new EggJointData(this, char_data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::make_slider_data
+//       Access: Public, Virtual
+//  Description: Allocates and returns a new EggSliderData structure
+//               for the given character.  This is primarily intended
+//               as a hook so derived classes can customize the type
+//               of EggSliderData nodes used to represent the slider
+//               list.
+////////////////////////////////////////////////////////////////////
+EggSliderData *EggCharacterCollection::
+make_slider_data(EggCharacterData *char_data) {
+  return new EggSliderData(this, char_data);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::make_character
+//       Access: Protected
+//  Description: Allocates and returns a new EggCharacterData object
+//               representing the named character, if there is not
+//               already a character by that name.
+////////////////////////////////////////////////////////////////////
+EggCharacterData *EggCharacterCollection::
+make_character(const string &character_name) {
+  // Does the named character exist yet?
+
+  Characters::iterator ci;
+  for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
+    EggCharacterData *char_data = (*ci);
+    if (char_data->get_name() == character_name) {
+      return char_data;
+    }
+  }
+
+  // Define a new character.
+  EggCharacterData *char_data = make_character_data();
+  char_data->set_name(character_name);
+  _characters.push_back(char_data);
+  return char_data;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::scan_hierarchy
 //       Access: Private
 //       Access: Private
 //  Description: Walks the given egg data's hierarchy, looking for
 //  Description: Walks the given egg data's hierarchy, looking for
 //               either the start of an animation channel or the start
 //               either the start of an animation channel or the start
@@ -139,7 +196,7 @@ make_joint_data() {
 //               Fills up the _top_egg_nodes according to the nodes
 //               Fills up the _top_egg_nodes according to the nodes
 //               found.
 //               found.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-bool EggCharacterData::
+bool EggCharacterCollection::
 scan_hierarchy(EggNode *egg_node) {
 scan_hierarchy(EggNode *egg_node) {
   if (egg_node->is_of_type(EggGroup::get_class_type())) {
   if (egg_node->is_of_type(EggGroup::get_class_type())) {
     EggGroup *group = DCAST(EggGroup, egg_node);
     EggGroup *group = DCAST(EggGroup, egg_node);
@@ -173,13 +230,13 @@ scan_hierarchy(EggNode *egg_node) {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::scan_for_top_joints
+//     Function: EggCharacterCollection::scan_for_top_joints
 //       Access: Private
 //       Access: Private
 //  Description: Once a character model has been found, continue
 //  Description: Once a character model has been found, continue
 //               scanning the egg hierarchy to look for the topmost
 //               scanning the egg hierarchy to look for the topmost
 //               <Joint> nodes encountered.
 //               <Joint> nodes encountered.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggCharacterData::
+void EggCharacterCollection::
 scan_for_top_joints(EggNode *egg_node, EggNode *model_root, 
 scan_for_top_joints(EggNode *egg_node, EggNode *model_root, 
 		    const string &character_name) {
 		    const string &character_name) {
   if (egg_node->is_of_type(EggGroup::get_class_type())) {
   if (egg_node->is_of_type(EggGroup::get_class_type())) {
@@ -206,13 +263,13 @@ scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::scan_for_top_tables
+//     Function: EggCharacterCollection::scan_for_top_tables
 //       Access: Private
 //       Access: Private
 //  Description: Once an animation has been found, continue scanning
 //  Description: Once an animation has been found, continue scanning
 //               the egg hierarchy to look for the topmost <Table>
 //               the egg hierarchy to look for the topmost <Table>
 //               nodes encountered.
 //               nodes encountered.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggCharacterData::
+void EggCharacterCollection::
 scan_for_top_tables(EggTable *bundle, EggNode *model_root,
 scan_for_top_tables(EggTable *bundle, EggNode *model_root,
 		    const string &character_name) {
 		    const string &character_name) {
   // We really only need to check the immediate children of the bundle
   // We really only need to check the immediate children of the bundle
@@ -239,7 +296,121 @@ scan_for_top_tables(EggTable *bundle, EggNode *model_root,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::match_egg_nodes
+//     Function: EggCharacterCollection::scan_for_morphs
+//       Access: Private
+//  Description: Go back through a model's hierarchy and look for
+//               morph targets on the vertices and primitives.
+////////////////////////////////////////////////////////////////////
+void EggCharacterCollection::
+scan_for_morphs(EggNode *egg_node, int model_index,
+		EggCharacterData *char_data) {
+  if (egg_node->is_of_type(EggPrimitive::get_class_type())) {
+    EggPrimitive *prim = DCAST(EggPrimitive, egg_node);
+    // Check for morphs on the primitive.
+    add_morph_back_pointers(prim, prim, model_index, char_data);
+
+    // Also check for morphs on each of the prim's vertices.
+    EggPrimitive::const_iterator vi;
+    for (vi = prim->begin(); vi != prim->end(); ++vi) {
+      EggVertex *vertex = (*vi);
+
+      add_morph_back_pointers(vertex, vertex, model_index, char_data);
+
+      EggMorphVertexList::const_iterator mvi;
+      for (mvi = vertex->_dxyzs.begin(); 
+	   mvi != vertex->_dxyzs.end();
+	   ++mvi) {
+	const EggMorphVertex &morph = (*mvi);
+	char_data->make_slider(morph.get_name())->add_back_pointer(model_index, vertex);
+      }
+    }
+  }
+
+  if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
+    EggGroupNode *group = DCAST(EggGroupNode, egg_node);
+    EggGroupNode::iterator gi;
+    for (gi = group->begin(); gi != group->end(); ++gi) {
+      scan_for_morphs(*gi, model_index, char_data);
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::scan_for_sliders
+//       Access: Private
+//  Description: Go back to the animation tables and look for morph
+//               slider animation channels.
+////////////////////////////////////////////////////////////////////
+void EggCharacterCollection::
+scan_for_sliders(EggNode *egg_node, int model_index,
+		 EggCharacterData *char_data) {
+  if (egg_node->is_of_type(EggTable::get_class_type())) {
+    EggTable *bundle = DCAST(EggTable, egg_node);
+
+    // We really only need to check the immediate children of the
+    // bundle for a table node called "morph".  This is a sibling of
+    // "<skeleton>", which we found a minute ago, but we weren't ready
+    // to scan for the morph sliders at the time, so we have to look
+    // again now.
+
+    EggGroupNode::iterator gi;
+    for (gi = bundle->begin(); gi != bundle->end(); ++gi) {
+      EggNode *child = (*gi);
+      if (child->is_of_type(EggTable::get_class_type())) {
+	EggTable *table = DCAST(EggTable, child);
+	if (table->get_name() == "morph") {
+	  // Here it is!  Now the immediate children of this node are
+	  // all the slider channels.
+
+	  EggGroupNode::iterator cgi;
+	  for (cgi = table->begin(); cgi != table->end(); ++cgi) {
+	    EggNode *grandchild = (*cgi);
+	    if (grandchild->is_of_type(EggSAnimData::get_class_type())) {
+	      char_data->make_slider(grandchild->get_name())->add_back_pointer(model_index, grandchild);
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::add_morph_back_pointers
+//       Access: Private
+//  Description: Adds the back pointers for the kinds of morphs we
+//               might find in an EggAttributes object.
+////////////////////////////////////////////////////////////////////
+void EggCharacterCollection::
+add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
+			int model_index, EggCharacterData *char_data) {
+  EggMorphNormalList::const_iterator mni;
+  for (mni = attrib->_dnormals.begin(); 
+       mni != attrib->_dnormals.end();
+       ++mni) {
+    const EggMorphNormal &morph = (*mni);
+    char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
+  }
+  
+  EggMorphTexCoordList::const_iterator mti;
+  for (mti = attrib->_duvs.begin(); 
+       mti != attrib->_duvs.end(); 
+       ++mti) {
+    const EggMorphTexCoord &morph = (*mti);
+    char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
+  }
+
+  EggMorphColorList::const_iterator mci;
+  for (mci = attrib->_drgbas.begin(); 
+       mci != attrib->_drgbas.end();
+       ++mci) {
+    const EggMorphColor &morph = (*mci);
+    char_data->make_slider(morph.get_name())->add_back_pointer(model_index, egg_object);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterCollection::match_egg_nodes
 //       Access: Private
 //       Access: Private
 //  Description: Attempts to match up the indicated list of egg_nodes
 //  Description: Attempts to match up the indicated list of egg_nodes
 //               with the children of the given joint_data, by name if
 //               with the children of the given joint_data, by name if
@@ -248,9 +419,9 @@ scan_for_top_tables(EggTable *bundle, EggNode *model_root,
 //               Also recurses on each matched joint to build up the
 //               Also recurses on each matched joint to build up the
 //               entire joint hierarchy.
 //               entire joint hierarchy.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggCharacterData::
-match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
-		int egg_index, int model_index) {
+void EggCharacterCollection::
+match_egg_nodes(EggCharacterData *char_data, EggJointData *joint_data,
+		EggNodeList &egg_nodes, int egg_index, int model_index) {
   // Sort the list of egg_nodes in order by name.  This will make the
   // Sort the list of egg_nodes in order by name.  This will make the
   // matching up by names easier and more reliable.
   // matching up by names easier and more reliable.
   sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
   sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames<Namable>());
@@ -261,9 +432,9 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
     EggNodeList::iterator ei;
     EggNodeList::iterator ei;
     for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
     for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) {
       EggNode *egg_node = (*ei);
       EggNode *egg_node = (*ei);
-      EggJointData *data = make_joint_data();
+      EggJointData *data = make_joint_data(char_data);
       joint_data->_children.push_back(data);
       joint_data->_children.push_back(data);
-      found_egg_node_match(data, egg_node, egg_index, model_index);
+      found_egg_match(char_data, data, egg_node, egg_index, model_index);
     }
     }
 
 
   } else {
   } else {
@@ -295,7 +466,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
 
 
       } else {
       } else {
 	// Hey, these two match!  Hooray!
 	// Hey, these two match!  Hooray!
-	found_egg_node_match(data, egg_node, egg_index, model_index);
+	found_egg_match(char_data, data, egg_node, egg_index, model_index);
 	++ei;
 	++ei;
 	++di;
 	++di;
       }	
       }	
@@ -335,7 +506,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
 	  EggJointData *data = (*di);
 	  EggJointData *data = (*di);
 	  if (data->matches_name(egg_node->get_name())) {
 	  if (data->matches_name(egg_node->get_name())) {
 	    matched = true;
 	    matched = true;
-	    found_egg_node_match(data, egg_node, egg_index, model_index);
+	    found_egg_match(char_data, data, egg_node, egg_index, model_index);
 	    extra_data.erase(di);
 	    extra_data.erase(di);
 	  }
 	  }
 	}
 	}
@@ -357,7 +528,7 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
 	for (i = 0; i < extra_egg_nodes.size(); i++) {
 	for (i = 0; i < extra_egg_nodes.size(); i++) {
 	  EggNode *egg_node = extra_egg_nodes[i];
 	  EggNode *egg_node = extra_egg_nodes[i];
 	  EggJointData *data = extra_data[i];
 	  EggJointData *data = extra_data[i];
-	  found_egg_node_match(data, egg_node, egg_index, model_index);
+	  found_egg_match(char_data, data, egg_node, egg_index, model_index);
 	}
 	}
 
 
       } else {
       } else {
@@ -365,9 +536,9 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
 	EggNodeList::iterator ei;
 	EggNodeList::iterator ei;
 	for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
 	for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) {
 	  EggNode *egg_node = (*ei);
 	  EggNode *egg_node = (*ei);
-	  EggJointData *data = make_joint_data();
+	  EggJointData *data = make_joint_data(char_data);
 	  joint_data->_children.push_back(data);
 	  joint_data->_children.push_back(data);
-	  found_egg_node_match(data, egg_node, egg_index, model_index);
+	  found_egg_match(char_data, data, egg_node, egg_index, model_index);
 	}
 	}
       }
       }
     }
     }
@@ -380,16 +551,19 @@ match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::found_egg_node_match
+//     Function: EggCharacterCollection::found_egg_match
 //       Access: Private
 //       Access: Private
 //  Description: Marks a one-to-one association between the indicated
 //  Description: Marks a one-to-one association between the indicated
 //               EggJointData and the indicated EggNode, and then
 //               EggJointData and the indicated EggNode, and then
 //               recurses below.
 //               recurses below.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggCharacterData::
-found_egg_node_match(EggJointData *data, EggNode *egg_node,
-		     int egg_index, int model_index) {
-  data->add_egg_node(egg_index, model_index, egg_node);
+void EggCharacterCollection::
+found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
+		EggNode *egg_node, int egg_index, int model_index) {
+  if (egg_node->has_name()) {
+    joint_data->add_name(egg_node->get_name());
+  }
+  joint_data->add_back_pointer(model_index, egg_node);
 
 
   if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
   if (egg_node->is_of_type(EggGroupNode::get_class_type())) {
     EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
     EggGroupNode *group_node = DCAST(EggGroupNode, egg_node);
@@ -429,24 +603,23 @@ found_egg_node_match(EggJointData *data, EggNode *egg_node,
     }
     }
 
 
     if (!egg_nodes.empty()) {
     if (!egg_nodes.empty()) {
-      match_egg_nodes(data, egg_nodes, egg_index, model_index);
+      match_egg_nodes(char_data, joint_data, egg_nodes, 
+		      egg_index, model_index);
     }
     }
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterData::write
+//     Function: EggCharacterCollection::write
 //       Access: Public, Virtual
 //       Access: Public, Virtual
 //  Description: 
 //  Description: 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-void EggCharacterData::
+void EggCharacterCollection::
 write(ostream &out, int indent_level) const {
 write(ostream &out, int indent_level) const {
   Characters::const_iterator ci;
   Characters::const_iterator ci;
 
 
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
   for (ci = _characters.begin(); ci != _characters.end(); ++ci) {
-    const CharacterInfo &character_info = (*ci);
-    indent(out, indent_level)
-      << "Character " << character_info._name << ":\n";
-    character_info._root_joint->write(out, indent_level + 2);
+    EggCharacterData *char_data = (*ci);
+    char_data->write(out, indent_level);
   }
   }
 }
 }

+ 93 - 0
pandatool/src/eggcharbase/eggCharacterCollection.h

@@ -0,0 +1,93 @@
+// Filename: eggCharacterCollection.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGCHARACTERCOLLECTION_H
+#define EGGCHARACTERCOLLECTION_H
+
+#include <pandatoolbase.h>
+
+#include "eggCharacterData.h"
+
+#include <eggData.h>
+#include <eggNode.h>
+#include <pointerTo.h>
+
+class EggTable;
+class EggAttributes;
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggCharacterCollection
+// Description : Represents a set of characters, as read and collected
+//               from possibly several model and/or animation egg
+//               files.
+////////////////////////////////////////////////////////////////////
+class EggCharacterCollection {
+public:
+  EggCharacterCollection();
+  virtual ~EggCharacterCollection();
+
+  bool add_egg(EggData *egg);
+
+  INLINE int get_num_eggs() const;
+  INLINE EggData *get_egg(int i) const;
+
+  INLINE int get_num_characters() const;
+  INLINE EggCharacterData *get_character(int i) const;
+  EggCharacterData *get_character_by_name(const string &character_name) const;
+
+  virtual void write(ostream &out, int indent_level = 0) const;
+
+  virtual EggCharacterData *make_character_data();
+  virtual EggJointData *make_joint_data(EggCharacterData *char_data);
+  virtual EggSliderData *make_slider_data(EggCharacterData *char_data);
+
+public:
+  EggCharacterData *make_character(const string &character_name);
+
+  class EggInfo {
+  public:
+    PT(EggData) _egg;
+    typedef vector<PT(EggNode)> Models;
+    Models _models;
+  };
+  
+  typedef vector<EggInfo> Eggs;
+  Eggs _eggs;
+
+  typedef vector<EggCharacterData *> Characters;
+  Characters _characters;
+
+private:
+  bool scan_hierarchy(EggNode *egg_node);
+  void scan_for_top_joints(EggNode *egg_node, EggNode *model_root,
+			   const string &character_name);
+  void scan_for_top_tables(EggTable *bundle, EggNode *model_root,
+			   const string &character_name);
+  void scan_for_morphs(EggNode *egg_node, int model_index,
+		       EggCharacterData *char_data);
+  void scan_for_sliders(EggNode *egg_node, int model_index,
+			EggCharacterData *char_data);
+
+  void add_morph_back_pointers(EggAttributes *attrib, EggObject *egg_object,
+			       int model_index, EggCharacterData *char_data);
+
+  typedef vector<EggNode *> EggNodeList;
+  typedef map<EggNode *, EggNodeList> TopEggNodes;
+  typedef map<string, TopEggNodes> TopEggNodesByName;
+  TopEggNodesByName _top_egg_nodes;
+
+  int _next_model_index;
+
+  void match_egg_nodes(EggCharacterData *char_Data, EggJointData *joint_data,
+		       EggNodeList &egg_nodes, int egg_index, int model_index);
+  void found_egg_match(EggCharacterData *char_data, EggJointData *joint_data,
+		       EggNode *egg_node, int egg_index, int model_index);
+};
+
+#include "eggCharacterCollection.I"
+
+#endif
+
+

+ 20 - 0
pandatool/src/eggcharbase/eggCharacterData.I

@@ -0,0 +1,20 @@
+// Filename: eggCharacterData.I
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::get_root_joint
+//       Access: Public
+//  Description: Returns the root joint of the character hierarchy.
+//               This root joint does not represent an actual joint in
+//               the hierarchy, but instead is a fictitious joint that
+//               is the parent of all the top joints in the hierarchy
+//               (since the hierarchy may actually contain zero or
+//               more top joints).
+////////////////////////////////////////////////////////////////////
+INLINE EggJointData *EggCharacterData::
+get_root_joint() const {
+  return _root_joint;
+}

+ 76 - 0
pandatool/src/eggcharbase/eggCharacterData.cxx

@@ -0,0 +1,76 @@
+// Filename: eggCharacterData.cxx
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggCharacterData.h"
+#include "eggCharacterCollection.h"
+#include "eggJointData.h"
+#include "eggSliderData.h"
+
+#include <indent.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggCharacterData::
+EggCharacterData(EggCharacterCollection *collection) {
+  _collection = collection;
+  _root_joint = _collection->make_joint_data(this);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggCharacterData::
+~EggCharacterData() {
+  delete _root_joint;
+
+  Sliders::iterator si;
+  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
+    EggSliderData *slider = (*si).second;
+    delete slider;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::make_slider
+//       Access: Public
+//  Description: Returns the slider matching the indicated name.  If
+//               no such slider exists already, creates a new one.
+////////////////////////////////////////////////////////////////////
+EggSliderData *EggCharacterData::
+make_slider(const string &name) {
+  Sliders::iterator si;
+  si = _sliders.find(name);
+  if (si != _sliders.end()) {
+    return (*si).second;
+  }
+
+  EggSliderData *slider = _collection->make_slider_data(this);
+  slider->set_name(name);
+  _sliders.insert(Sliders::value_type(name, slider));
+  return slider;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggCharacterData::write
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void EggCharacterData::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level)
+    << "Character " << get_name() << ":\n";
+  get_root_joint()->write(out, indent_level + 2);
+
+  Sliders::const_iterator si;
+  for (si = _sliders.begin(); si != _sliders.end(); ++si) {
+    EggSliderData *slider = (*si).second;
+    slider->write(out, indent_level + 2);
+  }
+}

+ 66 - 0
pandatool/src/eggcharbase/eggCharacterData.h

@@ -0,0 +1,66 @@
+// Filename: eggCharacterData.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGCHARACTERDATA_H
+#define EGGCHARACTERDATA_H
+
+#include <pandatoolbase.h>
+
+#include <namable.h>
+
+#include <map>
+
+class EggCharacterCollection;
+class EggJointData;
+class EggSliderData;
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggCharacterData
+// Description : Represents a single character, as read and collected
+//               from several models and animation files.  This
+//               contains a hierarchy of EggJointData nodes
+//               representing the skeleton, as well as a list of
+//               EggSliderData nodes representing the morph channels
+//               for the character.
+//
+//               This is very similar to the Character class from
+//               Panda, in that it's capable of associating
+//               skeleton-morph animation channels with models and
+//               calculating the vertex position for each frame.  To
+//               some degree, it duplicates the functionality of
+//               Character.  However, it differs in one fundamental
+//               principle: it is designed to be a non-real-time
+//               operation, working directly on the Egg structures as
+//               they are, instead of first boiling the Egg data into
+//               native Panda Geom tables for real-time animation.
+//               Because of this, it is (a) double-precision instead
+//               of single precision, (b) capable of generating
+//               modified Egg files, and (c) about a hundred times
+//               slower than the Panda Character class.
+////////////////////////////////////////////////////////////////////
+class EggCharacterData : public Namable {
+public:
+  EggCharacterData(EggCharacterCollection *collection);
+  virtual ~EggCharacterData();
+
+  INLINE EggJointData *get_root_joint() const;
+
+  EggSliderData *make_slider(const string &name);
+
+  virtual void write(ostream &out, int indent_level = 0) const;
+
+protected:
+  EggCharacterCollection *_collection;
+  EggJointData *_root_joint;
+
+  typedef map<string, EggSliderData *> Sliders;
+  Sliders _sliders;
+};
+
+#include "eggCharacterData.I"
+
+#endif
+
+

+ 17 - 16
pandatool/src/eggbase/eggCharacterFilter.cxx → pandatool/src/eggcharbase/eggCharacterFilter.cxx

@@ -4,7 +4,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "eggCharacterFilter.h"
 #include "eggCharacterFilter.h"
-#include "eggCharacterData.h"
+#include "eggCharacterCollection.h"
 
 
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -14,7 +14,7 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 EggCharacterFilter::
 EggCharacterFilter::
 EggCharacterFilter() : EggMultiFilter(false) {
 EggCharacterFilter() : EggMultiFilter(false) {
-  _character_data = (EggCharacterData *)NULL;
+  _collection = (EggCharacterCollection *)NULL;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -24,8 +24,8 @@ EggCharacterFilter() : EggMultiFilter(false) {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 EggCharacterFilter::
 EggCharacterFilter::
 ~EggCharacterFilter() {
 ~EggCharacterFilter() {
-  if (_character_data != (EggCharacterData *)NULL) {
-    delete _character_data;
+  if (_collection != (EggCharacterCollection *)NULL) {
+    delete _collection;
   }
   }
 }
 }
 
 
@@ -37,8 +37,8 @@ EggCharacterFilter::
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool EggCharacterFilter::
 bool EggCharacterFilter::
 post_command_line() {
 post_command_line() {
-  if (_character_data == (EggCharacterData *)NULL) {
-    _character_data = make_character_data();
+  if (_collection == (EggCharacterCollection *)NULL) {
+    _collection = make_collection();
   }
   }
 
 
   if (!EggMultiFilter::post_command_line()) {
   if (!EggMultiFilter::post_command_line()) {
@@ -49,27 +49,28 @@ post_command_line() {
   for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
   for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) {
     EggData *data = (*ei);
     EggData *data = (*ei);
     
     
-    if (!_character_data->add_egg(data)) {
+    if (!_collection->add_egg(data)) {
       nout << data->get_egg_filename().get_basename()
       nout << data->get_egg_filename().get_basename()
 	   << " does not contain a character model or animation channel.\n";
 	   << " does not contain a character model or animation channel.\n";
       return false;
       return false;
     }
     }
   }
   }
 
 
-  _character_data->write(cerr);
+  _collection->write(cerr);
 
 
   return true;
   return true;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: EggCharacterFilter::make_character_data
+//     Function: EggCharacterFilter::make_collection
 //       Access: Protected, Virtual
 //       Access: Protected, Virtual
-//  Description: Allocates and returns a new EggCharacterData structure.
-//               This is primarily intended as a hook so derived
-//               classes can customize the type of EggCharacterData nodes
-//               used to represent the character information.
+//  Description: Allocates and returns a new EggCharacterCollection
+//               structure.  This is primarily intended as a hook so
+//               derived classes can customize the type of
+//               EggCharacterCollection object used to represent the
+//               character information.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-EggCharacterData *EggCharacterFilter::
-make_character_data() {
-  return new EggCharacterData;
+EggCharacterCollection *EggCharacterFilter::
+make_collection() {
+  return new EggCharacterCollection;
 }
 }

+ 3 - 2
pandatool/src/eggbase/eggCharacterFilter.h → pandatool/src/eggcharbase/eggCharacterFilter.h

@@ -11,6 +11,7 @@
 #include "eggMultiFilter.h"
 #include "eggMultiFilter.h"
 
 
 class EggCharacterData;
 class EggCharacterData;
+class EggCharacterCollection;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : EggCharacterFilter
 // 	 Class : EggCharacterFilter
@@ -31,9 +32,9 @@ public:
 protected:
 protected:
   virtual bool post_command_line();
   virtual bool post_command_line();
 
 
-  virtual EggCharacterData *make_character_data();
+  virtual EggCharacterCollection *make_collection();
 
 
-  EggCharacterData *_character_data;
+  EggCharacterCollection *_collection;
 };
 };
 
 
 #endif
 #endif

+ 49 - 0
pandatool/src/eggcharbase/eggComponentData.I

@@ -0,0 +1,49 @@
+// Filename: eggComponentData.I
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::get_num_back_pointers
+//       Access: Public
+//  Description: Returns the maximum number of back pointers this
+//               component may have.  The component may store a back
+//               pointer for models indexed 0 .. num_back_pointers -
+//               1.  You must call has_back_pointer() on each model
+//               index to confirm whether a particular model in that
+//               range has a back pointer.
+////////////////////////////////////////////////////////////////////
+INLINE int EggComponentData::
+get_num_back_pointers() const {
+  return _back_pointers.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::has_back_pointer
+//       Access: Public
+//  Description: Returns true if the component has a back pointer to
+//               an egg file somewhere for the indicated model, false
+//               otherwise.
+////////////////////////////////////////////////////////////////////
+INLINE bool EggComponentData::
+has_back_pointer(int model_index) const {
+  if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
+    return _back_pointers[model_index] != (EggBackPointer *)NULL;
+  }
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::get_back_pointer
+//       Access: Public
+//  Description: Returns the back pointer to an egg file for the
+//               indicated model if it exists, or NULL if it does not.
+////////////////////////////////////////////////////////////////////
+INLINE EggBackPointer *EggComponentData::
+get_back_pointer(int model_index) const {
+  if (model_index >= 0 && model_index < (int)_back_pointers.size()) {
+    return _back_pointers[model_index];
+  }
+  return (EggBackPointer *)NULL;
+}

+ 87 - 0
pandatool/src/eggcharbase/eggComponentData.cxx

@@ -0,0 +1,87 @@
+// Filename: eggComponentData.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggComponentData.h"
+#include "eggBackPointer.h"
+
+#include <indent.h>
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggComponentData::
+EggComponentData(EggCharacterCollection *collection, 
+		 EggCharacterData *char_data) :
+  _collection(collection),
+  _char_data(char_data)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::Destructor
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggComponentData::
+~EggComponentData() {
+  BackPointers::iterator bpi;
+  for (bpi = _back_pointers.begin(); bpi != _back_pointers.end(); ++bpi) {
+    EggBackPointer *back = (*bpi);
+    if (back != (EggBackPointer *)NULL) {
+      delete back;
+    }
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::add_name
+//       Access: Public
+//  Description: Adds the indicated name to the set of names that this
+//               component can be identified with.  If this is the
+//               first name added, it becomes the primary name of the
+//               component; later names added do not replace the
+//               primary name, but do get added to the list of names
+//               that will be accepted by matched_name().
+////////////////////////////////////////////////////////////////////
+void EggComponentData::
+add_name(const string &name) {
+  if (!has_name()) {
+    set_name(name);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::matches_name
+//       Access: Public
+//  Description: Returns true if the indicated name matches any name
+//               that was ever matched with this particular joint,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool EggComponentData::
+matches_name(const string &name) const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggComponentData::set_back_pointer
+//       Access: Public
+//  Description: Sets the back_pointer associated with the given
+//               model_index.
+////////////////////////////////////////////////////////////////////
+void EggComponentData::
+set_back_pointer(int model_index, EggBackPointer *back) {
+  while ((int)_back_pointers.size() <= model_index) {
+    _back_pointers.push_back((EggBackPointer *)NULL);
+  }
+
+  if (_back_pointers[model_index] != (EggBackPointer *)NULL) {
+    nout << "Warning: deleting old back pointer.\n";
+    delete _back_pointers[model_index];
+  }
+  _back_pointers[model_index] = back;
+}

+ 59 - 0
pandatool/src/eggcharbase/eggComponentData.h

@@ -0,0 +1,59 @@
+// Filename: eggComponentData.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGCOMPONENTDATA_H
+#define EGGCOMPONENTDATA_H
+
+#include <pandatoolbase.h>
+
+#include <namable.h>
+
+class EggCharacterCollection;
+class EggCharacterData;
+class EggBackPointer;
+class EggObject;
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggComponentData
+// Description : This is the base class of both EggJointData and
+//               EggSliderData.  It represents a single component of a
+//               character, either a joint or a slider, along with
+//               back pointers to the references to this component in
+//               all model and animation egg files read.
+////////////////////////////////////////////////////////////////////
+class EggComponentData : public Namable {
+public:
+  EggComponentData(EggCharacterCollection *collection,
+		   EggCharacterData *char_data);
+  virtual ~EggComponentData();
+
+  void add_name(const string &name);
+  bool matches_name(const string &name) const;
+
+  virtual void add_back_pointer(int model_index, EggObject *egg_object)=0;
+  virtual void write(ostream &out, int indent_level = 0) const=0;
+
+  INLINE int get_num_back_pointers() const;
+  INLINE bool has_back_pointer(int model_index) const;
+  INLINE EggBackPointer *get_back_pointer(int model_index) const;
+  void set_back_pointer(int model_index, EggBackPointer *back);
+
+protected:
+
+  // This points back to all the egg structures that reference this
+  // particular table or slider.
+  typedef vector<EggBackPointer *> BackPointers;
+  BackPointers _back_pointers;
+
+
+  EggCharacterCollection *_collection;
+  EggCharacterData *_char_data;
+};
+
+#include "eggComponentData.I"
+
+#endif
+
+

+ 0 - 0
pandatool/src/eggbase/eggJointData.I → pandatool/src/eggcharbase/eggJointData.I


+ 74 - 0
pandatool/src/eggcharbase/eggJointData.cxx

@@ -0,0 +1,74 @@
+// Filename: eggJointData.cxx
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggJointData.h"
+#include "eggJointPointer.h"
+#include "eggMatrixTablePointer.h"
+
+#include <eggGroup.h>
+#include <eggTable.h>
+#include <indent.h>
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointData::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggJointData::
+EggJointData(EggCharacterCollection *collection, 
+	     EggCharacterData *char_data) :
+  EggComponentData(collection, char_data)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointData::add_back_pointer
+//       Access: Public, Virtual
+//  Description: Adds the indicated model joint or anim table to the
+//               data.
+////////////////////////////////////////////////////////////////////
+void EggJointData::
+add_back_pointer(int model_index, EggObject *egg_object) {
+  if (egg_object->is_of_type(EggGroup::get_class_type())) {
+    // It must be a <Joint>.
+    EggJointPointer *joint = new EggJointPointer(egg_object);
+    set_back_pointer(model_index, joint);
+
+  } else if (egg_object->is_of_type(EggTable::get_class_type())) {
+    // It's a <Table> with an "xform" child beneath it.
+    EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object);
+    set_back_pointer(model_index, xform);
+
+  } else {
+    nout << "Invalid object added to joint for back pointer.\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointData::write
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void EggJointData::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level)
+    << "Joint " << get_name()
+    << " (models:";
+  int num_back_pointers = get_num_back_pointers();
+  for (int model_index = 0; model_index < num_back_pointers; model_index++) {
+    if (has_back_pointer(model_index)) {
+      out << " " << model_index;
+    }
+  }
+  out << ") {\n";
+
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    (*ci)->write(out, indent_level + 2);
+  }
+
+  indent(out, indent_level) << "}\n";
+}

+ 6 - 28
pandatool/src/eggbase/eggJointData.h → pandatool/src/eggcharbase/eggJointData.h

@@ -8,11 +8,7 @@
 
 
 #include <pandatoolbase.h>
 #include <pandatoolbase.h>
 
 
-#include <eggNode.h>
-#include <pointerTo.h>
-#include <namable.h>
-
-class EggGroup;
+#include "eggComponentData.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : EggJointData
 // 	 Class : EggJointData
@@ -22,42 +18,24 @@ class EggGroup;
 //               various models, the LOD's of each model, and the
 //               various models, the LOD's of each model, and the
 //               various animation channel files.
 //               various animation channel files.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-class EggJointData : public Namable {
+class EggJointData : public EggComponentData {
 public:
 public:
-  EggJointData();
-  virtual ~EggJointData();
+  EggJointData(EggCharacterCollection *collection,
+	       EggCharacterData *char_data);
 
 
   INLINE int get_num_children() const;
   INLINE int get_num_children() const;
   INLINE EggJointData *get_child(int n) const;
   INLINE EggJointData *get_child(int n) const;
 
 
-  bool matches_name(const string &name) const;
-  void add_egg_node(int egg_index, int model_index, EggNode *egg_node);
-
+  virtual void add_back_pointer(int model_index, EggObject *egg_object);
   virtual void write(ostream &out, int indent_level = 0) const;
   virtual void write(ostream &out, int indent_level = 0) const;
 
 
 protected:
 protected:
-  typedef vector<PT(EggNode)> JointNodes;
-  typedef vector<JointNodes> Joints;
-
-  Joints _tables;
-  // _tables[i][anim] is the table for the animth bundle of the ith
-  // file.
-
-  Joints _joints;
-  // _joints[i][model] is the joint for the modelth lod of the ith
-  // file.
-
-  LMatrix4d _rest_transform;
-  LMatrix4d _net_rest_transform;
-
   typedef vector<EggJointData *> Children;
   typedef vector<EggJointData *> Children;
   Children _children;
   Children _children;
 
 
-  friend class EggCharacterData;
+  friend class EggCharacterCollection;
 };
 };
 
 
 #include "eggJointData.I"
 #include "eggJointData.I"
 
 
 #endif
 #endif
-
-

+ 19 - 0
pandatool/src/eggcharbase/eggJointPointer.cxx

@@ -0,0 +1,19 @@
+// Filename: eggJointPointer.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggJointPointer.h"
+
+
+TypeHandle EggJointPointer::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggJointPointer::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggJointPointer::
+EggJointPointer(EggObject *object) {
+  _joint = DCAST(EggGroup, object);
+}

+ 47 - 0
pandatool/src/eggcharbase/eggJointPointer.h

@@ -0,0 +1,47 @@
+// Filename: eggJointPointer.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGJOINTPOINTER_H
+#define EGGJOINTPOINTER_H
+
+#include <pandatoolbase.h>
+
+#include "eggBackPointer.h"
+
+#include <eggGroup.h>
+#include <pointerTo.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggJointPointer
+// Description : This stores a pointer back to a <Joint> node.
+////////////////////////////////////////////////////////////////////
+class EggJointPointer : public EggBackPointer {
+public:
+  EggJointPointer(EggObject *object);
+
+private:
+  PT(EggGroup) _joint;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggBackPointer::init_type();
+    register_type(_type_handle, "EggJointPointer",
+		  EggBackPointer::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+ 
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+
+

+ 45 - 0
pandatool/src/eggcharbase/eggMatrixTablePointer.cxx

@@ -0,0 +1,45 @@
+// Filename: eggMatrixTablePointer.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggMatrixTablePointer.h"
+
+#include <eggXfmAnimData.h>
+#include <eggXfmSAnim.h>
+
+TypeHandle EggMatrixTablePointer::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggMatrixTablePointer::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggMatrixTablePointer::
+EggMatrixTablePointer(EggObject *object) {
+  _table = DCAST(EggTable, object);
+
+  if (_table != (EggTable *)NULL) {
+    // Now search for the child named "xform".  This contains the
+    // actual table data.
+    EggGroupNode::iterator ci;
+    bool found = false;
+    for (ci = _table->begin(); ci != _table->end() && !found; ++ci) {
+      EggNode *child = (*ci);
+      if (child->get_name() == "xform") {
+	if (child->is_of_type(EggXfmSAnim::get_class_type())) {
+	  _xform = DCAST(EggXfmSAnim, child);
+	  found = true;
+
+	} else if (child->is_of_type(EggXfmAnimData::get_class_type())) {
+	  // Quietly replace old-style XfmAnim tables with new-style
+	  // XfmSAnim tables.
+	  PT(EggXfmAnimData) anim = DCAST(EggXfmAnimData, child);
+	  _xform = new EggXfmSAnim(*anim);
+	  _table->replace(ci, _xform.p());
+	  found = true;
+	}
+      }
+    }
+  }
+}

+ 52 - 0
pandatool/src/eggcharbase/eggMatrixTablePointer.h

@@ -0,0 +1,52 @@
+// Filename: eggMatrixTablePointer.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGMATRIXTABLEPOINTER_H
+#define EGGMATRIXTABLEPOINTER_H
+
+#include <pandatoolbase.h>
+
+#include "eggBackPointer.h"
+
+#include <eggTable.h>
+#include <eggXfmSAnim.h>
+#include <pointerTo.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggMatrixTablePointer
+// Description : This stores a pointer back to an EggXfmSAnim table
+//               (i.e. an <Xfm$Anim_S$> entry in an egg file),
+//               corresponding to the animation data from a single
+//               bundle for this joint.
+////////////////////////////////////////////////////////////////////
+class EggMatrixTablePointer : public EggBackPointer {
+public:
+  EggMatrixTablePointer(EggObject *object);
+
+private:
+  PT(EggTable) _table;
+  PT(EggXfmSAnim) _xform;
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggBackPointer::init_type();
+    register_type(_type_handle, "EggMatrixTablePointer",
+		  EggBackPointer::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+ 
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+
+

+ 4 - 0
pandatool/src/eggcharbase/eggSliderData.I

@@ -0,0 +1,4 @@
+// Filename: eggSliderData.I
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////

+ 80 - 0
pandatool/src/eggcharbase/eggSliderData.cxx

@@ -0,0 +1,80 @@
+// Filename: eggSliderData.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggSliderData.h"
+#include "eggVertexPointer.h"
+
+#include <eggPrimitive.h>
+#include <eggVertex.h>
+#include <eggSAnimData.h>
+#include <indent.h>
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggSliderData::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggSliderData::
+EggSliderData(EggCharacterCollection *collection, 
+	      EggCharacterData *char_data) :
+  EggComponentData(collection, char_data)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggSliderData::add_back_pointer
+//       Access: Public, Virtual
+//  Description: Adds the indicated vertex, primitive, or morph table
+//               to the data.
+////////////////////////////////////////////////////////////////////
+void EggSliderData::
+add_back_pointer(int model_index, EggObject *egg_object) {
+  if (egg_object->is_of_type(EggPrimitive::get_class_type())) {
+    // A primitive!
+    EggBackPointer *back = get_back_pointer(model_index);
+    if (back == (EggBackPointer *)NULL) {
+      back = new EggVertexPointer;
+      set_back_pointer(model_index, back);
+    }
+
+  } else if (egg_object->is_of_type(EggVertex::get_class_type())) {
+    // A vertex!
+    EggBackPointer *back = get_back_pointer(model_index);
+    if (back == (EggBackPointer *)NULL) {
+      back = new EggVertexPointer;
+      set_back_pointer(model_index, back);
+    }
+
+  } else if (egg_object->is_of_type(EggSAnimData::get_class_type())) {
+    // A slider animation table!  Woo hoo!
+    EggBackPointer *back = get_back_pointer(model_index);
+    if (back == (EggBackPointer *)NULL) {
+      back = new EggVertexPointer;
+      set_back_pointer(model_index, back);
+    }
+
+  } else {
+    nout << "Invalid object added to slider for back pointer.\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggSliderData::write
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void EggSliderData::
+write(ostream &out, int indent_level) const {
+  indent(out, indent_level)
+    << "Slider " << get_name()
+    << " (models:";
+  int num_back_pointers = get_num_back_pointers();
+  for (int model_index = 0; model_index < num_back_pointers; model_index++) {
+    if (has_back_pointer(model_index)) {
+      out << " " << model_index;
+    }
+  }
+  out << ")\n";
+}

+ 35 - 0
pandatool/src/eggcharbase/eggSliderData.h

@@ -0,0 +1,35 @@
+// Filename: eggSliderData.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGSLIDERDATA_H
+#define EGGSLIDERDATA_H
+
+#include <pandatoolbase.h>
+
+#include "eggComponentData.h"
+
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggSliderData
+// Description : This corresponds to a single morph slider control.
+//               It contains back pointers to all the vertices and
+//               primitives that reference this slider across all
+//               models, as well as all the tables in which it appears
+//               in all animation files.
+////////////////////////////////////////////////////////////////////
+class EggSliderData : public EggComponentData {
+public:
+  EggSliderData(EggCharacterCollection *collection,
+		EggCharacterData *char_data);
+
+  virtual void add_back_pointer(int model_index, EggObject *egg_object);
+  virtual void write(ostream &out, int indent_level = 0) const;
+};
+
+#include "eggSliderData.I"
+
+#endif
+
+

+ 18 - 0
pandatool/src/eggcharbase/eggVertexPointer.cxx

@@ -0,0 +1,18 @@
+// Filename: eggVertexPointer.cxx
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggVertexPointer.h"
+
+
+TypeHandle EggVertexPointer::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggVertexPointer::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+EggVertexPointer::
+EggVertexPointer() {
+}

+ 46 - 0
pandatool/src/eggcharbase/eggVertexPointer.h

@@ -0,0 +1,46 @@
+// Filename: eggVertexPointer.h
+// Created by:  drose (26Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGVERTEXPOINTER_H
+#define EGGVERTEXPOINTER_H
+
+#include <pandatoolbase.h>
+
+#include "eggBackPointer.h"
+
+#include <eggGroup.h>
+#include <pointerTo.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 Class : EggVertexPointer
+// Description : This stores a pointer back to a <Vertex>, or to a
+//               particular pritimive like a <Polygon>, representing a
+//               morph offset.
+////////////////////////////////////////////////////////////////////
+class EggVertexPointer : public EggBackPointer {
+public:
+  EggVertexPointer();
+
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    EggBackPointer::init_type();
+    register_type(_type_handle, "EggVertexPointer",
+		  EggBackPointer::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+ 
+private:
+  static TypeHandle _type_handle;
+};
+
+#endif
+
+

+ 1 - 0
pandatool/src/eggprogs/Sources.pp

@@ -22,6 +22,7 @@
 #end bin_target
 #end bin_target
 
 
 #begin noinst_bin_target
 #begin noinst_bin_target
+  #define LOCAL_LIBS eggcharbase $[LOCAL_LIBS]
   #define TARGET egg-topstrip
   #define TARGET egg-topstrip
 
 
   #define SOURCES \
   #define SOURCES \