Panda3D
|
00001 // Filename: renderAttrib.cxx 00002 // Created by: drose (21Feb02) 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 "renderAttrib.h" 00016 #include "bamReader.h" 00017 #include "indent.h" 00018 #include "config_pgraph.h" 00019 #include "lightReMutexHolder.h" 00020 #include "pStatTimer.h" 00021 00022 LightReMutex *RenderAttrib::_attribs_lock = NULL; 00023 RenderAttrib::Attribs *RenderAttrib::_attribs = NULL; 00024 TypeHandle RenderAttrib::_type_handle; 00025 00026 int RenderAttrib::_garbage_index = 0; 00027 00028 PStatCollector RenderAttrib::_garbage_collect_pcollector("*:State Cache:Garbage Collect"); 00029 00030 //////////////////////////////////////////////////////////////////// 00031 // Function: RenderAttrib::Constructor 00032 // Access: Protected 00033 // Description: 00034 //////////////////////////////////////////////////////////////////// 00035 RenderAttrib:: 00036 RenderAttrib() { 00037 if (_attribs == (Attribs *)NULL) { 00038 init_attribs(); 00039 } 00040 _saved_entry = -1; 00041 00042 _always_reissue = false; 00043 } 00044 00045 //////////////////////////////////////////////////////////////////// 00046 // Function: RenderAttrib::Copy Constructor 00047 // Access: Private 00048 // Description: RenderAttribs are not meant to be copied. 00049 //////////////////////////////////////////////////////////////////// 00050 RenderAttrib:: 00051 RenderAttrib(const RenderAttrib &) { 00052 nassertv(false); 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: RenderAttrib::Copy Assignment Operator 00057 // Access: Private 00058 // Description: RenderAttribs are not meant to be copied. 00059 //////////////////////////////////////////////////////////////////// 00060 void RenderAttrib:: 00061 operator = (const RenderAttrib &) { 00062 nassertv(false); 00063 } 00064 00065 //////////////////////////////////////////////////////////////////// 00066 // Function: RenderAttrib::Destructor 00067 // Access: Public, Virtual 00068 // Description: The destructor is responsible for removing the 00069 // RenderAttrib from the global set if it is there. 00070 //////////////////////////////////////////////////////////////////// 00071 RenderAttrib:: 00072 ~RenderAttrib() { 00073 LightReMutexHolder holder(*_attribs_lock); 00074 00075 // unref() should have cleared this. 00076 nassertv(_saved_entry == -1); 00077 } 00078 00079 //////////////////////////////////////////////////////////////////// 00080 // Function: RenderAttrib::lower_attrib_can_override 00081 // Access: Public, Virtual 00082 // Description: Intended to be overridden by derived RenderAttrib 00083 // types to specify how two consecutive RenderAttrib 00084 // objects of the same type interact. 00085 // 00086 // This should return false if a RenderAttrib on a 00087 // higher node will compose into a RenderAttrib on a 00088 // lower node that has a higher override value, or true 00089 // if the lower RenderAttrib will completely replace the 00090 // state. 00091 // 00092 // The default behavior is false: normally, a 00093 // RenderAttrib in the graph cannot completely override 00094 // a RenderAttrib above it, regardless of its override 00095 // value--instead, the two attribs are composed. But 00096 // for some kinds of RenderAttribs, it is useful to 00097 // allow this kind of override. 00098 // 00099 // This method only handles the one special case of a 00100 // lower RenderAttrib with a higher override value. If 00101 // the higher RenderAttrib has a higher override value, 00102 // it always completely overrides. And if both 00103 // RenderAttribs have the same override value, they are 00104 // always composed. 00105 //////////////////////////////////////////////////////////////////// 00106 bool RenderAttrib:: 00107 lower_attrib_can_override() const { 00108 return false; 00109 } 00110 00111 //////////////////////////////////////////////////////////////////// 00112 // Function: RenderAttrib::has_cull_callback 00113 // Access: Public, Virtual 00114 // Description: Should be overridden by derived classes to return 00115 // true if cull_callback() has been defined. Otherwise, 00116 // returns false to indicate cull_callback() does not 00117 // need to be called for this node during the cull 00118 // traversal. 00119 //////////////////////////////////////////////////////////////////// 00120 bool RenderAttrib:: 00121 has_cull_callback() const { 00122 return false; 00123 } 00124 00125 //////////////////////////////////////////////////////////////////// 00126 // Function: RenderAttrib::cull_callback 00127 // Access: Public, Virtual 00128 // Description: If has_cull_callback() returns true, this function 00129 // will be called during the cull traversal to perform 00130 // any additional operations that should be performed at 00131 // cull time. 00132 // 00133 // This is called each time the RenderAttrib is 00134 // discovered applied to a Geom in the traversal. It 00135 // should return true if the Geom is visible, false if 00136 // it should be omitted. 00137 //////////////////////////////////////////////////////////////////// 00138 bool RenderAttrib:: 00139 cull_callback(CullTraverser *, const CullTraverserData &) const { 00140 return true; 00141 } 00142 00143 //////////////////////////////////////////////////////////////////// 00144 // Function: RenderAttrib::get_auto_shader_attrib_impl 00145 // Access: Protected, Virtual 00146 // Description: 00147 //////////////////////////////////////////////////////////////////// 00148 CPT(RenderAttrib) RenderAttrib:: 00149 get_auto_shader_attrib_impl(const RenderState *state) const { 00150 return NULL; 00151 } 00152 00153 //////////////////////////////////////////////////////////////////// 00154 // Function: RenderAttrib::unref 00155 // Access: Published, Virtual 00156 // Description: This method overrides ReferenceCount::unref() to 00157 // clear the pointer from the global object pool when 00158 // its reference count goes to zero. 00159 //////////////////////////////////////////////////////////////////// 00160 bool RenderAttrib:: 00161 unref() const { 00162 if (!state_cache || garbage_collect_states) { 00163 // If we're not using the cache at all, or if we're relying on 00164 // garbage collection, just allow the pointer to unref normally. 00165 return ReferenceCount::unref(); 00166 } 00167 00168 // Here is the normal refcounting case, with a normal cache, and 00169 // without garbage collection in effect. In this case we will pull 00170 // the object out of the cache when its reference count goes to 0. 00171 00172 // We always have to grab the lock, since we will definitely need to 00173 // be holding it if we happen to drop the reference count to 0. 00174 // Having to grab the lock at every call to unref() is a big 00175 // limiting factor on parallelization. 00176 LightReMutexHolder holder(*_attribs_lock); 00177 00178 if (ReferenceCount::unref()) { 00179 // The reference count is still nonzero. 00180 return true; 00181 } 00182 00183 // The reference count has just reached zero. Make sure the object 00184 // is removed from the global object pool, before anyone else finds 00185 // it and tries to ref it. 00186 ((RenderAttrib *)this)->release_new(); 00187 00188 return false; 00189 } 00190 00191 //////////////////////////////////////////////////////////////////// 00192 // Function: RenderAttrib::output 00193 // Access: Published, Virtual 00194 // Description: 00195 //////////////////////////////////////////////////////////////////// 00196 void RenderAttrib:: 00197 output(ostream &out) const { 00198 out << get_type(); 00199 } 00200 00201 //////////////////////////////////////////////////////////////////// 00202 // Function: RenderAttrib::write 00203 // Access: Published, Virtual 00204 // Description: 00205 //////////////////////////////////////////////////////////////////// 00206 void RenderAttrib:: 00207 write(ostream &out, int indent_level) const { 00208 indent(out, indent_level) << *this << "\n"; 00209 } 00210 00211 //////////////////////////////////////////////////////////////////// 00212 // Function: RenderAttrib::get_num_attribs 00213 // Access: Published, Static 00214 // Description: Returns the total number of unique RenderAttrib 00215 // objects allocated in the world. This will go up and 00216 // down during normal operations. 00217 //////////////////////////////////////////////////////////////////// 00218 int RenderAttrib:: 00219 get_num_attribs() { 00220 LightReMutexHolder holder(*_attribs_lock); 00221 00222 if (_attribs == (Attribs *)NULL) { 00223 return 0; 00224 } 00225 return _attribs->get_num_entries(); 00226 } 00227 00228 //////////////////////////////////////////////////////////////////// 00229 // Function: RenderAttrib::list_attribs 00230 // Access: Published, Static 00231 // Description: Lists all of the RenderAttribs in the cache to the 00232 // output stream, one per line. This can be quite a lot 00233 // of output if the cache is large, so be prepared. 00234 //////////////////////////////////////////////////////////////////// 00235 void RenderAttrib:: 00236 list_attribs(ostream &out) { 00237 LightReMutexHolder holder(*_attribs_lock); 00238 00239 out << _attribs->get_num_entries() << " attribs:\n"; 00240 int size = _attribs->get_size(); 00241 for (int si = 0; si < size; ++si) { 00242 if (!_attribs->has_element(si)) { 00243 continue; 00244 } 00245 const RenderAttrib *attrib = _attribs->get_key(si); 00246 attrib->write(out, 2); 00247 } 00248 } 00249 00250 //////////////////////////////////////////////////////////////////// 00251 // Function: RenderAttrib::garbage_collect 00252 // Access: Published, Static 00253 // Description: Performs a garbage-collection cycle. This is called 00254 // automatically from RenderState::garbage_collect(); 00255 // see that method for more information. 00256 //////////////////////////////////////////////////////////////////// 00257 int RenderAttrib:: 00258 garbage_collect() { 00259 if (_attribs == (Attribs *)NULL || !garbage_collect_states) { 00260 return 0; 00261 } 00262 LightReMutexHolder holder(*_attribs_lock); 00263 00264 PStatTimer timer(_garbage_collect_pcollector); 00265 int orig_size = _attribs->get_num_entries(); 00266 00267 nassertr(_attribs->validate(), 0); 00268 00269 // How many elements to process this pass? 00270 int size = _attribs->get_size(); 00271 int num_this_pass = int(size * garbage_collect_states_rate); 00272 if (num_this_pass <= 0) { 00273 return 0; 00274 } 00275 num_this_pass = min(num_this_pass, size); 00276 int stop_at_element = (_garbage_index + num_this_pass) % size; 00277 00278 int num_elements = 0; 00279 int si = _garbage_index; 00280 do { 00281 if (_attribs->has_element(si)) { 00282 ++num_elements; 00283 RenderAttrib *attrib = (RenderAttrib *)_attribs->get_key(si); 00284 if (attrib->get_ref_count() == 1) { 00285 // This attrib has recently been unreffed to 1 (the one we 00286 // added when we stored it in the cache). Now it's time to 00287 // delete it. This is safe, because we're holding the 00288 // _attribs_lock, so it's not possible for some other thread to 00289 // find the attrib in the cache and ref it while we're doing 00290 // this. 00291 attrib->release_new(); 00292 unref_delete(attrib); 00293 } 00294 } 00295 00296 si = (si + 1) % size; 00297 } while (si != stop_at_element); 00298 _garbage_index = si; 00299 nassertr(_attribs->validate(), 0); 00300 00301 int new_size = _attribs->get_num_entries(); 00302 return orig_size - new_size; 00303 } 00304 00305 //////////////////////////////////////////////////////////////////// 00306 // Function: RenderAttrib::validate_attribs 00307 // Access: Published, Static 00308 // Description: Ensures that the cache is still stored in sorted 00309 // order. Returns true if so, false if there is a 00310 // problem (which implies someone has modified one of 00311 // the supposedly-const RenderAttrib objects). 00312 //////////////////////////////////////////////////////////////////// 00313 bool RenderAttrib:: 00314 validate_attribs() { 00315 LightReMutexHolder holder(*_attribs_lock); 00316 if (_attribs->is_empty()) { 00317 return true; 00318 } 00319 00320 if (!_attribs->validate()) { 00321 pgraph_cat.error() 00322 << "RenderAttrib::_attribs cache is invalid!\n"; 00323 00324 int size = _attribs->get_size(); 00325 for (int si = 0; si < size; ++si) { 00326 if (!_attribs->has_element(si)) { 00327 continue; 00328 } 00329 const RenderAttrib *attrib = _attribs->get_key(si); 00330 cerr << si << ": " << attrib << "\n"; 00331 attrib->get_hash(); 00332 attrib->write(cerr, 2); 00333 } 00334 00335 return false; 00336 } 00337 00338 int size = _attribs->get_size(); 00339 int si = 0; 00340 while (si < size && !_attribs->has_element(si)) { 00341 ++si; 00342 } 00343 nassertr(si < size, false); 00344 nassertr(_attribs->get_key(si)->get_ref_count() >= 0, false); 00345 int snext = si; 00346 ++snext; 00347 while (snext < size && !_attribs->has_element(snext)) { 00348 ++snext; 00349 } 00350 while (snext < size) { 00351 nassertr(_attribs->get_key(snext)->get_ref_count() >= 0, false); 00352 const RenderAttrib *ssi = _attribs->get_key(si); 00353 const RenderAttrib *ssnext = _attribs->get_key(snext); 00354 int c = ssi->compare_to(*ssnext); 00355 int ci = ssnext->compare_to(*ssi); 00356 if ((ci < 0) != (c > 0) || 00357 (ci > 0) != (c < 0) || 00358 (ci == 0) != (c == 0)) { 00359 pgraph_cat.error() 00360 << "RenderAttrib::compare_to() not defined properly!\n"; 00361 pgraph_cat.error(false) 00362 << "(a, b): " << c << "\n"; 00363 pgraph_cat.error(false) 00364 << "(b, a): " << ci << "\n"; 00365 ssi->write(pgraph_cat.error(false), 2); 00366 ssnext->write(pgraph_cat.error(false), 2); 00367 return false; 00368 } 00369 si = snext; 00370 ++snext; 00371 while (snext < size && !_attribs->has_element(snext)) { 00372 ++snext; 00373 } 00374 } 00375 00376 return true; 00377 } 00378 00379 //////////////////////////////////////////////////////////////////// 00380 // Function: RenderAttrib::return_new 00381 // Access: Protected, Static 00382 // Description: This function is used by derived RenderAttrib types 00383 // to share a common RenderAttrib pointer for all 00384 // equivalent RenderAttrib objects. 00385 // 00386 // This is different from return_unique() in that it 00387 // does not actually guarantee a unique pointer, unless 00388 // uniquify-attribs is set. 00389 //////////////////////////////////////////////////////////////////// 00390 CPT(RenderAttrib) RenderAttrib:: 00391 return_new(RenderAttrib *attrib) { 00392 nassertr(attrib != (RenderAttrib *)NULL, attrib); 00393 if (!uniquify_attribs) { 00394 return attrib; 00395 } 00396 00397 return return_unique(attrib); 00398 } 00399 00400 //////////////////////////////////////////////////////////////////// 00401 // Function: RenderAttrib::return_unique 00402 // Access: Protected, Static 00403 // Description: This function is used by derived RenderAttrib types 00404 // to share a common RenderAttrib pointer for all 00405 // equivalent RenderAttrib objects. 00406 // 00407 // The make() function of the derived type should create 00408 // a new RenderAttrib and pass it through return_new(), 00409 // which will either save the pointer and return it 00410 // unchanged (if this is the first similar such object) 00411 // or delete it and return an equivalent pointer (if 00412 // there was already a similar object saved). 00413 //////////////////////////////////////////////////////////////////// 00414 CPT(RenderAttrib) RenderAttrib:: 00415 return_unique(RenderAttrib *attrib) { 00416 nassertr(attrib != (RenderAttrib *)NULL, attrib); 00417 00418 if (!state_cache) { 00419 return attrib; 00420 } 00421 00422 #ifndef NDEBUG 00423 if (paranoid_const) { 00424 nassertr(validate_attribs(), attrib); 00425 } 00426 #endif 00427 00428 LightReMutexHolder holder(*_attribs_lock); 00429 00430 if (attrib->_saved_entry != -1) { 00431 // This attrib is already in the cache. 00432 //nassertr(_attribs->find(attrib) == attrib->_saved_entry, attrib); 00433 return attrib; 00434 } 00435 00436 // Save the attrib in a local PointerTo so that it will be freed at 00437 // the end of this function if no one else uses it. 00438 CPT(RenderAttrib) pt_attrib = attrib; 00439 00440 int si = _attribs->find(attrib); 00441 if (si != -1) { 00442 // There's an equivalent attrib already in the set. Return it. 00443 return _attribs->get_key(si); 00444 } 00445 00446 // Not already in the set; add it. 00447 if (garbage_collect_states) { 00448 // If we'll be garbage collecting attribs explicitly, we'll 00449 // increment the reference count when we store it in the cache, so 00450 // that it won't be deleted while it's in it. 00451 attrib->ref(); 00452 } 00453 si = _attribs->store(attrib, Empty()); 00454 00455 // Save the index and return the input attrib. 00456 attrib->_saved_entry = si; 00457 return pt_attrib; 00458 } 00459 00460 //////////////////////////////////////////////////////////////////// 00461 // Function: RenderAttrib::compare_to_impl 00462 // Access: Protected, Virtual 00463 // Description: Intended to be overridden by derived RenderAttrib 00464 // types to return a unique number indicating whether 00465 // this RenderAttrib is equivalent to the other one. 00466 // 00467 // This should return 0 if the two RenderAttrib objects 00468 // are equivalent, a number less than zero if this one 00469 // should be sorted before the other one, and a number 00470 // greater than zero otherwise. 00471 // 00472 // This will only be called with two RenderAttrib 00473 // objects whose get_type() functions return the same. 00474 //////////////////////////////////////////////////////////////////// 00475 int RenderAttrib:: 00476 compare_to_impl(const RenderAttrib *other) const { 00477 return 0; 00478 } 00479 00480 //////////////////////////////////////////////////////////////////// 00481 // Function: RenderAttrib::get_hash_impl 00482 // Access: Protected, Virtual 00483 // Description: Intended to be overridden by derived RenderAttrib 00484 // types to return a unique hash for these particular 00485 // properties. RenderAttribs that compare the same with 00486 // compare_to_impl(), above, should return the same 00487 // hash; RenderAttribs that compare differently should 00488 // return a different hash. 00489 //////////////////////////////////////////////////////////////////// 00490 size_t RenderAttrib:: 00491 get_hash_impl() const { 00492 return 0; 00493 } 00494 00495 //////////////////////////////////////////////////////////////////// 00496 // Function: RenderAttrib::compose_impl 00497 // Access: Protected, Virtual 00498 // Description: Intended to be overridden by derived RenderAttrib 00499 // types to specify how two consecutive RenderAttrib 00500 // objects of the same type interact. 00501 // 00502 // This should return the result of applying the other 00503 // RenderAttrib to a node in the scene graph below this 00504 // RenderAttrib, which was already applied. In most 00505 // cases, the result is the same as the other 00506 // RenderAttrib (that is, a subsequent RenderAttrib 00507 // completely replaces the preceding one). On the other 00508 // hand, some kinds of RenderAttrib (for instance, 00509 // ColorTransformAttrib) might combine in meaningful 00510 // ways. 00511 //////////////////////////////////////////////////////////////////// 00512 CPT(RenderAttrib) RenderAttrib:: 00513 compose_impl(const RenderAttrib *other) const { 00514 return other; 00515 } 00516 00517 //////////////////////////////////////////////////////////////////// 00518 // Function: RenderAttrib::invert_compose_impl 00519 // Access: Protected, Virtual 00520 // Description: Intended to be overridden by derived RenderAttrib 00521 // types to specify how two consecutive RenderAttrib 00522 // objects of the same type interact. 00523 // 00524 // See invert_compose() and compose_impl(). 00525 //////////////////////////////////////////////////////////////////// 00526 CPT(RenderAttrib) RenderAttrib:: 00527 invert_compose_impl(const RenderAttrib *other) const { 00528 return other; 00529 } 00530 00531 //////////////////////////////////////////////////////////////////// 00532 // Function: RenderAttrib::output_comparefunc 00533 // Access: Protected 00534 // Description: Outputs a string representation of the given 00535 // PandaCompareFunc object. 00536 //////////////////////////////////////////////////////////////////// 00537 void RenderAttrib:: 00538 output_comparefunc(ostream &out, PandaCompareFunc fn) const { 00539 switch (fn) { 00540 case M_none: 00541 out << "none"; 00542 break; 00543 00544 case M_never: 00545 out << "never"; 00546 break; 00547 00548 case M_less: 00549 out << "less"; 00550 break; 00551 00552 case M_equal: 00553 out << "equal"; 00554 break; 00555 00556 case M_less_equal: 00557 out << "less_equal"; 00558 break; 00559 00560 case M_greater: 00561 out << "greater"; 00562 break; 00563 00564 case M_not_equal: 00565 out << "not_equal"; 00566 break; 00567 00568 case M_greater_equal: 00569 out << "greater_equal"; 00570 break; 00571 00572 case M_always: 00573 out << "always"; 00574 break; 00575 } 00576 } 00577 00578 //////////////////////////////////////////////////////////////////// 00579 // Function: RenderAttrib::release_new 00580 // Access: Private 00581 // Description: This inverse of return_new, this releases this object 00582 // from the global RenderAttrib table. 00583 // 00584 // You must already be holding _attribs_lock before you 00585 // call this method. 00586 //////////////////////////////////////////////////////////////////// 00587 void RenderAttrib:: 00588 release_new() { 00589 nassertv(_attribs_lock->debug_is_locked()); 00590 00591 if (_saved_entry != -1) { 00592 //nassertv(_attribs->find(this) == _saved_entry); 00593 _saved_entry = _attribs->find(this); 00594 _attribs->remove_element(_saved_entry); 00595 _saved_entry = -1; 00596 } 00597 } 00598 00599 //////////////////////////////////////////////////////////////////// 00600 // Function: RenderAttrib::init_attribs 00601 // Access: Public, Static 00602 // Description: Make sure the global _attribs map is allocated. This 00603 // only has to be done once. We could make this map 00604 // static, but then we run into problems if anyone 00605 // creates a RenderAttrib object at static init time; 00606 // it also seems to cause problems when the Panda shared 00607 // library is unloaded at application exit time. 00608 //////////////////////////////////////////////////////////////////// 00609 void RenderAttrib:: 00610 init_attribs() { 00611 _attribs = new Attribs; 00612 00613 // TODO: we should have a global Panda mutex to allow us to safely 00614 // create _attribs_lock without a startup race condition. For the 00615 // meantime, this is OK because we guarantee that this method is 00616 // called at static init time, presumably when there is still only 00617 // one thread in the world. 00618 _attribs_lock = new LightReMutex("RenderAttrib::_attribs_lock"); 00619 nassertv(Thread::get_current_thread() == Thread::get_main_thread()); 00620 } 00621 00622 //////////////////////////////////////////////////////////////////// 00623 // Function: RenderAttrib::write_datagram 00624 // Access: Public, Virtual 00625 // Description: Writes the contents of this object to the datagram 00626 // for shipping out to a Bam file. 00627 //////////////////////////////////////////////////////////////////// 00628 void RenderAttrib:: 00629 write_datagram(BamWriter *manager, Datagram &dg) { 00630 TypedWritable::write_datagram(manager, dg); 00631 } 00632 00633 //////////////////////////////////////////////////////////////////// 00634 // Function: RenderAttrib::change_this 00635 // Access: Public, Static 00636 // Description: Called immediately after complete_pointers(), this 00637 // gives the object a chance to adjust its own pointer 00638 // if desired. Most objects don't change pointers after 00639 // completion, but some need to. 00640 // 00641 // Once this function has been called, the old pointer 00642 // will no longer be accessed. 00643 //////////////////////////////////////////////////////////////////// 00644 TypedWritable *RenderAttrib:: 00645 change_this(TypedWritable *old_ptr, BamReader *manager) { 00646 // First, uniquify the pointer. 00647 RenderAttrib *attrib = DCAST(RenderAttrib, old_ptr); 00648 CPT(RenderAttrib) pointer = return_unique(attrib); 00649 00650 // But now we have a problem, since we have to hold the reference 00651 // count and there's no way to return a TypedWritable while still 00652 // holding the reference count! We work around this by explicitly 00653 // upping the count, and also setting a finalize() callback to down 00654 // it later. 00655 if (pointer == attrib) { 00656 pointer->ref(); 00657 manager->register_finalize(attrib); 00658 } 00659 00660 // We have to cast the pointer back to non-const, because the bam 00661 // reader expects that. 00662 return (RenderAttrib *)pointer.p(); 00663 } 00664 00665 //////////////////////////////////////////////////////////////////// 00666 // Function: RenderAttrib::finalize 00667 // Access: Public, Virtual 00668 // Description: Called by the BamReader to perform any final actions 00669 // needed for setting up the object after all objects 00670 // have been read and all pointers have been completed. 00671 //////////////////////////////////////////////////////////////////// 00672 void RenderAttrib:: 00673 finalize(BamReader *) { 00674 // Unref the pointer that we explicitly reffed in change_this(). 00675 unref(); 00676 00677 // We should never get back to zero after unreffing our own count, 00678 // because we expect to have been stored in a pointer somewhere. If 00679 // we do get to zero, it's a memory leak; the way to avoid this is 00680 // to call unref_delete() above instead of unref(), but this is 00681 // dangerous to do from within a virtual function. 00682 nassertv(get_ref_count() != 0); 00683 } 00684 00685 //////////////////////////////////////////////////////////////////// 00686 // Function: RenderAttrib::fillin 00687 // Access: Protected 00688 // Description: This internal function is called by make_from_bam to 00689 // read in all of the relevant data from the BamFile for 00690 // the new RenderAttrib. 00691 //////////////////////////////////////////////////////////////////// 00692 void RenderAttrib:: 00693 fillin(DatagramIterator &scan, BamReader *manager) { 00694 TypedWritable::fillin(scan, manager); 00695 manager->register_change_this(change_this, this); 00696 }