Browse Source

support instancing syntax

David Rose 17 years ago
parent
commit
83d21bc2b1

+ 74 - 0
panda/src/egg/eggGroup.cxx

@@ -121,6 +121,14 @@ EggGroup::
 void EggGroup::
 void EggGroup::
 set_group_type(GroupType type) {
 set_group_type(GroupType type) {
   if (type != get_group_type()) {
   if (type != get_group_type()) {
+#ifndef NDEBUG
+    if (type != GT_instance) {
+      // Only valid to change to a non-instance type if we have no
+      // group refs.
+      nassertv(_group_refs.empty());
+    }
+#endif 
+
     // Make sure the user didn't give us any stray bits.
     // Make sure the user didn't give us any stray bits.
     nassertv((type & ~F_group_type)==0);
     nassertv((type & ~F_group_type)==0);
     _flags = (_flags & ~F_group_type) | type;
     _flags = (_flags & ~F_group_type) | type;
@@ -259,6 +267,13 @@ write(ostream &out, int indent_level) const {
       << "<Scalar> blenda { " << c[3] << " }\n";
       << "<Scalar> blenda { " << c[3] << " }\n";
   }
   }
 
 
+  GroupRefs::const_iterator gri;
+  for (gri = _group_refs.begin(); gri != _group_refs.end(); ++gri) {
+    EggGroup *group_ref = (*gri);
+    indent(out, indent_level + 2)
+      << "<Ref> { " << group_ref->get_name() << " }\n";
+  }
+
   // We have to write the children nodes before we write the vertex
   // We have to write the children nodes before we write the vertex
   // references, since we might be referencing a vertex that's defined
   // references, since we might be referencing a vertex that's defined
   // in one of those children nodes!
   // in one of those children nodes!
@@ -767,6 +782,65 @@ test_vref_integrity() const {
 
 
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::add_group_ref
+//       Access: Published
+//  Description: Adds a new <Ref> entry to the group.  This declares
+//               an internal reference to another node, and is used to
+//               implement scene-graph instancing; it is only valid if
+//               the group_type is GT_instance.
+////////////////////////////////////////////////////////////////////
+void EggGroup::
+add_group_ref(EggGroup *group) {
+  nassertv(get_group_type() == GT_instance);
+  _group_refs.push_back(group);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::get_num_group_refs
+//       Access: Published
+//  Description: Returns the number of <Ref> entries within this
+//               group.  See add_group_ref().
+////////////////////////////////////////////////////////////////////
+int EggGroup::
+get_num_group_refs() const {
+  return _group_refs.size();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::get_group_ref
+//       Access: Published
+//  Description: Returns the nth <Ref> entry within this group.  See
+//               add_group_ref().
+////////////////////////////////////////////////////////////////////
+EggGroup *EggGroup::
+get_group_ref(int n) const {
+  nassertr(n >= 0 && n < (int)_group_refs.size(), NULL);
+  return _group_refs[n];
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::remove_group_ref
+//       Access: Published
+//  Description: Removes the nth <Ref> entry within this group.  See
+//               add_group_ref().
+////////////////////////////////////////////////////////////////////
+void EggGroup::
+remove_group_ref(int n) {
+  nassertv(n >= 0 && n < (int)_group_refs.size());
+  _group_refs.erase(_group_refs.begin() + n);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: EggGroup::clear_group_refs
+//       Access: Published
+//  Description: Removes all of the <Ref> entries within this group.
+//               See add_group_ref().
+////////////////////////////////////////////////////////////////////
+void EggGroup::
+clear_group_refs() {
+  _group_refs.clear();
+}
 
 
 
 
 
 

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

@@ -285,6 +285,12 @@ PUBLISHED:
   void test_vref_integrity() const { }
   void test_vref_integrity() const { }
 #endif  // NDEBUG
 #endif  // NDEBUG
 
 
+  void add_group_ref(EggGroup *group);
+  int get_num_group_refs() const;
+  EggGroup *get_group_ref(int n) const;
+  void remove_group_ref(int n);
+  void clear_group_refs();
+
   static GroupType string_group_type(const string &strval);
   static GroupType string_group_type(const string &strval);
   static DartType string_dart_type(const string &strval);
   static DartType string_dart_type(const string &strval);
   static DCSType string_dcs_type(const string &strval);
   static DCSType string_dcs_type(const string &strval);
@@ -353,6 +359,9 @@ private:
   TagData _tag_data;
   TagData _tag_data;
   VertexRef _vref;
   VertexRef _vref;
 
 
+  typedef pvector< PT(EggGroup) > GroupRefs;
+  GroupRefs _group_refs;
+
 
 
 public:
 public:
 
 

File diff suppressed because it is too large
+ 626 - 617
panda/src/egg/parser.cxx.prebuilt


+ 46 - 2
panda/src/egg/parser.yxx

@@ -79,6 +79,10 @@ static Textures textures;
 typedef pmap<string,  PT_EggMaterial > Materials;
 typedef pmap<string,  PT_EggMaterial > Materials;
 static Materials materials;
 static Materials materials;
 
 
+// Group names to groups.
+typedef pmap<string,  PT(EggGroup) > Groups;
+static Groups groups;
+
 // We need to be able to save the index number requested for a vertex
 // We need to be able to save the index number requested for a vertex
 // temporarily.
 // temporarily.
 static int vertex_index;
 static int vertex_index;
@@ -101,6 +105,7 @@ egg_init_parser(istream &in, const string &filename,
   vertex_pools.clear();
   vertex_pools.clear();
   textures.clear();
   textures.clear();
   materials.clear();
   materials.clear();
+  groups.clear();
 
 
   egg_stack.push_back(tos);
   egg_stack.push_back(tos);
   egg_top_node = top_node;
   egg_top_node = top_node;
@@ -140,6 +145,7 @@ egg_cleanup_parser() {
   vertex_pools.clear();
   vertex_pools.clear();
   textures.clear();
   textures.clear();
   materials.clear();
   materials.clear();
+  groups.clear();
 }
 }
 
 
 %}
 %}
@@ -208,6 +214,7 @@ egg_cleanup_parser() {
 %type <_egg> texture_name
 %type <_egg> texture_name
 %type <_egg> material_name
 %type <_egg> material_name
 %type <_egg> vertex_pool_name
 %type <_egg> vertex_pool_name
+%type <_egg> group_name
 
 
 %type <_number> real
 %type <_number> real
 %type <_number> integer
 %type <_number> integer
@@ -1137,8 +1144,12 @@ group:
 }
 }
         '{' group_body '}'
         '{' group_body '}'
 {
 {
-  $$ = egg_stack.back();
+  EggGroup *group = DCAST(EggGroup, egg_stack.back());
+  $$ = group;
   egg_stack.pop_back();
   egg_stack.pop_back();
+  if (group->has_name()) {
+    groups[group->get_name()] = group;
+  }
   Thread::consider_yield();
   Thread::consider_yield();
 }
 }
         ;
         ;
@@ -1180,8 +1191,12 @@ instance:
 }
 }
         '{' group_body '}'
         '{' group_body '}'
 {
 {
-  $$ = egg_stack.back();
+  EggGroup *group = DCAST(EggGroup, egg_stack.back());
+  $$ = group;
   egg_stack.pop_back();
   egg_stack.pop_back();
+  if (group->has_name()) {
+    groups[group->get_name()] = group;
+  }
 }
 }
         ;
         ;
 
 
@@ -1419,6 +1434,15 @@ group_body:
         | group_body transform
         | group_body transform
         | group_body group_vertex_ref
         | group_body group_vertex_ref
         | group_body switchcondition
         | group_body switchcondition
+        | group_body REF '{' group_name '}'
+{
+  EggGroup *group = DCAST(EggGroup, egg_stack.back());
+  if (group->get_group_type() != EggGroup::GT_instance) {
+    eggyyerror("<Ref> valid only within <Instance>");
+  } else if ($4 != (EggObject *)NULL) {
+    group->add_group_ref(DCAST(EggGroup, $4));
+  }
+}
         | group_body node
         | group_body node
 {
 {
   DCAST(EggGroup, egg_stack.back())->add_child(DCAST(EggNode, $2));
   DCAST(EggGroup, egg_stack.back())->add_child(DCAST(EggNode, $2));
@@ -2825,6 +2849,26 @@ vertex_pool_name:
 }
 }
         ;
         ;
 
 
+/*
+ * group_name
+ *
+ * enter: 
+ * exit: Returns an EggGroup pointer, or NULL.
+ *
+ */
+group_name:
+        required_name
+{
+  string name = $1;
+  Groups::iterator vpi = groups.find(name);
+  if (vpi == groups.end()) {
+    eggyyerror("Unknown group " + name);
+    $$ = PT(EggObject)();
+  } else {
+    $$ = (*vpi).second;
+  }
+}
+        ;
 
 
 /*
 /*
  * required_name
  * required_name

+ 14 - 0
panda/src/egg2pg/eggLoader.cxx

@@ -1758,6 +1758,7 @@ make_lod(EggBin *egg_bin, PandaNode *parent) {
     lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
     lod_node->add_switch(instance._d->_switch_in, instance._d->_switch_out);
   }
   }
 
 
+  _groups[egg_bin] = lod_node;
   return create_group_arc(egg_bin, parent, lod_node);
   return create_group_arc(egg_bin, parent, lod_node);
 }
 }
 
 
@@ -1897,6 +1898,19 @@ make_node(EggGroup *egg_group, PandaNode *parent) {
   if (node == (PandaNode *)NULL) {
   if (node == (PandaNode *)NULL) {
     return NULL;
     return NULL;
   }
   }
+
+  // Associate any instances with this node.
+  int num_group_refs = egg_group->get_num_group_refs();
+  for (int gri = 0; gri < num_group_refs; ++gri) {
+    EggGroup *group_ref = egg_group->get_group_ref(gri);
+    Groups::const_iterator gi = _groups.find(group_ref);
+    if (gi != _groups.end()) {
+      PandaNode *node_ref = (*gi).second;
+      node->add_child(node_ref);
+    }
+  }
+
+  _groups[egg_group] = node;
   return create_group_arc(egg_group, parent, node);
   return create_group_arc(egg_group, parent, node);
 }
 }
 
 

+ 3 - 0
panda/src/egg2pg/eggLoader.h

@@ -224,6 +224,9 @@ private:
   Materials _materials;
   Materials _materials;
   Materials _materials_bface;
   Materials _materials_bface;
 
 
+  typedef pmap<PT(EggGroup), PT(PandaNode) > Groups;
+  Groups _groups;
+
   typedef pset<PandaNode *> ExtraNodes;
   typedef pset<PandaNode *> ExtraNodes;
   ExtraNodes _decals;
   ExtraNodes _decals;
   ExtraNodes _sequences;
   ExtraNodes _sequences;

Some files were not shown because too many files changed in this diff