Panda3D
eggFile.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 eggFile.cxx
10  * @author drose
11  * @date 2000-11-29
12  */
13 
14 #include "eggFile.h"
15 #include "textureImage.h"
16 #include "paletteGroup.h"
17 #include "texturePlacement.h"
18 #include "textureReference.h"
19 #include "sourceTextureImage.h"
20 #include "palettizer.h"
21 #include "filenameUnifier.h"
22 
23 #include "eggData.h"
24 #include "eggGroup.h"
25 #include "eggTextureCollection.h"
26 #include "eggComment.h"
27 #include "datagram.h"
28 #include "datagramIterator.h"
29 #include "bamReader.h"
30 #include "bamWriter.h"
31 #include "executionEnvironment.h"
32 #include "dSearchPath.h"
33 #include "indirectLess.h"
34 
35 #include <algorithm>
36 
37 TypeHandle EggFile::_type_handle;
38 
39 /**
40  *
41  */
42 EggFile::
43 EggFile() {
44  _data = nullptr;
45  _first_txa_match = false;
46  _default_group = nullptr;
47  _is_surprise = true;
48  _is_stale = true;
49  _had_data = false;
50 }
51 
52 /**
53  * Accepts the information about the egg file as supplied from the command
54  * line. Returns true if the egg file is valid, false otherwise.
55  */
58  const Filename &source_filename,
59  const Filename &dest_filename,
60  const std::string &egg_comment) {
61  _data = data;
62  _had_data = true;
63  remove_backstage(_data);
64 
65  // We save the current directory at the time the egg file appeared on the
66  // command line, so that we'll later be able to properly resolve external
67  // references (like textures) that might be relative to this directory.
68  _current_directory = ExecutionEnvironment::get_cwd();
69  _source_filename = source_filename;
70  _source_filename.make_absolute();
71  _dest_filename = dest_filename;
72  _dest_filename.make_absolute();
73 
74  // We also save the command line that loaded this egg file, so we can
75  // continue to write it as a comment to the beginning of the egg file,
76  // should we need to rewrite it later.
77  _egg_comment = egg_comment;
78 
79  // We save the default PaletteGroup at this point, because the egg file
80  // inherits the default group that was in effect when it was specified on
81  // the command line.
82  _default_group = pal->get_default_group();
83 
84  return true;
85 }
86 
87 /**
88  * Returns the filename this egg file was read from.
89  */
91 get_source_filename() const {
92  return _source_filename;
93 }
94 
95 
96 /**
97  * Scans the egg file for texture references and updates the _textures list
98  * appropriately. This assumes the egg file was supplied on the command line
99  * and thus the _data member is available.
100  */
102 scan_textures() {
103  nassertv(_data != nullptr);
104 
105  // Extract the set of textures referenced by this egg file.
107  tc.find_used_textures(_data);
108 
109  // Make sure each tref name is unique within a given file.
110  tc.uniquify_trefs();
111 
112  // Now build up a list of new TextureReference objects that represent the
113  // textures actually used and their uv range, etc.
114  Textures new_textures;
115 
116  EggTextureCollection::iterator eti;
117  for (eti = tc.begin(); eti != tc.end(); ++eti) {
118  EggTexture *egg_tex = (*eti);
119 
121  ref->from_egg(this, _data, egg_tex);
122 
123  if (!ref->has_uvs()) {
124  // This texture isn't *really* referenced. (Usually this happens if the
125  // texture is only referenced by "backstage" geometry, which we don't
126  // care about.)
127  delete ref;
128 
129  } else {
130  new_textures.push_back(ref);
131  }
132  }
133 
134  // Sort the new references into order so we can compare them with the
135  // original references.
136  sort(new_textures.begin(), new_textures.end(),
138 
139  // Sort the original references too. This should already be sorted from the
140  // previous run, but we might as well be neurotic about it.
141  sort(_textures.begin(), _textures.end(),
143 
144  // Now go through and merge the lists.
145  Textures combined_textures;
146  Textures::const_iterator ai = _textures.begin();
147  Textures::const_iterator bi = new_textures.begin();
148 
149  while (ai != _textures.end() && bi != new_textures.end()) {
150  TextureReference *aref = (*ai);
151  TextureReference *bref = (*bi);
152 
153  if ((*aref) < (*bref)) {
154  // Here's a texture reference in the original list, but not in the new
155  // list. Remove it.
156  delete aref;
157  ++ai;
158 
159  } else if ((*bref) < (*aref)) {
160  // Here's a texture reference in the new list, but not in the original
161  // list. Add it.
162  combined_textures.push_back(bref);
163  ++bi;
164 
165  } else { // (*bref) == (*aref)
166  // Here's a texture reference that was in both lists. Compare it.
167  if (aref->is_equivalent(*bref)) {
168  // It hasn't changed substantially, so keep the original (which still
169  // has the placement references from a previous pass).
170  aref->from_egg_quick(*bref);
171  combined_textures.push_back(aref);
172  delete bref;
173 
174  } else {
175  // It has changed, so drop the original and keep the new one.
176  combined_textures.push_back(bref);
177  delete aref;
178  }
179  ++ai;
180  ++bi;
181  }
182  }
183 
184  while (bi != new_textures.end()) {
185  TextureReference *bref = (*bi);
186  // Here's a texture reference in the new list, but not in the original
187  // list. Add it.
188  combined_textures.push_back(bref);
189  ++bi;
190  }
191 
192  while (ai != _textures.end()) {
193  TextureReference *aref = (*ai);
194  // Here's a texture reference in the original list, but not in the new
195  // list. Remove it.
196  delete aref;
197  ++ai;
198  }
199 
200  _textures.swap(combined_textures);
201 }
202 
203 /**
204  * Fills up the indicated set with the set of textures referenced by this egg
205  * file. It is the user's responsibility to ensure the set is empty before
206  * making this call; otherwise, the new textures will be appended to the
207  * existing set.
208  */
210 get_textures(pset<TextureImage *> &result) const {
211  Textures::const_iterator ti;
212  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
213  result.insert((*ti)->get_texture());
214  }
215 }
216 
217 /**
218  * Does some processing prior to scanning the .txa file.
219  */
221 pre_txa_file() {
222  _is_surprise = true;
223  _first_txa_match = true;
224 }
225 
226 /**
227  * Adds the indicated set of groups, read from the .txa file, to the set of
228  * groups to which the egg file is assigned.
229  */
231 match_txa_groups(const PaletteGroups &groups) {
232  if (_first_txa_match) {
233  // If this is the first line we matched in the .txa file, clear the set of
234  // groups we'd matched from before. We don't clear until we match a line
235  // in the .txa file, because if we don't match any lines we still want to
236  // remember what groups we used to be assigned to.
237  _explicitly_assigned_groups.clear();
238  _first_txa_match = false;
239  }
240 
241  _explicitly_assigned_groups.make_union(_explicitly_assigned_groups, groups);
242 }
243 
244 /**
245  * Once the egg file has been matched against all of the matching lines the
246  * .txa file, do whatever adjustment is necessary.
247  */
249 post_txa_file() {
250 }
251 
252 /**
253  * Returns the set of PaletteGroups that the egg file has been explicitly
254  * assigned to in the .txa file.
255  */
257 get_explicit_groups() const {
258  return _explicitly_assigned_groups;
259 }
260 
261 /**
262  * Returns the PaletteGroup that was specified as the default group on the
263  * command line at the time the egg file last appeared on the command line.
264  */
266 get_default_group() const {
267  return _default_group;
268 }
269 
270 /**
271  * Returns the complete set of PaletteGroups that the egg file is assigned to.
272  * This is the set of all the groups it is explicitly assigned to, plus all
273  * the groups that these groups depend on.
274  */
276 get_complete_groups() const {
277  return _complete_groups;
278 }
279 
280 /**
281  * Removes the 'surprise' flag; this file has been successfully matched
282  * against a line in the .txa file.
283  */
285 clear_surprise() {
286  _is_surprise = false;
287 }
288 
289 /**
290  * Returns true if this particular egg file is a 'surprise', i.e. it wasn't
291  * matched by a line in the .txa file that didn't include the keyword 'cont'.
292  */
294 is_surprise() const {
295  return _is_surprise;
296 }
297 
298 /**
299  * Marks this particular egg file as stale, meaning that something has
300  * changed, such as the location of a texture within its palette, which causes
301  * the egg file to need to be regenerated.
302  */
304 mark_stale() {
305  _is_stale = true;
306 }
307 
308 /**
309  * Returns true if the egg file needs to be updated, i.e. some palettizations
310  * have changed affecting it, or false otherwise.
311  */
313 is_stale() const {
314  return _is_stale;
315 }
316 
317 /**
318  * Calls TextureImage::note_egg_file() and
319  * SourceTextureImage::increment_egg_count() for each texture the egg file
320  * references, and PaletteGroup::increment_egg_count() for each palette group
321  * it wants. This sets up some of the back references to support determining
322  * an ideal texture assignment.
323  */
326  if (_explicitly_assigned_groups.empty()) {
327  // If the egg file has been assigned to no groups, we have to assign it to
328  // something.
329  _complete_groups.clear();
330  _complete_groups.insert(_default_group);
331  _complete_groups.make_complete(_complete_groups);
332 
333  } else {
334  _complete_groups.make_complete(_explicitly_assigned_groups);
335  }
336 
337  Textures::const_iterator ti;
338  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
339  TextureReference *reference = (*ti);
340  TextureImage *texture = reference->get_texture();
341  nassertv(texture != nullptr);
342  texture->note_egg_file(this);
343 
344  // Actually, this may count the same egg file multiple times for a
345  // particular SourceTextureImage, since a given texture may be referenced
346  // multiples times within an egg file. No harm done, however.
347  reference->get_source()->increment_egg_count();
348  }
349 
350  PaletteGroups::const_iterator gi;
351  for (gi = _complete_groups.begin();
352  gi != _complete_groups.end();
353  ++gi) {
354  (*gi)->increment_egg_count();
355  }
356 }
357 
358 /**
359  * Calls apply_properties_to_source() for each texture reference, updating all
360  * the referenced source textures with the complete set of property
361  * information from this egg file.
362  */
365  Textures::const_iterator ti;
366  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
367  TextureReference *reference = (*ti);
368  reference->apply_properties_to_source();
369  }
370 }
371 
372 /**
373  * Once all the textures have been assigned to groups (but before they may
374  * actually be placed), chooses a suitable TexturePlacement for each texture
375  * that appears in the egg file. This will be necessary to do at some point
376  * before writing out the egg file anyway, and doing it before the textures
377  * are placed allows us to decide what the necessary UV range is for each to-
378  * be-placed texture.
379  */
382  Textures::const_iterator ti;
383  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
384  TextureReference *reference = (*ti);
385  TextureImage *texture = reference->get_texture();
386 
387  if (reference->get_placement() != nullptr &&
388  texture->get_groups().count(reference->get_placement()->get_group()) != 0) {
389  // The egg file is already using a TexturePlacement that is suitable.
390  // Don't bother changing it.
391 
392  } else {
393  // We need to select a new TexturePlacement.
394  PaletteGroups groups;
395  groups.make_intersection(get_complete_groups(), texture->get_groups());
396 
397  // Now groups is the set of groups that the egg file requires, which
398  // also happen to include the texture.
399 
400  if (groups.empty()) {
401  // It might be empty if the egg file was assigned only to the "null"
402  // group (since this group is not propagated to the textures). In
403  // this case, choose from the wider set of groups available to the
404  // texture.
405  groups = texture->get_groups();
406  }
407 
408  if (!groups.empty()) {
409  // It doesn't really matter which group in the set we choose, so we
410  // arbitrarily choose the first one.
411  PaletteGroup *group = (*groups.begin());
412 
413  // Now get the TexturePlacement object that corresponds to the
414  // placement of this texture into this group.
415  TexturePlacement *placement = texture->get_placement(group);
416  nassertv(placement != nullptr);
417 
418  reference->set_placement(placement);
419  }
420  }
421  }
422 }
423 
424 /**
425  * Returns true if the EggData for this EggFile has been loaded, and not yet
426  * released.
427  */
429 has_data() const {
430  return (_data != nullptr);
431 }
432 
433 /**
434  * Returns true if the EggData for this EggFile has ever been loaded in this
435  * session.
436  */
438 had_data() const {
439  return _had_data;
440 }
441 
442 /**
443  * Once all textures have been placed appropriately, updates the egg file with
444  * all the information to reference the new textures.
445  */
447 update_egg() {
448  nassertv(_data != nullptr);
449 
450  Textures::iterator ti;
451  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
452  TextureReference *reference = (*ti);
453  reference->update_egg();
454  }
455 }
456 
457 /**
458  * Removes this egg file from all things that reference it, in preparation for
459  * removing it from the database.
460  */
462 remove_egg() {
463  Textures::iterator ti;
464  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
465  TextureReference *reference = (*ti);
466  TexturePlacement *placement = reference->get_placement();
467  placement->remove_egg(reference);
468  }
469 }
470 
471 /**
472  * Reads in the egg file from its _source_filename. It is only valid to call
473  * this if it has not already been read in, e.g. from the command line.
474  * Returns true if successful, false if there is an error.
475  *
476  * This may also be called after a previous call to release_egg_data(), in
477  * order to re-read the same egg file.
478  */
480 read_egg(bool noabs) {
481  nassertr(_data == nullptr, false);
482  nassertr(!_source_filename.empty(), false);
483 
484  Filename user_source_filename =
485  FilenameUnifier::make_user_filename(_source_filename);
486 
487  if (!_source_filename.exists()) {
488  nout << user_source_filename << " does not exist.\n";
489  return false;
490  }
491 
492  PT(EggData) data = new EggData;
493  if (!data->read(_source_filename, user_source_filename)) {
494  // Failure reading.
495  return false;
496  }
497 
498  if (noabs && data->original_had_absolute_pathnames()) {
499  nout << _source_filename.get_basename()
500  << " references textures using absolute pathnames!\n";
501  return false;
502  }
503 
504  // Extract the set of textures referenced by this egg file.
506  tc.find_used_textures(data);
507 
508  // Make sure each tref name is unique within a given file.
509  tc.uniquify_trefs();
510 
511  // Now build up a list of new TextureReference objects that represent the
512  // textures actually used and their uv range, etc.
513  Textures new_textures;
514 
515  // We want to search for filenames based on the egg directory, and also on
516  // our current directory from which we originally loaded the egg file. This
517  // is important because it's possible the egg file referenced some textures
518  // or something relative to that directory.
519  DSearchPath dir;
520  dir.append_directory(_source_filename.get_dirname());
521  dir.append_directory(_current_directory);
522  data->resolve_filenames(dir);
523 
524  // If any relative filenames remain, they are relative to the source
525  // directory, by convention.
526  data->force_filenames(_current_directory);
527 
528  if (!data->load_externals()) {
529  // Failure reading an external.
530  return false;
531  }
532 
533  _data = data;
534  _had_data = true;
535  remove_backstage(_data);
536 
537  // Insert a comment that shows how we first generated the egg file.
538  PT(EggNode) comment = new EggComment("", _egg_comment);
539  _data->insert(_data->begin(), comment);
540 
541  if (!_textures.empty()) {
542  // If we already have textures, assume we're re-reading the file.
543  rescan_textures();
544  }
545 
546  return true;
547 }
548 
549 /**
550  * Releases the memory that was loaded by a previous call to read_egg().
551  */
554  if (_data != nullptr) {
555  _data = nullptr;
556  }
557  Textures::iterator ti;
558  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
559  TextureReference *reference = (*ti);
560  reference->release_egg_data();
561  }
562 }
563 
564 /**
565  * Writes out the egg file to its _dest_filename. Returns true if successful,
566  * false if there is an error.
567  */
569 write_egg() {
570  nassertr(_data != nullptr, false);
571  nassertr(!_dest_filename.empty(), false);
572 
573  _dest_filename.make_dir();
574  nout << "Writing " << FilenameUnifier::make_user_filename(_dest_filename)
575  << "\n";
576  if (!_data->write_egg(_dest_filename)) {
577  // Some error while writing. Most unusual.
578  _is_stale = true;
579  return false;
580  }
581 
582  _is_stale = false;
583  return true;
584 }
585 
586 /**
587  * Writes a one-line description of the egg file and its group assignments to
588  * the indicated output stream.
589  */
591 write_description(std::ostream &out, int indent_level) const {
592  indent(out, indent_level) << get_name() << ": ";
593  if (_explicitly_assigned_groups.empty()) {
594  if (_default_group != nullptr) {
595  out << _default_group->get_name();
596  }
597  } else {
598  out << _explicitly_assigned_groups;
599  }
600 
601  if (is_stale()) {
602  out << " (needs update)";
603  }
604  out << "\n";
605 }
606 
607 /**
608  * Writes the list of texture references to the indicated output stream, one
609  * per line.
610  */
612 write_texture_refs(std::ostream &out, int indent_level) const {
613  Textures::const_iterator ti;
614  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
615  TextureReference *reference = (*ti);
616  reference->write(out, indent_level);
617  }
618 }
619 
620 /**
621  * Recursively walks the egg hierarchy and removes any "backstage" nodes found
622  * from the scene graph completely. These aren't part of the egg scene
623  * anyway, and removing them early helps reduce confusion.
624  */
625 void EggFile::
626 remove_backstage(EggGroupNode *node) {
627  EggGroupNode::iterator ci;
628  ci = node->begin();
629  while (ci != node->end()) {
630  EggNode *child = (*ci);
631  bool remove_child = false;
632 
633  if (child->is_of_type(EggGroup::get_class_type())) {
634  EggGroup *egg_group;
635  DCAST_INTO_V(egg_group, child);
636  remove_child = egg_group->has_object_type("backstage");
637  }
638 
639  if (remove_child) {
640  ci = node->erase(ci);
641  } else {
642  if (child->is_of_type(EggGroupNode::get_class_type())) {
643  // Recurse on children.
644  remove_backstage(DCAST(EggGroupNode, child));
645  }
646  ++ci;
647  }
648  }
649 }
650 
651 /**
652  * After reloading the egg file for the second time in a given session,
653  * rematches the texture pointers with the TextureReference objects.
654  */
655 void EggFile::
656 rescan_textures() {
657  nassertv(_data != nullptr);
658 
659  // Extract the set of textures referenced by this egg file.
661  tc.find_used_textures(_data);
662 
663  // Make sure each tref name is unique within a given file.
664  tc.uniquify_trefs();
665 
666  typedef pmap<std::string, TextureReference *> ByTRefName;
667  ByTRefName by_tref_name;
668  for (Textures::const_iterator ti = _textures.begin();
669  ti != _textures.end();
670  ++ti) {
671  TextureReference *ref = (*ti);
672  by_tref_name[ref->get_tref_name()] = ref;
673  }
674 
675  EggTextureCollection::iterator eti;
676  for (eti = tc.begin(); eti != tc.end(); ++eti) {
677  EggTexture *egg_tex = (*eti);
678 
679  ByTRefName::const_iterator tni = by_tref_name.find(egg_tex->get_name());
680  if (tni == by_tref_name.end()) {
681  // We didn't find this TRef name last time around!
682  nout << _source_filename.get_basename()
683  << " modified during session--TRef " << egg_tex->get_name()
684  << " is new!\n";
685 
686  } else {
687  TextureReference *ref = (*tni).second;
688  ref->rebind_egg_data(_data, egg_tex);
689  }
690  }
691 }
692 
693 /**
694  * Registers the current object as something that can be read from a Bam file.
695  */
699  register_factory(get_class_type(), make_EggFile);
700 }
701 
702 /**
703  * Fills the indicated datagram up with a binary representation of the current
704  * object, in preparation for writing to a Bam file.
705  */
707 write_datagram(BamWriter *writer, Datagram &datagram) {
708  TypedWritable::write_datagram(writer, datagram);
709  datagram.add_string(get_name());
710 
711  // We don't write out _data; that needs to be reread each session.
712 
713  datagram.add_string(FilenameUnifier::make_bam_filename(_current_directory));
714  datagram.add_string(FilenameUnifier::make_bam_filename(_source_filename));
715  datagram.add_string(FilenameUnifier::make_bam_filename(_dest_filename));
716  datagram.add_string(_egg_comment);
717 
718  datagram.add_uint32(_textures.size());
719  Textures::iterator ti;
720  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
721  writer->write_pointer(datagram, (*ti));
722  }
723 
724  _explicitly_assigned_groups.write_datagram(writer, datagram);
725  writer->write_pointer(datagram, _default_group);
726 
727  // We don't write out _complete_groups; that is recomputed each session.
728 
729  datagram.add_bool(_is_surprise);
730  datagram.add_bool(_is_stale);
731 }
732 
733 /**
734  * Called after the object is otherwise completely read from a Bam file, this
735  * function's job is to store the pointers that were retrieved from the Bam
736  * file for each pointer object written. The return value is the number of
737  * pointers processed from the list.
738  */
740 complete_pointers(TypedWritable **p_list, BamReader *manager) {
741  int pi = TypedWritable::complete_pointers(p_list, manager);
742 
743  int i;
744  _textures.reserve(_num_textures);
745  for (i = 0; i < _num_textures; i++) {
746  TextureReference *texture;
747  DCAST_INTO_R(texture, p_list[pi], pi);
748  _textures.push_back(texture);
749  pi++;
750  }
751 
752  pi += _explicitly_assigned_groups.complete_pointers(p_list + pi, manager);
753 
754  if (p_list[pi] != nullptr) {
755  DCAST_INTO_R(_default_group, p_list[pi], pi);
756  }
757  pi++;
758 
759  return pi;
760 }
761 
762 /**
763  * This method is called by the BamReader when an object of this type is
764  * encountered in a Bam file; it should allocate and return a new object with
765  * all the data read.
766  */
767 TypedWritable* EggFile::
768 make_EggFile(const FactoryParams &params) {
769  EggFile *me = new EggFile();
770  DatagramIterator scan;
771  BamReader *manager;
772 
773  parse_params(params, scan, manager);
774  me->fillin(scan, manager);
775  return me;
776 }
777 
778 /**
779  * Reads the binary data from the given datagram iterator, which was written
780  * by a previous call to write_datagram().
781  */
782 void EggFile::
783 fillin(DatagramIterator &scan, BamReader *manager) {
784  TypedWritable::fillin(scan, manager);
785  set_name(scan.get_string());
786  _current_directory = FilenameUnifier::get_bam_filename(scan.get_string());
787  _source_filename = FilenameUnifier::get_bam_filename(scan.get_string());
788  _dest_filename = FilenameUnifier::get_bam_filename(scan.get_string());
789  if (Palettizer::_read_pi_version >= 9) {
790  _egg_comment = scan.get_string();
791  }
792 
793  _num_textures = scan.get_uint32();
794  manager->read_pointers(scan, _num_textures);
795 
796  _explicitly_assigned_groups.fillin(scan, manager);
797  manager->read_pointer(scan); // _default_group
798 
799  _is_surprise = scan.get_bool();
800  _is_stale = scan.get_bool();
801 
802  if (Palettizer::_read_pi_version < 11) {
803  // If this file was written by a version of egg-palettize prior to 11, we
804  // didn't store the tref names on the texture references. Since we need
805  // that information now, it follows that every egg file is stale.
806  _is_stale = true;
807  }
808 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void parse_params(const FactoryParams &params, DatagramIterator &scan, BamReader *&manager)
Takes in a FactoryParams, passed from a WritableFactory into any TypedWritable's make function,...
Definition: bamReader.I:275
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
Definition: bamWriter.cxx:317
This class stores a list of directories that can be searched, in order, to locate a particular file.
Definition: dSearchPath.h:28
void append_directory(const Filename &directory)
Adds a new directory to the end of the search list.
A class to retrieve the individual data elements previously stored in a Datagram.
uint32_t get_uint32()
Extracts an unsigned 32-bit integer.
bool get_bool()
Extracts a boolean value.
std::string get_string()
Extracts a variable-length string.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
void add_uint32(uint32_t value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:94
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
A comment that appears in an egg file within a <Comment> entry.
Definition: eggComment.h:24
This is the primary interface into all the egg data, and the root of the egg file structure.
Definition: eggData.h:37
This represents a single egg file known to the palettizer.
Definition: eggFile.h:36
void remove_egg()
Removes this egg file from all things that reference it, in preparation for removing it from the data...
Definition: eggFile.cxx:462
void match_txa_groups(const PaletteGroups &groups)
Adds the indicated set of groups, read from the .txa file, to the set of groups to which the egg file...
Definition: eggFile.cxx:231
void pre_txa_file()
Does some processing prior to scanning the .txa file.
Definition: eggFile.cxx:221
bool from_command_line(EggData *data, const Filename &source_filename, const Filename &dest_filename, const std::string &egg_comment)
Accepts the information about the egg file as supplied from the command line.
Definition: eggFile.cxx:57
void choose_placements()
Once all the textures have been assigned to groups (but before they may actually be placed),...
Definition: eggFile.cxx:381
bool is_stale() const
Returns true if the egg file needs to be updated, i.e.
Definition: eggFile.cxx:313
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object,...
Definition: eggFile.cxx:707
void get_textures(pset< TextureImage * > &result) const
Fills up the indicated set with the set of textures referenced by this egg file.
Definition: eggFile.cxx:210
void write_description(std::ostream &out, int indent_level=0) const
Writes a one-line description of the egg file and its group assignments to the indicated output strea...
Definition: eggFile.cxx:591
const Filename & get_source_filename() const
Returns the filename this egg file was read from.
Definition: eggFile.cxx:91
const PaletteGroups & get_complete_groups() const
Returns the complete set of PaletteGroups that the egg file is assigned to.
Definition: eggFile.cxx:276
void update_egg()
Once all textures have been placed appropriately, updates the egg file with all the information to re...
Definition: eggFile.cxx:447
void apply_properties_to_source()
Calls apply_properties_to_source() for each texture reference, updating all the referenced source tex...
Definition: eggFile.cxx:364
void clear_surprise()
Removes the 'surprise' flag; this file has been successfully matched against a line in the ....
Definition: eggFile.cxx:285
PaletteGroup * get_default_group() const
Returns the PaletteGroup that was specified as the default group on the command line at the time the ...
Definition: eggFile.cxx:266
void build_cross_links()
Calls TextureImage::note_egg_file() and SourceTextureImage::increment_egg_count() for each texture th...
Definition: eggFile.cxx:325
const PaletteGroups & get_explicit_groups() const
Returns the set of PaletteGroups that the egg file has been explicitly assigned to in the ....
Definition: eggFile.cxx:257
void release_egg_data()
Releases the memory that was loaded by a previous call to read_egg().
Definition: eggFile.cxx:553
void scan_textures()
Scans the egg file for texture references and updates the _textures list appropriately.
Definition: eggFile.cxx:102
void write_texture_refs(std::ostream &out, int indent_level=0) const
Writes the list of texture references to the indicated output stream, one per line.
Definition: eggFile.cxx:612
bool had_data() const
Returns true if the EggData for this EggFile has ever been loaded in this session.
Definition: eggFile.cxx:438
bool is_surprise() const
Returns true if this particular egg file is a 'surprise', i.e.
Definition: eggFile.cxx:294
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
Definition: eggFile.cxx:697
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function's job is to store...
Definition: eggFile.cxx:740
bool write_egg()
Writes out the egg file to its _dest_filename.
Definition: eggFile.cxx:569
void mark_stale()
Marks this particular egg file as stale, meaning that something has changed, such as the location of ...
Definition: eggFile.cxx:304
void post_txa_file()
Once the egg file has been matched against all of the matching lines the .txa file,...
Definition: eggFile.cxx:249
bool read_egg(bool noabs)
Reads in the egg file from its _source_filename.
Definition: eggFile.cxx:480
bool has_data() const
Returns true if the EggData for this EggFile has been loaded, and not yet released.
Definition: eggFile.cxx:429
A base class for nodes in the hierarchy that are not leaf nodes.
Definition: eggGroupNode.h:46
The main glue of the egg hierarchy, this corresponds to the <Group>, <Instance>, and <Joint> type nod...
Definition: eggGroup.h:34
bool has_object_type(const std::string &object_type) const
Returns true if the indicated object type has been added to the group, or false otherwise.
Definition: eggGroup.cxx:145
A base class for things that may be directly added into the egg hierarchy.
Definition: eggNode.h:36
This is a collection of textures by TRef name.
int find_used_textures(EggNode *node)
Walks the egg hierarchy beginning at the indicated node, looking for textures that are referenced by ...
void uniquify_trefs()
Guarantees that each texture in the collection has a unique TRef name.
Defines a texture map that may be applied to geometry.
Definition: eggTexture.h:30
get_cwd
Returns the name of the current working directory.
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
static Filename get_bam_filename(Filename filename)
Returns an absolute pathname based on the given relative pathname, presumably read from the bam file ...
static Filename make_bam_filename(Filename filename)
Returns a new filename that's made relative to the bam file itself, suitable for writing to the bam f...
static Filename make_user_filename(Filename filename)
Returns a new filename that's made relative to the current directory, suitable for reporting to the u...
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
std::string get_basename() const
Returns the basename part of the filename.
Definition: filename.I:367
bool make_dir() const
Creates all the directories in the path to the file specified in the filename, except for the basenam...
Definition: filename.cxx:2484
std::string get_dirname() const
Returns the directory part of the filename.
Definition: filename.I:358
void make_absolute()
Converts the filename to a fully-qualified pathname from the root (if it is a relative pathname),...
Definition: filename.cxx:968
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
An STL function object class, this is intended to be used on any ordered collection of pointers to cl...
Definition: indirectLess.h:25
This is the highest level of grouping for TextureImages.
Definition: paletteGroup.h:43
A set of PaletteGroups.
Definition: paletteGroups.h:28
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function's job is to store...
void make_complete(const PaletteGroups &a)
Completes the set with the transitive closure of all dependencies: for each PaletteGroup already in t...
iterator begin() const
Returns an iterator suitable for traversing the set.
void insert(PaletteGroup *group)
Inserts a new group to the set, if it is not already there.
void clear()
Empties the set.
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object,...
size_type count(PaletteGroup *group) const
Returns the number of times the given group appears in the set.
void make_intersection(const PaletteGroups &a, const PaletteGroups &b)
Computes the intersection of PaletteGroups a and b, and stores the result in this object.
void make_union(const PaletteGroups &a, const PaletteGroups &b)
Computes the union of PaletteGroups a and b, and stores the result in this object.
iterator end() const
Returns an iterator suitable for traversing the set.
bool empty() const
Returns true if the set is empty, false otherwise.
void fillin(DatagramIterator &scan, BamReader *manager)
Reads the binary data from the given datagram iterator, which was written by a previous call to write...
PaletteGroup * get_default_group()
Returns the default group to which an egg file should be assigned if it is not mentioned in the ....
Definition: palettizer.cxx:824
void increment_egg_count()
Increments by one the number of egg files that are known to reference this SourceTextureImage.
This represents a single source texture that is referenced by one or more egg files.
Definition: textureImage.h:46
void note_egg_file(EggFile *egg_file)
Records that a particular egg file references this texture.
const PaletteGroups & get_groups() const
Once assign_groups() has been called, this returns the actual set of groups the TextureImage has been...
TexturePlacement * get_placement(PaletteGroup *group) const
Gets the TexturePlacement object which represents the assignment of this texture to the indicated gro...
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
PaletteGroup * get_group() const
Returns the group that this placement represents.
void remove_egg(TextureReference *reference)
Notes that a particular egg file is no longer using this particular TexturePlacement.
This is the particular reference of a texture filename by an egg file.
bool has_uvs() const
Returns true if this TextureReference actually uses the texture on geometry, with UV's and everything...
const std::string & get_tref_name() const
Returns the name of the EggTexture entry that references this texture.
bool is_equivalent(const TextureReference &other) const
Returns true if all essential properties of this TextureReference are the same as that of the other,...
void apply_properties_to_source()
Applies the texture properties as read from the egg file to the source image's properties.
void update_egg()
Updates the egg file with all the relevant information to reference the texture in its new home,...
void from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex)
Sets up the TextureReference using information extracted from an egg file.
void rebind_egg_data(EggData *data, EggTexture *egg_tex)
After an EggData has previously been released via release_egg_data(), this can be called to indicate ...
void set_placement(TexturePlacement *placement)
Sets the particular TexturePlacement that is appropriate for this egg file.
TexturePlacement * get_placement() const
Returns the particular TexturePlacement that is appropriate for this egg file.
TextureImage * get_texture() const
Returns the TextureImage that this object refers to.
SourceTextureImage * get_source() const
Returns the SourceTextureImage that this object refers to.
void from_egg_quick(const TextureReference &other)
Sets up the pointers within the TextureReference to the same egg file pointers indicated by the other...
void release_egg_data()
Called to indicate that the EggData previously passed to from_egg() is about to be deallocated,...
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
virtual void fillin(DatagramIterator &scan, BamReader *manager)
This internal function is intended to be called by each class's make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Receives an array of pointers, one for each time manager->read_pointer() was called in fillin().
This is our own Panda specialization on the default STL map.
Definition: pmap.h:49
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.
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.
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.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.