Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/renderState.cxx

Go to the documentation of this file.
00001 // Filename: renderState.cxx
00002 // Created by:  drose (21Feb02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "renderState.h"
00020 #include "transparencyAttrib.h"
00021 #include "cullBinAttrib.h"
00022 #include "cullBinManager.h"
00023 #include "fogAttrib.h"
00024 #include "transparencyAttrib.h"
00025 #include "config_pgraph.h"
00026 #include "bamReader.h"
00027 #include "bamWriter.h"
00028 #include "datagramIterator.h"
00029 #include "indent.h"
00030 #include "compareTo.h"
00031 
00032 RenderState::States *RenderState::_states = NULL;
00033 CPT(RenderState) RenderState::_empty_state;
00034 TypeHandle RenderState::_type_handle;
00035 
00036 
00037 ////////////////////////////////////////////////////////////////////
00038 //     Function: RenderState::Constructor
00039 //       Access: Protected
00040 //  Description: Actually, this could be a private constructor, since
00041 //               no one inherits from RenderState, but gcc gives us a
00042 //               spurious warning if all constructors are private.
00043 ////////////////////////////////////////////////////////////////////
00044 RenderState::
00045 RenderState() {
00046   if (_states == (States *)NULL) {
00047     // Make sure the global _states map is allocated.  This only has
00048     // to be done once.  We could make this map static, but then we
00049     // run into problems if anyone creates a RenderState object at
00050     // static init time; it also seems to cause problems when the
00051     // Panda shared library is unloaded at application exit time.
00052     _states = new States;
00053   }
00054   _saved_entry = _states->end();
00055   _self_compose = (RenderState *)NULL;
00056   _flags = 0;
00057 }
00058 
00059 ////////////////////////////////////////////////////////////////////
00060 //     Function: RenderState::Copy Constructor
00061 //       Access: Private
00062 //  Description: RenderStates are not meant to be copied.
00063 ////////////////////////////////////////////////////////////////////
00064 RenderState::
00065 RenderState(const RenderState &) {
00066   nassertv(false);
00067 }
00068 
00069 ////////////////////////////////////////////////////////////////////
00070 //     Function: RenderState::Copy Assignment Operator
00071 //       Access: Private
00072 //  Description: RenderStates are not meant to be copied.
00073 ////////////////////////////////////////////////////////////////////
00074 void RenderState::
00075 operator = (const RenderState &) {
00076   nassertv(false);
00077 }
00078 
00079 ////////////////////////////////////////////////////////////////////
00080 //     Function: RenderState::Destructor
00081 //       Access: Public, Virtual
00082 //  Description: The destructor is responsible for removing the
00083 //               RenderState from the global set if it is there.
00084 ////////////////////////////////////////////////////////////////////
00085 RenderState::
00086 ~RenderState() {
00087   // We'd better not call the destructor twice on a particular object.
00088   nassertv(!is_destructing());
00089   set_destructing();
00090 
00091   if (_saved_entry != _states->end()) {
00092     nassertv(_states->find(this) == _saved_entry);
00093     _states->erase(_saved_entry);
00094     _saved_entry = _states->end();
00095   }
00096 
00097   // Now make sure we clean up all other floating pointers to the
00098   // RenderState.  These may be scattered around in the various
00099   // CompositionCaches from other RenderState objects.
00100 
00101   // Fortunately, since we added CompositionCache records in pairs, we
00102   // know exactly the set of RenderState objects that have us in their
00103   // cache: it's the same set of RenderState objects that we have in
00104   // our own cache.
00105 
00106   // We do need to put considerable thought into this loop, because as
00107   // we clear out cache entries we'll cause other RenderState
00108   // objects to destruct, which could cause things to get pulled out
00109   // of our own _composition_cache map.  We want to allow this (so
00110   // that we don't encounter any just-destructed pointers in our
00111   // cache), but we don't want to get bitten by this cascading effect.
00112   // Instead of walking through the map from beginning to end,
00113   // therefore, we just pull out the first one each time, and erase
00114   // it.
00115 
00116   // There are lots of ways to do this loop wrong.  Be very careful if
00117   // you need to modify it for any reason.
00118   while (!_composition_cache.empty()) {
00119     CompositionCache::iterator ci = _composition_cache.begin();
00120 
00121     // It is possible that the "other" RenderState object is
00122     // currently within its own destructor.  We therefore can't use a
00123     // PT() to hold its pointer; that could end up calling its
00124     // destructor twice.  Fortunately, we don't need to hold its
00125     // reference count to ensure it doesn't destruct while we process
00126     // this loop; as long as we ensure that no *other* RenderState
00127     // objects destruct, there will be no reason for that one to.
00128     RenderState *other = (RenderState *)(*ci).first;
00129 
00130     // We should never have a reflexive entry in this map.  If we
00131     // do, something got screwed up elsewhere.
00132     nassertv(other != this);
00133 
00134     // We hold a copy of the composition result to ensure that the
00135     // result RenderState object (if there is one) doesn't
00136     // destruct.
00137     Composition comp = (*ci).second;
00138 
00139     // Now we can remove the element from our cache.  We do this now,
00140     // rather than later, before any other RenderState objects have
00141     // had a chance to destruct, so we are confident that our iterator
00142     // is still valid.
00143     _composition_cache.erase(ci);
00144 
00145     CompositionCache::iterator oci = other->_composition_cache.find(this);
00146 
00147     // We may or may not still be listed in the other's cache (it
00148     // might be halfway through pulling entries out, from within its
00149     // own destructor).
00150     if (oci != other->_composition_cache.end()) {
00151       // Hold a copy of the other composition result, too.
00152       Composition ocomp = (*oci).second;
00153       
00154       // Now we're holding a reference count to both computed
00155       // results, so no objects will be tempted to destruct while we
00156       // erase the other cache entry.
00157       other->_composition_cache.erase(oci);
00158     }
00159 
00160     // It's finally safe to let our held pointers go away.  This may
00161     // have cascading effects as other RenderState objects are
00162     // destructed, but there will be no harm done if they destruct
00163     // now.
00164   }
00165 
00166   // A similar bit of code for the invert cache.
00167   while (!_invert_composition_cache.empty()) {
00168     CompositionCache::iterator ci = _invert_composition_cache.begin();
00169     RenderState *other = (RenderState *)(*ci).first;
00170     nassertv(other != this);
00171     Composition comp = (*ci).second;
00172     _invert_composition_cache.erase(ci);
00173     CompositionCache::iterator oci = 
00174       other->_invert_composition_cache.find(this);
00175     if (oci != other->_invert_composition_cache.end()) {
00176       Composition ocomp = (*oci).second;
00177       other->_invert_composition_cache.erase(oci);
00178     }
00179   }
00180 
00181   // Also, if we called compose(this) at some point and the return
00182   // value was something other than this, we need to decrement the
00183   // associated reference count.
00184   if (_self_compose != (RenderState *)NULL && _self_compose != this) {
00185     unref_delete((RenderState *)_self_compose);
00186   }
00187 }
00188 
00189 ////////////////////////////////////////////////////////////////////
00190 //     Function: RenderState::operator <
00191 //       Access: Public
00192 //  Description: Provides an arbitrary ordering among all unique
00193 //               RenderStates, so we can store the essentially
00194 //               different ones in a big set and throw away the rest.
00195 //
00196 //               This method is not needed outside of the RenderState
00197 //               class because all equivalent RenderState objects are
00198 //               guaranteed to share the same pointer; thus, a pointer
00199 //               comparison is always sufficient.
00200 ////////////////////////////////////////////////////////////////////
00201 bool RenderState::
00202 operator < (const RenderState &other) const {
00203   // We must compare all the properties of the attributes, not just
00204   // the type; thus, we compare them one at a time using compare_to().
00205   return lexicographical_compare(_attributes.begin(), _attributes.end(),
00206                                  other._attributes.begin(), other._attributes.end(),
00207                                  CompareTo<Attribute>());
00208 }
00209 
00210 
00211 ////////////////////////////////////////////////////////////////////
00212 //     Function: RenderState::find_attrib
00213 //       Access: Published
00214 //  Description: Searches for an attribute with the indicated type in
00215 //               the state, and returns its index if it is found, or
00216 //               -1 if it is not.
00217 ////////////////////////////////////////////////////////////////////
00218 int RenderState::
00219 find_attrib(TypeHandle type) const {
00220   Attributes::const_iterator ai = _attributes.find(Attribute(type));
00221   if (ai == _attributes.end()) {
00222     return -1;
00223   }
00224   return ai - _attributes.begin();
00225 }
00226 
00227 ////////////////////////////////////////////////////////////////////
00228 //     Function: RenderState::make_empty
00229 //       Access: Published, Static
00230 //  Description: Returns a RenderState with no attributes set.
00231 ////////////////////////////////////////////////////////////////////
00232 CPT(RenderState) RenderState::
00233 make_empty() {
00234   // The empty state is asked for so often, we make it a special case
00235   // and store a pointer forever once we find it the first time.
00236   if (_empty_state == (RenderState *)NULL) {
00237     RenderState *state = new RenderState;
00238     _empty_state = return_new(state);
00239   }
00240 
00241   return _empty_state;
00242 }
00243 
00244 ////////////////////////////////////////////////////////////////////
00245 //     Function: RenderState::make
00246 //       Access: Published, Static
00247 //  Description: Returns a RenderState with one attribute set.
00248 ////////////////////////////////////////////////////////////////////
00249 CPT(RenderState) RenderState::
00250 make(const RenderAttrib *attrib, int override) {
00251   RenderState *state = new RenderState;
00252   state->_attributes.reserve(1);
00253   state->_attributes.insert(Attribute(attrib, override));
00254   return return_new(state);
00255 }
00256 
00257 ////////////////////////////////////////////////////////////////////
00258 //     Function: RenderState::make
00259 //       Access: Published, Static
00260 //  Description: Returns a RenderState with two attributes set.
00261 ////////////////////////////////////////////////////////////////////
00262 CPT(RenderState) RenderState::
00263 make(const RenderAttrib *attrib1,
00264      const RenderAttrib *attrib2, int override) {
00265   RenderState *state = new RenderState;
00266   state->_attributes.reserve(2);
00267   state->_attributes.push_back(Attribute(attrib1, override));
00268   state->_attributes.push_back(Attribute(attrib2, override));
00269   state->_attributes.sort();
00270   return return_new(state);
00271 }
00272 
00273 ////////////////////////////////////////////////////////////////////
00274 //     Function: RenderState::make
00275 //       Access: Published, Static
00276 //  Description: Returns a RenderState with three attributes set.
00277 ////////////////////////////////////////////////////////////////////
00278 CPT(RenderState) RenderState::
00279 make(const RenderAttrib *attrib1,
00280      const RenderAttrib *attrib2,
00281      const RenderAttrib *attrib3, int override) {
00282   RenderState *state = new RenderState;
00283   state->_attributes.reserve(3);
00284   state->_attributes.push_back(Attribute(attrib1, override));
00285   state->_attributes.push_back(Attribute(attrib2, override));
00286   state->_attributes.push_back(Attribute(attrib3, override));
00287   state->_attributes.sort();
00288   return return_new(state);
00289 }
00290 
00291 ////////////////////////////////////////////////////////////////////
00292 //     Function: RenderState::make
00293 //       Access: Published, Static
00294 //  Description: Returns a RenderState with four attributes set.
00295 ////////////////////////////////////////////////////////////////////
00296 CPT(RenderState) RenderState::
00297 make(const RenderAttrib *attrib1,
00298      const RenderAttrib *attrib2,
00299      const RenderAttrib *attrib3,
00300      const RenderAttrib *attrib4, int override) {
00301   RenderState *state = new RenderState;
00302   state->_attributes.reserve(4);
00303   state->_attributes.push_back(Attribute(attrib1, override));
00304   state->_attributes.push_back(Attribute(attrib2, override));
00305   state->_attributes.push_back(Attribute(attrib3, override));
00306   state->_attributes.push_back(Attribute(attrib4, override));
00307   state->_attributes.sort();
00308   return return_new(state);
00309 }
00310 
00311 ////////////////////////////////////////////////////////////////////
00312 //     Function: RenderState::make
00313 //       Access: Published, Static
00314 //  Description: Returns a RenderState with n attributes set.
00315 ////////////////////////////////////////////////////////////////////
00316 CPT(RenderState) RenderState::
00317 make(const RenderAttrib * const *attrib, int num_attribs, int override) {
00318   RenderState *state = new RenderState;
00319   state->_attributes.reserve(num_attribs);
00320   for (int i = 0; i < num_attribs; i++) {
00321     state->_attributes.push_back(Attribute(attrib[i], override));
00322   }
00323   return return_new(state);
00324 }
00325 
00326 ////////////////////////////////////////////////////////////////////
00327 //     Function: RenderState::compose
00328 //       Access: Published
00329 //  Description: Returns a new RenderState object that represents the
00330 //               composition of this state with the other state.
00331 //
00332 //               The result of this operation is cached, and will be
00333 //               retained as long as both this RenderState object and
00334 //               the other RenderState object continue to exist.
00335 //               Should one of them destruct, the cached entry will be
00336 //               removed, and its pointer will be allowed to destruct
00337 //               as well.
00338 ////////////////////////////////////////////////////////////////////
00339 CPT(RenderState) RenderState::
00340 compose(const RenderState *other) const {
00341   // This method isn't strictly const, because it updates the cache,
00342   // but we pretend that it is because it's only a cache which is
00343   // transparent to the rest of the interface.
00344 
00345   // We handle empty state (identity) as a trivial special case.
00346   if (is_empty()) {
00347     return other;
00348   }
00349   if (other->is_empty()) {
00350     return this;
00351   }
00352 
00353   if (other == this) {
00354     // compose(this) has to be handled as a special case, because the
00355     // caching problem is so different.
00356     if (_self_compose != (RenderState *)NULL) {
00357       return _self_compose;
00358     }
00359     CPT(RenderState) result = do_compose(this);
00360     ((RenderState *)this)->_self_compose = result;
00361 
00362     if (result != (const RenderState *)this) {
00363       // If the result of compose(this) is something other than this,
00364       // explicitly increment the reference count.  We have to be sure
00365       // to decrement it again later, in our destructor.
00366       _self_compose->ref();
00367 
00368       // (If the result was just this again, we still store the
00369       // result, but we don't increment the reference count, since
00370       // that would be a self-referential leak.  What a mess this is.)
00371     }
00372     return _self_compose;
00373   }
00374 
00375   // Is this composition already cached?
00376   CompositionCache::const_iterator ci = _composition_cache.find(other);
00377   if (ci != _composition_cache.end()) {
00378     const Composition &comp = (*ci).second;
00379     if (comp._result == (const RenderState *)NULL) {
00380       // Well, it wasn't cached already, but we already had an entry
00381       // (probably created for the reverse direction), so use the same
00382       // entry to store the new result.
00383       ((Composition &)comp)._result = do_compose(other);
00384     }
00385     // Here's the cache!
00386     return comp._result;
00387   }
00388 
00389   // We need to make a new cache entry, both in this object and in the
00390   // other object.  We make both records so the other RenderState
00391   // object will know to delete the entry from this object when it
00392   // destructs, and vice-versa.
00393 
00394   // The cache entry in this object is the only one that indicates the
00395   // result; the other will be NULL for now.
00396   CPT(RenderState) result = do_compose(other);
00397 
00398   ((RenderState *)other)->_composition_cache[this]._result = NULL;
00399   ((RenderState *)this)->_composition_cache[other]._result = result;
00400 
00401   return result;
00402 }
00403 
00404 ////////////////////////////////////////////////////////////////////
00405 //     Function: RenderState::invert_compose
00406 //       Access: Published
00407 //  Description: Returns a new RenderState object that represents the
00408 //               composition of this state's inverse with the other
00409 //               state.
00410 //
00411 //               This is similar to compose(), but is particularly
00412 //               useful for computing the relative state of a node as
00413 //               viewed from some other node.
00414 ////////////////////////////////////////////////////////////////////
00415 CPT(RenderState) RenderState::
00416 invert_compose(const RenderState *other) const {
00417   // This method isn't strictly const, because it updates the cache,
00418   // but we pretend that it is because it's only a cache which is
00419   // transparent to the rest of the interface.
00420 
00421   // We handle empty state (identity) as a trivial special case.
00422   if (is_empty()) {
00423     return other;
00424   }
00425   // Unlike compose(), the case of other->is_empty() is not quite as
00426   // trivial for invert_compose().
00427 
00428   if (other == this) {
00429     // a->invert_compose(a) always produces identity.
00430     return make_empty();
00431   }
00432 
00433   // Is this composition already cached?
00434   CompositionCache::const_iterator ci = _invert_composition_cache.find(other);
00435   if (ci != _invert_composition_cache.end()) {
00436     const Composition &comp = (*ci).second;
00437     if (comp._result == (const RenderState *)NULL) {
00438       // Well, it wasn't cached already, but we already had an entry
00439       // (probably created for the reverse direction), so use the same
00440       // entry to store the new result.
00441       ((Composition &)comp)._result = do_invert_compose(other);
00442     }
00443     // Here's the cache!
00444     return comp._result;
00445   }
00446 
00447   // We need to make a new cache entry, both in this object and in the
00448   // other object.  We make both records so the other RenderState
00449   // object will know to delete the entry from this object when it
00450   // destructs, and vice-versa.
00451 
00452   // The cache entry in this object is the only one that indicates the
00453   // result; the other will be NULL for now.
00454   CPT(RenderState) result = do_invert_compose(other);
00455 
00456   ((RenderState *)other)->_invert_composition_cache[this]._result = NULL;
00457   ((RenderState *)this)->_invert_composition_cache[other]._result = result;
00458 
00459   return result;
00460 }
00461 
00462 ////////////////////////////////////////////////////////////////////
00463 //     Function: RenderState::add_attrib
00464 //       Access: Published
00465 //  Description: Returns a new RenderState object that represents the
00466 //               same as the source state, with the new RenderAttrib
00467 //               added.  If there is already a RenderAttrib with the
00468 //               same type, it is replaced.
00469 ////////////////////////////////////////////////////////////////////
00470 CPT(RenderState) RenderState::
00471 add_attrib(const RenderAttrib *attrib, int override) const {
00472   RenderState *new_state = new RenderState;
00473   back_insert_iterator<Attributes> result = 
00474     back_inserter(new_state->_attributes);
00475 
00476   Attribute new_attribute(attrib, override);
00477   Attributes::const_iterator ai = _attributes.begin();
00478 
00479   while (ai != _attributes.end() && (*ai) < new_attribute) {
00480     *result = *ai;
00481     ++ai;
00482     ++result;
00483   }
00484   *result = new_attribute;
00485   ++result;
00486 
00487   if (ai != _attributes.end() && !(new_attribute < (*ai))) {
00488     // At this point we know:
00489     // !((*ai) < new_attribute) && !(new_attribute < (*ai))
00490     // which means (*ai) == new_attribute--so we should leave it out,
00491     // to avoid duplicating attributes in the set.
00492     ++ai;
00493   }
00494 
00495   while (ai != _attributes.end()) {
00496     *result = *ai;
00497     ++ai;
00498     ++result;
00499   }
00500 
00501   return return_new(new_state);
00502 }
00503 
00504 ////////////////////////////////////////////////////////////////////
00505 //     Function: RenderState::remove_attrib
00506 //       Access: Published
00507 //  Description: Returns a new RenderState object that represents the
00508 //               same as the source state, with the indicated
00509 //               RenderAttrib removed.
00510 ////////////////////////////////////////////////////////////////////
00511 CPT(RenderState) RenderState::
00512 remove_attrib(TypeHandle type) const {
00513   RenderState *new_state = new RenderState;
00514   back_insert_iterator<Attributes> result = 
00515     back_inserter(new_state->_attributes);
00516 
00517   Attributes::const_iterator ai = _attributes.begin();
00518 
00519   while (ai != _attributes.end()) {
00520     if ((*ai)._type != type) {
00521       *result = *ai;
00522       ++result;
00523     }
00524     ++ai;
00525   }
00526 
00527   return return_new(new_state);
00528 }
00529 
00530 ////////////////////////////////////////////////////////////////////
00531 //     Function: RenderState::remove_attrib
00532 //       Access: Published
00533 //  Description: Returns a new RenderState object that represents the
00534 //               same as the source state, with all attributes'
00535 //               override values incremented (or decremented, if
00536 //               negative) by the indicated amount.  If the override
00537 //               would drop below zero, it is set to zero.
00538 ////////////////////////////////////////////////////////////////////
00539 CPT(RenderState) RenderState::
00540 adjust_all_priorities(int adjustment) const {
00541   RenderState *new_state = new RenderState;
00542   new_state->_attributes.reserve(_attributes.size());
00543 
00544   Attributes::const_iterator ai;
00545   for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
00546     Attribute attrib = *ai;
00547     attrib._override = max(attrib._override + adjustment, 0);
00548     new_state->_attributes.push_back(attrib);
00549   }
00550 
00551   return return_new(new_state);
00552 }
00553 
00554 ////////////////////////////////////////////////////////////////////
00555 //     Function: RenderState::get_attrib
00556 //       Access: Published, Virtual
00557 //  Description: Looks for a RenderAttrib of the indicated type in the
00558 //               state, and returns it if it is found, or NULL if it
00559 //               is not.
00560 ////////////////////////////////////////////////////////////////////
00561 const RenderAttrib *RenderState::
00562 get_attrib(TypeHandle type) const {
00563   Attributes::const_iterator ai;
00564   ai = _attributes.find(Attribute(type));
00565   if (ai != _attributes.end()) {
00566     return (*ai)._attrib;
00567   }
00568   return NULL;
00569 }
00570 
00571 ////////////////////////////////////////////////////////////////////
00572 //     Function: RenderState::output
00573 //       Access: Published, Virtual
00574 //  Description: 
00575 ////////////////////////////////////////////////////////////////////
00576 void RenderState::
00577 output(ostream &out) const {
00578   out << "S:";
00579   if (_attributes.empty()) {
00580     out << "(empty)";
00581 
00582   } else {
00583     Attributes::const_iterator ai = _attributes.begin();
00584     out << "(" << (*ai)._type;
00585     ++ai;
00586     while (ai != _attributes.end()) {
00587       out << " " << (*ai)._type;
00588       ++ai;
00589     }
00590     out << ")";
00591   }
00592 }
00593 
00594 ////////////////////////////////////////////////////////////////////
00595 //     Function: RenderState::write
00596 //       Access: Published, Virtual
00597 //  Description: 
00598 ////////////////////////////////////////////////////////////////////
00599 void RenderState::
00600 write(ostream &out, int indent_level) const {
00601   indent(out, indent_level) << _attributes.size() << " attribs:\n";
00602   Attributes::const_iterator ai;
00603   for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
00604     const Attribute &attribute = (*ai);
00605     attribute._attrib->write(out, indent_level + 2);
00606   }
00607 }
00608 
00609 ////////////////////////////////////////////////////////////////////
00610 //     Function: RenderState::get_max_priority
00611 //       Access: Published, Static
00612 //  Description: Returns the maximum priority number (sometimes called
00613 //               override) that may be set on any node.  This may or
00614 //               may not be enforced, but the scene graph code assumes
00615 //               that no priority numbers will be larger than this,
00616 //               and some effects may not work properly if you use a
00617 //               larger number.
00618 ////////////////////////////////////////////////////////////////////
00619 int RenderState::
00620 get_max_priority() {
00621   return 1000000000;
00622 }
00623 
00624 ////////////////////////////////////////////////////////////////////
00625 //     Function: RenderState::get_num_states
00626 //       Access: Published, Static
00627 //  Description: Returns the total number of unique RenderState
00628 //               objects allocated in the world.  This will go up and
00629 //               down during normal operations.
00630 ////////////////////////////////////////////////////////////////////
00631 int RenderState::
00632 get_num_states() {
00633   if (_states == (States *)NULL) {
00634     return 0;
00635   }
00636   return _states->size();
00637 }
00638 
00639 ////////////////////////////////////////////////////////////////////
00640 //     Function: RenderState::get_num_unused_states
00641 //       Access: Published, Static
00642 //  Description: Returns the total number of RenderState objects that
00643 //               have been allocated but have no references outside of
00644 //               the internal RenderState map.
00645 ////////////////////////////////////////////////////////////////////
00646 int RenderState::
00647 get_num_unused_states() {
00648   if (_states == (States *)NULL) {
00649     return 0;
00650   }
00651 
00652   int num_unused = 0;
00653 
00654   // First, we need to count the number of times each RenderState
00655   // object is recorded in the cache.
00656   typedef pmap<const RenderState *, int> StateCount;
00657   StateCount state_count;
00658 
00659   States::iterator si;
00660   for (si = _states->begin(); si != _states->end(); ++si) {
00661     const RenderState *state = (*si);
00662 
00663     CompositionCache::const_iterator ci;
00664     for (ci = state->_composition_cache.begin();
00665          ci != state->_composition_cache.end();
00666          ++ci) {
00667       const RenderState *result = (*ci).second._result;
00668       if (result != (const RenderState *)NULL) {
00669         // Here's a RenderState that's recorded in the cache.
00670         // Count it.
00671         pair<StateCount::iterator, bool> ir =
00672           state_count.insert(StateCount::value_type(result, 1));
00673         if (!ir.second) {
00674           // If the above insert operation fails, then it's already in
00675           // the cache; increment its value.
00676           (*(ir.first)).second++;
00677         }
00678       }
00679     }
00680     for (ci = state->_invert_composition_cache.begin();
00681          ci != state->_invert_composition_cache.end();
00682          ++ci) {
00683       const RenderState *result = (*ci).second._result;
00684       if (result != (const RenderState *)NULL) {
00685         pair<StateCount::iterator, bool> ir =
00686           state_count.insert(StateCount::value_type(result, 1));
00687         if (!ir.second) {
00688           (*(ir.first)).second++;
00689         }
00690       }
00691     }
00692 
00693     // Finally, check the self_compose field, which might be reference
00694     // counted too.
00695     if (state->_self_compose != (const RenderState *)NULL &&
00696         state->_self_compose != state) {
00697       const RenderState *result = state->_self_compose;
00698       if (result != (const RenderState *)NULL) {
00699         pair<StateCount::iterator, bool> ir =
00700           state_count.insert(StateCount::value_type(result, 1));
00701         if (!ir.second) {
00702           (*(ir.first)).second++;
00703         }
00704       }
00705     }
00706 
00707   }
00708 
00709   // Now that we have the appearance count of each RenderState
00710   // object, we can tell which ones are unreferenced outside of the
00711   // RenderState cache, by comparing these to the reference counts.
00712   StateCount::iterator sci;
00713   for (sci = state_count.begin(); sci != state_count.end(); ++sci) {
00714     const RenderState *state = (*sci).first;
00715     int count = (*sci).second;
00716     nassertr(count <= state->get_ref_count(), num_unused);
00717     if (count == state->get_ref_count()) {
00718       num_unused++;
00719     }
00720   }
00721 
00722   return num_unused;
00723 }
00724 
00725 ////////////////////////////////////////////////////////////////////
00726 //     Function: RenderState::clear_cache
00727 //       Access: Published, Static
00728 //  Description: Empties the cache of composed RenderStates.  This
00729 //               makes every RenderState forget what results when
00730 //               it is composed with other RenderStates.
00731 //
00732 //               This will eliminate any RenderState objects that
00733 //               have been allocated but have no references outside of
00734 //               the internal RenderState map.  It will not
00735 //               eliminate RenderState objects that are still in
00736 //               use.
00737 //
00738 //               Normally, RenderState objects will remove
00739 //               themselves from the interal map when their reference
00740 //               counts go to 0, but since circular references are
00741 //               possible there may be some cycles that cannot remove
00742 //               themselves.  Calling this function from time to time
00743 //               will ensure there is no wasteful memory leakage, but
00744 //               calling it too often may result in decreased
00745 //               performance as the cache is forced to be recomputed.
00746 //
00747 //               The return value is the number of RenderStates
00748 //               freed by this operation.
00749 ////////////////////////////////////////////////////////////////////
00750 int RenderState::
00751 clear_cache() {
00752   if (_states == (States *)NULL) {
00753     return 0;
00754   }
00755 
00756   int orig_size = _states->size();
00757 
00758   // First, we need to copy the entire set of states to a temporary
00759   // vector, reference-counting each object.  That way we can walk
00760   // through the copy, without fear of dereferencing (and deleting)
00761   // the objects in the map as we go.
00762   {
00763     typedef pvector< CPT(RenderState) > TempStates;
00764     TempStates temp_states;
00765     temp_states.reserve(orig_size);
00766 
00767     copy(_states->begin(), _states->end(),
00768          back_inserter(temp_states));
00769 
00770     // Now it's safe to walk through the list, destroying the cache
00771     // within each object as we go.  Nothing will be destructed till
00772     // we're done.
00773     TempStates::iterator ti;
00774     for (ti = temp_states.begin(); ti != temp_states.end(); ++ti) {
00775       RenderState *state = (RenderState *)(*ti).p();
00776       state->_composition_cache.clear();
00777       state->_invert_composition_cache.clear();
00778       if (state->_self_compose != (RenderState *)NULL && 
00779           state->_self_compose != state) {
00780         unref_delete((RenderState *)state->_self_compose);
00781         state->_self_compose = (RenderState *)NULL;
00782       }
00783     }
00784 
00785     // Once this block closes and the temp_states object goes away,
00786     // all the destruction will begin.  Anything whose reference was
00787     // held only within the various objects' caches will go away.
00788   }
00789 
00790   int new_size = _states->size();
00791   return orig_size - new_size;
00792 }
00793 
00794 ////////////////////////////////////////////////////////////////////
00795 //     Function: RenderState::issue_delta_modify
00796 //       Access: Public
00797 //  Description: This is intended to be called only from
00798 //               GraphicsStateGuardian::modify_state().  It calls
00799 //               issue() for each attribute given in the other state
00800 //               that differs from the current state (which is assumed
00801 //               to represent the GSG's current state).  Returns the
00802 //               RenderState representing the newly composed result.
00803 ////////////////////////////////////////////////////////////////////
00804 CPT(RenderState) RenderState::
00805 issue_delta_modify(const RenderState *other, 
00806                    GraphicsStateGuardianBase *gsg) const {
00807   if (other->is_empty()) {
00808     // If the other state is empty, that's a trivial special case.
00809     return this;
00810   }
00811 
00812   // First, build a new Attributes member that represents the union of
00813   // this one and that one.
00814   Attributes::const_iterator ai = _attributes.begin();
00815   Attributes::const_iterator bi = other->_attributes.begin();
00816 
00817   // Create a new RenderState that will hold the result.
00818   RenderState *new_state = new RenderState;
00819   back_insert_iterator<Attributes> result = 
00820     back_inserter(new_state->_attributes);
00821 
00822   bool any_changed = false;
00823 
00824   while (ai != _attributes.end() && bi != other->_attributes.end()) {
00825     if ((*ai) < (*bi)) {
00826       // Here is an attribute that we have in the original, which is
00827       // not present in the secondary.  Leave it alone.
00828       *result = *ai;
00829       ++ai;
00830       ++result;
00831     } else if ((*bi) < (*ai)) {
00832       // Here is a new attribute we have in the secondary, that was
00833       // not present in the original.  Issue the new one, and save it.
00834       (*bi)._attrib->issue(gsg);
00835       *result = *bi;
00836       ++bi;
00837       ++result;
00838       any_changed = true;
00839     } else {
00840       // Here is an attribute we have in both.  Issue the new one if
00841       // it's different, and save it.
00842       if ((*ai)._attrib != (*bi)._attrib) {
00843         any_changed = true;
00844         (*bi)._attrib->issue(gsg);
00845       }
00846       *result = *bi;
00847       ++ai;
00848       ++bi;
00849       ++result;
00850     }
00851   }
00852 
00853   while (ai != _attributes.end()) {
00854     *result = *ai;
00855     ++ai;
00856     ++result;
00857   }
00858 
00859   while (bi != other->_attributes.end()) {
00860     (*bi)._attrib->issue(gsg);
00861     *result = *bi;
00862     ++bi;
00863     ++result;
00864     any_changed = true;
00865   }
00866 
00867   if (any_changed) {
00868     return return_new(new_state);
00869   } else {
00870     delete new_state;
00871     return this;
00872   }
00873 }
00874 
00875 ////////////////////////////////////////////////////////////////////
00876 //     Function: RenderState::issue_delta_set
00877 //       Access: Public
00878 //  Description: This is intended to be called only from
00879 //               GraphicsStateGuardian::set_state().  It calls issue()
00880 //               for each attribute given in the other state that
00881 //               differs from the current state (which is assumed to
00882 //               represent the GSG's current state).  Returns the
00883 //               RenderState representing the newly composed result
00884 //               (which will be the same as other).
00885 ////////////////////////////////////////////////////////////////////
00886 CPT(RenderState) RenderState::
00887 issue_delta_set(const RenderState *other, 
00888                 GraphicsStateGuardianBase *gsg) const {
00889   if (other == this) {
00890     // If the state doesn't change, that's a trivial special case.
00891     return other;
00892   }
00893 
00894   Attributes::const_iterator ai = _attributes.begin();
00895   Attributes::const_iterator bi = other->_attributes.begin();
00896 
00897   while (ai != _attributes.end() && bi != other->_attributes.end()) {
00898     if ((*ai) < (*bi)) {
00899       // Here is an attribute that we have in the original, which is
00900       // not present in the secondary.  Issue the default state instead.
00901       (*ai)._attrib->make_default()->issue(gsg);
00902       ++ai;
00903 
00904     } else if ((*bi) < (*ai)) {
00905       // Here is a new attribute we have in the secondary, that was
00906       // not present in the original.  Issue the new one.
00907       (*bi)._attrib->issue(gsg);
00908       ++bi;
00909 
00910     } else {
00911       // Here is an attribute we have in both.  Issue the new one if
00912       // it's different.
00913       if ((*ai)._attrib != (*bi)._attrib) {
00914         (*bi)._attrib->issue(gsg);
00915       }
00916       ++ai;
00917       ++bi;
00918     }
00919   }
00920 
00921   while (ai != _attributes.end()) {
00922     (*ai)._attrib->make_default()->issue(gsg);
00923     ++ai;
00924   }
00925 
00926   while (bi != other->_attributes.end()) {
00927     (*bi)._attrib->issue(gsg);
00928     ++bi;
00929   }
00930 
00931   return other;
00932 }
00933 
00934 ////////////////////////////////////////////////////////////////////
00935 //     Function: RenderState::bin_removed
00936 //       Access: Public, Static
00937 //  Description: Intended to be called by
00938 //               CullBinManager::remove_bin(), this informs all the
00939 //               RenderStates in the world to remove the indicated
00940 //               bin_index from their cache if it has been cached.
00941 ////////////////////////////////////////////////////////////////////
00942 void RenderState::
00943 bin_removed(int bin_index) {
00944   // Do something here.
00945   nassertv(false);
00946 }
00947 
00948 ////////////////////////////////////////////////////////////////////
00949 //     Function: RenderState::return_new
00950 //       Access: Private, Static
00951 //  Description: This function is used to share a common RenderState
00952 //               pointer for all equivalent RenderState objects.
00953 //
00954 //               See the similar logic in RenderAttrib.  The idea is
00955 //               to create a new RenderState object and pass it
00956 //               through this function, which will share the pointer
00957 //               with a previously-created RenderState object if it is
00958 //               equivalent.
00959 ////////////////////////////////////////////////////////////////////
00960 CPT(RenderState) RenderState::
00961 return_new(RenderState *state) {
00962   nassertr(state != (RenderState *)NULL, state);
00963 
00964   // This should be a newly allocated pointer, not one that was used
00965   // for anything else.
00966   nassertr(state->_saved_entry == _states->end(), state);
00967 
00968   // Save the state in a local PointerTo so that it will be freed at
00969   // the end of this function if no one else uses it.
00970   CPT(RenderState) pt_state = state;
00971 
00972   pair<States::iterator, bool> result = _states->insert(state);
00973 
00974   if (result.second) {
00975     // The state was inserted; save the iterator and return the
00976     // input state.
00977     state->_saved_entry = result.first;
00978     return pt_state;
00979   }
00980   
00981   // The state was not inserted; there must be an equivalent one
00982   // already in the set.  Return that one.
00983   return *(result.first);
00984 }
00985 
00986 ////////////////////////////////////////////////////////////////////
00987 //     Function: RenderState::do_compose
00988 //       Access: Private
00989 //  Description: The private implemention of compose(); this actually
00990 //               composes two RenderStates, without bothering with the
00991 //               cache.
00992 ////////////////////////////////////////////////////////////////////
00993 CPT(RenderState) RenderState::
00994 do_compose(const RenderState *other) const {
00995   // First, build a new Attributes member that represents the union of
00996   // this one and that one.
00997   Attributes::const_iterator ai = _attributes.begin();
00998   Attributes::const_iterator bi = other->_attributes.begin();
00999 
01000   // Create a new RenderState that will hold the result.
01001   RenderState *new_state = new RenderState;
01002   back_insert_iterator<Attributes> result = 
01003     back_inserter(new_state->_attributes);
01004 
01005   while (ai != _attributes.end() && bi != other->_attributes.end()) {
01006     if ((*ai) < (*bi)) {
01007       // Here is an attribute that we have in the original, which is
01008       // not present in the secondary.
01009       *result = *ai;
01010       ++ai;
01011       ++result;
01012     } else if ((*bi) < (*ai)) {
01013       // Here is a new attribute we have in the secondary, that was
01014       // not present in the original.
01015       *result = *bi;
01016       ++bi;
01017       ++result;
01018     } else {
01019       // Here is an attribute we have in both.  Does one override the
01020       // other?
01021       const Attribute &a = (*ai);
01022       const Attribute &b = (*bi);
01023       if (a._override < b._override) {
01024         // B overrides.
01025         *result = *bi;
01026 
01027       } else if (b._override < a._override) {
01028         // A overrides.
01029         *result = *ai;
01030 
01031       } else {
01032         // No, they're equivalent, so compose them.
01033         *result = Attribute(a._attrib->compose(b._attrib), b._override);
01034       }
01035       ++ai;
01036       ++bi;
01037       ++result;
01038     }
01039   }
01040 
01041   while (ai != _attributes.end()) {
01042     *result = *ai;
01043     ++ai;
01044     ++result;
01045   }
01046 
01047   while (bi != other->_attributes.end()) {
01048     *result = *bi;
01049     ++bi;
01050     ++result;
01051   }
01052 
01053   return return_new(new_state);
01054 }
01055 
01056 ////////////////////////////////////////////////////////////////////
01057 //     Function: RenderState::do_invert_compose
01058 //       Access: Private
01059 //  Description: The private implemention of invert_compose().
01060 ////////////////////////////////////////////////////////////////////
01061 CPT(RenderState) RenderState::
01062 do_invert_compose(const RenderState *other) const {
01063   Attributes::const_iterator ai = _attributes.begin();
01064   Attributes::const_iterator bi = other->_attributes.begin();
01065 
01066   // Create a new RenderState that will hold the result.
01067   RenderState *new_state = new RenderState;
01068   back_insert_iterator<Attributes> result = 
01069     back_inserter(new_state->_attributes);
01070 
01071   while (ai != _attributes.end() && bi != other->_attributes.end()) {
01072     if ((*ai) < (*bi)) {
01073       // Here is an attribute that we have in the original, which is
01074       // not present in the secondary.
01075       *result = Attribute((*ai)._attrib->invert_compose((*ai)._attrib->make_default()), 0);
01076       ++ai;
01077       ++result;
01078     } else if ((*bi) < (*ai)) {
01079       // Here is a new attribute we have in the secondary, that was
01080       // not present in the original.
01081       *result = *bi;
01082       ++bi;
01083       ++result;
01084     } else {
01085       // Here is an attribute we have in both.  In this case, override
01086       // is meaningless.
01087       *result = Attribute((*ai)._attrib->invert_compose((*bi)._attrib), (*bi)._override);
01088       ++ai;
01089       ++bi;
01090       ++result;
01091     }
01092   }
01093 
01094   while (ai != _attributes.end()) {
01095     *result = Attribute((*ai)._attrib->invert_compose((*ai)._attrib->make_default()), 0);
01096     ++ai;
01097     ++result;
01098   }
01099 
01100   while (bi != other->_attributes.end()) {
01101     *result = *bi;
01102     ++bi;
01103     ++result;
01104   }
01105 
01106   return return_new(new_state);
01107 }
01108 
01109 ////////////////////////////////////////////////////////////////////
01110 //     Function: RenderState::determine_bin_index
01111 //       Access: Private
01112 //  Description: This is the private implementation of
01113 //               get_bin_index() and get_draw_order().
01114 ////////////////////////////////////////////////////////////////////
01115 void RenderState::
01116 determine_bin_index() {
01117   string bin_name;
01118   _draw_order = 0;
01119 
01120   const CullBinAttrib *bin_attrib = get_bin();
01121   if (bin_attrib != (const CullBinAttrib *)NULL) {
01122     bin_name = bin_attrib->get_bin_name();
01123     _draw_order = bin_attrib->get_draw_order();
01124   }
01125 
01126   if (bin_name.empty()) {
01127     // No explicit bin is specified; put in the in the default bin,
01128     // either opaque or transparent, based on the transparency
01129     // setting.
01130     bin_name = "opaque";
01131     const TransparencyAttrib *trans = get_transparency();
01132     if (trans != (const TransparencyAttrib *)NULL) {
01133       switch (trans->get_mode()) {
01134       case TransparencyAttrib::M_alpha:
01135       case TransparencyAttrib::M_alpha_sorted:
01136       case TransparencyAttrib::M_dual:
01137         // These transparency modes require special back-to-front sorting.
01138         bin_name = "transparent";
01139         break;
01140 
01141       default:
01142         break;
01143       }
01144     }
01145   }
01146 
01147   CullBinManager *bin_manager = CullBinManager::get_global_ptr();
01148   _bin_index = bin_manager->find_bin(bin_name);
01149   if (_bin_index == -1) {
01150     pgraph_cat.warning()
01151       << "No bin named " << bin_name << "; creating default bin.\n";
01152     _bin_index = bin_manager->add_bin(bin_name, CullBinManager::BT_unsorted, 0);
01153   }
01154   _flags |= F_checked_bin_index;
01155 }
01156 
01157 ////////////////////////////////////////////////////////////////////
01158 //     Function: RenderState::determine_fog
01159 //       Access: Private
01160 //  Description: This is the private implementation of get_fog().
01161 ////////////////////////////////////////////////////////////////////
01162 void RenderState::
01163 determine_fog() {
01164   const RenderAttrib *attrib = get_attrib(FogAttrib::get_class_type());
01165   _fog = (const FogAttrib *)NULL;
01166   if (attrib != (const RenderAttrib *)NULL) {
01167     _fog = DCAST(FogAttrib, attrib);
01168   }
01169   _flags |= F_checked_fog;
01170 }
01171 
01172 ////////////////////////////////////////////////////////////////////
01173 //     Function: RenderState::determine_bin
01174 //       Access: Private
01175 //  Description: This is the private implementation of get_bin().
01176 ////////////////////////////////////////////////////////////////////
01177 void RenderState::
01178 determine_bin() {
01179   const RenderAttrib *attrib = get_attrib(CullBinAttrib::get_class_type());
01180   _bin = (const CullBinAttrib *)NULL;
01181   if (attrib != (const RenderAttrib *)NULL) {
01182     _bin = DCAST(CullBinAttrib, attrib);
01183   }
01184   _flags |= F_checked_bin;
01185 }
01186 
01187 ////////////////////////////////////////////////////////////////////
01188 //     Function: RenderState::determine_transparency
01189 //       Access: Private
01190 //  Description: This is the private implementation of get_transparency().
01191 ////////////////////////////////////////////////////////////////////
01192 void RenderState::
01193 determine_transparency() {
01194   const RenderAttrib *attrib = 
01195     get_attrib(TransparencyAttrib::get_class_type());
01196   _transparency = (const TransparencyAttrib *)NULL;
01197   if (attrib != (const RenderAttrib *)NULL) {
01198     _transparency = DCAST(TransparencyAttrib, attrib);
01199   }
01200   _flags |= F_checked_transparency;
01201 }
01202 
01203 ////////////////////////////////////////////////////////////////////
01204 //     Function: RenderState::register_with_read_factory
01205 //       Access: Public, Static
01206 //  Description: Tells the BamReader how to create objects of type
01207 //               RenderState.
01208 ////////////////////////////////////////////////////////////////////
01209 void RenderState::
01210 register_with_read_factory() {
01211   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
01212 }
01213 
01214 ////////////////////////////////////////////////////////////////////
01215 //     Function: RenderState::write_datagram
01216 //       Access: Public, Virtual
01217 //  Description: Writes the contents of this object to the datagram
01218 //               for shipping out to a Bam file.
01219 ////////////////////////////////////////////////////////////////////
01220 void RenderState::
01221 write_datagram(BamWriter *manager, Datagram &dg) {
01222   TypedWritable::write_datagram(manager, dg);
01223 
01224   int num_attribs = _attributes.size();
01225   nassertv(num_attribs == (int)(PN_uint16)num_attribs);
01226   dg.add_uint16(num_attribs);
01227 
01228   // **** We should smarten up the writing of the override
01229   // number--most of the time these will all be zero.
01230   Attributes::const_iterator ai;
01231   for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
01232     const Attribute &attribute = (*ai);
01233 
01234     manager->write_pointer(dg, attribute._attrib);
01235     dg.add_int32(attribute._override);
01236   }
01237 }
01238 
01239 ////////////////////////////////////////////////////////////////////
01240 //     Function: RenderState::complete_pointers
01241 //       Access: Public, Virtual
01242 //  Description: Receives an array of pointers, one for each time
01243 //               manager->read_pointer() was called in fillin().
01244 //               Returns the number of pointers processed.
01245 ////////////////////////////////////////////////////////////////////
01246 int RenderState::
01247 complete_pointers(TypedWritable **p_list, BamReader *manager) {
01248   int pi = TypedWritable::complete_pointers(p_list, manager);
01249 
01250   // Get the attribute pointers.
01251   Attributes::iterator ai;
01252   for (ai = _attributes.begin(); ai != _attributes.end(); ++ai) {
01253     Attribute &attribute = (*ai);
01254 
01255     attribute._attrib = DCAST(RenderAttrib, p_list[pi++]);
01256     nassertr(attribute._attrib != (RenderAttrib *)NULL, pi);
01257     attribute._type = attribute._attrib->get_type();
01258   }
01259 
01260   // Now make sure the array is properly sorted.  (It won't
01261   // necessarily preserve its correct sort after being read from bam,
01262   // because the sort is based on TypeHandle indices and raw pointers,
01263   // both of which can change from session to session.)
01264   _attributes.sort();
01265 
01266   return pi;
01267 }
01268 
01269 ////////////////////////////////////////////////////////////////////
01270 //     Function: RenderState::change_this
01271 //       Access: Public, Static
01272 //  Description: Called immediately after complete_pointers(), this
01273 //               gives the object a chance to adjust its own pointer
01274 //               if desired.  Most objects don't change pointers after
01275 //               completion, but some need to.
01276 //
01277 //               Once this function has been called, the old pointer
01278 //               will no longer be accessed.
01279 ////////////////////////////////////////////////////////////////////
01280 TypedWritable *RenderState::
01281 change_this(TypedWritable *old_ptr, BamReader *manager) {
01282   // First, uniquify the pointer.
01283   RenderState *state = DCAST(RenderState, old_ptr);
01284   CPT(RenderState) pointer = return_new(state);
01285 
01286   // But now we have a problem, since we have to hold the reference
01287   // count and there's no way to return a TypedWritable while still
01288   // holding the reference count!  We work around this by explicitly
01289   // upping the count, and also setting a finalize() callback to down
01290   // it later.
01291   if (pointer == state) {
01292     pointer->ref();
01293     manager->register_finalize(state);
01294   }
01295   
01296   // We have to cast the pointer back to non-const, because the bam
01297   // reader expects that.
01298   return (RenderState *)pointer.p();
01299 }
01300 
01301 ////////////////////////////////////////////////////////////////////
01302 //     Function: RenderState::finalize
01303 //       Access: Public, Virtual
01304 //  Description: Called by the BamReader to perform any final actions
01305 //               needed for setting up the object after all objects
01306 //               have been read and all pointers have been completed.
01307 ////////////////////////////////////////////////////////////////////
01308 void RenderState::
01309 finalize() {
01310   // Unref the pointer that we explicitly reffed in make_from_bam().
01311   unref();
01312 
01313   // We should never get back to zero after unreffing our own count,
01314   // because we expect to have been stored in a pointer somewhere.  If
01315   // we do get to zero, it's a memory leak; the way to avoid this is
01316   // to call unref_delete() above instead of unref(), but this is
01317   // dangerous to do from within a virtual function.
01318   nassertv(get_ref_count() != 0);
01319 }
01320 
01321 ////////////////////////////////////////////////////////////////////
01322 //     Function: RenderState::make_from_bam
01323 //       Access: Protected, Static
01324 //  Description: This function is called by the BamReader's factory
01325 //               when a new object of type RenderState is encountered
01326 //               in the Bam file.  It should create the RenderState
01327 //               and extract its information from the file.
01328 ////////////////////////////////////////////////////////////////////
01329 TypedWritable *RenderState::
01330 make_from_bam(const FactoryParams &params) {
01331   RenderState *state = new RenderState;
01332   DatagramIterator scan;
01333   BamReader *manager;
01334 
01335   parse_params(params, scan, manager);
01336   state->fillin(scan, manager);
01337   manager->register_change_this(change_this, state);
01338 
01339   return state;
01340 }
01341 
01342 ////////////////////////////////////////////////////////////////////
01343 //     Function: RenderState::fillin
01344 //       Access: Protected
01345 //  Description: This internal function is called by make_from_bam to
01346 //               read in all of the relevant data from the BamFile for
01347 //               the new RenderState.
01348 ////////////////////////////////////////////////////////////////////
01349 void RenderState::
01350 fillin(DatagramIterator &scan, BamReader *manager) {
01351   TypedWritable::fillin(scan, manager);
01352 
01353   int num_attribs = scan.get_uint16();
01354 
01355   // Push back a NULL pointer for each attribute for now, until we get
01356   // the actual list of pointers later in complete_pointers().
01357   _attributes.reserve(num_attribs);
01358   for (int i = 0; i < num_attribs; i++) {
01359     manager->read_pointer(scan);
01360     int override = scan.get_int32();
01361     _attributes.push_back(Attribute(override));
01362   }
01363 }

Generated on Fri May 2 00:42:18 2003 for Panda by doxygen1.3