From 720ca3db245062f31d900ac2ee87fa40d78cec60 Mon Sep 17 00:00:00 2001 From: David Rose Date: Fri, 24 Jan 2003 18:56:38 +0000 Subject: [PATCH] support multiple ObjectType flags --- panda/src/egg/eggGroup.I | 29 ++-- panda/src/egg/eggGroup.cxx | 7 +- panda/src/egg/eggGroup.h | 17 +-- panda/src/egg/parser.yxx | 2 +- panda/src/egg2pg/eggLoader.cxx | 235 +++++++++++++++++++++------------ panda/src/egg2pg/eggLoader.h | 5 + 6 files changed, 184 insertions(+), 111 deletions(-) diff --git a/panda/src/egg/eggGroup.I b/panda/src/egg/eggGroup.I index c1d37339b0..ece99d1f8e 100644 --- a/panda/src/egg/eggGroup.I +++ b/panda/src/egg/eggGroup.I @@ -282,43 +282,44 @@ get_switch_fps() const { } //////////////////////////////////////////////////////////////////// -// Function: EggGroup::set_objecttype +// Function: EggGroup::add_object_type // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE void EggGroup:: -set_objecttype(const string &objecttype) { - _objecttype = objecttype; +add_object_type(const string &object_type) { + _object_types.push_back(object_type); } //////////////////////////////////////////////////////////////////// -// Function: EggGroup::clear_objecttype +// Function: EggGroup::clear_object_types // Access: Public // Description: //////////////////////////////////////////////////////////////////// INLINE void EggGroup:: -clear_objecttype() { - _objecttype = ""; +clear_object_types() { + _object_types.clear(); } //////////////////////////////////////////////////////////////////// -// Function: EggGroup::has_objecttype +// Function: EggGroup::get_num_object_types // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE bool EggGroup:: -has_objecttype() const { - return !_objecttype.empty(); +INLINE int EggGroup:: +get_num_object_types() const { + return _object_types.size(); } //////////////////////////////////////////////////////////////////// -// Function: EggGroup::get_objecttype +// Function: EggGroup::get_object_type // Access: Public // Description: //////////////////////////////////////////////////////////////////// -INLINE const string &EggGroup:: -get_objecttype() const { - return _objecttype; +INLINE string EggGroup:: +get_object_type(int index) const { + nassertr(index >= 0 && index < (int)_object_types.size(), string()); + return _object_types[index]; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/egg/eggGroup.cxx b/panda/src/egg/eggGroup.cxx index 36e2a16266..8877d9ad85 100644 --- a/panda/src/egg/eggGroup.cxx +++ b/panda/src/egg/eggGroup.cxx @@ -61,7 +61,7 @@ operator = (const EggGroup ©) { EggTransform3d::operator = (copy); _flags = copy._flags; _flags2 = copy._flags2; - _objecttype = copy._objecttype; + _object_types = copy._object_types; _collision_name = copy._collision_name; _fps = copy._fps; @@ -220,10 +220,11 @@ write(ostream &out, int indent_level) const { EggTransform3d::write(out, indent_level + 2); } - if (has_objecttype()) { + vector_string::const_iterator oi; + for (oi = _object_types.begin(); oi != _object_types.end(); ++oi) { indent(out, indent_level + 2) << " { "; - enquote_string(out, get_objecttype()) << " }\n"; + enquote_string(out, (*oi)) << " }\n"; } if (get_model_flag()) { diff --git a/panda/src/egg/eggGroup.h b/panda/src/egg/eggGroup.h index ddb1194eaf..be0f462f27 100644 --- a/panda/src/egg/eggGroup.h +++ b/panda/src/egg/eggGroup.h @@ -19,7 +19,7 @@ #ifndef EGGGROUP_H #define EGGGROUP_H -#include +#include "pandabase.h" #include "eggGroupNode.h" #include "eggRenderMode.h" @@ -28,8 +28,9 @@ #include "eggSwitchCondition.h" #include "pt_EggVertex.h" -#include -#include +#include "luse.h" +#include "collideMask.h" +#include "vector_string.h" //////////////////////////////////////////////////////////////////// // Class : EggGroup @@ -131,10 +132,10 @@ public: INLINE void set_switch_fps(double fps); INLINE double get_switch_fps() const; - INLINE void set_objecttype(const string &objecttype); - INLINE void clear_objecttype(); - INLINE bool has_objecttype() const; - INLINE const string &get_objecttype() const; + INLINE void add_object_type(const string &object_type); + INLINE void clear_object_types(); + INLINE int get_num_object_types() const; + INLINE string get_object_type(int index) const; INLINE void set_model_flag(bool flag); INLINE bool get_model_flag() const; @@ -227,7 +228,7 @@ private: int _flags2; CollideMask _collide_mask, _from_collide_mask, _into_collide_mask; LPoint3d _billboard_center; - string _objecttype; + vector_string _object_types; string _collision_name; double _fps; PT(EggSwitchCondition) _lod; diff --git a/panda/src/egg/parser.yxx b/panda/src/egg/parser.yxx index f09f60f92d..9573df107a 100644 --- a/panda/src/egg/parser.yxx +++ b/panda/src/egg/parser.yxx @@ -970,7 +970,7 @@ group_body: { EggGroup *group = DCAST(EggGroup, egg_stack.back()); string type = $4; - group->set_objecttype(type); + group->add_object_type(type); } | group_body MODEL '{' integer '}' { diff --git a/panda/src/egg2pg/eggLoader.cxx b/panda/src/egg2pg/eggLoader.cxx index 56babdae92..c35245532a 100644 --- a/panda/src/egg2pg/eggLoader.cxx +++ b/panda/src/egg2pg/eggLoader.cxx @@ -1284,93 +1284,11 @@ PandaNode *EggLoader:: make_node(EggGroup *egg_group, PandaNode *parent) { PT(PandaNode) node = NULL; - if (egg_group->has_objecttype()) { - // We'll allow recursive expansion of ObjectType strings--but we - // don't want to get caught in a cycle. Keep track of the strings - // we've expanded so far. + if (egg_group->get_num_object_types() != 0) { pset expanded; pvector expanded_history; - - while (egg_group->has_objecttype()) { - string objecttype = egg_group->get_objecttype(); - if (!expanded.insert(objecttype).second) { - egg2pg_cat.error() - << "Cycle in ObjectType expansions:\n"; - pvector::const_iterator pi; - for (pi = expanded_history.begin(); - pi != expanded_history.end(); - ++pi) { - egg2pg_cat.error(false) - << (*pi) << " -> "; - } - egg2pg_cat.error(false) << objecttype << "\n"; - _error = true; - break; - } - expanded_history.push_back(objecttype); - - // Now clear the group's ObjectType flag. We'll only loop back - // here again if we end up setting this during the ObjectType - // expansion; e.g. the expansion string itself contains an - // reference. - egg_group->clear_objecttype(); - - // Now try to find the egg syntax that the given objecttype is - // shorthand for. First, look in the config file. - - string egg_syntax = - config_egg2pg.GetString("egg-object-type-" + objecttype, "none"); - - if (egg_syntax == "none") { - // It wasn't defined in a config file. Maybe it's built in? - - if (cmp_nocase_uh(objecttype, "barrier") == 0) { - egg_syntax = " { Polyset descend }"; - - } else if (cmp_nocase_uh(objecttype, "solidpoly") == 0) { - egg_syntax = " { Polyset descend solid }"; - - } else if (cmp_nocase_uh(objecttype, "turnstile") == 0) { - egg_syntax = " { Polyset descend turnstile }"; - - } else if (cmp_nocase_uh(objecttype, "sphere") == 0) { - egg_syntax = " { Sphere descend }"; - - } else if (cmp_nocase_uh(objecttype, "trigger") == 0) { - egg_syntax = " { Polyset descend intangible }"; - - } else if (cmp_nocase_uh(objecttype, "trigger_sphere") == 0) { - egg_syntax = " { Sphere descend intangible }"; - - } else if (cmp_nocase_uh(objecttype, "eye_trigger") == 0) { - egg_syntax = " { Polyset descend intangible center }"; - - } else if (cmp_nocase_uh(objecttype, "bubble") == 0) { - egg_syntax = " { Sphere keep descend }"; - - } else if (cmp_nocase_uh(objecttype, "ghost") == 0) { - egg_syntax = " collide-mask { 0 }"; - - } else if (cmp_nocase_uh(objecttype, "backstage") == 0) { - // Ignore "backstage" geometry. - return NULL; - - } else { - egg2pg_cat.error() - << "Unknown ObjectType " << objecttype << "\n"; - _error = true; - break; - } - } - - if (!egg_syntax.empty()) { - if (!egg_group->parse_egg(egg_syntax)) { - egg2pg_cat.error() - << "Error while parsing definition for ObjectType " - << objecttype << "\n"; - _error = true; - } - } + if (!expand_object_types(egg_group, expanded, expanded_history)) { + return NULL; } } @@ -1949,6 +1867,153 @@ apply_deferred_nodes(PandaNode *node, const DeferredNodeProperty &prop) { } } +//////////////////////////////////////////////////////////////////// +// Function: EggLoader::expand_object_types +// Access: Private +// Description: Recursively expands the group's ObjectType string(s). +// It's recursive because an ObjectType string might +// itself expand to another ObjectType string, which is +// allowed; but we don't want to get caught in a cycle. +// +// The return value is true if the object type is +// expanded and the node is valid, or false if the node +// should be ignored (e.g. ObjectType "backstage"). +//////////////////////////////////////////////////////////////////// +bool EggLoader:: +expand_object_types(EggGroup *egg_group, const pset &expanded, + const pvector &expanded_history) { + int num_object_types = egg_group->get_num_object_types(); + + // First, copy out the object types so we can recursively modify the + // list. + vector_string object_types; + int i; + for (i = 0; i < num_object_types; i++) { + object_types.push_back(egg_group->get_object_type(i)); + } + egg_group->clear_object_types(); + + for (i = 0; i < num_object_types; i++) { + string object_type = object_types[i]; + pset new_expanded(expanded); + + // Check for a cycle. + if (!new_expanded.insert(object_type).second) { + egg2pg_cat.error() + << "Cycle in ObjectType expansions:\n"; + pvector::const_iterator pi; + for (pi = expanded_history.begin(); + pi != expanded_history.end(); + ++pi) { + egg2pg_cat.error(false) + << (*pi) << " -> "; + } + egg2pg_cat.error(false) << object_type << "\n"; + _error = true; + + } else { + // No cycle; continue. + pvector new_expanded_history(expanded_history); + new_expanded_history.push_back(object_type); + + if (!do_expand_object_type(egg_group, new_expanded, + new_expanded_history, object_type)) { + // Ignorable group; stop here. + return false; + } + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggLoader::expand_object_type +// Access: Private +// Description: Further implementation of expand_object_types(). +//////////////////////////////////////////////////////////////////// +bool EggLoader:: +do_expand_object_type(EggGroup *egg_group, const pset &expanded, + const pvector &expanded_history, + const string &object_type) { + // Try to find the egg syntax that the given objecttype is + // shorthand for. First, look in the config file. + + string egg_syntax = + config_egg2pg.GetString("egg-object-type-" + object_type, "none"); + + if (egg_syntax == "none") { + // It wasn't defined in a config file. Maybe it's built in? + + if (cmp_nocase_uh(object_type, "barrier") == 0) { + egg_syntax = " { Polyset descend }"; + + } else if (cmp_nocase_uh(object_type, "solidpoly") == 0) { + egg_syntax = " { Polyset descend solid }"; + + } else if (cmp_nocase_uh(object_type, "turnstile") == 0) { + egg_syntax = " { Polyset descend turnstile }"; + + } else if (cmp_nocase_uh(object_type, "sphere") == 0) { + egg_syntax = " { Sphere descend }"; + + } else if (cmp_nocase_uh(object_type, "trigger") == 0) { + egg_syntax = " { Polyset descend intangible }"; + + } else if (cmp_nocase_uh(object_type, "trigger_sphere") == 0) { + egg_syntax = " { Sphere descend intangible }"; + + } else if (cmp_nocase_uh(object_type, "eye_trigger") == 0) { + egg_syntax = " { Polyset descend intangible center }"; + + } else if (cmp_nocase_uh(object_type, "bubble") == 0) { + egg_syntax = " { Sphere keep descend }"; + + } else if (cmp_nocase_uh(object_type, "ghost") == 0) { + egg_syntax = " collide-mask { 0 }"; + + } else if (cmp_nocase_uh(object_type, "dcs") == 0) { + egg_syntax = " { 1 }"; + + } else if (cmp_nocase_uh(object_type, "model") == 0) { + egg_syntax = " { 1 }"; + + } else if (cmp_nocase_uh(object_type, "decal") == 0) { + egg_syntax = " { 1 }"; + + } else if (cmp_nocase_uh(object_type, "backstage") == 0) { + // Ignore "backstage" geometry. + return false; + + } else { + egg2pg_cat.error() + << "Unknown ObjectType " << object_type << "\n"; + _error = true; + return true; + } + } + + if (!egg_syntax.empty()) { + if (!egg_group->parse_egg(egg_syntax)) { + egg2pg_cat.error() + << "Error while parsing definition for ObjectType " + << object_type << "\n"; + _error = true; + + } else { + // Now we've parsed the object type syntax, which might have + // added more object types. Recurse if necessary. + if (egg_group->get_num_object_types() != 0) { + if (!expand_object_types(egg_group, expanded, expanded_history)) { + return false; + } + } + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: EggLoader::make_transform // Access: Private diff --git a/panda/src/egg2pg/eggLoader.h b/panda/src/egg2pg/eggLoader.h index 66d7742efb..676beef795 100644 --- a/panda/src/egg2pg/eggLoader.h +++ b/panda/src/egg2pg/eggLoader.h @@ -122,6 +122,11 @@ private: EggGroup::CollideFlags flags); void apply_deferred_nodes(PandaNode *node, const DeferredNodeProperty &prop); + bool expand_object_types(EggGroup *egg_group, const pset &expanded, + const pvector &expanded_history); + bool do_expand_object_type(EggGroup *egg_group, const pset &expanded, + const pvector &expanded_history, + const string &object_type); CPT(TransformState) make_transform(const EggTransform3d *egg_transform);