diff --git a/panda/src/pgraph/modelNode.cxx b/panda/src/pgraph/modelNode.cxx index 0e63c94705..b2b45a4c45 100644 --- a/panda/src/pgraph/modelNode.cxx +++ b/panda/src/pgraph/modelNode.cxx @@ -34,6 +34,32 @@ make_copy() const { return new ModelNode(*this); } +//////////////////////////////////////////////////////////////////// +// Function: ModelNode::combine_with +// Access: Public, Virtual +// Description: Collapses this PandaNode with the other PandaNode, if +// possible, and returns a pointer to the combined +// PandaNode, or NULL if the two PandaNodes cannot +// safely be combined. +// +// The return value may be this, other, or a new +// PandaNode altogether. +// +// This function is called from GraphReducer::flatten(), +// and need not deal with children; its job is just to +// decide whether to collapse the two PandaNodes and +// what the collapsed PandaNode should look like. +//////////////////////////////////////////////////////////////////// +PandaNode *ModelNode:: +combine_with(PandaNode *other) { + if (_preserve_transform == PT_drop_node) { + // If we have PT_drop_node set, we always yield to the other node. + return other; + } + + return PandaNode::combine_with(other); +} + //////////////////////////////////////////////////////////////////// // Function: ModelNode::safe_to_flatten // Access: Public, Virtual @@ -45,7 +71,7 @@ make_copy() const { //////////////////////////////////////////////////////////////////// bool ModelNode:: safe_to_flatten() const { - return false; + return _preserve_transform == PT_drop_node; } //////////////////////////////////////////////////////////////////// @@ -58,7 +84,7 @@ safe_to_flatten() const { //////////////////////////////////////////////////////////////////// bool ModelNode:: safe_to_transform() const { - return _preserve_transform == PT_none; + return _preserve_transform == PT_none || _preserve_transform == PT_drop_node; } //////////////////////////////////////////////////////////////////// @@ -90,7 +116,7 @@ safe_to_modify_transform() const { //////////////////////////////////////////////////////////////////// bool ModelNode:: safe_to_combine() const { - return false; + return _preserve_transform == PT_drop_node; } //////////////////////////////////////////////////////////////////// @@ -102,7 +128,7 @@ safe_to_combine() const { //////////////////////////////////////////////////////////////////// bool ModelNode:: preserve_name() const { - return true; + return _preserve_transform != PT_drop_node; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/pgraph/modelNode.h b/panda/src/pgraph/modelNode.h index 14bfd50d60..81ab574a63 100644 --- a/panda/src/pgraph/modelNode.h +++ b/panda/src/pgraph/modelNode.h @@ -41,6 +41,7 @@ protected: public: virtual PandaNode *make_copy() const; + virtual PandaNode *combine_with(PandaNode *other); virtual bool safe_to_flatten() const; virtual bool safe_to_transform() const; virtual bool safe_to_modify_transform() const; @@ -52,7 +53,8 @@ PUBLISHED: enum PreserveTransform { PT_none, PT_local, - PT_net + PT_net, + PT_drop_node, }; INLINE void set_preserve_transform(PreserveTransform preserve_transform); diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 7c3ff876f6..6e1ea71b87 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -2131,6 +2131,23 @@ compare_to(const NodePath &other) const { return 0; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::clear_model_nodes +// Access: Published +// Description: Recursively walks through the scene graph at this +// level and below, looking for ModelNodes, and calls +// model_node->set_preserve_transform(PT_drop_node) on +// each one. This allows a subsequent call to +// flatten_strong() to eliminate all of the ModelNodes. +// +// Returns the number of ModelNodes found. +//////////////////////////////////////////////////////////////////// +INLINE int NodePath:: +clear_model_nodes() { + nassertr_always(!is_empty(), 0); + return r_clear_model_nodes(node()); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::set_tag // Access: Published diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index a8a92eeee3..80fd1b50b7 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -64,6 +64,7 @@ #include "dcast.h" #include "pStatCollector.h" #include "pStatTimer.h" +#include "modelNode.h" // stack seems to overflow on Intel C++ at 7000. If we need more than // 7000, need to increase stack size. @@ -6303,6 +6304,33 @@ find_matches(NodePathCollection &result, FindApproxLevelEntry *level, } } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::r_clear_model_nodes +// Access: Private +// Description: The recursive implementation of +// clear_model_nodes(). This walks through the +// subgraph defined by the indicated node and below. +//////////////////////////////////////////////////////////////////// +int NodePath:: +r_clear_model_nodes(PandaNode *node) { + int count = 0; + + if (node->is_of_type(ModelNode::get_class_type())) { + ModelNode *mnode; + DCAST_INTO_R(mnode, node, count); + mnode->set_preserve_transform(ModelNode::PT_drop_node); + ++count; + } + + PandaNode::Children cr = node->get_children(); + int num_children = cr.get_num_children(); + for (int i = 0; i < num_children; i++) { + count += r_clear_model_nodes(cr.get_child(i)); + } + + return count; +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::r_adjust_all_priorities // Access: Private diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index e8006d8bb8..b5e64ce783 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -807,6 +807,7 @@ PUBLISHED: int flatten_light(); int flatten_medium(); int flatten_strong(); + INLINE int clear_model_nodes(); INLINE void set_tag(const string &key, const string &value); INLINE string get_tag(const string &key) const; @@ -863,6 +864,7 @@ private: FindApproxLevelEntry *level, int max_matches) const; + int r_clear_model_nodes(PandaNode *node); void r_adjust_all_priorities(PandaNode *node, int adjustment); void r_force_recompute_bounds(PandaNode *node);