Panda3D

nodePathCollection.cxx

00001 // Filename: nodePathCollection.cxx
00002 // Created by:  drose (06Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "nodePathCollection.h"
00016 #include "findApproxPath.h"
00017 #include "findApproxLevelEntry.h"
00018 #include "textureAttrib.h"
00019 #include "colorScaleAttrib.h"
00020 #include "colorAttrib.h"
00021 #include "indent.h"
00022 
00023 #ifdef HAVE_PYTHON
00024 #include "py_panda.h"
00025 #endif
00026 
00027 ////////////////////////////////////////////////////////////////////
00028 //     Function: NodePathCollection::Constructor
00029 //       Access: Published
00030 //  Description:
00031 ////////////////////////////////////////////////////////////////////
00032 NodePathCollection::
00033 NodePathCollection() {
00034 }
00035 
00036 ////////////////////////////////////////////////////////////////////
00037 //     Function: NodePathCollection::Copy Constructor
00038 //       Access: Published
00039 //  Description:
00040 ////////////////////////////////////////////////////////////////////
00041 NodePathCollection::
00042 NodePathCollection(const NodePathCollection &copy) :
00043   _node_paths(copy._node_paths)
00044 {
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: NodePathCollection::Copy Assignment Operator
00049 //       Access: Published
00050 //  Description:
00051 ////////////////////////////////////////////////////////////////////
00052 void NodePathCollection::
00053 operator = (const NodePathCollection &copy) {
00054   _node_paths = copy._node_paths;
00055 }
00056 
00057 #ifdef HAVE_PYTHON
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: NodePathCollection::Constructor
00060 //       Access: Published
00061 //  Description: This special constructor accepts a Python list of
00062 //               NodePaths.  Since this constructor accepts a generic
00063 //               PyObject *, it should be the last constructor listed
00064 //               in the class record.
00065 ////////////////////////////////////////////////////////////////////
00066 NodePathCollection::
00067 NodePathCollection(PyObject *self, PyObject *sequence) {
00068   // We have to pre-initialize self's "this" pointer when we receive
00069   // self in the constructor--the caller can't initialize this for us.
00070   ((Dtool_PyInstDef *)self)->_ptr_to_object = this;
00071 
00072   if (!PySequence_Check(sequence)) {
00073     // If passed with a non-sequence, this isn't the right constructor.
00074     PyErr_SetString(PyExc_TypeError, "NodePathCollection constructor requires a sequence");
00075     return;
00076   }
00077 
00078   int size = PySequence_Size(sequence);
00079   for (int i = 0; i < size; ++i) {
00080     PyObject *item = PySequence_GetItem(sequence, i);
00081     if (item == NULL) {
00082       return;
00083     }
00084     PyObject *result = PyObject_CallMethod(self, (char *)"addPath", (char *)"O", item);
00085     Py_DECREF(item);
00086     if (result == NULL) {
00087       // Unable to add item--probably it wasn't of the appropriate type.
00088       ostringstream stream;
00089       stream << "Element " << i << " in sequence passed to NodePathCollection constructor could not be added";
00090       string str = stream.str();
00091       PyErr_SetString(PyExc_TypeError, str.c_str());
00092       return;
00093     }
00094     Py_DECREF(result);
00095   }
00096 }
00097 #endif  // HAVE_PYTHON
00098 
00099 #ifdef HAVE_PYTHON
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: NodePathCollection::__reduce__
00102 //       Access: Published
00103 //  Description: This special Python method is implement to provide
00104 //               support for the pickle module.
00105 ////////////////////////////////////////////////////////////////////
00106 PyObject *NodePathCollection::
00107 __reduce__(PyObject *self) const {
00108   // Here we will return a 4-tuple: (Class, (args), None, iterator),
00109   // where iterator is an iterator that will yield successive
00110   // NodePaths.
00111 
00112   // We should return at least a 2-tuple, (Class, (args)): the
00113   // necessary class object whose constructor we should call
00114   // (e.g. this), and the arguments necessary to reconstruct this
00115   // object.
00116 
00117   PyObject *this_class = PyObject_Type(self);
00118   if (this_class == NULL) {
00119     return NULL;
00120   }
00121 
00122   // Since a NodePathCollection is itself an iterator, we can simply
00123   // pass it as the fourth tuple component.
00124   PyObject *result = Py_BuildValue("(O()OO)", this_class, Py_None, self);
00125   Py_DECREF(this_class);
00126   return result;
00127 }
00128 #endif  // HAVE_PYTHON
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: NodePathCollection::add_path
00132 //       Access: Published
00133 //  Description: Adds a new NodePath to the collection.
00134 ////////////////////////////////////////////////////////////////////
00135 void NodePathCollection::
00136 add_path(const NodePath &node_path) {
00137   // If the pointer to our internal array is shared by any other
00138   // NodePathCollections, we have to copy the array now so we won't
00139   // inadvertently modify any of our brethren NodePathCollection
00140   // objects.
00141 
00142   if (_node_paths.get_ref_count() > 1) {
00143     NodePaths old_node_paths = _node_paths;
00144     _node_paths = NodePaths::empty_array(0);
00145     _node_paths.v() = old_node_paths.v();
00146   }
00147 
00148   _node_paths.push_back(node_path);
00149 }
00150 
00151 ////////////////////////////////////////////////////////////////////
00152 //     Function: NodePathCollection::remove_path
00153 //       Access: Published
00154 //  Description: Removes the indicated NodePath from the collection.
00155 //               Returns true if the path was removed, false if it was
00156 //               not a member of the collection.
00157 ////////////////////////////////////////////////////////////////////
00158 bool NodePathCollection::
00159 remove_path(const NodePath &node_path) {
00160   int path_index = -1;
00161   for (int i = 0; path_index == -1 && i < (int)_node_paths.size(); i++) {
00162     if (_node_paths[i] == node_path) {
00163       path_index = i;
00164     }
00165   }
00166 
00167   if (path_index == -1) {
00168     // The indicated path was not a member of the collection.
00169     return false;
00170   }
00171 
00172   // If the pointer to our internal array is shared by any other
00173   // NodePathCollections, we have to copy the array now so we won't
00174   // inadvertently modify any of our brethren NodePathCollection
00175   // objects.
00176 
00177   if (_node_paths.get_ref_count() > 1) {
00178     NodePaths old_node_paths = _node_paths;
00179     _node_paths = NodePaths::empty_array(0);
00180     _node_paths.v() = old_node_paths.v();
00181   }
00182 
00183   _node_paths.erase(_node_paths.begin() + path_index);
00184   return true;
00185 }
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: NodePathCollection::add_paths_from
00189 //       Access: Published
00190 //  Description: Adds all the NodePaths indicated in the other
00191 //               collection to this path.  The other paths are simply
00192 //               appended to the end of the paths in this list;
00193 //               duplicates are not automatically removed.
00194 ////////////////////////////////////////////////////////////////////
00195 void NodePathCollection::
00196 add_paths_from(const NodePathCollection &other) {
00197   int other_num_paths = other.get_num_paths();
00198   for (int i = 0; i < other_num_paths; i++) {
00199     add_path(other.get_path(i));
00200   }
00201 }
00202 
00203 
00204 ////////////////////////////////////////////////////////////////////
00205 //     Function: NodePathCollection::remove_paths_from
00206 //       Access: Published
00207 //  Description: Removes from this collection all of the NodePaths
00208 //               listed in the other collection.
00209 ////////////////////////////////////////////////////////////////////
00210 void NodePathCollection::
00211 remove_paths_from(const NodePathCollection &other) {
00212   NodePaths new_paths;
00213   int num_paths = get_num_paths();
00214   for (int i = 0; i < num_paths; i++) {
00215     NodePath path = get_path(i);
00216     if (!other.has_path(path)) {
00217       new_paths.push_back(path);
00218     }
00219   }
00220   _node_paths = new_paths;
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: NodePathCollection::remove_duplicate_paths
00225 //       Access: Published
00226 //  Description: Removes any duplicate entries of the same NodePaths
00227 //               on this collection.  If a NodePath appears multiple
00228 //               times, the first appearance is retained; subsequent
00229 //               appearances are removed.
00230 ////////////////////////////////////////////////////////////////////
00231 void NodePathCollection::
00232 remove_duplicate_paths() {
00233   NodePaths new_paths;
00234 
00235   int num_paths = get_num_paths();
00236   for (int i = 0; i < num_paths; i++) {
00237     NodePath path = get_path(i);
00238     bool duplicated = false;
00239 
00240     for (int j = 0; j < i && !duplicated; j++) {
00241       duplicated = (path == get_path(j));
00242     }
00243 
00244     if (!duplicated) {
00245       new_paths.push_back(path);
00246     }
00247   }
00248 
00249   _node_paths = new_paths;
00250 }
00251 
00252 ////////////////////////////////////////////////////////////////////
00253 //     Function: NodePathCollection::has_path
00254 //       Access: Published
00255 //  Description: Returns true if the indicated NodePath appears in
00256 //               this collection, false otherwise.
00257 ////////////////////////////////////////////////////////////////////
00258 bool NodePathCollection::
00259 has_path(const NodePath &path) const {
00260   for (int i = 0; i < get_num_paths(); i++) {
00261     if (path == get_path(i)) {
00262       return true;
00263     }
00264   }
00265   return false;
00266 }
00267 
00268 ////////////////////////////////////////////////////////////////////
00269 //     Function: NodePathCollection::clear
00270 //       Access: Published
00271 //  Description: Removes all NodePaths from the collection.
00272 ////////////////////////////////////////////////////////////////////
00273 void NodePathCollection::
00274 clear() {
00275   _node_paths.clear();
00276 }
00277 
00278 ////////////////////////////////////////////////////////////////////
00279 //     Function: NodePathCollection::is_empty
00280 //       Access: Published
00281 //  Description: Returns true if there are no NodePaths in the
00282 //               collection, false otherwise.
00283 ////////////////////////////////////////////////////////////////////
00284 bool NodePathCollection::
00285 is_empty() const {
00286   return _node_paths.empty();
00287 }
00288 
00289 ////////////////////////////////////////////////////////////////////
00290 //     Function: NodePathCollection::get_num_paths
00291 //       Access: Published
00292 //  Description: Returns the number of NodePaths in the collection.
00293 ////////////////////////////////////////////////////////////////////
00294 int NodePathCollection::
00295 get_num_paths() const {
00296   return _node_paths.size();
00297 }
00298 
00299 ////////////////////////////////////////////////////////////////////
00300 //     Function: NodePathCollection::get_path
00301 //       Access: Published
00302 //  Description: Returns the nth NodePath in the collection.
00303 ////////////////////////////////////////////////////////////////////
00304 NodePath NodePathCollection::
00305 get_path(int index) const {
00306   nassertr(index >= 0 && index < (int)_node_paths.size(), NodePath());
00307 
00308   return _node_paths[index];
00309 }
00310 
00311 ////////////////////////////////////////////////////////////////////
00312 //     Function: NodePathCollection::operator []
00313 //       Access: Published
00314 //  Description: Returns the nth NodePath in the collection.  This is
00315 //               the same as get_path(), but it may be a more
00316 //               convenient way to access it.
00317 ////////////////////////////////////////////////////////////////////
00318 NodePath NodePathCollection::
00319 operator [] (int index) const {
00320   nassertr(index >= 0 && index < (int)_node_paths.size(), NodePath());
00321 
00322   return _node_paths[index];
00323 }
00324 
00325 ////////////////////////////////////////////////////////////////////
00326 //     Function: NodePathCollection::size
00327 //       Access: Published
00328 //  Description: Returns the number of paths in the collection.  This
00329 //               is the same thing as get_num_paths().
00330 ////////////////////////////////////////////////////////////////////
00331 int NodePathCollection::
00332 size() const {
00333   return _node_paths.size();
00334 }
00335 
00336 ////////////////////////////////////////////////////////////////////
00337 //     Function: NodePathCollection::ls
00338 //       Access: Published
00339 //  Description: Lists all the nodes at and below each node in the
00340 //               collection hierarchically.
00341 ////////////////////////////////////////////////////////////////////
00342 void NodePathCollection::
00343 ls(ostream &out, int indent_level) const {
00344   for (int i = 0; i < get_num_paths(); i++) {
00345     NodePath path = get_path(i);
00346     indent(out, indent_level) << path << "\n";
00347     path.ls(out, indent_level + 2);
00348     out << "\n";
00349   }
00350 }
00351 
00352 ////////////////////////////////////////////////////////////////////
00353 //     Function: NodePathCollection::find_all_matches
00354 //       Access: Published
00355 //  Description: Returns the complete set of all NodePaths that begin
00356 //               with any NodePath in this collection and can be
00357 //               extended by path.  The shortest paths will be listed
00358 //               first.
00359 ////////////////////////////////////////////////////////////////////
00360 NodePathCollection NodePathCollection::
00361 find_all_matches(const string &path) const {
00362   NodePathCollection result;
00363 
00364   FindApproxPath approx_path;
00365   if (approx_path.add_string(path)) {
00366     if (!is_empty()) {
00367       FindApproxLevelEntry *level = NULL;
00368       for (int i = 0; i < get_num_paths(); i++) {
00369         FindApproxLevelEntry *start = 
00370           new FindApproxLevelEntry(get_path(i), approx_path);
00371         start->_next = level;
00372         level = start;
00373       }
00374       get_path(0).find_matches(result, level, -1);
00375     }
00376   }
00377 
00378   return result;
00379 }
00380 
00381 ////////////////////////////////////////////////////////////////////
00382 //     Function: NodePathCollection::reparent_to
00383 //       Access: Published
00384 //  Description: Reparents all the NodePaths in the collection to the
00385 //               indicated node.
00386 ////////////////////////////////////////////////////////////////////
00387 void NodePathCollection::
00388 reparent_to(const NodePath &other) {
00389   for (int i = 0; i < get_num_paths(); i++) {
00390     get_path(i).reparent_to(other);
00391   }
00392 }
00393 
00394 ////////////////////////////////////////////////////////////////////
00395 //     Function: NodePathCollection::wrt_reparent_to
00396 //       Access: Published
00397 //  Description: Reparents all the NodePaths in the collection to the
00398 //               indicated node, adjusting each transform so as not to
00399 //               move in world coordinates.
00400 ////////////////////////////////////////////////////////////////////
00401 void NodePathCollection::
00402 wrt_reparent_to(const NodePath &other) {
00403   for (int i = 0; i < get_num_paths(); i++) {
00404     get_path(i).wrt_reparent_to(other);
00405   }
00406 }
00407 
00408 ////////////////////////////////////////////////////////////////////
00409 //     Function: NodePathCollection::show
00410 //       Access: Published
00411 //  Description: Shows all NodePaths in the collection.
00412 ////////////////////////////////////////////////////////////////////
00413 void NodePathCollection::
00414 show() {
00415   for (int i = 0; i < get_num_paths(); i++) {
00416     get_path(i).show();
00417   }
00418 }
00419 
00420 ////////////////////////////////////////////////////////////////////
00421 //     Function: NodePathCollection::show
00422 //       Access: Published
00423 //  Description: Hides all NodePaths in the collection.
00424 ////////////////////////////////////////////////////////////////////
00425 void NodePathCollection::
00426 hide() {
00427   for (int i = 0; i < get_num_paths(); i++) {
00428     get_path(i).hide();
00429   }
00430 }
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: NodePathCollection::stash
00434 //       Access: Published
00435 //  Description: Stashes all NodePaths in the collection.
00436 ////////////////////////////////////////////////////////////////////
00437 void NodePathCollection::
00438 stash() {
00439   for (int i = 0; i < get_num_paths(); i++) {
00440     get_path(i).stash();
00441   }
00442 }
00443 
00444 ////////////////////////////////////////////////////////////////////
00445 //     Function: NodePathCollection::unstash
00446 //       Access: Published
00447 //  Description: Unstashes all NodePaths in the collection.
00448 ////////////////////////////////////////////////////////////////////
00449 void NodePathCollection::
00450 unstash() {
00451   for (int i = 0; i < get_num_paths(); i++) {
00452     get_path(i).unstash();
00453   }
00454 }
00455 
00456 ////////////////////////////////////////////////////////////////////
00457 //     Function: NodePathCollection::detach
00458 //       Access: Published
00459 //  Description: Detaches all NodePaths in the collection.
00460 ////////////////////////////////////////////////////////////////////
00461 void NodePathCollection::
00462 detach() {
00463   for (int i = 0; i < get_num_paths(); i++) {
00464     get_path(i).detach_node();
00465   }
00466 }
00467 
00468 ////////////////////////////////////////////////////////////////////
00469 //     Function: NodePathCollection::get_collide_mask
00470 //       Access: Published
00471 //  Description: Returns the union of all of the into_collide_masks
00472 //               for nodes at this level and below.  This is the same
00473 //               thing as node()->get_net_collide_mask().
00474 //
00475 //               If you want to return what the into_collide_mask of
00476 //               this node itself is, without regard to its children,
00477 //               use node()->get_into_collide_mask().
00478 ////////////////////////////////////////////////////////////////////
00479 CollideMask NodePathCollection::
00480 get_collide_mask() const {
00481   CollideMask collide_mask;
00482   for (int i = 0; i < get_num_paths(); i++) {
00483     collide_mask |= get_path(i).get_collide_mask();
00484   }
00485   return collide_mask;
00486 }
00487 
00488 ////////////////////////////////////////////////////////////////////
00489 //     Function: NodePathCollection::set_collide_mask
00490 //       Access: Published
00491 //  Description: Recursively applies the indicated CollideMask to the
00492 //               into_collide_masks for all nodes at this level and
00493 //               below.  Only nodes 
00494 //
00495 //               The default is to change all bits, but if
00496 //               bits_to_change is not all bits on, then only the bits
00497 //               that are set in bits_to_change are modified, allowing
00498 //               this call to change only a subset of the bits in the
00499 //               subgraph.
00500 ////////////////////////////////////////////////////////////////////
00501 void NodePathCollection::
00502 set_collide_mask(CollideMask new_mask, CollideMask bits_to_change,
00503                  TypeHandle node_type) {
00504   for (int i = 0; i < get_num_paths(); i++) {
00505     get_path(i).set_collide_mask(new_mask, bits_to_change, node_type);
00506   }
00507 }
00508 
00509 ////////////////////////////////////////////////////////////////////
00510 //     Function: NodePathCollection::set_texture
00511 //       Access: Published
00512 //  Description: Adds the indicated texture to the list of textures
00513 //               that will be rendered on the default texture stage.
00514 //
00515 //               This is the deprecated single-texture variant of this
00516 //               method; it is now superceded by set_texture() that
00517 //               accepts a stage and texture.  However, this method
00518 //               may be used in the presence of multitexture if you
00519 //               just want to adjust the default stage.
00520 ////////////////////////////////////////////////////////////////////
00521 void NodePathCollection::
00522 set_texture(Texture *tex, int priority) {
00523   PT(TextureStage) stage = TextureStage::get_default();
00524   set_texture(stage, tex, priority);
00525 }
00526 
00527 ////////////////////////////////////////////////////////////////////
00528 //     Function: NodePathCollection::set_texture
00529 //       Access: Published
00530 //  Description: Adds the indicated texture to the list of textures
00531 //               that will be rendered on the indicated multitexture
00532 //               stage.  If there are multiple texture stages
00533 //               specified (possibly on multiple different nodes at
00534 //               different levels), they will all be applied to
00535 //               geometry together, according to the stage
00536 //               specification set up in the TextureStage object.
00537 ////////////////////////////////////////////////////////////////////
00538 void NodePathCollection::
00539 set_texture(TextureStage *stage, Texture *tex, int priority) {
00540   StateMap state_map;
00541 
00542   NodePaths::iterator npi;
00543   for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
00544     NodePath &np = (*npi);
00545     CPT(RenderState) orig_state = np.get_state();
00546     StateMap::iterator smi = state_map.find(orig_state);
00547     if (smi != state_map.end()) {
00548       // This RenderState has already been encountered; reuse it.
00549       np.set_state((*smi).second);
00550     } else {
00551       // This RenderState has not yet been encountered; apply the
00552       // attrib to it.
00553       np.set_texture(stage, tex, priority);
00554       state_map[orig_state] = np.get_state();
00555     }
00556   }
00557 }
00558 
00559 ////////////////////////////////////////////////////////////////////
00560 //     Function: NodePathCollection::set_texture_off
00561 //       Access: Published
00562 //  Description: Sets the geometry at this level and below to render
00563 //               using no texture, on any stage.  This is different
00564 //               from not specifying a texture; rather, this
00565 //               specifically contradicts set_texture() at a higher
00566 //               node level (or, with a priority, overrides a
00567 //               set_texture() at a lower level).
00568 ////////////////////////////////////////////////////////////////////
00569 void NodePathCollection::
00570 set_texture_off(int priority) {
00571   nassertv_always(!is_empty());
00572   set_attrib(TextureAttrib::make_all_off(), priority);
00573 }
00574 
00575 ////////////////////////////////////////////////////////////////////
00576 //     Function: NodePathCollection::set_texture_off
00577 //       Access: Published
00578 //  Description: Sets the geometry at this level and below to render
00579 //               using no texture, on the indicated stage.  This is
00580 //               different from not specifying a texture; rather, this
00581 //               specifically contradicts set_texture() at a higher
00582 //               node level (or, with a priority, overrides a
00583 //               set_texture() at a lower level).
00584 ////////////////////////////////////////////////////////////////////
00585 void NodePathCollection::
00586 set_texture_off(TextureStage *stage, int priority) {
00587   StateMap state_map;
00588 
00589   NodePaths::iterator npi;
00590   for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
00591     NodePath &np = (*npi);
00592     CPT(RenderState) orig_state = np.get_state();
00593     StateMap::iterator smi = state_map.find(orig_state);
00594     if (smi != state_map.end()) {
00595       // This RenderState has already been encountered; reuse it.
00596       np.set_state((*smi).second);
00597     } else {
00598       // This RenderState has not yet been encountered; apply the
00599       // attrib to it.
00600       np.set_texture_off(stage, priority);
00601       state_map[orig_state] = np.get_state();
00602     }
00603   }
00604 }
00605 
00606 ////////////////////////////////////////////////////////////////////
00607 //     Function: NodePathCollection::set_color
00608 //       Access: Published
00609 //  Description: Colors all NodePaths in the collection
00610 ////////////////////////////////////////////////////////////////////
00611 void NodePathCollection::
00612 set_color(const LColor &color, int priority) {
00613   set_attrib(ColorAttrib::make_flat(color), priority);
00614 }
00615 
00616 ////////////////////////////////////////////////////////////////////
00617 //     Function: NodePathCollection::set_color_scale
00618 //       Access: Published
00619 //  Description: Applies color scales to all NodePaths in the
00620 //               collection.  The existing color scale is replaced.
00621 ////////////////////////////////////////////////////////////////////
00622 void NodePathCollection::
00623 set_color_scale(const LVecBase4 &scale, int priority) {
00624   StateMap state_map;
00625 
00626   NodePaths::iterator npi;
00627   for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
00628     NodePath &np = (*npi);
00629     CPT(RenderState) orig_state = np.get_state();
00630     StateMap::iterator smi = state_map.find(orig_state);
00631     if (smi != state_map.end()) {
00632       // This RenderState has already been encountered; reuse it.
00633       np.set_state((*smi).second);
00634     } else {
00635       // This RenderState has not yet been encountered; apply the
00636       // attrib to it.
00637       np.set_color_scale(scale, priority);
00638       state_map[orig_state] = np.get_state();
00639     }
00640   }
00641 }
00642 
00643 ////////////////////////////////////////////////////////////////////
00644 //     Function: NodePathCollection::compose_color_scale
00645 //       Access: Published
00646 //  Description: Applies color scales to all NodePaths in the
00647 //               collection.  The existing color scale, if any, is
00648 //               multiplied by the specified color scale.
00649 ////////////////////////////////////////////////////////////////////
00650 void NodePathCollection::
00651 compose_color_scale(const LVecBase4 &scale, int priority) {
00652   StateMap state_map;
00653 
00654   NodePaths::iterator npi;
00655   for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
00656     NodePath &np = (*npi);
00657     CPT(RenderState) orig_state = np.get_state();
00658     StateMap::iterator smi = state_map.find(orig_state);
00659     if (smi != state_map.end()) {
00660       // This RenderState has already been encountered; reuse it.
00661       np.set_state((*smi).second);
00662     } else {
00663       // This RenderState has not yet been encountered; apply the
00664       // attrib to it.
00665       np.compose_color_scale(scale, priority);
00666       state_map[orig_state] = np.get_state();
00667     }
00668   }
00669 }
00670 
00671 ////////////////////////////////////////////////////////////////////
00672 //     Function: NodePathCollection::set_attrib
00673 //       Access: Published
00674 //  Description: Applies the indicated RenderAttrib to all NodePaths
00675 //               in the collection.  An effort is made to apply the
00676 //               attrib to many NodePaths as quickly as possible;
00677 //               redundant RenderState compositions are not
00678 //               duplicated.
00679 ////////////////////////////////////////////////////////////////////
00680 void NodePathCollection::
00681 set_attrib(const RenderAttrib *attrib, int priority) {
00682   StateMap state_map;
00683 
00684   NodePaths::iterator npi;
00685   for (npi = _node_paths.begin(); npi != _node_paths.end(); ++npi) {
00686     NodePath &np = (*npi);
00687     CPT(RenderState) orig_state = np.get_state();
00688     StateMap::iterator smi = state_map.find(orig_state);
00689     if (smi != state_map.end()) {
00690       // This RenderState has already been encountered; reuse it.
00691       np.set_state((*smi).second);
00692     } else {
00693       // This RenderState has not yet been encountered; apply the
00694       // attrib to it.
00695       np.set_attrib(attrib, priority);
00696       state_map[orig_state] = np.get_state();
00697     }
00698   }
00699 }
00700 
00701 ////////////////////////////////////////////////////////////////////
00702 //     Function: NodePathCollection::output
00703 //       Access: Published
00704 //  Description: Writes a brief one-line description of the
00705 //               NodePathCollection to the indicated output stream.
00706 ////////////////////////////////////////////////////////////////////
00707 void NodePathCollection::
00708 output(ostream &out) const {
00709   if (get_num_paths() == 1) {
00710     out << "1 NodePath";
00711   } else {
00712     out << get_num_paths() << " NodePaths";
00713   }
00714 }
00715 
00716 ////////////////////////////////////////////////////////////////////
00717 //     Function: NodePathCollection::write
00718 //       Access: Published
00719 //  Description: Writes a complete multi-line description of the
00720 //               NodePathCollection to the indicated output stream.
00721 ////////////////////////////////////////////////////////////////////
00722 void NodePathCollection::
00723 write(ostream &out, int indent_level) const {
00724   for (int i = 0; i < get_num_paths(); i++) {
00725     indent(out, indent_level) << get_path(i) << "\n";
00726   }
00727 }
 All Classes Functions Variables Enumerations