Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

pandatool/src/flt/fltRecord.cxx

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

Generated on Fri May 2 03:19:31 2003 for Panda-Tool by doxygen1.3