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 }
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
void setup_shadow_images()
Ensures that each PaletteImage's _shadow_image has the correct filename and image types,...
void report_statistics() const
Output a report of the palettization effectiveness, texture memory utilization, and so on.
Definition: palettizer.cxx:297
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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 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
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...
PaletteGroup * get_palette_group(const std::string &name)
Returns the PaletteGroup with the given name.
Definition: palettizer.cxx:793
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void post_txa_file()
Once the egg file has been matched against all of the matching lines the .txa file,...
Definition: eggFile.cxx:249
PaletteGroup * test_palette_group(const std::string &name) const
Returns the PaletteGroup with the given name.
Definition: palettizer.cxx:810
bool get_bool()
Extracts a boolean value.
void pre_txa_file()
Updates any internal state prior to reading the .txa file.
void scan_textures()
Scans the egg file for texture references and updates the _textures list appropriately.
Definition: eggFile.cxx:102
uint8_t get_uint8()
Extracts an unsigned 8-bit integer.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_float64(PN_float64 value)
Adds a 64-bit floating-point number to the datagram.
Definition: datagram.I:123
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
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
void place_all()
Once all the textures have been assigned to this group, try to place them all onto suitable PaletteIm...
TextureImage * get_texture(const std::string &name)
Returns the TextureImage with the given name.
Definition: palettizer.cxx:838
bool get_noabs() const
Returns the current setting of the noabs flag.
Definition: palettizer.cxx:143
bool is_newer_than(const Filename &reference_filename)
Returns true if the source image is newer than the indicated file, false otherwise.
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
Definition: bamReader.h:110
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
void clear_source_basic_properties()
Calls clear_basic_properties() on each source texture image used by this texture, to reset the proper...
This is the main engine behind egg-palettize.
Definition: palettizer.h:39
void write_scale_info(std::ostream &out, int indent_level=0)
Writes the information about the texture's size and placement.
get_suggested_extension
Returns a suitable filename extension (without a leading dot) to suggest for files of this type,...
Definition: pnmFileType.h:49
bool had_data() const
Returns true if the EggData for this EggFile has ever been loaded in this session.
Definition: eggFile.cxx:438
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
Base class for objects that can be written to and read from Bam files.
Definition: typedWritable.h:35
void process_all(bool force_texture_read, const Filename &state_filename)
Reprocesses all textures known.
Definition: palettizer.cxx:514
void determine_placement_size()
Calls determine_size() on each TexturePlacement for the texture, to ensure that each TexturePlacement...
This is the highest level of grouping for TextureImages.
Definition: paletteGroup.h:43
const Filename & get_source_filename() const
Returns the filename this egg file was read from.
Definition: eggFile.cxx:91
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 pre_txa_file()
Does some processing prior to scanning the .txa file.
Definition: eggFile.cxx:221
bool read_egg(bool noabs)
Reads in the egg file from its _source_filename.
Definition: eggFile.cxx:480
virtual void finalize(BamReader *manager)
Called by the BamReader to perform any final actions needed for setting up the object after all objec...
size_type size() const
Returns the number of elements in the set.
void report(std::ostream &out, int indent_level)
Reports the measured texture memory usage.
string downcase(const string &s)
Returns the input string with all uppercase letters converted to lowercase.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool remove_egg_file(const std::string &name)
Removes the named egg file from the database, if it exists.
Definition: palettizer.cxx:766
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:63
int32_t get_int32()
Extracts a signed 32-bit integer.
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
std::string get_string()
Extracts a variable-length string.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
static PNMFileTypeRegistry * get_global_ptr()
Returns a pointer to the global PNMFileTypeRegistry object.
void reset_dependency_level()
Unconditionally sets the dependency level and order of this group to zero, in preparation for a later...
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
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
This is our own Panda specialization on the default STL vector.
Definition: pvector.h:42
void choose_placements()
Once all the textures have been assigned to groups (but before they may actually be placed),...
Definition: eggFile.cxx:381
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
bool is_used() const
Returns true if this particular texture has been placed somewhere, anywhere, or false if it is not us...
void release_egg_data()
Releases the memory that was loaded by a previous call to read_egg().
Definition: eggFile.cxx:553
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
void add_bool(bool value)
Adds a boolean value to the datagram.
Definition: datagram.I:34
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...
void read_header()
Causes the header part of the image to be reread, usually to confirm that its image properties (size,...
bool write_egg()
Writes out the egg file to its _dest_filename.
Definition: eggFile.cxx:569
void report_pi() const
Output a verbose description of all the palettization information to standard output,...
Definition: palettizer.cxx:176
The name of a file, such as a texture file or an Egg file.
Definition: filename.h:39
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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().
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
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 read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:653
static Filename get_bam_filename(Filename filename)
Returns an absolute pathname based on the given relative pathname, presumably read from the bam file ...
bool has_data() const
Returns true if the EggData for this EggFile has been loaded, and not yet released.
Definition: eggFile.cxx:429
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
bool write_eggs()
Adjusts the egg files to reference the newly generated textures, and writes them out.
Definition: palettizer.cxx:714
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void add_string(const std::string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:219
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:36
void copy_unplaced(bool redo_all)
Copies the texture to whichever destination directories are appropriate for the groups in which it ha...
void add_placement(TexturePlacement *placement)
Adds the indicated TexturePlacement to the counter.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
This corresponds to a particular assignment of a TextureImage with a PaletteGroup,...
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
Definition: filename.cxx:2319
void generate_images(bool redo_all)
Actually generates the appropriate palette and unplaced texture images into the map directories.
Definition: palettizer.cxx:633
void update_images(bool redo_all)
Regenerates each PaletteImage on this group that needs it.
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
void assign_groups()
Assigns the texture to all of the PaletteGroups the various egg files that use it need.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
void set_noabs(bool noabs)
Changes the current setting of the noabs flag.
Definition: palettizer.cxx:158
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...
bool is_surprise() const
Returns true if this particular texture is a 'surprise', i.e.
bool is_surprise() const
Returns true if this particular egg file is a 'surprise', i.e.
Definition: eggFile.cxx:294
void set_dependency_level(int level)
Sets the dependency level of this group to the indicated level, provided that level is not lower than...
bool is_stale() const
Returns true if the egg file needs to be updated, i.e.
Definition: eggFile.cxx:313
void make_complete(const PaletteGroups &a)
Completes the set with the transitive closure of all dependencies: for each PaletteGroup already in t...
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...
This class is used to gather statistics on texture memory usage, etc.
void mark_texture_named()
Indicates that this particular texture has been named by the user for processing this session,...
void set_dirname(const std::string &dirname)
Sets the directory name associated with the palette group.
void reset_images()
Throws away all of the current PaletteImages, so that new ones may be created (and the packing made m...
PN_float64 get_float64()
Extracts a 64-bit floating-point number.
bool set_dependency_order()
Updates the dependency order of this group.
void get_placements(pvector< TexturePlacement * > &placements) const
Adds the set of TexturePlacements associated with this group to the indicated vector.
void add_int32(int32_t value)
Adds a signed 32-bit integer to the datagram.
Definition: datagram.I:67
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:177
const PNMImage & read_source_image()
Reads in the original image, if it has not already been read, and returns it.
A set of PaletteGroups.
Definition: paletteGroups.h:28
bool read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:610
bool has_dirname() const
Returns true if the directory name has been explicitly set for this group.
void get_complete_placements(pvector< TexturePlacement * > &placements) const
Adds the set of TexturePlacements associated with this group and all dependent groups to the indicate...
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
Definition: palettizer.cxx:913
bool is_preferred_over(const PaletteGroup &other) const
Returns true if this group should be preferred for adding textures over the other group,...
void add_uint8(uint8_t value)
Adds an unsigned 8-bit integer to the datagram.
Definition: datagram.I:50
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
A class to retrieve the individual data elements previously stored in a Datagram.
This represents a single source texture that is referenced by one or more egg files.
Definition: textureImage.h:46
void post_txa_file()
Once the .txa file has been read and the TextureImage matched against it, considers applying the requ...
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
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
Definition: palettizer.cxx:606
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:38
const PaletteGroups & get_groups() const
Returns the set of groups this group depends on.
void clear_depends()
Eliminates all the dependency information for this group.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
Definition: filename.cxx:1267
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
int get_dependency_order() const
Returns the dependency order of this group.
This represents a single egg file known to the palettizer.
Definition: eggFile.h:36
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
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
static void set_rel_dirname(const Filename &rel_dirname)
Sets the name of the directory that texture filenames will be written relative to,...
EggFile * get_egg_file(const std::string &name)
Returns the EggFile with the given name.
Definition: palettizer.cxx:749
void release_source_image()
Frees the memory that was allocated by a previous call to read_source_image().
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,...