Panda3D
|
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 ©) : 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 ©) { 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 }