15 #include "paletteImage.h" 16 #include "palettePage.h" 17 #include "paletteGroup.h" 18 #include "texturePlacement.h" 19 #include "palettizer.h" 20 #include "textureImage.h" 21 #include "sourceTextureImage.h" 22 #include "filenameUnifier.h" 26 #include "datagramIterator.h" 27 #include "bamReader.h" 28 #include "bamWriter.h" 29 #include "string_utils.h" 41 PaletteImage::ClearedRegion::
54 PaletteImage::ClearedRegion::
67 PaletteImage::ClearedRegion::
68 ClearedRegion(
const PaletteImage::ClearedRegion ©) :
71 _x_size(copy._x_size),
81 void PaletteImage::ClearedRegion::
82 operator = (
const PaletteImage::ClearedRegion ©) {
85 _x_size = copy._x_size;
86 _y_size = copy._y_size;
94 void PaletteImage::ClearedRegion::
96 LRGBColorf rgb(pal->_background[0], pal->_background[1], pal->_background[2]);
97 float alpha = pal->_background[3];
99 for (
int y = _y; y < _y + _y_size; y++) {
100 for (
int x = _x; x < _x + _x_size; x++) {
105 for (
int y = _y; y < _y + _y_size; y++) {
106 for (
int x = _x; x < _x + _x_size; x++) {
119 void PaletteImage::ClearedRegion::
120 write_datagram(
Datagram &datagram)
const {
133 void PaletteImage::ClearedRegion::
174 _x_size = pal->_pal_x_size;
175 _y_size = pal->_pal_y_size;
189 PaletteImage(
PalettePage *page,
int index,
unsigned swapIndex) :
192 _swapped_image(swapIndex)
196 _x_size = pal->_pal_x_size;
197 _y_size = pal->_pal_y_size;
225 if (_placements.empty()) {
229 }
else if (_placements.size() == 1) {
232 return (_placements[0]->get_omit_reason() == OR_solitary);
253 Placements::const_iterator pi;
254 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
260 used_pixels += texture_pixels;
265 return (
double)used_pixels / (double)total_pixels;
282 int coverage_pixels = 0;
284 Placements::const_iterator pi;
285 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
297 coverage_pixels += placed_pixels - orig_pixels;
302 return (
double)coverage_pixels / (double)total_pixels;
320 _placements.push_back(placement);
323 TexturePlacement::TextureSwaps::iterator tsi;
324 for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
325 if ((tsi - placement->_textureSwaps.begin()) >= (
int)_swappedImages.size()) {
326 PaletteImage *swappedImage =
new PaletteImage(_page, _swappedImages.size(), tsi - placement->_textureSwaps.begin() + 1);
327 swappedImage->_masterPlacements = &_placements;
328 _swappedImages.push_back(swappedImage);
347 Placements::iterator pi;
348 pi = find(_placements.begin(), _placements.end(), placement);
349 while (pi != _placements.end()) {
350 _placements.erase(pi);
351 pi = find(_placements.begin(), _placements.end(), placement);
353 _cleared_regions.push_back(ClearedRegion(placement));
370 if (_placements.size() == 1) {
376 if (pal->_omit_solitary || placement->
get_omit_reason() == OR_solitary) {
386 Placements::const_iterator pi;
387 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
415 bool resized_any =
false;
419 nassertv(_x_size > 0 && _y_size > 0);
436 << _x_size <<
" " << _y_size <<
"\n";
439 SwappedImages::iterator si;
440 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
460 _cleared_regions.clear();
466 saved.swap(_placements);
469 int saved_x_size = _x_size;
470 int saved_y_size = _y_size;
478 Placements::iterator pi;
479 for (pi = saved.begin(); pi != saved.end(); ++pi) {
480 (*pi)->force_replace();
488 for (pi = saved.begin(); pi != saved.end() && packed; ++pi) {
496 _x_size = saved_x_size;
497 _y_size = saved_y_size;
500 remove.swap(_placements);
501 for (pi =
remove.begin(); pi !=
remove.end(); ++pi) {
502 (*pi)->force_replace();
505 bool all_packed =
true;
506 for (pi = saved.begin(); pi != saved.end(); ++pi) {
511 nassertr(all_packed,
false);
542 Placements::const_iterator pi;
543 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
559 Placements::const_iterator pi;
560 for (pi = copy_placements.begin(); pi != copy_placements.end(); ++pi) {
566 _cleared_regions.clear();
582 SwappedImages::iterator si;
583 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
599 if (
is_empty() && pal->_aggressively_clean_mapdir) {
616 _new_image || !
exists() ||
617 !_cleared_regions.empty();
619 Placements::iterator pi;
623 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
647 TexturePlacement::TextureSwaps::iterator tsi;
648 for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
674 get_swapped_images();
677 ClearedRegions::iterator ci;
678 for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
679 ClearedRegion ®ion = (*ci);
680 region.clear(_image);
683 SwappedImages::iterator si;
684 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
686 region.clear(swappedImage->_image);
689 _cleared_regions.clear();
692 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
698 SwappedImages::iterator si;
699 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
709 if (pal->_shadow_color_type != (
PNMFileType *)NULL) {
710 _shadow_image.
write(_image);
716 SwappedImages::iterator si;
717 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
719 swappedImage->
write(swappedImage->_image);
720 if (pal->_shadow_color_type != (
PNMFileType *)NULL) {
721 swappedImage->_shadow_image.
write(swappedImage->_image);
723 swappedImage->release_image();
739 Filename orig_alpha_filename = _alpha_filename;
742 if (setup_filename()) {
746 if (!orig_filename.empty() && orig_filename.
exists()) {
750 if (!orig_alpha_filename.empty() && orig_alpha_filename.
exists()) {
752 orig_alpha_filename.
unlink();
754 if (!orig_shadow_filename.empty() && orig_shadow_filename.
exists()) {
756 orig_shadow_filename.
unlink();
766 Placements::iterator pi;
767 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
791 _basename = string();
793 string::iterator si = pal->_generated_image_pattern.begin();
794 while (si != pal->_generated_image_pattern.end()) {
798 if (si != pal->_generated_image_pattern.end()) {
805 _basename += _page->
get_group()->get_name();
809 _basename += _page->get_name();
813 _basename += format_string(_index + 1);
829 if (_swapped_image > 0) {
830 _basename +=
"_swp_";
831 _basename += format_string(_swapped_image);
838 if (_basename.empty() || _basename[_basename.length() - 1] !=
'.') {
842 bool any_changed =
false;
864 find_hole(
int &x,
int &y,
int x_size,
int y_size)
const {
866 while (y + y_size <= _y_size) {
867 int next_y = _y_size;
870 while (x + x_size <= _x_size) {
883 nassertr(next_x > x,
false);
887 nassertr(next_y > y,
false);
907 find_overlap(
int x,
int y,
int x_size,
int y_size)
const {
908 Placements::const_iterator pi;
909 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
912 placement->
intersects(x, y, x_size, y_size)) {
933 if (pal->_shadow_color_type != (
PNMFileType *)NULL) {
946 nout <<
"Generating new " 950 _cleared_regions.clear();
953 _image.
fill(pal->_background[0], pal->_background[1], pal->_background[2]);
962 Placements::iterator pi;
963 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
975 get_swapped_image(
int index) {
981 if (pal->_shadow_color_type != (
PNMFileType *)NULL) {
994 nout <<
"Generating new " 998 _cleared_regions.clear();
1001 _image.
fill(pal->_background[0], pal->_background[1], pal->_background[2]);
1010 Placements::iterator pi;
1011 for (pi = _masterPlacements->begin(); pi != _masterPlacements->end(); ++pi) {
1013 if ((
int)placement->_textureSwaps.size() > index) {
1028 get_swapped_images() {
1029 SwappedImages::iterator si;
1030 for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
1032 swappedImage->get_swapped_image(si - _swappedImages.begin());
1056 if (pal->_shadow_color_type != (
PNMFileType *)NULL) {
1071 register_factory(get_class_type(), make_PaletteImage);
1085 datagram.
add_uint32(_cleared_regions.size());
1086 ClearedRegions::const_iterator ci;
1087 for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
1088 (*ci).write_datagram(datagram);
1092 Placements::const_iterator pi;
1093 for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
1125 _placements.reserve(_num_placements);
1126 for (i = 0; i < _num_placements; i++) {
1128 DCAST_INTO_R(placement, p_list[index], index);
1129 _placements.push_back(placement);
1134 DCAST_INTO_R(_page, p_list[index], index);
1155 parse_params(params, scan, manager);
1156 me->fillin(scan, manager);
1169 ImageFile::fillin(scan, manager);
1172 _cleared_regions.reserve(num_cleared_regions);
1173 for (
int i = 0; i < num_cleared_regions; i++) {
1174 _cleared_regions.push_back(ClearedRegion());
1175 _cleared_regions.back().fillin(scan);
bool write(const PNMImage &image) const
Writes out the image in the indicated PNMImage to the _filename and/or _alpha_filename.
bool is_filled() const
Returns true if the texture has been filled (i.e.
bool read(PNMImage &image) const
Reads in the image (or images, if the alpha_filename is separate) and stores it in the indicated PNMI...
int get_y_size() const
Returns the size in the Y dimension, in pixels, of the texture image as it must appear in the palette...
This is the base class for all three-component vectors and points.
void not_solitary()
Indicates that the texture, formerly indicated as solitary, is now no longer.
double count_utilization() const
Returns the fraction of the PaletteImage that is actually used by any textures.
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
bool get_bool()
Extracts a boolean value.
void add_string(const string &str)
Adds a variable-length string to the datagram.
The name of this class derives from the fact that we originally implemented it as a layer on top of t...
bool exists() const
Returns true if the file or files named by the image file exist, false otherwise. ...
bool is_empty() const
Returns true if there are no textures, or only one "solitary" texture, placed on the image...
This is the fundamental interface for extracting binary objects from a Bam file, as generated by a Ba...
int get_placed_x_size() const
Returns the size in the X dimension, in pixels, of the texture image as it has been placed within the...
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function's job is to store...
void alpha_fill(float alpha=0.0)
Sets the entire alpha channel to the given level.
bool set_filename(PaletteGroup *group, const string &basename)
Sets the filename, and if applicable, the alpha_filename, from the indicated basename.
double count_coverage() const
Returns the a weighted average of the fraction of coverage represented by all of the textures placed ...
int get_y_size() const
Returns the size of the image file in pixels in the Y direction.
PaletteImage * get_image() const
Returns the particular PaletteImage on which the texture has been placed.
Base class for objects that can be written to and read from Bam files.
This is the base class of a family of classes that represent particular image file types that PNMImag...
int get_placed_x() const
Returns the X pixel at which the texture has been placed within its PaletteImage. ...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
bool make_shadow_image(const string &basename)
Sets up the ImageFile as a "shadow image" of a particular PaletteImage.
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object, in preparation for writing to a Bam file.
PN_int32 get_int32()
Extracts a signed 32-bit integer.
This is a particular collection of textures, within a PaletteGroup, that all share the same TexturePr...
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
void place_at(PaletteImage *image, int x, int y)
Assigns the texture to a particular position within the indicated PaletteImage.
void omit_solitary()
Sets the omit reason (returned by get_omit()) to OR_solitary, indicating that the palettized version ...
string get_string()
Extracts a variable-length string.
int get_placed_y() const
Returns the Y pixel at which the texture has been placed within its PaletteImage. ...
SourceTextureImage * get_preferred_source()
Determines the preferred source image for examining size and reading pixels, etc. ...
This is our own Panda specialization on the default STL vector.
void write_placements(ostream &out, int indent_level=0) const
Writes a list of the textures that have been placed on this image to the indicated output stream...
PalettePage * get_page() const
Returns the particular PalettePage this image is associated with.
bool place(TexturePlacement *placement)
Attempts to place the indicated texture on the image.
virtual void write_datagram(BamWriter *writer, Datagram &datagram)
Fills the indicated datagram up with a binary representation of the current object, in preparation for writing to a Bam file.
void optimal_resize()
Attempts to resize the palette image to as small as it can go.
void force_replace()
Removes the texture from its particular PaletteImage, but does not remove it from the PaletteGroup...
void mark_unfilled()
Marks the texture as unfilled, so that it will need to be copied into the palette image again...
void add_bool(bool value)
Adds a boolean value to the datagram.
bool is_size_known() const
Returns true if the texture's size is known, false otherwise.
void check_solitary()
To be called after all textures have been placed on the image, this checks to see if there is only on...
static Filename make_user_filename(Filename filename)
Returns a new filename that's made relative to the current directory, suitable for reporting to the u...
The name of a file, such as a texture file or an Egg file.
int get_x_size() const
Returns the size of the image file in pixels in the X direction.
void reset_image()
Unpacks each texture that has been placed on this image, resetting the image to empty.
PaletteGroup * get_group() const
Returns the group this particular PalettePage belongs to.
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of 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...
An instance of this class is passed to the Factory when requesting it to do its business and construc...
This corresponds to a particular assignment of a TextureImage with a PaletteGroup, and specifically describes which PaletteImage (if any), and where on the PaletteImage, the TextureImage has been assigned to.
bool unlink() const
Permanently deletes the file associated with the filename, if possible.
This is a texture image reference as it appears in an egg file: the source image of the texture...
OmitReason get_omit_reason() const
Returns the reason the texture has been omitted from a palette image, or OR_none if it has not...
int compare_timestamps(const Filename &other, bool this_missing_is_old=true, bool other_missing_is_old=true) const
Returns a number less than zero if the file named by this object is older than the given file...
void unlink()
Deletes the image file or files.
void clear()
Frees all memory allocated for the image, and clears all its parameters (size, color, type, etc).
TextureImage * get_texture() const
Returns the texture that this placement represents.
void set_alpha(int x, int y, float a)
Sets the alpha component color only at the indicated pixel.
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
int get_x_size() const
Returns the size in the X dimension, in pixels, of the texture image as it must appear in the palette...
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
void setup_shadow_image()
Ensures the _shadow_image has the correct filename and image types, based on what was supplied on the...
bool is_texture_named() const
Returns true if this particular texture has been named by the user for procession this session...
void fill_swapped_image(PNMImage &image, int index)
Fills in the rectangle of the swapped palette image represented by the texture placement with the ima...
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
void unplace(TexturePlacement *placement)
Removes the texture from the image.
bool intersects(int x, int y, int x_size, int y_size)
Returns true if the particular position this texture has been assigned to overlaps the rectangle whos...
void add_int32(PN_int32 value)
Adds a signed 32-bit integer to the datagram.
A class to retrieve the individual data elements previously stored in a Datagram. ...
bool resize_image(int x_size, int y_size)
Attempts to resize the palette image, and repack all of the textures within the new size...
This represents a single source texture that is referenced by one or more egg files.
void update_image(bool redo_all)
If the palette has changed since it was last written out, updates the image and writes out a new one...
TypeHandle is the identifier used to differentiate C++ class types.
void fill(float red, float green, float blue)
Sets the entire image (except the alpha channel) to the given color.
const Filename & get_filename() const
Returns the primary filename of the image file.
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
void resize_swapped_image(int x_size, int y_size)
Attempts to resize the palette image, and repack all of the textures within the new size...
int get_placed_y_size() const
Returns the size in the Y dimension, in pixels, of the texture image as it has been placed within the...
void set_xel(int x, int y, const LRGBColorf &value)
Changes the RGB color at the indicated pixel.
void mark_eggs_stale()
Marks all the egg files that reference this placement stale.
void write_placed(ostream &out, int indent_level=0)
Writes the placement position information on a line by itself.
bool exists() const
Returns true if the filename exists on the disk, false otherwise.
bool update_filename()
Changes the image filename to match the current naming scheme, assuming something has changed since t...
void fill_image(PNMImage &image)
Fills in the rectangle of the palette image represented by the texture placement with the image pixel...
bool is_placed() const
Returns true if the texture has been placed on a palette image, false otherwise.
void write_pointer(Datagram &packet, const TypedWritable *dest)
The interface for writing a pointer to another object to a Bam file.
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
const TextureProperties & get_properties() const
Returns the texture grouping properties that all textures in this page share.