Panda3D
fltRecord.cxx
Go to the documentation of this file.
1 /**
2  * PANDA 3D SOFTWARE
3  * Copyright (c) Carnegie Mellon University. All rights reserved.
4  *
5  * All use of this software is subject to the terms of the revised BSD
6  * license. You should have received a copy of this license along
7  * with this source code in a file named "LICENSE."
8  *
9  * @file fltRecord.cxx
10  * @author drose
11  * @date 2000-08-24
12  */
13 
14 #include "fltRecord.h"
15 #include "fltRecordReader.h"
16 #include "fltRecordWriter.h"
17 #include "fltHeader.h"
18 #include "fltGroup.h"
19 #include "fltObject.h"
20 #include "fltFace.h"
21 #include "fltCurve.h"
22 #include "fltMesh.h"
23 #include "fltLocalVertexPool.h"
24 #include "fltMeshPrimitive.h"
25 #include "fltVertexList.h"
26 #include "fltLOD.h"
27 #include "fltInstanceDefinition.h"
28 #include "fltInstanceRef.h"
29 #include "fltUnsupportedRecord.h"
30 #include "fltExternalReference.h"
31 #include "fltVectorRecord.h"
32 #include "config_flt.h"
33 
34 #include "dcast.h"
35 #include "indent.h"
36 #include "datagramIterator.h"
37 
38 #include <assert.h>
39 
40 TypeHandle FltRecord::_type_handle;
41 
42 /**
43  *
44  */
45 FltRecord::
46 FltRecord(FltHeader *header) :
47  _header(header)
48 {
49 }
50 
51 /**
52  *
53  */
54 FltRecord::
55 ~FltRecord() {
56 }
57 
58 /**
59  * Returns the number of child records of this record. This reflects the
60  * normal scene graph hierarchy.
61  */
62 int FltRecord::
64  return _children.size();
65 }
66 
67 /**
68  * Returns the nth child of this record.
69  */
71 get_child(int n) const {
72  nassertr(n >= 0 && n < (int)_children.size(), nullptr);
73  return _children[n];
74 }
75 
76 /**
77  * Removes all children from this record.
78  */
79 void FltRecord::
81  _children.clear();
82 }
83 
84 /**
85  * Adds a new child to the end of the list of children for this record.
86  */
87 void FltRecord::
89  _children.push_back(child);
90 }
91 
92 /**
93  * Returns the number of subface records of this record. Normally, subfaces
94  * will only be present on object records, although it is logically possible
95  * for them to appear anywhere.
96  */
97 int FltRecord::
99  return _subfaces.size();
100 }
101 
102 /**
103  * Returns the nth subface of this record.
104  */
106 get_subface(int n) const {
107  nassertr(n >= 0 && n < (int)_subfaces.size(), nullptr);
108  return _subfaces[n];
109 }
110 
111 /**
112  * Removes all subfaces from this record.
113  */
114 void FltRecord::
116  _subfaces.clear();
117 }
118 
119 /**
120  * Adds a new subface to the end of the list of subfaces for this record.
121  */
122 void FltRecord::
124  _subfaces.push_back(subface);
125 }
126 
127 /**
128  * Returns the number of extension attribute records for this object. These
129  * are auxiliary nodes, presumably of type FO_extension, that have some local
130  * meaning to the object.
131  */
132 int FltRecord::
134  return _extensions.size();
135 }
136 
137 /**
138  * Returns the nth extension of this record.
139  */
141 get_extension(int n) const {
142  nassertr(n >= 0 && n < (int)_extensions.size(), nullptr);
143  return _extensions[n];
144 }
145 
146 /**
147  * Removes all extensions from this record.
148  */
149 void FltRecord::
151  _extensions.clear();
152 }
153 
154 /**
155  * Adds a new extension to the end of the list of extensions for this record.
156  * This should be a record of type FO_extension.
157  */
158 void FltRecord::
160  _extensions.push_back(extension);
161 }
162 
163 /**
164  * Returns the number of unsupported ancillary records of this record. These
165  * are ancillary records that appeared following this record in the flt file
166  * but that aren't directly understood by the flt loader--normally, an
167  * ancillary record is examined and decoded on the spot, and no pointer to it
168  * is kept.
169  */
170 int FltRecord::
172  return _ancillary.size();
173 }
174 
175 /**
176  * Returns the nth unsupported ancillary record of this record. See
177  * get_num_ancillary().
178  */
180 get_ancillary(int n) const {
181  nassertr(n >= 0 && n < (int)_ancillary.size(), nullptr);
182  return _ancillary[n];
183 }
184 
185 /**
186  * Removes all unsupported ancillary records from this record. See
187  * get_num_ancillary().
188  */
189 void FltRecord::
191  _ancillary.clear();
192 }
193 
194 /**
195  * Adds a new unsupported ancillary record to the end of the list of ancillary
196  * records for this record. This record will be written to the flt file
197  * following this record, without attempting to understand what is in it.
198  *
199  * Normally, there is no reason to use this function; if the data stored in
200  * the FltRecord requires one or more ancillary record, the appropriate
201  * records will automatically be generated when the record is written. This
202  * function is only required to output a record whose type is not supported by
203  * the flt loader. But it would be better to extend the flt loader to know
204  * about this new kind of data record.
205  */
206 void FltRecord::
208  _ancillary.push_back(ancillary);
209 }
210 
211 /**
212  * Returns true if this record has a nonempty comment, false otherwise.
213  */
214 bool FltRecord::
215 has_comment() const {
216  return !_comment.empty();
217 }
218 
219 /**
220  * Retrieves the comment for this record, or empty string if the record has no
221  * comment.
222  */
223 const std::string &FltRecord::
224 get_comment() const {
225  return _comment;
226 }
227 
228 /**
229  * Removes the comment for this record.
230  */
231 void FltRecord::
233  _comment = "";
234 }
235 
236 /**
237  * Changes the comment for this record.
238  */
239 void FltRecord::
240 set_comment(const std::string &comment) {
241  _comment = comment;
242 }
243 
244 /**
245  * Checks that the iterator has no bytes left, as it should at the end of a
246  * successfully read record. If there *are* remaining bytes, print a warning
247  * message but otherwise don't worry about it.
248  *
249  * If we are attempting to read a flt file whose version is newer than the
250  * newest this program understands, don't even print a warning message, since
251  * this is exactly the sort of thing we expect.
252  */
253 void FltRecord::
254 check_remaining_size(const DatagramIterator &di, const std::string &name) const {
255  if (di.get_remaining_size() == 0) {
256  return;
257  }
258 
259  if (_header->get_flt_version() <= _header->max_flt_version()) {
260  nout << "Warning! Ignoring extra " << di.get_remaining_size()
261  << " bytes at the end of a ";
262  if (name.empty()) {
263  nout << get_type();
264  } else {
265  nout << name;
266  }
267  nout << " record.\n";
268  }
269 }
270 
271 /**
272  * Walks the hierarchy at this record and below and copies the
273  * _converted_filename record into the _orig_filename record, so the flt file
274  * will be written out with the converted filename instead of what was
275  * originally read in.
276  */
277 void FltRecord::
279  Records::const_iterator ci;
280  for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
281  (*ci)->apply_converted_filenames();
282  }
283  for (ci = _children.begin(); ci != _children.end(); ++ci) {
284  (*ci)->apply_converted_filenames();
285  }
286 }
287 
288 /**
289  * Writes a quick one-line description of the record, but not its children.
290  * This is a human-readable description, primarily for debugging; to write a
291  * flt file, use FltHeader::write_flt().
292  */
293 void FltRecord::
294 output(std::ostream &out) const {
295  out << get_type();
296 }
297 
298 /**
299  * Writes a multiple-line description of the record and all of its children.
300  * This is a human-readable description, primarily for debugging; to write a
301  * flt file, use FltHeader::write_flt().
302  */
303 void FltRecord::
304 write(std::ostream &out, int indent_level) const {
305  indent(out, indent_level) << *this;
306  write_children(out, indent_level);
307 }
308 
309 /**
310  * Assuming the current write position has been left at the end of the last
311  * line of the record description, writes out the list of children.
312  */
313 void FltRecord::
314 write_children(std::ostream &out, int indent_level) const {
315  if (!_ancillary.empty()) {
316  out << " + " << _ancillary.size() << " ancillary";
317  }
318  if (!_extensions.empty()) {
319  out << " + " << _extensions.size() << " extensions";
320  }
321  if (!_subfaces.empty()) {
322  out << " [";
323  Records::const_iterator ci;
324  for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
325  out << " " << *(*ci);
326  }
327  out << " ]";
328  }
329  if (!_children.empty()) {
330  out << " {\n";
331  Records::const_iterator ci;
332  for (ci = _children.begin(); ci != _children.end(); ++ci) {
333  (*ci)->write(out, indent_level + 2);
334  }
335  indent(out, indent_level) << "}\n";
336  } else {
337  out << "\n";
338  }
339 }
340 
341  /*
342  virtual void write(ostream &out) const;
343  virtual void build_record(Datagram &datagram) const;
344  */
345 
346 /**
347  * Returns true if the indicated opcode corresponds to an ancillary record
348  * type, false otherwise. In general, this function is used to identify
349  * ancillary records that are not presently supported by the FltReader; these
350  * will be ignored. Normally, ancillary records will be detected and
351  * processed by extract_ancillary().
352  */
353 bool FltRecord::
354 is_ancillary(FltOpcode opcode) {
355  switch (opcode) {
356  case FO_comment:
357  case FO_long_id:
358  case FO_multitexture:
359  case FO_uv_list:
360  case FO_replicate:
361  case FO_road_zone:
362  case FO_transform_matrix:
363  case FO_rotate_about_edge:
364  case FO_translate:
365  case FO_scale:
366  case FO_rotate_about_point:
367  case FO_rotate_and_scale:
368  case FO_put:
369  case FO_general_matrix:
370  case FO_vector:
371  case FO_bounding_box:
372  case FO_bounding_sphere:
373  case FO_bounding_cylinder:
374  case FO_bv_center:
375  case FO_bv_orientation:
376  case FO_local_vertex_pool:
377  case FO_cat_data:
378 
379  case FO_14_material_palette:
380  case FO_vertex_palette:
381  case FO_vertex_c:
382  case FO_vertex_cn:
383  case FO_vertex_cnu:
384  case FO_vertex_cu:
385  case FO_color_palette:
386  case FO_name_table:
387  case FO_15_material:
388  case FO_texture:
389  case FO_eyepoint_palette:
390  case FO_light_definition:
391  case FO_texture_map_palette:
392  return true;
393 
394  case FO_header:
395  case FO_mesh:
396  case FO_mesh_primitive:
397  case FO_group:
398  case FO_object:
399  case FO_face:
400  case FO_light_point:
401  case FO_dof:
402  case FO_vertex_list:
403  case FO_morph_list:
404  case FO_bsp:
405  case FO_external_ref:
406  case FO_lod:
407  case FO_sound:
408  case FO_light_source:
409  case FO_road_segment:
410  case FO_road_construction:
411  case FO_road_path:
412  case FO_clip_region:
413  case FO_text:
414  case FO_switch:
415  case FO_cat:
416  case FO_extension:
417  case FO_curve:
418  return false;
419 
420  case FO_push:
421  case FO_pop:
422  case FO_push_face:
423  case FO_pop_face:
424  case FO_push_attribute:
425  case FO_pop_attribute:
426  case FO_push_extension:
427  case FO_pop_extension:
428  case FO_instance:
429  case FO_instance_ref:
430  return false;
431 
432  default:
433  nout << "Don't know whether " << opcode << " is ancillary.\n";
434  return false;
435  }
436 }
437 
438 /**
439  * Creates a new FltRecord corresponding to the opcode. If the opcode is
440  * unknown, creates a FltUnsupportedRecord.
441  */
442 FltRecord *FltRecord::
443 create_new_record(FltOpcode opcode) const {
444  switch (opcode) {
445  case FO_group:
446  return new FltGroup(_header);
447 
448  case FO_object:
449  return new FltObject(_header);
450 
451  case FO_face:
452  return new FltFace(_header);
453 
454  case FO_curve:
455  return new FltCurve(_header);
456 
457  case FO_mesh:
458  return new FltMesh(_header);
459 
460  case FO_local_vertex_pool:
461  return new FltLocalVertexPool(_header);
462 
463  case FO_mesh_primitive:
464  return new FltMeshPrimitive(_header);
465 
466  case FO_vertex_list:
467  return new FltVertexList(_header);
468 
469  case FO_lod:
470  return new FltLOD(_header);
471 
472  case FO_instance:
473  return new FltInstanceDefinition(_header);
474 
475  case FO_instance_ref:
476  return new FltInstanceRef(_header);
477 
478  case FO_external_ref:
479  return new FltExternalReference(_header);
480 
481  case FO_vector:
482  return new FltVectorRecord(_header);
483 
484  default:
485  nout << "Ignoring unsupported record " << opcode << "\n";
486  return new FltUnsupportedRecord(_header);
487  }
488 }
489 
490 /**
491  * Extracts this record information from the current record presented in the
492  * reader, then advances the reader and continues to read any children, if
493  * present. On return, the reader is position on the next sibling record to
494  * this record.
495  *
496  * Returns FE_ok if successful, otherwise on error.
497  */
498 FltError FltRecord::
499 read_record_and_children(FltRecordReader &reader) {
500  if (!extract_record(reader)) {
501  nout << "Could not extract record for " << *this << "\n";
502  assert(!flt_error_abort);
503  return FE_invalid_record;
504  }
505  FltError result = reader.advance();
506  if (result == FE_end_of_file) {
507  return FE_ok;
508  } else if (result != FE_ok) {
509  return result;
510  }
511 
512  while (true) {
513  if (extract_ancillary(reader)) {
514  // Ok, a known ancillary record. Fine.
515 
516  } else if (reader.get_opcode() == FO_push) {
517  // A push begins a new list of children.
518  result = reader.advance();
519  if (result != FE_ok) {
520  return result;
521  }
522 
523  while (reader.get_opcode() != FO_pop) {
524  PT(FltRecord) child = create_new_record(reader.get_opcode());
525  FltError result = child->read_record_and_children(reader);
526  if (result != FE_ok) {
527  return result;
528  }
529 
530  if (child->is_of_type(FltInstanceDefinition::get_class_type())) {
531  // A special case for an instance definition. These shouldn't
532  // appear in the hierarchy, but should instead be added directly to
533  // the header.
534  _header->add_instance(DCAST(FltInstanceDefinition, child));
535 
536  } else {
537  add_child(child);
538  }
539 
540  if (reader.eof() || reader.error()) {
541  assert(!flt_error_abort);
542  return FE_end_of_file;
543  }
544  }
545 
546  } else if (reader.get_opcode() == FO_push_face) {
547  // A push subface begins a new list of subfaces.
548  result = reader.advance();
549  if (result != FE_ok) {
550  return result;
551  }
552 
553  while (reader.get_opcode() != FO_pop_face) {
554  PT(FltRecord) subface = create_new_record(reader.get_opcode());
555  FltError result = subface->read_record_and_children(reader);
556  if (result != FE_ok) {
557  return result;
558  }
559  add_subface(subface);
560  if (reader.eof() || reader.error()) {
561  assert(!flt_error_abort);
562  return FE_end_of_file;
563  }
564  }
565 
566  } else if (reader.get_opcode() == FO_push_extension) {
567  // A push extension begins a new list of extensions.
568  result = reader.advance();
569  if (result != FE_ok) {
570  return result;
571  }
572 
573  while (reader.get_opcode() != FO_pop_extension) {
574  PT(FltRecord) extension = create_new_record(reader.get_opcode());
575  FltError result = extension->read_record_and_children(reader);
576  if (result != FE_ok) {
577  return result;
578  }
579  add_extension(extension);
580  if (reader.eof() || reader.error()) {
581  assert(!flt_error_abort);
582  return FE_end_of_file;
583  }
584  }
585 
586  } else if (is_ancillary(reader.get_opcode())) {
587  // An unsupported ancillary record. Skip it.
588  PT(FltRecord) ancillary = create_new_record(reader.get_opcode());
589  ancillary->extract_record(reader);
590  _ancillary.push_back(ancillary);
591 
592  } else {
593  // None of the above: we're done.
594  return FE_ok;
595  }
596 
597  // Skip to the next record. If that's the end, fine.
598  result = reader.advance(true);
599  if (reader.eof() || result != FE_ok) {
600  return result;
601  }
602  }
603 }
604 
605 /**
606  * Fills in the information in this record based on the information given in
607  * the indicated datagram, whose opcode has already been read. Returns true
608  * on success, false if the datagram is invalid.
609  */
610 bool FltRecord::
611 extract_record(FltRecordReader &) {
612  return true;
613 }
614 
615 /**
616  * Checks whether the given record, which follows this record sequentially in
617  * the file, is an ancillary record of this record. If it is, extracts the
618  * relevant information and returns true; otherwise, leaves it alone and
619  * returns false.
620  */
621 bool FltRecord::
622 extract_ancillary(FltRecordReader &reader) {
623  if (reader.get_opcode() == FO_comment) {
624  DatagramIterator &di = reader.get_iterator();
625  _comment = di.get_fixed_string(di.get_remaining_size());
626  return true;
627  }
628 
629  return false;
630 }
631 
632 /**
633  * Writes this record out to the flt file, along with all of its ancillary
634  * records and children records. Returns FE_ok on success, or something else
635  * on error.
636  */
637 FltError FltRecord::
638 write_record_and_children(FltRecordWriter &writer) const {
639  // First, write the record.
640  if (!build_record(writer)) {
641  assert(!flt_error_abort);
642  return FE_bad_data;
643  }
644 
645  FltError result = writer.advance();
646  if (result != FE_ok) {
647  return result;
648  }
649 
650  // Then the ancillary data.
651  result = write_ancillary(writer);
652  if (result != FE_ok) {
653  return result;
654  }
655  Records::const_iterator ci;
656  for (ci = _ancillary.begin(); ci != _ancillary.end(); ++ci) {
657  if (!(*ci)->build_record(writer)) {
658  assert(!flt_error_abort);
659  return FE_bad_data;
660  }
661  result = writer.advance();
662  if (result != FE_ok) {
663  return result;
664  }
665  }
666 
667  // Any extensions?
668  if (!_extensions.empty()) {
669  result = writer.write_record(FO_push_face);
670  if (result != FE_ok) {
671  return result;
672  }
673 
674  for (ci = _extensions.begin(); ci != _extensions.end(); ++ci) {
675  (*ci)->write_record_and_children(writer);
676  }
677 
678  result = writer.write_record(FO_pop_face);
679  if (result != FE_ok) {
680  return result;
681  }
682  }
683 
684  // Finally, write all the children.
685  if (!_children.empty()) {
686  result = writer.write_record(FO_push);
687  if (result != FE_ok) {
688  return result;
689  }
690 
691  for (ci = _children.begin(); ci != _children.end(); ++ci) {
692  (*ci)->write_record_and_children(writer);
693  }
694 
695  result = writer.write_record(FO_pop);
696  if (result != FE_ok) {
697  return result;
698  }
699  }
700 
701  // We must write subfaces *after* the list of children, or Creator will
702  // crash trying to load the file.
703  if (!_subfaces.empty()) {
704  result = writer.write_record(FO_push_face);
705  if (result != FE_ok) {
706  return result;
707  }
708 
709  for (ci = _subfaces.begin(); ci != _subfaces.end(); ++ci) {
710  (*ci)->write_record_and_children(writer);
711  }
712 
713  result = writer.write_record(FO_pop_face);
714  if (result != FE_ok) {
715  return result;
716  }
717  }
718 
719  return FE_ok;
720 }
721 
722 /**
723  * Fills up the current record on the FltRecordWriter with data for this
724  * record, but does not advance the writer. Returns true on success, false if
725  * there is some error.
726  */
727 bool FltRecord::
728 build_record(FltRecordWriter &) const {
729  return true;
730 }
731 
732 /**
733  * Writes whatever ancillary records are required for this record. Returns
734  * FE_ok on success, or something else if there is some error.
735  */
736 FltError FltRecord::
737 write_ancillary(FltRecordWriter &writer) const {
738  if (!_comment.empty()) {
739  Datagram dc(_comment.data(), _comment.size());
740  FltError result = writer.write_record(FO_comment, dc);
741  if (result != FE_ok) {
742  return result;
743  }
744  }
745  return FE_ok;
746 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void clear_comment()
Removes the comment for this record.
Definition: fltRecord.cxx:232
int get_flt_version() const
Returns the version number of the flt file as reported in the header, times 100.
Definition: fltHeader.cxx:309
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.
Definition: fltRecord.cxx:190
void clear_extensions()
Removes all extensions from this record.
Definition: fltRecord.cxx:150
This class turns an istream into a sequence of FltRecords by reading a sequence of Datagrams and extr...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FltRecord * get_ancillary(int n) const
Returns the nth unsupported ancillary record of this record.
Definition: fltRecord.cxx:180
void check_remaining_size(const DatagramIterator &di, const std::string &name=std::string()) const
Checks that the iterator has no bytes left, as it should at the end of a successfully read record.
Definition: fltRecord.cxx:254
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
int get_num_children() const
Returns the number of child records of this record.
Definition: fltRecord.cxx:63
static int max_flt_version()
Returns the latest flt version number that this codebase is known to support (times 100).
Definition: fltHeader.cxx:345
FltRecord * get_extension(int n) const
Returns the nth extension of this record.
Definition: fltRecord.cxx:141
The main grouping bead of the flt file.
Definition: fltGroup.h:24
virtual void apply_converted_filenames()
Walks the hierarchy at this record and below and copies the _converted_filename record into the _orig...
Definition: fltRecord.cxx:278
bool error() const
Returns true if some error has been encountered while reading (for instance, a truncated file).
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A single primitive of a mesh, like a triangle strip or fan.
A single face bead, e.g.
Definition: fltFace.h:24
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.
Definition: fltRecord.cxx:88
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
size_t get_remaining_size() const
Return the bytes left in the datagram.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the first bead in the file, the top of the bead hierarchy, and the primary interface to readi...
Definition: fltHeader.h:44
bool has_comment() const
Returns true if this record has a nonempty comment, false otherwise.
Definition: fltRecord.cxx:215
A local vertex pool, as might appear in the middle of the hierarchy, for instance for a mesh.
const std::string & get_comment() const
Retrieves the comment for this record, or empty string if the record has no comment.
Definition: fltRecord.cxx:224
FltRecord * get_subface(int n) const
Returns the nth subface of this record.
Definition: fltRecord.cxx:106
A mesh of connected polygons and tristrips, etc., with a local vertex pool.
Definition: fltMesh.h:27
A list of vertices, typically added as a child of a face bead.
Definition: fltVertexList.h:28
void set_comment(const std::string &comment)
Changes the comment for this record.
Definition: fltRecord.cxx:240
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
std::ostream & indent(std::ostream &out, int indent_level)
A handy function for doing text formatting.
Definition: indent.cxx:20
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The base class for all kinds of records in a MultiGen OpenFlight file.
Definition: fltRecord.h:36
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This bead appears in the hierarchy to refer to a FltInstanceDefinition node defined elsewhere.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
The main objecting bead of the flt file.
Definition: fltObject.h:24
FltRecord * get_child(int n) const
Returns the nth child of this record.
Definition: fltRecord.cxx:71
void add_extension(FltRecord *extension)
Adds a new extension to the end of the list of extensions for this record.
Definition: fltRecord.cxx:159
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_subface(FltRecord *subface)
Adds a new subface to the end of the list of subfaces for this record.
Definition: fltRecord.cxx:123
FltOpcode get_opcode() const
Returns the opcode associated with the current record.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void output(std::ostream &out) const
Writes a quick one-line description of the record, but not its children.
Definition: fltRecord.cxx:294
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_instance(FltInstanceDefinition *instance)
Defines a new instance subtree.
Definition: fltHeader.cxx:445
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.
Definition: fltRecord.cxx:207
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
A single curve, like a Bezier or B-Spline.
Definition: fltCurve.h:27
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
A Level-of-Detail record.
Definition: fltLOD.h:24
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.
Definition: fltRecord.cxx:171
void clear_children()
Removes all children from this record.
Definition: fltRecord.cxx:80
void clear_subfaces()
Removes all subfaces from this record.
Definition: fltRecord.cxx:115
virtual void write(std::ostream &out, int indent_level=0) const
Writes a multiple-line description of the record and all of its children.
Definition: fltRecord.cxx:304
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
Definition: fltRecord.cxx:98
int get_num_extensions() const
Returns the number of extension attribute records for this object.
Definition: fltRecord.cxx:133
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...
std::string get_fixed_string(size_t size)
Extracts a fixed-length string.