diff --git a/panda/src/pgraph/pandaNode.cxx b/panda/src/pgraph/pandaNode.cxx index 11929ec624..6aa1266286 100644 --- a/panda/src/pgraph/pandaNode.cxx +++ b/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 diff --git a/panda/src/pgraph/pandaNode.h b/panda/src/pgraph/pandaNode.h index 697673fc67..4e4cc0c67f 100644 --- a/panda/src/pgraph/pandaNode.h +++ b/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); diff --git a/panda/src/pgraph/sceneGraphReducer.cxx b/panda/src/pgraph/sceneGraphReducer.cxx index 371a43a6d7..06b54ab2d9 100644 --- a/panda/src/pgraph/sceneGraphReducer.cxx +++ b/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; }