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