Panda3D
palettizer.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 palettizer.cxx
10  * @author drose
11  * @date 2000-12-01
12  */
13 
14 #include "palettizer.h"
15 #include "eggFile.h"
16 #include "textureImage.h"
17 #include "pal_string_utils.h"
18 #include "paletteGroup.h"
19 #include "filenameUnifier.h"
20 #include "textureMemoryCounter.h"
21 
22 #include "pnmImage.h"
23 #include "pnmFileTypeRegistry.h"
24 #include "pnmFileType.h"
25 #include "eggData.h"
26 #include "datagram.h"
27 #include "datagramIterator.h"
28 #include "bamReader.h"
29 #include "bamWriter.h"
30 #include "indent.h"
31 
32 using std::cout;
33 using std::string;
34 
35 Palettizer *pal = nullptr;
36 
37 // This number is written out as the first number to the pi file, to indicate
38 // the version of egg-palettize that wrote it out. This allows us to easily
39 // update egg-palettize to write out additional information to its pi file,
40 // without having it increment the bam version number for all bam and boo
41 // files anywhere in the world.
42 int Palettizer::_pi_version = 20;
43 /*
44  * Updated to version 8 on 32003 to remove extensions from texture key names.
45  * Updated to version 9 on 41303 to add a few properties in various places.
46  * Updated to version 10 on 41503 to add _alpha_file_channel. Updated to
47  * version 11 on 43003 to add TextureReference::_tref_name. Updated to
48  * version 12 on 91103 to add _generated_image_pattern. Updated to version 13
49  * on 91303 to add _keep_format and _background. Updated to version 14 on
50  * 72605 to add _omit_everything. Updated to version 15 on 80105 to make
51  * TextureImages be case-insensitive. Updated to version 16 on 40306 to add
52  * Palettizer::_cutout_mode et al. Updated to version 17 on 30207 to add
53  * TextureImage::_txa_wrap_u etc. Updated to version 18 on 51308 to add
54  * TextureProperties::_quality_level. Updated to version 19 on 71609 to add
55  * PaletteGroup::_override_margin Updated to version 20 on 72709 to add
56  * TexturePlacement::_swapTextures
57  */
58 
59 int Palettizer::_min_pi_version = 8;
60 // Dropped support for versions 7 and below on 71403.
61 
62 int Palettizer::_read_pi_version = 0;
63 
64 TypeHandle Palettizer::_type_handle;
65 
66 std::ostream &operator << (std::ostream &out, Palettizer::RemapUV remap) {
67  switch (remap) {
68  case Palettizer::RU_never:
69  return out << "never";
70 
71  case Palettizer::RU_group:
72  return out << "per group";
73 
74  case Palettizer::RU_poly:
75  return out << "per polygon";
76 
77  case Palettizer::RU_invalid:
78  return out << "(invalid)";
79  }
80 
81  return out << "**invalid**(" << (int)remap << ")";
82 }
83 
84 
85 // This STL function object is used in report_statistics(), below.
86 class SortGroupsByDependencyOrder {
87 public:
88  bool operator ()(PaletteGroup *a, PaletteGroup *b) {
89  if (a->get_dependency_order() != b->get_dependency_order()) {
90  return a->get_dependency_order() < b->get_dependency_order();
91  }
92  return a->get_name() < b->get_name();
93  }
94 };
95 
96 // And this one is used in report_pi().
97 class SortGroupsByPreference {
98 public:
99  bool operator ()(PaletteGroup *a, PaletteGroup *b) {
100  return !a->is_preferred_over(*b);
101  }
102 };
103 
104 /**
105  *
106  */
107 Palettizer::
108 Palettizer() {
109  _is_valid = true;
110  _noabs = false;
111 
112  _generated_image_pattern = "%g_palette_%p_%i";
113  _map_dirname = "%g";
114  _shadow_dirname = "shadow";
115  _margin = 2;
116  _omit_solitary = false;
117  _omit_everything = false;
118  _coverage_threshold = 2.5;
119  _aggressively_clean_mapdir = true;
120  _force_power_2 = true;
122  _alpha_type = nullptr;
123  _shadow_color_type = nullptr;
124  _shadow_alpha_type = nullptr;
125  _pal_x_size = _pal_y_size = 512;
126  _background.set(0.0, 0.0, 0.0, 0.0);
127  _cutout_mode = EggRenderMode::AM_dual;
128  _cutout_ratio = 0.3;
129 
130  _round_uvs = true;
131  _round_unit = 0.1;
132  _round_fuzz = 0.01;
133  _remap_uv = RU_poly;
134  _remap_char_uv = RU_poly;
135 
136  get_palette_group("null");
137 }
138 
139 /**
140  * Returns the current setting of the noabs flag. See set_noabs().
141  */
142 bool Palettizer::
143 get_noabs() const {
144  return _noabs;
145 }
146 
147 /**
148  * Changes the current setting of the noabs flag.
149  *
150  * If this flag is true, then it is an error to process an egg file that
151  * contains absolute pathname references. This flag is intended to help
152  * detect egg files that are incorrectly built within a model tree (which
153  * should use entirely relative pathnames).
154  *
155  * This flag must be set before any egg files are processed.
156  */
157 void Palettizer::
158 set_noabs(bool noabs) {
159  _noabs = noabs;
160 }
161 
162 /**
163  * Returns true if the palette information file was read correctly, or false
164  * if there was some error and the palettization can't continue.
165  */
166 bool Palettizer::
167 is_valid() const {
168  return _is_valid;
169 }
170 
171 /**
172  * Output a verbose description of all the palettization information to
173  * standard output, for the user's perusal.
174  */
175 void Palettizer::
176 report_pi() const {
177  // Start out with the cross links and back counts; some of these are nice to
178  // report.
179  EggFiles::const_iterator efi;
180  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
181  (*efi).second->build_cross_links();
182  }
183 
184  cout
185  << "\nparams\n"
186  << " generated image pattern: " << _generated_image_pattern << "\n"
187  << " map directory: " << _map_dirname << "\n"
188  << " shadow directory: "
189  << FilenameUnifier::make_user_filename(_shadow_dirname) << "\n"
190  << " egg relative directory: "
191  << FilenameUnifier::make_user_filename(_rel_dirname) << "\n"
192  << " palettize size: " << _pal_x_size << " by " << _pal_y_size << "\n"
193  << " background: " << _background << "\n"
194  << " margin: " << _margin << "\n"
195  << " coverage threshold: " << _coverage_threshold << "\n"
196  << " force textures to power of 2: " << yesno(_force_power_2) << "\n"
197  << " aggressively clean the map directory: "
198  << yesno(_aggressively_clean_mapdir) << "\n"
199  << " omit everything: " << yesno(_omit_everything) << "\n"
200  << " round UV area: " << yesno(_round_uvs) << "\n";
201  if (_round_uvs) {
202  cout << " round UV area to nearest " << _round_unit << " with fuzz "
203  << _round_fuzz << "\n";
204  }
205  cout << " remap UV's: " << _remap_uv << "\n"
206  << " remap UV's for characters: " << _remap_char_uv << "\n";
207  cout << " alpha cutouts: " << _cutout_mode << " " << _cutout_ratio << "\n";
208 
209  if (_color_type != nullptr) {
210  cout << " generate image files of type: "
211  << _color_type->get_suggested_extension();
212  if (_alpha_type != nullptr) {
213  cout << "," << _alpha_type->get_suggested_extension();
214  }
215  cout << "\n";
216  }
217 
218  if (_shadow_color_type != nullptr) {
219  cout << " generate shadow palette files of type: "
220  << _shadow_color_type->get_suggested_extension();
221  if (_shadow_alpha_type != nullptr) {
222  cout << "," << _shadow_alpha_type->get_suggested_extension();
223  }
224  cout << "\n";
225  }
226 
227  cout << "\ntexture source pathnames and assignments\n";
228  Textures::const_iterator ti;
229  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
230  TextureImage *texture = (*ti).second;
231  if (texture->is_used()) {
232  cout << " " << texture->get_name() << ":\n";
233  texture->write_source_pathnames(cout, 4);
234  }
235  }
236 
237  cout << "\negg files and textures referenced\n";
238  EggFiles::const_iterator ei;
239  for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
240  EggFile *egg_file = (*ei).second;
241  egg_file->write_description(cout, 2);
242  egg_file->write_texture_refs(cout, 4);
243  }
244 
245  // Sort the palette groups into order of preference, so that the more
246  // specific ones appear at the bottom.
247  pvector<PaletteGroup *> sorted_groups;
248  Groups::const_iterator gi;
249  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
250  sorted_groups.push_back((*gi).second);
251  }
252  sort(sorted_groups.begin(), sorted_groups.end(),
253  SortGroupsByPreference());
254 
255  cout << "\npalette groups\n";
257  for (si = sorted_groups.begin(); si != sorted_groups.end(); ++si) {
258  PaletteGroup *group = (*si);
259  if (si != sorted_groups.begin()) {
260  cout << "\n";
261  }
262  cout << " " << group->get_name()
263  // << " (" << group->get_dirname_order() << "," <<
264  // group->get_dependency_order() << ")"
265  << ": " << group->get_groups() << "\n";
266  group->write_image_info(cout, 4);
267  }
268 
269  cout << "\ntextures\n";
270  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
271  TextureImage *texture = (*ti).second;
272  texture->write_scale_info(cout, 2);
273  }
274 
275  cout << "\nsurprises\n";
276  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
277  TextureImage *texture = (*ti).second;
278  if (texture->is_surprise()) {
279  cout << " " << texture->get_name() << "\n";
280  }
281  }
282  for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
283  EggFile *egg_file = (*ei).second;
284  if (egg_file->is_surprise()) {
285  cout << " " << egg_file->get_name() << "\n";
286  }
287  }
288 
289  cout << "\n";
290 }
291 
292 /**
293  * Output a report of the palettization effectiveness, texture memory
294  * utilization, and so on.
295  */
296 void Palettizer::
298  // Sort the groups into order by dependency order, for the user's
299  // convenience.
300  pvector<PaletteGroup *> sorted_groups;
301 
302  Groups::const_iterator gi;
303  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
304  sorted_groups.push_back((*gi).second);
305  }
306 
307  sort(sorted_groups.begin(), sorted_groups.end(),
308  SortGroupsByDependencyOrder());
309 
310  Placements overall_placements;
311 
313  for (si = sorted_groups.begin();
314  si != sorted_groups.end();
315  ++si) {
316  PaletteGroup *group = (*si);
317 
318  Placements placements;
319  group->get_placements(placements);
320  if (!placements.empty()) {
321  group->get_placements(overall_placements);
322 
323  cout << "\n" << group->get_name() << ", by itself:\n";
324  compute_statistics(cout, 2, placements);
325 
326  PaletteGroups complete;
327  complete.make_complete(group->get_groups());
328 
329  if (complete.size() > 1) {
330  Placements complete_placements;
331  group->get_complete_placements(complete_placements);
332  if (complete_placements.size() != placements.size()) {
333  cout << "\n" << group->get_name()
334  << ", with dependents (" << complete << "):\n";
335  compute_statistics(cout, 2, complete_placements);
336  }
337  }
338  }
339  }
340 
341  cout << "\nOverall:\n";
342  compute_statistics(cout, 2, overall_placements);
343 
344  cout << "\n";
345 }
346 
347 
348 /**
349  * Reads in the .txa file and keeps it ready for matching textures and egg
350  * files.
351  */
352 void Palettizer::
353 read_txa_file(std::istream &txa_file, const string &txa_filename) {
354  // Clear out the group dependencies, in preparation for reading them again
355  // from the .txa file.
356  Groups::iterator gi;
357  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
358  PaletteGroup *group = (*gi).second;
359  group->clear_depends();
360  group->set_dirname("");
361  }
362 
363  // Also reset _shadow_color_type.
364  _shadow_color_type = nullptr;
365  _shadow_alpha_type = nullptr;
366 
367  if (!_txa_file.read(txa_file, txa_filename)) {
368  exit(1);
369  }
370 
371  if (_color_type == nullptr) {
372  nout << "No valid output image file type available; cannot run.\n"
373  << "Use :imagetype command in .txa file.\n";
374  exit(1);
375  }
376 
377  // Compute the correct dependency level and order for each group. This will
378  // help us when we assign the textures to their groups.
379  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
380  PaletteGroup *group = (*gi).second;
381  group->reset_dependency_level();
382  }
383 
384  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
385  PaletteGroup *group = (*gi).second;
386  group->set_dependency_level(1);
387  }
388 
389  bool any_changed;
390  do {
391  any_changed = false;
392  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
393  PaletteGroup *group = (*gi).second;
394  if (group->set_dependency_order()) {
395  any_changed = true;
396  }
397  }
398  } while (any_changed);
399 }
400 
401 /**
402  * Called after all command line parameters have been set up, this is a hook
403  * to do whatever initialization is necessary.
404  */
405 void Palettizer::
407  // Make sure the palettes have their shadow images set up properly.
408  Groups::iterator gi;
409  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
410  PaletteGroup *group = (*gi).second;
411  group->setup_shadow_images();
412  }
413 }
414 
415 /**
416  * Processes all the textures named in the _command_line_eggs, placing them on
417  * the appropriate palettes or whatever needs to be done with them.
418  *
419  * If force_texture_read is true, it forces each texture image file to be read
420  * (and thus legitimately checked for grayscaleness etc.) before placing.
421  */
422 void Palettizer::
423 process_command_line_eggs(bool force_texture_read, const Filename &state_filename) {
424  _command_line_textures.clear();
425 
426  // Start by scanning all the egg files we read up on the command line.
427  CommandLineEggs::const_iterator ei;
428  for (ei = _command_line_eggs.begin();
429  ei != _command_line_eggs.end();
430  ++ei) {
431  EggFile *egg_file = (*ei);
432 
433  egg_file->scan_textures();
434  egg_file->get_textures(_command_line_textures);
435 
436  egg_file->pre_txa_file();
437  _txa_file.match_egg(egg_file);
438  egg_file->post_txa_file();
439  }
440 
441  // Now that all of our egg files are read in, build in all the cross links
442  // and back pointers and stuff.
443  EggFiles::const_iterator efi;
444  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
445  (*efi).second->build_cross_links();
446  }
447 
448  // Now match each of the textures mentioned in those egg files against a
449  // line in the .txa file.
450  CommandLineTextures::iterator ti;
451  for (ti = _command_line_textures.begin();
452  ti != _command_line_textures.end();
453  ++ti) {
454  TextureImage *texture = *ti;
455 
456  if (force_texture_read || texture->is_newer_than(state_filename)) {
457  // If we're forcing a redo, or the texture image has changed, re-read
458  // the complete image.
459  texture->read_source_image();
460  } else {
461  // Otherwise, just the header is sufficient.
462  texture->read_header();
463  }
464 
465  texture->mark_texture_named();
466  texture->pre_txa_file();
467  _txa_file.match_texture(texture);
468  texture->post_txa_file();
469  }
470 
471  // And now, assign each of the current set of textures to an appropriate
472  // group or groups.
473  for (ti = _command_line_textures.begin();
474  ti != _command_line_textures.end();
475  ++ti) {
476  TextureImage *texture = *ti;
477  texture->assign_groups();
478  }
479 
480  // And then the egg files need to sign up for a particular TexturePlacement,
481  // so we can determine some more properties about how the textures are
482  // placed (for instance, how big the UV range is for a particular
483  // TexturePlacement).
484  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
485  (*efi).second->choose_placements();
486  }
487 
488  // Now that *that's* done, we need to make sure the various
489  // TexturePlacements require the right size for their textures.
490  for (ti = _command_line_textures.begin();
491  ti != _command_line_textures.end();
492  ++ti) {
493  TextureImage *texture = *ti;
494  texture->determine_placement_size();
495  }
496 
497  // Now that each texture has been assigned to a suitable group, make sure
498  // the textures are placed on specific PaletteImages.
499  Groups::iterator gi;
500  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
501  PaletteGroup *group = (*gi).second;
502  group->update_unknown_textures(_txa_file);
503  group->place_all();
504  }
505 }
506 
507 /**
508  * Reprocesses all textures known.
509  *
510  * If force_texture_read is true, it forces each texture image file to be read
511  * (and thus legitimately checked for grayscaleness etc.) before placing.
512  */
513 void Palettizer::
514 process_all(bool force_texture_read, const Filename &state_filename) {
515  // First, clear all the basic properties on the source texture images, so we
516  // can reapply them from the complete set of egg files and thereby ensure
517  // they are up-to-date.
518  Textures::iterator ti;
519  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
520  TextureImage *texture = (*ti).second;
522  }
523 
524  // If there *were* any egg files on the command line, deal with them.
525  CommandLineEggs::const_iterator ei;
526  for (ei = _command_line_eggs.begin();
527  ei != _command_line_eggs.end();
528  ++ei) {
529  EggFile *egg_file = (*ei);
530 
531  egg_file->scan_textures();
532  egg_file->get_textures(_command_line_textures);
533  }
534 
535  // Then match up all the egg files we know about with the .txa file.
536  EggFiles::const_iterator efi;
537  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
538  EggFile *egg_file = (*efi).second;
539  egg_file->pre_txa_file();
540  _txa_file.match_egg(egg_file);
541  egg_file->post_txa_file();
542  }
543 
544  // Now that all of our egg files are read in, build in all the cross links
545  // and back pointers and stuff.
546  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
547  (*efi).second->build_cross_links();
548 
549  // Also make sure each egg file's properties are applied to the source
550  // image (since we reset all the source image properties, above).
551  (*efi).second->apply_properties_to_source();
552  }
553 
554  // Now match each of the textures in the world against a line in the .txa
555  // file.
556  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
557  TextureImage *texture = (*ti).second;
558  if (force_texture_read || texture->is_newer_than(state_filename)) {
559  texture->read_source_image();
560  }
561 
562  texture->mark_texture_named();
563  texture->pre_txa_file();
564  _txa_file.match_texture(texture);
565  texture->post_txa_file();
566 
567  // We need to do this to avoid bloating memory.
568  texture->release_source_image();
569  }
570 
571  // And now, assign each texture to an appropriate group or groups.
572  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
573  TextureImage *texture = (*ti).second;
574  texture->assign_groups();
575  }
576 
577  // And then the egg files need to sign up for a particular TexturePlacement,
578  // so we can determine some more properties about how the textures are
579  // placed (for instance, how big the UV range is for a particular
580  // TexturePlacement).
581  for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
582  (*efi).second->choose_placements();
583  }
584 
585  // Now that *that's* done, we need to make sure the various
586  // TexturePlacements require the right size for their textures.
587  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
588  TextureImage *texture = (*ti).second;
589  texture->determine_placement_size();
590  }
591 
592  // Now that each texture has been assigned to a suitable group, make sure
593  // the textures are placed on specific PaletteImages.
594  Groups::iterator gi;
595  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
596  PaletteGroup *group = (*gi).second;
597  group->update_unknown_textures(_txa_file);
598  group->place_all();
599  }
600 }
601 
602 /**
603  * Attempts to resize each PalettteImage down to its smallest possible size.
604  */
605 void Palettizer::
607  Groups::iterator gi;
608  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
609  PaletteGroup *group = (*gi).second;
610  group->optimal_resize();
611  }
612 }
613 
614 /**
615  * Throws away all of the current PaletteImages, so that new ones may be
616  * created (and the packing made more optimal).
617  */
618 void Palettizer::
620  Groups::iterator gi;
621  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
622  PaletteGroup *group = (*gi).second;
623  group->reset_images();
624  }
625 }
626 
627 /**
628  * Actually generates the appropriate palette and unplaced texture images into
629  * the map directories. If redo_all is true, this forces a regeneration of
630  * each image file.
631  */
632 void Palettizer::
633 generate_images(bool redo_all) {
634  Groups::iterator gi;
635  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
636  PaletteGroup *group = (*gi).second;
637  group->update_images(redo_all);
638  }
639 
640  Textures::iterator ti;
641  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
642  TextureImage *texture = (*ti).second;
643  texture->copy_unplaced(redo_all);
644  }
645 }
646 
647 /**
648  * Reads in any egg file that is known to be stale, even if it was not listed
649  * on the command line, so that it may be updated and written out when
650  * write_eggs() is called. If redo_all is true, this even reads egg files
651  * that were not flagged as stale.
652  *
653  * Returns true if successful, or false if there was some error.
654  */
655 bool Palettizer::
656 read_stale_eggs(bool redo_all) {
657  bool okflag = true;
658 
659  pvector<EggFiles::iterator> invalid_eggs;
660 
661  EggFiles::iterator ei;
662  for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
663  EggFile *egg_file = (*ei).second;
664  if (!egg_file->had_data() &&
665  (egg_file->is_stale() || redo_all)) {
666  if (!egg_file->read_egg(_noabs)) {
667  invalid_eggs.push_back(ei);
668 
669  } else {
670  egg_file->scan_textures();
671  egg_file->choose_placements();
672  egg_file->release_egg_data();
673  }
674  }
675  }
676 
677  // Now eliminate all the invalid egg files.
679  for (ii = invalid_eggs.begin(); ii != invalid_eggs.end(); ++ii) {
680  EggFiles::iterator ei = (*ii);
681  EggFile *egg_file = (*ei).second;
682  if (egg_file->get_source_filename().exists()) {
683  // If there is an invalid egg file, remove it; hopefully it will get
684  // rebuilt properly next time.
685  nout << "Removing invalid egg file: "
687  << "\n";
688 
689  egg_file->get_source_filename().unlink();
690  okflag = false;
691 
692  } else {
693  // If the egg file is simply missing, quietly remove any record of it
694  // from the database.
695  egg_file->remove_egg();
696  _egg_files.erase(ei);
697  }
698  }
699 
700  if (!okflag) {
701  nout << "\n"
702  << "Some errors in egg files encountered.\n"
703  << "Re-run make install or make opt-pal to try to regenerate these.\n\n";
704  }
705 
706  return okflag;
707 }
708 
709 /**
710  * Adjusts the egg files to reference the newly generated textures, and writes
711  * them out. Returns true if successful, or false if there was some error.
712  */
713 bool Palettizer::
715  bool okflag = true;
716 
717  EggFiles::iterator ei;
718  for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
719  EggFile *egg_file = (*ei).second;
720  if (egg_file->had_data()) {
721  if (!egg_file->has_data()) {
722  // Re-read the egg file.
723  bool read_ok = egg_file->read_egg(_noabs);
724  if (!read_ok) {
725  nout << "Error! Unable to re-read egg file.\n";
726  okflag = false;
727  }
728  }
729 
730  if (egg_file->has_data()) {
731  egg_file->update_egg();
732  if (!egg_file->write_egg()) {
733  okflag = false;
734  }
735  egg_file->release_egg_data();
736  }
737  }
738  }
739 
740  return okflag;
741 }
742 
743 /**
744  * Returns the EggFile with the given name. If there is no EggFile with the
745  * indicated name, creates one. This is the key name used to sort the egg
746  * files, which is typically the basename of the filename.
747  */
749 get_egg_file(const string &name) {
750  EggFiles::iterator ei = _egg_files.find(name);
751  if (ei != _egg_files.end()) {
752  return (*ei).second;
753  }
754 
755  EggFile *file = new EggFile;
756  file->set_name(name);
757  _egg_files.insert(EggFiles::value_type(name, file));
758  return file;
759 }
760 
761 /**
762  * Removes the named egg file from the database, if it exists. Returns true
763  * if the egg file was found, false if it was not.
764  */
765 bool Palettizer::
766 remove_egg_file(const string &name) {
767  EggFiles::iterator ei = _egg_files.find(name);
768  if (ei != _egg_files.end()) {
769  EggFile *file = (*ei).second;
770  file->remove_egg();
771  _egg_files.erase(ei);
772  return true;
773  }
774 
775  return false;
776 }
777 
778 /**
779  * Adds the indicated EggFile to the list of eggs that are considered to have
780  * been read on the command line. These will be processed by
781  * process_command_line_eggs().
782  */
783 void Palettizer::
785  _command_line_eggs.push_back(egg_file);
786 }
787 
788 /**
789  * Returns the PaletteGroup with the given name. If there is no PaletteGroup
790  * with the indicated name, creates one.
791  */
793 get_palette_group(const string &name) {
794  Groups::iterator gi = _groups.find(name);
795  if (gi != _groups.end()) {
796  return (*gi).second;
797  }
798 
799  PaletteGroup *group = new PaletteGroup;
800  group->set_name(name);
801  _groups.insert(Groups::value_type(name, group));
802  return group;
803 }
804 
805 /**
806  * Returns the PaletteGroup with the given name. If there is no PaletteGroup
807  * with the indicated name, returns NULL.
808  */
810 test_palette_group(const string &name) const {
811  Groups::const_iterator gi = _groups.find(name);
812  if (gi != _groups.end()) {
813  return (*gi).second;
814  }
815 
816  return nullptr;
817 }
818 
819 /**
820  * Returns the default group to which an egg file should be assigned if it is
821  * not mentioned in the .txa file.
822  */
825  PaletteGroup *default_group = get_palette_group(_default_groupname);
826  if (!_default_groupdir.empty() && !default_group->has_dirname()) {
827  default_group->set_dirname(_default_groupdir);
828  }
829  return default_group;
830 }
831 
832 /**
833  * Returns the TextureImage with the given name. If there is no TextureImage
834  * with the indicated name, creates one. This is the key name used to sort
835  * the textures, which is typically the basename of the primary filename.
836  */
838 get_texture(const string &name) {
839  // Look first in the same-case name, just in case it happens to be there
840  // (from an older version of egg-palettize that did this).
841  Textures::iterator ti = _textures.find(name);
842  if (ti != _textures.end()) {
843  return (*ti).second;
844  }
845 
846  // Then look in the downcase name, since we nowadays index textures only by
847  // their downcase names (to implement case insensitivity).
848  string downcase_name = downcase(name);
849  ti = _textures.find(downcase_name);
850  if (ti != _textures.end()) {
851  return (*ti).second;
852  }
853 
854  TextureImage *image = new TextureImage;
855  image->set_name(name);
856  // image->set_filename(name);
857  _textures.insert(Textures::value_type(downcase_name, image));
858 
859  return image;
860 }
861 
862 /**
863  * A silly function to return "yes" or "no" based on a bool flag for nicely
864  * formatted output.
865  */
866 const char *Palettizer::
867 yesno(bool flag) {
868  return flag ? "yes" : "no";
869 }
870 
871 /**
872  * Returns the RemapUV code corresponding to the indicated string, or
873  * RU_invalid if the string is invalid.
874  */
875 Palettizer::RemapUV Palettizer::
876 string_remap(const string &str) {
877  if (str == "never") {
878  return RU_never;
879 
880  } else if (str == "group") {
881  return RU_group;
882 
883  } else if (str == "poly") {
884  return RU_poly;
885 
886  } else {
887  return RU_invalid;
888  }
889 }
890 
891 /**
892  * Determines how much memory, etc. is required by the indicated set of
893  * texture placements, and reports this to the indicated output stream.
894  */
895 void Palettizer::
896 compute_statistics(std::ostream &out, int indent_level,
897  const Palettizer::Placements &placements) const {
898  TextureMemoryCounter counter;
899 
900  Placements::const_iterator pi;
901  for (pi = placements.begin(); pi != placements.end(); ++pi) {
902  TexturePlacement *placement = (*pi);
903  counter.add_placement(placement);
904  }
905 
906  counter.report(out, indent_level);
907 }
908 
909 /**
910  * Registers the current object as something that can be read from a Bam file.
911  */
912 void Palettizer::
915  register_factory(get_class_type(), make_Palettizer);
916 }
917 
918 /**
919  * Fills the indicated datagram up with a binary representation of the current
920  * object, in preparation for writing to a Bam file.
921  */
922 void Palettizer::
923 write_datagram(BamWriter *writer, Datagram &datagram) {
924  TypedWritable::write_datagram(writer, datagram);
925 
926  datagram.add_int32(_pi_version);
927  datagram.add_string(_generated_image_pattern);
928  datagram.add_string(_map_dirname);
929  datagram.add_string(FilenameUnifier::make_bam_filename(_shadow_dirname));
930  datagram.add_string(FilenameUnifier::make_bam_filename(_rel_dirname));
931  datagram.add_int32(_pal_x_size);
932  datagram.add_int32(_pal_y_size);
933  datagram.add_float64(_background[0]);
934  datagram.add_float64(_background[1]);
935  datagram.add_float64(_background[2]);
936  datagram.add_float64(_background[3]);
937  datagram.add_int32(_margin);
938  datagram.add_bool(_omit_solitary);
939  datagram.add_bool(_omit_everything);
940  datagram.add_float64(_coverage_threshold);
941  datagram.add_bool(_force_power_2);
942  datagram.add_bool(_aggressively_clean_mapdir);
943  datagram.add_bool(_round_uvs);
944  datagram.add_float64(_round_unit);
945  datagram.add_float64(_round_fuzz);
946  datagram.add_int32((int)_remap_uv);
947  datagram.add_int32((int)_remap_char_uv);
948  datagram.add_uint8((int)_cutout_mode);
949  datagram.add_float64(_cutout_ratio);
950 
951  writer->write_pointer(datagram, _color_type);
952  writer->write_pointer(datagram, _alpha_type);
953  writer->write_pointer(datagram, _shadow_color_type);
954  writer->write_pointer(datagram, _shadow_alpha_type);
955 
956  datagram.add_int32(_egg_files.size());
957  EggFiles::const_iterator ei;
958  for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) {
959  writer->write_pointer(datagram, (*ei).second);
960  }
961 
962  // We don't write _command_line_eggs; that's specific to each session.
963 
964  datagram.add_int32(_groups.size());
965  Groups::const_iterator gi;
966  for (gi = _groups.begin(); gi != _groups.end(); ++gi) {
967  writer->write_pointer(datagram, (*gi).second);
968  }
969 
970  datagram.add_int32(_textures.size());
971  Textures::const_iterator ti;
972  for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
973  writer->write_pointer(datagram, (*ti).second);
974  }
975 }
976 
977 /**
978  * Called after the object is otherwise completely read from a Bam file, this
979  * function's job is to store the pointers that were retrieved from the Bam
980  * file for each pointer object written. The return value is the number of
981  * pointers processed from the list.
982  */
983 int Palettizer::
985  int index = TypedWritable::complete_pointers(p_list, manager);
986 
987  if (p_list[index] != nullptr) {
988  DCAST_INTO_R(_color_type, p_list[index], index);
989  }
990  index++;
991 
992  if (p_list[index] != nullptr) {
993  DCAST_INTO_R(_alpha_type, p_list[index], index);
994  }
995  index++;
996 
997  if (p_list[index] != nullptr) {
998  DCAST_INTO_R(_shadow_color_type, p_list[index], index);
999  }
1000  index++;
1001 
1002  if (p_list[index] != nullptr) {
1003  DCAST_INTO_R(_shadow_alpha_type, p_list[index], index);
1004  }
1005  index++;
1006 
1007  int i;
1008  for (i = 0; i < _num_egg_files; i++) {
1009  EggFile *egg_file;
1010  DCAST_INTO_R(egg_file, p_list[index], index);
1011  _egg_files.insert(EggFiles::value_type(egg_file->get_name(), egg_file));
1012  index++;
1013  }
1014 
1015  for (i = 0; i < _num_groups; i++) {
1016  PaletteGroup *group;
1017  DCAST_INTO_R(group, p_list[index], index);
1018  _groups.insert(Groups::value_type(group->get_name(), group));
1019  index++;
1020  }
1021 
1022  for (i = 0; i < _num_textures; i++) {
1023  TextureImage *texture;
1024  DCAST_INTO_R(texture, p_list[index], index);
1025 
1026  string name = downcase(texture->get_name());
1027  std::pair<Textures::iterator, bool> result = _textures.insert(Textures::value_type(name, texture));
1028  if (!result.second) {
1029  // Two textures mapped to the same slot--probably a case error (since we
1030  // just changed this rule).
1031  _texture_conflicts.push_back(texture);
1032  }
1033  index++;
1034  }
1035 
1036  return index;
1037 }
1038 
1039 /**
1040  * Called by the BamReader to perform any final actions needed for setting up
1041  * the object after all objects have been read and all pointers have been
1042  * completed.
1043  */
1044 void Palettizer::
1045 finalize(BamReader *manager) {
1046  // Walk through the list of texture names that were in conflict. These can
1047  // only happen if there were two different names that different only in
1048  // case, which means the textures.boo file was created before we introduced
1049  // the rule that case is insignificant.
1050  TextureConflicts::iterator ci;
1051  for (ci = _texture_conflicts.begin();
1052  ci != _texture_conflicts.end();
1053  ++ci) {
1054  TextureImage *texture_b = (*ci);
1055  string downcase_name = downcase(texture_b->get_name());
1056 
1057  Textures::iterator ti = _textures.find(downcase_name);
1058  nassertv(ti != _textures.end());
1059  TextureImage *texture_a = (*ti).second;
1060  _textures.erase(ti);
1061 
1062  if (!texture_b->is_used() || !texture_a->is_used()) {
1063  // If either texture is not used, there's not really a conflict--the
1064  // other one wins.
1065  if (texture_a->is_used()) {
1066  bool inserted1 = _textures.insert(Textures::value_type(downcase_name, texture_a)).second;
1067  nassertd(inserted1) { }
1068 
1069  } else if (texture_b->is_used()) {
1070  bool inserted2 = _textures.insert(Textures::value_type(downcase_name, texture_b)).second;
1071  nassertd(inserted2) { }
1072  }
1073 
1074  } else {
1075  // If both textures are used, there *is* a conflict.
1076  nout << "Texture name conflict: \"" << texture_a->get_name()
1077  << "\" vs. \"" << texture_b->get_name() << "\"\n";
1078  if (texture_a->get_name() != downcase_name &&
1079  texture_b->get_name() != downcase_name) {
1080  // Arbitrarily pick texture_a to get the right case.
1081  bool inserted1 = _textures.insert(Textures::value_type(downcase_name, texture_a)).second;
1082  bool inserted2 = _textures.insert(Textures::value_type(texture_b->get_name(), texture_b)).second;
1083  nassertd(inserted1 && inserted2) { }
1084 
1085  } else {
1086  // One of them is already the right case.
1087  bool inserted1 = _textures.insert(Textures::value_type(texture_a->get_name(), texture_a)).second;
1088  bool inserted2 = _textures.insert(Textures::value_type(texture_b->get_name(), texture_b)).second;
1089  nassertd(inserted1 && inserted2) { }
1090  }
1091  }
1092  }
1093 }
1094 
1095 
1096 /**
1097  * This method is called by the BamReader when an object of this type is
1098  * encountered in a Bam file; it should allocate and return a new object with
1099  * all the data read.
1100  */
1101 TypedWritable* Palettizer::
1102 make_Palettizer(const FactoryParams &params) {
1103  Palettizer *me = new Palettizer;
1104  DatagramIterator scan;
1105  BamReader *manager;
1106 
1107  parse_params(params, scan, manager);
1108  me->fillin(scan, manager);
1109  manager->register_finalize(me);
1110 
1111  return me;
1112 }
1113 
1114 /**
1115  * Reads the binary data from the given datagram iterator, which was written
1116  * by a previous call to write_datagram().
1117  */
1118 void Palettizer::
1119 fillin(DatagramIterator &scan, BamReader *manager) {
1120  TypedWritable::fillin(scan, manager);
1121 
1122  _read_pi_version = scan.get_int32();
1123  if (_read_pi_version > _pi_version || _read_pi_version < _min_pi_version) {
1124  // Oops, we don't know how to read this palette information file.
1125  _is_valid = false;
1126  return;
1127  }
1128  if (_read_pi_version >= 12) {
1129  _generated_image_pattern = scan.get_string();
1130  }
1131  _map_dirname = scan.get_string();
1132  _shadow_dirname = FilenameUnifier::get_bam_filename(scan.get_string());
1133  _rel_dirname = FilenameUnifier::get_bam_filename(scan.get_string());
1134  FilenameUnifier::set_rel_dirname(_rel_dirname);
1135  _pal_x_size = scan.get_int32();
1136  _pal_y_size = scan.get_int32();
1137  if (_read_pi_version >= 13) {
1138  _background[0] = scan.get_float64();
1139  _background[1] = scan.get_float64();
1140  _background[2] = scan.get_float64();
1141  _background[3] = scan.get_float64();
1142  }
1143  _margin = scan.get_int32();
1144  _omit_solitary = scan.get_bool();
1145  if (_read_pi_version >= 14) {
1146  _omit_everything = scan.get_bool();
1147  }
1148  _coverage_threshold = scan.get_float64();
1149  _force_power_2 = scan.get_bool();
1150  _aggressively_clean_mapdir = scan.get_bool();
1151  _round_uvs = scan.get_bool();
1152  _round_unit = scan.get_float64();
1153  _round_fuzz = scan.get_float64();
1154  _remap_uv = (RemapUV)scan.get_int32();
1155  _remap_char_uv = (RemapUV)scan.get_int32();
1156  if (_read_pi_version >= 16) {
1157  _cutout_mode = (EggRenderMode::AlphaMode)scan.get_uint8();
1158  _cutout_ratio = scan.get_float64();
1159  }
1160 
1161  manager->read_pointer(scan); // _color_type
1162  manager->read_pointer(scan); // _alpha_type
1163  manager->read_pointer(scan); // _shadow_color_type
1164  manager->read_pointer(scan); // _shadow_alpha_type
1165 
1166  _num_egg_files = scan.get_int32();
1167  manager->read_pointers(scan, _num_egg_files);
1168 
1169  _num_groups = scan.get_int32();
1170  manager->read_pointers(scan, _num_groups);
1171 
1172  _num_textures = scan.get_int32();
1173  manager->read_pointers(scan, _num_textures);
1174 }
EggFile::release_egg_data
void release_egg_data()
Releases the memory that was loaded by a previous call to read_egg().
Definition: eggFile.cxx:553
PaletteGroup::clear_depends
void clear_depends()
Eliminates all the dependency information for this group.
Definition: paletteGroup.cxx:79
DatagramIterator::get_string
std::string get_string()
Extracts a variable-length string.
Definition: datagramIterator.cxx:26
TextureMemoryCounter::report
void report(std::ostream &out, int indent_level)
Reports the measured texture memory usage.
Definition: textureMemoryCounter.cxx:84
eggData.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Palettizer::remove_egg_file
bool remove_egg_file(const std::string &name)
Removes the named egg file from the database, if it exists.
Definition: palettizer.cxx:766
PaletteGroup::get_dependency_order
int get_dependency_order() const
Returns the dependency order of this group.
Definition: paletteGroup.cxx:268
TextureImage::assign_groups
void assign_groups()
Assigns the texture to all of the PaletteGroups the various egg files that use it need.
Definition: textureImage.cxx:76
FilenameUnifier::get_bam_filename
static Filename get_bam_filename(Filename filename)
Returns an absolute pathname based on the given relative pathname, presumably read from the bam file ...
Definition: filenameUnifier.cxx:72
PaletteGroup::place_all
void place_all()
Once all the textures have been assigned to this group, try to place them all onto suitable PaletteIm...
Definition: paletteGroup.cxx:408
DatagramIterator::get_int32
int32_t get_int32()
Extracts a signed 32-bit integer.
Definition: datagramIterator.I:107
Palettizer::write_datagram
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object,...
Definition: palettizer.cxx:923
TextureImage::read_header
void read_header()
Causes the header part of the image to be reread, usually to confirm that its image properties (size,...
Definition: textureImage.cxx:754
TextureMemoryCounter
This class is used to gather statistics on texture memory usage, etc.
Definition: textureMemoryCounter.h:33
PaletteGroup
This is the highest level of grouping for TextureImages.
Definition: paletteGroup.h:43
EggFile
This represents a single egg file known to the palettizer.
Definition: eggFile.h:36
pvector
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
PaletteGroup::update_images
void update_images(bool redo_all)
Regenerates each PaletteImage on this group that needs it.
Definition: paletteGroup.cxx:549
Palettizer::get_default_group
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
FilenameUnifier::make_bam_filename
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...
Definition: filenameUnifier.cxx:61
EggFile::write_texture_refs
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
EggFile::get_textures
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
PaletteGroup::set_dependency_level
void set_dependency_level(int level)
Sets the dependency level of this group to the indicated level, provided that level is not lower than...
Definition: paletteGroup.cxx:184
Palettizer::complete_pointers
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: palettizer.cxx:984
Palettizer::read_stale_eggs
bool read_stale_eggs(bool redo_all)
Reads in any egg file that is known to be stale, even if it was not listed on the command line,...
Definition: palettizer.cxx:656
Palettizer::register_with_read_factory
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
Definition: palettizer.cxx:913
EggFile::update_egg
void update_egg()
Once all textures have been placed appropriately, updates the egg file with all the information to re...
Definition: eggFile.cxx:447
pnmImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Palettizer::add_command_line_egg
void add_command_line_egg(EggFile *egg_file)
Adds the indicated EggFile to the list of eggs that are considered to have been read on the command l...
Definition: palettizer.cxx:784
Datagram::add_uint8
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
DatagramIterator
A class to retrieve the individual data elements previously stored in a Datagram.
Definition: datagramIterator.h:27
Filename::exists
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
PaletteGroup::update_unknown_textures
void update_unknown_textures(const TxaFile &txa_file)
Checks for new information on any textures within the group for which some of the saved information i...
Definition: paletteGroup.cxx:435
TypedWritable::complete_pointers
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().
Definition: typedWritable.cxx:81
BamReader
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
TxaFile::match_texture
bool match_texture(TextureImage *texture) const
Searches for a matching line in the .txa file for the given texture and applies its specifications.
Definition: txaFile.cxx:149
PaletteGroup::has_dirname
bool has_dirname() const
Returns true if the directory name has been explicitly set for this group.
Definition: paletteGroup.cxx:62
EggFile::post_txa_file
void post_txa_file()
Once the egg file has been matched against all of the matching lines the .txa file,...
Definition: eggFile.cxx:249
Palettizer::get_egg_file
EggFile * get_egg_file(const std::string &name)
Returns the EggFile with the given name.
Definition: palettizer.cxx:749
PaletteGroup::reset_images
void reset_images()
Throws away all of the current PaletteImages, so that new ones may be created (and the packing made m...
Definition: paletteGroup.cxx:523
BamWriter
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
TextureImage::pre_txa_file
void pre_txa_file()
Updates any internal state prior to reading the .txa file.
Definition: textureImage.cxx:265
BamWriter::write_pointer
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
Palettizer
This is the main engine behind egg-palettize.
Definition: palettizer.h:39
BamReader::get_factory
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
Palettizer::process_command_line_eggs
void process_command_line_eggs(bool force_texture_read, const Filename &state_filename)
Processes all the textures named in the _command_line_eggs, placing them on the appropriate palettes ...
Definition: palettizer.cxx:423
PaletteGroup::is_preferred_over
bool is_preferred_over(const PaletteGroup &other) const
Returns true if this group should be preferred for adding textures over the other group,...
Definition: paletteGroup.cxx:292
Palettizer::string_remap
static RemapUV string_remap(const std::string &str)
Returns the RemapUV code corresponding to the indicated string, or RU_invalid if the string is invali...
Definition: palettizer.cxx:876
PaletteGroup::get_complete_placements
void get_complete_placements(pvector< TexturePlacement * > &placements) const
Adds the set of TexturePlacements associated with this group and all dependent groups to the indicate...
Definition: paletteGroup.cxx:150
Palettizer::write_eggs
bool write_eggs()
Adjusts the egg files to reference the newly generated textures, and writes them out.
Definition: palettizer.cxx:714
EggFile::pre_txa_file
void pre_txa_file()
Does some processing prior to scanning the .txa file.
Definition: eggFile.cxx:221
downcase
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
Definition: string_utils.cxx:71
bamReader.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureImage::read_source_image
const PNMImage & read_source_image()
Reads in the original image, if it has not already been read, and returns it.
Definition: textureImage.cxx:709
textureImage.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TypedWritable
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
PNMFileType::get_suggested_extension
get_suggested_extension
Returns a suitable filename extension (without a leading dot) to suggest for files of this type,...
Definition: pnmFileType.h:49
Datagram
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
Palettizer::generate_images
void generate_images(bool redo_all)
Actually generates the appropriate palette and unplaced texture images into the map directories.
Definition: palettizer.cxx:633
DatagramIterator::get_float64
PN_float64 get_float64()
Extracts a 64-bit floating-point number.
Definition: datagramIterator.I:221
Palettizer::set_noabs
void set_noabs(bool noabs)
Changes the current setting of the noabs flag.
Definition: palettizer.cxx:158
TextureImage::post_txa_file
void post_txa_file()
Once the .txa file has been read and the TextureImage matched against it, considers applying the requ...
Definition: textureImage.cxx:289
Palettizer::report_statistics
void report_statistics() const
Output a report of the palettization effectiveness, texture memory utilization, and so on.
Definition: palettizer.cxx:297
EggFile::choose_placements
void choose_placements()
Once all the textures have been assigned to groups (but before they may actually be placed),...
Definition: eggFile.cxx:381
Datagram::add_string
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
BamReader::register_finalize
void register_finalize(TypedWritable *whom)
Should be called by an object reading itself from the Bam file to indicate that this particular objec...
Definition: bamReader.cxx:808
EggFile::get_source_filename
const Filename & get_source_filename() const
Returns the filename this egg file was read from.
Definition: eggFile.cxx:91
BamReader::read_pointers
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
filenameUnifier.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
DatagramIterator::get_bool
bool get_bool()
Extracts a boolean value.
Definition: datagramIterator.I:48
FactoryParams
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
TextureImage::is_surprise
bool is_surprise() const
Returns true if this particular texture is a 'surprise', i.e.
Definition: textureImage.cxx:465
Palettizer::get_noabs
bool get_noabs() const
Returns the current setting of the noabs flag.
Definition: palettizer.cxx:143
palettizer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PNMFileTypeRegistry::get_global_ptr
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
Definition: pnmFileTypeRegistry.cxx:277
TypedWritable::write_datagram
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
Definition: typedWritable.cxx:54
PaletteGroup::write_image_info
void write_image_info(std::ostream &out, int indent_level=0) const
Writes a list of the PaletteImages associated with this group, and all of their textures,...
Definition: paletteGroup.cxx:460
Palettizer::optimal_resize
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
Definition: palettizer.cxx:606
EggFile::write_egg
bool write_egg()
Writes out the egg file to its _dest_filename.
Definition: eggFile.cxx:569
TxaFile::read
bool read(std::istream &in, const std::string &filename)
Reads the indicated stream, and returns true if successful, or false if there is an error.
Definition: txaFile.cxx:37
TextureImage::release_source_image
void release_source_image()
Frees the memory that was allocated by a previous call to read_source_image().
Definition: textureImage.cxx:729
pnmFileType.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PaletteGroups::size
size_type size() const
Returns the number of elements in the set.
Definition: paletteGroups.cxx:192
TextureMemoryCounter::add_placement
void add_placement(TexturePlacement *placement)
Adds the indicated TexturePlacement to the counter.
Definition: textureMemoryCounter.cxx:54
PaletteGroup::optimal_resize
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
Definition: paletteGroup.cxx:510
datagram.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
TextureImage::is_used
bool is_used() const
Returns true if this particular texture has been placed somewhere, anywhere, or false if it is not us...
Definition: textureImage.cxx:480
TextureImage::clear_source_basic_properties
void clear_source_basic_properties()
Calls clear_basic_properties() on each source texture image used by this texture, to reset the proper...
Definition: textureImage.cxx:633
pnmFileTypeRegistry.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggFile::remove_egg
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
PaletteGroup::set_dirname
void set_dirname(const std::string &dirname)
Sets the directory name associated with the palette group.
Definition: paletteGroup.cxx:53
EggFile::write_description
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
TextureImage::is_newer_than
bool is_newer_than(const Filename &reference_filename)
Returns true if the source image is newer than the indicated file, false otherwise.
Definition: textureImage.cxx:768
Palettizer::read_txa_file
void read_txa_file(std::istream &txa_file, const std::string &txa_filename)
Reads in the .txa file and keeps it ready for matching textures and egg files.
Definition: palettizer.cxx:353
PaletteGroup::set_dependency_order
bool set_dependency_order()
Updates the dependency order of this group.
Definition: paletteGroup.cxx:204
EggFile::has_data
bool has_data() const
Returns true if the EggData for this EggFile has been loaded, and not yet released.
Definition: eggFile.cxx:429
Datagram::add_int32
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
pal_string_utils.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
EggFile::had_data
bool had_data() const
Returns true if the EggData for this EggFile has ever been loaded in this session.
Definition: eggFile.cxx:438
Palettizer::test_palette_group
PaletteGroup * test_palette_group(const std::string &name) const
Returns the PaletteGroup with the given name.
Definition: palettizer.cxx:810
FilenameUnifier::make_user_filename
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...
Definition: filenameUnifier.cxx:97
Palettizer::is_valid
bool is_valid() const
Returns true if the palette information file was read correctly, or false if there was some error and...
Definition: palettizer.cxx:167
TextureImage::write_scale_info
void write_scale_info(std::ostream &out, int indent_level=0)
Writes the information about the texture's size and placement.
Definition: textureImage.cxx:858
textureMemoryCounter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
BamReader::read_pointer
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
PaletteGroups::make_complete
void make_complete(const PaletteGroups &a)
Completes the set with the transitive closure of all dependencies: for each PaletteGroup already in t...
Definition: paletteGroups.cxx:75
TexturePlacement
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
Definition: texturePlacement.h:41
Datagram::add_bool
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
Palettizer::report_pi
void report_pi() const
Output a verbose description of all the palettization information to standard output,...
Definition: palettizer.cxx:176
PNMFileTypeRegistry::get_type_from_extension
PNMFileType * get_type_from_extension(const std::string &filename) const
Tries to determine what the PNMFileType is likely to be for a particular image file based on its exte...
Definition: pnmFileTypeRegistry.cxx:147
TextureImage::copy_unplaced
void copy_unplaced(bool redo_all)
Copies the texture to whichever destination directories are appropriate for the groups in which it ha...
Definition: textureImage.cxx:649
Palettizer::get_palette_group
PaletteGroup * get_palette_group(const std::string &name)
Returns the PaletteGroup with the given name.
Definition: palettizer.cxx:793
PaletteGroup::get_placements
void get_placements(pvector< TexturePlacement * > &placements) const
Adds the set of TexturePlacements associated with this group to the indicated vector.
Definition: paletteGroup.cxx:138
TextureImage::determine_placement_size
void determine_placement_size()
Calls determine_size() on each TexturePlacement for the texture, to ensure that each TexturePlacement...
Definition: textureImage.cxx:422
datagramIterator.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Palettizer::reset_images
void reset_images()
Throws away all of the current PaletteImages, so that new ones may be created (and the packing made m...
Definition: palettizer.cxx:619
EggFile::read_egg
bool read_egg(bool noabs)
Reads in the egg file from its _source_filename.
Definition: eggFile.cxx:480
indent.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
FilenameUnifier::set_rel_dirname
static void set_rel_dirname(const Filename &rel_dirname)
Sets the name of the directory that texture filenames will be written relative to,...
Definition: filenameUnifier.cxx:49
DatagramIterator::get_uint8
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
Definition: datagramIterator.I:72
Filename::unlink
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
TypedWritable::fillin
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...
Definition: typedWritable.cxx:103
Palettizer::process_all
void process_all(bool force_texture_read, const Filename &state_filename)
Reprocesses all textures known.
Definition: palettizer.cxx:514
Palettizer::get_texture
TextureImage * get_texture(const std::string &name)
Returns the TextureImage with the given name.
Definition: palettizer.cxx:838
bamWriter.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Palettizer::all_params_set
void all_params_set()
Called after all command line parameters have been set up, this is a hook to do whatever initializati...
Definition: palettizer.cxx:406
PaletteGroups
A set of PaletteGroups.
Definition: paletteGroups.h:28
eggFile.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PaletteGroup::setup_shadow_images
void setup_shadow_images()
Ensures that each PaletteImage's _shadow_image has the correct filename and image types,...
Definition: paletteGroup.cxx:537
EggFile::scan_textures
void scan_textures()
Scans the egg file for texture references and updates the _textures list appropriately.
Definition: eggFile.cxx:102
TextureImage::write_source_pathnames
void write_source_pathnames(std::ostream &out, int indent_level=0) const
Writes the list of source pathnames that might contribute to this texture to the indicated output str...
Definition: textureImage.cxx:785
PaletteGroup::reset_dependency_level
void reset_dependency_level()
Unconditionally sets the dependency level and order of this group to zero, in preparation for a later...
Definition: paletteGroup.cxx:169
TextureImage::mark_texture_named
void mark_texture_named()
Indicates that this particular texture has been named by the user for processing this session,...
Definition: textureImage.cxx:247
paletteGroup.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Datagram::add_float64
void add_float64(PN_float64 value)
Adds a 64-bit floating-point number to the datagram.
Definition: datagram.I:123
parse_params
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
TextureImage
This represents a single source texture that is referenced by one or more egg files.
Definition: textureImage.h:46
Filename
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
EggFile::is_surprise
bool is_surprise() const
Returns true if this particular egg file is a 'surprise', i.e.
Definition: eggFile.cxx:294
PaletteGroup::get_groups
const PaletteGroups & get_groups() const
Returns the set of groups this group depends on.
Definition: paletteGroup.cxx:102
TxaFile::match_egg
bool match_egg(EggFile *egg_file) const
Searches for a matching line in the .txa file for the given egg file and applies its specifications.
Definition: txaFile.cxx:131
Palettizer::finalize
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
Definition: palettizer.cxx:1045
EggFile::is_stale
bool is_stale() const
Returns true if the egg file needs to be updated, i.e.
Definition: eggFile.cxx:313