Panda3D
|
00001 // Filename: bamReader.cxx 00002 // Created by: jason (12Jun00) 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 "pnotify.h" 00017 00018 #include "bam.h" 00019 #include "bamReader.h" 00020 #include "datagramIterator.h" 00021 #include "config_util.h" 00022 #include "pipelineCyclerBase.h" 00023 00024 TypeHandle BamReaderAuxData::_type_handle; 00025 00026 WritableFactory *BamReader::_factory = (WritableFactory*)0L; 00027 BamReader *const BamReader::Null = (BamReader*)0L; 00028 WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L; 00029 00030 BamReader::NewTypes BamReader::_new_types; 00031 00032 const int BamReader::_cur_major = _bam_major_ver; 00033 const int BamReader::_cur_minor = _bam_minor_ver; 00034 00035 00036 //////////////////////////////////////////////////////////////////// 00037 // Function: BamReader::Constructor 00038 // Access: Published 00039 // Description: 00040 //////////////////////////////////////////////////////////////////// 00041 BamReader:: 00042 BamReader(DatagramGenerator *source, const Filename &name) 00043 : _source(source), _filename(name) 00044 { 00045 _needs_init = true; 00046 _num_extra_objects = 0; 00047 _nesting_level = 0; 00048 _now_creating = _created_objs.end(); 00049 _reading_cycler = (PipelineCyclerBase *)NULL; 00050 _pta_id = -1; 00051 _long_object_id = false; 00052 _long_pta_id = false; 00053 } 00054 00055 00056 //////////////////////////////////////////////////////////////////// 00057 // Function: BamReader::Destructor 00058 // Access: Published 00059 // Description: 00060 //////////////////////////////////////////////////////////////////// 00061 BamReader:: 00062 ~BamReader() { 00063 nassertv(_num_extra_objects == 0); 00064 nassertv(_nesting_level == 0); 00065 } 00066 00067 //////////////////////////////////////////////////////////////////// 00068 // Function: BamReader::set_source 00069 // Access: Published 00070 // Description: Changes the source of future datagrams for this 00071 // BamReader. This also implicitly calls init() if it 00072 // has not already been called. 00073 //////////////////////////////////////////////////////////////////// 00074 void BamReader:: 00075 set_source(DatagramGenerator *source) { 00076 _source = source; 00077 if (_needs_init && _source != NULL) { 00078 bool success = init(); 00079 nassertv(success); 00080 } 00081 } 00082 00083 //////////////////////////////////////////////////////////////////// 00084 // Function: BamReader::init 00085 // Access: Published 00086 // Description: Initializes the BamReader prior to reading any 00087 // objects from its source. This includes reading the 00088 // Bam header. 00089 // 00090 // This returns true if the BamReader successfully 00091 // initialized, false otherwise. 00092 //////////////////////////////////////////////////////////////////// 00093 bool BamReader:: 00094 init() { 00095 nassertr(_source != NULL, false); 00096 nassertr(_needs_init, false); 00097 _needs_init = false; 00098 Datagram header; 00099 00100 if (_source->is_error()) { 00101 return false; 00102 } 00103 00104 if (!get_datagram(header)) { 00105 bam_cat.error() 00106 << "Unable to read Bam header.\n"; 00107 return false; 00108 } 00109 00110 DatagramIterator scan(header); 00111 00112 _file_major = scan.get_uint16(); 00113 _file_minor = scan.get_uint16(); 00114 00115 // If the major version is different, or the minor version is 00116 // *newer*, we can't safely load the file. 00117 if (_file_major != _bam_major_ver || 00118 _file_minor < _bam_first_minor_ver || 00119 _file_minor > _bam_minor_ver) { 00120 bam_cat.error() 00121 << "Bam file is version " << _file_major << "." << _file_minor 00122 << ".\n"; 00123 00124 if (_bam_minor_ver == _bam_first_minor_ver) { 00125 bam_cat.error() 00126 << "This program can only load version " 00127 << _bam_major_ver << "." << _bam_first_minor_ver << " bams.\n"; 00128 } else { 00129 bam_cat.error() 00130 << "This program can only load version " 00131 << _bam_major_ver << "." << _bam_first_minor_ver << " through " 00132 << _bam_major_ver << "." << _bam_minor_ver << " bams.\n"; 00133 } 00134 00135 return false; 00136 } 00137 00138 _file_endian = (BamEndian)scan.get_uint8(); 00139 00140 if (bam_cat.is_debug()) { 00141 bam_cat.debug() 00142 << "Bam file is version " << _file_major << "." << _file_minor 00143 << ".\n"; 00144 if (_file_minor != _bam_minor_ver) { 00145 bam_cat.debug() 00146 << "(Current version is " << _bam_major_ver << "." << _bam_minor_ver 00147 << ".)\n"; 00148 } 00149 bam_cat.debug() 00150 << "Endian preference is " << _file_endian << "\n"; 00151 } 00152 00153 return true; 00154 } 00155 00156 //////////////////////////////////////////////////////////////////// 00157 // Function: BamReader::set_aux_data 00158 // Access: Published 00159 // Description: Associates an arbitrary block of data with the 00160 // indicated object (or NULL), and the indicated name. 00161 // 00162 // This is intended to provide a place for temporary 00163 // storage for objects reading themselves from the bam 00164 // file. To use it, inherit from BamReader::AuxData and 00165 // store whatever data you like there. Then associate 00166 // your AuxData with the object as it is being read with 00167 // set_aux_data(). You may later set the aux data to 00168 // NULL to remove it; or it will automatically be 00169 // removed (and deleted) after finalize() is called for 00170 // the object in question. 00171 // 00172 // If the TypedWritable pointer is NULL, the the aux 00173 // data is stored globally for the BamReader in general. 00174 // This pointer is available to any bam objects, and 00175 // will not be automatically removed until the BamReader 00176 // itself destructs. 00177 // 00178 // In either case, the name is just an arbitrary 00179 // user-defined key. If there is already a data pointer 00180 // stored for the obj/name pair, that data pointer will 00181 // be replaced (and deleted). 00182 //////////////////////////////////////////////////////////////////// 00183 void BamReader:: 00184 set_aux_data(TypedWritable *obj, const string &name, BamReader::AuxData *data) { 00185 if (data == (void *)NULL) { 00186 AuxDataTable::iterator ti = _aux_data.find(obj); 00187 if (ti != _aux_data.end()) { 00188 AuxDataNames &names = (*ti).second; 00189 names.erase(name); 00190 if (names.empty()) { 00191 _aux_data.erase(ti); 00192 } 00193 } 00194 00195 } else { 00196 _aux_data[obj][name] = data; 00197 } 00198 } 00199 00200 //////////////////////////////////////////////////////////////////// 00201 // Function: BamReader::get_aux_data 00202 // Access: Published 00203 // Description: Returns the pointer previously associated with the 00204 // bam reader by a previous call to set_aux_data(), or 00205 // NULL if data with the indicated key has not been set. 00206 //////////////////////////////////////////////////////////////////// 00207 BamReader::AuxData *BamReader:: 00208 get_aux_data(TypedWritable *obj, const string &name) const { 00209 AuxDataTable::const_iterator ti = _aux_data.find(obj); 00210 if (ti != _aux_data.end()) { 00211 const AuxDataNames &names = (*ti).second; 00212 AuxDataNames::const_iterator ni = names.find(name); 00213 if (ni != names.end()) { 00214 return (*ni).second; 00215 } 00216 } 00217 00218 return NULL; 00219 } 00220 00221 00222 //////////////////////////////////////////////////////////////////// 00223 // Function: BamReader::read_object 00224 // Access: Published 00225 // Description: Reads a single object from the Bam file. If the 00226 // object type is known, a new object of the appropriate 00227 // type is created and returned; otherwise, NULL is 00228 // returned. NULL is also returned when the end of the 00229 // file is reached. is_eof() may be called to 00230 // differentiate between these two cases. 00231 // 00232 // This may be called repeatedly to extract out all the 00233 // objects in the Bam file, but typically (especially 00234 // for scene graph files, indicated with the .bam 00235 // extension), only one object is retrieved directly 00236 // from the Bam file: the root of the scene graph. The 00237 // remaining objects will all be retrieved recursively 00238 // by the first object. 00239 // 00240 // Note that the object returned may not yet be 00241 // complete. In particular, some of its pointers may 00242 // not be filled in; you must call resolve() to fill in 00243 // all the available pointers before you can safely use 00244 // any objects returned by read_object(). 00245 // 00246 // This flavor of read_object() requires the caller to 00247 // know what type of object it has received in order to 00248 // properly manage the reference counts. 00249 //////////////////////////////////////////////////////////////////// 00250 TypedWritable *BamReader:: 00251 read_object() { 00252 TypedWritable *ptr; 00253 ReferenceCount *ref_ptr; 00254 00255 if (!read_object(ptr, ref_ptr)) { 00256 return NULL; 00257 } 00258 00259 return ptr; 00260 } 00261 00262 //////////////////////////////////////////////////////////////////// 00263 // Function: BamReader::read_object 00264 // Access: Published 00265 // Description: Reads a single object from the Bam file. 00266 // 00267 // This flavor of read_object() returns both a 00268 // TypedWritable and a ReferenceCount pointer to the 00269 // same object, so the reference count may be tracked 00270 // reliably, without having to know precisely what type 00271 // of object we have. It returns true on success, or 00272 // false on failure. 00273 //////////////////////////////////////////////////////////////////// 00274 bool BamReader:: 00275 read_object(TypedWritable *&ptr, ReferenceCount *&ref_ptr) { 00276 ptr = NULL; 00277 ref_ptr = NULL; 00278 nassertr(_num_extra_objects == 0, false); 00279 00280 int start_level = _nesting_level; 00281 00282 // First, read the base object. 00283 int object_id = p_read_object(); 00284 00285 // Now that object might have included some pointers to other 00286 // objects, which may still need to be read. And those objects 00287 // might in turn require reading additional objects. Read all the 00288 // remaining objects. 00289 00290 // Prior to 6.21, we kept track of _num_extra_objects to know when 00291 // we're done. 00292 while (_num_extra_objects > 0) { 00293 p_read_object(); 00294 _num_extra_objects--; 00295 } 00296 00297 // Beginning with 6.21, we use explicit nesting commands to know 00298 // when we're done. 00299 while (_nesting_level > start_level) { 00300 p_read_object(); 00301 } 00302 00303 // Now look up the pointer of the object we read first. It should 00304 // be available now. 00305 if (object_id == 0) { 00306 if (bam_cat.is_spam()) { 00307 bam_cat.spam() 00308 << "Returning false\n"; 00309 } 00310 return false; 00311 } 00312 00313 CreatedObjs::iterator oi = _created_objs.find(object_id); 00314 00315 if (oi == _created_objs.end()) { 00316 bam_cat.error() 00317 << "Undefined object encountered!\n"; 00318 return false; 00319 00320 } else { 00321 CreatedObj &created_obj = (*oi).second; 00322 ptr = created_obj._ptr; 00323 ref_ptr = created_obj._ref_ptr; 00324 00325 if (bam_cat.is_spam()) { 00326 if (ptr != (TypedWritable *)NULL) { 00327 bam_cat.spam() 00328 << "Returning object of type " << ptr->get_type() << "\n"; 00329 } 00330 } 00331 if (created_obj._change_this != NULL || 00332 created_obj._change_this_ref != NULL) { 00333 bam_cat.warning() 00334 << "Returning pointer to " << ptr->get_type() 00335 << " that might change.\n"; 00336 } 00337 00338 return true; 00339 } 00340 } 00341 00342 //////////////////////////////////////////////////////////////////// 00343 // Function: BamReader::resolve 00344 // Access: Published 00345 // Description: This may be called at any time during processing of 00346 // the Bam file to resolve all the known pointers so 00347 // far. It is usually called at the end of the 00348 // processing, after all objects have been read, which 00349 // is generally the best time to call it. 00350 // 00351 // This must be called at least once after reading a 00352 // particular object via get_object() in order to 00353 // validate that object. 00354 // 00355 // The return value is true if all objects have been 00356 // resolved, or false if some objects are still 00357 // outstanding (in which case you will need to call 00358 // resolve() again later). 00359 //////////////////////////////////////////////////////////////////// 00360 bool BamReader:: 00361 resolve() { 00362 bool all_completed; 00363 bool any_completed_this_pass; 00364 00365 do { 00366 if (bam_cat.is_spam()) { 00367 bam_cat.spam() 00368 << "resolve pass begin\n"; 00369 } 00370 all_completed = true; 00371 any_completed_this_pass = false; 00372 00373 ObjectPointers::iterator oi; 00374 oi = _object_pointers.begin(); 00375 while (oi != _object_pointers.end()) { 00376 int object_id = (*oi).first; 00377 PointerReference &pref = (*oi).second; 00378 00379 CreatedObjs::iterator ci = _created_objs.find(object_id); 00380 nassertr(ci != _created_objs.end(), false); 00381 00382 CreatedObj &created_obj = (*ci).second; 00383 00384 TypedWritable *object_ptr = created_obj._ptr; 00385 00386 // Update _now_creating, so a call to get_int_tag() from within 00387 // complete_pointers() will come to the right place. 00388 CreatedObjs::iterator was_creating = _now_creating; 00389 _now_creating = ci; 00390 00391 if (resolve_object_pointers(object_ptr, pref)) { 00392 // Now remove this object from the list of things that need 00393 // completion. We have to be a bit careful when deleting things 00394 // from the STL container while we are traversing it. 00395 ObjectPointers::iterator old = oi; 00396 ++oi; 00397 _object_pointers.erase(old); 00398 any_completed_this_pass = true; 00399 00400 // Does the pointer need to change? 00401 if (created_obj._change_this_ref != NULL) { 00402 // Reference-counting variant. 00403 TypedWritableReferenceCount *object_ref_ptr = (TypedWritableReferenceCount *)object_ptr; 00404 nassertr(created_obj._ref_ptr == NULL || created_obj._ref_ptr == object_ref_ptr, false); 00405 PT(TypedWritableReferenceCount) new_ptr = created_obj._change_this_ref(object_ref_ptr, this); 00406 if (new_ptr != object_ref_ptr) { 00407 // Also update the reverse 00408 vector_int &old_refs = _created_objs_by_pointer[object_ptr]; 00409 vector_int &new_refs = _created_objs_by_pointer[new_ptr]; 00410 for (vector_int::const_iterator oi = old_refs.begin(); 00411 oi != old_refs.end(); 00412 ++oi) { 00413 new_refs.push_back(*oi); 00414 } 00415 _created_objs_by_pointer.erase(object_ptr); 00416 00417 // Remove the pointer from the finalize list (the new 00418 // pointer presumably doesn't require finalizing). 00419 _finalize_list.erase(object_ptr); 00420 } 00421 created_obj.set_ptr(new_ptr, new_ptr); 00422 created_obj._change_this = NULL; 00423 created_obj._change_this_ref = NULL; 00424 00425 } else if (created_obj._change_this != NULL) { 00426 // Non-reference-counting variant. 00427 TypedWritable *new_ptr = created_obj._change_this(object_ptr, this); 00428 if (new_ptr != object_ptr) { 00429 // Also update the reverse 00430 vector_int &old_refs = _created_objs_by_pointer[object_ptr]; 00431 vector_int &new_refs = _created_objs_by_pointer[new_ptr]; 00432 for (vector_int::const_iterator oi = old_refs.begin(); 00433 oi != old_refs.end(); 00434 ++oi) { 00435 new_refs.push_back(*oi); 00436 } 00437 _created_objs_by_pointer.erase(object_ptr); 00438 00439 // Remove the pointer from the finalize list (the new 00440 // pointer presumably doesn't require finalizing). 00441 _finalize_list.erase(object_ptr); 00442 } 00443 created_obj.set_ptr(new_ptr, new_ptr->as_reference_count()); 00444 created_obj._change_this = NULL; 00445 created_obj._change_this_ref = NULL; 00446 } 00447 00448 } else { 00449 // Couldn't complete this object yet; it'll wait for next time. 00450 ++oi; 00451 all_completed = false; 00452 } 00453 00454 _now_creating = was_creating; 00455 } 00456 00457 if (bam_cat.is_spam()) { 00458 bam_cat.spam() 00459 << "resolve pass end: all_completed = " << all_completed 00460 << " any_completed_this_pass = " << any_completed_this_pass 00461 << "\n"; 00462 } 00463 } while (!all_completed && any_completed_this_pass); 00464 00465 if (all_completed) { 00466 finalize(); 00467 } else { 00468 // Report all the uncompleted objects for no good reason. This 00469 // will probably have to come out later when we have cases in 00470 // which some objects might legitimately be uncompleted after 00471 // calling resolve(), but for now we expect resolve() to always 00472 // succeed. 00473 ObjectPointers::const_iterator oi; 00474 for (oi = _object_pointers.begin(); 00475 oi != _object_pointers.end(); 00476 ++oi) { 00477 int object_id = (*oi).first; 00478 CreatedObjs::iterator ci = _created_objs.find(object_id); 00479 nassertr(ci != _created_objs.end(), false); 00480 CreatedObj &created_obj = (*ci).second; 00481 TypedWritable *object_ptr = created_obj._ptr; 00482 00483 bam_cat.warning() 00484 << "Unable to complete " << object_ptr->get_type() << "\n"; 00485 } 00486 } 00487 00488 return all_completed; 00489 } 00490 00491 //////////////////////////////////////////////////////////////////// 00492 // Function: BamReader::change_pointer 00493 // Access: Published 00494 // Description: Indicates that an object recently read from the bam 00495 // stream should be replaced with a new object. Any 00496 // future occurrences of the original object in the 00497 // stream will henceforth return the new object instead. 00498 // 00499 // The return value is true if the replacement was 00500 // successfully made, or false if the object was not 00501 // read from the stream (or if change_pointer had 00502 // already been called on it). 00503 //////////////////////////////////////////////////////////////////// 00504 bool BamReader:: 00505 change_pointer(const TypedWritable *orig_pointer, const TypedWritable *new_pointer) { 00506 if (orig_pointer == new_pointer) { 00507 return false; 00508 } 00509 CreatedObjsByPointer::iterator ci = _created_objs_by_pointer.find(orig_pointer); 00510 if (ci == _created_objs_by_pointer.end()) { 00511 // No record of this object. 00512 return false; 00513 } 00514 00515 if (bam_cat.is_spam()) { 00516 bam_cat.spam() 00517 << "change_pointer(" << (void *)orig_pointer << ", " 00518 << (void *)new_pointer << ") (" << new_pointer->get_type() << ")\n"; 00519 } 00520 00521 const vector_int &old_refs = (*ci).second; 00522 vector_int &new_refs = _created_objs_by_pointer[new_pointer]; 00523 00524 for (vector_int::const_iterator oi = old_refs.begin(); 00525 oi != old_refs.end(); 00526 ++oi) { 00527 int object_id = (*oi); 00528 00529 CreatedObjs::iterator ci = _created_objs.find(object_id); 00530 nassertr(ci != _created_objs.end(), false); 00531 nassertr((*ci).second._ptr == orig_pointer, false); 00532 00533 TypedWritable *ptr = (TypedWritable *)new_pointer; 00534 (*ci).second.set_ptr(ptr, ptr->as_reference_count()); 00535 new_refs.push_back(object_id); 00536 } 00537 00538 _created_objs_by_pointer.erase(ci); 00539 00540 // Also change the pointer on the finalize_list. 00541 Finalize::iterator fi = _finalize_list.find((TypedWritable *)orig_pointer); 00542 if (fi != _finalize_list.end()) { 00543 _finalize_list.insert((TypedWritable *)new_pointer); 00544 _finalize_list.erase(fi); 00545 } 00546 00547 return true; 00548 } 00549 00550 00551 //////////////////////////////////////////////////////////////////// 00552 // Function: BamReader::read_handle 00553 // Access: Published 00554 // Description: Reads a TypeHandle out of the Datagram. 00555 //////////////////////////////////////////////////////////////////// 00556 TypeHandle BamReader:: 00557 read_handle(DatagramIterator &scan) { 00558 // We encode TypeHandles within the Bam file by writing a unique 00559 // index number for each one to the file. When we write a 00560 // particular TypeHandle for the first time, we assign it a new 00561 // index number and then immediately follow it by its definition; 00562 // when we write the same TypeHandle on subsequent times we only 00563 // write the index number. 00564 00565 // Thus, to read a TypeHandle, we first read the index number. If 00566 // it is a number we have not yet encountered, we must then read the 00567 // definition. 00568 00569 // Here's the index number. 00570 int id = scan.get_uint16(); 00571 00572 if (id == 0) { 00573 // Index number 0 is always, by convention, TypeHandle::none(). 00574 return TypeHandle::none(); 00575 } 00576 00577 IndexMap::const_iterator mi = _index_map.find(id); 00578 if (mi != _index_map.end()) { 00579 // We've encountered this index number before, so there should be 00580 // no type definition following the id. Simply return the 00581 // TypeHandle we previously associated with the id. 00582 TypeHandle type = (*mi).second; 00583 return type; 00584 } 00585 00586 // We haven't encountered this index number before. This means it 00587 // will be immediately followed by the type definition. This 00588 // consists of the string name, followed by the list of parent 00589 // TypeHandles for this type. 00590 00591 string name = scan.get_string(); 00592 bool new_type = false; 00593 00594 TypeHandle type = TypeRegistry::ptr()->find_type(name); 00595 if (type == TypeHandle::none()) { 00596 // We've never heard of this type before! This is really an error 00597 // condition, but we'll do the best we can and declare it 00598 // on-the-fly. 00599 00600 type = TypeRegistry::ptr()->register_dynamic_type(name); 00601 bam_cat.warning() 00602 << "Bam file '" << _filename << "' contains objects of unknown type: " 00603 << type << "\n"; 00604 new_type = true; 00605 _new_types.insert(type); 00606 } 00607 00608 // Now pick up the derivation information. 00609 int num_parent_classes = scan.get_uint8(); 00610 for (int i = 0; i < num_parent_classes; i++) { 00611 TypeHandle parent_type = read_handle(scan); 00612 if (new_type) { 00613 TypeRegistry::ptr()->record_derivation(type, parent_type); 00614 } else { 00615 if (type.get_parent_towards(parent_type) != parent_type) { 00616 if (bam_cat.is_debug()) { 00617 bam_cat.debug() 00618 << "Bam file indicates a derivation of " << type 00619 << " from " << parent_type << " which is no longer true.\n"; 00620 } 00621 } 00622 } 00623 } 00624 00625 bool inserted = _index_map.insert(IndexMap::value_type(id, type)).second; 00626 nassertr(inserted, type); 00627 00628 if (bam_cat.is_spam()) { 00629 bam_cat.spam() 00630 << "Read TypeHandle for " << type << ".\n"; 00631 } 00632 00633 return type; 00634 } 00635 00636 //////////////////////////////////////////////////////////////////// 00637 // Function: BamReader::read_pointer 00638 // Access: Public 00639 // Description: The interface for reading a pointer to another object 00640 // from a Bam file. Objects reading themselves from a 00641 // Bam file should call this when they expect to read a 00642 // pointer to some other object. This function reads 00643 // whatever is stored in the bam file to represent the 00644 // pointer, and advances the datagram iterator 00645 // accordingly. 00646 // 00647 // Rather than returning a pointer immediately, this 00648 // function reads the internal pointer information from 00649 // the datagram and queues up the request. The pointer 00650 // itself may not be available until later (it may be a 00651 // pointer to an object that appears later in the Bam 00652 // file). Later, when all pointers are available, the 00653 // complete_pointers() callback function will be called 00654 // with an array of actual pointers, one for each time 00655 // read_pointer() was called. It is then the calling 00656 // object's responsibilty to store these pointers in the 00657 // object properly. 00658 //////////////////////////////////////////////////////////////////// 00659 void BamReader:: 00660 read_pointer(DatagramIterator &scan) { 00661 Thread::consider_yield(); 00662 00663 nassertv(_now_creating != _created_objs.end()); 00664 int requestor_id = (*_now_creating).first; 00665 00666 // Read the object ID, and associate it with the requesting object. 00667 int object_id = read_object_id(scan); 00668 00669 PointerReference &pref = _object_pointers[requestor_id]; 00670 if (_reading_cycler == (PipelineCyclerBase *)NULL) { 00671 // This is not being read within a read_cdata() call. 00672 pref._objects.push_back(object_id); 00673 } else { 00674 // This *is* being read within a read_cdata() call. 00675 pref._cycler_pointers[_reading_cycler].push_back(object_id); 00676 } 00677 00678 // If the object ID is zero (which indicates a NULL pointer), we 00679 // don't have to do anything else. 00680 if (object_id != 0) { 00681 /* 00682 CreatedObj new_created_obj; 00683 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).second; 00684 */ 00685 00686 if (get_file_minor_ver() < 21) { 00687 // Prior to bam version 6.21, we expect to read an adjunct 00688 // object for each non-NULL pointer we read. 00689 _num_extra_objects++; 00690 } 00691 } 00692 } 00693 00694 //////////////////////////////////////////////////////////////////// 00695 // Function: BamReader::read_pointers 00696 // Access: Public 00697 // Description: A convenience function to read a contiguous list of 00698 // pointers. This is equivalent to calling 00699 // read_pointer() count times. 00700 //////////////////////////////////////////////////////////////////// 00701 void BamReader:: 00702 read_pointers(DatagramIterator &scan, int count) { 00703 for (int i = 0; i < count; i++) { 00704 read_pointer(scan); 00705 } 00706 } 00707 00708 //////////////////////////////////////////////////////////////////// 00709 // Function: BamReader::skip_pointer 00710 // Access: Public 00711 // Description: Reads and discards a pointer value from the Bam file. 00712 // This pointer will not be counted among the pointers 00713 // read for a given object, and will not be in the list 00714 // of pointers passed to complete_pointers(). 00715 //////////////////////////////////////////////////////////////////// 00716 void BamReader:: 00717 skip_pointer(DatagramIterator &scan) { 00718 read_object_id(scan); 00719 } 00720 00721 //////////////////////////////////////////////////////////////////// 00722 // Function: BamReader::read_cdata 00723 // Access: Public 00724 // Description: Reads in the indicated CycleData object. This should 00725 // be used by classes that store some or all of their 00726 // data within a CycleData subclass, in support of 00727 // pipelining. This will call the virtual 00728 // CycleData::fillin() method to do the actual reading. 00729 //////////////////////////////////////////////////////////////////// 00730 void BamReader:: 00731 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler) { 00732 PipelineCyclerBase *old_cycler = _reading_cycler; 00733 _reading_cycler = &cycler; 00734 CycleData *cdata = cycler.write(Thread::get_current_thread()); 00735 cdata->fillin(scan, this); 00736 cycler.release_write(cdata); 00737 _reading_cycler = old_cycler; 00738 } 00739 00740 //////////////////////////////////////////////////////////////////// 00741 // Function: BamReader::read_cdata 00742 // Access: Public 00743 // Description: This flavor of read_cdata allows passing an 00744 // additional parameter to cdata->fillin(). 00745 //////////////////////////////////////////////////////////////////// 00746 void BamReader:: 00747 read_cdata(DatagramIterator &scan, PipelineCyclerBase &cycler, 00748 void *extra_data) { 00749 PipelineCyclerBase *old_cycler = _reading_cycler; 00750 _reading_cycler = &cycler; 00751 CycleData *cdata = cycler.write(Thread::get_current_thread()); 00752 cdata->fillin(scan, this, extra_data); 00753 cycler.release_write(cdata); 00754 _reading_cycler = old_cycler; 00755 } 00756 00757 //////////////////////////////////////////////////////////////////// 00758 // Function: BamReader::set_int_tag 00759 // Access: Public 00760 // Description: Allows the creating object to store a temporary data 00761 // value on the BamReader. This method may be called 00762 // during an object's fillin() method; it will associate 00763 // an integer value with an arbitrary string key (which 00764 // is in turn associated with the calling object only). 00765 // Later, in the complete_pointers() method, the same 00766 // object may query this data again via get_int_tag(). 00767 // 00768 // The tag string need not be unique between different 00769 // objects, but it should be unique between an object 00770 // and its CData object(s). 00771 //////////////////////////////////////////////////////////////////// 00772 void BamReader:: 00773 set_int_tag(const string &tag, int value) { 00774 nassertv(_now_creating != _created_objs.end()); 00775 int requestor_id = (*_now_creating).first; 00776 00777 PointerReference &pref = _object_pointers[requestor_id]; 00778 pref._int_tags[tag] = value; 00779 } 00780 00781 //////////////////////////////////////////////////////////////////// 00782 // Function: BamReader::get_int_tag 00783 // Access: Public 00784 // Description: Returns the value previously set via set_int_tag(). 00785 // It is an error if no value has been set. 00786 //////////////////////////////////////////////////////////////////// 00787 int BamReader:: 00788 get_int_tag(const string &tag) const { 00789 nassertr(_now_creating != _created_objs.end(), 0); 00790 int requestor_id = (*_now_creating).first; 00791 00792 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id); 00793 nassertr(opi != _object_pointers.end(), 0); 00794 const PointerReference &pref = (*opi).second; 00795 00796 IntTags::const_iterator iti = pref._int_tags.find(tag); 00797 nassertr(iti != pref._int_tags.end(), 0); 00798 return (*iti).second; 00799 } 00800 00801 //////////////////////////////////////////////////////////////////// 00802 // Function: BamReader::set_aux_tag 00803 // Access: Public 00804 // Description: Allows the creating object to store a temporary data 00805 // value on the BamReader. This method may be called 00806 // during an object's fillin() method; it will associate 00807 // a newly-allocated BamReaderAuxData construct with an 00808 // arbitrary string key (which is in turn associated 00809 // with the calling object only). Later, in the 00810 // complete_pointers() method, the same object may query 00811 // this data again via get_aux_tag(). 00812 // 00813 // The BamReader will maintain the reference count on 00814 // the BamReaderAuxData, and destruct it when it is 00815 // cleaned up. 00816 // 00817 // The tag string need not be unique between different 00818 // objects, but it should be unique between an object 00819 // and its CData object(s). 00820 //////////////////////////////////////////////////////////////////// 00821 void BamReader:: 00822 set_aux_tag(const string &tag, BamReaderAuxData *value) { 00823 nassertv(_now_creating != _created_objs.end()); 00824 int requestor_id = (*_now_creating).first; 00825 00826 PointerReference &pref = _object_pointers[requestor_id]; 00827 pref._aux_tags[tag] = value; 00828 } 00829 00830 //////////////////////////////////////////////////////////////////// 00831 // Function: BamReader::get_aux_tag 00832 // Access: Public 00833 // Description: Returns the value previously set via set_aux_tag(). 00834 // It is an error if no value has been set. 00835 //////////////////////////////////////////////////////////////////// 00836 BamReaderAuxData *BamReader:: 00837 get_aux_tag(const string &tag) const { 00838 nassertr(_now_creating != _created_objs.end(), NULL); 00839 int requestor_id = (*_now_creating).first; 00840 00841 ObjectPointers::const_iterator opi = _object_pointers.find(requestor_id); 00842 nassertr(opi != _object_pointers.end(), NULL); 00843 const PointerReference &pref = (*opi).second; 00844 00845 AuxTags::const_iterator ati = pref._aux_tags.find(tag); 00846 nassertr(ati != pref._aux_tags.end(), NULL); 00847 return (*ati).second; 00848 } 00849 00850 //////////////////////////////////////////////////////////////////// 00851 // Function: BamReader::register_finalize 00852 // Access: Public 00853 // Description: Should be called by an object reading itself from the 00854 // Bam file to indicate that this particular object 00855 // would like to receive the finalize() callback when 00856 // all the objects and pointers in the Bam file are 00857 // completely read. 00858 // 00859 // This provides a hook for objects that need to do any 00860 // additional finalization work after all of their 00861 // related pointers are guaranteed to be filled in. 00862 //////////////////////////////////////////////////////////////////// 00863 void BamReader:: 00864 register_finalize(TypedWritable *whom) { 00865 nassertv(whom != (TypedWritable *)NULL); 00866 00867 if (bam_cat.is_spam()) { 00868 bam_cat.spam() 00869 << "register_finalize(" << (void *)whom << ") (" << whom->get_type() 00870 << ")\n"; 00871 } 00872 00873 _finalize_list.insert(whom); 00874 } 00875 00876 //////////////////////////////////////////////////////////////////// 00877 // Function: BamReader::register_change_this 00878 // Access: Public 00879 // Description: Called by an object reading itself from the bam file 00880 // to indicate that the object pointer that will be 00881 // returned is temporary, and will eventually need to be 00882 // replaced with another pointer. 00883 // 00884 // The supplied function pointer will later be called on 00885 // the object, immediately after complete_pointers() is 00886 // called; it should return the new and final pointer. 00887 // 00888 // We use a static function pointer instead of a virtual 00889 // function (as in finalize()), to allow the function to 00890 // destruct the old pointer if necessary. (It is 00891 // invalid to destruct the this pointer within a virtual 00892 // function.) 00893 //////////////////////////////////////////////////////////////////// 00894 void BamReader:: 00895 register_change_this(ChangeThisFunc func, TypedWritable *object) { 00896 nassertv(_now_creating != _created_objs.end()); 00897 CreatedObj &created_obj = (*_now_creating).second; 00898 00899 #ifndef NDEBUG 00900 // Sanity check the pointer--it should always be the same pointer 00901 // after we set it the first time. 00902 if (created_obj._ptr == (TypedWritable *)NULL) { 00903 created_obj.set_ptr(object, object->as_reference_count()); 00904 } else { 00905 // We've previously assigned this pointer, and we should have 00906 // assigned it to the same this pointer we have now. 00907 nassertv(created_obj._ptr == object); 00908 } 00909 #endif // NDEBUG 00910 00911 created_obj._change_this = func; 00912 created_obj._change_this_ref = NULL; 00913 } 00914 00915 //////////////////////////////////////////////////////////////////// 00916 // Function: BamReader::register_change_this 00917 // Access: Public 00918 // Description: Called by an object reading itself from the bam file 00919 // to indicate that the object pointer that will be 00920 // returned is temporary, and will eventually need to be 00921 // replaced with another pointer. 00922 // 00923 // The supplied function pointer will later be called on 00924 // the object, immediately after complete_pointers() is 00925 // called; it should return the new and final pointer. 00926 // 00927 // We use a static function pointer instead of a virtual 00928 // function (as in finalize()), to allow the function to 00929 // destruct the old pointer if necessary. (It is 00930 // invalid to destruct the this pointer within a virtual 00931 // function.) 00932 //////////////////////////////////////////////////////////////////// 00933 void BamReader:: 00934 register_change_this(ChangeThisRefFunc func, TypedWritableReferenceCount *object) { 00935 nassertv(_now_creating != _created_objs.end()); 00936 CreatedObj &created_obj = (*_now_creating).second; 00937 00938 #ifndef NDEBUG 00939 // Sanity check the pointer--it should always be the same pointer 00940 // after we set it the first time. 00941 if (created_obj._ptr == (TypedWritable *)NULL) { 00942 created_obj.set_ptr(object, object); 00943 } else { 00944 // We've previously assigned this pointer, and we should have 00945 // assigned it to the same this pointer we have now. 00946 nassertv(created_obj._ptr == object); 00947 nassertv(created_obj._ref_ptr == object); 00948 } 00949 #endif // NDEBUG 00950 00951 created_obj._change_this = NULL; 00952 created_obj._change_this_ref = func; 00953 } 00954 00955 //////////////////////////////////////////////////////////////////// 00956 // Function: BamReader::finalize_now 00957 // Access: Public 00958 // Description: Forces the finalization of a particular object. This 00959 // may be called by any of the objects during 00960 // finalization, to guarantee finalization ordering 00961 // where it is important. 00962 //////////////////////////////////////////////////////////////////// 00963 void BamReader:: 00964 finalize_now(TypedWritable *whom) { 00965 nassertv(whom != (TypedWritable *)NULL); 00966 00967 Finalize::iterator fi = _finalize_list.find(whom); 00968 if (fi != _finalize_list.end()) { 00969 _finalize_list.erase(fi); 00970 if (bam_cat.is_spam()) { 00971 bam_cat.spam() 00972 << "finalizing " << (void *)whom << " (" << whom->get_type() 00973 << ")\n"; 00974 } 00975 whom->finalize(this); 00976 } 00977 } 00978 00979 //////////////////////////////////////////////////////////////////// 00980 // Function: BamReader::get_pta 00981 // Access: Public 00982 // Description: This function works in conjection with 00983 // register_pta(), below, to read a PointerToArray (PTA) 00984 // from the Bam file, and unify references to the same 00985 // PTA. 00986 // 00987 // The first time get_pta() encounters a particular PTA, 00988 // it will return NULL. This is the indication that the 00989 // caller should then read in the data associated with 00990 // the PTA, and subsequently call register_pta() with 00991 // the address of the filled-in array. 00992 // 00993 // The next time (and all subsequent times) that 00994 // get_pta() encounters this same PTA, it will return 00995 // the pointer that was passed with register_pta(). 00996 // 00997 // Also see the READ_PTA() macro, which consolidates all 00998 // the work that must be done to read a PTA. 00999 //////////////////////////////////////////////////////////////////// 01000 void *BamReader:: 01001 get_pta(DatagramIterator &scan) { 01002 nassertr(_pta_id == -1, (void *)NULL); 01003 int id = read_pta_id(scan); 01004 01005 if (id == 0) { 01006 // As always, a 0 ID indicates a NULL pointer. The caller will 01007 // not be able to differentiate this case from that of a 01008 // previously-read pointer, but that's OK because the next data in 01009 // the Bam file is the length of the array, which will be 01010 // zero--indicating an empty or NULL array. 01011 return (void *)NULL; 01012 } 01013 01014 PTAMap::iterator pi = _pta_map.find(id); 01015 if (pi == _pta_map.end()) { 01016 // This is the first time we've encountered this particular ID, 01017 // meaning we need to read the data now and register it. 01018 _pta_id = id; 01019 return (void *)NULL; 01020 } 01021 01022 return (*pi).second; 01023 } 01024 01025 //////////////////////////////////////////////////////////////////// 01026 // Function: BamReader::register_pta 01027 // Access: Public 01028 // Description: The second part of read_pta(), this should be called 01029 // with the pointer to the array that was read in after 01030 // read_pta() returned NULL. This associates the 01031 // pointer with the ID that was previously read, so that 01032 // future calls to read_pta() will return the same 01033 // pointer. 01034 // 01035 // Also see the READ_PTA() macro, which consolidates all 01036 // the work that must be done to read a PTA. 01037 //////////////////////////////////////////////////////////////////// 01038 void BamReader:: 01039 register_pta(void *ptr) { 01040 if (_pta_id != -1) { 01041 bool inserted = _pta_map.insert(PTAMap::value_type(_pta_id, ptr)).second; 01042 _pta_id = -1; 01043 nassertv(inserted); 01044 } 01045 } 01046 01047 //////////////////////////////////////////////////////////////////// 01048 // Function: BamReader::free_object_ids 01049 // Access: Private 01050 // Description: Handles a record that begins with the _remove_flag 01051 // TypeHandle; this contains a list of object ID's that 01052 // will no longer be used in this file and can safely be 01053 // removed. 01054 //////////////////////////////////////////////////////////////////// 01055 void BamReader:: 01056 free_object_ids(DatagramIterator &scan) { 01057 // We have to fully complete any objects before we remove them. 01058 // Might as well try to complete everything before we get started. 01059 resolve(); 01060 01061 while (scan.get_remaining_size() > 0) { 01062 int object_id = read_object_id(scan); 01063 01064 CreatedObjs::iterator ci = _created_objs.find(object_id); 01065 if (ci == _created_objs.end()) { 01066 util_cat.warning() 01067 << "Bam file suggests eliminating object_id " << object_id 01068 << ", already gone.\n"; 01069 } else { 01070 01071 // Make sure the object was successfully completed. 01072 ObjectPointers::iterator oi = _object_pointers.find(object_id); 01073 if (oi != _object_pointers.end()) { 01074 util_cat.warning() 01075 << "Unable to resolve object " << object_id 01076 << " before removing from table.\n"; 01077 } 01078 01079 _created_objs_by_pointer.erase((*ci).second._ptr); 01080 _created_objs.erase(ci); 01081 } 01082 } 01083 } 01084 01085 01086 //////////////////////////////////////////////////////////////////// 01087 // Function: BamReader::read_object_id 01088 // Access: Private 01089 // Description: Reads an object id from the datagram. 01090 //////////////////////////////////////////////////////////////////// 01091 int BamReader:: 01092 read_object_id(DatagramIterator &scan) { 01093 int object_id; 01094 01095 if (_long_object_id) { 01096 object_id = scan.get_uint32(); 01097 01098 } else { 01099 object_id = scan.get_uint16(); 01100 if (object_id == 0xffff) { 01101 _long_object_id = true; 01102 } 01103 } 01104 01105 return object_id; 01106 } 01107 01108 //////////////////////////////////////////////////////////////////// 01109 // Function: BamReader::read_pta_id 01110 // Access: Private 01111 // Description: Reads an pta id from the datagram. 01112 //////////////////////////////////////////////////////////////////// 01113 int BamReader:: 01114 read_pta_id(DatagramIterator &scan) { 01115 int pta_id; 01116 01117 if (_long_pta_id) { 01118 pta_id = scan.get_uint32(); 01119 01120 } else { 01121 pta_id = scan.get_uint16(); 01122 if (pta_id == 0xffff) { 01123 _long_pta_id = true; 01124 } 01125 } 01126 01127 return pta_id; 01128 } 01129 01130 //////////////////////////////////////////////////////////////////// 01131 // Function: BamReader::p_read_object 01132 // Access: Private 01133 // Description: The private implementation of read_object(); this 01134 // reads an object from the file and returns its object 01135 // ID. 01136 //////////////////////////////////////////////////////////////////// 01137 int BamReader:: 01138 p_read_object() { 01139 Datagram packet; 01140 01141 // First, read a datagram for the object. 01142 if (!get_datagram(packet)) { 01143 // When we run out of datagrams, we're at the end of the file. 01144 if (bam_cat.is_debug()) { 01145 bam_cat.debug() 01146 << "Reached end of bam source.\n"; 01147 } 01148 return 0; 01149 } 01150 01151 // Now extract the object definition from the datagram. 01152 DatagramIterator scan(packet); 01153 01154 // First, read the BamObjectCode. In bam versions prior to 6.21, 01155 // there was no BamObjectCode in the stream. 01156 BamObjectCode boc = BOC_adjunct; 01157 if (get_file_minor_ver() >= 21) { 01158 boc = (BamObjectCode)scan.get_uint8(); 01159 } 01160 switch (boc) { 01161 case BOC_push: 01162 ++_nesting_level; 01163 break; 01164 01165 case BOC_pop: 01166 --_nesting_level; 01167 return 0; 01168 01169 case BOC_adjunct: 01170 break; 01171 01172 case BOC_remove: 01173 // The BOC_remove code is a special case; it begins a 01174 // record that simply lists all of the object ID's that are no 01175 // longer important to the file and may be released. 01176 free_object_ids(scan); 01177 01178 // Now that we've freed all of the object id's indicate, read the 01179 // next object id in the stream. It's easiest to do this by 01180 // calling recursively. 01181 return p_read_object(); 01182 } 01183 01184 // An object definition in a Bam file consists of a TypeHandle 01185 // definition, defining the object's type, followed by an object ID 01186 // index, defining the particular instance (e.g. pointer) of this 01187 // object. 01188 01189 TypeHandle type = read_handle(scan); 01190 01191 int object_id = read_object_id(scan); 01192 01193 // There are two cases (not counting the special _remove_flag case, 01194 // above). Either this is a new object definition, or this is a 01195 // reference to an object that was previously defined. 01196 01197 // We use the TypeHandle to differentiate these two cases. By 01198 // convention, we write a TypeHandle::none() to the Bam file when we 01199 // are writing a reference to a previously-defined object, but we 01200 // write the object's actual type when we are writing its definition 01201 // right now. 01202 01203 // Therefore, if the type is TypeHandle::none(), then we must have 01204 // already read in and created the object (although its pointers may 01205 // not be fully instantiated yet). On the other hand, if the type 01206 // is anything else, then we must read the definition to follow. 01207 01208 if (type != TypeHandle::none()) { 01209 // Now we are going to read and create a new object. 01210 01211 // First, we must add an entry into the map for this object ID, so 01212 // that in case this function is called recursively during the 01213 // object's factory constructor, we will have some definition for 01214 // the object. For now, we give it a NULL pointer. 01215 CreatedObj new_created_obj; 01216 CreatedObjs::iterator oi = 01217 _created_objs.insert(CreatedObjs::value_type(object_id, new_created_obj)).first; 01218 CreatedObj &created_obj = (*oi).second; 01219 01220 if (created_obj._ptr != NULL) { 01221 // This object had already existed; thus, we are just receiving 01222 // an update for it. 01223 01224 // Update _now_creating during this call so if this function 01225 // calls read_pointer() or register_change_this() we'll match it 01226 // up properly. This might recursively call back into this 01227 // p_read_object(), so be sure to save and restore the original 01228 // value of _now_creating. 01229 CreatedObjs::iterator was_creating = _now_creating; 01230 _now_creating = oi; 01231 created_obj._ptr->fillin(scan, this); 01232 _now_creating = was_creating; 01233 01234 } else { 01235 // We are receiving a new object. Now we can call the factory 01236 // to create the object. 01237 01238 // Define the parameters for passing to the object factory. 01239 FactoryParams fparams; 01240 fparams.add_param(new BamReaderParam(scan, this)); 01241 01242 // As above, we update and preserve _now_creating during this 01243 // call. 01244 CreatedObjs::iterator was_creating = _now_creating; 01245 _now_creating = oi; 01246 TypedWritable *object = 01247 _factory->make_instance_more_general(type, fparams); 01248 _now_creating = was_creating; 01249 01250 // And now we can store the new object pointer in the map. 01251 nassertr(created_obj._ptr == object || created_obj._ptr == NULL, object_id); 01252 if (object == NULL) { 01253 created_obj.set_ptr(NULL, NULL); 01254 } else { 01255 created_obj.set_ptr(object, object->as_reference_count()); 01256 } 01257 created_obj._created = true; 01258 01259 if (created_obj._change_this_ref != NULL) { 01260 // If the pointer is scheduled to change after 01261 // complete_pointers(), but we have no entry in 01262 // _object_pointers for this object (and hence no plan to call 01263 // complete_pointers()), then just change the pointer 01264 // immediately. 01265 ObjectPointers::const_iterator ri = _object_pointers.find(object_id); 01266 if (ri == _object_pointers.end()) { 01267 PT(TypedWritableReferenceCount) object_ref = (*created_obj._change_this_ref)((TypedWritableReferenceCount *)object, this); 01268 TypedWritable *new_ptr = object_ref; 01269 created_obj.set_ptr(object_ref, object_ref); 01270 created_obj._change_this = NULL; 01271 created_obj._change_this_ref = NULL; 01272 01273 // Remove the pointer from the finalize list (the new 01274 // pointer presumably doesn't require finalizing). 01275 if (new_ptr != object) { 01276 _finalize_list.erase(object); 01277 } 01278 object = new_ptr; 01279 } 01280 01281 } else if (created_obj._change_this != NULL) { 01282 // Non-reference-counting variant. 01283 ObjectPointers::const_iterator ri = _object_pointers.find(object_id); 01284 if (ri == _object_pointers.end()) { 01285 TypedWritable *new_ptr = (*created_obj._change_this)(object, this); 01286 created_obj.set_ptr(new_ptr, new_ptr->as_reference_count()); 01287 created_obj._change_this = NULL; 01288 created_obj._change_this_ref = NULL; 01289 01290 if (new_ptr != object) { 01291 _finalize_list.erase(object); 01292 } 01293 object = new_ptr; 01294 } 01295 } 01296 01297 _created_objs_by_pointer[created_obj._ptr].push_back(object_id); 01298 01299 // Just some sanity checks 01300 if (object == (TypedWritable *)NULL) { 01301 if (bam_cat.is_debug()) { 01302 bam_cat.debug() 01303 << "Unable to create an object of type " << type << endl; 01304 } 01305 01306 } else if (object->get_type() != type) { 01307 if (_new_types.find(type) != _new_types.end()) { 01308 // This was a type we hadn't heard of before, so it's not 01309 // really surprising we didn't know how to create it. 01310 // Suppress the warning (make it a debug statement instead). 01311 if (bam_cat.is_debug()) { 01312 bam_cat.warning() 01313 << "Attempted to create a " << type.get_name() \ 01314 << " but a " << object->get_type() \ 01315 << " was created instead." << endl; 01316 } 01317 01318 } else { 01319 // This was a normal type that we should have known how to 01320 // create. Report the error. 01321 bam_cat.warning() 01322 << "Attempted to create a " << type.get_name() \ 01323 << " but a " << object->get_type() \ 01324 << " was created instead." << endl; 01325 } 01326 01327 } else { 01328 if (bam_cat.is_spam()) { 01329 bam_cat.spam() 01330 << "Read a " << object->get_type() << ": " << (void *)object << "\n"; 01331 } 01332 } 01333 } 01334 } 01335 01336 return object_id; 01337 } 01338 01339 //////////////////////////////////////////////////////////////////// 01340 // Function: BamReader::resolve_object_pointers 01341 // Access: Private 01342 // Description: Checks whether all of the pointers a particular 01343 // object is waiting for have been filled in yet. If 01344 // they have, calls complete_pointers() on the object 01345 // and returns true; otherwise, returns false. 01346 //////////////////////////////////////////////////////////////////// 01347 bool BamReader:: 01348 resolve_object_pointers(TypedWritable *object, 01349 BamReader::PointerReference &pref) { 01350 // Some objects further require all of their nested objects to have 01351 // been completed (i.e. complete_pointers has been called on each 01352 // nested object) before they can themselves be completed. 01353 bool require_fully_complete = object->require_fully_complete(); 01354 01355 // First do the PipelineCycler objects. 01356 CyclerPointers::iterator ci; 01357 ci = pref._cycler_pointers.begin(); 01358 while (ci != pref._cycler_pointers.end()) { 01359 PipelineCyclerBase *cycler = (*ci).first; 01360 const vector_int &pointer_ids = (*ci).second; 01361 01362 if (resolve_cycler_pointers(cycler, pointer_ids, require_fully_complete)) { 01363 // Now remove this cycler from the list of things that need 01364 // completion. We have to be a bit careful when deleting things 01365 // from the STL container while we are traversing it. 01366 CyclerPointers::iterator old = ci; 01367 ++ci; 01368 pref._cycler_pointers.erase(old); 01369 01370 } else { 01371 // Couldn't complete this cycler yet; it'll wait for next time. 01372 ++ci; 01373 } 01374 } 01375 01376 if (!pref._cycler_pointers.empty()) { 01377 // If we didn't get all the cyclers, we have to wait. 01378 if (bam_cat.is_spam()) { 01379 bam_cat.spam() 01380 << "some cyclers pending: complete_pointers for " << (void *)object 01381 << " (" << object->get_type() << ")\n"; 01382 } 01383 return false; 01384 } 01385 01386 // Now make sure we have all of the pointers this object is 01387 // waiting for. If any of the pointers has not yet been read 01388 // in, we can't resolve this object--we can't do anything for a 01389 // given object until we have *all* outstanding pointers for 01390 // that object. 01391 bool is_complete = true; 01392 01393 vector_typedWritable references; 01394 references.reserve(pref._objects.size()); 01395 01396 vector_int::const_iterator pi; 01397 for (pi = pref._objects.begin(); 01398 pi != pref._objects.end() && is_complete; 01399 ++pi) { 01400 int child_id = (*pi); 01401 if (child_id == 0) { 01402 // A NULL pointer is a NULL pointer. 01403 references.push_back((TypedWritable *)NULL); 01404 01405 } else { 01406 // See if we have the pointer available now. 01407 CreatedObjs::const_iterator oi = _created_objs.find(child_id); 01408 if (oi == _created_objs.end()) { 01409 // No, too bad. 01410 is_complete = false; 01411 01412 } else { 01413 const CreatedObj &child_obj = (*oi).second; 01414 if (!child_obj._created) { 01415 // The child object hasn't yet been created. 01416 is_complete = false; 01417 } else if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) { 01418 // It's been created, but the pointer might still change. 01419 is_complete = false; 01420 } else { 01421 if (require_fully_complete && 01422 _object_pointers.find(child_id) != _object_pointers.end()) { 01423 // It's not yet complete itself. 01424 is_complete = false; 01425 01426 } else { 01427 // Yes, it's ready. 01428 references.push_back(child_obj._ptr); 01429 } 01430 } 01431 } 01432 } 01433 } 01434 01435 if (is_complete) { 01436 // Okay, here's the complete list of pointers for you! 01437 nassertr(references.size() == pref._objects.size(), false); 01438 01439 if (bam_cat.is_spam()) { 01440 bam_cat.spam() 01441 << "complete_pointers for " << (void *)object 01442 << " (" << object->get_type() << "), " << references.size() 01443 << " pointers.\n"; 01444 } 01445 int num_completed = 0; 01446 if (!references.empty()) { 01447 num_completed = object->complete_pointers(&references[0], this); 01448 } 01449 if (num_completed != (int)references.size()) { 01450 bam_cat.warning() 01451 << object->get_type() << " completed " << num_completed 01452 << " of " << references.size() << " pointers.\n"; 01453 nassertr(num_completed < (int)references.size(), true); 01454 } 01455 return true; 01456 01457 } else { 01458 if (bam_cat.is_spam()) { 01459 bam_cat.spam() 01460 << "not ready: complete_pointers for " << (void *)object 01461 << " (" << object->get_type() << ")\n"; 01462 } 01463 } 01464 01465 return false; 01466 } 01467 01468 //////////////////////////////////////////////////////////////////// 01469 // Function: BamReader::resolve_cycler_pointers 01470 // Access: Private 01471 // Description: Checks whether all of the pointers a particular 01472 // PipelineCycler is waiting for have been filled in 01473 // yet. If they have, calls complete_pointers() on the 01474 // cycler and returns true; otherwise, returns false. 01475 //////////////////////////////////////////////////////////////////// 01476 bool BamReader:: 01477 resolve_cycler_pointers(PipelineCyclerBase *cycler, 01478 const vector_int &pointer_ids, 01479 bool require_fully_complete) { 01480 // Now make sure we have all of the pointers this cycler is 01481 // waiting for. If any of the pointers has not yet been read 01482 // in, we can't resolve this cycler--we can't do anything for a 01483 // given cycler until we have *all* outstanding pointers for 01484 // that cycler. 01485 01486 bool is_complete = true; 01487 vector_typedWritable references; 01488 01489 vector_int::const_iterator pi; 01490 for (pi = pointer_ids.begin(); pi != pointer_ids.end() && is_complete; ++pi) { 01491 int child_id = (*pi); 01492 01493 if (child_id == 0) { 01494 // A NULL pointer is a NULL pointer. 01495 references.push_back((TypedWritable *)NULL); 01496 01497 } else { 01498 // See if we have the pointer available now. 01499 CreatedObjs::const_iterator oi = _created_objs.find(child_id); 01500 if (oi == _created_objs.end()) { 01501 // No, too bad. 01502 is_complete = false; 01503 01504 } else { 01505 const CreatedObj &child_obj = (*oi).second; 01506 if (child_obj._change_this != NULL || child_obj._change_this_ref != NULL) { 01507 // It's been created, but the pointer might still change. 01508 is_complete = false; 01509 01510 } else { 01511 if (require_fully_complete && 01512 _object_pointers.find(child_id) != _object_pointers.end()) { 01513 // It's not yet complete itself. 01514 is_complete = false; 01515 01516 } else { 01517 // Yes, it's ready. 01518 references.push_back(child_obj._ptr); 01519 } 01520 } 01521 } 01522 } 01523 } 01524 01525 if (is_complete) { 01526 // Okay, here's the complete list of pointers for you! 01527 CycleData *cdata = cycler->write(Thread::get_current_thread()); 01528 if (bam_cat.is_spam()) { 01529 bam_cat.spam() 01530 << "complete_pointers for CycleData object " << (void *)cdata 01531 << "\n"; 01532 } 01533 int num_completed = cdata->complete_pointers(&references[0], this); 01534 cycler->release_write(cdata); 01535 if (num_completed != (int)references.size()) { 01536 bam_cat.warning() 01537 << "CycleData object completed " << num_completed 01538 << " of " << references.size() << " pointers.\n"; 01539 nassertr(num_completed < (int)references.size(), true); 01540 } 01541 return true; 01542 } 01543 01544 return false; 01545 } 01546 01547 //////////////////////////////////////////////////////////////////// 01548 // Function: BamReader::finalize 01549 // Access: Private 01550 // Description: Should be called after all objects have been read, 01551 // this will finalize all the objects that registered 01552 // themselves for the finalize callback. 01553 //////////////////////////////////////////////////////////////////// 01554 void BamReader:: 01555 finalize() { 01556 if (bam_cat.is_debug()) { 01557 bam_cat.debug() 01558 << "Finalizing bam source\n"; 01559 } 01560 01561 Finalize::iterator fi = _finalize_list.begin(); 01562 while (fi != _finalize_list.end()) { 01563 TypedWritable *object = (*fi); 01564 nassertv(object != (TypedWritable *)NULL); 01565 _finalize_list.erase(fi); 01566 if (bam_cat.is_spam()) { 01567 bam_cat.spam() 01568 << "finalizing " << (void *)object << " (" << object->get_type() 01569 << ")\n"; 01570 } 01571 object->finalize(this); 01572 _aux_data.erase(object); 01573 fi = _finalize_list.begin(); 01574 } 01575 01576 // Now clear the aux data of all objects, except the NULL object. 01577 if (!_aux_data.empty()) { 01578 AuxDataTable::iterator ti = _aux_data.find((TypedWritable *)NULL); 01579 01580 if (ti != _aux_data.end()) { 01581 if (_aux_data.size() > 1) { 01582 // Move the NULL data to the new table; remove the rest. 01583 AuxDataTable new_aux_data; 01584 AuxDataTable::iterator nti = 01585 new_aux_data.insert(AuxDataTable::value_type(NULL, AuxDataNames())).first; 01586 (*nti).second.swap((*ti).second); 01587 _aux_data.swap(new_aux_data); 01588 } 01589 } else { 01590 // There's no NULL data; clear the whole table. 01591 _aux_data.clear(); 01592 } 01593 } 01594 } 01595 01596 //////////////////////////////////////////////////////////////////// 01597 // Function: BamReader::AuxData::Destructor 01598 // Access: Public, Virtual 01599 // Description: 01600 //////////////////////////////////////////////////////////////////// 01601 BamReader::AuxData:: 01602 ~AuxData() { 01603 } 01604