diff --git a/panda/src/framework/framework.cxx b/panda/src/framework/framework.cxx index e3481de15a..e1c183a648 100644 --- a/panda/src/framework/framework.cxx +++ b/panda/src/framework/framework.cxx @@ -738,7 +738,7 @@ void event_C(CPT_Event) { void event_N(CPT_Event) { nout << "Reducing scene graph.\n"; SceneGraphReducer gr(RenderRelation::get_class_type()); - gr.apply_transitions(root); + gr.apply_transitions(first_arc); int num_reduced = gr.flatten(root, true); nout << "Removed " << num_reduced << " arcs.\n"; } @@ -1120,8 +1120,8 @@ int framework_main(int argc, char *argv[]) { first_arc = new RenderRelation(render, root, 100); if (files.empty() && framework.GetBool("have-omnitriangle", true)) { - // The user did not specify an file. Create some default - // geometry. + // The user did not specify a model file to load. Create some + // default geometry. PTA_Vertexf coords; PTA_TexCoordf uvs; diff --git a/panda/src/graph/nodeRelation.I b/panda/src/graph/nodeRelation.I index 1285edb48d..641cf0dcc3 100644 --- a/panda/src/graph/nodeRelation.I +++ b/panda/src/graph/nodeRelation.I @@ -10,9 +10,9 @@ // attaches it. //////////////////////////////////////////////////////////////////// INLINE NodeRelation:: -NodeRelation(Node *parent, Node *to, int sort, TypeHandle type) : +NodeRelation(Node *parent, Node *to, int sort, TypeHandle graph_type) : _parent(parent), _child(to), _sort(sort), - _type(type), _num_transitions(0) + _graph_type(graph_type), _num_transitions(0) { _top_subtree = NULL; _attached = false; @@ -29,8 +29,8 @@ NodeRelation(Node *parent, Node *to, int sort, TypeHandle type) : // general, attempt to create an unattached arc. //////////////////////////////////////////////////////////////////// INLINE NodeRelation:: -NodeRelation(TypeHandle type) : - _type(type) +NodeRelation(TypeHandle graph_type) : + _graph_type(graph_type) { _parent = NULL; _child = NULL; @@ -49,14 +49,13 @@ NodeRelation(TypeHandle type) : // unattached arc. //////////////////////////////////////////////////////////////////// INLINE NodeRelation:: -NodeRelation(void) -{ +NodeRelation(void) { _parent = NULL; _child = NULL; _sort = 0; _top_subtree = NULL; _attached = false; - _type = get_class_type(); + _graph_type = get_class_type(); _num_transitions = 0; } @@ -124,6 +123,20 @@ get_sort() const { return _sort; } +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::get_graph_type +// Access: Public +// Description: Returns the type of graph this arc represents. This +// is normally the same value as get_type(), i.e. the +// class type of the arc, but it may be set to any type. +// A node may simultaneously have many arcs of different +// types. +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle NodeRelation:: +get_graph_type() const { + return _graph_type; +} + //////////////////////////////////////////////////////////////////// // Function: NodeRelation::change_parent // Access: Public @@ -189,6 +202,20 @@ set_sort(int sort) { attach(); } +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::set_graph_type +// Access: Public +// Description: Changes the graph type of the arc. This moves the +// arc into a totally different graph; it may now be +// detected only by a special traversal. +//////////////////////////////////////////////////////////////////// +INLINE void NodeRelation:: +set_graph_type(TypeHandle graph_type) { + PT(NodeRelation) hold_arc = detach(); + _graph_type = graph_type; + attach(); +} + //////////////////////////////////////////////////////////////////// // Function: NodeRelation::set_transition // Access: Public @@ -390,6 +417,31 @@ get_factory() { return *_factory; } +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::get_class_type +// Access: Public, Static +// Description: Returns the TypeHandle associated with this type. +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle NodeRelation:: +get_class_type() { + return _type_handle; +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::get_stashed_type +// Access: Public, Static +// Description: Returns a special TypeHandle that, by convention, +// arcs that wish to remove themselves from normal +// consideration during any traversal (including +// rendering and collision traversals), as well as +// removing themselves from the bounding volumes of +// their parents, should set their graph_type to. +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle NodeRelation:: +get_stashed_type() { + return _stashed_type_handle; +} + //////////////////////////////////////////////////////////////////// // Function: get_transition_into // Description: This external template function is handy for diff --git a/panda/src/graph/nodeRelation.cxx b/panda/src/graph/nodeRelation.cxx index 0f33d9375a..fdbf363065 100644 --- a/panda/src/graph/nodeRelation.cxx +++ b/panda/src/graph/nodeRelation.cxx @@ -12,6 +12,7 @@ #include TypeHandle NodeRelation::_type_handle; +TypeHandle NodeRelation::_stashed_type_handle; Factory *NodeRelation::_factory = NULL; @@ -507,8 +508,8 @@ attach() { _attached = true; - DownRelationPointers &parent_list = _parent->_children[_type]; - UpRelationPointers &child_list = _child->_parents[_type]; + DownRelationPointers &parent_list = _parent->_children[_graph_type]; + UpRelationPointers &child_list = _child->_parents[_graph_type]; bool inserted_one = internal_insert_arc(parent_list, this); bool inserted_two = internal_insert_arc(child_list, this); @@ -516,7 +517,7 @@ attach() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - _last_update = ++last_graph_update(_type); + _last_update = ++last_graph_update(_graph_type); // If we have just added a new parent arc to a node that previously // had exactly one parent, we also need to set the update sequence @@ -557,8 +558,8 @@ detach() { force_bound_stale(); - DownRelationPointers &parent_list = _parent->_children[_type]; - UpRelationPointers &child_list = _child->_parents[_type]; + DownRelationPointers &parent_list = _parent->_children[_graph_type]; + UpRelationPointers &child_list = _child->_parents[_graph_type]; bool removed_one = internal_remove_arc(parent_list, this); bool removed_two = internal_remove_arc(child_list, this); @@ -570,7 +571,7 @@ detach() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - _last_update = ++last_graph_update(_type); + _last_update = ++last_graph_update(_graph_type); // If we have just removed a parent arc from a node, leaving exactly // one parent, we also need to set the update sequence @@ -580,6 +581,16 @@ detach() { child_list[0]->_last_update = _last_update; } + // If we have completely emptied the parent or child lists, remove + // the entry for this graph type from the node, as a small render + // optimization. + if (parent_list.empty()) { + _parent->_children.erase(_graph_type); + } + if (child_list.empty()) { + _child->_parents.erase(_graph_type); + } + return result; } @@ -601,7 +612,7 @@ detach_below() { force_bound_stale(); - bool removed = internal_remove_arc(_child->_parents[_type], this); + bool removed = internal_remove_arc(_child->_parents[_graph_type], this); nassertr(removed, result); @@ -609,7 +620,7 @@ detach_below() { // Blow out the cache and increment the current update sequence. _net_transitions.clear(); - _last_update = ++last_graph_update(_type); + _last_update = ++last_graph_update(_graph_type); return result; } @@ -631,7 +642,7 @@ changed_transition(TypeHandle trans_type) { if (_net_transitions != (NodeTransitionCache *)NULL) { _net_transitions->clear_transition(trans_type); } - _last_update = ++last_graph_update(get_type()); + _last_update = ++last_graph_update(_graph_type); } //////////////////////////////////////////////////////////////////// @@ -648,7 +659,7 @@ propagate_stale_bound() { nassertv(node != (Node*)NULL); UpRelations::const_iterator uri; - uri = node->_parents.find(get_type()); + uri = node->_parents.find(_graph_type); if (uri != node->_parents.end()) { const UpRelationPointers &urp = (*uri).second; @@ -681,7 +692,7 @@ recompute_bound() { child_volumes.push_back(&node->get_bound()); DownRelations::const_iterator dri; - dri = node->_children.find(get_type()); + dri = node->_children.find(_graph_type); if (dri != node->_children.end()) { const DownRelationPointers &drp = (*dri).second; @@ -717,7 +728,7 @@ void NodeRelation:: write_datagram(BamWriter *manager, Datagram &me) { //Write out the "dynamic" type - manager->write_handle(me, _type); + manager->write_handle(me, _graph_type); //We should always be attached if we are trying to write out nassertv(_attached); @@ -769,7 +780,7 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager) // We must explicitly add the arc to its child node, but not to // its parent node. - UpRelationPointers &child_list = _child->_parents[_type]; + UpRelationPointers &child_list = _child->_parents[_graph_type]; bool inserted = internal_insert_arc(child_list, this); nassertr(inserted, _num_transitions + 2); _attached = true; @@ -785,8 +796,9 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager) //at old code if (plist[i] == TypedWriteable::Null) { - graph_cat->warning() << get_type().get_name() - << "Ignoring null Transition" << endl; + graph_cat->warning() + << get_type().get_name() + << ": Ignoring null Transition" << endl; } else { @@ -829,7 +841,7 @@ make_NodeRelation(const FactoryParams ¶ms) void NodeRelation:: fillin(DatagramIterator& scan, BamReader* manager) { - _type = manager->read_handle(scan); + _graph_type = manager->read_handle(scan); //Read in my parent manager->read_pointer(scan, this); //Read in my child @@ -855,3 +867,46 @@ register_with_read_factory(void) { BamReader::get_factory()->register_factory(get_class_type(), make_NodeRelation); } + +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::init_type +// Access: Public, Static +// Description: Initializes the TypeHandles associated with this +// class. +//////////////////////////////////////////////////////////////////// +void NodeRelation:: +init_type() { + TypedWriteableReferenceCount::init_type(); + BoundedObject::init_type(); + register_type(_type_handle, "NodeRelation", + TypedWriteableReferenceCount::get_class_type(), + BoundedObject::get_class_type()); + register_type(_stashed_type_handle, "StashedNodeRelation", + get_class_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::get_type +// Access: Public, Virtual +// Description: Returns the particular type represented by this +// instance of the class. +//////////////////////////////////////////////////////////////////// +TypeHandle NodeRelation:: +get_type() const { + return get_class_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodeRelation::force_init_type +// Access: Public, Virtual +// Description: Called by the TypeHandle system when it is detected +// that init_type() was not called for some reason. +// This is only called in an error situation, and it +// attempts to remedy the problem so we can recover and +// continue. +//////////////////////////////////////////////////////////////////// +TypeHandle NodeRelation:: +force_init_type() { + init_type(); + return get_class_type(); +} diff --git a/panda/src/graph/nodeRelation.h b/panda/src/graph/nodeRelation.h index b18271b3e2..21bf22cc2b 100644 --- a/panda/src/graph/nodeRelation.h +++ b/panda/src/graph/nodeRelation.h @@ -47,13 +47,13 @@ extern EXPCL_PANDA UpdateSeq &last_graph_update(TypeHandle graph_type); //////////////////////////////////////////////////////////////////// class EXPCL_PANDA NodeRelation : public TypedWriteableReferenceCount, public BoundedObject { public: - INLINE NodeRelation(Node *from, Node *to, int sort, TypeHandle type); + INLINE NodeRelation(Node *from, Node *to, int sort, TypeHandle graph_type); protected: // Normally, this should only be used from derived classes for // passing to the factory. Don't attempt to create an unattached // arc directly. - INLINE NodeRelation(TypeHandle type); + INLINE NodeRelation(TypeHandle graph_type); //make_NodeRelation needs to have a construct that takes nothing //since it creates the object before it has any information @@ -80,12 +80,14 @@ PUBLISHED: INLINE Node *get_parent() const; INLINE Node *get_child() const; INLINE int get_sort() const; + INLINE TypeHandle get_graph_type() const; INLINE void change_parent(Node *parent); INLINE void change_parent(Node *parent, int sort); INLINE void change_child(Node *child); INLINE void change_parent_and_child(Node *parent, Node *child); INLINE void set_sort(int sort); + INLINE void set_graph_type(TypeHandle graph_type); INLINE PT(NodeTransition) set_transition(TypeHandle handle, NodeTransition *trans); @@ -141,7 +143,7 @@ private: Node *_parent; PT_Node _child; int _sort; - TypeHandle _type; + TypeHandle _graph_type; bool _attached; private: @@ -193,24 +195,18 @@ protected: virtual void propagate_stale_bound(); virtual void recompute_bound(); +PUBLISHED: + INLINE static TypeHandle get_class_type(); + INLINE static TypeHandle get_stashed_type(); + public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - TypedWriteableReferenceCount::init_type(); - BoundedObject::init_type(); - register_type(_type_handle, "NodeRelation", - TypedWriteableReferenceCount::get_class_type(), - BoundedObject::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static void init_type(); + virtual TypeHandle get_type() const; + virtual TypeHandle force_init_type(); private: static TypeHandle _type_handle; + static TypeHandle _stashed_type_handle; friend INLINE void remove_arc(NodeRelation *arc); friend class Node; diff --git a/panda/src/sgattrib/renderRelation.I b/panda/src/sgattrib/renderRelation.I index 724f2bcac4..89485f515c 100644 --- a/panda/src/sgattrib/renderRelation.I +++ b/panda/src/sgattrib/renderRelation.I @@ -39,3 +39,13 @@ INLINE void RenderRelation:: register_with_factory() { get_factory().register_factory(get_class_type(), make_arc); } + +//////////////////////////////////////////////////////////////////// +// Function: RenderRelation::get_class_type +// Access: Public, Static +// Description: Returns the TypeHandle associated with this type. +//////////////////////////////////////////////////////////////////// +INLINE TypeHandle RenderRelation:: +get_class_type() { + return _type_handle; +} diff --git a/panda/src/sgattrib/renderRelation.cxx b/panda/src/sgattrib/renderRelation.cxx index 7a31ffd688..eda9b84682 100644 --- a/panda/src/sgattrib/renderRelation.cxx +++ b/panda/src/sgattrib/renderRelation.cxx @@ -98,3 +98,43 @@ register_with_read_factory(void) { BamReader::get_factory()->register_factory(get_class_type(), make_RenderRelation); } + + +//////////////////////////////////////////////////////////////////// +// Function: RenderRelation::init_type +// Access: Public, Static +// Description: Initializes the TypeHandles associated with this +// class. +//////////////////////////////////////////////////////////////////// +void RenderRelation:: +init_type() { + NodeRelation::init_type(); + register_type(_type_handle, "RenderRelation", + NodeRelation::get_class_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderRelation::get_type +// Access: Public, Virtual +// Description: Returns the particular type represented by this +// instance of the class. +//////////////////////////////////////////////////////////////////// +TypeHandle RenderRelation:: +get_type() const { + return get_class_type(); +} + +//////////////////////////////////////////////////////////////////// +// Function: RenderRelation::force_init_type +// Access: Public, Virtual +// Description: Called by the TypeHandle system when it is detected +// that init_type() was not called for some reason. +// This is only called in an error situation, and it +// attempts to remedy the problem so we can recover and +// continue. +//////////////////////////////////////////////////////////////////// +TypeHandle RenderRelation:: +force_init_type() { + init_type(); + return get_class_type(); +} diff --git a/panda/src/sgattrib/renderRelation.h b/panda/src/sgattrib/renderRelation.h index 8b7cbdea6b..590100cb83 100644 --- a/panda/src/sgattrib/renderRelation.h +++ b/panda/src/sgattrib/renderRelation.h @@ -43,20 +43,12 @@ public: static TypedWriteable *make_RenderRelation(const FactoryParams ¶ms); PUBLISHED: - static TypeHandle get_class_type() { - return _type_handle; - } + INLINE static TypeHandle get_class_type(); public: - static void init_type() { - NodeRelation::init_type(); - register_type(_type_handle, "RenderRelation", - NodeRelation::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} + static void init_type(); + virtual TypeHandle get_type() const; + virtual TypeHandle force_init_type(); private: static TypeHandle _type_handle; diff --git a/panda/src/sgmanip/findApproxLevel.I b/panda/src/sgmanip/findApproxLevel.I index d314fc0019..63254dd78f 100644 --- a/panda/src/sgmanip/findApproxLevel.I +++ b/panda/src/sgmanip/findApproxLevel.I @@ -44,6 +44,17 @@ operator = (const FindApproxLevelEntry ©) { } +//////////////////////////////////////////////////////////////////// +// Function: FindApproxLevelEntry::next_is_stashed +// Access: Public +// Description: Returns true if the next node matched by this entry +// must be a stashed node, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool FindApproxLevelEntry:: +next_is_stashed() const { + return _approx_path.matches_stashed(_i); +} + //////////////////////////////////////////////////////////////////// // Function: FindApproxLevelEntry::is_solution // Access: Public diff --git a/panda/src/sgmanip/findApproxLevel.cxx b/panda/src/sgmanip/findApproxLevel.cxx index ce9ce210e0..73e1737193 100644 --- a/panda/src/sgmanip/findApproxLevel.cxx +++ b/panda/src/sgmanip/findApproxLevel.cxx @@ -30,6 +30,61 @@ output(ostream &out) const { } } +//////////////////////////////////////////////////////////////////// +// Function: FindApproxLevelEntry::consider_node +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void FindApproxLevelEntry:: +consider_node(NodePathCollection &result, FindApproxLevel &next_level, + int max_matches, TypeHandle graph_type) const { + nassertv(_i < _approx_path.get_num_components()); + + if (_approx_path.is_component_match_many(_i)) { + // Match any number, zero or more, levels of nodes. This is the + // tricky case that requires this whole nutty breadth-first thing. + + // This means we must reconsider our own entry with the next path + // entry, before we consider the next entry--this supports + // matching zero levels of nodes. + FindApproxLevelEntry reconsider(*this); + ++reconsider._i; + + if (reconsider.is_solution()) { + // Does this now represent a solution? + result.add_path(reconsider._node_path); + if (max_matches > 0 && result.get_num_paths() >= max_matches) { + return; + } + } else { + reconsider.consider_node(result, next_level, max_matches, graph_type); + } + } + + Node *bottom_node = _node_path.node(); + nassertv(bottom_node != (Node *)NULL); + + TypeHandle next_graph_type = graph_type; + if (next_is_stashed()) { + next_graph_type = NodeRelation::get_stashed_type(); + } + + DownRelations::const_iterator dri; + dri = bottom_node->_children.find(next_graph_type); + if (dri != bottom_node->_children.end()) { + const DownRelationPointers &drp = (*dri).second; + + DownRelationPointers::const_iterator drpi; + for (drpi = drp.begin(); drpi != drp.end(); ++drpi) { + NodeRelation *arc = (*drpi); + consider_next_step(result, arc, next_level, max_matches, graph_type); + if (max_matches > 0 && result.get_num_paths() >= max_matches) { + return; + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: FindApproxLevelEntry::consider_next_step // Access: Public @@ -40,47 +95,28 @@ output(ostream &out) const { // whatever additional entries are appropriate and // stores them in next_level. // -// If a complete solution is found, returns the solution -// node; otherwise, returns NULL. +// If a complete solution is found, stores it in result. //////////////////////////////////////////////////////////////////// void FindApproxLevelEntry:: consider_next_step(NodePathCollection &result, NodeRelation *arc, FindApproxLevel &next_level, - int max_matches) const { + int max_matches, TypeHandle graph_type) const { nassertv(_i < _approx_path.get_num_components()); FindApproxLevelEntry next(*this); bool eb = next._node_path.extend_by(arc); nassertv(eb); - Node *child = arc->get_child(); if (_approx_path.is_component_match_many(_i)) { // Match any number, zero or more, levels of nodes. This is the // tricky case that requires this whole nutty breadth-first thing. - // This means we must reconsider our own entry with the next - // path entry, before we consider the next entry. - FindApproxLevelEntry reconsider(*this); - ++reconsider._i; - if (reconsider.is_solution()) { - // Does this now represent a solution? - bool eb = reconsider._node_path.extend_by(arc); - nassertv(eb); - result.add_path(reconsider._node_path); - } else { - reconsider.consider_next_step(result, arc, next_level, max_matches); - } - - if (max_matches > 0 && result.get_num_paths() >= max_matches) { - return; - } - // And now we just add the next entry without incrementing its // path entry. next_level.add_entry(next); } else { - if (_approx_path.matches_component(_i, child)) { + if (_approx_path.matches_component(_i, arc)) { // That matched, and it consumes one path entry. ++next._i; next_level.add_entry(next); diff --git a/panda/src/sgmanip/findApproxLevel.h b/panda/src/sgmanip/findApproxLevel.h index 7c50676140..2d19fe6ddf 100644 --- a/panda/src/sgmanip/findApproxLevel.h +++ b/panda/src/sgmanip/findApproxLevel.h @@ -32,9 +32,13 @@ public: INLINE FindApproxLevelEntry(const FindApproxLevelEntry ©); INLINE void operator = (const FindApproxLevelEntry ©); + INLINE bool next_is_stashed() const; + + void consider_node(NodePathCollection &result, FindApproxLevel &next_level, + int max_matches, TypeHandle graph_type) const; void consider_next_step(NodePathCollection &result, NodeRelation *arc, FindApproxLevel &next_level, - int max_matches) const; + int max_matches, TypeHandle graph_type) const; INLINE bool is_solution() const; void output(ostream &out) const; diff --git a/panda/src/sgmanip/findApproxPath.I b/panda/src/sgmanip/findApproxPath.I index 043a6b629c..ac887b43ae 100644 --- a/panda/src/sgmanip/findApproxPath.I +++ b/panda/src/sgmanip/findApproxPath.I @@ -20,10 +20,11 @@ FindApproxPath() { // exactly. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_name(const string &name) { +add_match_name(const string &name, int flags) { Component comp; comp._type = CT_match_name; comp._name = name; + comp._flags = flags; _path.push_back(comp); } @@ -35,10 +36,11 @@ add_match_name(const string &name) { // characters accepted. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_name_glob(const string &name) { +add_match_name_glob(const string &name, int flags) { Component comp; comp._type = CT_match_name_glob; comp._name = name; + comp._flags = flags; _path.push_back(comp); } @@ -49,10 +51,11 @@ add_match_name_glob(const string &name) { // exactly, with no derived types matching. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_exact_type(TypeHandle type) { +add_match_exact_type(TypeHandle type, int flags) { Component comp; comp._type = CT_match_exact_type; comp._type_handle = type; + comp._flags = flags; _path.push_back(comp); } @@ -63,10 +66,11 @@ add_match_exact_type(TypeHandle type) { // or be a base class of the node's type. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_inexact_type(TypeHandle type) { +add_match_inexact_type(TypeHandle type, int flags) { Component comp; comp._type = CT_match_inexact_type; comp._type_handle = type; + comp._flags = flags; _path.push_back(comp); } @@ -77,9 +81,10 @@ add_match_inexact_type(TypeHandle type) { // chain of many nodes). //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_one() { +add_match_one(int flags) { Component comp; comp._type = CT_match_one; + comp._flags = flags; _path.push_back(comp); } @@ -90,9 +95,10 @@ add_match_one() { // more consecutive nodes. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_many() { +add_match_many(int flags) { Component comp; comp._type = CT_match_many; + comp._flags = flags; _path.push_back(comp); } @@ -103,10 +109,11 @@ add_match_many() { // exactly, by pointer. //////////////////////////////////////////////////////////////////// INLINE void FindApproxPath:: -add_match_pointer(Node *pointer) { +add_match_pointer(Node *pointer, int flags) { Component comp; comp._type = CT_match_pointer; comp._pointer = pointer; + comp._flags = flags; _path.push_back(comp); } @@ -139,9 +146,24 @@ is_component_match_many(int index) const { // the indicated node, false otherwise. //////////////////////////////////////////////////////////////////// INLINE bool FindApproxPath:: -matches_component(int index, Node *node) const { +matches_component(int index, NodeRelation *arc) const { nassertr(index >= 0 && index < (int)_path.size(), false); - return (_path[index].matches(node)); + return (_path[index].matches(arc)); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::matches_stashed +// Access: Public +// Description: Returns true if the nth component of the path matches +// a stashed node only, false otherwise. +//////////////////////////////////////////////////////////////////// +INLINE bool FindApproxPath:: +matches_stashed(int index) const { + if (index >= 0 && index < (int)_path.size()) { + return ((_path[index]._flags & CF_stashed) != 0); + } else { + return false; + } } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/sgmanip/findApproxPath.cxx b/panda/src/sgmanip/findApproxPath.cxx index c6f93e56bb..fceafe4a9f 100644 --- a/panda/src/sgmanip/findApproxPath.cxx +++ b/panda/src/sgmanip/findApproxPath.cxx @@ -9,6 +9,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////// @@ -18,7 +19,8 @@ // component, false otherwise. //////////////////////////////////////////////////////////////////// bool FindApproxPath::Component:: -matches(Node *node) const { +matches(NodeRelation *arc) const { + Node *node = arc->get_child(); string node_name; switch (_type) { @@ -113,12 +115,22 @@ add_string(const string &str_path) { // the string component was in some way invalid. //////////////////////////////////////////////////////////////////// bool FindApproxPath:: -add_component(const string &str_component) { +add_component(string str_component) { + int flags = 0; + if (str_component.size() >= 2 && str_component.substr(0, 2) == "@@") { + flags |= CF_stashed; + str_component = str_component.substr(2); + } + if (str_component == "*") { - add_match_one(); + add_match_one(flags); } else if (str_component == "**") { - add_match_many(); + if ((flags & CF_stashed) != 0) { + sgmanip_cat.warning() + << "@@** is ambiguous; use @@*/** or **/@@* instead.\n"; + } + add_match_many(flags); } else if (!str_component.empty() && str_component[0] == '-') { string type_name = str_component.substr(1); @@ -130,7 +142,7 @@ add_component(const string &str_component) { return false; } else { - add_match_exact_type(handle); + add_match_exact_type(handle, flags); } } else if (!str_component.empty() && str_component[0] == '+') { @@ -143,11 +155,11 @@ add_component(const string &str_component) { return false; } else { - add_match_inexact_type(handle); + add_match_inexact_type(handle, flags); } } else { - add_match_name_glob(str_component); + add_match_name_glob(str_component, flags); } return true; diff --git a/panda/src/sgmanip/findApproxPath.h b/panda/src/sgmanip/findApproxPath.h index 8a57b7a8d4..83895bebfd 100644 --- a/panda/src/sgmanip/findApproxPath.h +++ b/panda/src/sgmanip/findApproxPath.h @@ -14,6 +14,7 @@ #include class Node; +class NodeRelation; //////////////////////////////////////////////////////////////////// // Class : FindApproxPath @@ -27,19 +28,20 @@ public: INLINE FindApproxPath(); bool add_string(const string &str_path); - bool add_component(const string &str_component); + bool add_component(string str_component); - INLINE void add_match_name(const string &name); - INLINE void add_match_name_glob(const string &glob); - INLINE void add_match_exact_type(TypeHandle type); - INLINE void add_match_inexact_type(TypeHandle type); - INLINE void add_match_one(); - INLINE void add_match_many(); - INLINE void add_match_pointer(Node *pointer); + INLINE void add_match_name(const string &name, int flags); + INLINE void add_match_name_glob(const string &glob, int flags); + INLINE void add_match_exact_type(TypeHandle type, int flags); + INLINE void add_match_inexact_type(TypeHandle type, int flags); + INLINE void add_match_one(int flags); + INLINE void add_match_many(int flags); + INLINE void add_match_pointer(Node *pointer, int flags); INLINE int get_num_components() const; INLINE bool is_component_match_many(int index) const; - INLINE bool matches_component(int index, Node *node) const; + INLINE bool matches_component(int index, NodeRelation *arc) const; + INLINE bool matches_stashed(int index) const; void output(ostream &out) const; INLINE void output_component(ostream &out, int index) const; @@ -58,16 +60,20 @@ private: CT_match_many, CT_match_pointer }; + enum ComponentFlags { + CF_stashed = 0x001, + }; class Component { public: - bool matches(Node *node) const; + bool matches(NodeRelation *arc) const; void output(ostream &out) const; ComponentType _type; string _name; TypeHandle _type_handle; Node *_pointer; + int _flags; }; typedef vector Path; diff --git a/panda/src/sgmanip/nodePath.I b/panda/src/sgmanip/nodePath.I index ca2442cedc..a75953be94 100644 --- a/panda/src/sgmanip/nodePath.I +++ b/panda/src/sgmanip/nodePath.I @@ -98,6 +98,7 @@ INLINE NodePath:: NodePath(const ArcChain &chain, TypeHandle graph_type) : NodePathBase(chain, graph_type) { + reset_top_node(); nassertv(verify_connectivity()); } @@ -262,6 +263,18 @@ get_num_nodes() const { return get_num_arcs() + 1; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::get_top_node +// Access: Public +// Description: Returns the top node of the path, or NULL if the path +// is empty. +//////////////////////////////////////////////////////////////////// +INLINE Node *NodePath:: +get_top_node() { + reset_top_node(); + return _top_node; +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::node // Access: Public @@ -1409,6 +1422,13 @@ show() { // Access: Public // Description: Puts a PruneTransition on this bottom arc so that the // geometry at this level and below will be invisible. +// +// However, it will remain part of the scene graph, and +// will still be counted in its parent's bounding +// volume; furthermore, traversals like the collision +// traversal will still visit the node. +// +// See stash() for a more thorough way to hide the node. //////////////////////////////////////////////////////////////////// INLINE void NodePath:: hide() { @@ -1439,3 +1459,61 @@ INLINE void NodePath:: hide_collision_solids() { find_all_matches("**/+CollisionNode").hide(); } + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::is_hidden +// Access: Public +// Description: Returns true if some arc above this bottom node has +// been set to 'hide', false if it should be visible. +//////////////////////////////////////////////////////////////////// +INLINE bool NodePath:: +is_hidden() const { + return !get_hidden_ancestor().is_empty(); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::stash +// Access: Public +// Description: A more thorough version of hide(), this effectively +// removes the bottom node from the scene graph--it does +// not appear in any traversals, rendering or otherwise, +// and cannot be located again via NodePath::find(). +// The node is also removed from its parents' bounding +// volume. +// +// However, the node is still associated with its +// parent, and will be removed if the parent is removed, +// and it can be revealed again by a future call to +// unstash(). +//////////////////////////////////////////////////////////////////// +INLINE void NodePath:: +stash() { + nassertv(has_arcs()); + nassertv(_head != (ArcComponent *)NULL); + + _head->_arc->set_graph_type(NodeRelation::get_stashed_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::unstash +// Access: Public +// Description: Reveals a node that was previously hidden via stash(). +//////////////////////////////////////////////////////////////////// +INLINE void NodePath:: +unstash() { + nassertv(has_arcs()); + nassertv(_head != (ArcComponent *)NULL); + + _head->_arc->set_graph_type(_head->_arc->get_type()); +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePath::is_stashed +// Access: Public +// Description: Returns true if some arc above this bottom node has +// been set to 'stash', false if it should be visible. +//////////////////////////////////////////////////////////////////// +INLINE bool NodePath:: +is_stashed() const { + return !get_stashed_ancestor().is_empty(); +} diff --git a/panda/src/sgmanip/nodePath.cxx b/panda/src/sgmanip/nodePath.cxx index 469a3e93aa..ed65fdabf0 100644 --- a/panda/src/sgmanip/nodePath.cxx +++ b/panda/src/sgmanip/nodePath.cxx @@ -122,8 +122,6 @@ bool NodePath:: extend_by(NodeRelation *arc) { nassertr(verify_connectivity(), false); nassertr(arc != (NodeRelation *)NULL, false); - // Make sure the graph types are consistent. - nassertr(arc->get_type() == _graph_type, false); if (is_empty()) { nassertr(_head == (ArcComponent *)NULL, false); @@ -212,8 +210,8 @@ extend_down_to(Node *dnode) { nassertr(verify_connectivity(), false); NodePathCollection col; FindApproxPath approx_path; - approx_path.add_match_many(); - approx_path.add_match_pointer(dnode); + approx_path.add_match_many(0); + approx_path.add_match_pointer(dnode, 0); find_matches(col, approx_path, -1); if (col.is_empty()) { @@ -352,8 +350,8 @@ find_all_paths_down_to(Node *dnode) const { nassertr(verify_connectivity(), col); nassertr(dnode != (Node *)NULL, col); FindApproxPath approx_path; - approx_path.add_match_many(); - approx_path.add_match_pointer(dnode); + approx_path.add_match_many(0); + approx_path.add_match_pointer(dnode, 0); find_matches(col, approx_path, -1); return col; } @@ -485,30 +483,6 @@ get_arc(int index) const { return comp->_arc; } -//////////////////////////////////////////////////////////////////// -// Function: NodePath::get_top_node -// Access: Public -// Description: Returns the top node of the path, or NULL if the path -// is empty. This requires iterating through the path. -//////////////////////////////////////////////////////////////////// -Node *NodePath:: -get_top_node() const { - if (_head == (ArcComponent *)NULL) { - // A singleton or empty list. - return _top_node; - } - - ArcComponent *comp = _head; - while (comp->_next != (ArcComponent *)NULL) { - comp = comp->_next; - } - - // This assertion should not fail unless there is a logic error in - // the above. - nassertr(comp != (ArcComponent *)NULL, NULL); - return comp->_arc->get_parent(); -} - //////////////////////////////////////////////////////////////////// // Function: NodePath::share_with // Access: Public @@ -604,12 +578,6 @@ verify_connectivity() const { return false; } - // We also want to verify that all of the arcs are of the proper - // type. - if (comp->_arc->get_type() != _graph_type) { - return false; - } - comp = comp->_next; while (comp != (const ArcComponent *)NULL) { Node *next_parent = comp->_arc->get_parent(); @@ -620,15 +588,21 @@ verify_connectivity() const { if (next_child != parent) { return false; } - if (comp->_arc->get_type() != _graph_type) { - return false; - } parent = next_parent; child = next_child; comp = comp->_next; } + // We cannot insist that _top_node be correct, since it might have + // wandered, particularly if our parent path has changed without our + // knowledge. + /* + if (parent != _top_node) { + return false; + } + */ + return true; } @@ -666,15 +640,6 @@ amputate_badness() { return false; } - // We also want to verify that all of the arcs are of the proper - // type. - if (comp->_arc->get_type() != _graph_type) { - // Eek! The bottom arc is broken! - _top_node = child; - _head = (ArcComponent *)NULL; - return false; - } - ArcComponent *prev = comp; comp = comp->_next; while (comp != (const ArcComponent *)NULL) { @@ -682,14 +647,12 @@ amputate_badness() { Node *next_child = comp->_arc->get_child(); if (next_parent == (Node *)NULL || next_child == (Node *)NULL) { prev->_next = (ArcComponent *)NULL; + _top_node = parent; return false; } if (next_child != parent) { prev->_next = (ArcComponent *)NULL; - return false; - } - if (comp->_arc->get_type() != _graph_type) { - prev->_next = (ArcComponent *)NULL; + _top_node = parent; return false; } @@ -714,6 +677,14 @@ amputate_badness() { //////////////////////////////////////////////////////////////////// bool NodePath:: repair_connectivity(const NodePath &top) { + // If the only problem is the top node, we can fix that first. + reset_top_node(); + if (verify_connectivity()) { + return true; + } + + nassertr(top.verify_connectivity(), false); + NodePath new_path(*this); new_path.amputate_badness(); if (new_path.is_empty()) { @@ -731,6 +702,7 @@ repair_connectivity(const NodePath &top) { } (*this) = full_path; + return true; } @@ -767,6 +739,7 @@ reparent_to(const NodePath &other, int sort) { // update our own path, as well as all paths that share the same // head pointer (i.e. all paths derived from this one). _head->_next = other._head; + _top_node = other._top_node; } //////////////////////////////////////////////////////////////////// @@ -832,6 +805,7 @@ instance_to(const NodePath &other, int sort) const { NodePath instance(*this); instance._head = new ArcComponent(darc, other._head); + instance._top_node = other._top_node; return instance; } @@ -874,6 +848,7 @@ copy_to(const NodePath &other, int sort) const { NodePath instance(*this); instance._head = new ArcComponent(darc, other._head); + instance._top_node = other._top_node; return instance; } @@ -1080,7 +1055,7 @@ int NodePath:: flatten_medium() { nassertr(!is_empty(), 0); SceneGraphReducer gr(_graph_type); - gr.apply_transitions(node()); + gr.apply_transitions(arc()); int num_removed = gr.flatten(node(), false); if (sgmanip_cat.is_debug()) { @@ -1112,7 +1087,7 @@ int NodePath:: flatten_strong() { nassertr(!is_empty(), 0); SceneGraphReducer gr(_graph_type); - gr.apply_transitions(node()); + gr.apply_transitions(arc()); int num_removed = gr.flatten(node(), true); if (sgmanip_cat.is_debug()) { @@ -2312,17 +2287,6 @@ get_transparency() const { return false; } -//////////////////////////////////////////////////////////////////// -// Function: NodePath::is_hidden -// Access: Public -// Description: Returns true if some arc above this bottom node has -// been set to 'hide', false if it should be visible. -//////////////////////////////////////////////////////////////////// -bool NodePath:: -is_hidden() const { - return !get_hidden_ancestor().is_empty(); -} - //////////////////////////////////////////////////////////////////// // Function: NodePath::get_hidden_ancestor // Access: Public @@ -2351,6 +2315,33 @@ get_hidden_ancestor() const { return next.get_hidden_ancestor(); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::get_stashed_ancestor +// Access: Public +// Description: Returns a NodePath indicating the lowest arc above +// this node which has been set to 'stash'. Calling +// unstash() on the NodePath returned by this function +// should make the node visible again (unless there is +// another arc further up that also has been 'stashed'. +// +// This function returns an empty NodePath if no +// ancestors have been 'stashed'. +//////////////////////////////////////////////////////////////////// +NodePath NodePath:: +get_stashed_ancestor() const { + if (!has_arcs()) { + return NodePath(); + } + nassertr(_head != (ArcComponent *)NULL, NodePath()); + if (_head->_arc->get_graph_type() != _graph_type) { + return *this; + } + + NodePath next(*this); + next.shorten(); + return next.get_stashed_ancestor(); +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::prepare_scene // Access: Public @@ -2450,6 +2441,27 @@ write_bounds(ostream &out) const { get_bounds()->write(out); } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::reset_top_node +// Access: Private +// Description: Recomputes the _top_node member to accurately reflect +// the top node of the chain. +//////////////////////////////////////////////////////////////////// +void NodePath:: +reset_top_node() { + if (_head != (ArcComponent *)NULL) { + ArcComponent *comp = _head; + while (comp->_next != (ArcComponent *)NULL) { + comp = comp->_next; + } + + // This assertion should not fail unless there is a logic error in + // the above. + nassertv(comp != (ArcComponent *)NULL); + _top_node = comp->_arc->get_parent(); + } +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::r_compare_to // Access: Private, Static @@ -2513,8 +2525,9 @@ r_as_string(const ArcComponent *comp, string &result, int skip_nodes) const { // Here's the end of the chain. if (skip_nodes == 0) { // Skip no nodes; return the full name. - result = format_node_name(comp->_arc->get_parent()) + "/" + - format_node_name(comp->_arc->get_child()); + result = format_node_name(comp->_arc->get_parent()); + result += format_arc_name(comp->_arc); + result += format_node_name(comp->_arc->get_child()); } else if (skip_nodes == 1) { // Skip the first node. @@ -2530,14 +2543,13 @@ r_as_string(const ArcComponent *comp, string &result, int skip_nodes) const { // This is not the first node, so format a slash between the // previous node and this node. - if (comp->_arc->get_child() == (Node *)NULL || - comp->_arc->get_parent() == comp->_next->_arc->get_child()) { - result += "/"; - } else { + if (!(comp->_arc->get_child() == (Node *)NULL || + comp->_arc->get_parent() == comp->_next->_arc->get_child())) { // Unless the path is broken here. In this case, insert a // visual indication of the break. - result += "/.../" + format_node_name(comp->_arc->get_parent()) + "/"; + result += "/.../" + format_node_name(comp->_arc->get_parent()); } + result += format_arc_name(comp->_arc); result += format_node_name(comp->_arc->get_child()); } } @@ -2615,6 +2627,28 @@ format_node_name(Node *dnode) const { return name; } +//////////////////////////////////////////////////////////////////// +// Function: NodePath::format_arc_name +// Access: Private +// Description: Formats the "name" for the arc in as_string(). +// Normally, this is simply "/", but for certain arcs +// (as for stashed nodes, for instance), it might +// contain other characters. +//////////////////////////////////////////////////////////////////// +string NodePath:: +format_arc_name(NodeRelation *arc) const { + string result = "/"; + + if (arc->get_graph_type() == NodeRelation::get_stashed_type()) { + result += "@@"; + + } else if (arc->get_graph_type() != _graph_type) { + result += "@@(" + arc->get_graph_type().get_name() + ")"; + } + + return result; +} + //////////////////////////////////////////////////////////////////// // Function: NodePath::find_matches // Access: Private @@ -2685,31 +2719,16 @@ r_find_matches(NodePathCollection &result, FindApproxLevel::Vec::const_iterator li; for (li = level._v.begin(); li != level._v.end(); ++li) { const FindApproxLevelEntry &entry = (*li); + if (entry.is_solution()) { // Does this entry already represent a solution? result.add_path(entry._node_path); - if (max_matches > 0 && result.get_num_paths() >= max_matches) { - return; - } - } else { - Node *bottom_node = entry._node_path.node(); - nassertv(bottom_node != (Node *)NULL); + entry.consider_node(result, next_level, max_matches, _graph_type); + } - DownRelations::const_iterator dri; - dri = bottom_node->_children.find(_graph_type); - if (dri != bottom_node->_children.end()) { - const DownRelationPointers &drp = (*dri).second; - - DownRelationPointers::const_iterator drpi; - for (drpi = drp.begin(); drpi != drp.end(); ++drpi) { - NodeRelation *arc = (*drpi); - entry.consider_next_step(result, arc, next_level, max_matches); - if (max_matches > 0 && result.get_num_paths() >= max_matches) { - return; - } - } - } + if (max_matches > 0 && result.get_num_paths() >= max_matches) { + return; } } diff --git a/panda/src/sgmanip/nodePath.h b/panda/src/sgmanip/nodePath.h index e03e3cacfc..57e9d48dcf 100644 --- a/panda/src/sgmanip/nodePath.h +++ b/panda/src/sgmanip/nodePath.h @@ -154,7 +154,7 @@ PUBLISHED: int get_num_arcs() const; NodeRelation *get_arc(int index) const; - Node *get_top_node() const; + INLINE Node *get_top_node(); INLINE Node *node() const; INLINE NodeRelation *arc() const; @@ -442,9 +442,14 @@ PUBLISHED: INLINE void hide(); INLINE void show_collision_solids(); INLINE void hide_collision_solids(); - bool is_hidden() const; + INLINE bool is_hidden() const; NodePath get_hidden_ancestor() const; + INLINE void stash(); + INLINE void unstash(); + INLINE bool is_stashed() const; + NodePath get_stashed_ancestor() const; + void prepare_scene(GraphicsStateGuardianBase *gsg); void show_bounds(); @@ -466,6 +471,7 @@ public: }; private: + void reset_top_node(); static int r_compare_to(const ArcComponent *a, const ArcComponent *v); bool r_extend_by(const ArcComponent *other); int r_as_string(const ArcComponent *comp, string &result, @@ -475,6 +481,7 @@ private: void r_get_net_transitions(const ArcComponent *comp, AllTransitionsWrapper &trans) const; string format_node_name(Node *dnode) const; + string format_arc_name(NodeRelation *arc) const; void find_matches(NodePathCollection &result, const string &approx_path_str, diff --git a/panda/src/sgmanip/nodePathBase.h b/panda/src/sgmanip/nodePathBase.h index 8fa9a5b59b..d64ef81313 100644 --- a/panda/src/sgmanip/nodePathBase.h +++ b/panda/src/sgmanip/nodePathBase.h @@ -32,8 +32,14 @@ protected: // Most of the interesting part of NodePathBase is inherited from // ArcChain. This gives us a sharable linked list of arcs. - // The _top_node pointer is only used when the NodePath is a - // singleton. If there is at least one arc, this is ignored. + // We also add an explicit pointer to the top node in the chain, + // mainly to allow us to define a NodePath containing a single node, + // even if the chain of arcs is empty. + + // If the chain is nonempty, this might still be useful (int that it + // keeps a reference count to the top node), but this is problematic + // since it will not automatically update if our parent is changed + // without our knowledge. PT_Node _top_node; TypeHandle _graph_type; diff --git a/panda/src/sgmanip/nodePathCollection.cxx b/panda/src/sgmanip/nodePathCollection.cxx index ef3dab5b83..36f8d1ae98 100644 --- a/panda/src/sgmanip/nodePathCollection.cxx +++ b/panda/src/sgmanip/nodePathCollection.cxx @@ -348,6 +348,30 @@ hide() { } } +//////////////////////////////////////////////////////////////////// +// Function: NodePathCollection::stash +// Access: Published +// Description: Stashes all NodePaths in the collection. +//////////////////////////////////////////////////////////////////// +void NodePathCollection:: +stash() { + for (int i = 0; i < get_num_paths(); i++) { + get_path(i).stash(); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: NodePathCollection::unstash +// Access: Published +// Description: Unstashes all NodePaths in the collection. +//////////////////////////////////////////////////////////////////// +void NodePathCollection:: +unstash() { + for (int i = 0; i < get_num_paths(); i++) { + get_path(i).unstash(); + } +} + //////////////////////////////////////////////////////////////////// // Function: NodePathCollection::output // Access: Published diff --git a/panda/src/sgmanip/nodePathCollection.h b/panda/src/sgmanip/nodePathCollection.h index 3a5b58db12..7b7f011999 100644 --- a/panda/src/sgmanip/nodePathCollection.h +++ b/panda/src/sgmanip/nodePathCollection.h @@ -54,6 +54,8 @@ PUBLISHED: void show(); void hide(); + void stash(); + void unstash(); void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; diff --git a/panda/src/sgraphutil/sceneGraphReducer.cxx b/panda/src/sgraphutil/sceneGraphReducer.cxx index 1d126ebf62..4d77247a27 100644 --- a/panda/src/sgraphutil/sceneGraphReducer.cxx +++ b/panda/src/sgraphutil/sceneGraphReducer.cxx @@ -89,7 +89,7 @@ SceneGraphReducer(TypeHandle graph_type) : // operations impossible. //////////////////////////////////////////////////////////////////// void SceneGraphReducer:: -apply_transitions(Node *root, int transition_types) { +apply_transitions(NodeRelation *arc, int transition_types) { AccumulatedTransitions trans; if ((transition_types & TT_transform) != 0) { trans._transform = new TransformTransition; @@ -101,20 +101,7 @@ apply_transitions(Node *root, int transition_types) { trans._texture_matrix = new TexMatrixTransition; } - DownRelations::const_iterator dri; - dri = root->_children.find(_graph_type); - if (dri != root->_children.end()) { - // We must make a temporary copy of the DownRelationPointers, - // because we'll be modifying this list as we go. - DownRelationPointers drp = (*dri).second; - - DownRelationPointers::const_iterator drpi; - for (drpi = drp.begin(); drpi != drp.end(); ++drpi) { - NodeRelation *child_arc = (*drpi); - - r_apply_transitions(child_arc, transition_types, trans, false); - } - } + r_apply_transitions(arc, transition_types, trans, false); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/sgraphutil/sceneGraphReducer.h b/panda/src/sgraphutil/sceneGraphReducer.h index cc7bbb9031..3c12bba0f5 100644 --- a/panda/src/sgraphutil/sceneGraphReducer.h +++ b/panda/src/sgraphutil/sceneGraphReducer.h @@ -36,7 +36,7 @@ public: TT_texture_matrix = 0x004, }; - void apply_transitions(Node *root, int transition_types = ~0); + void apply_transitions(NodeRelation *arc, int transition_types = ~0); protected: class AccumulatedTransitions { diff --git a/panda/src/text/textNode.cxx b/panda/src/text/textNode.cxx index fc1e427fd5..fb6888141c 100644 --- a/panda/src/text/textNode.cxx +++ b/panda/src/text/textNode.cxx @@ -510,7 +510,7 @@ do_rebuild() { if (flatten_text) { SceneGraphReducer gr(RenderRelation::get_class_type()); - gr.apply_transitions(_root); + gr.apply_transitions(_root_arc); gr.flatten(_root, true); } }