00001 // Filename: renderEffect.cxx 00002 // Created by: drose (14Mar02) 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 "renderEffect.h" 00020 #include "bamReader.h" 00021 #include "indent.h" 00022 00023 RenderEffect::Effects RenderEffect::_effects; 00024 TypeHandle RenderEffect::_type_handle; 00025 00026 //////////////////////////////////////////////////////////////////// 00027 // Function: RenderEffect::Constructor 00028 // Access: Protected 00029 // Description: 00030 //////////////////////////////////////////////////////////////////// 00031 RenderEffect:: 00032 RenderEffect() { 00033 _saved_entry = _effects.end(); 00034 } 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: RenderEffect::Copy Constructor 00038 // Access: Private 00039 // Description: RenderEffects are not meant to be copied. 00040 //////////////////////////////////////////////////////////////////// 00041 RenderEffect:: 00042 RenderEffect(const RenderEffect &) { 00043 nassertv(false); 00044 } 00045 00046 //////////////////////////////////////////////////////////////////// 00047 // Function: RenderEffect::Copy Assignment Operator 00048 // Access: Private 00049 // Description: RenderEffects are not meant to be copied. 00050 //////////////////////////////////////////////////////////////////// 00051 void RenderEffect:: 00052 operator = (const RenderEffect &) { 00053 nassertv(false); 00054 } 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: RenderEffect::Destructor 00058 // Access: Public, Virtual 00059 // Description: The destructor is responsible for removing the 00060 // RenderEffect from the global set if it is there. 00061 //////////////////////////////////////////////////////////////////// 00062 RenderEffect:: 00063 ~RenderEffect() { 00064 if (_saved_entry != _effects.end()) { 00065 // We cannot make this assertion, because the RenderEffect has 00066 // already partially destructed--this means we cannot look up the 00067 // object in the map. In fact, the map is temporarily invalid 00068 // until we finish destructing, since we screwed up the ordering 00069 // when we changed the return value of get_type(). 00070 // nassertv(_effects.find(this) == _saved_entry); 00071 00072 // Note: this isn't thread-safe, because once the derived class 00073 // destructor exits and before this destructor completes, the map 00074 // is invalid, and other threads may inadvertently attempt to read 00075 // the invalid map. To make it thread-safe, we need to move this 00076 // functionality to a separate method, that is to be called from 00077 // *each* derived class's destructor (and then we can put the 00078 // above assert back in). 00079 _effects.erase(_saved_entry); 00080 _saved_entry = _effects.end(); 00081 } 00082 } 00083 00084 //////////////////////////////////////////////////////////////////// 00085 // Function: RenderEffect::safe_to_transform 00086 // Access: Public, Virtual 00087 // Description: Returns true if it is generally safe to transform 00088 // this particular kind of RenderEffect by calling the 00089 // xform() method, false otherwise. 00090 //////////////////////////////////////////////////////////////////// 00091 bool RenderEffect:: 00092 safe_to_transform() const { 00093 return true; 00094 } 00095 00096 //////////////////////////////////////////////////////////////////// 00097 // Function: RenderEffect::safe_to_combine 00098 // Access: Public, Virtual 00099 // Description: Returns true if this kind of effect can safely be 00100 // combined with sibling nodes that share the exact same 00101 // effect, or false if this is not a good idea. 00102 //////////////////////////////////////////////////////////////////// 00103 bool RenderEffect:: 00104 safe_to_combine() const { 00105 return true; 00106 } 00107 00108 //////////////////////////////////////////////////////////////////// 00109 // Function: RenderEffect::xform 00110 // Access: Public, Virtual 00111 // Description: Returns a new RenderEffect transformed by the 00112 // indicated matrix. 00113 //////////////////////////////////////////////////////////////////// 00114 CPT(RenderEffect) RenderEffect:: 00115 xform(const LMatrix4f &) const { 00116 return this; 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: RenderEffect::output 00121 // Access: Published, Virtual 00122 // Description: 00123 //////////////////////////////////////////////////////////////////// 00124 void RenderEffect:: 00125 output(ostream &out) const { 00126 out << get_type(); 00127 } 00128 00129 //////////////////////////////////////////////////////////////////// 00130 // Function: RenderEffect::write 00131 // Access: Published, Virtual 00132 // Description: 00133 //////////////////////////////////////////////////////////////////// 00134 void RenderEffect:: 00135 write(ostream &out, int indent_level) const { 00136 indent(out, indent_level) << *this << "\n"; 00137 } 00138 00139 //////////////////////////////////////////////////////////////////// 00140 // Function: RenderEffect::return_new 00141 // Access: Protected, Static 00142 // Description: This function is used by derived RenderEffect types 00143 // to share a common RenderEffect pointer for all 00144 // equivalent RenderEffect objects. 00145 // 00146 // The make() function of the derived type should create 00147 // a new RenderEffect and pass it through return_new(), 00148 // which will either save the pointer and return it 00149 // unchanged (if this is the first similar such object) 00150 // or delete it and return an equivalent pointer (if 00151 // there was already a similar object saved). 00152 //////////////////////////////////////////////////////////////////// 00153 CPT(RenderEffect) RenderEffect:: 00154 return_new(RenderEffect *effect) { 00155 nassertr(effect != (RenderEffect *)NULL, effect); 00156 00157 // This should be a newly allocated pointer, not one that was used 00158 // for anything else. 00159 nassertr(effect->_saved_entry == _effects.end(), effect); 00160 00161 // Save the effect in a local PointerTo so that it will be freed at 00162 // the end of this function if no one else uses it. 00163 CPT(RenderEffect) pt_effect = effect; 00164 00165 pair<Effects::iterator, bool> result = _effects.insert(effect); 00166 if (result.second) { 00167 // The effect was inserted; save the iterator and return the 00168 // input effect. 00169 effect->_saved_entry = result.first; 00170 return pt_effect; 00171 } 00172 00173 // The effect was not inserted; there must be an equivalent one 00174 // already in the set. Return that one. 00175 return *(result.first); 00176 } 00177 00178 //////////////////////////////////////////////////////////////////// 00179 // Function: RenderEffect::compare_to_impl 00180 // Access: Protected, Virtual 00181 // Description: Intended to be overridden by derived RenderEffect 00182 // types to return a unique number indicating whether 00183 // this RenderEffect is equivalent to the other one. 00184 // 00185 // This should return 0 if the two RenderEffect objects 00186 // are equivalent, a number less than zero if this one 00187 // should be sorted before the other one, and a number 00188 // greater than zero otherwise. 00189 // 00190 // This will only be called with two RenderEffect 00191 // objects whose get_type() functions return the same. 00192 //////////////////////////////////////////////////////////////////// 00193 int RenderEffect:: 00194 compare_to_impl(const RenderEffect *other) const { 00195 return 0; 00196 } 00197 00198 //////////////////////////////////////////////////////////////////// 00199 // Function: RenderEffect::write_datagram 00200 // Access: Public, Virtual 00201 // Description: Writes the contents of this object to the datagram 00202 // for shipping out to a Bam file. 00203 //////////////////////////////////////////////////////////////////// 00204 void RenderEffect:: 00205 write_datagram(BamWriter *manager, Datagram &dg) { 00206 TypedWritable::write_datagram(manager, dg); 00207 } 00208 00209 //////////////////////////////////////////////////////////////////// 00210 // Function: RenderEffect::change_this 00211 // Access: Public, Static 00212 // Description: Called immediately after complete_pointers(), this 00213 // gives the object a chance to adjust its own pointer 00214 // if desired. Most objects don't change pointers after 00215 // completion, but some need to. 00216 // 00217 // Once this function has been called, the old pointer 00218 // will no longer be accessed. 00219 //////////////////////////////////////////////////////////////////// 00220 TypedWritable *RenderEffect:: 00221 change_this(TypedWritable *old_ptr, BamReader *manager) { 00222 // First, uniquify the pointer. 00223 RenderEffect *effect = DCAST(RenderEffect, old_ptr); 00224 CPT(RenderEffect) pointer = return_new(effect); 00225 00226 // But now we have a problem, since we have to hold the reference 00227 // count and there's no way to return a TypedWritable while still 00228 // holding the reference count! We work around this by explicitly 00229 // upping the count, and also setting a finalize() callback to down 00230 // it later. 00231 if (pointer == effect) { 00232 pointer->ref(); 00233 manager->register_finalize(effect); 00234 } 00235 00236 // We have to cast the pointer back to non-const, because the bam 00237 // reader expects that. 00238 return (RenderEffect *)pointer.p(); 00239 } 00240 00241 //////////////////////////////////////////////////////////////////// 00242 // Function: RenderEffect::finalize 00243 // Access: Public, Virtual 00244 // Description: Method to ensure that any necessary clean up tasks 00245 // that have to be performed by this object are performed 00246 //////////////////////////////////////////////////////////////////// 00247 void RenderEffect:: 00248 finalize() { 00249 // Unref the pointer that we explicitly reffed in make_from_bam(). 00250 unref(); 00251 00252 // We should never get back to zero after unreffing our own count, 00253 // because we expect to have been stored in a pointer somewhere. If 00254 // we do get to zero, it's a memory leak; the way to avoid this is 00255 // to call unref_delete() above instead of unref(), but this is 00256 // dangerous to do from within a virtual function. 00257 nassertv(get_ref_count() != 0); 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: RenderEffect::fillin 00262 // Access: Protected 00263 // Description: This internal function is called by make_from_bam to 00264 // read in all of the relevant data from the BamFile for 00265 // the new RenderEffect. 00266 //////////////////////////////////////////////////////////////////// 00267 void RenderEffect:: 00268 fillin(DatagramIterator &scan, BamReader *manager) { 00269 TypedWritable::fillin(scan, manager); 00270 }