From aa42fdae2fe862bcd5553f0c6a64706d32f53c44 Mon Sep 17 00:00:00 2001 From: David Rose Date: Tue, 27 Feb 2001 04:24:16 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/egg/eggGroupNode.cxx | 19 ++ panda/src/egg/eggGroupNode.h | 1 + panda/src/egg/eggNode.I | 13 ++ panda/src/egg/eggNode.cxx | 13 ++ panda/src/egg/eggNode.h | 2 + panda/src/egg/eggVertexPool.cxx | 14 ++ panda/src/egg/eggVertexPool.h | 1 + pandatool/src/eggcharbase/Sources.pp | 3 + .../src/eggcharbase/config_eggcharbase.cxx | 43 ++++ .../src/eggcharbase/config_eggcharbase.h | 16 ++ .../src/eggcharbase/eggCharacterCollection.I | 38 ++++ .../eggcharbase/eggCharacterCollection.cxx | 21 +- .../src/eggcharbase/eggCharacterCollection.h | 5 +- pandatool/src/eggcharbase/eggCharacterData.I | 54 +++++ .../src/eggcharbase/eggCharacterData.cxx | 15 ++ pandatool/src/eggcharbase/eggCharacterData.h | 19 +- .../src/eggcharbase/eggCharacterFilter.cxx | 4 +- pandatool/src/eggcharbase/eggComponentData.I | 16 +- .../src/eggcharbase/eggComponentData.cxx | 4 +- pandatool/src/eggcharbase/eggComponentData.h | 8 +- pandatool/src/eggcharbase/eggJointData.cxx | 37 +++- pandatool/src/eggcharbase/eggJointData.h | 1 + .../src/eggcharbase/eggJointNodePointer.cxx | 81 +++++++ .../src/eggcharbase/eggJointNodePointer.h | 51 +++++ pandatool/src/eggcharbase/eggJointPointer.cxx | 15 +- pandatool/src/eggcharbase/eggJointPointer.h | 18 +- .../src/eggcharbase/eggMatrixTablePointer.cxx | 54 +++++ .../src/eggcharbase/eggMatrixTablePointer.h | 13 +- pandatool/src/eggcharbase/eggSliderData.cxx | 18 +- pandatool/src/eggprogs/eggTopstrip.cxx | 205 ++++++++++++++++++ pandatool/src/eggprogs/eggTopstrip.h | 18 ++ pandatool/src/progbase/programBase.cxx | 36 +++ pandatool/src/progbase/programBase.h | 2 + 33 files changed, 800 insertions(+), 58 deletions(-) create mode 100644 pandatool/src/eggcharbase/config_eggcharbase.cxx create mode 100644 pandatool/src/eggcharbase/config_eggcharbase.h create mode 100644 pandatool/src/eggcharbase/eggJointNodePointer.cxx create mode 100644 pandatool/src/eggcharbase/eggJointNodePointer.h diff --git a/panda/src/egg/eggGroupNode.cxx b/panda/src/egg/eggGroupNode.cxx index 8a04c13471..29665f437f 100644 --- a/panda/src/egg/eggGroupNode.cxx +++ b/panda/src/egg/eggGroupNode.cxx @@ -653,6 +653,25 @@ r_transform(const LMatrix4d &mat, const LMatrix4d &inv, } } +//////////////////////////////////////////////////////////////////// +// Function: EggGroupNode::r_transform_vertices +// Access: Protected, Virtual +// Description: This is called from within the egg code by +// transform_vertices_only()(). It applies a +// transformation matrix to the current node in some +// sensible way (if the current node is a vertex pool +// with vertices), then continues down the tree. +//////////////////////////////////////////////////////////////////// +void EggGroupNode:: +r_transform_vertices(const LMatrix4d &mat) { + Children::iterator ci; + for (ci = _children.begin(); + ci != _children.end(); + ++ci) { + (*ci)->r_transform_vertices(mat); + } +} + //////////////////////////////////////////////////////////////////// // Function: EggGroupNode::r_mark_coordsys // Access: Protected, Virtual diff --git a/panda/src/egg/eggGroupNode.h b/panda/src/egg/eggGroupNode.h index 0927f80618..0c6a13f0ae 100644 --- a/panda/src/egg/eggGroupNode.h +++ b/panda/src/egg/eggGroupNode.h @@ -111,6 +111,7 @@ protected: virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv, CoordinateSystem to_cs); + virtual void r_transform_vertices(const LMatrix4d &mat); virtual void r_mark_coordsys(CoordinateSystem cs); virtual void r_flatten_transforms(); virtual void r_apply_texmats(EggTextureCollection &textures); diff --git a/panda/src/egg/eggNode.I b/panda/src/egg/eggNode.I index a28523c65b..7bcee61158 100644 --- a/panda/src/egg/eggNode.I +++ b/panda/src/egg/eggNode.I @@ -213,6 +213,19 @@ transform(const LMatrix4d &mat) { r_transform(mat, inv, CS_default); } +//////////////////////////////////////////////////////////////////// +// Function: EggNode::transform_vertices_only +// Access: Public +// Description: Applies the indicated transformation only to vertices +// that appear in global space within vertex pools at +// this node and below. Joints and other transforms are +// not affected, nor are local vertices. +//////////////////////////////////////////////////////////////////// +INLINE void EggNode:: +transform_vertices_only(const LMatrix4d &mat) { + r_transform_vertices(mat); +} + //////////////////////////////////////////////////////////////////// // Function: EggNode::flatten_transforms // Access: Public diff --git a/panda/src/egg/eggNode.cxx b/panda/src/egg/eggNode.cxx index 0172c6c937..e71463ac76 100644 --- a/panda/src/egg/eggNode.cxx +++ b/panda/src/egg/eggNode.cxx @@ -232,6 +232,19 @@ void EggNode:: r_transform(const LMatrix4d &, const LMatrix4d &, CoordinateSystem) { } +//////////////////////////////////////////////////////////////////// +// Function: EggNode::r_transform_vertices +// Access: Protected, Virtual +// Description: This is called from within the egg code by +// transform_vertices_only()(). It applies a +// transformation matrix to the current node in some +// sensible way (if the current node is a vertex pool +// with vertices), then continues down the tree. +//////////////////////////////////////////////////////////////////// +void EggNode:: +r_transform_vertices(const LMatrix4d &) { +} + //////////////////////////////////////////////////////////////////// // Function: EggNode::r_mark_coordsys // Access: Protected, Virtual diff --git a/panda/src/egg/eggNode.h b/panda/src/egg/eggNode.h index 9b17503a6b..5613a632ff 100644 --- a/panda/src/egg/eggNode.h +++ b/panda/src/egg/eggNode.h @@ -45,6 +45,7 @@ public: INLINE const LMatrix4d &get_vertex_to_node() const; INLINE void transform(const LMatrix4d &mat); + INLINE void transform_vertices_only(const LMatrix4d &mat); INLINE void flatten_transforms(); void apply_texmats(); @@ -75,6 +76,7 @@ protected: virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv, CoordinateSystem to_cs); + virtual void r_transform_vertices(const LMatrix4d &mat); virtual void r_mark_coordsys(CoordinateSystem cs); virtual void r_flatten_transforms(); virtual void r_apply_texmats(EggTextureCollection &textures); diff --git a/panda/src/egg/eggVertexPool.cxx b/panda/src/egg/eggVertexPool.cxx index 22daac8f4f..deed4238f9 100644 --- a/panda/src/egg/eggVertexPool.cxx +++ b/panda/src/egg/eggVertexPool.cxx @@ -404,3 +404,17 @@ void EggVertexPool:: r_transform(const LMatrix4d &mat, const LMatrix4d &, CoordinateSystem) { transform(mat); } + +//////////////////////////////////////////////////////////////////// +// Function: EggVertexPool::r_transform_vertices +// Access: Protected, Virtual +// Description: This is called from within the egg code by +// transform_vertices_only()(). It applies a +// transformation matrix to the current node in some +// sensible way (if the current node is a vertex pool +// with vertices), then continues down the tree. +//////////////////////////////////////////////////////////////////// +void EggVertexPool:: +r_transform_vertices(const LMatrix4d &mat) { + transform(mat); +} diff --git a/panda/src/egg/eggVertexPool.h b/panda/src/egg/eggVertexPool.h index 166d57a572..7247732156 100644 --- a/panda/src/egg/eggVertexPool.h +++ b/panda/src/egg/eggVertexPool.h @@ -104,6 +104,7 @@ public: protected: virtual void r_transform(const LMatrix4d &mat, const LMatrix4d &inv, CoordinateSystem to_cs); + virtual void r_transform_vertices(const LMatrix4d &mat); private: UniqueVertices _unique_vertices; diff --git a/pandatool/src/eggcharbase/Sources.pp b/pandatool/src/eggcharbase/Sources.pp index 11aa77ffe8..33756a0996 100644 --- a/pandatool/src/eggcharbase/Sources.pp +++ b/pandatool/src/eggcharbase/Sources.pp @@ -6,6 +6,7 @@ egg:c panda:m #define SOURCES \ + config_eggcharbase.cxx config_eggcharbase.h \ eggBackPointer.cxx eggBackPointer.h \ eggCharacterCollection.cxx eggCharacterCollection.h \ eggCharacterCollection.I \ @@ -14,6 +15,7 @@ eggComponentData.cxx eggComponentData.h eggComponentData.I \ eggJointData.cxx eggJointData.h eggJointData.I \ eggJointPointer.cxx eggJointPointer.h \ + eggJointNodePointer.cxx eggJointNodePointer.h \ eggMatrixTablePointer.cxx eggMatrixTablePointer.h \ eggSliderData.cxx eggSliderData.h eggSliderData.I \ eggVertexPointer.cxx eggVertexPointer.h @@ -25,6 +27,7 @@ eggComponentData.I eggComponentData.h \ eggJointData.h eggJointData.I \ eggJointPointer.h \ + eggJointNodePointer.h \ eggMatrixTablePointer.h \ eggSliderData.I eggSliderData.h \ eggVertexPointer.h diff --git a/pandatool/src/eggcharbase/config_eggcharbase.cxx b/pandatool/src/eggcharbase/config_eggcharbase.cxx new file mode 100644 index 0000000000..b16fb0ffb1 --- /dev/null +++ b/pandatool/src/eggcharbase/config_eggcharbase.cxx @@ -0,0 +1,43 @@ +// Filename: config_eggcharbase.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "config_eggcharbase.h" +#include "eggBackPointer.h" +#include "eggJointNodePointer.h" +#include "eggJointPointer.h" +#include "eggMatrixTablePointer.h" +#include "eggVertexPointer.h" + +#include + +Configure(config_eggcharbase); +NotifyCategoryDef(eggcharbase, ""); + +ConfigureFn(config_eggcharbase) { + init_libeggcharbase(); +} + +//////////////////////////////////////////////////////////////////// +// Function: init_libeggcharbase +// Description: Initializes the library. This must be called at +// least once before any of the functions or classes in +// this library can be used. Normally it will be +// called by the static initializers and need not be +// called explicitly, but special cases exist. +//////////////////////////////////////////////////////////////////// +void +init_libeggcharbase() { + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + EggBackPointer::init_type(); + EggJointNodePointer::init_type(); + EggJointPointer::init_type(); + EggMatrixTablePointer::init_type(); + EggVertexPointer::init_type(); +} diff --git a/pandatool/src/eggcharbase/config_eggcharbase.h b/pandatool/src/eggcharbase/config_eggcharbase.h new file mode 100644 index 0000000000..3145698fd4 --- /dev/null +++ b/pandatool/src/eggcharbase/config_eggcharbase.h @@ -0,0 +1,16 @@ +// Filename: config_eggcharbase.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef CONFIG_EGGCHARBASE_H +#define CONFIG_EGGCHARBASE_H + +#include +#include + +NotifyCategoryDecl(eggcharbase, EXPCL_MISC, EXPTP_MISC); + +extern void init_libeggcharbase(); + +#endif diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.I b/pandatool/src/eggcharbase/eggCharacterCollection.I index 7305e4c689..da63d5ed4e 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.I +++ b/pandatool/src/eggcharbase/eggCharacterCollection.I @@ -26,6 +26,44 @@ get_egg(int i) const { return _eggs[i]._egg; } +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_first_model_index +// Access: Public +// Description: Returns the first model index associated with the +// indicated egg file. An egg file may contain multiple +// models, which will be consecutive integers beginning +// at get_first_model_index() and continuing for +// get_num_models(). +// +// Each "model" corresponds to a single character model, +// or one LOD of a multiple-LOD model, or a single +// animation bundle. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterCollection:: +get_first_model_index(int egg_index) const { + nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0); + return _eggs[egg_index]._first_model_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterCollection::get_num_models +// Access: Public +// Description: Returns the number of different models found in the +// indicated egg file. An egg file may contain multiple +// models, which will be consecutive integers beginning +// at get_first_model_index() and continuing for +// get_num_models(). +// +// Each "model" corresponds to a single character model, +// or one LOD of a multiple-LOD model, or a single +// animation bundle. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterCollection:: +get_num_models(int egg_index) const { + nassertr(egg_index >= 0 && egg_index < (int)_eggs.size(), 0); + return _eggs[egg_index]._models.size(); +} + //////////////////////////////////////////////////////////////////// // Function: EggCharacterCollection::get_num_characters // Access: Public diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.cxx b/pandatool/src/eggcharbase/eggCharacterCollection.cxx index 9febd19d98..c07a4a7e35 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.cxx +++ b/pandatool/src/eggcharbase/eggCharacterCollection.cxx @@ -49,25 +49,28 @@ EggCharacterCollection:: // Access: Public // Description: Adds a new egg file to the list of models and // animation files for this particular character. -// Returns true if the file is successfully added, or -// false if there is some problem (for instance, it does -// not contain a character model or animation table). +// +// Returns the new egg_index if the file is successfully +// added, or -1 if there is some problem (for instance, +// it does not contain a character model or animation +// table). // // If the joint hierarchy does not match the existing // joint hierarchy, a best match is attempted. //////////////////////////////////////////////////////////////////// -bool EggCharacterCollection:: +int EggCharacterCollection:: add_egg(EggData *egg) { _top_egg_nodes.clear(); if (!scan_hierarchy(egg)) { - return false; + return -1; } int egg_index = _eggs.size(); _eggs.push_back(EggInfo()); EggInfo &egg_info = _eggs.back(); egg_info._egg = egg; + egg_info._first_model_index = 0; // Now, for each model, add an entry in the egg_info and match the // joint hierarchy to the known joints. @@ -84,7 +87,13 @@ add_egg(EggData *egg) { EggNodeList &egg_nodes = (*ti).second; int model_index = _next_model_index++; + if (egg_info._models.empty()) { + egg_info._first_model_index = model_index; + } egg_info._models.push_back(model_root); + + char_data->add_model(model_index, model_root); + match_egg_nodes(char_data, root_joint, egg_nodes, egg_index, model_index); @@ -93,7 +102,7 @@ add_egg(EggData *egg) { } } - return true; + return egg_index; } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/eggcharbase/eggCharacterCollection.h b/pandatool/src/eggcharbase/eggCharacterCollection.h index 11b2946972..4a00cebf63 100644 --- a/pandatool/src/eggcharbase/eggCharacterCollection.h +++ b/pandatool/src/eggcharbase/eggCharacterCollection.h @@ -28,10 +28,12 @@ public: EggCharacterCollection(); virtual ~EggCharacterCollection(); - bool add_egg(EggData *egg); + int add_egg(EggData *egg); INLINE int get_num_eggs() const; INLINE EggData *get_egg(int i) const; + INLINE int get_first_model_index(int egg_index) const; + INLINE int get_num_models(int egg_index) const; INLINE int get_num_characters() const; INLINE EggCharacterData *get_character(int i) const; @@ -51,6 +53,7 @@ public: PT(EggData) _egg; typedef vector Models; Models _models; + int _first_model_index; }; typedef vector Eggs; diff --git a/pandatool/src/eggcharbase/eggCharacterData.I b/pandatool/src/eggcharbase/eggCharacterData.I index 3cfc23b2ad..92d06f52d0 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.I +++ b/pandatool/src/eggcharbase/eggCharacterData.I @@ -4,6 +4,49 @@ //////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_num_models +// Access: Public +// Description: Returns the total number of models associated with +// this character. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterData:: +get_num_models() const { + return _models.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_model_index +// Access: Public +// Description: Returns the model_index of the nth model associated +// with this character. This model_index may be used to +// ask questions about the particular model from the +// EggCharacterCollection object, or from the individual +// EggJointData and EggSliderData objects. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterData:: +get_model_index(int n) const { + nassertr(n >= 0 && n < (int)_models.size(), 0); + return _models[n]._model_index; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_model_root +// Access: Public +// Description: Returns the model_root of the nth model associated +// with this character. +// +// This is the node at which the character, animation +// bundle, or LOD officially began within its particular +// egg file. +//////////////////////////////////////////////////////////////////// +INLINE EggNode *EggCharacterData:: +get_model_root(int n) const { + nassertr(n >= 0 && n < (int)_models.size(), (EggNode *)NULL); + return _models[n]._model_root; +} + //////////////////////////////////////////////////////////////////// // Function: EggCharacterData::get_root_joint // Access: Public @@ -18,3 +61,14 @@ INLINE EggJointData *EggCharacterData:: get_root_joint() const { return _root_joint; } + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::find_joint +// Access: Public +// Description: Returns the first joint found with the indicated +// name, or NULL if no joint has that name. +//////////////////////////////////////////////////////////////////// +INLINE EggJointData *EggCharacterData:: +find_joint(const string &name) const { + return _root_joint->find_joint(name); +} diff --git a/pandatool/src/eggcharbase/eggCharacterData.cxx b/pandatool/src/eggcharbase/eggCharacterData.cxx index edb5cc33c0..24601e93f5 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.cxx +++ b/pandatool/src/eggcharbase/eggCharacterData.cxx @@ -37,6 +37,21 @@ EggCharacterData:: } } +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::add_model +// Access: Public +// Description: Indicates that the given model_index (with the +// indicated model_root) is associated with this +// character. +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +add_model(int model_index, EggNode *model_root) { + Model m; + m._model_index = model_index; + m._model_root = model_root; + _models.push_back(m); +} + //////////////////////////////////////////////////////////////////// // Function: EggCharacterData::make_slider // Access: Public diff --git a/pandatool/src/eggcharbase/eggCharacterData.h b/pandatool/src/eggcharbase/eggCharacterData.h index d9194d29cf..62076932f1 100644 --- a/pandatool/src/eggcharbase/eggCharacterData.h +++ b/pandatool/src/eggcharbase/eggCharacterData.h @@ -8,12 +8,15 @@ #include +#include "eggJointData.h" + +#include +#include #include #include class EggCharacterCollection; -class EggJointData; class EggSliderData; //////////////////////////////////////////////////////////////////// @@ -45,13 +48,27 @@ public: EggCharacterData(EggCharacterCollection *collection); virtual ~EggCharacterData(); + void add_model(int model_index, EggNode *model_root); + INLINE int get_num_models() const; + INLINE int get_model_index(int n) const; + INLINE EggNode *get_model_root(int n) const; + INLINE EggJointData *get_root_joint() const; + INLINE EggJointData *find_joint(const string &name) const; EggSliderData *make_slider(const string &name); virtual void write(ostream &out, int indent_level = 0) const; protected: + class Model { + public: + int _model_index; + PT(EggNode) _model_root; + }; + typedef vector Models; + Models _models; + EggCharacterCollection *_collection; EggJointData *_root_joint; diff --git a/pandatool/src/eggcharbase/eggCharacterFilter.cxx b/pandatool/src/eggcharbase/eggCharacterFilter.cxx index 5006665242..b3db5384b7 100644 --- a/pandatool/src/eggcharbase/eggCharacterFilter.cxx +++ b/pandatool/src/eggcharbase/eggCharacterFilter.cxx @@ -49,15 +49,13 @@ post_command_line() { for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { EggData *data = (*ei); - if (!_collection->add_egg(data)) { + if (_collection->add_egg(data) < 0) { nout << data->get_egg_filename().get_basename() << " does not contain a character model or animation channel.\n"; return false; } } - _collection->write(cerr); - return true; } diff --git a/pandatool/src/eggcharbase/eggComponentData.I b/pandatool/src/eggcharbase/eggComponentData.I index 02d1cfb81a..a3e0947351 100644 --- a/pandatool/src/eggcharbase/eggComponentData.I +++ b/pandatool/src/eggcharbase/eggComponentData.I @@ -5,29 +5,29 @@ //////////////////////////////////////////////////////////////////// -// Function: EggComponentData::get_num_back_pointers +// Function: EggComponentData::get_num_models // 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 +// pointer for models indexed 0 .. num_models - +// 1. You must call has_model() 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 { +get_num_models() const { return _back_pointers.size(); } //////////////////////////////////////////////////////////////////// -// Function: EggComponentData::has_back_pointer +// Function: EggComponentData::has_model // 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 { +has_model(int model_index) const { if (model_index >= 0 && model_index < (int)_back_pointers.size()) { return _back_pointers[model_index] != (EggBackPointer *)NULL; } @@ -35,13 +35,13 @@ has_back_pointer(int model_index) const { } //////////////////////////////////////////////////////////////////// -// Function: EggComponentData::get_back_pointer +// Function: EggComponentData::get_model // 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 { +get_model(int model_index) const { if (model_index >= 0 && model_index < (int)_back_pointers.size()) { return _back_pointers[model_index]; } diff --git a/pandatool/src/eggcharbase/eggComponentData.cxx b/pandatool/src/eggcharbase/eggComponentData.cxx index 4aad1618ee..52becefe41 100644 --- a/pandatool/src/eggcharbase/eggComponentData.cxx +++ b/pandatool/src/eggcharbase/eggComponentData.cxx @@ -68,13 +68,13 @@ matches_name(const string &name) const { } //////////////////////////////////////////////////////////////////// -// Function: EggComponentData::set_back_pointer +// Function: EggComponentData::set_model // Access: Public // Description: Sets the back_pointer associated with the given // model_index. //////////////////////////////////////////////////////////////////// void EggComponentData:: -set_back_pointer(int model_index, EggBackPointer *back) { +set_model(int model_index, EggBackPointer *back) { while ((int)_back_pointers.size() <= model_index) { _back_pointers.push_back((EggBackPointer *)NULL); } diff --git a/pandatool/src/eggcharbase/eggComponentData.h b/pandatool/src/eggcharbase/eggComponentData.h index 791d120a02..8fb9349d0e 100644 --- a/pandatool/src/eggcharbase/eggComponentData.h +++ b/pandatool/src/eggcharbase/eggComponentData.h @@ -35,10 +35,10 @@ public: 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); + INLINE int get_num_models() const; + INLINE bool has_model(int model_index) const; + INLINE EggBackPointer *get_model(int model_index) const; + void set_model(int model_index, EggBackPointer *back); protected: diff --git a/pandatool/src/eggcharbase/eggJointData.cxx b/pandatool/src/eggcharbase/eggJointData.cxx index b422df1900..440ae526ee 100644 --- a/pandatool/src/eggcharbase/eggJointData.cxx +++ b/pandatool/src/eggcharbase/eggJointData.cxx @@ -4,7 +4,7 @@ //////////////////////////////////////////////////////////////////// #include "eggJointData.h" -#include "eggJointPointer.h" +#include "eggJointNodePointer.h" #include "eggMatrixTablePointer.h" #include @@ -24,6 +24,29 @@ EggJointData(EggCharacterCollection *collection, { } +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::find_joint +// Access: Public +// Description: Returns the first descendent joint found with the +// indicated name, or NULL if no joint has that name. +//////////////////////////////////////////////////////////////////// +INLINE EggJointData *EggJointData:: +find_joint(const string &name) { + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + EggJointData *child = (*ci); + if (child->get_name() == name) { + return child; + } + EggJointData *result = child->find_joint(name); + if (result != (EggJointData *)NULL) { + return result; + } + } + + return (EggJointData *)NULL; +} + //////////////////////////////////////////////////////////////////// // Function: EggJointData::add_back_pointer // Access: Public, Virtual @@ -34,13 +57,13 @@ 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 . - EggJointPointer *joint = new EggJointPointer(egg_object); - set_back_pointer(model_index, joint); + EggJointNodePointer *joint = new EggJointNodePointer(egg_object); + set_model(model_index, joint); } else if (egg_object->is_of_type(EggTable::get_class_type())) { // It's a with an "xform" child beneath it. EggMatrixTablePointer *xform = new EggMatrixTablePointer(egg_object); - set_back_pointer(model_index, xform); + set_model(model_index, xform); } else { nout << "Invalid object added to joint for back pointer.\n"; @@ -57,9 +80,9 @@ 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)) { + int num_models = get_num_models(); + for (int model_index = 0; model_index < num_models; model_index++) { + if (has_model(model_index)) { out << " " << model_index; } } diff --git a/pandatool/src/eggcharbase/eggJointData.h b/pandatool/src/eggcharbase/eggJointData.h index 278846eb29..eb0783058d 100644 --- a/pandatool/src/eggcharbase/eggJointData.h +++ b/pandatool/src/eggcharbase/eggJointData.h @@ -25,6 +25,7 @@ public: INLINE int get_num_children() const; INLINE EggJointData *get_child(int n) const; + EggJointData *find_joint(const string &name); virtual void add_back_pointer(int model_index, EggObject *egg_object); virtual void write(ostream &out, int indent_level = 0) const; diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.cxx b/pandatool/src/eggcharbase/eggJointNodePointer.cxx new file mode 100644 index 0000000000..015faba721 --- /dev/null +++ b/pandatool/src/eggcharbase/eggJointNodePointer.cxx @@ -0,0 +1,81 @@ +// Filename: eggJointNodePointer.cxx +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggJointNodePointer.h" + +#include +#include +#include + + +TypeHandle EggJointNodePointer::_type_handle; + +//////////////////////////////////////////////////////////////////// +// Function: EggJointNodePointer::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggJointNodePointer:: +EggJointNodePointer(EggObject *object) { + _joint = DCAST(EggGroup, object); + + if (_joint != (EggGroup *)NULL) { + // Quietly insist that the joint has a transform, for neatness. If + // it does not, give it the identity transform. + if (!_joint->has_transform()) { + _joint->set_transform(LMatrix4d::ident_mat()); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointNodePointer::get_num_frames +// Access: Public, Virtual +// Description: Returns the number of frames of animation for this +// particular joint. +// +// In the case of a EggJointNodePointer, which just +// stores a pointer to a entry for a character +// model (not an animation table), there is always +// exactly one frame: the rest pose. +//////////////////////////////////////////////////////////////////// +int EggJointNodePointer:: +get_num_frames() const { + return 1; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointNodePointer::get_frame +// Access: Public, Virtual +// Description: Returns the transform matrix corresponding to this +// joint position in the nth frame. +// +// In the case of a EggJointNodePointer, which just +// stores a pointer to a entry for a character +// model (not an animation table), there is always +// exactly one frame: the rest pose. +//////////////////////////////////////////////////////////////////// +LMatrix4d EggJointNodePointer:: +get_frame(int n) const { + nassertr(n == 0, LMatrix4d::ident_mat()); + return _joint->get_transform(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointNodePointer::set_frame +// Access: Public, Virtual +// Description: Sets the transform matrix corresponding to this +// joint position in the nth frame. +// +// In the case of a EggJointNodePointer, which just +// stores a pointer to a entry for a character +// model (not an animation table), there is always +// exactly one frame: the rest pose. +//////////////////////////////////////////////////////////////////// +void EggJointNodePointer:: +set_frame(int n, const LMatrix4d &mat) { + nassertv(n == 0); + _joint->set_transform(mat); +} diff --git a/pandatool/src/eggcharbase/eggJointNodePointer.h b/pandatool/src/eggcharbase/eggJointNodePointer.h new file mode 100644 index 0000000000..f0f2b2144c --- /dev/null +++ b/pandatool/src/eggcharbase/eggJointNodePointer.h @@ -0,0 +1,51 @@ +// Filename: eggJointNodePointer.h +// Created by: drose (26Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGJOINTNODEPOINTER_H +#define EGGJOINTNODEPOINTER_H + +#include + +#include "eggJointPointer.h" + +#include +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggJointNodePointer +// Description : This stores a pointer back to a node. +//////////////////////////////////////////////////////////////////// +class EggJointNodePointer : public EggJointPointer { +public: + EggJointNodePointer(EggObject *object); + + virtual int get_num_frames() const; + virtual LMatrix4d get_frame(int n) const; + virtual void set_frame(int n, const LMatrix4d &mat); + +private: + PT(EggGroup) _joint; + +public: + static TypeHandle get_class_type() { + return _type_handle; + } + static void init_type() { + EggJointPointer::init_type(); + register_type(_type_handle, "EggJointNodePointer", + EggJointPointer::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 + + diff --git a/pandatool/src/eggcharbase/eggJointPointer.cxx b/pandatool/src/eggcharbase/eggJointPointer.cxx index 88151cec77..df79ed4d9c 100644 --- a/pandatool/src/eggcharbase/eggJointPointer.cxx +++ b/pandatool/src/eggcharbase/eggJointPointer.cxx @@ -8,12 +8,15 @@ TypeHandle EggJointPointer::_type_handle; + //////////////////////////////////////////////////////////////////// -// Function: EggJointPointer::Constructor -// Access: Public -// Description: +// Function: EggJointPointer::add_frame +// Access: Public, Virtual +// Description: Appends a new frame onto the end of the data, if +// possible; returns true if not possible, or false +// otherwise (e.g. for a static joint). //////////////////////////////////////////////////////////////////// -EggJointPointer:: -EggJointPointer(EggObject *object) { - _joint = DCAST(EggGroup, object); +bool EggJointPointer:: +add_frame(const LMatrix4d &) { + return false; } diff --git a/pandatool/src/eggcharbase/eggJointPointer.h b/pandatool/src/eggcharbase/eggJointPointer.h index 1f13dc8804..b6e4064a3e 100644 --- a/pandatool/src/eggcharbase/eggJointPointer.h +++ b/pandatool/src/eggcharbase/eggJointPointer.h @@ -10,19 +10,23 @@ #include "eggBackPointer.h" -#include -#include +#include //////////////////////////////////////////////////////////////////// // Class : EggJointPointer -// Description : This stores a pointer back to a node. +// Description : This is a base class for EggJointNodePointer and +// EggMatrixTablePointer. It stores a back pointer to +// either a entry or an xform
data, and +// thus presents an interface that returns 1-n matrices, +// one for each frame. ( entries, for model +// files, appear the same as one-frame animations.) //////////////////////////////////////////////////////////////////// class EggJointPointer : public EggBackPointer { public: - EggJointPointer(EggObject *object); - -private: - PT(EggGroup) _joint; + virtual int get_num_frames() const=0; + virtual LMatrix4d get_frame(int n) const=0; + virtual void set_frame(int n, const LMatrix4d &mat)=0; + virtual bool add_frame(const LMatrix4d &mat); public: static TypeHandle get_class_type() { diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx index 40f8444941..82468dfeff 100644 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.cxx @@ -43,3 +43,57 @@ EggMatrixTablePointer(EggObject *object) { } } } + +//////////////////////////////////////////////////////////////////// +// Function: EggMatrixTablePointer::get_num_frames +// Access: Public, Virtual +// Description: Returns the number of frames of animation for this +// particular joint. +//////////////////////////////////////////////////////////////////// +int EggMatrixTablePointer:: +get_num_frames() const { + if (_xform == (EggXfmSAnim *)NULL) { + return 0; + } else { + return _xform->get_num_rows(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggMatrixTablePointer::get_frame +// Access: Public, Virtual +// Description: Returns the transform matrix corresponding to this +// joint position in the nth frame. +//////////////////////////////////////////////////////////////////// +LMatrix4d EggMatrixTablePointer:: +get_frame(int n) const { + nassertr(n >= 0 && n < get_num_frames(), LMatrix4d::ident_mat()); + LMatrix4d mat; + _xform->get_value(n, mat); + return mat; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggMatrixTablePointer::set_frame +// Access: Public, Virtual +// Description: Sets the transform matrix corresponding to this +// joint position in the nth frame. +//////////////////////////////////////////////////////////////////// +void EggMatrixTablePointer:: +set_frame(int n, const LMatrix4d &mat) { + nassertv(n >= 0 && n < get_num_frames()); + // Do something here. +} + +//////////////////////////////////////////////////////////////////// +// Function: EggMatrixTablePointer::add_frame +// Access: Public, Virtual +// Description: Appends a new frame onto the end of the data, if +// possible; returns true if not possible, or false +// otherwise (e.g. for a static joint). +//////////////////////////////////////////////////////////////////// +bool EggMatrixTablePointer:: +add_frame(const LMatrix4d &mat) { + // Do something here. + return true; +} diff --git a/pandatool/src/eggcharbase/eggMatrixTablePointer.h b/pandatool/src/eggcharbase/eggMatrixTablePointer.h index c9865270db..834bb25e41 100644 --- a/pandatool/src/eggcharbase/eggMatrixTablePointer.h +++ b/pandatool/src/eggcharbase/eggMatrixTablePointer.h @@ -8,7 +8,7 @@ #include -#include "eggBackPointer.h" +#include "eggJointPointer.h" #include #include @@ -21,10 +21,15 @@ // corresponding to the animation data from a single // bundle for this joint. //////////////////////////////////////////////////////////////////// -class EggMatrixTablePointer : public EggBackPointer { +class EggMatrixTablePointer : public EggJointPointer { public: EggMatrixTablePointer(EggObject *object); + virtual int get_num_frames() const; + virtual LMatrix4d get_frame(int n) const; + virtual void set_frame(int n, const LMatrix4d &mat); + virtual bool add_frame(const LMatrix4d &mat); + private: PT(EggTable) _table; PT(EggXfmSAnim) _xform; @@ -34,9 +39,9 @@ public: return _type_handle; } static void init_type() { - EggBackPointer::init_type(); + EggJointPointer::init_type(); register_type(_type_handle, "EggMatrixTablePointer", - EggBackPointer::get_class_type()); + EggJointPointer::get_class_type()); } virtual TypeHandle get_type() const { return get_class_type(); diff --git a/pandatool/src/eggcharbase/eggSliderData.cxx b/pandatool/src/eggcharbase/eggSliderData.cxx index d81e846c56..317eb6291f 100644 --- a/pandatool/src/eggcharbase/eggSliderData.cxx +++ b/pandatool/src/eggcharbase/eggSliderData.cxx @@ -33,26 +33,26 @@ 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); + EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { back = new EggVertexPointer; - set_back_pointer(model_index, back); + set_model(model_index, back); } } else if (egg_object->is_of_type(EggVertex::get_class_type())) { // A vertex! - EggBackPointer *back = get_back_pointer(model_index); + EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { back = new EggVertexPointer; - set_back_pointer(model_index, back); + set_model(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); + EggBackPointer *back = get_model(model_index); if (back == (EggBackPointer *)NULL) { back = new EggVertexPointer; - set_back_pointer(model_index, back); + set_model(model_index, back); } } else { @@ -70,9 +70,9 @@ 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)) { + int num_models = get_num_models(); + for (int model_index = 0; model_index < num_models; model_index++) { + if (has_model(model_index)) { out << " " << model_index; } } diff --git a/pandatool/src/eggprogs/eggTopstrip.cxx b/pandatool/src/eggprogs/eggTopstrip.cxx index f9aad7f7dd..7a48dc7ab7 100644 --- a/pandatool/src/eggprogs/eggTopstrip.cxx +++ b/pandatool/src/eggprogs/eggTopstrip.cxx @@ -5,6 +5,12 @@ #include "eggTopstrip.h" +#include +#include +#include +#include +#include + //////////////////////////////////////////////////////////////////// // Function: EggTopstrip::Constructor // Access: Public @@ -20,6 +26,42 @@ EggTopstrip() { "This is a particularly useful thing to do to generate character " "models that can stack one on top of the other in a sensible way."); + + add_option + ("t", "name", 0, + "Specify the name of the 'top' joint, from which to draw the " + "animation channels which will be applied to the entire animation.", + &EggTopstrip::dispatch_string, NULL, &_top_joint_name); + + add_option + ("i", "", 0, + "Invert the matrix before applying. This causes a subtractive " + "effect. This is the default unless -r is specified.", + &EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform); + + add_option + ("n", "", 0, + "Do not invert the matrix before applying. This causes an " + "additive effect.", + &EggTopstrip::dispatch_true, &_got_invert_transform, &_invert_transform); + + add_option + ("s", "[ijkphrxyz]", 0, + "Specify the components of the transform that are to be applied. Use " + "any combination of the nine token letters: i, j, k represent the " + "three scale axes; h, p, r represent rotation; and x, y, z represent " + "translation. The default is everything: -s ijkphrxyz.", + &EggTopstrip::dispatch_string, NULL, &_transform_channels); + + add_option + ("r", "file.egg", 0, + "Read the animation channel from the indicated egg file. If this " + "is not specified, the first egg file named on the command line is " + "used.", + &EggTopstrip::dispatch_filename, NULL, &_channel_filename); + + _invert_transform = true; + _transform_channels = "ijkphrxyz"; } //////////////////////////////////////////////////////////////////// @@ -29,6 +71,169 @@ EggTopstrip() { //////////////////////////////////////////////////////////////////// void EggTopstrip:: run() { + nassertv(_collection != (EggCharacterCollection *)NULL); + nassertv(_collection->get_num_eggs() > 0); + + // Get the number of characters first, in case adding the + // _channel_egg changes this. + int num_characters = _collection->get_num_characters(); + + // Determine which model we'll be pulling the animation channels + // from. + int from_model = -1; + + if (!_channel_filename.empty()) { + // Read in the extra egg file that we use for extracting the + // channels out. + PT(EggData) channel_egg = read_egg(_channel_filename); + if (channel_egg == (EggData *)NULL) { + nout << "Cannot read " << _channel_filename << "\n"; + exit(1); + } + int channel_egg_index = _collection->add_egg(channel_egg); + if (channel_egg_index < 0) { + nout << _channel_filename + << " does not contain a character model or animation channel.\n"; + exit(1); + } + + from_model = _collection->get_first_model_index(channel_egg_index); + + if (!_got_invert_transform) { + // With -r, the default is not to invert the transform. + _invert_transform = false; + } + } + + // Now process each character. + for (int i = 0; i < num_characters; i++) { + EggCharacterData *char_data = _collection->get_character(i); + + EggJointData *root_joint = char_data->get_root_joint(); + + EggJointData *top_joint = (EggJointData *)NULL; + if (_top_joint_name.empty()) { + // The default top joint name is the alphabetically first joint + // in the top level. + if (root_joint->get_num_children() == 0) { + nout << "Character " << char_data->get_name() << " has no joints.\n"; + exit(1); + } + top_joint = root_joint->get_child(0); + } else { + top_joint = char_data->find_joint(_top_joint_name); + if (top_joint == (EggJointData *)NULL) { + nout << "Character " << char_data->get_name() + << " has no joint named " << _top_joint_name << "\n"; + exit(1); + } + } + + int num_children = root_joint->get_num_children(); + for (int i = 0; i < num_children; i++) { + EggJointData *joint_data = root_joint->get_child(i); + strip_anim(joint_data, from_model, top_joint); + } + + // We also need to transform the vertices for any models involved + // here. + int num_models = char_data->get_num_models(); + for (int m = 0; m < num_models; m++) { + EggNode *node = char_data->get_model_root(m); + if (!node->is_of_type(EggTable::get_class_type())) { + strip_anim_vertices(node, m, from_model, top_joint); + } + } + } + + write_eggs(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggTopstrip::strip_anim +// Access: Public +// Description: Applies the channels from joint _top_joint +// in model from_model to the joint referenced by +// joint_data. +//////////////////////////////////////////////////////////////////// +void EggTopstrip:: +strip_anim(EggJointData *joint_data, int from_model, EggJointData *top_joint) { + int num_models = joint_data->get_num_models(); + for (int i = 0; i < num_models; i++) { + EggBackPointer *back = joint_data->get_model(i); + if (back != (EggBackPointer *)NULL) { + EggJointPointer *joint; + DCAST_INTO_V(joint, back); + + cerr << "joint is " << joint->get_type() << "\n"; + + int model = (from_model < 0) ? i : from_model; + EggBackPointer *from_back = top_joint->get_model(model); + if (from_back == (EggBackPointer *)NULL) { + nout << "Joint " << top_joint->get_name() << " has no model index " + << model << "\n"; + exit(1); + } + EggJointPointer *from_joint; + DCAST_INTO_V(from_joint, from_back); + + int num_into_frames = joint->get_num_frames(); + int num_from_frames = from_joint->get_num_frames(); + + int num_frames = max(num_into_frames, num_from_frames); + + for (int f = 0; f < num_frames; f++) { + LMatrix4d start = joint->get_frame(f % num_into_frames); + LMatrix4d strip = from_joint->get_frame(f % num_from_frames); + + if (_invert_transform) { + strip.invert_in_place(); + } + + cerr << "Applying " << strip << " to " << f << " of " + << joint_data->get_name() << " model " << i << "\n"; + + if (f >= num_into_frames) { + if (!joint->add_frame(start * strip)) { + nout << "Cannot apply multiple frames of animation to a model file.\n" + << "In general, be careful when using -r and model files.\n"; + exit(1); + } + } else { + joint->set_frame(f, start * strip); + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggTopstrip::strip_anim_vertices +// Access: Public +// Description: Applies the channels from joint _top_joint +// in model from_model to the vertices at egg_node. +//////////////////////////////////////////////////////////////////// +void EggTopstrip:: +strip_anim_vertices(EggNode *egg_node, int into_model, int from_model, + EggJointData *top_joint) { + int model = (from_model < 0) ? into_model : from_model; + EggBackPointer *from_back = top_joint->get_model(model); + if (from_back == (EggBackPointer *)NULL) { + nout << "Joint " << top_joint->get_name() << " has no model index " + << model << "\n"; + exit(1); + } + + EggJointPointer *from_joint; + DCAST_INTO_V(from_joint, from_back); + + LMatrix4d strip = from_joint->get_frame(0); + if (_invert_transform) { + strip.invert_in_place(); + } + + cerr << "Applying " << strip << " to vertices.\n"; + egg_node->transform_vertices_only(strip); } diff --git a/pandatool/src/eggprogs/eggTopstrip.h b/pandatool/src/eggprogs/eggTopstrip.h index e51f6ac0ff..a38e93a877 100644 --- a/pandatool/src/eggprogs/eggTopstrip.h +++ b/pandatool/src/eggprogs/eggTopstrip.h @@ -9,6 +9,12 @@ #include #include +#include + +#include + +class EggJointData; +class EggJointPointer; //////////////////////////////////////////////////////////////////// // Class : EggTopstrip @@ -23,6 +29,18 @@ public: EggTopstrip(); void run(); + + void strip_anim(EggJointData *joint_data, int from_model, + EggJointData *top_joint); + void strip_anim_vertices(EggNode *egg_node, int into_model, + int from_model, EggJointData *top_joint); + + + string _top_joint_name; + bool _got_invert_transform; + bool _invert_transform; + string _transform_channels; + Filename _channel_filename; }; #endif diff --git a/pandatool/src/progbase/programBase.cxx b/pandatool/src/progbase/programBase.cxx index 6756866470..b1378b4e46 100644 --- a/pandatool/src/progbase/programBase.cxx +++ b/pandatool/src/progbase/programBase.cxx @@ -567,6 +567,42 @@ dispatch_none(const string &, const string &, void *) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: ProgramBase::dispatch_true +// Access: Protected, Static +// Description: Standard dispatch function for an option that takes +// no parameters, and when it is present sets a bool +// variable to the 'true' value. This is another way to +// handle a boolean flag. See also dispatch_none() and +// dispatch_false(). +// +// The data pointer is to a bool variable. +//////////////////////////////////////////////////////////////////// +bool ProgramBase:: +dispatch_true(const string &, const string &, void *var) { + bool *bp = (bool *)var; + (*bp) = true; + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: ProgramBase::dispatch_false +// Access: Protected, Static +// Description: Standard dispatch function for an option that takes +// no parameters, and when it is present sets a bool +// variable to the 'false' value. This is another way to +// handle a boolean flag. See also dispatch_none() and +// dispatch_true(). +// +// The data pointer is to a bool variable. +//////////////////////////////////////////////////////////////////// +bool ProgramBase:: +dispatch_false(const string &, const string &, void *var) { + bool *bp = (bool *)var; + (*bp) = false; + return true; +} + //////////////////////////////////////////////////////////////////// // Function: ProgramBase::dispatch_count // Access: Protected, Static diff --git a/pandatool/src/progbase/programBase.h b/pandatool/src/progbase/programBase.h index cfd9bd12f5..5d9968f45f 100644 --- a/pandatool/src/progbase/programBase.h +++ b/pandatool/src/progbase/programBase.h @@ -66,6 +66,8 @@ protected: bool remove_option(const string &option); static bool dispatch_none(const string &opt, const string &arg, void *); + static bool dispatch_true(const string &opt, const string &arg, void *var); + static bool dispatch_false(const string &opt, const string &arg, void *var); static bool dispatch_count(const string &opt, const string &arg, void *var); static bool dispatch_int(const string &opt, const string &arg, void *var); static bool dispatch_int_pair(const string &opt, const string &arg, void *var);