Browse Source

support multiple ObjectType flags

David Rose 23 years ago
parent
commit
720ca3db24

+ 15 - 14
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];
 }
 
 ////////////////////////////////////////////////////////////////////

+ 4 - 3
panda/src/egg/eggGroup.cxx

@@ -61,7 +61,7 @@ operator = (const EggGroup &copy) {
   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)
       << "<ObjectType> { ";
-    enquote_string(out, get_objecttype()) << " }\n";
+    enquote_string(out, (*oi)) << " }\n";
   }
 
   if (get_model_flag()) {

+ 9 - 8
panda/src/egg/eggGroup.h

@@ -19,7 +19,7 @@
 #ifndef EGGGROUP_H
 #define EGGGROUP_H
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 #include "eggGroupNode.h"
 #include "eggRenderMode.h"
@@ -28,8 +28,9 @@
 #include "eggSwitchCondition.h"
 #include "pt_EggVertex.h"
 
-#include <luse.h>
-#include <collideMask.h>
+#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;

+ 1 - 1
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 '}'
 {

+ 150 - 85
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<string> expanded;
     pvector<string> 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<string>::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
-      // <ObjectType> 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 = "<Collide> { Polyset descend }";
-
-        } else if (cmp_nocase_uh(objecttype, "solidpoly") == 0) {
-          egg_syntax = "<Collide> { Polyset descend solid }";
-
-        } else if (cmp_nocase_uh(objecttype, "turnstile") == 0) {
-          egg_syntax = "<Collide> { Polyset descend turnstile }";
-
-        } else if (cmp_nocase_uh(objecttype, "sphere") == 0) {
-          egg_syntax = "<Collide> { Sphere descend }";
-
-        } else if (cmp_nocase_uh(objecttype, "trigger") == 0) {
-          egg_syntax = "<Collide> { Polyset descend intangible }";
-
-        } else if (cmp_nocase_uh(objecttype, "trigger_sphere") == 0) {
-          egg_syntax = "<Collide> { Sphere descend intangible }";
-
-        } else if (cmp_nocase_uh(objecttype, "eye_trigger") == 0) {
-          egg_syntax = "<Collide> { Polyset descend intangible center }";
-
-        } else if (cmp_nocase_uh(objecttype, "bubble") == 0) {
-          egg_syntax = "<Collide> { Sphere keep descend }";
-
-        } else if (cmp_nocase_uh(objecttype, "ghost") == 0) {
-          egg_syntax = "<Scalar> 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<string> &expanded,
+                    const pvector<string> &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<string> new_expanded(expanded);
+
+    // Check for a cycle.
+    if (!new_expanded.insert(object_type).second) {
+      egg2pg_cat.error()
+        << "Cycle in ObjectType expansions:\n";
+      pvector<string>::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<string> 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<string> &expanded,
+                      const pvector<string> &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 = "<Collide> { Polyset descend }";
+      
+    } else if (cmp_nocase_uh(object_type, "solidpoly") == 0) {
+      egg_syntax = "<Collide> { Polyset descend solid }";
+      
+    } else if (cmp_nocase_uh(object_type, "turnstile") == 0) {
+      egg_syntax = "<Collide> { Polyset descend turnstile }";
+      
+    } else if (cmp_nocase_uh(object_type, "sphere") == 0) {
+      egg_syntax = "<Collide> { Sphere descend }";
+      
+    } else if (cmp_nocase_uh(object_type, "trigger") == 0) {
+      egg_syntax = "<Collide> { Polyset descend intangible }";
+      
+    } else if (cmp_nocase_uh(object_type, "trigger_sphere") == 0) {
+      egg_syntax = "<Collide> { Sphere descend intangible }";
+      
+    } else if (cmp_nocase_uh(object_type, "eye_trigger") == 0) {
+      egg_syntax = "<Collide> { Polyset descend intangible center }";
+      
+    } else if (cmp_nocase_uh(object_type, "bubble") == 0) {
+      egg_syntax = "<Collide> { Sphere keep descend }";
+      
+    } else if (cmp_nocase_uh(object_type, "ghost") == 0) {
+      egg_syntax = "<Scalar> collide-mask { 0 }";
+      
+    } else if (cmp_nocase_uh(object_type, "dcs") == 0) {
+      egg_syntax = "<DCS> { 1 }";
+      
+    } else if (cmp_nocase_uh(object_type, "model") == 0) {
+      egg_syntax = "<Model> { 1 }";
+      
+    } else if (cmp_nocase_uh(object_type, "decal") == 0) {
+      egg_syntax = "<Decal> { 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

+ 5 - 0
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<string> &expanded,
+                           const pvector<string> &expanded_history);
+  bool do_expand_object_type(EggGroup *egg_group, const pset<string> &expanded,
+                             const pvector<string> &expanded_history,
+                             const string &object_type);
 
   CPT(TransformState) make_transform(const EggTransform3d *egg_transform);