Browse Source

more major rewrites for trivial performance gains

David Rose 24 years ago
parent
commit
d78b81f540
71 changed files with 613 additions and 308 deletions
  1. 1 1
      panda/src/cull/cullTraverser.I
  2. 1 1
      panda/src/cull/geomBinUnsorted.cxx
  3. 3 0
      panda/src/display/config_display.cxx
  4. 2 0
      panda/src/display/config_display.h
  5. 83 4
      panda/src/display/graphicsStateGuardian.I
  6. 188 194
      panda/src/display/graphicsStateGuardian.cxx
  7. 25 5
      panda/src/display/graphicsStateGuardian.h
  8. 11 11
      panda/src/dxgsg/dxGraphicsStateGuardian.cxx
  9. 30 0
      panda/src/express/typeHandle.I
  10. 3 0
      panda/src/express/typeHandle.h
  11. 6 30
      panda/src/express/typeRegistryNode.cxx
  12. 0 3
      panda/src/express/typeRegistryNode.h
  13. 9 10
      panda/src/glgsg/glGraphicsStateGuardian.cxx
  14. 20 7
      panda/src/graph/nodeTransition.cxx
  15. 1 0
      panda/src/graph/nodeTransition.h
  16. 31 0
      panda/src/graph/nodeTransitionCache.I
  17. 5 2
      panda/src/graph/nodeTransitionCache.h
  18. 1 1
      panda/src/graph/nodeTransitions.h
  19. 1 1
      panda/src/pgui/pgTop.cxx
  20. 5 1
      panda/src/sgattrib/alphaTransformTransition.cxx
  21. 2 0
      panda/src/sgattrib/alphaTransformTransition.h
  22. 5 1
      panda/src/sgattrib/billboardTransition.cxx
  23. 1 0
      panda/src/sgattrib/billboardTransition.h
  24. 5 1
      panda/src/sgattrib/clipPlaneTransition.cxx
  25. 3 0
      panda/src/sgattrib/clipPlaneTransition.h
  26. 5 1
      panda/src/sgattrib/colorBlendTransition.cxx
  27. 2 0
      panda/src/sgattrib/colorBlendTransition.h
  28. 5 1
      panda/src/sgattrib/colorMaskTransition.cxx
  29. 2 0
      panda/src/sgattrib/colorMaskTransition.h
  30. 5 1
      panda/src/sgattrib/colorMatrixTransition.cxx
  31. 3 2
      panda/src/sgattrib/colorMatrixTransition.h
  32. 5 1
      panda/src/sgattrib/colorTransition.cxx
  33. 2 0
      panda/src/sgattrib/colorTransition.h
  34. 5 1
      panda/src/sgattrib/cullFaceTransition.cxx
  35. 2 0
      panda/src/sgattrib/cullFaceTransition.h
  36. 5 1
      panda/src/sgattrib/decalTransition.cxx
  37. 3 0
      panda/src/sgattrib/decalTransition.h
  38. 5 1
      panda/src/sgattrib/depthTestTransition.cxx
  39. 2 0
      panda/src/sgattrib/depthTestTransition.h
  40. 5 1
      panda/src/sgattrib/depthWriteTransition.cxx
  41. 3 0
      panda/src/sgattrib/depthWriteTransition.h
  42. 7 3
      panda/src/sgattrib/drawBoundsTransition.cxx
  43. 8 4
      panda/src/sgattrib/drawBoundsTransition.h
  44. 5 1
      panda/src/sgattrib/fogTransition.cxx
  45. 2 0
      panda/src/sgattrib/fogTransition.h
  46. 5 1
      panda/src/sgattrib/linesmoothTransition.cxx
  47. 3 0
      panda/src/sgattrib/linesmoothTransition.h
  48. 5 1
      panda/src/sgattrib/materialTransition.cxx
  49. 2 0
      panda/src/sgattrib/materialTransition.h
  50. 5 1
      panda/src/sgattrib/pointShapeTransition.cxx
  51. 2 0
      panda/src/sgattrib/pointShapeTransition.h
  52. 5 1
      panda/src/sgattrib/polygonOffsetTransition.cxx
  53. 2 0
      panda/src/sgattrib/polygonOffsetTransition.h
  54. 5 1
      panda/src/sgattrib/renderModeTransition.cxx
  55. 2 0
      panda/src/sgattrib/renderModeTransition.h
  56. 5 1
      panda/src/sgattrib/stencilTransition.cxx
  57. 2 0
      panda/src/sgattrib/stencilTransition.h
  58. 5 1
      panda/src/sgattrib/texGenTransition.cxx
  59. 2 0
      panda/src/sgattrib/texGenTransition.h
  60. 5 1
      panda/src/sgattrib/texMatrixTransition.cxx
  61. 3 0
      panda/src/sgattrib/texMatrixTransition.h
  62. 5 1
      panda/src/sgattrib/textureApplyTransition.cxx
  63. 2 0
      panda/src/sgattrib/textureApplyTransition.h
  64. 5 1
      panda/src/sgattrib/textureTransition.cxx
  65. 2 0
      panda/src/sgattrib/textureTransition.h
  66. 5 1
      panda/src/sgattrib/transformTransition.cxx
  67. 3 2
      panda/src/sgattrib/transformTransition.h
  68. 5 1
      panda/src/sgattrib/transparencyTransition.cxx
  69. 2 0
      panda/src/sgattrib/transparencyTransition.h
  70. 2 2
      panda/src/sgraphutil/directRenderTraverser.cxx
  71. 1 1
      panda/src/sgraphutil/quickRenderTraverser.cxx

+ 1 - 1
panda/src/cull/cullTraverser.I

@@ -37,7 +37,7 @@ draw_geom(GeomNode *geom_node, const AllTransitionsWrapper &initial_state) {
       << "Drawing " << *geom_node << " with state: " << initial_state << "\n";
       << "Drawing " << *geom_node << " with state: " << initial_state << "\n";
   }
   }
   nassertv(geom_node != (GeomNode *)NULL);
   nassertv(geom_node != (GeomNode *)NULL);
-  _gsg->set_state(initial_state.get_transitions(), true);
+  _gsg->set_state(initial_state);
   _gsg->prepare_display_region();
   _gsg->prepare_display_region();
   geom_node->draw(_gsg);
   geom_node->draw(_gsg);
 }
 }

+ 1 - 1
panda/src/cull/geomBinUnsorted.cxx

