15 #include "fltRecord.h" 16 #include "fltRecordReader.h" 17 #include "fltRecordWriter.h" 18 #include "fltHeader.h" 20 #include "fltObject.h" 24 #include "fltLocalVertexPool.h" 25 #include "fltMeshPrimitive.h" 26 #include "fltVertexList.h" 28 #include "fltInstanceDefinition.h" 29 #include "fltInstanceRef.h" 30 #include "fltUnsupportedRecord.h" 31 #include "fltExternalReference.h" 32 #include "fltVectorRecord.h" 33 #include "config_flt.h" 37 #include "datagramIterator.h" 71 return _children.size();
81 nassertr(n >= 0 && n < (
int)_children.size(), (
FltRecord *)NULL);
103 _children.push_back(child);
116 return _subfaces.size();
126 nassertr(n >= 0 && n < (
int)_subfaces.size(), (
FltRecord *)NULL);
148 _subfaces.push_back(subface);
161 return _extensions.size();
171 nassertr(n >= 0 && n < (
int)_extensions.size(), (
FltRecord *)NULL);
172 return _extensions[n];
194 _extensions.push_back(extension);
209 return _ancillary.size();
220 nassertr(n >= 0 && n < (
int)_ancillary.size(), (
FltRecord *)NULL);
221 return _ancillary[n];
254 _ancillary.push_back(ancillary);
265 return !_comment.empty();
320 <<
" bytes at the end of a ";
326 nout <<
" record.\n";
341 Records::const_iterator ci;
342 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
343 (*ci)->apply_converted_filenames();
345 for (ci = _children.begin(); ci != _children.end(); ++ci) {
346 (*ci)->apply_converted_filenames();
372 write(ostream &out,
int indent_level)
const {
373 indent(out, indent_level) << *
this;
374 write_children(out, indent_level);
385 write_children(ostream &out,
int indent_level)
const {
386 if (!_ancillary.empty()) {
387 out <<
" + " << _ancillary.size() <<
" ancillary";
389 if (!_extensions.empty()) {
390 out <<
" + " << _extensions.size() <<
" extensions";
392 if (!_subfaces.empty()) {
394 Records::const_iterator ci;
395 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
396 out <<
" " << *(*ci);
400 if (!_children.empty()) {
402 Records::const_iterator ci;
403 for (ci = _children.begin(); ci != _children.end(); ++ci) {
404 (*ci)->write(out, indent_level + 2);
406 indent(out, indent_level) <<
"}\n";
429 is_ancillary(FltOpcode opcode) {
433 case FO_multitexture:
437 case FO_transform_matrix:
438 case FO_rotate_about_edge:
441 case FO_rotate_about_point:
442 case FO_rotate_and_scale:
444 case FO_general_matrix:
446 case FO_bounding_box:
447 case FO_bounding_sphere:
448 case FO_bounding_cylinder:
450 case FO_bv_orientation:
451 case FO_local_vertex_pool:
454 case FO_14_material_palette:
455 case FO_vertex_palette:
460 case FO_color_palette:
464 case FO_eyepoint_palette:
465 case FO_light_definition:
466 case FO_texture_map_palette:
471 case FO_mesh_primitive:
480 case FO_external_ref:
483 case FO_light_source:
484 case FO_road_segment:
485 case FO_road_construction:
499 case FO_push_attribute:
500 case FO_pop_attribute:
501 case FO_push_extension:
502 case FO_pop_extension:
504 case FO_instance_ref:
508 nout <<
"Don't know whether " << opcode <<
" is ancillary.\n";
521 create_new_record(FltOpcode opcode)
const {
538 case FO_local_vertex_pool:
541 case FO_mesh_primitive:
548 return new FltLOD(_header);
553 case FO_instance_ref:
556 case FO_external_ref:
563 nout <<
"Ignoring unsupported record " << opcode <<
"\n";
581 if (!extract_record(reader)) {
582 nout <<
"Could not extract record for " << *
this <<
"\n";
583 assert(!flt_error_abort);
584 return FE_invalid_record;
586 FltError result = reader.
advance();
587 if (result == FE_end_of_file) {
589 }
else if (result != FE_ok) {
594 if (extract_ancillary(reader)) {
600 if (result != FE_ok) {
606 FltError result = child->read_record_and_children(reader);
607 if (result != FE_ok) {
611 if (child->is_of_type(FltInstanceDefinition::get_class_type())) {
621 if (reader.
eof() || reader.
error()) {
622 assert(!flt_error_abort);
623 return FE_end_of_file;
627 }
else if (reader.
get_opcode() == FO_push_face) {
630 if (result != FE_ok) {
636 FltError result = subface->read_record_and_children(reader);
637 if (result != FE_ok) {
641 if (reader.
eof() || reader.
error()) {
642 assert(!flt_error_abort);
643 return FE_end_of_file;
647 }
else if (reader.
get_opcode() == FO_push_extension) {
650 if (result != FE_ok) {
654 while (reader.
get_opcode() != FO_pop_extension) {
656 FltError result = extension->read_record_and_children(reader);
657 if (result != FE_ok) {
661 if (reader.
eof() || reader.
error()) {
662 assert(!flt_error_abort);
663 return FE_end_of_file;
667 }
else if (is_ancillary(reader.
get_opcode())) {
670 ancillary->extract_record(reader);
671 _ancillary.push_back(ancillary);
680 if (reader.
eof() || result != FE_ok) {
728 if (!build_record(writer)) {
729 assert(!flt_error_abort);
733 FltError result = writer.
advance();
734 if (result != FE_ok) {
739 result = write_ancillary(writer);
740 if (result != FE_ok) {
743 Records::const_iterator ci;
744 for (ci = _ancillary.begin(); ci != _ancillary.end(); ++ci) {
745 if (!(*ci)->build_record(writer)) {
746 assert(!flt_error_abort);
750 if (result != FE_ok) {
756 if (!_extensions.empty()) {
758 if (result != FE_ok) {
762 for (ci = _extensions.begin(); ci != _extensions.end(); ++ci) {
763 (*ci)->write_record_and_children(writer);
767 if (result != FE_ok) {
773 if (!_children.empty()) {
775 if (result != FE_ok) {
779 for (ci = _children.begin(); ci != _children.end(); ++ci) {
780 (*ci)->write_record_and_children(writer);
784 if (result != FE_ok) {
791 if (!_subfaces.empty()) {
793 if (result != FE_ok) {
797 for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
798 (*ci)->write_record_and_children(writer);
802 if (result != FE_ok) {
832 if (!_comment.empty()) {
835 if (result != FE_ok) {
void clear_comment()
Removes the comment for this record.
This class writes a sequence of FltRecords to an ostream, handling opcode and size counts properly...
void clear_ancillary()
Removes all unsupported ancillary records from this record.
void clear_extensions()
Removes all extensions from this record.
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
void set_comment(const string &comment)
Changes the comment for this record.
FltRecord * get_ancillary(int n) const
Returns the nth unsupported ancillary record of this record.
int get_num_children() const
Returns the number of child records of this record.
FltRecord * get_extension(int n) const
Returns the nth extension of this record.
The main grouping bead of the flt file.
virtual void apply_converted_filenames()
Walks the hierarchy at this record and below and copies the _converted_filename record into the _orig...
bool error() const
Returns true if some error has been encountered while reading (for instance, a truncated file)...
void check_remaining_size(const DatagramIterator &di, const string &name=string()) const
Checks that the iterator has no bytes left, as it should at the end of a successfully read record...
A single primitive of a mesh, like a triangle strip or fan.
DatagramIterator & get_iterator()
Returns an iterator suitable for extracting data from the current record.
void add_child(FltRecord *child)
Adds a new child to the end of the list of children for this record.
bool has_comment() const
Returns true if this record has a nonempty comment, false otherwise.
A local vertex pool, as might appear in the middle of the hierarchy, for instance for a mesh...
FltRecord * get_subface(int n) const
Returns the nth subface of this record.
A mesh of connected polygons and tristrips, etc., with a local vertex pool.
virtual void output(ostream &out) const
Writes a quick one-line description of the record, but not its children.
A list of vertices, typically added as a child of a face bead.
const string & get_comment() const
Retrieves the comment for this record, or empty string if the record has no comment.
int get_remaining_size() const
Return the bytes left in the datagram.
The base class for all kinds of records in a MultiGen OpenFlight file.
This bead appears in the hierarchy to refer to a FltInstanceDefinition node defined elsewhere...
An external reference to another flt file (possibly to a specific bead within the flt file)...
FltError advance()
Writes the current record to the flt file, and resets the current record to receive new data...
The main objecting bead of the flt file.
FltRecord * get_child(int n) const
Returns the nth child of this record.
void add_extension(FltRecord *extension)
Adds a new extension to the end of the list of extensions for this record.
void add_subface(FltRecord *subface)
Adds a new subface to the end of the list of subfaces for this record.
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
A class to retrieve the individual data elements previously stored in a Datagram. ...
void add_ancillary(FltRecord *ancillary)
Adds a new unsupported ancillary record to the end of the list of ancillary records for this record...
TypeHandle is the identifier used to differentiate C++ class types.
string get_remaining_bytes() const
Returns the remaining bytes in the datagram as a string, but does not extract them from the iterator...
A single curve, like a Bezier or B-Spline.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
A Level-of-Detail record.
FltError advance(bool ok_eof=false)
Extracts the next record from the file.
int get_num_ancillary() const
Returns the number of unsupported ancillary records of this record.
void clear_children()
Removes all children from this record.
void clear_subfaces()
Removes all subfaces from this record.
This special kind of record marks the top node of an instance subtree.
This is an ancillary record of the old (pre-15.4) face node.
int get_num_subfaces() const
Returns the number of subface records of this record.
virtual void write(ostream &out, int indent_level=0) const
Writes a multiple-line description of the record and all of its children.
int get_num_extensions() const
Returns the number of extension attribute records for this object.
bool eof() const
Returns true if end-of-file has been reached without error.
FltError write_record(FltOpcode opcode, const Datagram &datagram=Datagram())
A convenience function to quickly write a simple record that consists of an opcode and possibly a dat...