00001 // Filename: bamReader.cxx 00002 // Created by: jason (12Jun00) 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 "pandabase.h" 00020 #include "notify.h" 00021 00022 #include "bam.h" 00023 #include "bamReader.h" 00024 #include "datagramIterator.h" 00025 #include "config_util.h" 00026 #include "pipelineCyclerBase.h" 00027 00028 WritableFactory *BamReader::_factory = (WritableFactory*)0L; 00029 BamReader *const BamReader::Null = (BamReader*)0L; 00030 WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L; 00031 00032 BamReader::NewTypes BamReader::_new_types; 00033 00034 const int BamReader::_cur_major = _bam_major_ver; 00035 const int BamReader::_cur_minor = _bam_minor_ver; 00036 00037 00038 //////////////////////////////////////////////////////////////////// 00039 // Function: BamReader::Constructor 00040 // Access: Public 00041 // Description: 00042 //////////////////////////////////////////////////////////////////// 00043 BamReader:: 00044 BamReader(DatagramGenerator *generator) 00045 : _source(generator) 00046 { 00047 _num_extra_objects = 0; 00048 _now_creating = _created_objs.end(); 00049 _reading_cycler = (PipelineCyclerBase *)NULL; 00050 _pta_id = -1; 00051 } 00052 00053 00054 //////////////////////////////////////////////////////////////////// 00055 // Function: BamReader::Destructor 00056 // Access: Public 00057 // Description: 00058 //////////////////////////////////////////////////////////////////// 00059 BamReader:: 00060 ~BamReader() { 00061 } 00062 00063 //////////////////////////////////////////////////////////////////// 00064 // Function: BamReader::init 00065 // Access: Public 00066 // Description: Initializes the BamReader prior to reading any 00067 // objects from its source. This includes reading the 00068 // Bam header. 00069 // 00070 // This returns true if the BamReader successfully 00071 // initialized, false otherwise. 00072 //////////////////////////////////////////////////////////////////// 00073 bool BamReader:: 00074 init() { 00075 Datagram header; 00076 00077 if (_source->is_error()) { 00078 return false; 00079 } 00080 00081 if (!_source->get_datagram(header)) { 00082 bam_cat.error() 00083 << "Unable to read Bam header.\n"; 00084 return false; 00085 } 00086 00087 DatagramIterator scan(header); 00088 00089 _file_major = scan.get_uint16(); 00090 _file_minor = scan.get_uint16(); 00091 00092 // If the major version is different, or the minor version is 00093 // *newer*, we can't safely load the file. 00094 if (_file_major != _bam_major_ver || _file_minor > _bam_minor_ver) { 00095 bam_cat.error() 00096 << "Bam file is version " << _file_major << "." << _file_minor 00097 << ".\n"; 00098 00099 if (_bam_minor_ver == 0) { 00100 bam_cat.error() 00101 << "This program can only load version " 00102 << _bam_major_ver << ".0 bams.\n"; 00103 } else { 00104 bam_cat.error() 00105 << "This program can only load version " 00106 << _bam_major_ver << ".0 through " 00107 << _bam_major_ver << "." << _bam_minor_ver << " bams.\n"; 00108 } 00109 00110 return false; 00111 } 00112 00113 if (bam_cat.is_debug()) { 00114 bam_cat.debug() 00115 << "Bam file is version " << _file_major << "." << _file_minor 00116 << ".\n"; 00117 if (_file_minor != _bam_minor_ver) { 00118 bam_cat.debug() 00119 << "(Current version is " << _bam_major_ver << "." << _bam_minor_ver 00120 << ".)\n"; 00121 } 00122 } 00123 00124 return true; 00125 } 00126 00127 //////////////////////////////////////////////////////////////////// 00128 // Function: BamReader::read_object 00129 // Access: Public 00130 // Description: Reads a single object from the Bam file. If the 00131 // object type is known, a new object of the appropriate 00132 // type is created and returned; otherwise, NULL is 00133 // returned. NULL is also returned when the end of the 00134 // file is reached. is_eof() may be called to 00135 // differentiate between these two cases. 00136 // 00137 // This may be called repeatedly to extract out all the 00138 // objects in the Bam file, but typically (especially 00139 // for scene graph files, indicated with the .bam 00140 // extension), only one object is retrieved directly 00141 // from the Bam file: the root of the scene graph. The 00142 // remaining objects will all be retrieved recursively 00143 // by the first object. 00144 // 00145 // Note that the object returned may not yet be 00146 // complete. In particular, some of its pointers may 00147 // not be filled in; you must call resolve() to fill in 00148 // all the available pointers before you can safely use 00149 // any objects returned by read_object(). 00150 //////////////////////////////////////////////////////////////////// 00151 TypedWritable *BamReader:: 00152 read_object() { 00153 nassertr(_num_extra_objects == 0, (TypedWritable *)NULL); 00154 00155 // First, read the base object. 00156 int object_id = p_read_object(); 00157 00158 // Now that object might have included some pointers to other 00159 // objects, which may still need to be read. And those objects 00160 // might in turn require reading additional objects. Read all the 00161 // remaining objects. 00162 while (_num_extra_objects > 0) { 00163 p_read_object(); 00164 _num_extra_objects--; 00165 } 00166 00167 // Now look up the pointer of the object we read first. It should 00168 // be available now. 00169 if (object_id == 0) { 00170 if (bam_cat.is_spam()) { 00171 bam_cat.spam() 00172 << "Returning NULL\n"; 00173 } 00174 return (TypedWritable *)NULL; 00175 } 00176 00177 CreatedObjs::iterator oi = _created_objs.find(object_id); 00178 00179 if (oi == _created_objs.end()) { 00180 bam_cat.error() 00181 << "Undefined object encountered!\n"; 00182 return (TypedWritable *)NULL; 00183 00184 } else { 00185 CreatedObj &created_obj = (*oi).second; 00186 TypedWritable *object = created_obj._ptr; 00187 00188 if (bam_cat.is_spam()) { 00189 if (object != (TypedWritable *)NULL) { 00190 bam_cat.spam() 00191 << "Returning object of type " << object->get_type() << "\n"; 00192 } 00193 } 00194 if (created_obj._change_this != NULL) { 00195 bam_cat.warning() 00196 << "Returning pointer to " << object->get_type() 00197 << " that might change.\n"; 00198 } 00199 00200 return object; 00201 } 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: BamReader::resolve 00206 // Access: Public 00207 // Description: This may be called at any time during processing of 00208 // the Bam file to resolve all the known pointers so 00209 // far. It is usually called at the end of the 00210 // processing, after all objects have been read, which 00211 // is generally the best time to call it. 00212 // 00213 // This must be called at least once after reading a 00214 // particular object via get_object() in order to 00215 // validate that object. 00216 // 00217 // The return value is true if all objects have been 00218 // resolved, or false if some objects are still 00219 // outstanding (in which case you will need to call 00220 // resolve() again later). 00221 //////////////////////////////////////////////////////////////////// 00222 bool BamReader:: 00223 resolve() { 00224 bool all_completed; 00225 bool any_completed_this_pass; 00226 00227 do { 00228 all_completed = true; 00229 any_completed_this_pass = false; 00230 00231 // Walk through all the objects that still have outstanding pointers. 00232 ObjectPointers::iterator oi; 00233 oi = _object_pointers.begin(); 00234 while (oi != _object_pointers.end()) { 00235 int object_id = (*oi).first; 00236 const vector_int &pointer_ids = (*oi).second; 00237 00238 CreatedObjs::iterator ci = _created_objs.find(object_id); 00239 nassertr(ci != _created_objs.end(), false); 00240 CreatedObj &created_obj = (*ci).second; 00241 00242 TypedWritable *object_ptr = created_obj._ptr; 00243 00244 if (resolve_object_pointers(object_ptr, pointer_ids)) { 00245 // Now remove this object from the list of things that need 00246 // completion. We have to be a bit careful when deleting things 00247 // from the STL container while we are traversing it. 00248 ObjectPointers::iterator old = oi; 00249 ++oi; 00250 _object_pointers.erase(old); 00251 00252 // Does the pointer need to change? 00253 if (created_obj._change_this != NULL) { 00254 created_obj._ptr = created_obj._change_this(object_ptr, this); 00255 created_obj._change_this = NULL; 00256 } 00257 any_completed_this_pass = true; 00258 00259 } else { 00260 // Couldn't complete this object yet; it'll wait for next time. 00261 ++oi; 00262 all_completed = false; 00263 } 00264 } 00265 } while (!all_completed && any_completed_this_pass); 00266 00267 // Also do the PipelineCycler objects. We only need to try these 00268 // once, since they don't depend on each other. 00269 00270 CyclerPointers::iterator ci; 00271 ci = _cycler_pointers.begin(); 00272 while (ci != _cycler_pointers.end()) { 00273 PipelineCyclerBase *cycler = (*ci).first; 00274 const vector_int &pointer_ids = (*ci).second; 00275 00276 if (resolve_cycler_pointers(cycler, pointer_ids)) { 00277 // Now remove this cycler from the list of things that need 00278 // completion. We have to be a bit careful when deleting things 00279 // from the STL container while we are traversing it. 00280 CyclerPointers::iterator old = ci; 00281 ++ci; 00282 _cycler_pointers.erase(old); 00283 00284 } else { 00285 // Couldn't complete this cycler yet; it'll wait for next time. 00286 ++ci; 00287 all_completed = false; 00288 } 00289 } 00290 00291 if (all_completed) { 00292 finalize(); 00293 } else { 00294 // Report all the uncompleted objects for no good reason. This 00295 // will probably have to come out later when we have cases in 00296 // which some objects might legitimately be uncompleted after 00297 // calling resolve(), but for now we expect resolve() to always 00298 // succeed. 00299 ObjectPointers::const_iterator oi; 00300 for (oi = _object_pointers.begin(); 00301 oi != _object_pointers.end(); 00302 ++oi) { 00303 int object_id = (*oi).first; 00304 CreatedObjs::iterator ci = _created_objs.find(object_id); 00305 nassertr(ci != _created_objs.end(), false); 00306 CreatedObj &created_obj = (*ci).second; 00307 TypedWritable *object_ptr = created_obj._ptr; 00308 00309 bam_cat.warning() 00310 << "Unable to complete " << object_ptr->get_type() << "\n"; 00311 } 00312 } 00313 00314 return all_completed; 00315 } 00316 00317 //////////////////////////////////////////////////////////////////// 00318 // Function: BamReader::read_handle 00319 // Access: Public 00320 // Description: Reads a TypeHandle out of the Datagram. 00321 //////////////////////////////////////////////////////////////////// 00322 TypeHandle BamReader:: 00323 read_handle(DatagramIterator &scan) { 00324 // We encode TypeHandles within the Bam file by writing a unique 00325 // index number for each one to the file. When we write a 00326 // particular TypeHandle for the first time, we assign it a new 00327 // index number and then immediately follow it by its definition; 00328 // when we write the same TypeHandle on subsequent times we only 00329 // write the index number. 00330 00331 // Thus, to read a TypeHandle, we first read the index number. If 00332 // it is a number we have not yet encountered, we must then read the 00333 // definition. 00334 00335 // Here's the index number. 00336 int id = scan.get_uint16(); 00337 00338 if (id == 0) { 00339 // Index number 0 is always, by convention, TypeHandle::none(). 00340 return TypeHandle::none(); 00341 } 00342 00343 IndexMap::const_iterator mi = _index_map.find(id); 00344 if (mi != _index_map.end()) { 00345 // We've encountered this index number before, so there should be 00346 // no type definition following the id. Simply return the 00347 // TypeHandle we previously associated with the id. 00348 TypeHandle type = (*mi).second; 00349 return type; 00350 } 00351 00352 // We haven't encountered this index number before. This means it 00353 // will be immediately followed by the type definition. This 00354 // consists of the string name, followed by the list of parent 00355 // TypeHandles for this type. 00356 00357 string name = scan.get_string(); 00358 bool new_type = false; 00359 00360 TypeHandle type = TypeRegistry::ptr()->find_type(name); 00361 if (type == TypeHandle::none()) { 00362 // We've never heard of this type before! This is really an error 00363 // condition, but we'll do the best we can and declare it 00364 // on-the-fly. 00365 00366 type = TypeRegistry::ptr()->register_dynamic_type(name); 00367 bam_cat.warning() 00368 << "Bam file contains objects of unknown type: " << type << "\n"; 00369 new_type = true; 00370 _new_types.insert(type); 00371 } 00372 00373 // Now pick up the derivation information. 00374 int num_parent_classes = scan.get_uint8(); 00375 for (int i = 0; i < num_parent_classes; i++) { 00376 TypeHandle parent_type = read_handle(scan); 00377 if (new_type) { 00378 TypeRegistry::ptr()->record_derivation(type, parent_type); 00379 } else { 00380 if (type.get_parent_towards(parent_type) != parent_type) { 00381 bam_cat.warning() 00382 << "Bam file indicates a derivation of " << type 00383 << " from " << parent_type << " which is no longer true.\n"; 00384 } 00385 } 00386 } 00387 00388 bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second; 00389 nassertr(inserted, type); 00390 00391 if (bam_cat.is_spam()) { 00392 bam_cat.spam() 00393 << "Read TypeHandle for " << type << ".\n"; 00394 } 00395 00396 return type; 00397 } 00398 00399 //////////////////////////////////////////////////////////////////// 00400 // Function: BamReader::read_pointer 00401 // Access: Public 00402 // Description: The interface for reading a pointer to another object 00403 // from a Bam file. Objects reading themselves from a 00404 // Bam file should call this when they expect to read a 00405 // pointer to some other object. This function reads 00406 // whatever is stored in the bam file to represent the 00407 // pointer, and advances the datagram iterator 00408 // accordingly. 00409 // 00410 // Rather than returning a pointer immediately, this 00411 // function reads the internal pointer information from 00412 // the datagram and queues up the request. The pointer 00413 // itself may not be available until later (it may be a 00414 // pointer to an object that appears later in the Bam 00415 // file). Later, when all pointers are available, the 00416 // complete_pointers() callback function will be called 00417 // with an array of actual pointers, one for time 00418 // read_pointer() was called. It is then the calling 00419 // object's responsibilty to store these pointers in the 00420 // object properly. 00421 //////////////////////////////////////////////////////////////////// 00422 void BamReader:: 00423 read_pointer(DatagramIterator &scan) { 00424 nassertv(_now_creating != _created_objs.end()); 00425 int requestor_id = (*_now_creating).first; 00426 00427 // Read the object ID, and associate it with the requesting object. 00428 int object_id = scan.get_uint16(); 00429 00430 if (_reading_cycler == (PipelineCyclerBase *)NULL) { 00431 // This is not being read within a read_cdata() call. 00432 _object_pointers[requestor_id].push_back(object_id); 00433 } else { 00434 // This *is* being read within a read_cdata() call. 00435 _cycler_pointers[_reading_cycler].push_back(object_id); 00436 } 00437 00438 // If the object ID is zero (which indicates a NULL pointer), we 00439 // don't have to do anything else. 00440 if (object_id != 0) { 00441 if (_created_objs.count(object_id) == 0) { 00442 // If we don't already have an entry in the map for this object 00443 // ID (that is, we haven't encountered this object before), we 00444 // must remember to read the object definition later. 00445 _num_extra_objects++; 00446 } 00447 } 00448 } 00449 00450 //////////////////////////////////////////////////////////////////// 00451 // Function: BamReader::read_pointers 00452 // Access: Public 00453 // Description: A convenience function to read a contiguous list of 00454 // pointers. This is equivalent to calling 00455 // read_pointer() count times. 00456 //////////////////////////////////////////////////////////////////// 00457 void BamReader:: 00458 read_pointers(DatagramIterator &scan, int count) { 00459 for (int i = 0; i < count; i++) { 00460 read_pointer(scan); 00461 } 00462 } 00463 00464 //////////////////////////////////////////////////////////////////// 00465 // Function: BamReader::skip_pointer 00466 // Access: Public 00467 // Description: Reads and discards a pointer value from the Bam file. 00468 // This pointer will not be counted among the pointers 00469 // read for a given object, and will not be in the list 00470 // of pointers passed to complete_pointers(). 00471 //////////////////////////////////////////////////////////////////// 00472 void BamReader:: 00473 skip_pointer(DatagramIterator &scan) { 00474 scan.get_uint16(); 00475 } 00476 00477 //////////////////////////////////////////////////////////////////// 00478 // Function: BamReader::read_cdata 00479 // Access: Public 00480 // Description: Reads in the indicated CycleData object. This should 00481 // be used by classes that store some or all of their 00482 // data within a CycleData subclass, in support of 00483 // pipelining. This will call the virtual 00484 // CycleData::fillin() method to do the actual reading. 00485 //////////////////////////////////////////////////////////////////// 00486 void BamReader:: 00487 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) { 00488 PipelineCyclerBase *old_cycler = _reading_cycler; 00489 _reading_cycler = &cycler; 00490 CycleData *cdata = cycler.write(); 00491 cdata->fillin(scan, this); 00492 cycler.release_write(cdata); 00493 _reading_cycler = old_cycler; 00494 } 00495 00496 //////////////////////////////////////////////////////////////////// 00497 // Function: BamReader::register_finalize 00498 // Access: Public 00499 // Description: Should be called by an object reading itself from the 00500 // Bam file to indicate that this particular object 00501 // would like to receive the finalize() callback when 00502 // all the objects and pointers in the Bam file are 00503 // completely read. 00504 // 00505 // This provides a hook for objects (like Characters) 00506 // that need to do any additional finalization work 00507 // after all of their related pointers are guaranteed to 00508 // be filled in. 00509 //////////////////////////////////////////////////////////////////// 00510 void BamReader:: 00511 register_finalize(TypedWritable *whom) { 00512 if (whom == TypedWritable::Null) { 00513 bam_cat.error() << "Can't register a null pointer to finalize!" << endl; 00514 return; 00515 } 00516 _finalize_list.insert(whom); 00517 } 00518 00519 //////////////////////////////////////////////////////////////////// 00520 // Function: BamReader::register_change_this 00521 // Access: Public 00522 // Description: Called by an object reading itself from the bam file 00523 // to indicate that the object pointer that will be 00524 // returned is temporary, and will eventually need to be 00525 // replaced with another pointer. 00526 // 00527 // The supplied function pointer will later be called on 00528 // the object, immediately after complete_pointers() is 00529 // called; it should return the new and final pointer. 00530 // 00531 // We use a static function pointer instead of a virtual 00532 // function (as in finalize()), to allow the function to 00533 // destruct the old pointer if necessary. (It is 00534 // invalid to destruct the this pointer within a virtual 00535 // function.) 00536 //////////////////////////////////////////////////////////////////// 00537 void BamReader:: 00538 register_change_this(ChangeThisFunc func, TypedWritable *object) { 00539 nassertv(_now_creating != _created_objs.end()); 00540 CreatedObj &created_obj = (*_now_creating).second; 00541 00542 #ifndef NDEBUG 00543 // Sanity check the pointer--it should always be the same pointer 00544 // after we set it the first time. 00545 if (created_obj._ptr == (TypedWritable *)NULL) { 00546 created_obj._ptr = object; 00547 } else { 00548 // We've previously assigned this pointer, and we should have 00549 // assigned it to the same this pointer we have now. 00550 nassertv(created_obj._ptr == object); 00551 } 00552 #endif // NDEBUG 00553 00554 created_obj._change_this = func; 00555 } 00556 00557 //////////////////////////////////////////////////////////////////// 00558 // Function: BamReader::finalize_now 00559 // Access: Public 00560 // Description: Forces the finalization of a particular object. This 00561 // may be called by any of the objects during 00562 // finalization, to guarantee finalization ordering 00563 // where it is important. 00564 //////////////////////////////////////////////////////////////////// 00565 void BamReader:: 00566 finalize_now(TypedWritable *whom) { 00567 nassertv(whom != (TypedWritable *)NULL); 00568 00569 Finalize::iterator fi = _finalize_list.find(whom); 00570 if (fi != _finalize_list.end()) { 00571 _finalize_list.erase(fi); 00572 whom->finalize(); 00573 } 00574 } 00575 00576 //////////////////////////////////////////////////////////////////// 00577 // Function: BamReader::get_pta 00578 // Access: Public 00579 // Description: This function works in conjection with 00580 // register_pta(), below, to read a PointerToArray (PTA) 00581 // from the Bam file, and unify references to the same 00582 // PTA. 00583 // 00584 // The first time get_pta() encounters a particular PTA, 00585 // it will return NULL. This is the indication that the 00586 // caller should then read in the data associated with 00587 // the PTA, and subsequently call register_pta() with 00588 // the address of the filled-in array. 00589 // 00590 // The next time (and all subsequent times) that 00591 // get_pta() encounters this same PTA, it will return 00592 // the pointer that was passed with register_pta(). 00593 // 00594 // Also see the READ_PTA() macro, which consolidates all 00595 // the work that must be done to read a PTA. 00596 //////////////////////////////////////////////////////////////////// 00597 void *BamReader:: 00598 get_pta(DatagramIterator &scan) { 00599 nassertr(_pta_id == -1, (void *)NULL); 00600 int id = scan.get_uint16(); 00601 00602 if (id == 0) { 00603 // As always, a 0 ID indicates a NULL pointer. The caller will 00604 // not be able to differentiate this case from that of a 00605 // previously-read pointer, but that's OK because the next data in 00606 // the Bam file is the length of the array, which will be 00607 // zero--indicating an empty or NULL array. 00608 return (void *)NULL; 00609 } 00610 00611 PTAMap::iterator pi = _pta_map.find(id); 00612 if (pi == _pta_map.end()) { 00613 // This is the first time we've encountered this particular ID, 00614 // meaning we need to read the data now and register it. 00615 _pta_id = id; 00616 return (void *)NULL; 00617 } 00618 00619 return (*pi).second; 00620 } 00621 00622 //////////////////////////////////////////////////////////////////// 00623 // Function: BamReader::register_pta 00624 // Access: Public 00625 // Description: The second part of read_pta(), this should be called 00626 // with the pointer to the array that was read in after 00627 // read_pta() returned NULL. This associates the 00628 // pointer with the ID that was previously read, so that 00629 // future calls to read_pta() will return the same 00630 // pointer. 00631 // 00632 // Also see the READ_PTA() macro, which consolidates all 00633 // the work that must be done to read a PTA. 00634 //////////////////////////////////////////////////////////////////// 00635 void BamReader:: 00636 register_pta(void *ptr) { 00637 if (_pta_id != -1) { 00638 bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second; 00639 _pta_id = -1; 00640 nassertv(inserted); 00641 } 00642 } 00643 00644 00645 00646 //////////////////////////////////////////////////////////////////// 00647 // Function: BamReader::p_read_object 00648 // Access: Private 00649 // Description: The private implementation of read_object(), this 00650 // reads an object from the file and returns its object 00651 // ID. 00652 //////////////////////////////////////////////////////////////////// 00653 int BamReader:: 00654 p_read_object() { 00655 Datagram packet; 00656 00657 if (_source->is_error()) { 00658 return 0; 00659 } 00660 00661 // First, read a datagram for the object. 00662 if (!_source->get_datagram(packet)) { 00663 // When we run out of datagrams, we're at the end of the file. 00664 00665 if (bam_cat.is_debug()) { 00666 bam_cat.debug() 00667 << "Reached end of bam source.\n"; 00668 } 00669 return 0; 00670 } 00671 00672 // Now extract the object definition from the datagram. 00673 DatagramIterator scan(packet); 00674 00675 // An object definition in a Bam file consists of a TypeHandle 00676 // definition, defining the object's type, followed by an object ID 00677 // index, defining the particular instance (e.g. pointer) of this 00678 // object. 00679 00680 TypeHandle type = read_handle(scan); 00681 int object_id = scan.get_uint16(); 00682 00683 // There are two cases. Either this is a new object definition, or 00684 // this is a reference to an object that was previously defined. 00685 00686 // We use the TypeHandle to differentiate these two cases. By 00687 // convention, we write a TypeHandle::none() to the Bam file when we 00688 // are writing a reference to a previously-defined object, but we 00689 // write the object's actual type when we are writing its definition 00690 // right now. 00691 00692 // Therefore, if the type is TypeHandle::none(), then we must have 00693 // already read in and created the object (although its pointers may 00694 // not be fully instantiated yet). On the other hand, if the type 00695 // is anything else, then we must read the definition to follow. 00696 00697 if (type != TypeHandle::none()) { 00698 // Now we are going to read and create a new object. 00699 00700 // Defined the parameters for passing to the object factory. 00701 FactoryParams fparams; 00702 fparams.add_param(new BamReaderParam(scan, this)); 00703 00704 // First, we must add an entry into the map for this object ID, so 00705 // that in case this function is called recursively during the 00706 // object's factory constructor, we will have some definition for 00707 // the object. For now, we give it a NULL pointer. 00708 CreatedObj new_created_obj; 00709 new_created_obj._ptr = NULL; 00710 new_created_obj._change_this = NULL; 00711 CreatedObjs::iterator oi = 00712 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first; 00713 CreatedObj &created_obj = (*oi).second; 00714 00715 // Now we can call the factory to create the object. Update 00716 // _now_creating during this call so if this function calls 00717 // read_pointer() or register_change_this() we'll match it up 00718 // properly. This might recursively call back into this 00719 // p_read_object(), so be sure to save and restore the original 00720 // value of _now_creating. 00721 CreatedObjs::iterator was_creating = _now_creating; 00722 _now_creating = oi; 00723 TypedWritable *object = 00724 _factory->make_instance_more_general(type, fparams); 00725 _now_creating = was_creating; 00726 00727 // And now we can store the new object pointer in the map. 00728 nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id); 00729 created_obj._ptr = object; 00730 00731 if (created_obj._change_this != NULL) { 00732 // If the pointer is scheduled to change after 00733 // complete_pointers(), but we have no entry in 00734 // _object_pointers for this object (and hence no plan to call 00735 // complete_pointers()), then just change the pointer 00736 // immediately. 00737 ObjectPointers::const_iterator ri = _object_pointers.find(object_id); 00738 if (ri == _object_pointers.end()) { 00739 object = created_obj._change_this(object, this); 00740 created_obj._ptr = object; 00741 created_obj._change_this = NULL; 00742 } 00743 } 00744 00745 // Just some sanity checks 00746 if (object == (TypedWritable *)NULL) { 00747 bam_cat.info() 00748 << "Unable to create an object of type " << type << endl; 00749 00750 } else if (object->get_type() != type) { 00751 if (_new_types.find(type) != _new_types.end()) { 00752 // This was a type we hadn't heard of before, so it's not 00753 // really surprising we didn't know how to create it. 00754 // Suppress the warning (make it a debug statement instead). 00755 if (bam_cat.is_debug()) { 00756 bam_cat.warning() 00757 << "Attempted to create a " << type.get_name() \ 00758 << " but a " << object->get_type() \ 00759 << " was created instead." << endl; 00760 } 00761 00762 } else { 00763 // This was a normal type that we should have known how to 00764 // create. Report the error. 00765 bam_cat.warning() 00766 << "Attempted to create a " << type.get_name() \ 00767 << " but a " << object->get_type() \ 00768 << " was created instead." << endl; 00769 } 00770 00771 } else { 00772 if (bam_cat.is_spam()) { 00773 bam_cat.spam() 00774 << "Read a " << object->get_type() << "\n"; 00775 } 00776 } 00777 } 00778 00779 return object_id; 00780 } 00781 00782 //////////////////////////////////////////////////////////////////// 00783 // Function: BamReader::resolve_object_pointers 00784 // Access: Private 00785 // Description: Checks whether all of the pointers a particular 00786 // object is waiting for have been filled in yet. If 00787 // they have, calls complete_pointers() on the object 00788 // and returns true; otherwise, returns false. 00789 //////////////////////////////////////////////////////////////////// 00790 bool BamReader:: 00791 resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) { 00792 // Now make sure we have all of the pointers this object is 00793 // waiting for. If any of the pointers has not yet been read 00794 // in, we can't resolve this object--we can't do anything for a 00795 // given object until we have *all* outstanding pointers for 00796 // that object. 00797 00798 bool is_complete = true; 00799 vector_typedWritable references; 00800 00801 vector_int::const_iterator pi; 00802 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) { 00803 int child_id = (*pi); 00804 00805 if (child_id == 0) { 00806 // A NULL pointer is a NULL pointer. 00807 references.push_back((TypedWritable *)NULL); 00808 00809 } else { 00810 // See if we have the pointer available now. 00811 CreatedObjs::const_iterator oi = _created_objs.find(child_id); 00812 if (oi == _created_objs.end()) { 00813 // No, too bad. 00814 is_complete = false; 00815 00816 } else { 00817 const CreatedObj &child_obj = (*oi).second; 00818 if (child_obj._change_this != NULL) { 00819 // It's been created, but the pointer might still change. 00820 is_complete = false; 00821 00822 } else { 00823 // Yes, it's ready. 00824 references.push_back(child_obj._ptr); 00825 } 00826 } 00827 } 00828 } 00829 00830 if (is_complete) { 00831 // Okay, here's the complete list of pointers for you! 00832 int num_completed = object->complete_pointers(&references[0], this); 00833 if (num_completed != (int)references.size()) { 00834 bam_cat.warning() 00835 << object->get_type() << " completed " << num_completed 00836 << " of " << references.size() << " pointers.\n"; 00837 } 00838 return true; 00839 } 00840 00841 return false; 00842 } 00843 00844 //////////////////////////////////////////////////////////////////// 00845 // Function: BamReader::resolve_cycler_pointers 00846 // Access: Private 00847 // Description: Checks whether all of the pointers a particular 00848 // PipelineCycler is waiting for have been filled in 00849 // yet. If they have, calls complete_pointers() on the 00850 // cycler and returns true; otherwise, returns false. 00851 //////////////////////////////////////////////////////////////////// 00852 bool BamReader:: 00853 resolve_cycler_pointers(PipelineCyclerBase *cycler, 00854 const vector_int &pointer_ids) { 00855 // Now make sure we have all of the pointers this cycler is 00856 // waiting for. If any of the pointers has not yet been read 00857 // in, we can't resolve this cycler--we can't do anything for a 00858 // given cycler until we have *all* outstanding pointers for 00859 // that cycler. 00860 00861 bool is_complete = true; 00862 vector_typedWritable references; 00863 00864 vector_int::const_iterator pi; 00865 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) { 00866 int child_id = (*pi); 00867 00868 if (child_id == 0) { 00869 // A NULL pointer is a NULL pointer. 00870 references.push_back((TypedWritable *)NULL); 00871 00872 } else { 00873 // See if we have the pointer available now. 00874 CreatedObjs::const_iterator oi = _created_objs.find(child_id); 00875 if (oi == _created_objs.end()) { 00876 // No, too bad. 00877 is_complete = false; 00878 00879 } else { 00880 const CreatedObj &child_obj = (*oi).second; 00881 if (child_obj._change_this != NULL) { 00882 // It's been created, but the pointer might still change. 00883 is_complete = false; 00884 00885 } else { 00886 // Yes, it's ready. 00887 references.push_back(child_obj._ptr); 00888 } 00889 } 00890 } 00891 } 00892 00893 if (is_complete) { 00894 // Okay, here's the complete list of pointers for you! 00895 CycleData *cdata = cycler->write(); 00896 int num_completed = cdata->complete_pointers(&references[0], this); 00897 cycler->release_write(cdata); 00898 if (num_completed != (int)references.size()) { 00899 bam_cat.warning() 00900 << "CycleData object completed " << num_completed 00901 << " of " << references.size() << " pointers.\n"; 00902 } 00903 return true; 00904 } 00905 00906 return false; 00907 } 00908 00909 //////////////////////////////////////////////////////////////////// 00910 // Function: BamReader::finalize 00911 // Access: Private 00912 // Description: Should be called after all objects have been read, 00913 // this will finalize all the objects that registered 00914 // themselves for the finalize callback. 00915 //////////////////////////////////////////////////////////////////// 00916 void BamReader:: 00917 finalize() { 00918 if (bam_cat.is_debug()) { 00919 bam_cat.debug() 00920 << "Finalizing bam source\n"; 00921 } 00922 00923 Finalize::iterator fi = _finalize_list.begin(); 00924 while (fi != _finalize_list.end()) { 00925 TypedWritable *object = (*fi); 00926 nassertv(object != (TypedWritable *)NULL); 00927 _finalize_list.erase(fi); 00928 object->finalize(); 00929 00930 fi = _finalize_list.begin(); 00931 } 00932 }