Panda3D
 All Classes Functions Variables Enumerations
fltRecord.cxx
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 }
 All Classes Functions Variables Enumerations