Browse Source

add NodePathCollection::set_texture()

David Rose 18 years ago
parent
commit
f56e10210d

+ 33 - 0
panda/src/pgraph/nodePathCollection.I

@@ -36,3 +36,36 @@ INLINE void NodePathCollection::
 ls() const {
 ls() const {
   ls(nout);
   ls(nout);
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::set_color
+//       Access: Published
+//  Description: Colors all NodePaths in the collection
+////////////////////////////////////////////////////////////////////
+INLINE void NodePathCollection::
+set_color(float r, float g, float b, float a, int priority) {
+  set_color(Colorf(r, g, b, a), priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::set_color_scale
+//       Access: Published
+//  Description: Applies color scales to all NodePaths in the
+//               collection.  The existing color scale is replaced.
+////////////////////////////////////////////////////////////////////
+INLINE void NodePathCollection::
+set_color_scale(float r, float g, float b, float a, int priority) {
+  set_color_scale(LVecBase4f(r, g, b, a), priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::compose_color_scale
+//       Access: Published
+//  Description: Applies color scales to all NodePaths in the
+//               collection.  The existing color scale, if any, is
+//               multiplied by the specified color scale.
+////////////////////////////////////////////////////////////////////
+INLINE void NodePathCollection::
+compose_color_scale(float r, float g, float b, float a, int priority) {
+  compose_color_scale(LVecBase4f(r, g, b, a), priority);
+}

+ 151 - 30
panda/src/pgraph/nodePathCollection.cxx

@@ -19,6 +19,8 @@
 #include "nodePathCollection.h"
 #include "nodePathCollection.h"
 #include "findApproxPath.h"
 #include "findApproxPath.h"
 #include "findApproxLevelEntry.h"
 #include "findApproxLevelEntry.h"
+#include "textureAttrib.h"
+#include "colorScaleAttrib.h"
 #include "colorAttrib.h"
 #include "colorAttrib.h"
 
 
 #include "indent.h"
 #include "indent.h"
@@ -422,75 +424,194 @@ set_collide_mask(CollideMask new_mask, CollideMask bits_to_change,
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodePathCollection::set_color
+//     Function: NodePathCollection::set_texture
 //       Access: Published
 //       Access: Published
-//  Description: Colors all NodePaths in the collection
+//  Description: Adds the indicated texture to the list of textures
+//               that will be rendered on the default texture stage.
+//
+//               This is the deprecated single-texture variant of this
+//               method; it is now superceded by set_texture() that
+//               accepts a stage and texture.  However, this method
+//               may be used in the presence of multitexture if you
+//               just want to adjust the default stage.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-set_color(float r, float g, float b, float a, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).set_color(Colorf(r, g, b, a), priority);
-  }
+set_texture(Texture *tex, int priority) {
+  PT(TextureStage) stage = TextureStage::get_default();
+  set_texture(stage, tex, priority);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodePathCollection::set_color
+//     Function: NodePathCollection::set_texture
 //       Access: Published
 //       Access: Published
-//  Description: Colors all NodePaths in the collection
+//  Description: Adds the indicated texture to the list of textures
+//               that will be rendered on the indicated multitexture
+//               stage.  If there are multiple texture stages
+//               specified (possibly on multiple different nodes at
+//               different levels), they will all be applied to
+//               geometry together, according to the stage
+//               specification set up in the TextureStage object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-set_color(const Colorf &color, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).set_color(color, priority);
-    //get_path(i).node()->set_attrib(ColorAttrib::make_flat(color), priority);
+set_texture(TextureStage *stage, Texture *tex, int priority) {
+  StateMap state_map;
+
+  NodePaths::iterator npi;
+  for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
+    NodePath &np = (*npi);
+    CPT(RenderState) orig_state = np.get_state();
+    StateMap::iterator smi = state_map.find(orig_state);
+    if (smi != state_map.end()) {
+      // This RenderState has already been encountered; reuse it.
+      np.set_state((*smi).second);
+    } else {
+      // This RenderState has not yet been encountered; apply the
+      // attrib to it.
+      np.set_texture(stage, tex, priority);
+      state_map[orig_state] = np.get_state();
+    }
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodePathCollection::set_color_scale
+//     Function: NodePathCollection::set_texture_off
 //       Access: Published
 //       Access: Published
-//  Description: Applies color scales to all NodePaths in the collection
+//  Description: Sets the geometry at this level and below to render
+//               using no texture, on any stage.  This is different
+//               from not specifying a texture; rather, this
+//               specifically contradicts set_texture() at a higher
+//               node level (or, with a priority, overrides a
+//               set_texture() at a lower level).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-set_color_scale(float r, float g, float b, float a, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).set_color_scale(Colorf(r, g, b, a), priority);
+set_texture_off(int priority) {
+  nassertv_always(!is_empty());
+  set_attrib(TextureAttrib::make_all_off(), priority);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::set_texture_off
+//       Access: Published
+//  Description: Sets the geometry at this level and below to render
+//               using no texture, on the indicated stage.  This is
+//               different from not specifying a texture; rather, this
+//               specifically contradicts set_texture() at a higher
+//               node level (or, with a priority, overrides a
+//               set_texture() at a lower level).
+////////////////////////////////////////////////////////////////////
+void NodePathCollection::
+set_texture_off(TextureStage *stage, int priority) {
+  StateMap state_map;
+
+  NodePaths::iterator npi;
+  for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
+    NodePath &np = (*npi);
+    CPT(RenderState) orig_state = np.get_state();
+    StateMap::iterator smi = state_map.find(orig_state);
+    if (smi != state_map.end()) {
+      // This RenderState has already been encountered; reuse it.
+      np.set_state((*smi).second);
+    } else {
+      // This RenderState has not yet been encountered; apply the
+      // attrib to it.
+      np.set_texture_off(stage, priority);
+      state_map[orig_state] = np.get_state();
+    }
   }
   }
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodePathCollection::set_color
+//       Access: Published
+//  Description: Colors all NodePaths in the collection
+////////////////////////////////////////////////////////////////////
+void NodePathCollection::
+set_color(const Colorf &color, int priority) {
+  set_attrib(ColorAttrib::make_flat(color), priority);
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePathCollection::set_color_scale
 //     Function: NodePathCollection::set_color_scale
 //       Access: Published
 //       Access: Published
-//  Description: Applies color scales to all NodePaths in the collection
+//  Description: Applies color scales to all NodePaths in the
+//               collection.  The existing color scale is replaced.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-set_color_scale(const Colorf &color, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).set_color_scale(color, priority);
+set_color_scale(const LVecBase4f &scale, int priority) {
+  StateMap state_map;
+
+  NodePaths::iterator npi;
+  for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
+    NodePath &np = (*npi);
+    CPT(RenderState) orig_state = np.get_state();
+    StateMap::iterator smi = state_map.find(orig_state);
+    if (smi != state_map.end()) {
+      // This RenderState has already been encountered; reuse it.
+      np.set_state((*smi).second);
+    } else {
+      // This RenderState has not yet been encountered; apply the
+      // attrib to it.
+      np.set_color_scale(scale, priority);
+      state_map[orig_state] = np.get_state();
+    }
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: NodePathCollection::compose_color_scale
 //     Function: NodePathCollection::compose_color_scale
 //       Access: Published
 //       Access: Published
-//  Description: Applies color scales to all NodePaths in the collection
+//  Description: Applies color scales to all NodePaths in the
+//               collection.  The existing color scale, if any, is
+//               multiplied by the specified color scale.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-compose_color_scale(float r, float g, float b, float a, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).compose_color_scale(Colorf(r, g, b, a), priority);
+compose_color_scale(const LVecBase4f &scale, int priority) {
+  StateMap state_map;
+
+  NodePaths::iterator npi;
+  for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
+    NodePath &np = (*npi);
+    CPT(RenderState) orig_state = np.get_state();
+    StateMap::iterator smi = state_map.find(orig_state);
+    if (smi != state_map.end()) {
+      // This RenderState has already been encountered; reuse it.
+      np.set_state((*smi).second);
+    } else {
+      // This RenderState has not yet been encountered; apply the
+      // attrib to it.
+      np.compose_color_scale(scale, priority);
+      state_map[orig_state] = np.get_state();
+    }
   }
   }
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
-//     Function: NodePathCollection::compose_color_scale
+//     Function: NodePathCollection::set_attrib
 //       Access: Published
 //       Access: Published
-//  Description: Applies color scales to all NodePaths in the collection
+//  Description: Applies the indicated RenderAttrib to all NodePaths
+//               in the collection.  An effort is made to apply the
+//               attrib to many NodePaths as quickly as possible;
+//               redundant RenderState compositions are not
+//               duplicated.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void NodePathCollection::
 void NodePathCollection::
-compose_color_scale(const Colorf &color, int priority) {
-  for (int i = 0; i < get_num_paths(); i++) {
-    get_path(i).compose_color_scale(color, priority);
+set_attrib(const RenderAttrib *attrib, int priority) {
+  StateMap state_map;
+
+  NodePaths::iterator npi;
+  for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
+    NodePath &np = (*npi);
+    CPT(RenderState) orig_state = np.get_state();
+    StateMap::iterator smi = state_map.find(orig_state);
+    if (smi != state_map.end()) {
+      // This RenderState has already been encountered; reuse it.
+      np.set_state((*smi).second);
+    } else {
+      // This RenderState has not yet been encountered; apply the
+      // attrib to it.
+      np.set_attrib(attrib, priority);
+      state_map[orig_state] = np.get_state();
+    }
   }
   }
 }
 }
 
 

+ 18 - 8
panda/src/pgraph/nodePathCollection.h

@@ -68,17 +68,24 @@ PUBLISHED:
   void set_collide_mask(CollideMask new_mask, CollideMask bits_to_change = CollideMask::all_on(),
   void set_collide_mask(CollideMask new_mask, CollideMask bits_to_change = CollideMask::all_on(),
                         TypeHandle node_type = TypeHandle::none());
                         TypeHandle node_type = TypeHandle::none());
 
 
-  void set_color(float r, float g, float b, float a = 1.0,
-                 int priority = 0);
+  void set_texture(Texture *tex, int priority = 0);
+  void set_texture(TextureStage *stage, Texture *tex, int priority = 0);
+  void set_texture_off(int priority = 0);
+  void set_texture_off(TextureStage *stage, int priority = 0);
+
+  INLINE void set_color(float r, float g, float b, float a = 1.0,
+                        int priority = 0);
   void set_color(const Colorf &color, int priority = 0);
   void set_color(const Colorf &color, int priority = 0);
 
 
-  void set_color_scale(float r, float g, float b, float a = 1.0,
-                       int priority = 0);
-  void set_color_scale(const Colorf &color, int priority = 0);
+  INLINE void set_color_scale(float r, float g, float b, float a = 1.0,
+                              int priority = 0);
+  void set_color_scale(const LVecBase4f &scale, int priority = 0);
 
 
-  void compose_color_scale(float r, float g, float b, float a = 1.0,
-                        int priority = 0);
-  void compose_color_scale(const Colorf &color, int priority = 0);
+  INLINE void compose_color_scale(float r, float g, float b, float a = 1.0,
+                                  int priority = 0);
+  void compose_color_scale(const LVecBase4f &scale, int priority = 0);
+
+  void set_attrib(const RenderAttrib *attrib, int priority = 0);
 
 
   void output(ostream &out) const;
   void output(ostream &out) const;
   void write(ostream &out, int indent_level = 0) const;
   void write(ostream &out, int indent_level = 0) const;
@@ -86,6 +93,9 @@ PUBLISHED:
 private:
 private:
   typedef PTA(NodePath) NodePaths;
   typedef PTA(NodePath) NodePaths;
   NodePaths _node_paths;
   NodePaths _node_paths;
+
+  // This typedef is used in set_attrib() and similar methods.
+  typedef pmap<CPT(RenderState), CPT(RenderState) > StateMap;
 };
 };
 
 
 INLINE ostream &operator << (ostream &out, const NodePathCollection &col) {
 INLINE ostream &operator << (ostream &out, const NodePathCollection &col) {