Panda3D
|
00001 // Filename: fltRecord.cxx 00002 // Created by: drose (24Aug00) 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 "fltRecord.h" 00016 #include "fltRecordReader.h" 00017 #include "fltRecordWriter.h" 00018 #include "fltHeader.h" 00019 #include "fltGroup.h" 00020 #include "fltObject.h" 00021 #include "fltFace.h" 00022 #include "fltCurve.h" 00023 #include "fltMesh.h" 00024 #include "fltLocalVertexPool.h" 00025 #include "fltMeshPrimitive.h" 00026 #include "fltVertexList.h" 00027 #include "fltLOD.h" 00028 #include "fltInstanceDefinition.h" 00029 #include "fltInstanceRef.h" 00030 #include "fltUnsupportedRecord.h" 00031 #include "fltExternalReference.h" 00032 #include "fltVectorRecord.h" 00033 #include "config_flt.h" 00034 00035 #include "dcast.h" 00036 #include "indent.h" 00037 #include "datagramIterator.h" 00038 00039 #include <assert.h> 00040 00041 TypeHandle FltRecord::_type_handle; 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: FltRecord::Constructor 00045 // Access: Public 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 FltRecord:: 00049 FltRecord(FltHeader *header) : 00050 _header(header) 00051 { 00052 } 00053 00054 //////////////////////////////////////////////////////////////////// 00055 // Function: FltRecord::Destructor 00056 // Access: Public, Virtual 00057 // Description: 00058 //////////////////////////////////////////////////////////////////// 00059 FltRecord:: 00060 ~FltRecord() { 00061 } 00062 00063 //////////////////////////////////////////////////////////////////// 00064 // Function: FltRecord::get_num_children 00065 // Access: Public 00066 // Description: Returns the number of child records of this record. 00067 // This reflects the normal scene graph hierarchy. 00068 //////////////////////////////////////////////////////////////////// 00069 int FltRecord:: 00070 get_num_children() const { 00071 return _children.size(); 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: FltRecord::get_child 00076 // Access: Public 00077 // Description: Returns the nth child of this record. 00078 //////////////////////////////////////////////////////////////////// 00079 FltRecord *FltRecord:: 00080 get_child(int n) const { 00081 nassertr(n >= 0 && n < (int)_children.size(), (FltRecord *)NULL); 00082 return _children[n]; 00083 } 00084 00085 //////////////////////////////////////////////////////////////////// 00086 // Function: FltRecord::clear_children 00087 // Access: Public 00088 // Description: Removes all children from this record. 00089 //////////////////////////////////////////////////////////////////// 00090 void FltRecord:: 00091 clear_children() { 00092 _children.clear(); 00093 } 00094 00095 //////////////////////////////////////////////////////////////////// 00096 // Function: FltRecord::add_child 00097 // Access: Public 00098 // Description: Adds a new child to the end of the list of children 00099 // for this record. 00100 //////////////////////////////////////////////////////////////////// 00101 void FltRecord:: 00102 add_child(FltRecord *child) { 00103 _children.push_back(child); 00104 } 00105 00106 //////////////////////////////////////////////////////////////////// 00107 // Function: FltRecord::get_num_subfaces 00108 // Access: Public 00109 // Description: Returns the number of subface records of this record. 00110 // Normally, subfaces will only be present on object 00111 // records, although it is logically possible for them to 00112 // appear anywhere. 00113 //////////////////////////////////////////////////////////////////// 00114 int FltRecord:: 00115 get_num_subfaces() const { 00116 return _subfaces.size(); 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: FltRecord::get_subface 00121 // Access: Public 00122 // Description: Returns the nth subface of this record. 00123 //////////////////////////////////////////////////////////////////// 00124 FltRecord *FltRecord:: 00125 get_subface(int n) const { 00126 nassertr(n >= 0 && n < (int)_subfaces.size(), (FltRecord *)NULL); 00127 return _subfaces[n]; 00128 } 00129 00130 //////////////////////////////////////////////////////////////////// 00131 // Function: FltRecord::clear_subfaces 00132 // Access: Public 00133 // Description: Removes all subfaces from this record. 00134 //////////////////////////////////////////////////////////////////// 00135 void FltRecord:: 00136 clear_subfaces() { 00137 _subfaces.clear(); 00138 } 00139 00140 //////////////////////////////////////////////////////////////////// 00141 // Function: FltRecord::add_subface 00142 // Access: Public 00143 // Description: Adds a new subface to the end of the list of subfaces 00144 // for this record. 00145 //////////////////////////////////////////////////////////////////// 00146 void FltRecord:: 00147 add_subface(FltRecord *subface) { 00148 _subfaces.push_back(subface); 00149 } 00150 00151 //////////////////////////////////////////////////////////////////// 00152 // Function: FltRecord::get_num_extensions 00153 // Access: Public 00154 // Description: Returns the number of extension attribute records for 00155 // this object. These are auxiliary nodes, presumably 00156 // of type FO_extension, that have some local meaning to 00157 // the object. 00158 //////////////////////////////////////////////////////////////////// 00159 int FltRecord:: 00160 get_num_extensions() const { 00161 return _extensions.size(); 00162 } 00163 00164 //////////////////////////////////////////////////////////////////// 00165 // Function: FltRecord::get_extension 00166 // Access: Public 00167 // Description: Returns the nth extension of this record. 00168 //////////////////////////////////////////////////////////////////// 00169 FltRecord *FltRecord:: 00170 get_extension(int n) const { 00171 nassertr(n >= 0 && n < (int)_extensions.size(), (FltRecord *)NULL); 00172 return _extensions[n]; 00173 } 00174 00175 //////////////////////////////////////////////////////////////////// 00176 // Function: FltRecord::clear_extensions 00177 // Access: Public 00178 // Description: Removes all extensions from this record. 00179 //////////////////////////////////////////////////////////////////// 00180 void FltRecord:: 00181 clear_extensions() { 00182 _extensions.clear(); 00183 } 00184 00185 //////////////////////////////////////////////////////////////////// 00186 // Function: FltRecord::add_extension 00187 // Access: Public 00188 // Description: Adds a new extension to the end of the list of 00189 // extensions for this record. This should be a record 00190 // of type FO_extension. 00191 //////////////////////////////////////////////////////////////////// 00192 void FltRecord:: 00193 add_extension(FltRecord *extension) { 00194 _extensions.push_back(extension); 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: FltRecord::get_num_ancillary 00199 // Access: Public 00200 // Description: Returns the number of unsupported ancillary records 00201 // of this record. These are ancillary records that 00202 // appeared following this record in the flt file but that 00203 // aren't directly understood by the flt 00204 // loader--normally, an ancillary record is examined and 00205 // decoded on the spot, and no pointer to it is kept. 00206 //////////////////////////////////////////////////////////////////// 00207 int FltRecord:: 00208 get_num_ancillary() const { 00209 return _ancillary.size(); 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: FltRecord::get_ancillary 00214 // Access: Public 00215 // Description: Returns the nth unsupported ancillary record of this 00216 // record. See get_num_ancillary(). 00217 //////////////////////////////////////////////////////////////////// 00218 FltRecord *FltRecord:: 00219 get_ancillary(int n) const { 00220 nassertr(n >= 0 && n < (int)_ancillary.size(), (FltRecord *)NULL); 00221 return _ancillary[n]; 00222 } 00223 00224 //////////////////////////////////////////////////////////////////// 00225 // Function: FltRecord::clear_ancillary 00226 // Access: Public 00227 // Description: Removes all unsupported ancillary records from this 00228 // record. See get_num_ancillary(). 00229 //////////////////////////////////////////////////////////////////// 00230 void FltRecord:: 00231 clear_ancillary() { 00232 _ancillary.clear(); 00233 } 00234 00235 //////////////////////////////////////////////////////////////////// 00236 // Function: FltRecord::add_ancillary 00237 // Access: Public 00238 // Description: Adds a new unsupported ancillary record to the end of 00239 // the list of ancillary records for this record. This 00240 // record will be written to the flt file following this 00241 // record, without attempting to understand what is in it. 00242 // 00243 // Normally, there is no reason to use this function; if 00244 // the data stored in the FltRecord requires one or more 00245 // ancillary record, the appropriate records will 00246 // automatically be generated when the record is written. 00247 // This function is only required to output a record 00248 // whose type is not supported by the flt loader. But 00249 // it would be better to extend the flt loader to know 00250 // about this new kind of data record. 00251 //////////////////////////////////////////////////////////////////// 00252 void FltRecord:: 00253 add_ancillary(FltRecord *ancillary) { 00254 _ancillary.push_back(ancillary); 00255 } 00256 00257 //////////////////////////////////////////////////////////////////// 00258 // Function: FltRecord::has_comment 00259 // Access: Public 00260 // Description: Returns true if this record has a nonempty comment, 00261 // false otherwise. 00262 //////////////////////////////////////////////////////////////////// 00263 bool FltRecord:: 00264 has_comment() const { 00265 return !_comment.empty(); 00266 } 00267 00268 //////////////////////////////////////////////////////////////////// 00269 // Function: FltRecord::get_comment 00270 // Access: Public 00271 // Description: Retrieves the comment for this record, or empty 00272 // string if the record has no comment. 00273 //////////////////////////////////////////////////////////////////// 00274 const string &FltRecord:: 00275 get_comment() const { 00276 return _comment; 00277 } 00278 00279 //////////////////////////////////////////////////////////////////// 00280 // Function: FltRecord::clear_comment 00281 // Access: Public 00282 // Description: Removes the comment for this record. 00283 //////////////////////////////////////////////////////////////////// 00284 void FltRecord:: 00285 clear_comment() { 00286 _comment = ""; 00287 } 00288 00289 //////////////////////////////////////////////////////////////////// 00290 // Function: FltRecord::set_comment 00291 // Access: Public 00292 // Description: Changes the comment for this record. 00293 //////////////////////////////////////////////////////////////////// 00294 void FltRecord:: 00295 set_comment(const string &comment) { 00296 _comment = comment; 00297 } 00298 00299 //////////////////////////////////////////////////////////////////// 00300 // Function: FltRecord::check_remaining_size 00301 // Access: Public 00302 // Description: Checks that the iterator has no bytes left, as it 00303 // should at the end of a successfully read record. If 00304 // there *are* remaining bytes, print a warning message 00305 // but otherwise don't worry about it. 00306 // 00307 // If we are attempting to read a flt file whose version 00308 // is newer than the newest this program understands, 00309 // don't even print a warning message, since this is 00310 // exactly the sort of thing we expect. 00311 //////////////////////////////////////////////////////////////////// 00312 void FltRecord:: 00313 check_remaining_size(const DatagramIterator &di, const string &name) const { 00314 if (di.get_remaining_size() == 0) { 00315 return; 00316 } 00317 00318 if (_header->get_flt_version() <= _header->max_flt_version()) { 00319 nout << "Warning! Ignoring extra " << di.get_remaining_size() 00320 << " bytes at the end of a "; 00321 if (name.empty()) { 00322 nout << get_type(); 00323 } else { 00324 nout << name; 00325 } 00326 nout << " record.\n"; 00327 } 00328 } 00329 00330 //////////////////////////////////////////////////////////////////// 00331 // Function: FltRecord::apply_converted_filenames 00332 // Access: Public, Virtual 00333 // Description: Walks the hierarchy at this record and below and 00334 // copies the _converted_filename record into the 00335 // _orig_filename record, so the flt file will be 00336 // written out with the converted filename instead of 00337 // what was originally read in. 00338 //////////////////////////////////////////////////////////////////// 00339 void FltRecord:: 00340 apply_converted_filenames() { 00341 Records::const_iterator ci; 00342 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { 00343 (*ci)->apply_converted_filenames(); 00344 } 00345 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00346 (*ci)->apply_converted_filenames(); 00347 } 00348 } 00349 00350 //////////////////////////////////////////////////////////////////// 00351 // Function: FltRecord::output 00352 // Access: Public 00353 // Description: Writes a quick one-line description of the record, but 00354 // not its children. This is a human-readable 00355 // description, primarily for debugging; to write a flt 00356 // file, use FltHeader::write_flt(). 00357 //////////////////////////////////////////////////////////////////// 00358 void FltRecord:: 00359 output(ostream &out) const { 00360 out << get_type(); 00361 } 00362 00363 //////////////////////////////////////////////////////////////////// 00364 // Function: FltRecord::write 00365 // Access: Public 00366 // Description: Writes a multiple-line description of the record and 00367 // all of its children. This is a human-readable 00368 // description, primarily for debugging; to write a flt 00369 // file, use FltHeader::write_flt(). 00370 //////////////////////////////////////////////////////////////////// 00371 void FltRecord:: 00372 write(ostream &out, int indent_level) const { 00373 indent(out, indent_level) << *this; 00374 write_children(out, indent_level); 00375 } 00376 00377 //////////////////////////////////////////////////////////////////// 00378 // Function: FltRecord::write_children 00379 // Access: Protected 00380 // Description: Assuming the current write position has been left at 00381 // the end of the last line of the record description, 00382 // writes out the list of children. 00383 //////////////////////////////////////////////////////////////////// 00384 void FltRecord:: 00385 write_children(ostream &out, int indent_level) const { 00386 if (!_ancillary.empty()) { 00387 out << " + " << _ancillary.size() << " ancillary"; 00388 } 00389 if (!_extensions.empty()) { 00390 out << " + " << _extensions.size() << " extensions"; 00391 } 00392 if (!_subfaces.empty()) { 00393 out << " ["; 00394 Records::const_iterator ci; 00395 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { 00396 out << " " << *(*ci); 00397 } 00398 out << " ]"; 00399 } 00400 if (!_children.empty()) { 00401 out << " {\n"; 00402 Records::const_iterator ci; 00403 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00404 (*ci)->write(out, indent_level + 2); 00405 } 00406 indent(out, indent_level) << "}\n"; 00407 } else { 00408 out << "\n"; 00409 } 00410 } 00411 00412 /* 00413 virtual void write(ostream &out) const; 00414 virtual void build_record(Datagram &datagram) const; 00415 */ 00416 00417 //////////////////////////////////////////////////////////////////// 00418 // Function: FltRecord::is_ancillary 00419 // Access: Protected, Static 00420 // Description: Returns true if the indicated opcode corresponds to 00421 // an ancillary record type, false otherwise. In 00422 // general, this function is used to identify ancillary 00423 // records that are not presently supported by the 00424 // FltReader; these will be ignored. Normally, 00425 // ancillary records will be detected and processed by 00426 // extract_ancillary(). 00427 //////////////////////////////////////////////////////////////////// 00428 bool FltRecord:: 00429 is_ancillary(FltOpcode opcode) { 00430 switch (opcode) { 00431 case FO_comment: 00432 case FO_long_id: 00433 case FO_multitexture: 00434 case FO_uv_list: 00435 case FO_replicate: 00436 case FO_road_zone: 00437 case FO_transform_matrix: 00438 case FO_rotate_about_edge: 00439 case FO_translate: 00440 case FO_scale: 00441 case FO_rotate_about_point: 00442 case FO_rotate_and_scale: 00443 case FO_put: 00444 case FO_general_matrix: 00445 case FO_vector: 00446 case FO_bounding_box: 00447 case FO_bounding_sphere: 00448 case FO_bounding_cylinder: 00449 case FO_bv_center: 00450 case FO_bv_orientation: 00451 case FO_local_vertex_pool: 00452 case FO_cat_data: 00453 00454 case FO_14_material_palette: 00455 case FO_vertex_palette: 00456 case FO_vertex_c: 00457 case FO_vertex_cn: 00458 case FO_vertex_cnu: 00459 case FO_vertex_cu: 00460 case FO_color_palette: 00461 case FO_name_table: 00462 case FO_15_material: 00463 case FO_texture: 00464 case FO_eyepoint_palette: 00465 case FO_light_definition: 00466 case FO_texture_map_palette: 00467 return true; 00468 00469 case FO_header: 00470 case FO_mesh: 00471 case FO_mesh_primitive: 00472 case FO_group: 00473 case FO_object: 00474 case FO_face: 00475 case FO_light_point: 00476 case FO_dof: 00477 case FO_vertex_list: 00478 case FO_morph_list: 00479 case FO_bsp: 00480 case FO_external_ref: 00481 case FO_lod: 00482 case FO_sound: 00483 case FO_light_source: 00484 case FO_road_segment: 00485 case FO_road_construction: 00486 case FO_road_path: 00487 case FO_clip_region: 00488 case FO_text: 00489 case FO_switch: 00490 case FO_cat: 00491 case FO_extension: 00492 case FO_curve: 00493 return false; 00494 00495 case FO_push: 00496 case FO_pop: 00497 case FO_push_face: 00498 case FO_pop_face: 00499 case FO_push_attribute: 00500 case FO_pop_attribute: 00501 case FO_push_extension: 00502 case FO_pop_extension: 00503 case FO_instance: 00504 case FO_instance_ref: 00505 return false; 00506 00507 default: 00508 nout << "Don't know whether " << opcode << " is ancillary.\n"; 00509 return false; 00510 } 00511 } 00512 00513 //////////////////////////////////////////////////////////////////// 00514 // Function: FltRecord::create_new_record 00515 // Access: Protected 00516 // Description: Creates a new FltRecord corresponding to the opcode. 00517 // If the opcode is unknown, creates a 00518 // FltUnsupportedRecord. 00519 //////////////////////////////////////////////////////////////////// 00520 FltRecord *FltRecord:: 00521 create_new_record(FltOpcode opcode) const { 00522 switch (opcode) { 00523 case FO_group: 00524 return new FltGroup(_header); 00525 00526 case FO_object: 00527 return new FltObject(_header); 00528 00529 case FO_face: 00530 return new FltFace(_header); 00531 00532 case FO_curve: 00533 return new FltCurve(_header); 00534 00535 case FO_mesh: 00536 return new FltMesh(_header); 00537 00538 case FO_local_vertex_pool: 00539 return new FltLocalVertexPool(_header); 00540 00541 case FO_mesh_primitive: 00542 return new FltMeshPrimitive(_header); 00543 00544 case FO_vertex_list: 00545 return new FltVertexList(_header); 00546 00547 case FO_lod: 00548 return new FltLOD(_header); 00549 00550 case FO_instance: 00551 return new FltInstanceDefinition(_header); 00552 00553 case FO_instance_ref: 00554 return new FltInstanceRef(_header); 00555 00556 case FO_external_ref: 00557 return new FltExternalReference(_header); 00558 00559 case FO_vector: 00560 return new FltVectorRecord(_header); 00561 00562 default: 00563 nout << "Ignoring unsupported record " << opcode << "\n"; 00564 return new FltUnsupportedRecord(_header); 00565 } 00566 } 00567 00568 //////////////////////////////////////////////////////////////////// 00569 // Function: FltRecord::read_record_and_children 00570 // Access: Protected 00571 // Description: Extracts this record information from the current 00572 // record presented in the reader, then advances the 00573 // reader and continues to read any children, if 00574 // present. On return, the reader is position on the 00575 // next sibling record to this record. 00576 // 00577 // Returns FE_ok if successful, otherwise on error. 00578 //////////////////////////////////////////////////////////////////// 00579 FltError FltRecord:: 00580 read_record_and_children(FltRecordReader &reader) { 00581 if (!extract_record(reader)) { 00582 nout << "Could not extract record for " << *this << "\n"; 00583 assert(!flt_error_abort); 00584 return FE_invalid_record; 00585 } 00586 FltError result = reader.advance(); 00587 if (result == FE_end_of_file) { 00588 return FE_ok; 00589 } else if (result != FE_ok) { 00590 return result; 00591 } 00592 00593 while (true) { 00594 if (extract_ancillary(reader)) { 00595 // Ok, a known ancillary record. Fine. 00596 00597 } else if (reader.get_opcode() == FO_push) { 00598 // A push begins a new list of children. 00599 result = reader.advance(); 00600 if (result != FE_ok) { 00601 return result; 00602 } 00603 00604 while (reader.get_opcode() != FO_pop) { 00605 PT(FltRecord) child = create_new_record(reader.get_opcode()); 00606 FltError result = child->read_record_and_children(reader); 00607 if (result != FE_ok) { 00608 return result; 00609 } 00610 00611 if (child->is_of_type(FltInstanceDefinition::get_class_type())) { 00612 // A special case for an instance definition. These 00613 // shouldn't appear in the hierarchy, but should instead be 00614 // added directly to the header. 00615 _header->add_instance(DCAST(FltInstanceDefinition, child)); 00616 00617 } else { 00618 add_child(child); 00619 } 00620 00621 if (reader.eof() || reader.error()) { 00622 assert(!flt_error_abort); 00623 return FE_end_of_file; 00624 } 00625 } 00626 00627 } else if (reader.get_opcode() == FO_push_face) { 00628 // A push subface begins a new list of subfaces. 00629 result = reader.advance(); 00630 if (result != FE_ok) { 00631 return result; 00632 } 00633 00634 while (reader.get_opcode() != FO_pop_face) { 00635 PT(FltRecord) subface = create_new_record(reader.get_opcode()); 00636 FltError result = subface->read_record_and_children(reader); 00637 if (result != FE_ok) { 00638 return result; 00639 } 00640 add_subface(subface); 00641 if (reader.eof() || reader.error()) { 00642 assert(!flt_error_abort); 00643 return FE_end_of_file; 00644 } 00645 } 00646 00647 } else if (reader.get_opcode() == FO_push_extension) { 00648 // A push extension begins a new list of extensions. 00649 result = reader.advance(); 00650 if (result != FE_ok) { 00651 return result; 00652 } 00653 00654 while (reader.get_opcode() != FO_pop_extension) { 00655 PT(FltRecord) extension = create_new_record(reader.get_opcode()); 00656 FltError result = extension->read_record_and_children(reader); 00657 if (result != FE_ok) { 00658 return result; 00659 } 00660 add_extension(extension); 00661 if (reader.eof() || reader.error()) { 00662 assert(!flt_error_abort); 00663 return FE_end_of_file; 00664 } 00665 } 00666 00667 } else if (is_ancillary(reader.get_opcode())) { 00668 // An unsupported ancillary record. Skip it. 00669 PT(FltRecord) ancillary = create_new_record(reader.get_opcode()); 00670 ancillary->extract_record(reader); 00671 _ancillary.push_back(ancillary); 00672 00673 } else { 00674 // None of the above: we're done. 00675 return FE_ok; 00676 } 00677 00678 // Skip to the next record. If that's the end, fine. 00679 result = reader.advance(true); 00680 if (reader.eof() || result != FE_ok) { 00681 return result; 00682 } 00683 } 00684 } 00685 00686 //////////////////////////////////////////////////////////////////// 00687 // Function: FltRecord::extract_record 00688 // Access: Protected, Virtual 00689 // Description: Fills in the information in this record based on the 00690 // information given in the indicated datagram, whose 00691 // opcode has already been read. Returns true on 00692 // success, false if the datagram is invalid. 00693 //////////////////////////////////////////////////////////////////// 00694 bool FltRecord:: 00695 extract_record(FltRecordReader &) { 00696 return true; 00697 } 00698 00699 //////////////////////////////////////////////////////////////////// 00700 // Function: FltRecord::extract_ancillary 00701 // Access: Protected, Virtual 00702 // Description: Checks whether the given record, which follows this 00703 // record sequentially in the file, is an ancillary record 00704 // of this record. If it is, extracts the relevant 00705 // information and returns true; otherwise, leaves it 00706 // alone and returns false. 00707 //////////////////////////////////////////////////////////////////// 00708 bool FltRecord:: 00709 extract_ancillary(FltRecordReader &reader) { 00710 if (reader.get_opcode() == FO_comment) { 00711 _comment = reader.get_iterator().get_remaining_bytes(); 00712 return true; 00713 } 00714 00715 return false; 00716 } 00717 00718 //////////////////////////////////////////////////////////////////// 00719 // Function: FltRecord::write_record_and_children 00720 // Access: Protected, Virtual 00721 // Description: Writes this record out to the flt file, along with all 00722 // of its ancillary records and children records. Returns 00723 // FE_ok on success, or something else on error. 00724 //////////////////////////////////////////////////////////////////// 00725 FltError FltRecord:: 00726 write_record_and_children(FltRecordWriter &writer) const { 00727 // First, write the record. 00728 if (!build_record(writer)) { 00729 assert(!flt_error_abort); 00730 return FE_bad_data; 00731 } 00732 00733 FltError result = writer.advance(); 00734 if (result != FE_ok) { 00735 return result; 00736 } 00737 00738 // Then the ancillary data. 00739 result = write_ancillary(writer); 00740 if (result != FE_ok) { 00741 return result; 00742 } 00743 Records::const_iterator ci; 00744 for (ci = _ancillary.begin(); ci != _ancillary.end(); ++ci) { 00745 if (!(*ci)->build_record(writer)) { 00746 assert(!flt_error_abort); 00747 return FE_bad_data; 00748 } 00749 result = writer.advance(); 00750 if (result != FE_ok) { 00751 return result; 00752 } 00753 } 00754 00755 // Any extensions? 00756 if (!_extensions.empty()) { 00757 result = writer.write_record(FO_push_face); 00758 if (result != FE_ok) { 00759 return result; 00760 } 00761 00762 for (ci = _extensions.begin(); ci != _extensions.end(); ++ci) { 00763 (*ci)->write_record_and_children(writer); 00764 } 00765 00766 result = writer.write_record(FO_pop_face); 00767 if (result != FE_ok) { 00768 return result; 00769 } 00770 } 00771 00772 // Finally, write all the children. 00773 if (!_children.empty()) { 00774 result = writer.write_record(FO_push); 00775 if (result != FE_ok) { 00776 return result; 00777 } 00778 00779 for (ci = _children.begin(); ci != _children.end(); ++ci) { 00780 (*ci)->write_record_and_children(writer); 00781 } 00782 00783 result = writer.write_record(FO_pop); 00784 if (result != FE_ok) { 00785 return result; 00786 } 00787 } 00788 00789 // We must write subfaces *after* the list of children, or Creator 00790 // will crash trying to load the file. 00791 if (!_subfaces.empty()) { 00792 result = writer.write_record(FO_push_face); 00793 if (result != FE_ok) { 00794 return result; 00795 } 00796 00797 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) { 00798 (*ci)->write_record_and_children(writer); 00799 } 00800 00801 result = writer.write_record(FO_pop_face); 00802 if (result != FE_ok) { 00803 return result; 00804 } 00805 } 00806 00807 return FE_ok; 00808 } 00809 00810 //////////////////////////////////////////////////////////////////// 00811 // Function: FltRecord::build_record 00812 // Access: Protected, Virtual 00813 // Description: Fills up the current record on the FltRecordWriter with 00814 // data for this record, but does not advance the 00815 // writer. Returns true on success, false if there is 00816 // some error. 00817 //////////////////////////////////////////////////////////////////// 00818 bool FltRecord:: 00819 build_record(FltRecordWriter &) const { 00820 return true; 00821 } 00822 00823 //////////////////////////////////////////////////////////////////// 00824 // Function: FltRecord::write_ancillary 00825 // Access: Protected, Virtual 00826 // Description: Writes whatever ancillary records are required for 00827 // this record. Returns FE_ok on success, or something 00828 // else if there is some error. 00829 //////////////////////////////////////////////////////////////////// 00830 FltError FltRecord:: 00831 write_ancillary(FltRecordWriter &writer) const { 00832 if (!_comment.empty()) { 00833 Datagram dc(_comment); 00834 FltError result = writer.write_record(FO_comment, dc); 00835 if (result != FE_ok) { 00836 return result; 00837 } 00838 } 00839 return FE_ok; 00840 }