Browse Source

preserve tags while flattening

David Rose 19 years ago
parent
commit
55a8ab333b

+ 80 - 0
panda/src/pgraph/pandaNode.cxx

@@ -1492,6 +1492,86 @@ list_tags(ostream &out, const string &separator) const {
 #endif  // HAVE_PYTHON
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: PandaNode::compare_tags
+//       Access: Published
+//  Description: Returns a number less than 0, 0, or greater than 0,
+//               to indicate the similarity of tags between this node
+//               and the other one.  If this returns 0, the tags are
+//               identical.  If it returns other than 0, then the tags
+//               are different; and the nodes may be sorted into a
+//               consistent (but arbitrary) ordering based on this
+//               number.
+////////////////////////////////////////////////////////////////////
+int PandaNode::
+compare_tags(const PandaNode *other) const {
+  CDReader cdata(_cycler);
+  CDReader cdata_other(other->_cycler);
+
+  TagData::const_iterator ati = cdata->_tag_data.begin();
+  TagData::const_iterator bti = cdata_other->_tag_data.begin();
+  while (ati != cdata->_tag_data.end() &&
+         bti != cdata_other->_tag_data.end()) {
+    int cmp = strcmp((*ati).first.c_str(), (*bti).first.c_str());
+    if (cmp != 0) {
+      return cmp;
+    }
+
+    cmp = strcmp((*ati).second.c_str(), (*bti).second.c_str());
+    if (cmp != 0) {
+      return cmp;
+    }
+
+    ++ati;
+    ++bti;
+  }
+  if (ati != cdata->_tag_data.end()) {
+    // list A is longer.
+    return 1;
+  }
+  if (bti != cdata_other->_tag_data.end()) {
+    // list B is longer.
+    return -1;
+  }
+
+#ifdef HAVE_PYTHON
+  PythonTagData::const_iterator api = cdata->_python_tag_data.begin();
+  PythonTagData::const_iterator bpi = cdata_other->_python_tag_data.begin();
+  while (api != cdata->_python_tag_data.end() &&
+         bpi != cdata_other->_python_tag_data.end()) {
+    int cmp = strcmp((*api).first.c_str(), (*bpi).first.c_str());
+    if (cmp != 0) {
+      return cmp;
+    }
+
+    if (PyObject_Cmp((*api).second, (*bpi).second, &cmp) == -1) {
+      // Unable to compare objects; just compare pointers.
+      if ((*api).second != (*bpi).second) {
+        cmp = (*api).second < (*bpi).second ? -1 : 1;
+      } else {
+        cmp = 0;
+      }
+    }
+    if (cmp != 0) {
+      return cmp;
+    }
+
+    ++api;
+    ++bpi;
+  }
+  if (api != cdata->_python_tag_data.end()) {
+    // list A is longer.
+    return 1;
+  }
+  if (bpi != cdata_other->_python_tag_data.end()) {
+    // list B is longer.
+    return -1;
+  }
+#endif  // HAVE_PYTHON
+
+  return 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: PandaNode::copy_all_properties
 //       Access: Published

+ 2 - 0
panda/src/pgraph/pandaNode.h

@@ -199,6 +199,8 @@ PUBLISHED:
   void copy_tags(PandaNode *other);
   void list_tags(ostream &out, const string &separator = "\n") const;
 
+  int compare_tags(const PandaNode *other) const;
+
   void copy_all_properties(PandaNode *other);
   void replace_node(PandaNode *other);
 

+ 6 - 1
panda/src/pgraph/sceneGraphReducer.cxx

@@ -355,6 +355,10 @@ operator () (const PandaNode *node1, const PandaNode *node2) const {
   if (node1->get_draw_show_mask() != node2->get_draw_show_mask()) {
     return node1->get_draw_show_mask() < node2->get_draw_show_mask();
   }
+  int cmp = (node1->compare_tags(node2));
+  if (cmp != 0) {
+    return cmp < 0;
+  }
 
   return 0;
 }
@@ -461,7 +465,8 @@ consider_child(PandaNode *grandparent_node, PandaNode *parent_node,
       parent_node->get_state() != child_node->get_state() ||
       parent_node->get_effects() != child_node->get_effects() ||
       parent_node->get_draw_control_mask() != child_node->get_draw_control_mask() ||
-      parent_node->get_draw_show_mask() != child_node->get_draw_show_mask()) {
+      parent_node->get_draw_show_mask() != child_node->get_draw_show_mask() ||
+      parent_node->compare_tags(child_node) != 0) {
     // The two nodes have a different state; too bad.
     return false;
   }