@@ -101,7 +101,7 @@ draw(CullTraverser *trav) {
     }
     }
 
 
     if (cs->geom_size() != 0) {
     if (cs->geom_size() != 0) {
-      gsg->set_state(cs->get_attributes().get_transitions(), true);
+      gsg->set_state(cs->get_attributes());
       gsg->prepare_display_region();
       gsg->prepare_display_region();
 
 
       CullState::geom_iterator gi;
       CullState::geom_iterator gi;

+ 3 - 0
panda/src/display/config_display.cxx

@@ -54,6 +54,9 @@ const bool pipe_spec_is_remote = config_display.Defined("pipe-machine")
                                  || config_display.GetBool("pipe-remote",
                                  || config_display.GetBool("pipe-remote",
                                                            false);
                                                            false);
 
 
+const bool compare_state_by_pointer =
+config_display.GetBool("compare-state-by-pointer", true);
+
 const float gsg_clear_r = config_display.GetFloat("gsg-clear-r", 0.0);
 const float gsg_clear_r = config_display.GetFloat("gsg-clear-r", 0.0);
 const float gsg_clear_g = config_display.GetFloat("gsg-clear-g", 0.0);
 const float gsg_clear_g = config_display.GetFloat("gsg-clear-g", 0.0);
 const float gsg_clear_b = config_display.GetFloat("gsg-clear-b", 0.0);
 const float gsg_clear_b = config_display.GetFloat("gsg-clear-b", 0.0);

+ 2 - 0
panda/src/display/config_display.h

@@ -35,6 +35,8 @@ extern const int pipe_spec_pipe_number;
 extern const bool pipe_spec_is_file;
 extern const bool pipe_spec_is_file;
 extern const bool pipe_spec_is_remote;
 extern const bool pipe_spec_is_remote;
 
 
+extern const bool compare_state_by_pointer;
+
 extern const float gsg_clear_r;
 extern const float gsg_clear_r;
 extern const float gsg_clear_g;
 extern const float gsg_clear_g;
 extern const float gsg_clear_b;
 extern const float gsg_clear_b;

+ 83 - 4
panda/src/display/graphicsStateGuardian.I

@@ -18,6 +18,50 @@
 
 
 #include <notify.h>
 #include <notify.h>
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::StateInfo::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsStateGuardian::StateInfo::
+StateInfo(TypeHandle type) :
+  _type(type)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::StateInfo::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsStateGuardian::StateInfo::
+StateInfo(const NodeTransitions::value_type &value) :
+  _type(value.first), _trans(value.second)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::StateInfo::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE GraphicsStateGuardian::StateInfo::
+StateInfo(const NodeTransitionCache::value_type &value) :
+  _type(value.first), _trans(value.second)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::StateInfo::Ordering operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool GraphicsStateGuardian::StateInfo::
+operator < (const StateInfo &other) const {
+  return _type < other._type;
+}
+
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::set_render_traverser
 //     Function: GraphicsStateGuardian::set_render_traverser
 //       Access: Published
 //       Access: Published
@@ -53,19 +97,36 @@ is_closed() const {
   return (_win == (GraphicsWindow *)NULL);
   return (_win == (GraphicsWindow *)NULL);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::set_state
+//       Access: Public
+//  Description: Applies the transitions indicated in the state set to
+//               the current state, and issues the changes to the
+//               graphics hardware.
+//
+//               The state is taken to be a complete description of
+//               what the graphics state should be; any transitions
+//               not mentioned in new_state are implicitly reset to
+//               their initial values.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsStateGuardian::
+set_state(const AllTransitionsWrapper &new_state) {
+  set_state(new_state.get_transitions());
+}
+
+/*
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_state
 //     Function: GraphicsStateGuardian::get_state
 //       Access: Public
 //       Access: Public
 //  Description: Returns the current state of the GSG.  This state may
 //  Description: Returns the current state of the GSG.  This state may
 //               be saved and used to restore the GSG to its current
 //               be saved and used to restore the GSG to its current
-//               state later; however, this save/restore operation
-//               should be used with caution, as it could grow to be
-//               expensive.
+//               state later.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-INLINE const NodeTransitions &GraphicsStateGuardian::
+INLINE const NodeTransitionCache *GraphicsStateGuardian::
 get_state() const {
 get_state() const {
   return _state;
   return _state;
 }
 }
+*/
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_current_projection_node
 //     Function: GraphicsStateGuardian::get_current_projection_node
@@ -207,3 +268,21 @@ INLINE CoordinateSystem GraphicsStateGuardian::
 get_coordinate_system() const {
 get_coordinate_system() const {
   return _coordinate_system;
   return _coordinate_system;
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: get_attribute_into
+//  Description: This external template function is handy for
+//               extracting a transition of a particular type from the
+//               gsg's state.  It works like get_transition_into().
+////////////////////////////////////////////////////////////////////
+template<class Transition>
+INLINE bool
+get_attribute_into(Transition *&ptr, GraphicsStateGuardian *gsg) {
+  NodeTransition *nt = gsg->get_attribute(Transition::get_class_type());
+  if (nt == (NodeTransition *)NULL) {
+    ptr = (Transition *)NULL;
+    return false;
+  }
+  DCAST_INTO_R(ptr, nt, false);
+  return true;
+}

+ 188 - 194
panda/src/display/graphicsStateGuardian.cxx

@@ -128,36 +128,29 @@ reset() {
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: GraphicsStateGuardian::set_state
+//     Function: GraphicsStateGuardian::modify_state
 //       Access: Public
 //       Access: Public
-//  Description: Sets the graphics backend to the state represented by
-//               the indicated set of attributes.  Only the minimal
-//               number of graphics commands are issued--attributes
-//               which have not changed since the last call to
-//               set_state are detected and not issued again.
+//  Description: Applies the transitions indicated in the state set to
+//               the current state, and issues the changes to the
+//               graphics hardware.
 //
 //
-//               If complete is true, it means that the supplied state
-//               is a complete description of the desired state--if an
-//               attribute is absent, it should be taken to be the
-//               same as the initial value for that attribute.  If
-//               complete is false, it means that the supplied state
-//               specifies only a subset of the desired state, and
-//               that absent attributes should remain unchanged.
+//               Any transitions not mentioned in new_state are left
+//               unchanged.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
-set_state(const NodeTransitions &new_state, bool complete) {
+modify_state(const NodeTransitions &new_state) {
   PStatTimer timer(_set_state_pcollector);
   PStatTimer timer(_set_state_pcollector);
 
 
   if (gsg_cat.is_debug()) {
   if (gsg_cat.is_debug()) {
     gsg_cat.debug() << "\n";
     gsg_cat.debug() << "\n";
     gsg_cat.debug()
     gsg_cat.debug()
       << "Frame " << ClockObject::get_global_clock()->get_frame_count()
       << "Frame " << ClockObject::get_global_clock()->get_frame_count()
-      << ", setting to (complete = " << complete << ")\n";
+      << ", setting via NodeTransitions\n";
     new_state.write(gsg_cat.debug(false), 10);
     new_state.write(gsg_cat.debug(false), 10);
   }
   }
 
 
   NodeTransitions::const_iterator new_i;
   NodeTransitions::const_iterator new_i;
-  NodeTransitions::iterator current_i;
+  State::iterator current_i;
 
 
   new_i = new_state.begin();
   new_i = new_state.begin();
   current_i = _state.begin();
   current_i = _state.begin();
@@ -165,8 +158,8 @@ set_state(const NodeTransitions &new_state, bool complete) {
   while (new_i != new_state.end() && current_i != _state.end()) {
   while (new_i != new_state.end() && current_i != _state.end()) {
     TypeHandle new_type = (*new_i).first;
     TypeHandle new_type = (*new_i).first;
     NodeTransition *new_trans = (*new_i).second;
     NodeTransition *new_trans = (*new_i).second;
-    TypeHandle current_type = (*current_i).first;
-    PT(NodeTransition) &current_trans = (*current_i).second;
+    TypeHandle current_type = (*current_i)._type;
+    PT(NodeTransition) &current_trans = (*current_i)._trans;
 
 
     if (new_type < current_type) {
     if (new_type < current_type) {
       // The user requested setting an attribute that we've never set
       // The user requested setting an attribute that we've never set
@@ -180,7 +173,9 @@ set_state(const NodeTransitions &new_state, bool complete) {
         record_state_change(new_type);
         record_state_change(new_type);
         new_trans->issue(this);
         new_trans->issue(this);
 
 
-        // And store the new value.
+        // And store the new value.  This is a terribly slow way to
+        // insert an element into a vector, but it happens only very
+        // rarely.
         current_i = _state.insert(current_i, *new_i);
         current_i = _state.insert(current_i, *new_i);
         ++current_i;
         ++current_i;
       }
       }
@@ -190,77 +185,66 @@ set_state(const NodeTransitions &new_state, bool complete) {
     } else if (current_type < new_type) {
     } else if (current_type < new_type) {
       // Here's an attribute that we've set previously, but the user
       // Here's an attribute that we've set previously, but the user
       // didn't specify this time.
       // didn't specify this time.
+      ++current_i;
 
 
-      if (complete) {
-        // If we're in the "complete state" model, that means this
-        // attribute should now get the default initial value.
-
-        if (gsg_cat.is_debug()) {
-          gsg_cat.debug()
-            << "Unissuing attrib " << *current_trans
-            << " (previously set, not now)\n";
-        }
-        record_state_change(current_type);
-
-        PT(NodeTransition) initial = current_trans->make_initial();
-        initial->issue(this);
-
-        NodeTransitions::iterator erase_i = current_i;
-        ++current_i;
-
-        _state.erase(erase_i);
-
-      } else {
-        ++current_i;
-      }
-
-    } else {  // current_type == new_type)
+    } else {  // current_type == new_type
 
 
       if (new_trans == (NodeTransition *)NULL) {
       if (new_trans == (NodeTransition *)NULL) {
         // Here's an attribute that we've set previously, which
         // Here's an attribute that we've set previously, which
         // appears in the new list, but is NULL indicating it should
         // appears in the new list, but is NULL indicating it should
         // be removed.
         // be removed.
+        ++current_i;
+        ++new_i;
 
 
-        if (complete) {
-          // Only remove it if we're in the "complete state" model.
-
-          if (gsg_cat.is_debug()) {
-            gsg_cat.debug()
-              << "Unissuing attrib " << *current_trans
-              << " (previously set, now NULL)\n";
-          }
-          record_state_change(current_type);
-
-          // Issue the initial attribute before clearing the state.
-          PT(NodeTransition) initial = current_trans->make_initial();
-          initial->issue(this);
-
-          NodeTransitions::iterator erase_i = current_i;
-          ++current_i;
-
-          _state.erase(erase_i);
-
-        } else {
-          ++current_i;
+      } else if (current_trans == (NodeTransition *)NULL) {
+        // Here's a new attribute which we had previously set NULL,
+        // indicating the initial attribute.
+        if (gsg_cat.is_debug()) {
+          gsg_cat.debug()
+            << "Issuing previously NULL attrib " << *new_trans << "\n";
         }
         }
-        ++new_i;
+        record_state_change(new_type);
+        new_trans->issue(this);
+        
+        // And store the new value.
+        current_trans = new_trans;
 
 
       } else {
       } else {
         // Here's an attribute that we've set previously, and the user
         // Here's an attribute that we've set previously, and the user
         // asked us to set it again.  Issue the command only if the new
         // asked us to set it again.  Issue the command only if the new
         // attribute is different from that which we'd set before.
         // attribute is different from that which we'd set before.
-        if (new_trans->compare_to(*current_trans) != 0) {
-          if (gsg_cat.is_debug()) {
-            gsg_cat.debug()
-              << "Reissuing attrib " << *new_trans << "\n";
-            gsg_cat.debug()
-              << "Previous was " << *current_trans << "\n";
+        if (new_trans != current_trans) {
+          if (!compare_state_by_pointer &&
+              new_trans->compare_to_ignore_priority(*current_trans) == 0) {
+            // Oops, different pointers, same value.
+
+            // Get an assignable reference to the source.  We modify
+            // the source in this way in a trivial manner--we replace
+            // the transition in the source with an identical one--in
+            // the hopes that this will reduce the need for future
+            // comparisons.
+            PT(NodeTransition) &new_trans_assign = 
+              (PT(NodeTransition) &)(*new_i).second;
+            new_trans_assign = current_trans;
+
+            if (gsg_cat.is_debug()) {
+              gsg_cat.debug()
+                << "Updating pointer for attrib " << *new_trans << "\n";
+            }
+
+          } else {
+            if (gsg_cat.is_debug()) {
+              gsg_cat.debug()
+                << "Reissuing attrib " << *new_trans << "\n";
+              gsg_cat.debug()
+                << "Previous was " << *current_trans << "\n";
+            }
+            record_state_change(new_type);
+            new_trans->issue(this);
+            
+            // And store the new value.
+            current_trans = new_trans;
           }
           }
-          record_state_change(new_type);
-          new_trans->issue(this);
-
-          // And store the new value.
-          current_trans = new_trans;
 
 
         } else if (gsg_cat.is_debug()) {
         } else if (gsg_cat.is_debug()) {
           gsg_cat.debug()
           gsg_cat.debug()
@@ -289,69 +273,38 @@ set_state(const NodeTransitions &new_state, bool complete) {
       new_trans->issue(this);
       new_trans->issue(this);
 
 
       // And store the new value.
       // And store the new value.
-      _state.insert(_state.end(), *new_i);
+      _state.push_back(*new_i);
     }
     }
     ++new_i;
     ++new_i;
   }
   }
-
-  if (complete) {
-    while (current_i != _state.end()) {
-      // Here's an attribute that we've set previously, but the user
-      // didn't specify this time.
-      TypeHandle current_type = (*current_i).first;
-      PT(NodeTransition) &current_trans = (*current_i).second;
-
-      if (gsg_cat.is_debug()) {
-        gsg_cat.debug()
-          << "Unissuing attrib " << *current_trans
-          << " (previously set, end of list)\n";
-      }
-      record_state_change(current_type);
-
-      // If we're in the "complete state" model, that means this
-      // attribute should now get the default initial value.
-      PT(NodeTransition) initial = current_trans->make_initial();
-      initial->issue(this);
-
-      NodeTransitions::iterator erase_i = current_i;
-      ++current_i;
-
-      _state.erase(erase_i);
-    }
-  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::set_state
 //     Function: GraphicsStateGuardian::set_state
 //       Access: Public
 //       Access: Public
-//  Description: Sets the graphics backend to the state represented by
-//               the indicated set of attributes.  Only the minimal
-//               number of graphics commands are issued--attributes
-//               which have not changed since the last call to
-//               set_state are detected and not issued again.
+//  Description: Applies the transitions indicated in the state set to
+//               the current state, and issues the changes to the
+//               graphics hardware.
 //
 //
-//               If complete is true, it means that the supplied state
-//               is a complete description of the desired state--if an
-//               attribute is absent, it should be taken to be the
-//               same as the initial value for that attribute.  If
-//               complete is false, it means that the supplied state
-//               specifies only a subset of the desired state, and
-//               that absent attributes should remain unchanged.
+//               The state is taken to be a complete description of
+//               what the graphics state should be; any transitions
+//               not mentioned in new_state are implicitly reset to
+//               their initial values.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
-set_state(const NodeTransitionCache &new_state, bool complete) {
+set_state(const NodeTransitionCache &new_state) {
   PStatTimer timer(_set_state_pcollector);
   PStatTimer timer(_set_state_pcollector);
 
 
   if (gsg_cat.is_debug()) {
   if (gsg_cat.is_debug()) {
     gsg_cat.debug() << "\n";
     gsg_cat.debug() << "\n";
     gsg_cat.debug()
     gsg_cat.debug()
       << "Frame " << ClockObject::get_global_clock()->get_frame_count()
       << "Frame " << ClockObject::get_global_clock()->get_frame_count()
-      << ", setting to (complete = " << complete << ")\n";
+      << ", setting to\n";
     new_state.write(gsg_cat.debug(false), 10);
     new_state.write(gsg_cat.debug(false), 10);
   }
   }
 
 
   NodeTransitionCache::const_iterator new_i;
   NodeTransitionCache::const_iterator new_i;
-  NodeTransitions::iterator current_i;
+  State::iterator current_i;
 
 
   new_i = new_state.begin();
   new_i = new_state.begin();
   current_i = _state.begin();
   current_i = _state.begin();
@@ -359,8 +312,8 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
   while (new_i != new_state.end() && current_i != _state.end()) {
   while (new_i != new_state.end() && current_i != _state.end()) {
     TypeHandle new_type = (*new_i).first;
     TypeHandle new_type = (*new_i).first;
     NodeTransition *new_trans = (*new_i).second.get_trans();
     NodeTransition *new_trans = (*new_i).second.get_trans();
-    TypeHandle current_type = (*current_i).first;
-    PT(NodeTransition) &current_trans = (*current_i).second;
+    TypeHandle current_type = (*current_i)._type;
+    PT(NodeTransition) &current_trans = (*current_i)._trans;
 
 
     if (new_type < current_type) {
     if (new_type < current_type) {
       // The user requested setting an attribute that we've never set
       // The user requested setting an attribute that we've never set
@@ -374,7 +327,9 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
         record_state_change(new_type);
         record_state_change(new_type);
         new_trans->issue(this);
         new_trans->issue(this);
 
 
-        // And store the new value.
+        // And store the new value.  This is a terribly slow way to
+        // insert an element into a vector, but it happens only very
+        // rarely.
         current_i = _state.insert(current_i, *new_i);
         current_i = _state.insert(current_i, *new_i);
         ++current_i;
         ++current_i;
       }
       }
@@ -385,9 +340,8 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
       // Here's an attribute that we've set previously, but the user
       // Here's an attribute that we've set previously, but the user
       // didn't specify this time.
       // didn't specify this time.
 
 
-      if (complete) {
-        // If we're in the "complete state" model, that means this
-        // attribute should now get the default initial value.
+      if (current_trans != (NodeTransition *)NULL) {
+        // This attribute should now get the default initial value.
 
 
         if (gsg_cat.is_debug()) {
         if (gsg_cat.is_debug()) {
           gsg_cat.debug()
           gsg_cat.debug()
@@ -399,25 +353,18 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
         PT(NodeTransition) initial = current_trans->make_initial();
         PT(NodeTransition) initial = current_trans->make_initial();
         initial->issue(this);
         initial->issue(this);
 
 
-        NodeTransitions::iterator erase_i = current_i;
-        ++current_i;
-
-        _state.erase(erase_i);
-
-      } else {
-        ++current_i;
+        current_trans = NULL;
       }
       }
 
 
-    } else {  // current_type == new_type)
+      ++current_i;
+
+    } else {  // current_type == new_type
 
 
       if (new_trans == (NodeTransition *)NULL) {
       if (new_trans == (NodeTransition *)NULL) {
         // Here's an attribute that we've set previously, which
         // Here's an attribute that we've set previously, which
         // appears in the new list, but is NULL indicating it should
         // appears in the new list, but is NULL indicating it should
         // be removed.
         // be removed.
-
-        if (complete) {
-          // Only remove it if we're in the "complete state" model.
-
+        if (current_trans != (NodeTransition *)NULL) {
           if (gsg_cat.is_debug()) {
           if (gsg_cat.is_debug()) {
             gsg_cat.debug()
             gsg_cat.debug()
               << "Unissuing attrib " << *current_trans
               << "Unissuing attrib " << *current_trans
@@ -429,42 +376,87 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
           PT(NodeTransition) initial = current_trans->make_initial();
           PT(NodeTransition) initial = current_trans->make_initial();
           initial->issue(this);
           initial->issue(this);
 
 
-          NodeTransitions::iterator erase_i = current_i;
-          ++current_i;
-
-          _state.erase(erase_i);
-
-        } else {
-          ++current_i;
+          current_trans = NULL;
         }
         }
-        ++new_i;
 
 
+      } else if (current_trans == (NodeTransition *)NULL) {
+        // Here's a new attribute which we had previously set NULL,
+        // indicating the initial attribute.
+        if (gsg_cat.is_debug()) {
+          gsg_cat.debug()
+            << "Issuing previously NULL attrib " << *new_trans << "\n";
+        }
+        record_state_change(new_type);
+        new_trans->issue(this);
+        
+        // And store the new value.
+        current_trans = new_trans;
+        
       } else {
       } else {
         // Here's an attribute that we've set previously, and the user
         // Here's an attribute that we've set previously, and the user
         // asked us to set it again.  Issue the command only if the new
         // asked us to set it again.  Issue the command only if the new
         // attribute is different from that which we'd set before.
         // attribute is different from that which we'd set before.
-        if (new_trans->compare_to(*current_trans) != 0) {
-          if (gsg_cat.is_debug()) {
-            gsg_cat.debug()
-              << "Reissuing attrib " << *new_trans << "\n";
-            gsg_cat.debug()
-              << "Previous was " << *current_trans << "\n";
+        if (new_trans != current_trans) {
+          if (!compare_state_by_pointer &&
+              new_trans->compare_to_ignore_priority(*current_trans) == 0) {
+            // Oops, different pointers, same value.
+
+            // Get an assignable reference to the source.  We modify
+            // the source in this way in a trivial manner--we replace
+            // the transition in the source with an identical one--in
+            // the hopes that this will reduce the need for future
+            // comparisons.
+            NodeTransitionCacheEntry &new_trans_assign = 
+              (NodeTransitionCacheEntry &)(*new_i).second;
+            new_trans_assign.set_trans(current_trans);
+
+          } else {
+            if (gsg_cat.is_debug()) {
+              gsg_cat.debug()
+                << "Reissuing attrib " << *new_trans << "\n";
+              gsg_cat.debug()
+                << "Previous was " << *current_trans << "\n";
+            }
+            record_state_change(new_type);
+            new_trans->issue(this);
+            
+            // And store the new value.
+            current_trans = new_trans;
           }
           }
-          record_state_change(new_type);
-          new_trans->issue(this);
-
-          // And store the new value.
-          current_trans = new_trans;
 
 
         } else if (gsg_cat.is_debug()) {
         } else if (gsg_cat.is_debug()) {
           gsg_cat.debug()
           gsg_cat.debug()
             << "Not reissuing unchanged attrib " << *new_trans << "\n";
             << "Not reissuing unchanged attrib " << *new_trans << "\n";
         }
         }
+      }
 
 
-        ++current_i;
-        ++new_i;
+      ++current_i;
+      ++new_i;
+    }
+  }
+
+  while (current_i != _state.end()) {
+    // Here's an attribute that we've set previously, but the user
+    // didn't specify this time.
+    TypeHandle current_type = (*current_i)._type;
+    PT(NodeTransition) &current_trans = (*current_i)._trans;
+    
+    if (current_trans != (NodeTransition *)NULL) {
+      if (gsg_cat.is_debug()) {
+        gsg_cat.debug()
+          << "Unissuing attrib " << *current_trans
+          << " (previously set, end of list)\n";
       }
       }
+      record_state_change(current_type);
+      
+      // This attribute should now get the default initial value.
+      PT(NodeTransition) initial = current_trans->make_initial();
+      initial->issue(this);
+
+      current_trans = NULL;
     }
     }
+    
+    ++current_i;
   }
   }
 
 
   while (new_i != new_state.end()) {
   while (new_i != new_state.end()) {
@@ -483,36 +475,10 @@ set_state(const NodeTransitionCache &new_state, bool complete) {
       new_trans->issue(this);
       new_trans->issue(this);
 
 
       // And store the new value.
       // And store the new value.
-      _state.insert(_state.end(), *new_i);
+      _state.push_back(*new_i);
     }
     }
     ++new_i;
     ++new_i;
   }
   }
-
-  if (complete) {
-    while (current_i != _state.end()) {
-      // Here's an attribute that we've set previously, but the user
-      // didn't specify this time.
-      TypeHandle current_type = (*current_i).first;
-      PT(NodeTransition) &current_trans = (*current_i).second;
-
-      if (gsg_cat.is_debug()) {
-        gsg_cat.debug()
-          << "Unissuing attrib " << *current_trans
-          << " (previously set, end of list)\n";
-      }
-      record_state_change(current_type);
-
-      // If we're in the "complete state" model, that means this
-      // attribute should now get the default initial value.
-      PT(NodeTransition) initial = current_trans->make_initial();
-      initial->issue(this);
-
-      NodeTransitions::iterator erase_i = current_i;
-      ++current_i;
-
-      _state.erase(erase_i);
-    }
-  }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -658,17 +624,44 @@ release_all_geoms() {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void GraphicsStateGuardian::
 void GraphicsStateGuardian::
 clear_attribute(TypeHandle type) {
 clear_attribute(TypeHandle type) {
-  NodeTransitions::iterator ai = _state.find(type);
-  if (ai != _state.end()) {
-    // The state is already set; get the initial value and reset it.
-    PT(NodeTransition) initial = (*ai).second->make_initial();
-    initial->issue(this);
-
-    // Now remove the state entry from the set.
-    _state.erase(ai);
+  // Look for the transition in our state vector.  We'll use STL's
+  // binary search functions to do this.
+
+  State::iterator si =
+    lower_bound(_state.begin(), _state.end(), StateInfo(type));
+
+  if (si != _state.end() && (*si)._type == type) {
+    // We found it.
+    PT(NodeTransition) &current_trans = (*si)._trans;
+
+    if (current_trans != (NodeTransition *)NULL) {
+      // The state was already set; get the initial value and reset it.
+      PT(NodeTransition) initial = current_trans->make_initial();
+      initial->issue(this);
+      current_trans = (NodeTransition *)NULL;
+    }
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_attribute
+//       Access: Public
+//  Description: Returns the NodeTransition from the current state
+//               associated with the indicated type, or NULL if there
+//               is no such transition set.
+////////////////////////////////////////////////////////////////////
+NodeTransition *GraphicsStateGuardian::
+get_attribute(TypeHandle type) const {
+  State::const_iterator si =
+    lower_bound(_state.begin(), _state.end(), StateInfo(type));
+
+  if (si != _state.end() && (*si)._type == type) {
+    return (*si)._trans;
+  }
+
+  return (NodeTransition *)NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::prepare_texture
 //     Function: GraphicsStateGuardian::prepare_texture
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -1062,9 +1055,10 @@ record_state_change(TypeHandle type) {
 
 
   // We can't use the get_class_type() methods since we don't have
   // We can't use the get_class_type() methods since we don't have
   // those header files available yet.
   // those header files available yet.
-  if (type.get_name() == "TransformTransition") {
+  string name = type.get_name();
+  if (name == "TransformTransition") {
     _transform_state_pcollector.add_level(1);
     _transform_state_pcollector.add_level(1);
-  } else if (type.get_name() == "TextureTransition") {
+  } else if (name == "TextureTransition") {
     _texture_state_pcollector.add_level(1);
     _texture_state_pcollector.add_level(1);
   }
   }
 }
 }

+ 25 - 5
panda/src/display/graphicsStateGuardian.h

@@ -33,8 +33,9 @@
 #include "factory.h"
 #include "factory.h"
 #include "renderTraverser.h"
 #include "renderTraverser.h"
 #include "pStatCollector.h"
 #include "pStatCollector.h"
+#include "allTransitionsWrapper.h"
 
 
-#include "plist.h"
+#include "pvector.h"
 
 
 class AllTransitionsWrapper;
 class AllTransitionsWrapper;
 
 
@@ -82,6 +83,7 @@ PUBLISHED:
   void release_all_geoms();
   void release_all_geoms();
 
 
   void clear_attribute(TypeHandle type);
   void clear_attribute(TypeHandle type);
+  NodeTransition *get_attribute(TypeHandle type) const;
 
 
 public:
 public:
   INLINE bool is_closed() const;
   INLINE bool is_closed() const;
@@ -126,9 +128,11 @@ public:
 
 
   virtual void reset();
   virtual void reset();
 
 
-  void set_state(const NodeTransitions &new_state, bool complete);
-  void set_state(const NodeTransitionCache &new_state, bool complete);
-  INLINE const NodeTransitions &get_state() const;
+  void modify_state(const NodeTransitions &new_state);
+  //  void modify_state(const NodeTransitionCache &new_state);
+  void set_state(const NodeTransitionCache &new_state);
+  INLINE void set_state(const AllTransitionsWrapper &new_state);
+  //  INLINE const NodeTransitionCache *get_state() const;
 
 
   RenderBuffer get_render_buffer(int buffer_type);
   RenderBuffer get_render_buffer(int buffer_type);
 
 
@@ -188,8 +192,20 @@ protected:
 #endif
 #endif
 
 
 protected:
 protected:
+  class StateInfo {
+  public:
+    INLINE StateInfo(TypeHandle type);
+    INLINE StateInfo(const NodeTransitions::value_type &value);
+    INLINE StateInfo(const NodeTransitionCache::value_type &value);
+    INLINE bool operator < (const StateInfo &other) const;
+
+    TypeHandle _type;
+    PT(NodeTransition) _trans;
+  };
+  typedef pvector<StateInfo> State;
+  State _state;
+
   int _buffer_mask;
   int _buffer_mask;
-  NodeTransitions _state;
   Colorf _color_clear_value;
   Colorf _color_clear_value;
   float _depth_clear_value;
   float _depth_clear_value;
   bool _stencil_clear_value;
   bool _stencil_clear_value;
@@ -308,6 +324,10 @@ private:
   friend class GraphicsWindow;
   friend class GraphicsWindow;
 };
 };
 
 
+template<class Transition>
+INLINE bool
+get_attribute_into(Transition *&ptr, GraphicsStateGuardian *gsg);
+
 #include "graphicsStateGuardian.I"
 #include "graphicsStateGuardian.I"
 
 
 #endif
 #endif

+ 11 - 11
panda/src/dxgsg/dxGraphicsStateGuardian.cxx

@@ -732,7 +732,7 @@ render_frame() {
   // measurably expensive.
   // measurably expensive.
   NodeTransitions state;
   NodeTransitions state;
   state.set_transition(new TextureTransition);
   state.set_transition(new TextureTransition);
-  set_state(state, false);
+  modify_state(state);
 #endif
 #endif
 
 
   HRESULT hr = _d3dDevice->BeginScene();
   HRESULT hr = _d3dDevice->BeginScene();
@@ -815,7 +815,7 @@ render_frame() {
         // same set of light pointers we had this frame.
         // same set of light pointers we had this frame.
         NodeTransitions state;
         NodeTransitions state;
         state.set_transition(new LightTransition);
         state.set_transition(new LightTransition);
-        set_state(state, false);
+        modify_state(state);
 
 
         // All this work to undo the lighting state each frame doesn't seem
         // All this work to undo the lighting state each frame doesn't seem
         // ideal--there may be a better way.  Maybe if the lights were just
         // ideal--there may be a better way.  Maybe if the lights were just
@@ -1335,7 +1335,7 @@ wants_colors() const {
     // shouldn't bother issuing geometry color commands.
     // shouldn't bother issuing geometry color commands.
 
 
     const ColorTransition *catt;
     const ColorTransition *catt;
-    if (!get_transition_into(catt, _state, ColorTransition::get_class_type())) {
+    if (!get_attribute_into(catt, this)) {
         // No scene graph color at all.
         // No scene graph color at all.
         return true;
         return true;
     }
     }
@@ -1835,7 +1835,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
     LMatrix4f modelview_mat;
     LMatrix4f modelview_mat;
 
 
     const TransformTransition *ctatt;
     const TransformTransition *ctatt;
-    if (!get_transition_into(ctatt, _state, TransformTransition::get_class_type()))
+    if (!get_attribute_into(ctatt, this)) {
         modelview_mat = LMatrix4f::ident_mat();
         modelview_mat = LMatrix4f::ident_mat();
     else
     else
         modelview_mat = ctatt->get_matrix();
         modelview_mat = ctatt->get_matrix();
@@ -1868,7 +1868,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
     TextureApplyTransition *taa = new TextureApplyTransition(TextureApplyProperty::M_modulate);
     TextureApplyTransition *taa = new TextureApplyTransition(TextureApplyProperty::M_modulate);
     state.set_transition(taa);
     state.set_transition(taa);
 
 
-    set_state(state, false);
+    modify_state(state);
 
 
     // the user can override alpha sorting if they want
     // the user can override alpha sorting if they want
     bool alpha = false;
     bool alpha = false;
@@ -1876,8 +1876,8 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) {
     if (!geom->get_alpha_disable()) {
     if (!geom->get_alpha_disable()) {
         // figure out if alpha's enabled (if not, no reason to sort)
         // figure out if alpha's enabled (if not, no reason to sort)
         const TransparencyTransition *ctratt;
         const TransparencyTransition *ctratt;
-        if (get_transition_into(ctratt, _state, TransparencyTransition::get_class_type()))
-            alpha = true;
+        if (get_attribute_into(ctratt, this))
+          alpha = (ctratt->get_mode() != TransparencyProperty::M_none);
     }
     }
 
 
     // inner loop vars
     // inner loop vars
@@ -2330,7 +2330,7 @@ draw_tri(GeomTri *geom, GeomContext *gc) {
         bool bDoGlobalSceneGraphColor=FALSE,bDoColor=(ColorBinding != G_OFF);
         bool bDoGlobalSceneGraphColor=FALSE,bDoColor=(ColorBinding != G_OFF);
 
 
         // We should issue geometry colors only if the scene graph color is off.
         // We should issue geometry colors only if the scene graph color is off.
-        if (get_transition_into(catt, _state, ColorTransition::get_class_type()) && !catt->is_off()) {
+        if (get_attribute_into(catt, this)) {
             if (!catt->is_real())
             if (!catt->is_real())
                 bDoColor=FALSE;  // this turns off any Geom colors
                 bDoColor=FALSE;  // this turns off any Geom colors
             else {
             else {
@@ -2731,7 +2731,7 @@ draw_multitri(Geom *geom, D3DPRIMITIVETYPE trilisttype) {
         bool bDoGlobalSceneGraphColor=FALSE,bDoColor=(ColorBinding != G_OFF);
         bool bDoGlobalSceneGraphColor=FALSE,bDoColor=(ColorBinding != G_OFF);
 
 
         // We should issue geometry colors only if the scene graph color is off.
         // We should issue geometry colors only if the scene graph color is off.
-        if (get_transition_into(catt, _state, ColorTransition::get_class_type()) && !catt->is_off()) {
+        if (get_attribute_into(catt, this)) {
             if (!catt->is_real())
             if (!catt->is_real())
                 bDoColor=FALSE;  // this turns off any Geom colors
                 bDoColor=FALSE;  // this turns off any Geom colors
             else {
             else {
@@ -3547,7 +3547,7 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr) {
     state.set_transition(dwa);
     state.set_transition(dwa);
     state.set_transition(ta);
     state.set_transition(ta);
     state.set_transition(taa);
     state.set_transition(taa);
-    set_state(state, false);
+    modify_state(state);
 
 
     // We set up an orthographic projection that defines our entire
     // We set up an orthographic projection that defines our entire
     // viewport to the range [0..1] in both dimensions.  Then, when we
     // viewport to the range [0..1] in both dimensions.  Then, when we
@@ -3759,7 +3759,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
             break;
             break;
     }
     }
 
 
-    set_state(state, false);
+    modify_state(state);
 
 
     enable_color_material(false);
     enable_color_material(false);
     set_unpack_alignment(1);
     set_unpack_alignment(1);

+ 30 - 0
panda/src/express/typeHandle.I

@@ -74,6 +74,36 @@ operator < (const TypeHandle &other) const {
   return (_index < other._index);
   return (_index < other._index);
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: TypeHandle::Ordering Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool TypeHandle::
+operator <= (const TypeHandle &other) const {
+  return (_index <= other._index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypeHandle::Ordering Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool TypeHandle::
+operator > (const TypeHandle &other) const {
+  return (_index > other._index);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: TypeHandle::Ordering Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool TypeHandle::
+operator >= (const TypeHandle &other) const {
+  return (_index >= other._index);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TypeHandle::get_name
 //     Function: TypeHandle::get_name
 //       Access: Public
 //       Access: Public

+ 3 - 0
panda/src/express/typeHandle.h

@@ -96,6 +96,9 @@ PUBLISHED:
   INLINE bool operator == (const TypeHandle &other) const;
   INLINE bool operator == (const TypeHandle &other) const;
   INLINE bool operator != (const TypeHandle &other) const;
   INLINE bool operator != (const TypeHandle &other) const;
   INLINE bool operator < (const TypeHandle &other) const;
   INLINE bool operator < (const TypeHandle &other) const;
+  INLINE bool operator <= (const TypeHandle &other) const;
+  INLINE bool operator > (const TypeHandle &other) const;
+  INLINE bool operator >= (const TypeHandle &other) const;
 
 
   INLINE string get_name(TypedObject *object = (TypedObject *)NULL) const;
   INLINE string get_name(TypedObject *object = (TypedObject *)NULL) const;
   INLINE bool is_derived_from(TypeHandle parent,
   INLINE bool is_derived_from(TypeHandle parent,

+ 6 - 30
panda/src/express/typeRegistryNode.cxx

@@ -99,14 +99,17 @@ is_derived_from(const TypeRegistryNode *child, const TypeRegistryNode *base) {
 
 
   // First, we should check whether the subtree tops of the two nodes
   // First, we should check whether the subtree tops of the two nodes
   // inherit from each other.
   // inherit from each other.
-  const TypeRegistryNode *child_top = child->_inherit._top;
-  const TypeRegistryNode *base_top = base->_inherit._top;
+  TypeRegistryNode *child_top = child->_inherit._top;
+  TypeRegistryNode *base_top = base->_inherit._top;
 
 
   bool derives = false;
   bool derives = false;
 
 
   // If child_top does not inherit from base_top, it follows that
   // If child_top does not inherit from base_top, it follows that
   // child does not inherit from base.
   // child does not inherit from base.
-  TopInheritance::const_iterator ti = child_top->find_top_inherit(base_top);
+  TopInheritance::const_iterator ti = 
+    lower_bound(child_top->_top_inheritance.begin(), 
+                child_top->_top_inheritance.end(),
+                Inherit(base_top, 0, 0));
 
 
   while (ti != child_top->_top_inheritance.end() && 
   while (ti != child_top->_top_inheritance.end() && 
          (*ti)._top == base_top &&
          (*ti)._top == base_top &&
@@ -333,33 +336,6 @@ r_build_subtrees(TypeRegistryNode *top, int bit_count,
     }      
     }      
   }
   }
 }
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: TypeRegistryNode::find_top_inherit
-//       Access: Private, Static
-//  Description: Finds the first element in the _top_inheritance array
-//               that matches the indicated base node.  If the base
-//               node does not appear in the _top_inheritance array
-//               (implying that this node does not inherit from the
-//               base node), returns _top_inheritance.end().
-////////////////////////////////////////////////////////////////////
-TypeRegistryNode::TopInheritance::const_iterator TypeRegistryNode::
-find_top_inherit(const TypeRegistryNode *base) const {
-  // If the need arises, we can make this a binary search to
-  // theoretically save even more time, since the list is already
-  // sorted.  However, the lists do tend to be short, and this
-  // function doesn't get called too awful much, so a linear search is
-  // not as bad as you might think.
-
-  TopInheritance::const_iterator ti;
-  for (ti = _top_inheritance.begin(); ti != _top_inheritance.end(); ++ti) {
-    if ((*ti)._top == base) {
-      return ti;
-    }
-  }
-
-  return _top_inheritance.end();
-}
  
  
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: TypeRegistryNode::check_derived_from
 //     Function: TypeRegistryNode::check_derived_from

+ 0 - 3
panda/src/express/typeRegistryNode.h

@@ -80,9 +80,6 @@ private:
   void r_build_subtrees(TypeRegistryNode *top, 
   void r_build_subtrees(TypeRegistryNode *top, 
                         int bit_count, SubtreeMaskType bits);
                         int bit_count, SubtreeMaskType bits);
 
 
-  TopInheritance::const_iterator
-  find_top_inherit(const TypeRegistryNode *base) const;
-
   static bool check_derived_from(const TypeRegistryNode *child,
   static bool check_derived_from(const TypeRegistryNode *child,
                                  const TypeRegistryNode *base);
                                  const TypeRegistryNode *base);
 
 

+ 9 - 10
panda/src/glgsg/glGraphicsStateGuardian.cxx

@@ -392,7 +392,7 @@ clear(const RenderBuffer &buffer) {
   glgsg_cat.debug(false) << ")" << endl;
   glgsg_cat.debug(false) << ")" << endl;
 #endif
 #endif
 
 
-  set_state(state, false);
+  modify_state(state);
   glClear(mask);
   glClear(mask);
 }
 }
 
 
@@ -958,7 +958,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
   LMatrix4f modelview_mat;
   LMatrix4f modelview_mat;
 
 
   const TransformTransition *ctatt;
   const TransformTransition *ctatt;
-  if (!get_transition_into(ctatt, _state, TransformTransition::get_class_type()))
+  if (!get_attribute_into(ctatt, this))
     modelview_mat = LMatrix4f::ident_mat();
     modelview_mat = LMatrix4f::ident_mat();
   else
   else
     modelview_mat = ctatt->get_matrix();
     modelview_mat = ctatt->get_matrix();
@@ -1025,7 +1025,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
   taa->set_mode(TextureApplyProperty::M_modulate);
   taa->set_mode(TextureApplyProperty::M_modulate);
   state.set_transition(taa);
   state.set_transition(taa);
 
 
-  set_state(state, false);
+  modify_state(state);
 
 
   // the user can override alpha sorting if they want
   // the user can override alpha sorting if they want
   bool alpha = false;
   bool alpha = false;
@@ -1033,8 +1033,8 @@ draw_sprite(GeomSprite *geom, GeomContext *) {
   if (geom->get_alpha_disable() == false) {
   if (geom->get_alpha_disable() == false) {
     // figure out if alpha's enabled (if not, no reason to sort)
     // figure out if alpha's enabled (if not, no reason to sort)
     const TransparencyTransition *ctratt;
     const TransparencyTransition *ctratt;
-    if (get_transition_into(ctratt, _state))
-      alpha = true;
+    if (get_attribute_into(ctratt, this))
+      alpha = (ctratt->get_mode() != TransparencyProperty::M_none);
   }
   }
 
 
   // sort container and iterator
   // sort container and iterator
@@ -2061,7 +2061,7 @@ draw_texture(TextureContext *tc, const DisplayRegion *dr) {
   state.set_transition(dwa);
   state.set_transition(dwa);
   state.set_transition(ta);
   state.set_transition(ta);
   state.set_transition(taa);
   state.set_transition(taa);
-  set_state(state, false);
+  modify_state(state);
 
 
   // We set up an orthographic projection that defines our entire
   // We set up an orthographic projection that defines our entire
   // viewport to the range [0..1] in both dimensions.  Then, when we
   // viewport to the range [0..1] in both dimensions.  Then, when we
@@ -2301,7 +2301,7 @@ draw_pixel_buffer(PixelBuffer *pb, const DisplayRegion *dr,
     break;
     break;
   }
   }
 
 
-  set_state(state, false);
+  modify_state(state);
 
 
   set_unpack_alignment(1);
   set_unpack_alignment(1);
 
 
@@ -3511,8 +3511,7 @@ end_decal(GeomNode *base_geom) {
       // Finally, restore the depth write and color mask states to the
       // Finally, restore the depth write and color mask states to the
       // way they're supposed to be.
       // way they're supposed to be.
       DepthWriteTransition *depth_write;
       DepthWriteTransition *depth_write;
-      if (get_transition_into(depth_write, _state,
-                             DepthWriteTransition::get_class_type())) {
+      if (get_attribute_into(depth_write, this)) {
         issue_depth_write(depth_write);
         issue_depth_write(depth_write);
       }
       }
 
 
@@ -3523,7 +3522,7 @@ end_decal(GeomNode *base_geom) {
         }
         }
       } else {
       } else {
         ColorMaskTransition *color_mask;
         ColorMaskTransition *color_mask;
-        if (get_transition_into(color_mask, _state, ColorMaskTransition::get_class_type())) {
+        if (get_attribute_into(color_mask, this)) {
           issue_color_mask(color_mask);
           issue_color_mask(color_mask);
         } else {
         } else {
           glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
           glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);

+ 20 - 7
panda/src/graph/nodeTransition.cxx

@@ -41,17 +41,11 @@ TypeHandle NodeTransition::_type_handle;
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int NodeTransition::
 int NodeTransition::
 compare_to(const NodeTransition &other) const {
 compare_to(const NodeTransition &other) const {
-  if (this == &other) {
-    // Same pointer, no comparison necessary.
-    return 0;
-  }
-
   TypeHandle my_handle = get_handle();
   TypeHandle my_handle = get_handle();
   TypeHandle other_handle = other.get_handle();
   TypeHandle other_handle = other.get_handle();
 
 
   if (my_handle != other_handle) {
   if (my_handle != other_handle) {
-    return
-      (my_handle < other_handle) ? -1 : 1;
+    return (my_handle < other_handle) ? -1 : 1;
 
 
   } else if (_priority != other._priority) {
   } else if (_priority != other._priority) {
     return _priority - other._priority;
     return _priority - other._priority;
@@ -61,6 +55,25 @@ compare_to(const NodeTransition &other) const {
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeTransition::compare_to_ignore_priority
+//       Access: Public
+//  Description: This is equivalent to compare_to() but it does not
+//               consider different priorities to be relevant.
+////////////////////////////////////////////////////////////////////
+int NodeTransition::
+compare_to_ignore_priority(const NodeTransition &other) const {
+  TypeHandle my_handle = get_handle();
+  TypeHandle other_handle = other.get_handle();
+
+  if (my_handle != other_handle) {
+    return (my_handle < other_handle) ? -1 : 1;
+
+  } else {
+    return internal_compare_to(&other);
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeTransition::get_handle
 //     Function: NodeTransition::get_handle
 //       Access: Public, Virtual
 //       Access: Public, Virtual

+ 1 - 0
panda/src/graph/nodeTransition.h

@@ -74,6 +74,7 @@ public:
   INLINE_GRAPH bool operator >= (const NodeTransition &other) const;
   INLINE_GRAPH bool operator >= (const NodeTransition &other) const;
 
 
   int compare_to(const NodeTransition &other) const;
   int compare_to(const NodeTransition &other) const;
+  int compare_to_ignore_priority(const NodeTransition &other) const;
   INLINE_GRAPH void generate_hash(GraphHashGenerator &hash) const;
   INLINE_GRAPH void generate_hash(GraphHashGenerator &hash) const;
 
 
 PUBLISHED:
 PUBLISHED:

+ 31 - 0
panda/src/graph/nodeTransitionCache.I

@@ -44,6 +44,26 @@ size() const {
   return _cache.size();
   return _cache.size();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeTransitionCache::begin
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH NodeTransitionCache::iterator NodeTransitionCache::
+begin() {
+  return _cache.begin();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodeTransitionCache::end
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH NodeTransitionCache::iterator NodeTransitionCache::
+end() {
+  return _cache.end();
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeTransitionCache::begin
 //     Function: NodeTransitionCache::begin
 //       Access: Public
 //       Access: Public
@@ -64,6 +84,17 @@ end() const {
   return _cache.end();
   return _cache.end();
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeTransitionCache::end
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE_GRAPH NodeTransitionCache::iterator NodeTransitionCache::
+insert(NodeTransitionCache::iterator position, 
+       const NodeTransitionCache::value_type &item) {
+  return _cache.insert(position, item);
+}
+
 INLINE_GRAPH ostream &operator << (ostream &out, const NodeTransitionCache &ntc) {
 INLINE_GRAPH ostream &operator << (ostream &out, const NodeTransitionCache &ntc) {
   ntc.output(out);
   ntc.output(out);
   return out;
   return out;

+ 5 - 2
panda/src/graph/nodeTransitionCache.h

@@ -66,18 +66,21 @@ public:
 private:
 private:
   typedef pmap<TypeHandle, NodeTransitionCacheEntry> Cache;
   typedef pmap<TypeHandle, NodeTransitionCacheEntry> Cache;
 public:
 public:
-  // STL-like definitions to allow read-only traversal of the
+  // STL-like definitions to allow read-write traversal of the
   // individual transitions.  Note that each of these is a
   // individual transitions.  Note that each of these is a
   // NodeTransitionCacheEntry, not simply a PT(NodeTransition).
   // NodeTransitionCacheEntry, not simply a PT(NodeTransition).
   // Beware!  These are not safe to use outside of PANDA.DLL.
   // Beware!  These are not safe to use outside of PANDA.DLL.
-  typedef Cache::const_iterator iterator;
+  typedef Cache::iterator iterator;
   typedef Cache::const_iterator const_iterator;
   typedef Cache::const_iterator const_iterator;
   typedef Cache::value_type value_type;
   typedef Cache::value_type value_type;
   typedef Cache::size_type size_type;
   typedef Cache::size_type size_type;
 
 
   INLINE_GRAPH size_type size() const;
   INLINE_GRAPH size_type size() const;
+  INLINE_GRAPH iterator begin();
+  INLINE_GRAPH iterator end();
   INLINE_GRAPH const_iterator begin() const;
   INLINE_GRAPH const_iterator begin() const;
   INLINE_GRAPH const_iterator end() const;
   INLINE_GRAPH const_iterator end() const;
+  INLINE_GRAPH iterator insert(iterator position, const value_type &item);
 
 
 
 
 public:
 public:

+ 1 - 1
panda/src/graph/nodeTransitions.h

@@ -66,7 +66,7 @@ private:
   typedef pmap<TypeHandle, PT(NodeTransition) > Transitions;
   typedef pmap<TypeHandle, PT(NodeTransition) > Transitions;
 
 
 public:
 public:
-  // STL-like definitions to allow read-only traversal of the
+  // STL-like definitions to allow read-write traversal of the
   // individual transitions.  Beware!  These are not safe to use
   // individual transitions.  Beware!  These are not safe to use
   // outside of PANDA.DLL.
   // outside of PANDA.DLL.
   typedef Transitions::iterator iterator;
   typedef Transitions::iterator iterator;

+ 1 - 1
panda/src/pgui/pgTop.cxx

@@ -220,7 +220,7 @@ r_traverse(Node *node, const ArcChain &chain) {
         wrt_trans, RenderRelation::get_class_type());
         wrt_trans, RenderRelation::get_class_type());
     AllTransitionsWrapper complete_trans;
     AllTransitionsWrapper complete_trans;
     complete_trans.compose_from(_trans, wrt_trans);
     complete_trans.compose_from(_trans, wrt_trans);
-    _gsg->set_state(complete_trans.get_transitions(), true);
+    _gsg->set_state(complete_trans.get_transitions());
 
 
     // Finally, draw the Geom.
     // Finally, draw the Geom.
     _gsg->prepare_display_region();
     _gsg->prepare_display_region();

+ 5 - 1
panda/src/sgattrib/alphaTransformTransition.cxx

@@ -22,6 +22,7 @@
 #include "indent.h"
 #include "indent.h"
 #include "dcast.h"
 #include "dcast.h"
 
 
+PT(NodeTransition) AlphaTransformTransition::_initial;
 TypeHandle AlphaTransformTransition::_type_handle;
 TypeHandle AlphaTransformTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -43,7 +44,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *AlphaTransformTransition::
 NodeTransition *AlphaTransformTransition::
 make_initial() const {
 make_initial() const {
-  return new AlphaTransformTransition;
+  if (_initial.is_null()) {
+    _initial = new AlphaTransformTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/alphaTransformTransition.h

@@ -50,7 +50,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   AlphaTransformProperty _state;
   AlphaTransformProperty _state;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/billboardTransition.cxx

@@ -34,6 +34,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) BillboardTransition::_initial;
 TypeHandle BillboardTransition::_type_handle;
 TypeHandle BillboardTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -54,7 +55,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *BillboardTransition::
 NodeTransition *BillboardTransition::
 make_initial() const {
 make_initial() const {
-  return new BillboardTransition;
+  if (_initial.is_null()) {
+    _initial = new BillboardTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 1 - 0
panda/src/sgattrib/billboardTransition.h

@@ -76,6 +76,7 @@ private:
   bool _eye_relative;
   bool _eye_relative;
   bool _axial_rotate;
   bool _axial_rotate;
   float _offset;
   float _offset;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);

+ 5 - 1
panda/src/sgattrib/clipPlaneTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) ClipPlaneTransition::_initial;
 TypeHandle ClipPlaneTransition::_type_handle;
 TypeHandle ClipPlaneTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *ClipPlaneTransition::
 NodeTransition *ClipPlaneTransition::
 make_initial() const {
 make_initial() const {
-  return new ClipPlaneTransition;
+  if (_initial.is_null()) {
+    _initial = new ClipPlaneTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/sgattrib/clipPlaneTransition.h

@@ -55,6 +55,9 @@ protected:
   virtual void write_property(ostream &out, const PT_Node &prop,
   virtual void write_property(ostream &out, const PT_Node &prop,
                               int indent_level) const;
                               int indent_level) const;
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/colorBlendTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) ColorBlendTransition::_initial;
 TypeHandle ColorBlendTransition::_type_handle;
 TypeHandle ColorBlendTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *ColorBlendTransition::
 NodeTransition *ColorBlendTransition::
 make_initial() const {
 make_initial() const {
-  return new ColorBlendTransition;
+  if (_initial.is_null()) {
+    _initial = new ColorBlendTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/colorBlendTransition.h

@@ -48,7 +48,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   ColorBlendProperty _value;
   ColorBlendProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/colorMaskTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) ColorMaskTransition::_initial;
 TypeHandle ColorMaskTransition::_type_handle;
 TypeHandle ColorMaskTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *ColorMaskTransition::
 NodeTransition *ColorMaskTransition::
 make_initial() const {
 make_initial() const {
-  return new ColorMaskTransition;
+  if (_initial.is_null()) {
+    _initial = new ColorMaskTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/colorMaskTransition.h

@@ -59,7 +59,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   ColorMaskProperty _value;
   ColorMaskProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/colorMatrixTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamWriter.h>
 #include <bamWriter.h>
 #include <bamReader.h>
 #include <bamReader.h>
 
 
+PT(NodeTransition) ColorMatrixTransition::_initial;
 TypeHandle ColorMatrixTransition::_type_handle;
 TypeHandle ColorMatrixTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////s
 ////////////////////////////////////////////////////////////////////s
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *ColorMatrixTransition::
 NodeTransition *ColorMatrixTransition::
 make_initial() const {
 make_initial() const {
-  return new ColorMatrixTransition;
+  if (_initial.is_null()) {
+    _initial = new ColorMatrixTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/sgattrib/colorMatrixTransition.h

@@ -43,13 +43,14 @@ protected:
   virtual MatrixTransition<LMatrix4f> *
   virtual MatrixTransition<LMatrix4f> *
   make_with_matrix(const LMatrix4f &matrix) const;
   make_with_matrix(const LMatrix4f &matrix) const;
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);
 
 
   static TypedWritable *make_ColorMatrixTransition(const FactoryParams &params);
   static TypedWritable *make_ColorMatrixTransition(const FactoryParams &params);
 
 
-protected:
-
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/colorTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) ColorTransition::_initial;
 TypeHandle ColorTransition::_type_handle;
 TypeHandle ColorTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *ColorTransition::
 NodeTransition *ColorTransition::
 make_initial() const {
 make_initial() const {
-  return new ColorTransition;
+  if (_initial.is_null()) {
+    _initial = new ColorTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/colorTransition.h

@@ -62,7 +62,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   ColorProperty _value;
   ColorProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();

+ 5 - 1
panda/src/sgattrib/cullFaceTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) CullFaceTransition::_initial;
 TypeHandle CullFaceTransition::_type_handle;
 TypeHandle CullFaceTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *CullFaceTransition::
 NodeTransition *CullFaceTransition::
 make_initial() const {
 make_initial() const {
-  return new CullFaceTransition;
+  if (_initial.is_null()) {
+    _initial = new CullFaceTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/cullFaceTransition.h

@@ -50,7 +50,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   CullFaceProperty _value;
   CullFaceProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);

+ 5 - 1
panda/src/sgattrib/decalTransition.cxx

@@ -22,6 +22,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) DecalTransition::_initial;
 TypeHandle DecalTransition::_type_handle;
 TypeHandle DecalTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -43,7 +44,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *DecalTransition::
 NodeTransition *DecalTransition::
 make_initial() const {
 make_initial() const {
-  return new DecalTransition;
+  if (_initial.is_null()) {
+    _initial = new DecalTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/sgattrib/decalTransition.h

@@ -51,6 +51,9 @@ public:
 
 
   virtual bool has_sub_render() const;
   virtual bool has_sub_render() const;
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);
   static TypedWritable *make_DecalTransition(const FactoryParams &params);
   static TypedWritable *make_DecalTransition(const FactoryParams &params);

+ 5 - 1
panda/src/sgattrib/depthTestTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamWriter.h>
 #include <bamWriter.h>
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) DepthTestTransition::_initial;
 TypeHandle DepthTestTransition::_type_handle;
 TypeHandle DepthTestTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *DepthTestTransition::
 NodeTransition *DepthTestTransition::
 make_initial() const {
 make_initial() const {
-  return new DepthTestTransition;
+  if (_initial.is_null()) {
+    _initial = new DepthTestTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/depthTestTransition.h

@@ -52,7 +52,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   DepthTestProperty _value;
   DepthTestProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();

+ 5 - 1
panda/src/sgattrib/depthWriteTransition.cxx

@@ -23,6 +23,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) DepthWriteTransition::_initial;
 TypeHandle DepthWriteTransition::_type_handle;
 TypeHandle DepthWriteTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -44,7 +45,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *DepthWriteTransition::
 NodeTransition *DepthWriteTransition::
 make_initial() const {
 make_initial() const {
-  return new DepthWriteTransition;
+  if (_initial.is_null()) {
+    _initial = new DepthWriteTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/sgattrib/depthWriteTransition.h

@@ -39,6 +39,9 @@ public:
 
 
   virtual void issue(GraphicsStateGuardianBase *gsgbase);
   virtual void issue(GraphicsStateGuardianBase *gsgbase);
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();
   virtual void write_datagram(BamWriter* manager, Datagram &me);
   virtual void write_datagram(BamWriter* manager, Datagram &me);

+ 7 - 3
panda/src/sgattrib/drawBoundsTransition.cxx

@@ -31,6 +31,7 @@
 #include <renderTraverser.h>
 #include <renderTraverser.h>
 #include <geomSphere.h>
 #include <geomSphere.h>
 
 
+PT(NodeTransition) DrawBoundsTransition::_initial;
 TypeHandle DrawBoundsTransition::_type_handle;
 TypeHandle DrawBoundsTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -74,7 +75,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *DrawBoundsTransition::
 NodeTransition *DrawBoundsTransition::
 make_initial() const {
 make_initial() const {
-  return new DrawBoundsTransition;
+  if (_initial.is_null()) {
+    _initial = new DrawBoundsTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -111,7 +115,7 @@ sub_render(NodeRelation *arc, const AllTransitionsWrapper &input_trans,
     new_ta->set_matrix(mat);
     new_ta->set_matrix(mat);
     _outside_attrib.set_transition(new_ta);
     _outside_attrib.set_transition(new_ta);
 
 
-    gsg->set_state(_outside_attrib, true);
+    gsg->set_state(_outside_attrib);
 
 
     if (vol.is_of_type(BoundingSphere::get_class_type())) {
     if (vol.is_of_type(BoundingSphere::get_class_type())) {
       const BoundingSphere *sphere = DCAST(BoundingSphere, &vol);
       const BoundingSphere *sphere = DCAST(BoundingSphere, &vol);
@@ -126,7 +130,7 @@ sub_render(NodeRelation *arc, const AllTransitionsWrapper &input_trans,
       geom.set_num_prims(1);
       geom.set_num_prims(1);
 
 
       gsg->draw_sphere(&geom, NULL);
       gsg->draw_sphere(&geom, NULL);
-      gsg->set_state(_inside_attrib, false);
+      gsg->modify_state(_inside_attrib);
       gsg->draw_sphere(&geom, NULL);
       gsg->draw_sphere(&geom, NULL);
 
 
     } else {
     } else {

+ 8 - 4
panda/src/sgattrib/drawBoundsTransition.h

@@ -19,10 +19,11 @@
 #ifndef DRAWBOUNDSTRANSITION_H
 #ifndef DRAWBOUNDSTRANSITION_H
 #define DRAWBOUNDSTRANSITION_H
 #define DRAWBOUNDSTRANSITION_H
 
 
-#include <pandabase.h>
+#include "pandabase.h"
 
 
-#include <immediateTransition.h>
-#include <nodeTransitions.h>
+#include "immediateTransition.h"
+#include "nodeTransitions.h"
+#include "allTransitionsWrapper.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //       Class : DrawBoundsTransition
 //       Class : DrawBoundsTransition
@@ -46,9 +47,12 @@ public:
                           RenderTraverser *trav);
                           RenderTraverser *trav);
   virtual bool has_sub_render() const;
   virtual bool has_sub_render() const;
 
 
-  NodeTransitions _outside_attrib;
+private:
+  AllTransitionsWrapper _outside_attrib;
   NodeTransitions _inside_attrib;
   NodeTransitions _inside_attrib;
 
 
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/fogTransition.cxx

@@ -21,6 +21,7 @@
 #include "dcast.h"
 #include "dcast.h"
 #include "indent.h"
 #include "indent.h"
 
 
+PT(NodeTransition) FogTransition::_initial;
 TypeHandle FogTransition::_type_handle;
 TypeHandle FogTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -42,7 +43,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *FogTransition::
 NodeTransition *FogTransition::
 make_initial() const {
 make_initial() const {
-  return new FogTransition;
+  if (_initial.is_null()) {
+    _initial = new FogTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/fogTransition.h

@@ -51,7 +51,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   PT(Fog) _value;
   PT(Fog) _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/linesmoothTransition.cxx

@@ -18,6 +18,7 @@
 
 
 #include "linesmoothTransition.h"
 #include "linesmoothTransition.h"
 
 
+PT(NodeTransition) LinesmoothTransition::_initial;
 TypeHandle LinesmoothTransition::_type_handle;
 TypeHandle LinesmoothTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -39,7 +40,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *LinesmoothTransition::
 NodeTransition *LinesmoothTransition::
 make_initial() const {
 make_initial() const {
-  return new LinesmoothTransition;
+  if (_initial.is_null()) {
+    _initial = new LinesmoothTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/sgattrib/linesmoothTransition.h

@@ -39,6 +39,9 @@ public:
 
 
   virtual void issue(GraphicsStateGuardianBase *gsgbase);
   virtual void issue(GraphicsStateGuardianBase *gsgbase);
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/materialTransition.cxx

@@ -25,6 +25,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) MaterialTransition::_initial;
 TypeHandle MaterialTransition::_type_handle;
 TypeHandle MaterialTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -46,7 +47,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *MaterialTransition::
 NodeTransition *MaterialTransition::
 make_initial() const {
 make_initial() const {
-  return new MaterialTransition;
+  if (_initial.is_null()) {
+    _initial = new MaterialTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/materialTransition.h

@@ -51,7 +51,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   CPT(Material) _value;
   CPT(Material) _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();

+ 5 - 1
panda/src/sgattrib/pointShapeTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) PointShapeTransition::_initial;
 TypeHandle PointShapeTransition::_type_handle;
 TypeHandle PointShapeTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *PointShapeTransition::
 NodeTransition *PointShapeTransition::
 make_initial() const {
 make_initial() const {
-  return new PointShapeTransition;
+  if (_initial.is_null()) {
+    _initial = new PointShapeTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/pointShapeTransition.h

@@ -48,7 +48,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   PointShapeProperty _value;
   PointShapeProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/polygonOffsetTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) PolygonOffsetTransition::_initial;
 TypeHandle PolygonOffsetTransition::_type_handle;
 TypeHandle PolygonOffsetTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *PolygonOffsetTransition::
 NodeTransition *PolygonOffsetTransition::
 make_initial() const {
 make_initial() const {
-  return new PolygonOffsetTransition;
+  if (_initial.is_null()) {
+    _initial = new PolygonOffsetTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/polygonOffsetTransition.h

@@ -53,7 +53,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   PolygonOffsetProperty _state;
   PolygonOffsetProperty _state;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/renderModeTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) RenderModeTransition::_initial;
 TypeHandle RenderModeTransition::_type_handle;
 TypeHandle RenderModeTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *RenderModeTransition::
 NodeTransition *RenderModeTransition::
 make_initial() const {
 make_initial() const {
-  return new RenderModeTransition;
+  if (_initial.is_null()) {
+    _initial = new RenderModeTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/renderModeTransition.h

@@ -51,7 +51,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   RenderModeProperty _value;
   RenderModeProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/stencilTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) StencilTransition::_initial;
 TypeHandle StencilTransition::_type_handle;
 TypeHandle StencilTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *StencilTransition::
 NodeTransition *StencilTransition::
 make_initial() const {
 make_initial() const {
-  return new StencilTransition;
+  if (_initial.is_null()) {
+    _initial = new StencilTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/stencilTransition.h

@@ -57,7 +57,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   StencilProperty _value;
   StencilProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/texGenTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) TexGenTransition::_initial;
 TypeHandle TexGenTransition::_type_handle;
 TypeHandle TexGenTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TexGenTransition::
 NodeTransition *TexGenTransition::
 make_initial() const {
 make_initial() const {
-  return new TexGenTransition;
+  if (_initial.is_null()) {
+    _initial = new TexGenTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/texGenTransition.h

@@ -55,7 +55,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   TexGenProperty _value;
   TexGenProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {

+ 5 - 1
panda/src/sgattrib/texMatrixTransition.cxx

@@ -20,6 +20,7 @@
 
 
 #include <indent.h>
 #include <indent.h>
 
 
+PT(NodeTransition) TexMatrixTransition::_initial;
 TypeHandle TexMatrixTransition::_type_handle;
 TypeHandle TexMatrixTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -41,7 +42,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TexMatrixTransition::
 NodeTransition *TexMatrixTransition::
 make_initial() const {
 make_initial() const {
-  return new TexMatrixTransition;
+  if (_initial.is_null()) {
+    _initial = new TexMatrixTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 0
panda/src/sgattrib/texMatrixTransition.h

@@ -43,6 +43,9 @@ protected:
   virtual MatrixTransition<LMatrix4f> *
   virtual MatrixTransition<LMatrix4f> *
   make_with_matrix(const LMatrix4f &matrix) const;
   make_with_matrix(const LMatrix4f &matrix) const;
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/textureApplyTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) TextureApplyTransition::_initial;
 TypeHandle TextureApplyTransition::_type_handle;
 TypeHandle TextureApplyTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TextureApplyTransition::
 NodeTransition *TextureApplyTransition::
 make_initial() const {
 make_initial() const {
-  return new TextureApplyTransition;
+  if (_initial.is_null()) {
+    _initial = new TextureApplyTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/textureApplyTransition.h

@@ -48,7 +48,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   TextureApplyProperty _value;
   TextureApplyProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);

+ 5 - 1
panda/src/sgattrib/textureTransition.cxx

@@ -26,6 +26,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) TextureTransition::_initial;
 TypeHandle TextureTransition::_type_handle;
 TypeHandle TextureTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -47,7 +48,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TextureTransition::
 NodeTransition *TextureTransition::
 make_initial() const {
 make_initial() const {
-  return new TextureTransition;
+  if (_initial.is_null()) {
+    _initial = new TextureTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/textureTransition.h

@@ -63,7 +63,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   PT(Texture) _value;
   PT(Texture) _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory();
   static void register_with_read_factory();

+ 5 - 1
panda/src/sgattrib/transformTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamWriter.h>
 #include <bamWriter.h>
 #include <bamReader.h>
 #include <bamReader.h>
 
 
+PT(NodeTransition) TransformTransition::_initial;
 TypeHandle TransformTransition::_type_handle;
 TypeHandle TransformTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TransformTransition::
 NodeTransition *TransformTransition::
 make_initial() const {
 make_initial() const {
-  return new TransformTransition;
+  if (_initial.is_null()) {
+    _initial = new TransformTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 3 - 2
panda/src/sgattrib/transformTransition.h

@@ -42,13 +42,14 @@ protected:
   virtual MatrixTransition<LMatrix4f> *
   virtual MatrixTransition<LMatrix4f> *
   make_with_matrix(const LMatrix4f &matrix) const;
   make_with_matrix(const LMatrix4f &matrix) const;
 
 
+private:
+  static PT(NodeTransition) _initial;
+
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);
 
 
   static TypedWritable *make_TransformTransition(const FactoryParams &params);
   static TypedWritable *make_TransformTransition(const FactoryParams &params);
 
 
-protected:
-
 public:
 public:
   virtual TypeHandle get_type() const {
   virtual TypeHandle get_type() const {
     return get_class_type();
     return get_class_type();

+ 5 - 1
panda/src/sgattrib/transparencyTransition.cxx

@@ -24,6 +24,7 @@
 #include <bamReader.h>
 #include <bamReader.h>
 #include <bamWriter.h>
 #include <bamWriter.h>
 
 
+PT(NodeTransition) TransparencyTransition::_initial;
 TypeHandle TransparencyTransition::_type_handle;
 TypeHandle TransparencyTransition::_type_handle;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -45,7 +46,10 @@ make_copy() const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 NodeTransition *TransparencyTransition::
 NodeTransition *TransparencyTransition::
 make_initial() const {
 make_initial() const {
-  return new TransparencyTransition;
+  if (_initial.is_null()) {
+    _initial = new TransparencyTransition;
+  }
+  return _initial;
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////

+ 2 - 0
panda/src/sgattrib/transparencyTransition.h

@@ -56,7 +56,9 @@ protected:
   virtual void output_value(ostream &out) const;
   virtual void output_value(ostream &out) const;
   virtual void write_value(ostream &out, int indent_level) const;
   virtual void write_value(ostream &out, int indent_level) const;
 
 
+private:
   TransparencyProperty _value;
   TransparencyProperty _value;
+  static PT(NodeTransition) _initial;
 
 
 public:
 public:
   static void register_with_read_factory(void);
   static void register_with_read_factory(void);

+ 2 - 2
panda/src/sgraphutil/directRenderTraverser.cxx

@@ -164,7 +164,7 @@ reached_node(Node *node, AllTransitionsWrapper &render_state,
 
 
   if (node->is_of_type(GeomNode::get_class_type())) {
   if (node->is_of_type(GeomNode::get_class_type())) {
     _gsg->_geom_nodes_pcollector.add_level(1);
     _gsg->_geom_nodes_pcollector.add_level(1);
-    _gsg->set_state(render_state.get_transitions(), true);
+    _gsg->set_state(render_state);
     // Make sure the current display region is still in effect.
     // Make sure the current display region is still in effect.
     _gsg->prepare_display_region();
     _gsg->prepare_display_region();
 
 
@@ -256,7 +256,7 @@ backward_arc(NodeRelation *arc, AllTransitionsWrapper &,
   mark_backward_arc(arc);
   mark_backward_arc(arc);
   if (level_state._decal_mode) {
   if (level_state._decal_mode) {
     // Reset the state to redraw the base geometry.
     // Reset the state to redraw the base geometry.
-    _gsg->set_state(post.get_transitions(), true);
+    _gsg->set_state(post);
     _gsg->prepare_display_region();
     _gsg->prepare_display_region();
     _gsg->end_decal(DCAST(GeomNode, arc->get_child()));
     _gsg->end_decal(DCAST(GeomNode, arc->get_child()));
   }
   }

+ 1 - 1
panda/src/sgraphutil/quickRenderTraverser.cxx

@@ -149,7 +149,7 @@ r_traverse(RenderRelation *arc, const QuickRenderLevelState &level_state) {
     AllTransitionsWrapper attrib;
     AllTransitionsWrapper attrib;
     attrib.compose_from(_initial_state, trans);
     attrib.compose_from(_initial_state, trans);
 
 
-    _gsg->set_state(attrib.get_transitions(), true);
+    _gsg->set_state(attrib);
     gnode->draw(_gsg);
     gnode->draw(_gsg);
   }
   }