Panda3D
palettePage.cxx
1 // Filename: palettePage.cxx
2 // Created by: drose (01Dec00)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "palettePage.h"
16 #include "texturePlacement.h"
17 #include "textureImage.h"
18 #include "paletteImage.h"
19 #include "paletteGroup.h"
20 
21 #include "indent.h"
22 #include "datagram.h"
23 #include "datagramIterator.h"
24 #include "bamReader.h"
25 #include "bamWriter.h"
26 
27 #include <algorithm>
28 
29 TypeHandle PalettePage::_type_handle;
30 
31 ////////////////////////////////////////////////////////////////////
32 // Function: PalettePage::Default Constructor
33 // Access: Private
34 // Description: The default constructor is only for the convenience
35 // of the Bam reader.
36 ////////////////////////////////////////////////////////////////////
37 PalettePage::
38 PalettePage() {
39  _group = (PaletteGroup *)NULL;
40 }
41 
42 ////////////////////////////////////////////////////////////////////
43 // Function: PalettePage::Constructor
44 // Access: Public
45 // Description:
46 ////////////////////////////////////////////////////////////////////
47 PalettePage::
48 PalettePage(PaletteGroup *group, const TextureProperties &properties) :
49  Namable(properties.get_string()),
50  _group(group),
51  _properties(properties)
52 {
53 }
54 
55 ////////////////////////////////////////////////////////////////////
56 // Function: PalettePage::get_group
57 // Access: Public
58 // Description: Returns the group this particular PalettePage belongs
59 // to.
60 ////////////////////////////////////////////////////////////////////
62 get_group() const {
63  return _group;
64 }
65 
66 ////////////////////////////////////////////////////////////////////
67 // Function: PalettePage::get_properties
68 // Access: Public
69 // Description: Returns the texture grouping properties that all
70 // textures in this page share.
71 ////////////////////////////////////////////////////////////////////
73 get_properties() const {
74  return _properties;
75 }
76 
77 ////////////////////////////////////////////////////////////////////
78 // Function: PalettePage::assign
79 // Access: Public
80 // Description: Adds the indicated texture to the list of textures to
81 // consider placing on the page.
82 ////////////////////////////////////////////////////////////////////
83 void PalettePage::
84 assign(TexturePlacement *placement) {
85  _assigned.push_back(placement);
86 }
87 
88 
89 ////////////////////////////////////////////////////////////////////
90 // Function: PalettePage::place_all
91 // Access: Public
92 // Description: Assigns all the textures to their final home in a
93 // PaletteImage somewhere.
94 ////////////////////////////////////////////////////////////////////
95 void PalettePage::
97  // Sort the textures to be placed in order from biggest to smallest,
98  // as an aid to optimal packing.
99  sort(_assigned.begin(), _assigned.end(), SortPlacementBySize());
100 
101  Assigned::const_iterator ai;
102  for (ai = _assigned.begin(); ai != _assigned.end(); ++ai) {
103  TexturePlacement *placement = (*ai);
104  place(placement);
105  }
106 
107  _assigned.clear();
108 
109  // Now, look for solitary images; these are left placed, but flagged
110  // with OR_solitary, so they won't go into egg references. There's
111  // no real point in referencing these.
112  Images::iterator ii;
113  for (ii = _images.begin(); ii != _images.end(); ++ii) {
114  PaletteImage *image = (*ii);
115  image->check_solitary();
116  }
117 }
118 
119 ////////////////////////////////////////////////////////////////////
120 // Function: PalettePage::place
121 // Access: Public
122 // Description: Assigns the particular TexturePlacement to a
123 // PaletteImage where it fits.
124 ////////////////////////////////////////////////////////////////////
125 void PalettePage::
126 place(TexturePlacement *placement) {
127  nassertv(placement->get_omit_reason() == OR_working);
128 
129  // First, try to place it in one of our existing PaletteImages.
130  Images::iterator ii;
131  for (ii = _images.begin(); ii != _images.end(); ++ii) {
132  PaletteImage *image = (*ii);
133  if (image->place(placement)) {
134  return;
135  }
136  }
137 
138  // No good? Then we need to create a new PaletteImage for it.
139  PaletteImage *image = new PaletteImage(this, _images.size());
140  _images.push_back(image);
141 
142  bool placed = image->place(placement);
143 
144  // This should have stuck.
145  nassertv(placed);
146 }
147 
148 
149 ////////////////////////////////////////////////////////////////////
150 // Function: PalettePage::unplace
151 // Access: Public
152 // Description: Removes the TexturePlacement from wherever it has
153 // been placed.
154 ////////////////////////////////////////////////////////////////////
155 void PalettePage::
157  nassertv(placement->is_placed() && placement->get_page() == this);
158  placement->get_image()->unplace(placement);
159 }
160 
161 ////////////////////////////////////////////////////////////////////
162 // Function: PalettePage::write_image_info
163 // Access: Public
164 // Description: Writes a list of the PaletteImages associated with
165 // this page, and all of their textures, to the
166 // indicated output stream.
167 ////////////////////////////////////////////////////////////////////
168 void PalettePage::
169 write_image_info(ostream &out, int indent_level) const {
170  Images::const_iterator ii;
171  for (ii = _images.begin(); ii != _images.end(); ++ii) {
172  PaletteImage *image = (*ii);
173  if (!image->is_empty()) {
174  indent(out, indent_level);
175  image->output_filename(out);
176  out << "\n";
177  image->write_placements(out, indent_level + 2);
178  }
179  }
180 }
181 
182 ////////////////////////////////////////////////////////////////////
183 // Function: PalettePage::optimal_resize
184 // Access: Public
185 // Description: Attempts to resize each PalettteImage down to its
186 // smallest possible size.
187 ////////////////////////////////////////////////////////////////////
188 void PalettePage::
190  Images::iterator ii;
191  for (ii = _images.begin(); ii != _images.end(); ++ii) {
192  PaletteImage *image = (*ii);
193  image->optimal_resize();
194  }
195 }
196 
197 ////////////////////////////////////////////////////////////////////
198 // Function: PalettePage::reset_images
199 // Access: Public
200 // Description: Throws away all of the current PaletteImages, so that
201 // new ones may be created (and the packing made more
202 // optimal).
203 ////////////////////////////////////////////////////////////////////
204 void PalettePage::
206  Images::iterator ii;
207  for (ii = _images.begin(); ii != _images.end(); ++ii) {
208  PaletteImage *image = (*ii);
209  image->reset_image();
210  delete image;
211  }
212 
213  _images.clear();
214 }
215 
216 ////////////////////////////////////////////////////////////////////
217 // Function: PalettePage::setup_shadow_images
218 // Access: Public
219 // Description: Ensures that each PaletteImage's _shadow_image has
220 // the correct filename and image types, based on what
221 // was supplied on the command line and in the .txa
222 // file.
223 ////////////////////////////////////////////////////////////////////
224 void PalettePage::
226  Images::iterator ii;
227  for (ii = _images.begin(); ii != _images.end(); ++ii) {
228  PaletteImage *image = (*ii);
229  image->setup_shadow_image();
230  }
231 }
232 
233 ////////////////////////////////////////////////////////////////////
234 // Function: PalettePage::update_images
235 // Access: Public
236 // Description: Regenerates each PaletteImage on this page that needs
237 // it.
238 ////////////////////////////////////////////////////////////////////
239 void PalettePage::
240 update_images(bool redo_all) {
241  Images::iterator ii;
242  for (ii = _images.begin(); ii != _images.end(); ++ii) {
243  PaletteImage *image = (*ii);
244  image->update_image(redo_all);
245  }
246 }
247 
248 ////////////////////////////////////////////////////////////////////
249 // Function: PalettePage::register_with_read_factory
250 // Access: Public, Static
251 // Description: Registers the current object as something that can be
252 // read from a Bam file.
253 ////////////////////////////////////////////////////////////////////
254 void PalettePage::
257  register_factory(get_class_type(), make_PalettePage);
258 }
259 
260 ////////////////////////////////////////////////////////////////////
261 // Function: PalettePage::write_datagram
262 // Access: Public, Virtual
263 // Description: Fills the indicated datagram up with a binary
264 // representation of the current object, in preparation
265 // for writing to a Bam file.
266 ////////////////////////////////////////////////////////////////////
267 void PalettePage::
268 write_datagram(BamWriter *writer, Datagram &datagram) {
269  TypedWritable::write_datagram(writer, datagram);
270  datagram.add_string(get_name());
271 
272  writer->write_pointer(datagram, _group);
273  _properties.write_datagram(writer, datagram);
274 
275  // We don't write out _assigned, since that's rebuilt each session.
276 
277  datagram.add_uint32(_images.size());
278  Images::const_iterator ii;
279  for (ii = _images.begin(); ii != _images.end(); ++ii) {
280  writer->write_pointer(datagram, *ii);
281  }
282 }
283 
284 ////////////////////////////////////////////////////////////////////
285 // Function: PalettePage::complete_pointers
286 // Access: Public, Virtual
287 // Description: Called after the object is otherwise completely read
288 // from a Bam file, this function's job is to store the
289 // pointers that were retrieved from the Bam file for
290 // each pointer object written. The return value is the
291 // number of pointers processed from the list.
292 ////////////////////////////////////////////////////////////////////
293 int PalettePage::
295  int pi = TypedWritable::complete_pointers(p_list, manager);
296 
297  if (p_list[pi] != (TypedWritable *)NULL) {
298  DCAST_INTO_R(_group, p_list[pi], pi);
299  }
300  pi++;
301 
302  pi += _properties.complete_pointers(p_list + pi, manager);
303 
304  int i;
305  _images.reserve(_num_images);
306  for (i = 0; i < _num_images; i++) {
307  PaletteImage *image;
308  DCAST_INTO_R(image, p_list[pi++], pi);
309  _images.push_back(image);
310  }
311 
312  return pi;
313 }
314 
315 ////////////////////////////////////////////////////////////////////
316 // Function: PalettePage::make_PalettePage
317 // Access: Protected
318 // Description: This method is called by the BamReader when an object
319 // of this type is encountered in a Bam file; it should
320 // allocate and return a new object with all the data
321 // read.
322 ////////////////////////////////////////////////////////////////////
323 TypedWritable* PalettePage::
324 make_PalettePage(const FactoryParams &params) {
325  PalettePage *me = new PalettePage;
326  DatagramIterator scan;
327  BamReader *manager;
328 
329  parse_params(params, scan, manager);
330  me->fillin(scan, manager);
331  return me;
332 }
333 
334 ////////////////////////////////////////////////////////////////////
335 // Function: PalettePage::fillin
336 // Access: Protected
337 // Description: Reads the binary data from the given datagram
338 // iterator, which was written by a previous call to
339 // write_datagram().
340 ////////////////////////////////////////////////////////////////////
341 void PalettePage::
342 fillin(DatagramIterator &scan, BamReader *manager) {
343  TypedWritable::fillin(scan, manager);
344  set_name(scan.get_string());
345 
346  manager->read_pointer(scan); // _group
347  _properties.fillin(scan, manager);
348 
349  _num_images = scan.get_uint32();
350  manager->read_pointers(scan, _num_images);
351 }
void add_string(const string &str)
Adds a variable-length string to the datagram.
Definition: datagram.I:351
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...
Definition: bamReader.h:122
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function&#39;s job is to store...
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.
Definition: typedWritable.h:37
This is the highest level of grouping for TextureImages.
Definition: paletteGroup.h:47
void output_filename(ostream &out) const
Writes the filename (or pair of filenames) to the indicated output stream.
Definition: imageFile.cxx:483
virtual int complete_pointers(TypedWritable **p_list, BamReader *manager)
Called after the object is otherwise completely read from a Bam file, this function&#39;s job is to store...
void place_all()
Assigns all the textures to their final home in a PaletteImage somewhere.
Definition: palettePage.cxx:96
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 setup_shadow_images()
Ensures that each PaletteImage&#39;s _shadow_image has the correct filename and image types...
This is the fundamental interface for writing binary objects to a Bam file, to be extracted later by ...
Definition: bamWriter.h:73
void place(TexturePlacement *placement)
Assigns the particular TexturePlacement to a PaletteImage where it fits.
This is a particular collection of textures, within a PaletteGroup, that all share the same TexturePr...
Definition: palettePage.h:37
PN_uint32 get_uint32()
Extracts an unsigned 32-bit integer.
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&#39;s make_from_bam() method to read in all...
virtual void write_datagram(BamWriter *manager, Datagram &dg)
Writes the contents of this object to the datagram for shipping out to a Bam file.
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...
bool place(TexturePlacement *placement)
Attempts to place the indicated texture on the image.
void unplace(TexturePlacement *placement)
Removes the TexturePlacement from wherever it has been placed.
void optimal_resize()
Attempts to resize the palette image to as small as it can go.
A base class for all things which can have a name.
Definition: namable.h:29
void check_solitary()
To be called after all textures have been placed on the image, this checks to see if there is only on...
void write_image_info(ostream &out, int indent_level=0) const
Writes a list of the PaletteImages associated with this page, and all of their textures, to the indicated output stream.
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()...
void update_images(bool redo_all)
Regenerates each PaletteImage on this page that needs it.
static void register_with_read_factory()
Registers the current object as something that can be read from a Bam file.
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.
Definition: palettePage.cxx:62
void read_pointers(DatagramIterator &scan, int count)
A convenience function to read a contiguous list of pointers.
Definition: bamReader.cxx:700
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 assign(TexturePlacement *placement)
Adds the indicated texture to the list of textures to consider placing on the page.
Definition: palettePage.cxx:84
An instance of this class is passed to the Factory when requesting it to do its business and construc...
Definition: factoryParams.h:40
PalettePage * get_page() const
Returns the particular PalettePage on which the texture has been placed.
void optimal_resize()
Attempts to resize each PalettteImage down to its smallest possible size.
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.
OmitReason get_omit_reason() const
Returns the reason the texture has been omitted from a palette image, or OR_none if it has not...
void fillin(DatagramIterator &scan, BamReader *manager)
Reads the binary data from the given datagram iterator, which was written by a previous call to write...
static WritableFactory * get_factory()
Returns the global WritableFactory for generating TypedWritable objects.
Definition: bamReader.I:213
void reset_images()
Throws away all of the current PaletteImages, so that new ones may be created (and the packing made m...
void add_uint32(PN_uint32 value)
Adds an unsigned 32-bit integer to the datagram.
Definition: datagram.I:192
void setup_shadow_image()
Ensures the _shadow_image has the correct filename and image types, based on what was supplied on the...
This is a single palette image, one of several within a PalettePage, which is in turn one of several ...
Definition: paletteImage.h:36
void unplace(TexturePlacement *placement)
Removes the texture from the image.
A class to retrieve the individual data elements previously stored in a Datagram. ...
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.
Definition: typeHandle.h:85
An ordered list of data elements, formatted in memory for transmission over a socket or writing to a ...
Definition: datagram.h:43
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.
Definition: bamWriter.cxx:279
void read_pointer(DatagramIterator &scan)
The interface for reading a pointer to another object from a Bam file.
Definition: bamReader.cxx:658
const TextureProperties & get_properties() const
Returns the texture grouping properties that all textures in this page share.
Definition: palettePage.cxx:73
This is the set of characteristics of a texture that, if different from another texture, prevent the two textures from sharing a PaletteImage.