Panda3D
|
00001 // Filename: renderEffects.cxx 00002 // Created by: drose (14Mar02) 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 "renderEffects.h" 00016 #include "billboardEffect.h" 00017 #include "decalEffect.h" 00018 #include "compassEffect.h" 00019 #include "polylightEffect.h" 00020 #include "showBoundsEffect.h" 00021 #include "config_pgraph.h" 00022 #include "bamReader.h" 00023 #include "bamWriter.h" 00024 #include "datagramIterator.h" 00025 #include "indent.h" 00026 #include "compareTo.h" 00027 #include "lightReMutexHolder.h" 00028 #include "lightMutexHolder.h" 00029 #include "thread.h" 00030 00031 LightReMutex *RenderEffects::_states_lock = NULL; 00032 RenderEffects::States *RenderEffects::_states = NULL; 00033 CPT(RenderEffects) RenderEffects::_empty_state; 00034 TypeHandle RenderEffects::_type_handle; 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: RenderEffects::Constructor 00038 // Access: Protected 00039 // Description: Actually, this could be a private constructor, since 00040 // no one inherits from RenderEffects, but gcc gives us a 00041 // spurious warning if all constructors are private. 00042 //////////////////////////////////////////////////////////////////// 00043 RenderEffects:: 00044 RenderEffects() : _lock("RenderEffects") { 00045 if (_states == (States *)NULL) { 00046 init_states(); 00047 } 00048 _saved_entry = _states->end(); 00049 _flags = 0; 00050 } 00051 00052 //////////////////////////////////////////////////////////////////// 00053 // Function: RenderEffects::Copy Constructor 00054 // Access: Private 00055 // Description: RenderEffects are not meant to be copied. 00056 //////////////////////////////////////////////////////////////////// 00057 RenderEffects:: 00058 RenderEffects(const RenderEffects &) { 00059 nassertv(false); 00060 } 00061 00062 //////////////////////////////////////////////////////////////////// 00063 // Function: RenderEffects::Copy Assignment Operator 00064 // Access: Private 00065 // Description: RenderEffects are not meant to be copied. 00066 //////////////////////////////////////////////////////////////////// 00067 void RenderEffects:: 00068 operator = (const RenderEffects &) { 00069 nassertv(false); 00070 } 00071 00072 //////////////////////////////////////////////////////////////////// 00073 // Function: RenderEffects::Destructor 00074 // Access: Public, Virtual 00075 // Description: The destructor is responsible for removing the 00076 // RenderEffects from the global set if it is there. 00077 //////////////////////////////////////////////////////////////////// 00078 RenderEffects:: 00079 ~RenderEffects() { 00080 // Remove the deleted RenderEffects object from the global pool. 00081 LightReMutexHolder holder(*_states_lock); 00082 00083 // unref() should have cleared this. 00084 nassertv(_saved_entry == _states->end()); 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: RenderEffects::safe_to_transform 00089 // Access: Public 00090 // Description: Returns true if all of the effects in this set can 00091 // safely be transformed, and therefore the complete set 00092 // can be transformed, by calling xform(). 00093 //////////////////////////////////////////////////////////////////// 00094 bool RenderEffects:: 00095 safe_to_transform() const { 00096 Effects::const_iterator ai; 00097 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00098 const Effect &effect = (*ai); 00099 if (!effect._effect->safe_to_transform()) { 00100 return false; 00101 } 00102 } 00103 00104 return true; 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: RenderEffects::prepare_flatten_transform 00109 // Access: Public, Virtual 00110 // Description: Preprocesses the accumulated transform that is about 00111 // to be applied to (or through) this node due to a 00112 // flatten operation. The returned value will be used 00113 // instead. 00114 //////////////////////////////////////////////////////////////////// 00115 CPT(TransformState) RenderEffects:: 00116 prepare_flatten_transform(const TransformState *net_transform) const { 00117 CPT(TransformState) result = net_transform; 00118 Effects::const_iterator ai; 00119 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00120 const Effect &effect = (*ai); 00121 result = effect._effect->prepare_flatten_transform(result); 00122 } 00123 00124 return result; 00125 } 00126 00127 //////////////////////////////////////////////////////////////////// 00128 // Function: RenderEffects::safe_to_combine 00129 // Access: Public 00130 // Description: Returns true if all of the effects in this set can 00131 // safely be shared with a sibling node that has the 00132 // exact same set of effects, or false if this would be 00133 // bad for any of the effects. 00134 //////////////////////////////////////////////////////////////////// 00135 bool RenderEffects:: 00136 safe_to_combine() const { 00137 Effects::const_iterator ai; 00138 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00139 const Effect &effect = (*ai); 00140 if (!effect._effect->safe_to_combine()) { 00141 return false; 00142 } 00143 } 00144 00145 return true; 00146 } 00147 00148 //////////////////////////////////////////////////////////////////// 00149 // Function: RenderEffects::xform 00150 // Access: Public, Virtual 00151 // Description: Returns a new RenderEffects transformed by the 00152 // indicated matrix. 00153 //////////////////////////////////////////////////////////////////// 00154 CPT(RenderEffects) RenderEffects:: 00155 xform(const LMatrix4f &mat) const { 00156 if (is_empty()) { 00157 return this; 00158 } 00159 00160 RenderEffects *new_state = new RenderEffects; 00161 back_insert_iterator<Effects> result = 00162 back_inserter(new_state->_effects); 00163 00164 Effects::const_iterator ai; 00165 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00166 const Effect &effect = (*ai); 00167 Effect new_effect(effect); 00168 new_effect._effect = effect._effect->xform(mat); 00169 *result = new_effect; 00170 ++result; 00171 } 00172 00173 return return_new(new_state); 00174 } 00175 00176 //////////////////////////////////////////////////////////////////// 00177 // Function: RenderEffects::operator < 00178 // Access: Published 00179 // Description: Provides an arbitrary ordering among all unique 00180 // RenderEffects, so we can store the essentially 00181 // different ones in a big set and throw away the rest. 00182 // 00183 // This method is not needed outside of the RenderEffects 00184 // class because all equivalent RenderEffects objects are 00185 // guaranteed to share the same pointer; thus, a pointer 00186 // comparison is always sufficient. 00187 //////////////////////////////////////////////////////////////////// 00188 bool RenderEffects:: 00189 operator < (const RenderEffects &other) const { 00190 // We must compare all the properties of the effects, not just 00191 // the type; thus, we compare them one at a time using compare_to(). 00192 return lexicographical_compare(_effects.begin(), _effects.end(), 00193 other._effects.begin(), other._effects.end(), 00194 CompareTo<Effect>()); 00195 } 00196 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: RenderEffects::find_effect 00200 // Access: Published 00201 // Description: Searches for an effect with the indicated type in 00202 // the state, and returns its index if it is found, or 00203 // -1 if it is not. 00204 //////////////////////////////////////////////////////////////////// 00205 int RenderEffects:: 00206 find_effect(TypeHandle type) const { 00207 Effects::const_iterator ai = _effects.find(Effect(type)); 00208 if (ai == _effects.end()) { 00209 return -1; 00210 } 00211 return ai - _effects.begin(); 00212 } 00213 00214 //////////////////////////////////////////////////////////////////// 00215 // Function: RenderEffects::make_empty 00216 // Access: Published, Static 00217 // Description: Returns a RenderEffects with no effects set. 00218 //////////////////////////////////////////////////////////////////// 00219 CPT(RenderEffects) RenderEffects:: 00220 make_empty() { 00221 // The empty state is asked for so often, we make it a special case 00222 // and store a pointer forever once we find it the first time. 00223 if (_empty_state == (RenderEffects *)NULL) { 00224 RenderEffects *state = new RenderEffects; 00225 _empty_state = return_new(state); 00226 } 00227 00228 return _empty_state; 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: RenderEffects::make 00233 // Access: Published, Static 00234 // Description: Returns a RenderEffects with one effect set. 00235 //////////////////////////////////////////////////////////////////// 00236 CPT(RenderEffects) RenderEffects:: 00237 make(const RenderEffect *effect) { 00238 RenderEffects *state = new RenderEffects; 00239 state->_effects.reserve(1); 00240 state->_effects.insert(Effect(effect)); 00241 return return_new(state); 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: RenderEffects::make 00246 // Access: Published, Static 00247 // Description: Returns a RenderEffects with two effects set. 00248 //////////////////////////////////////////////////////////////////// 00249 CPT(RenderEffects) RenderEffects:: 00250 make(const RenderEffect *effect1, 00251 const RenderEffect *effect2) { 00252 RenderEffects *state = new RenderEffects; 00253 state->_effects.reserve(2); 00254 state->_effects.push_back(Effect(effect1)); 00255 state->_effects.push_back(Effect(effect2)); 00256 state->_effects.sort(); 00257 return return_new(state); 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: RenderEffects::make 00262 // Access: Published, Static 00263 // Description: Returns a RenderEffects with three effects set. 00264 //////////////////////////////////////////////////////////////////// 00265 CPT(RenderEffects) RenderEffects:: 00266 make(const RenderEffect *effect1, 00267 const RenderEffect *effect2, 00268 const RenderEffect *effect3) { 00269 RenderEffects *state = new RenderEffects; 00270 state->_effects.reserve(2); 00271 state->_effects.push_back(Effect(effect1)); 00272 state->_effects.push_back(Effect(effect2)); 00273 state->_effects.push_back(Effect(effect3)); 00274 state->_effects.sort(); 00275 return return_new(state); 00276 } 00277 00278 //////////////////////////////////////////////////////////////////// 00279 // Function: RenderEffects::make 00280 // Access: Published, Static 00281 // Description: Returns a RenderEffects with four effects set. 00282 //////////////////////////////////////////////////////////////////// 00283 CPT(RenderEffects) RenderEffects:: 00284 make(const RenderEffect *effect1, 00285 const RenderEffect *effect2, 00286 const RenderEffect *effect3, 00287 const RenderEffect *effect4) { 00288 RenderEffects *state = new RenderEffects; 00289 state->_effects.reserve(2); 00290 state->_effects.push_back(Effect(effect1)); 00291 state->_effects.push_back(Effect(effect2)); 00292 state->_effects.push_back(Effect(effect3)); 00293 state->_effects.push_back(Effect(effect4)); 00294 state->_effects.sort(); 00295 return return_new(state); 00296 } 00297 00298 //////////////////////////////////////////////////////////////////// 00299 // Function: RenderEffects::add_effect 00300 // Access: Published 00301 // Description: Returns a new RenderEffects object that represents the 00302 // same as the source state, with the new RenderEffect 00303 // added. If there is already a RenderEffect with the 00304 // same type, it is replaced. 00305 //////////////////////////////////////////////////////////////////// 00306 CPT(RenderEffects) RenderEffects:: 00307 add_effect(const RenderEffect *effect) const { 00308 RenderEffects *new_state = new RenderEffects; 00309 back_insert_iterator<Effects> result = 00310 back_inserter(new_state->_effects); 00311 00312 Effect new_effect(effect); 00313 Effects::const_iterator ai = _effects.begin(); 00314 00315 while (ai != _effects.end() && (*ai) < new_effect) { 00316 *result = *ai; 00317 ++ai; 00318 ++result; 00319 } 00320 *result = new_effect; 00321 ++result; 00322 00323 if (ai != _effects.end() && !(new_effect < (*ai))) { 00324 // At this point we know: 00325 // !((*ai) < new_effect) && !(new_effect < (*ai)) 00326 // which means (*ai) == new_effect--so we should leave it out, 00327 // to avoid duplicating effects in the set. 00328 ++ai; 00329 } 00330 00331 while (ai != _effects.end()) { 00332 *result = *ai; 00333 ++ai; 00334 ++result; 00335 } 00336 00337 return return_new(new_state); 00338 } 00339 00340 //////////////////////////////////////////////////////////////////// 00341 // Function: RenderEffects::remove_effect 00342 // Access: Published 00343 // Description: Returns a new RenderEffects object that represents the 00344 // same as the source state, with the indicated 00345 // RenderEffect removed. 00346 //////////////////////////////////////////////////////////////////// 00347 CPT(RenderEffects) RenderEffects:: 00348 remove_effect(TypeHandle type) const { 00349 RenderEffects *new_state = new RenderEffects; 00350 back_insert_iterator<Effects> result = 00351 back_inserter(new_state->_effects); 00352 00353 Effects::const_iterator ai = _effects.begin(); 00354 00355 while (ai != _effects.end()) { 00356 if ((*ai)._type != type) { 00357 *result = *ai; 00358 ++result; 00359 } 00360 ++ai; 00361 } 00362 00363 return return_new(new_state); 00364 } 00365 00366 //////////////////////////////////////////////////////////////////// 00367 // Function: RenderEffects::get_effect 00368 // Access: Published, Virtual 00369 // Description: Looks for a RenderEffect of the indicated type in the 00370 // state, and returns it if it is found, or NULL if it 00371 // is not. 00372 //////////////////////////////////////////////////////////////////// 00373 const RenderEffect *RenderEffects:: 00374 get_effect(TypeHandle type) const { 00375 Effects::const_iterator ai; 00376 ai = _effects.find(Effect(type)); 00377 if (ai != _effects.end()) { 00378 return (*ai)._effect; 00379 } 00380 return NULL; 00381 } 00382 00383 //////////////////////////////////////////////////////////////////// 00384 // Function: RenderEffects::unref 00385 // Access: Published, Virtual 00386 // Description: This method overrides ReferenceCount::unref() to 00387 // check whether the remaining reference count is 00388 // entirely in the cache, and if so, it checks for and 00389 // breaks a cycle in the cache involving this object. 00390 // This is designed to prevent leaks from cyclical 00391 // references within the cache. 00392 // 00393 // Note that this is not a virtual method, and cannot be 00394 // because ReferenceCount itself declares no virtual 00395 // methods (it avoids the overhead of a virtual function 00396 // pointer). But this doesn't matter, because 00397 // PT(TransformState) is a template class, and will call 00398 // the appropriate method even though it is non-virtual. 00399 //////////////////////////////////////////////////////////////////// 00400 bool RenderEffects:: 00401 unref() const { 00402 LightReMutexHolder holder(*_states_lock); 00403 00404 if (ReferenceCount::unref()) { 00405 // The reference count is still nonzero. 00406 return true; 00407 } 00408 00409 // The reference count has just reached zero. Make sure the object 00410 // is removed from the global object pool, before anyone else finds 00411 // it and tries to ref it. 00412 ((RenderEffects *)this)->release_new(); 00413 00414 return false; 00415 } 00416 00417 //////////////////////////////////////////////////////////////////// 00418 // Function: RenderEffects::output 00419 // Access: Published, Virtual 00420 // Description: 00421 //////////////////////////////////////////////////////////////////// 00422 void RenderEffects:: 00423 output(ostream &out) const { 00424 out << "E:"; 00425 if (_effects.empty()) { 00426 out << "(empty)"; 00427 00428 } else { 00429 Effects::const_iterator ai = _effects.begin(); 00430 out << "(" << (*ai)._type; 00431 ++ai; 00432 while (ai != _effects.end()) { 00433 out << " " << (*ai)._type; 00434 ++ai; 00435 } 00436 out << ")"; 00437 } 00438 } 00439 00440 //////////////////////////////////////////////////////////////////// 00441 // Function: RenderEffects::write 00442 // Access: Published, Virtual 00443 // Description: 00444 //////////////////////////////////////////////////////////////////// 00445 void RenderEffects:: 00446 write(ostream &out, int indent_level) const { 00447 indent(out, indent_level) << _effects.size() << " effects:\n"; 00448 Effects::const_iterator ai; 00449 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00450 const Effect &effect = (*ai); 00451 effect._effect->write(out, indent_level + 2); 00452 } 00453 } 00454 00455 //////////////////////////////////////////////////////////////////// 00456 // Function: RenderEffects::get_num_states 00457 // Access: Published, Static 00458 // Description: Returns the total number of unique RenderEffects 00459 // objects allocated in the world. This will go up and 00460 // down during normal operations. 00461 //////////////////////////////////////////////////////////////////// 00462 int RenderEffects:: 00463 get_num_states() { 00464 if (_states == (States *)NULL) { 00465 return 0; 00466 } 00467 LightReMutexHolder holder(*_states_lock); 00468 return _states->size(); 00469 } 00470 00471 //////////////////////////////////////////////////////////////////// 00472 // Function: RenderEffects::list_states 00473 // Access: Published, Static 00474 // Description: Lists all of the RenderEffects in the cache to the 00475 // output stream, one per line. This can be quite a lot 00476 // of output if the cache is large, so be prepared. 00477 //////////////////////////////////////////////////////////////////// 00478 void RenderEffects:: 00479 list_states(ostream &out) { 00480 out << _states->size() << " states:\n"; 00481 States::const_iterator si; 00482 for (si = _states->begin(); si != _states->end(); ++si) { 00483 const RenderEffects *state = (*si); 00484 state->write(out, 2); 00485 } 00486 } 00487 00488 //////////////////////////////////////////////////////////////////// 00489 // Function: RenderEffects::validate_states 00490 // Access: Published, Static 00491 // Description: Ensures that the cache is still stored in sorted 00492 // order. Returns true if so, false if there is a 00493 // problem (which implies someone has modified one of 00494 // the supposedly-const RenderEffects objects). 00495 //////////////////////////////////////////////////////////////////// 00496 bool RenderEffects:: 00497 validate_states() { 00498 if (_states->empty()) { 00499 return true; 00500 } 00501 LightReMutexHolder holder(*_states_lock); 00502 00503 States::const_iterator si = _states->begin(); 00504 States::const_iterator snext = si; 00505 ++snext; 00506 while (snext != _states->end()) { 00507 if (!(*(*si) < *(*snext))) { 00508 pgraph_cat.error() 00509 << "RenderEffects out of order!\n"; 00510 (*si)->write(pgraph_cat.error(false), 2); 00511 (*snext)->write(pgraph_cat.error(false), 2); 00512 return false; 00513 } 00514 if ((*(*snext) < *(*si))) { 00515 pgraph_cat.error() 00516 << "RenderEffects::operator < not defined properly!\n"; 00517 pgraph_cat.error(false) 00518 << "a < b: " << (*(*si) < *(*snext)) << "\n"; 00519 pgraph_cat.error(false) 00520 << "b < a: " << (*(*snext) < *(*si)) << "\n"; 00521 (*si)->write(pgraph_cat.error(false), 2); 00522 (*snext)->write(pgraph_cat.error(false), 2); 00523 return false; 00524 } 00525 si = snext; 00526 ++snext; 00527 } 00528 00529 return true; 00530 } 00531 00532 //////////////////////////////////////////////////////////////////// 00533 // Function: RenderEffects::cull_callback 00534 // Access: Public 00535 // Description: Calls cull_callback() on all effects. You may check 00536 // has_cull_callback() first to see if any effects 00537 // define this method to do anything useful. 00538 //////////////////////////////////////////////////////////////////// 00539 void RenderEffects:: 00540 cull_callback(CullTraverser *trav, CullTraverserData &data, 00541 CPT(TransformState) &node_transform, 00542 CPT(RenderState) &node_state) const { 00543 Effects::const_iterator ei; 00544 for (ei = _effects.begin(); ei != _effects.end(); ++ei) { 00545 (*ei)._effect->cull_callback(trav, data, node_transform, node_state); 00546 } 00547 } 00548 00549 //////////////////////////////////////////////////////////////////// 00550 // Function: RenderEffects::adjust_transform 00551 // Access: Public 00552 // Description: Calls adjust_transform() on all effects. You may check 00553 // has_adjust_transform() first to see if any effects 00554 // define this method to do anything useful. 00555 // 00556 // The order in which the individual effects are applied 00557 // is not defined, so if more than one effect applies a 00558 // change to the transform on any particular node, you 00559 // might get indeterminate results. 00560 //////////////////////////////////////////////////////////////////// 00561 void RenderEffects:: 00562 adjust_transform(CPT(TransformState) &net_transform, 00563 CPT(TransformState) &node_transform, 00564 PandaNode *node) const { 00565 Effects::const_iterator ei; 00566 for (ei = _effects.begin(); ei != _effects.end(); ++ei) { 00567 (*ei)._effect->adjust_transform(net_transform, node_transform, node); 00568 } 00569 } 00570 00571 //////////////////////////////////////////////////////////////////// 00572 // Function: RenderEffects::init_states 00573 // Access: Public, Static 00574 // Description: Make sure the global _states map is allocated. This 00575 // only has to be done once. We could make this map 00576 // static, but then we run into problems if anyone 00577 // creates a RenderEffects object at static init time; 00578 // it also seems to cause problems when the Panda shared 00579 // library is unloaded at application exit time. 00580 //////////////////////////////////////////////////////////////////// 00581 void RenderEffects:: 00582 init_states() { 00583 _states = new States; 00584 00585 // TODO: we should have a global Panda mutex to allow us to safely 00586 // create _states_lock without a startup race condition. For the 00587 // meantime, this is OK because we guarantee that this method is 00588 // called at static init time, presumably when there is still only 00589 // one thread in the world. 00590 _states_lock = new LightReMutex("RenderEffects::_states_lock"); 00591 nassertv(Thread::get_current_thread() == Thread::get_main_thread()); 00592 } 00593 00594 00595 //////////////////////////////////////////////////////////////////// 00596 // Function: RenderEffects::return_new 00597 // Access: Private, Static 00598 // Description: This function is used to share a common RenderEffects 00599 // pointer for all equivalent RenderEffects objects. 00600 // 00601 // See the similar logic in RenderEffect. The idea is 00602 // to create a new RenderEffects object and pass it 00603 // through this function, which will share the pointer 00604 // with a previously-created RenderEffects object if it is 00605 // equivalent. 00606 //////////////////////////////////////////////////////////////////// 00607 CPT(RenderEffects) RenderEffects:: 00608 return_new(RenderEffects *state) { 00609 nassertr(state != (RenderEffects *)NULL, state); 00610 00611 #ifndef NDEBUG 00612 if (!state_cache) { 00613 return state; 00614 } 00615 #endif 00616 00617 #ifndef NDEBUG 00618 if (paranoid_const) { 00619 nassertr(validate_states(), state); 00620 } 00621 #endif 00622 00623 LightReMutexHolder holder(*_states_lock); 00624 00625 // This should be a newly allocated pointer, not one that was used 00626 // for anything else. 00627 nassertr(state->_saved_entry == _states->end(), state); 00628 00629 // Save the state in a local PointerTo so that it will be freed at 00630 // the end of this function if no one else uses it. 00631 CPT(RenderEffects) pt_state = state; 00632 00633 pair<States::iterator, bool> result = _states->insert(state); 00634 if (result.second) { 00635 // The state was inserted; save the iterator and return the 00636 // input state. 00637 state->_saved_entry = result.first; 00638 nassertr(_states->find(state) == state->_saved_entry, pt_state); 00639 return pt_state; 00640 } 00641 00642 // The state was not inserted; there must be an equivalent one 00643 // already in the set. Return that one. 00644 return *(result.first); 00645 } 00646 00647 //////////////////////////////////////////////////////////////////// 00648 // Function: RenderEffects::release_new 00649 // Access: Private 00650 // Description: This inverse of return_new, this releases this object 00651 // from the global RenderEffects table. 00652 // 00653 // You must already be holding _states_lock before you 00654 // call this method. 00655 //////////////////////////////////////////////////////////////////// 00656 void RenderEffects:: 00657 release_new() { 00658 nassertv(_states_lock->debug_is_locked()); 00659 00660 if (_saved_entry != _states->end()) { 00661 nassertv(_states->find(this) == _saved_entry); 00662 _states->erase(_saved_entry); 00663 _saved_entry = _states->end(); 00664 } 00665 } 00666 00667 //////////////////////////////////////////////////////////////////// 00668 // Function: RenderEffects::determine_decal 00669 // Access: Private 00670 // Description: This is the private implementation of has_decal(). 00671 //////////////////////////////////////////////////////////////////// 00672 void RenderEffects:: 00673 determine_decal() { 00674 LightMutexHolder holder(_lock); 00675 if ((_flags & F_checked_decal) != 0) { 00676 // Someone else checked it first. 00677 return; 00678 } 00679 00680 const RenderEffect *effect = get_effect(DecalEffect::get_class_type()); 00681 if (effect != (const RenderEffect *)NULL) { 00682 _flags |= F_has_decal; 00683 } 00684 _flags |= F_checked_decal; 00685 } 00686 00687 //////////////////////////////////////////////////////////////////// 00688 // Function: RenderEffects::determine_show_bounds 00689 // Access: Private 00690 // Description: This is the private implementation of has_show_bounds(). 00691 //////////////////////////////////////////////////////////////////// 00692 void RenderEffects:: 00693 determine_show_bounds() { 00694 LightMutexHolder holder(_lock); 00695 if ((_flags & F_checked_show_bounds) != 0) { 00696 // Someone else checked it first. 00697 return; 00698 } 00699 00700 const RenderEffect *effect = get_effect(ShowBoundsEffect::get_class_type()); 00701 if (effect != (const RenderEffect *)NULL) { 00702 _flags |= F_has_show_bounds; 00703 const ShowBoundsEffect *sba = DCAST(ShowBoundsEffect, effect); 00704 if (sba->get_tight()) { 00705 _flags |= F_has_show_tight_bounds; 00706 } 00707 } 00708 _flags |= F_checked_show_bounds; 00709 } 00710 00711 //////////////////////////////////////////////////////////////////// 00712 // Function: RenderEffects::determine_cull_callback 00713 // Access: Private 00714 // Description: This is the private implementation of has_cull_callback(). 00715 //////////////////////////////////////////////////////////////////// 00716 void RenderEffects:: 00717 determine_cull_callback() { 00718 LightMutexHolder holder(_lock); 00719 if ((_flags & F_checked_cull_callback) != 0) { 00720 // Someone else checked it first. 00721 return; 00722 } 00723 00724 _flags |= F_checked_cull_callback; 00725 00726 Effects::const_iterator ei; 00727 for (ei = _effects.begin(); ei != _effects.end(); ++ei) { 00728 if ((*ei)._effect->has_cull_callback()) { 00729 _flags |= F_has_cull_callback; 00730 return; 00731 } 00732 } 00733 } 00734 00735 //////////////////////////////////////////////////////////////////// 00736 // Function: RenderEffects::determine_adjust_transform 00737 // Access: Private 00738 // Description: This is the private implementation of has_adjust_transform(). 00739 //////////////////////////////////////////////////////////////////// 00740 void RenderEffects:: 00741 determine_adjust_transform() { 00742 LightMutexHolder holder(_lock); 00743 if ((_flags & F_checked_adjust_transform) != 0) { 00744 // Someone else checked it first. 00745 return; 00746 } 00747 00748 _flags |= F_checked_adjust_transform; 00749 00750 Effects::const_iterator ei; 00751 for (ei = _effects.begin(); ei != _effects.end(); ++ei) { 00752 if ((*ei)._effect->has_adjust_transform()) { 00753 _flags |= F_has_adjust_transform; 00754 return; 00755 } 00756 } 00757 } 00758 00759 //////////////////////////////////////////////////////////////////// 00760 // Function: RenderEffects::register_with_read_factory 00761 // Access: Public, Static 00762 // Description: Tells the BamReader how to create objects of type 00763 // RenderEffects. 00764 //////////////////////////////////////////////////////////////////// 00765 void RenderEffects:: 00766 register_with_read_factory() { 00767 BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); 00768 } 00769 00770 //////////////////////////////////////////////////////////////////// 00771 // Function: RenderEffects::write_datagram 00772 // Access: Public, Virtual 00773 // Description: Writes the contents of this object to the datagram 00774 // for shipping out to a Bam file. 00775 //////////////////////////////////////////////////////////////////// 00776 void RenderEffects:: 00777 write_datagram(BamWriter *manager, Datagram &dg) { 00778 TypedWritable::write_datagram(manager, dg); 00779 00780 int num_effects = _effects.size(); 00781 nassertv(num_effects == (int)(PN_uint16)num_effects); 00782 dg.add_uint16(num_effects); 00783 00784 Effects::const_iterator ai; 00785 for (ai = _effects.begin(); ai != _effects.end(); ++ai) { 00786 const Effect &effect = (*ai); 00787 00788 manager->write_pointer(dg, effect._effect); 00789 } 00790 } 00791 00792 //////////////////////////////////////////////////////////////////// 00793 // Function: RenderEffects::complete_pointers 00794 // Access: Public, Virtual 00795 // Description: Receives an array of pointers, one for each time 00796 // manager->read_pointer() was called in fillin(). 00797 // Returns the number of pointers processed. 00798 //////////////////////////////////////////////////////////////////// 00799 int RenderEffects:: 00800 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00801 int pi = TypedWritable::complete_pointers(p_list, manager); 00802 00803 // Get the effect pointers. 00804 size_t i = 0; 00805 while (i < _effects.size()) { 00806 Effect &effect = _effects[i]; 00807 00808 effect._effect = DCAST(RenderEffect, p_list[pi++]); 00809 if (effect._effect == (RenderEffect *)NULL) { 00810 // Remove this bogus RenderEffect pointer (it must have been 00811 // from an unwritable class). 00812 _effects.erase(_effects.begin() + i); 00813 00814 } else { 00815 // Keep this good pointer, and increment. 00816 effect._type = effect._effect->get_type(); 00817 ++i; 00818 } 00819 } 00820 00821 // Now make sure the array is properly sorted. (It won't 00822 // necessarily preserve its correct sort after being read from bam, 00823 // because the sort is based on TypeHandle indices, which can change 00824 // from session to session.) 00825 _effects.sort(); 00826 00827 nassertr(_saved_entry == _states->end(), pi); 00828 return pi; 00829 } 00830 00831 //////////////////////////////////////////////////////////////////// 00832 // Function: RenderEffects::require_fully_complete 00833 // Access: Public, Virtual 00834 // Description: Some objects require all of their nested pointers to 00835 // have been completed before the objects themselves can 00836 // be completed. If this is the case, override this 00837 // method to return true, and be careful with circular 00838 // references (which would make the object unreadable 00839 // from a bam file). 00840 //////////////////////////////////////////////////////////////////// 00841 bool RenderEffects:: 00842 require_fully_complete() const { 00843 // Since we sort _states based on each RenderEffects' operator < 00844 // method, which in turn compares based on each nested RenderEffect 00845 // object's compare_to() method, some of which depend on the 00846 // RenderEffect's pointers having already been completed 00847 // (e.g. CharacterJointEffect), we therefore require each of out our 00848 // nested RenderEffect objects to have been completed before we can 00849 // be completed. 00850 return true; 00851 } 00852 00853 //////////////////////////////////////////////////////////////////// 00854 // Function: RenderEffects::change_this 00855 // Access: Public, Static 00856 // Description: Called immediately after complete_pointers(), this 00857 // gives the object a chance to adjust its own pointer 00858 // if desired. Most objects don't change pointers after 00859 // completion, but some need to. 00860 // 00861 // Once this function has been called, the old pointer 00862 // will no longer be accessed. 00863 //////////////////////////////////////////////////////////////////// 00864 TypedWritable *RenderEffects:: 00865 change_this(TypedWritable *old_ptr, BamReader *manager) { 00866 // First, uniquify the pointer. 00867 RenderEffects *state = DCAST(RenderEffects, old_ptr); 00868 CPT(RenderEffects) pointer = return_new(state); 00869 00870 // But now we have a problem, since we have to hold the reference 00871 // count and there's no way to return a TypedWritable while still 00872 // holding the reference count! We work around this by explicitly 00873 // upping the count, and also setting a finalize() callback to down 00874 // it later. 00875 if (pointer == state) { 00876 pointer->ref(); 00877 manager->register_finalize(state); 00878 } 00879 00880 // We have to cast the pointer back to non-const, because the bam 00881 // reader expects that. 00882 return (RenderEffects *)pointer.p(); 00883 } 00884 00885 //////////////////////////////////////////////////////////////////// 00886 // Function: RenderEffects::finalize 00887 // Access: Public, Virtual 00888 // Description: Called by the BamReader to perform any final actions 00889 // needed for setting up the object after all objects 00890 // have been read and all pointers have been completed. 00891 //////////////////////////////////////////////////////////////////// 00892 void RenderEffects:: 00893 finalize(BamReader *) { 00894 // Unref the pointer that we explicitly reffed in change_this(). 00895 unref(); 00896 00897 // We should never get back to zero after unreffing our own count, 00898 // because we expect to have been stored in a pointer somewhere. If 00899 // we do get to zero, it's a memory leak; the way to avoid this is 00900 // to call unref_delete() above instead of unref(), but this is 00901 // dangerous to do from within a virtual function. 00902 nassertv(get_ref_count() != 0); 00903 } 00904 00905 //////////////////////////////////////////////////////////////////// 00906 // Function: RenderEffects::make_from_bam 00907 // Access: Protected, Static 00908 // Description: This function is called by the BamReader's factory 00909 // when a new object of type RenderEffects is encountered 00910 // in the Bam file. It should create the RenderEffects 00911 // and extract its information from the file. 00912 //////////////////////////////////////////////////////////////////// 00913 TypedWritable *RenderEffects:: 00914 make_from_bam(const FactoryParams ¶ms) { 00915 RenderEffects *state = new RenderEffects; 00916 DatagramIterator scan; 00917 BamReader *manager; 00918 00919 parse_params(params, scan, manager); 00920 state->fillin(scan, manager); 00921 manager->register_change_this(change_this, state); 00922 00923 return state; 00924 } 00925 00926 //////////////////////////////////////////////////////////////////// 00927 // Function: RenderEffects::fillin 00928 // Access: Protected 00929 // Description: This internal function is called by make_from_bam to 00930 // read in all of the relevant data from the BamFile for 00931 // the new RenderEffects. 00932 //////////////////////////////////////////////////////////////////// 00933 void RenderEffects:: 00934 fillin(DatagramIterator &scan, BamReader *manager) { 00935 TypedWritable::fillin(scan, manager); 00936 00937 int num_effects = scan.get_uint16(); 00938 00939 // Push back a NULL pointer for each effect for now, until we get 00940 // the actual list of pointers later in complete_pointers(). 00941 _effects.reserve(num_effects); 00942 for (int i = 0; i < num_effects; i++) { 00943 manager->read_pointer(scan); 00944 _effects.push_back(Effect()); 00945 } 00946 00947 nassertv(_saved_entry == _states->end()); 00948 }