Panda3D

internalName.cxx

00001 // Filename: internalName.cxx
00002 // Created by: masad (15Jul04)
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 "pandabase.h"
00016 #include "internalName.h"
00017 #include "datagram.h"
00018 #include "datagramIterator.h"
00019 #include "bamReader.h"
00020 #include "preparedGraphicsObjects.h"
00021 
00022 PT(InternalName) InternalName::_root;
00023 PT(InternalName) InternalName::_error;
00024 PT(InternalName) InternalName::_default;
00025 PT(InternalName) InternalName::_vertex;
00026 PT(InternalName) InternalName::_normal;
00027 PT(InternalName) InternalName::_tangent;
00028 PT(InternalName) InternalName::_binormal;
00029 PT(InternalName) InternalName::_texcoord;
00030 PT(InternalName) InternalName::_color;
00031 PT(InternalName) InternalName::_rotate;
00032 PT(InternalName) InternalName::_size;
00033 PT(InternalName) InternalName::_aspect_ratio;
00034 PT(InternalName) InternalName::_transform_blend;
00035 PT(InternalName) InternalName::_transform_weight;
00036 PT(InternalName) InternalName::_transform_index;
00037 PT(InternalName) InternalName::_index;
00038 PT(InternalName) InternalName::_world;
00039 PT(InternalName) InternalName::_camera;
00040 PT(InternalName) InternalName::_model;
00041 PT(InternalName) InternalName::_view;
00042 
00043 TypeHandle InternalName::_type_handle;
00044 TypeHandle InternalName::_texcoord_type_handle;
00045 
00046 ////////////////////////////////////////////////////////////////////
00047 //     Function: InternalName::Constructor
00048 //       Access: Private
00049 //  Description: Use make() to make a new InternalName instance.
00050 ////////////////////////////////////////////////////////////////////
00051 InternalName::
00052 InternalName(InternalName *parent, const string &basename) :
00053   _parent(parent),
00054   _basename(basename)
00055 {
00056 }
00057 
00058 ////////////////////////////////////////////////////////////////////
00059 //     Function: InternalName::Destructor
00060 //       Access: Published, Virtual
00061 //  Description:
00062 ////////////////////////////////////////////////////////////////////
00063 InternalName::
00064 ~InternalName() {
00065 #ifndef NDEBUG
00066   if (_parent != (const InternalName *)NULL) {
00067     // unref() should have removed us from our parent's table already.
00068     LightMutexHolder holder(_parent->_name_table_lock);
00069     NameTable::iterator ni = _parent->_name_table.find(_basename);
00070     nassertv(ni == _parent->_name_table.end());
00071   }
00072 #endif
00073 }
00074 
00075 ////////////////////////////////////////////////////////////////////
00076 //     Function: InternalName::unref
00077 //       Access: Published, Virtual
00078 //  Description: This method overrides ReferenceCount::unref() to
00079 //               clear the pointer from its parent's table when
00080 //               its reference count goes to zero.
00081 ////////////////////////////////////////////////////////////////////
00082 bool InternalName::
00083 unref() const {
00084   if (_parent == (const InternalName *)NULL) {
00085     // No parent; no problem.  This is the root InternalName.
00086     // Actually, this probably shouldn't be destructing, but I guess
00087     // it might at application shutdown.
00088     return TypedWritableReferenceCount::unref();
00089   }
00090 
00091   LightMutexHolder holder(_parent->_name_table_lock);
00092 
00093   if (ReferenceCount::unref()) {
00094     return true;
00095   }
00096 
00097   // The reference count has just reached zero.
00098   NameTable::iterator ni = _parent->_name_table.find(_basename);
00099   nassertr(ni != _parent->_name_table.end(), false);
00100   _parent->_name_table.erase(ni);
00101 
00102   return false;
00103 }
00104 
00105 ////////////////////////////////////////////////////////////////////
00106 //     Function: InternalName::append
00107 //       Access: Published
00108 //  Description: Constructs a new InternalName based on this name,
00109 //               with the indicated string following it.  This is a
00110 //               cheaper way to construct a hierarchical name than
00111 //               InternalName::make(parent->get_name() + ".basename").
00112 ////////////////////////////////////////////////////////////////////
00113 PT(InternalName) InternalName::
00114 append(const string &name) {
00115   test_ref_count_integrity();
00116 
00117   if (name.empty()) {
00118     return this;
00119   }
00120 
00121   size_t dot = name.rfind('.');
00122   if (dot != string::npos) {
00123     return append(name.substr(0, dot))->append(name.substr(dot + 1));
00124   }
00125 
00126   LightMutexHolder holder(_name_table_lock);
00127 
00128   NameTable::iterator ni = _name_table.find(name);
00129   if (ni != _name_table.end()) {
00130     return (*ni).second;
00131   }
00132 
00133   InternalName *internal_name = new InternalName(this, name);
00134   _name_table[name] = internal_name;
00135   return internal_name;
00136 }
00137 
00138 ////////////////////////////////////////////////////////////////////
00139 //     Function: InternalName::get_name
00140 //       Access: Published
00141 //  Description: Returns the complete name represented by the
00142 //               InternalName and all of its parents.
00143 ////////////////////////////////////////////////////////////////////
00144 string InternalName::
00145 get_name() const {
00146   if (_parent == get_root()) {
00147     return _basename;
00148 
00149   } else if (_parent == (InternalName *)NULL) {
00150     return string();
00151 
00152   } else {
00153     return _parent->get_name() + "." + _basename;
00154   }
00155 }
00156 
00157 ////////////////////////////////////////////////////////////////////
00158 //     Function: InternalName::find_ancestor
00159 //       Access: Published
00160 //  Description: Returns the index of the ancestor with the indicated
00161 //               basename, or -1 if no ancestor has that basename.
00162 //               Returns 0 if this name has the basename.
00163 //
00164 //               This index value may be passed to get_ancestor() or
00165 //               get_net_basename() to retrieve more information about
00166 //               the indicated name.
00167 ////////////////////////////////////////////////////////////////////
00168 int InternalName::
00169 find_ancestor(const string &basename) const {
00170   test_ref_count_integrity();
00171 
00172   if (_basename == basename) {
00173     return 0;
00174 
00175   } else if (_parent != (InternalName *)NULL) {
00176     int index = _parent->find_ancestor(basename);
00177     if (index >= 0) {
00178       return index + 1;
00179     }
00180   }
00181 
00182   return -1;
00183 }
00184 
00185 ////////////////////////////////////////////////////////////////////
00186 //     Function: InternalName::get_ancestor
00187 //       Access: Published
00188 //  Description: Returns the ancestor with the indicated index number.
00189 //               0 is this name itself, 1 is the name's parent, 2 is
00190 //               the parent's parent, and so on.  If there are not
00191 //               enough ancestors, returns the root InternalName.
00192 ////////////////////////////////////////////////////////////////////
00193 const InternalName *InternalName::
00194 get_ancestor(int n) const {
00195   test_ref_count_integrity();
00196 
00197   if (n == 0) {
00198     return this;
00199 
00200   } else if (_parent != (InternalName *)NULL) {
00201     return _parent->get_ancestor(n - 1);
00202 
00203   } else {
00204     return get_root();
00205   } 
00206 }
00207 
00208 ////////////////////////////////////////////////////////////////////
00209 //     Function: InternalName::get_top
00210 //       Access: Published
00211 //  Description: Returns the oldest ancestor in the InternalName's
00212 //               chain, not counting the root.  This will be the first
00213 //               name in the string, e.g. "texcoord.foo.bar" will
00214 //               return the InternalName "texcoord".
00215 ////////////////////////////////////////////////////////////////////
00216 const InternalName *InternalName::
00217 get_top() const {
00218   test_ref_count_integrity();
00219 
00220   if (_parent != (InternalName *)NULL && _parent != get_root()) {
00221     return _parent->get_top();
00222   }
00223   return this;
00224 }
00225 
00226 ////////////////////////////////////////////////////////////////////
00227 //     Function: InternalName::get_net_basename
00228 //       Access: Published
00229 //  Description: Returns the basename of this name prefixed by the
00230 //               indicated number of ancestors.  0 is this name's
00231 //               basename, 1 is parent.basename, 2 is
00232 //               grandparent.parent.basename, and so on.
00233 ////////////////////////////////////////////////////////////////////
00234 string InternalName::
00235 get_net_basename(int n) const {
00236   if (n < 0) {
00237     return "";
00238 
00239   } else if (n == 0) {
00240     return _basename;
00241 
00242   } else if (_parent != (InternalName *)NULL && _parent != get_root()) {
00243     return _parent->get_net_basename(n - 1) + "." + _basename;
00244 
00245   } else {
00246     return _basename;
00247   } 
00248 }
00249 
00250 ////////////////////////////////////////////////////////////////////
00251 //     Function: InternalName::output
00252 //       Access: Published
00253 //  Description: 
00254 ////////////////////////////////////////////////////////////////////
00255 void InternalName::
00256 output(ostream &out) const {
00257   if (_parent == get_root()) {
00258     out << _basename;
00259 
00260   } else if (_parent == (InternalName *)NULL) {
00261     out << "(root)";
00262 
00263   } else {
00264     _parent->output(out);
00265     out << '.' << _basename;
00266   }
00267 }
00268 
00269 ////////////////////////////////////////////////////////////////////
00270 //     Function: InternalName::register_with_read_factory
00271 //       Access: Public, Static
00272 //  Description: Factory method to generate a InternalName object
00273 ////////////////////////////////////////////////////////////////////
00274 void InternalName::
00275 register_with_read_factory() {
00276   BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
00277   BamReader::get_factory()->register_factory(_texcoord_type_handle, make_texcoord_from_bam);
00278 }
00279 
00280 ////////////////////////////////////////////////////////////////////
00281 //     Function: InternalName::finalize
00282 //       Access: Public, Virtual
00283 //  Description: Called by the BamReader to perform any final actions
00284 //               needed for setting up the object after all objects
00285 //               have been read and all pointers have been completed.
00286 ////////////////////////////////////////////////////////////////////
00287 void InternalName::
00288 finalize(BamReader *) {
00289   // Unref the pointer that we explicitly reffed in make_from_bam().
00290   unref();
00291 
00292   // We should never get back to zero after unreffing our own count,
00293   // because we expect to have been stored in a pointer somewhere.  If
00294   // we do get to zero, it's a memory leak; the way to avoid this is
00295   // to call unref_delete() above instead of unref(), but this is
00296   // dangerous to do from within a virtual function.
00297   nassertv(get_ref_count() != 0);
00298 }
00299 
00300 ////////////////////////////////////////////////////////////////////
00301 //     Function: InternalName::make
00302 //       Access: Published, Static
00303 //  Description: Make using a string and an integer.  Concatenates
00304 //               the two.
00305 ////////////////////////////////////////////////////////////////////
00306 PT(InternalName) InternalName::
00307 make(const string &name, int index) {
00308   std::ostringstream full;
00309   full << name << index;
00310   return make(full.str());
00311 }
00312 
00313 ////////////////////////////////////////////////////////////////////
00314 //     Function: InternalName::make_from_bam
00315 //       Access: Protected, Static
00316 //  Description: This function is called by the BamReader's factory
00317 //               when a new object of type InternalName is encountered
00318 //               in the Bam file.  It should create the InternalName
00319 //               and extract its information from the file.
00320 ////////////////////////////////////////////////////////////////////
00321 TypedWritable *InternalName::
00322 make_from_bam(const FactoryParams &params) {
00323   // The process of making a InternalName is slightly
00324   // different than making other Writable objects.
00325   // That is because all creation of InternalNames should
00326   // be done through the make() constructor.
00327   DatagramIterator scan;
00328   BamReader *manager;
00329 
00330   parse_params(params, scan, manager);
00331 
00332   // The name is the only thing written to the data stream.
00333   string name = scan.get_string();
00334 
00335   // Make a new InternalName with that name (or get the previous one
00336   // if there is one already).
00337   PT(InternalName) me = make(name);
00338 
00339   // But now we have a problem, since we have to hold the reference
00340   // count and there's no way to return a TypedWritable while still
00341   // holding the reference count!  We work around this by explicitly
00342   // upping the count, and also setting a finalize() callback to down
00343   // it later.
00344   me->ref();
00345   manager->register_finalize(me);
00346   
00347   return me.p();
00348 }
00349 
00350 ////////////////////////////////////////////////////////////////////
00351 //     Function: InternalName::make_texcoord_from_bam
00352 //       Access: Protected, Static
00353 //  Description: This is a temporary method; it exists only to support
00354 //               old bam files (4.11 through 4.17) generated before we
00355 //               renamed this class from TexCoordName to InternalName.
00356 ////////////////////////////////////////////////////////////////////
00357 TypedWritable *InternalName::
00358 make_texcoord_from_bam(const FactoryParams &params) {
00359   DatagramIterator scan;
00360   BamReader *manager;
00361   parse_params(params, scan, manager);
00362 
00363   string name = scan.get_string();
00364   PT(InternalName) me;
00365   if (name == "default") {
00366     me = get_texcoord();
00367   } else {
00368     me = get_texcoord_name(name);
00369   }
00370 
00371   me->ref();
00372   manager->register_finalize(me);
00373   
00374   return me.p();
00375 }
00376 
00377 ////////////////////////////////////////////////////////////////////
00378 //     Function: InternalName::write_datagram
00379 //       Access: Public
00380 //  Description: Function to write the important information in
00381 //               the particular object to a Datagram
00382 ////////////////////////////////////////////////////////////////////
00383 void InternalName::
00384 write_datagram(BamWriter *manager, Datagram &me) {
00385   me.add_string(get_name());
00386 }
00387 
 All Classes Functions Variables Enumerations