00001 // Filename: palettePage.cxx 00002 // Created by: drose (01Dec00) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "palettePage.h" 00016 #include "texturePlacement.h" 00017 #include "textureImage.h" 00018 #include "paletteImage.h" 00019 #include "paletteGroup.h" 00020 00021 #include "indent.h" 00022 #include "datagram.h" 00023 #include "datagramIterator.h" 00024 #include "bamReader.h" 00025 #include "bamWriter.h" 00026 00027 #include <algorithm> 00028 00029 TypeHandle PalettePage::_type_handle; 00030 00031 //////////////////////////////////////////////////////////////////// 00032 // Function: PalettePage::Default Constructor 00033 // Access: Private 00034 // Description: The default constructor is only for the convenience 00035 // of the Bam reader. 00036 //////////////////////////////////////////////////////////////////// 00037 PalettePage:: 00038 PalettePage() { 00039 _group = (PaletteGroup *)NULL; 00040 } 00041 00042 //////////////////////////////////////////////////////////////////// 00043 // Function: PalettePage::Constructor 00044 // Access: Public 00045 // Description: 00046 //////////////////////////////////////////////////////////////////// 00047 PalettePage:: 00048 PalettePage(PaletteGroup *group, const TextureProperties &properties) : 00049 Namable(properties.get_string()), 00050 _group(group), 00051 _properties(properties) 00052 { 00053 } 00054 00055 //////////////////////////////////////////////////////////////////// 00056 // Function: PalettePage::get_group 00057 // Access: Public 00058 // Description: Returns the group this particular PalettePage belongs 00059 // to. 00060 //////////////////////////////////////////////////////////////////// 00061 PaletteGroup *PalettePage:: 00062 get_group() const { 00063 return _group; 00064 } 00065 00066 //////////////////////////////////////////////////////////////////// 00067 // Function: PalettePage::get_properties 00068 // Access: Public 00069 // Description: Returns the texture grouping properties that all 00070 // textures in this page share. 00071 //////////////////////////////////////////////////////////////////// 00072 const TextureProperties &PalettePage:: 00073 get_properties() const { 00074 return _properties; 00075 } 00076 00077 //////////////////////////////////////////////////////////////////// 00078 // Function: PalettePage::assign 00079 // Access: Public 00080 // Description: Adds the indicated texture to the list of textures to 00081 // consider placing on the page. 00082 //////////////////////////////////////////////////////////////////// 00083 void PalettePage:: 00084 assign(TexturePlacement *placement) { 00085 _assigned.push_back(placement); 00086 } 00087 00088 00089 //////////////////////////////////////////////////////////////////// 00090 // Function: PalettePage::place_all 00091 // Access: Public 00092 // Description: Assigns all the textures to their final home in a 00093 // PaletteImage somewhere. 00094 //////////////////////////////////////////////////////////////////// 00095 void PalettePage:: 00096 place_all() { 00097 // Sort the textures to be placed in order from biggest to smallest, 00098 // as an aid to optimal packing. 00099 sort(_assigned.begin(), _assigned.end(), SortPlacementBySize()); 00100 00101 Assigned::const_iterator ai; 00102 for (ai = _assigned.begin(); ai != _assigned.end(); ++ai) { 00103 TexturePlacement *placement = (*ai); 00104 place(placement); 00105 } 00106 00107 _assigned.clear(); 00108 00109 // Now, look for solitary images; these are left placed, but flagged 00110 // with OR_solitary, so they won't go into egg references. There's 00111 // no real point in referencing these. 00112 Images::iterator ii; 00113 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00114 PaletteImage *image = (*ii); 00115 image->check_solitary(); 00116 } 00117 } 00118 00119 //////////////////////////////////////////////////////////////////// 00120 // Function: PalettePage::place 00121 // Access: Public 00122 // Description: Assigns the particular TexturePlacement to a 00123 // PaletteImage where it fits. 00124 //////////////////////////////////////////////////////////////////// 00125 void PalettePage:: 00126 place(TexturePlacement *placement) { 00127 nassertv(placement->get_omit_reason() == OR_working); 00128 00129 // First, try to place it in one of our existing PaletteImages. 00130 Images::iterator ii; 00131 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00132 PaletteImage *image = (*ii); 00133 if (image->place(placement)) { 00134 return; 00135 } 00136 } 00137 00138 // No good? Then we need to create a new PaletteImage for it. 00139 PaletteImage *image = new PaletteImage(this, _images.size()); 00140 _images.push_back(image); 00141 00142 bool placed = image->place(placement); 00143 00144 // This should have stuck. 00145 nassertv(placed); 00146 } 00147 00148 00149 //////////////////////////////////////////////////////////////////// 00150 // Function: PalettePage::unplace 00151 // Access: Public 00152 // Description: Removes the TexturePlacement from wherever it has 00153 // been placed. 00154 //////////////////////////////////////////////////////////////////// 00155 void PalettePage:: 00156 unplace(TexturePlacement *placement) { 00157 nassertv(placement->is_placed() && placement->get_page() == this); 00158 placement->get_image()->unplace(placement); 00159 } 00160 00161 //////////////////////////////////////////////////////////////////// 00162 // Function: PalettePage::write_image_info 00163 // Access: Public 00164 // Description: Writes a list of the PaletteImages associated with 00165 // this page, and all of their textures, to the 00166 // indicated output stream. 00167 //////////////////////////////////////////////////////////////////// 00168 void PalettePage:: 00169 write_image_info(ostream &out, int indent_level) const { 00170 Images::const_iterator ii; 00171 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00172 PaletteImage *image = (*ii); 00173 if (!image->is_empty()) { 00174 indent(out, indent_level); 00175 image->output_filename(out); 00176 out << "\n"; 00177 image->write_placements(out, indent_level + 2); 00178 } 00179 } 00180 } 00181 00182 //////////////////////////////////////////////////////////////////// 00183 // Function: PalettePage::optimal_resize 00184 // Access: Public 00185 // Description: Attempts to resize each PalettteImage down to its 00186 // smallest possible size. 00187 //////////////////////////////////////////////////////////////////// 00188 void PalettePage:: 00189 optimal_resize() { 00190 Images::iterator ii; 00191 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00192 PaletteImage *image = (*ii); 00193 image->optimal_resize(); 00194 } 00195 } 00196 00197 //////////////////////////////////////////////////////////////////// 00198 // Function: PalettePage::reset_images 00199 // Access: Public 00200 // Description: Throws away all of the current PaletteImages, so that 00201 // new ones may be created (and the packing made more 00202 // optimal). 00203 //////////////////////////////////////////////////////////////////// 00204 void PalettePage:: 00205 reset_images() { 00206 Images::iterator ii; 00207 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00208 PaletteImage *image = (*ii); 00209 image->reset_image(); 00210 delete image; 00211 } 00212 00213 _images.clear(); 00214 } 00215 00216 //////////////////////////////////////////////////////////////////// 00217 // Function: PalettePage::setup_shadow_images 00218 // Access: Public 00219 // Description: Ensures that each PaletteImage's _shadow_image has 00220 // the correct filename and image types, based on what 00221 // was supplied on the command line and in the .txa 00222 // file. 00223 //////////////////////////////////////////////////////////////////// 00224 void PalettePage:: 00225 setup_shadow_images() { 00226 Images::iterator ii; 00227 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00228 PaletteImage *image = (*ii); 00229 image->setup_shadow_image(); 00230 } 00231 } 00232 00233 //////////////////////////////////////////////////////////////////// 00234 // Function: PalettePage::update_images 00235 // Access: Public 00236 // Description: Regenerates each PaletteImage on this page that needs 00237 // it. 00238 //////////////////////////////////////////////////////////////////// 00239 void PalettePage:: 00240 update_images(bool redo_all) { 00241 Images::iterator ii; 00242 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00243 PaletteImage *image = (*ii); 00244 image->update_image(redo_all); 00245 } 00246 } 00247 00248 //////////////////////////////////////////////////////////////////// 00249 // Function: PalettePage::register_with_read_factory 00250 // Access: Public, Static 00251 // Description: Registers the current object as something that can be 00252 // read from a Bam file. 00253 //////////////////////////////////////////////////////////////////// 00254 void PalettePage:: 00255 register_with_read_factory() { 00256 BamReader::get_factory()-> 00257 register_factory(get_class_type(), make_PalettePage); 00258 } 00259 00260 //////////////////////////////////////////////////////////////////// 00261 // Function: PalettePage::write_datagram 00262 // Access: Public, Virtual 00263 // Description: Fills the indicated datagram up with a binary 00264 // representation of the current object, in preparation 00265 // for writing to a Bam file. 00266 //////////////////////////////////////////////////////////////////// 00267 void PalettePage:: 00268 write_datagram(BamWriter *writer, Datagram &datagram) { 00269 TypedWritable::write_datagram(writer, datagram); 00270 datagram.add_string(get_name()); 00271 00272 writer->write_pointer(datagram, _group); 00273 _properties.write_datagram(writer, datagram); 00274 00275 // We don't write out _assigned, since that's rebuilt each session. 00276 00277 datagram.add_uint32(_images.size()); 00278 Images::const_iterator ii; 00279 for (ii = _images.begin(); ii != _images.end(); ++ii) { 00280 writer->write_pointer(datagram, *ii); 00281 } 00282 } 00283 00284 //////////////////////////////////////////////////////////////////// 00285 // Function: PalettePage::complete_pointers 00286 // Access: Public, Virtual 00287 // Description: Called after the object is otherwise completely read 00288 // from a Bam file, this function's job is to store the 00289 // pointers that were retrieved from the Bam file for 00290 // each pointer object written. The return value is the 00291 // number of pointers processed from the list. 00292 //////////////////////////////////////////////////////////////////// 00293 int PalettePage:: 00294 complete_pointers(TypedWritable **p_list, BamReader *manager) { 00295 int pi = TypedWritable::complete_pointers(p_list, manager); 00296 00297 if (p_list[pi] != (TypedWritable *)NULL) { 00298 DCAST_INTO_R(_group, p_list[pi], pi); 00299 } 00300 pi++; 00301 00302 pi += _properties.complete_pointers(p_list + pi, manager); 00303 00304 int i; 00305 _images.reserve(_num_images); 00306 for (i = 0; i < _num_images; i++) { 00307 PaletteImage *image; 00308 DCAST_INTO_R(image, p_list[pi++], pi); 00309 _images.push_back(image); 00310 } 00311 00312 return pi; 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: PalettePage::make_PalettePage 00317 // Access: Protected 00318 // Description: This method is called by the BamReader when an object 00319 // of this type is encountered in a Bam file; it should 00320 // allocate and return a new object with all the data 00321 // read. 00322 //////////////////////////////////////////////////////////////////// 00323 TypedWritable* PalettePage:: 00324 make_PalettePage(const FactoryParams ¶ms) { 00325 PalettePage *me = new PalettePage; 00326 DatagramIterator scan; 00327 BamReader *manager; 00328 00329 parse_params(params, scan, manager); 00330 me->fillin(scan, manager); 00331 return me; 00332 } 00333 00334 //////////////////////////////////////////////////////////////////// 00335 // Function: PalettePage::fillin 00336 // Access: Protected 00337 // Description: Reads the binary data from the given datagram 00338 // iterator, which was written by a previous call to 00339 // write_datagram(). 00340 //////////////////////////////////////////////////////////////////// 00341 void PalettePage:: 00342 fillin(DatagramIterator &scan, BamReader *manager) { 00343 TypedWritable::fillin(scan, manager); 00344 set_name(scan.get_string()); 00345 00346 manager->read_pointer(scan); // _group 00347 _properties.fillin(scan, manager); 00348 00349 _num_images = scan.get_uint32(); 00350 manager->read_pointers(scan, _num_images); 00351 }