Panda3D

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 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 &params) {
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 }
 All Classes Functions Variables Enumerations