Panda3D

paletteGroup.cxx

00001 // Filename: paletteGroup.cxx
00002 // Created by:  drose (30Nov00)
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 "paletteGroup.h"
00016 #include "palettePage.h"
00017 #include "texturePlacement.h"
00018 #include "textureImage.h"
00019 #include "palettizer.h"
00020 #include "paletteImage.h"
00021 
00022 #include "indent.h"
00023 #include "datagram.h"
00024 #include "datagramIterator.h"
00025 #include "bamReader.h"
00026 #include "bamWriter.h"
00027 #include "indirectCompareNames.h"
00028 #include "pvector.h"
00029 
00030 TypeHandle PaletteGroup::_type_handle;
00031 
00032 ////////////////////////////////////////////////////////////////////
00033 //     Function: PaletteGroup::Constructor
00034 //       Access: Public
00035 //  Description:
00036 ////////////////////////////////////////////////////////////////////
00037 PaletteGroup::
00038 PaletteGroup() {
00039   _egg_count = 0;
00040   _dependency_level = 0;
00041   _dependency_order = 0;
00042   _dirname_order = 0;
00043   _has_margin_override = false;
00044   _margin_override = 0;
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: PaletteGroup::set_dirname
00049 //       Access: Public
00050 //  Description: Sets the directory name associated with the palette
00051 //               group.  This is an optional feature that can be used
00052 //               to place the maps for the different palette groups
00053 //               into different install directories.
00054 ////////////////////////////////////////////////////////////////////
00055 void PaletteGroup::
00056 set_dirname(const string &dirname) {
00057   _dirname = dirname;
00058 }
00059 
00060 ////////////////////////////////////////////////////////////////////
00061 //     Function: PaletteGroup::has_dirname
00062 //       Access: Public
00063 //  Description: Returns true if the directory name has been
00064 //               explicitly set for this group.  If it has not,
00065 //               get_dirname() returns an empty string.
00066 ////////////////////////////////////////////////////////////////////
00067 bool PaletteGroup::
00068 has_dirname() const {
00069   return !_dirname.empty();
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: PaletteGroup::get_dirname
00074 //       Access: Public
00075 //  Description: Returns the directory name associated with the
00076 //               palette group.  See set_dirname().
00077 ////////////////////////////////////////////////////////////////////
00078 const string &PaletteGroup::
00079 get_dirname() const {
00080   return _dirname;
00081 }
00082 
00083 ////////////////////////////////////////////////////////////////////
00084 //     Function: PaletteGroup::clear_depends
00085 //       Access: Public
00086 //  Description: Eliminates all the dependency information for this
00087 //               group.
00088 ////////////////////////////////////////////////////////////////////
00089 void PaletteGroup::
00090 clear_depends() {
00091   _dependent.clear();
00092   _dependency_level = 0;
00093   _dependency_order = 0;
00094   _dirname_order = 0;
00095 }
00096 
00097 ////////////////////////////////////////////////////////////////////
00098 //     Function: PaletteGroup::group_with
00099 //       Access: Public
00100 //  Description: Indicates a dependency of this group on some other
00101 //               group.  This means that the textures assigned to this
00102 //               group may be considered successfully assigned if they
00103 //               are actually placed in the other group.  In practice,
00104 //               this means that the textures associated with the
00105 //               other palette group will always be resident at
00106 //               runtime when textures from this palette group are
00107 //               required.
00108 ////////////////////////////////////////////////////////////////////
00109 void PaletteGroup::
00110 group_with(PaletteGroup *other) {
00111   _dependent.insert(other);
00112 }
00113 
00114 ////////////////////////////////////////////////////////////////////
00115 //     Function: PaletteGroup::get_groups
00116 //       Access: Public
00117 //  Description: Returns the set of groups this group depends on.
00118 ////////////////////////////////////////////////////////////////////
00119 const PaletteGroups &PaletteGroup::
00120 get_groups() const {
00121   return _dependent;
00122 }
00123 
00124 ////////////////////////////////////////////////////////////////////
00125 //     Function: PaletteGroup::get_margin_override
00126 //       Access: Public
00127 //  Description: Returns the set of groups this group depends on.
00128 ////////////////////////////////////////////////////////////////////
00129 int PaletteGroup::
00130 get_margin_override() const {
00131   return _margin_override;
00132 }
00133 
00134 ////////////////////////////////////////////////////////////////////
00135 //     Function: PaletteGroup::get_margin_override
00136 //       Access: Public
00137 //  Description: Returns the set of groups this group depends on.
00138 ////////////////////////////////////////////////////////////////////
00139 void PaletteGroup::
00140 set_margin_override(const int override) {
00141   _margin_override = override;
00142   _has_margin_override = true;
00143 }
00144 
00145 ////////////////////////////////////////////////////////////////////
00146 //     Function: PaletteGroup::has_margin_override
00147 //       Access: Public
00148 //  Description: Returns the set of groups this group depends on.
00149 ////////////////////////////////////////////////////////////////////
00150 bool PaletteGroup::
00151 has_margin_override() const {
00152   return _has_margin_override;
00153 }
00154 
00155 ////////////////////////////////////////////////////////////////////
00156 //     Function: PaletteGroup::get_placements
00157 //       Access: Public
00158 //  Description: Adds the set of TexturePlacements associated with
00159 //               this group to the indicated vector.  The vector is
00160 //               not cleared before this operation; if the user wants
00161 //               to retrieve the set of placements particular to this
00162 //               group only, it is the user's responsibility to clear
00163 //               the vector first.
00164 ////////////////////////////////////////////////////////////////////
00165 void PaletteGroup::
00166 get_placements(pvector<TexturePlacement *> &placements) const {
00167   Placements::const_iterator pi;
00168   for (pi = _placements.begin(); pi != _placements.end(); ++pi) {
00169     placements.push_back(*pi);
00170   }
00171 }
00172 
00173 ////////////////////////////////////////////////////////////////////
00174 //     Function: PaletteGroup::get_complete_placements
00175 //       Access: Public
00176 //  Description: Adds the set of TexturePlacements associated with
00177 //               this group and all dependent groups to the indicated
00178 //               vector.  See get_placements().
00179 ////////////////////////////////////////////////////////////////////
00180 void PaletteGroup::
00181 get_complete_placements(pvector<TexturePlacement *> &placements) const {
00182   PaletteGroups complete;
00183   complete.make_complete(_dependent);
00184 
00185   PaletteGroups::iterator gi;
00186   for (gi = complete.begin(); gi != complete.end(); ++gi) {
00187     PaletteGroup *group = (*gi);
00188     group->get_placements(placements);
00189   }
00190 
00191   get_placements(placements);
00192 }
00193 
00194 ////////////////////////////////////////////////////////////////////
00195 //     Function: PaletteGroup::reset_dependency_level
00196 //       Access: Public
00197 //  Description: Unconditionally sets the dependency level and order
00198 //               of this group to zero, in preparation for a later
00199 //               call to set_dependency_level().  See
00200 //               set_dependency_level().
00201 ////////////////////////////////////////////////////////////////////
00202 void PaletteGroup::
00203 reset_dependency_level() {
00204   _dependency_level = 0;
00205   _dependency_order = 0;
00206   _dirname_order = 0;
00207 }
00208 
00209 ////////////////////////////////////////////////////////////////////
00210 //     Function: PaletteGroup::set_dependency_level
00211 //       Access: Public
00212 //  Description: Sets the dependency level of this group to the
00213 //               indicated level, provided that level is not lower
00214 //               than the level that was set previously.  Also
00215 //               cascades to all dependent groups.  See
00216 //               get_dependency_level().
00217 //
00218 //               This call recurses to correctly set the dependency
00219 //               level of all PaletteGroups in the hierarchy.
00220 ////////////////////////////////////////////////////////////////////
00221 void PaletteGroup::
00222 set_dependency_level(int level) {
00223   if (level > _dependency_level) {
00224     _dependency_level = level;
00225     PaletteGroups::iterator gi;
00226     for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) {
00227       PaletteGroup *group = (*gi);
00228       group->set_dependency_level(level + 1);
00229     }
00230   }
00231 }
00232 
00233 ////////////////////////////////////////////////////////////////////
00234 //     Function: PaletteGroup::set_dependency_order
00235 //       Access: Public
00236 //  Description: Updates the dependency order of this group.  This
00237 //               number is the inverse of the dependency level, and
00238 //               can be used to rank the groups in order so that all
00239 //               the groups that a given group depends on will appear
00240 //               first in the list.  See get_dependency_order().
00241 //
00242 //               This function returns true if anything was changed,
00243 //               false otherwise.
00244 ////////////////////////////////////////////////////////////////////
00245 bool PaletteGroup::
00246 set_dependency_order() {
00247   bool any_changed = false;
00248 
00249   PaletteGroups::iterator gi;
00250   for (gi = _dependent.begin(); gi != _dependent.end(); ++gi) {
00251     PaletteGroup *group = (*gi);
00252     if (group->set_dependency_order()) {
00253       any_changed = true;
00254     }
00255 
00256     if (_dependency_order <= group->get_dependency_order()) {
00257       _dependency_order = group->get_dependency_order() + 1;
00258       any_changed = true;
00259     }
00260 
00261     if (_dirname == group->get_dirname()) {
00262       // The dirname orders should be equal.
00263       if (_dirname_order < group->get_dirname_order()) {
00264         _dirname_order = group->get_dirname_order();
00265         any_changed = true;
00266       }
00267     } else {
00268       // The dirname orders should be different.
00269       if (_dirname_order <= group->get_dirname_order()) {
00270         _dirname_order = group->get_dirname_order() + 1;
00271         any_changed = true;
00272       }
00273     }
00274   }
00275 
00276   return any_changed;
00277 }
00278 
00279 ////////////////////////////////////////////////////////////////////
00280 //     Function: PaletteGroup::get_dependency_level
00281 //       Access: Public
00282 //  Description: Returns the dependency level of this group.  This is
00283 //               a measure of how specific the group is; the lower the
00284 //               dependency level, the more specific the group.
00285 //
00286 //               Groups depend on other groups in a hierarchical
00287 //               relationship.  In general, if group a depends on
00288 //               group b, then b->get_dependency_level() >
00289 //               a->get_dependency_level().
00290 //
00291 //               Thus, groups that lots of other groups depend on have
00292 //               a higher dependency level; groups that no one else
00293 //               depends on have a low dependency level.  This is
00294 //               important when deciding which groups are best suited
00295 //               for assigning a texture to; in general, the texture
00296 //               should be assigned to the most specific suitable
00297 //               group (i.e. the one with the lowest dependency
00298 //               level).
00299 ////////////////////////////////////////////////////////////////////
00300 int PaletteGroup::
00301 get_dependency_level() const {
00302   return _dependency_level;
00303 }
00304 
00305 ////////////////////////////////////////////////////////////////////
00306 //     Function: PaletteGroup::get_dependency_order
00307 //       Access: Public
00308 //  Description: Returns the dependency order of this group.  This is
00309 //               similar in principle to the dependency level, but it
00310 //               represents the inverse concept: if group a depends on
00311 //               group b, then a->get_dependency_order() >
00312 //               b->get_dependency_order().
00313 //
00314 //               This is not exactly the same thing as n -
00315 //               get_dependency_level().  In particular, this can be
00316 //               used to sort the groups into an ordering such that
00317 //               all the groups that group a depends on appear before
00318 //               group a in the list.
00319 ////////////////////////////////////////////////////////////////////
00320 int PaletteGroup::
00321 get_dependency_order() const {
00322   return _dependency_order;
00323 }
00324 
00325 ////////////////////////////////////////////////////////////////////
00326 //     Function: PaletteGroup::get_dirname_order
00327 //       Access: Public
00328 //  Description: Returns the dependency order of this group.  This is
00329 //               similar in principle to the dependency level, but it
00330 //               represents the inverse concept: if group a depends on
00331 //               group b, then a->get_dirname_order() >
00332 //               b->get_dirname_order().
00333 //
00334 //               This is not exactly the same thing as n -
00335 //               get_dependency_level().  In particular, this can be
00336 //               used to sort the groups into an ordering such that
00337 //               all the groups that group a depends on appear before
00338 //               group a in the list.
00339 ////////////////////////////////////////////////////////////////////
00340 int PaletteGroup::
00341 get_dirname_order() const {
00342   return _dirname_order;
00343 }
00344 
00345 ////////////////////////////////////////////////////////////////////
00346 //     Function: PaletteGroup::is_preferred_over
00347 //       Access: Public
00348 //  Description: Returns true if this group should be preferred for
00349 //               adding textures over the other group, if both are
00350 //               available.  In other words, this is a more specific
00351 //               group than the other one.
00352 ////////////////////////////////////////////////////////////////////
00353 bool PaletteGroup::
00354 is_preferred_over(const PaletteGroup &other) const {
00355   if (get_dirname_order() != other.get_dirname_order()) {
00356     return (get_dirname_order() > other.get_dirname_order());
00357 
00358   } else if (get_dependency_order() != other.get_dependency_order()) {
00359     return (get_dependency_order() > other.get_dependency_order());
00360 
00361   } else {
00362     return (get_egg_count() < other.get_egg_count());
00363   }
00364 }
00365 
00366 ////////////////////////////////////////////////////////////////////
00367 //     Function: PaletteGroup::increment_egg_count
00368 //       Access: Public
00369 //  Description: Increments by one the number of egg files that are
00370 //               known to reference this PaletteGroup.  This is
00371 //               designed to aid the heuristics in texture placing;
00372 //               it's useful to know how many different egg files are
00373 //               sharing a particular PaletteGroup.
00374 ////////////////////////////////////////////////////////////////////
00375 void PaletteGroup::
00376 increment_egg_count() {
00377   _egg_count++;
00378 }
00379 
00380 ////////////////////////////////////////////////////////////////////
00381 //     Function: PaletteGroup::get_egg_count
00382 //       Access: Public
00383 //  Description: Returns the number of egg files that share this
00384 //               PaletteGroup.
00385 ////////////////////////////////////////////////////////////////////
00386 int PaletteGroup::
00387 get_egg_count() const {
00388   return _egg_count;
00389 }
00390 
00391 ////////////////////////////////////////////////////////////////////
00392 //     Function: PaletteGroup::get_page
00393 //       Access: Public
00394 //  Description: Returns the page associated with the indicated
00395 //               properties.  If no page object has yet been created,
00396 //               creates one.
00397 ////////////////////////////////////////////////////////////////////
00398 PalettePage *PaletteGroup::
00399 get_page(const TextureProperties &properties) {
00400   Pages::iterator pi = _pages.find(properties);
00401   if (pi != _pages.end()) {
00402     return (*pi).second;
00403   }
00404 
00405   PalettePage *page = new PalettePage(this, properties);
00406   bool inserted = _pages.insert(Pages::value_type(properties, page)).second;
00407   nassertr(inserted, page);
00408   return page;
00409 }
00410 
00411 ////////////////////////////////////////////////////////////////////
00412 //     Function: PaletteGroup::prepare
00413 //       Access: Public
00414 //  Description: Marks the indicated Texture as ready for placing
00415 //               somewhere within this group, and returns a
00416 //               placeholder TexturePlacement object.  The texture is
00417 //               not placed immediately, but may be placed later when
00418 //               place_all() is called; at this time, the
00419 //               TexturePlacement fields will be filled in as
00420 //               appropriate.
00421 ////////////////////////////////////////////////////////////////////
00422 TexturePlacement *PaletteGroup::
00423 prepare(TextureImage *texture) {
00424   TexturePlacement *placement = new TexturePlacement(texture, this);
00425   _placements.insert(placement);
00426 
00427   // [gjeon] update swapTexture information
00428   TextureSwapInfo::iterator tsi = _textureSwapInfo.find(texture->get_name());
00429   if (tsi != _textureSwapInfo.end()) {
00430     vector_string swapTextures = (*tsi).second;
00431 
00432     vector_string::const_iterator wi;
00433     wi = swapTextures.begin();
00434     ++wi;
00435     ++wi;
00436 
00437     // [gjeon] since swapped texture usually didn't mapped to any egg file
00438     // we need to create soucreTextureImage by using original texture file's info
00439     const string originalTextureName = (*wi);
00440     TextureImage *originalTexture = pal->get_texture(originalTextureName);
00441     SourceTextureImage *source = originalTexture->get_preferred_source();
00442     const Filename originalTextureFilename = source->get_filename();
00443     const Filename originalTextureAlphaFilename = source->get_alpha_filename();
00444     int originalTextureAlphaFileChannel = source->get_alpha_file_channel();
00445 
00446     ++wi;
00447     while (wi != swapTextures.end()) {
00448       const string &swapTextureName = (*wi);
00449       TextureImage *swapTextureImage = pal->get_texture(swapTextureName);
00450       Filename swapTextureFilename = Filename(originalTextureFilename.get_dirname(), swapTextureName + "." + originalTextureFilename.get_extension());
00451       swapTextureImage->get_source(swapTextureFilename, originalTextureAlphaFilename, originalTextureAlphaFileChannel);
00452       placement->_textureSwaps.push_back(swapTextureImage);
00453       ++wi;
00454     }
00455   }  
00456 
00457   return placement;
00458 }
00459 
00460 ////////////////////////////////////////////////////////////////////
00461 //     Function: PaletteGroup::unplace
00462 //       Access: Public
00463 //  Description: Removes the texture from its position on a
00464 //               PaletteImage, if it has been so placed.
00465 ////////////////////////////////////////////////////////////////////
00466 void PaletteGroup::
00467 unplace(TexturePlacement *placement) {
00468   nassertv(placement->get_group() == this);
00469 
00470   Placements::iterator pi;
00471   pi = _placements.find(placement);
00472   if (pi != _placements.end()) {
00473     _placements.erase(pi);
00474 
00475     if (placement->is_placed()) {
00476       placement->get_page()->unplace(placement);
00477     }
00478   }
00479 }
00480 
00481 ////////////////////////////////////////////////////////////////////
00482 //     Function: PaletteGroup::place_all
00483 //       Access: Public
00484 //  Description: Once all the textures have been assigned to this
00485 //               group, try to place them all onto suitable
00486 //               PaletteImages.
00487 ////////////////////////////////////////////////////////////////////
00488 void PaletteGroup::
00489 place_all() {
00490   // First, go through our prepared textures and assign each unplaced
00491   // one to an appropriate page.
00492   Placements::iterator pli;
00493   for (pli = _placements.begin(); pli != _placements.end(); ++pli) {
00494     TexturePlacement *placement = (*pli);
00495       
00496     if (placement->get_omit_reason() == OR_working) {
00497       PalettePage *page = get_page(placement->get_properties());
00498       page->assign(placement);
00499     }
00500   }
00501 
00502   // Then, go through the pages and actually do the placing.
00503   Pages::iterator pai;
00504   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00505     PalettePage *page = (*pai).second;
00506     page->place_all();
00507   }
00508 }
00509 
00510 ////////////////////////////////////////////////////////////////////
00511 //     Function: PaletteGroup::update_unknown_textures
00512 //       Access: Public
00513 //  Description: Checks for new information on any textures within the
00514 //               group for which some of the saved information is
00515 //               incomplete.  This may be necessary before we can
00516 //               properly place all of the textures.
00517 ////////////////////////////////////////////////////////////////////
00518 void PaletteGroup::
00519 update_unknown_textures(const TxaFile &txa_file) {
00520   Placements::iterator pli;
00521   for (pli = _placements.begin(); pli != _placements.end(); ++pli) {
00522     TexturePlacement *placement = (*pli);
00523 
00524     if (!placement->is_size_known()) {
00525       // This texture's size isn't known; we have to determine its
00526       // size.
00527       TextureImage *texture = placement->get_texture();
00528       if (!texture->got_txa_file()) {
00529         // But first, we need to look up the texture in the .txa file.
00530         texture->pre_txa_file();
00531         txa_file.match_texture(texture);
00532         texture->post_txa_file();
00533       }
00534 
00535       placement->determine_size();
00536     }
00537   }
00538 }
00539 
00540 ////////////////////////////////////////////////////////////////////
00541 //     Function: PaletteGroup::write_image_info
00542 //       Access: Public
00543 //  Description: Writes a list of the PaletteImages associated with
00544 //               this group, and all of their textures, to the
00545 //               indicated output stream.
00546 ////////////////////////////////////////////////////////////////////
00547 void PaletteGroup::
00548 write_image_info(ostream &out, int indent_level) const {
00549   Pages::const_iterator pai;
00550   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00551     PalettePage *page = (*pai).second;
00552     page->write_image_info(out, indent_level);
00553   }
00554 
00555   // Write out all the unplaced textures, in alphabetical order by name.
00556   pvector<TexturePlacement *> placement_vector;
00557   placement_vector.reserve(_placements.size());
00558   Placements::const_iterator pli;
00559   for (pli = _placements.begin(); pli != _placements.end(); ++pli) {
00560     TexturePlacement *placement = (*pli);
00561     if (placement->get_omit_reason() != OR_none) {
00562       placement_vector.push_back(placement);
00563     }
00564   }
00565   sort(placement_vector.begin(), placement_vector.end(),
00566        IndirectCompareNames<TexturePlacement>());
00567 
00568   pvector<TexturePlacement *>::const_iterator pvi;
00569   for (pvi = placement_vector.begin(); 
00570        pvi != placement_vector.end();
00571        ++pvi) {
00572     TexturePlacement *placement = (*pvi);
00573 
00574     indent(out, indent_level)
00575       << placement->get_texture()->get_name()
00576       << " unplaced because ";
00577     switch (placement->get_omit_reason()) {
00578     case OR_coverage:
00579       out << "coverage (" << placement->get_uv_area() << ")";
00580       break;
00581       
00582     case OR_size:
00583       out << "size (" << placement->get_x_size() << " "
00584           << placement->get_y_size() << ")";
00585       break;
00586       
00587     default:
00588       out << placement->get_omit_reason();
00589     }
00590     out << "\n";
00591   }
00592 }
00593 
00594 ////////////////////////////////////////////////////////////////////
00595 //     Function: PaletteGroup::optimal_resize
00596 //       Access: Public
00597 //  Description: Attempts to resize each PalettteImage down to its
00598 //               smallest possible size.
00599 ////////////////////////////////////////////////////////////////////
00600 void PaletteGroup::
00601 optimal_resize() {
00602   Pages::iterator pai;
00603   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00604     PalettePage *page = (*pai).second;
00605     page->optimal_resize();
00606   }
00607 }
00608 
00609 ////////////////////////////////////////////////////////////////////
00610 //     Function: PaletteGroup::reset_images
00611 //       Access: Public
00612 //  Description: Throws away all of the current PaletteImages, so that
00613 //               new ones may be created (and the packing made more
00614 //               optimal).
00615 ////////////////////////////////////////////////////////////////////
00616 void PaletteGroup::
00617 reset_images() {
00618   Pages::iterator pai;
00619   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00620     PalettePage *page = (*pai).second;
00621     page->reset_images();
00622   }
00623 }
00624 
00625 ////////////////////////////////////////////////////////////////////
00626 //     Function: PaletteGroup::setup_shadow_images
00627 //       Access: Public
00628 //  Description: Ensures that each PaletteImage's _shadow_image has
00629 //               the correct filename and image types, based on what
00630 //               was supplied on the command line and in the .txa
00631 //               file.
00632 ////////////////////////////////////////////////////////////////////
00633 void PaletteGroup::
00634 setup_shadow_images() {
00635   Pages::iterator pai;
00636   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00637     PalettePage *page = (*pai).second;
00638     page->setup_shadow_images();
00639   }
00640 }
00641 
00642 ////////////////////////////////////////////////////////////////////
00643 //     Function: PaletteGroup::update_images
00644 //       Access: Public
00645 //  Description: Regenerates each PaletteImage on this group that needs
00646 //               it.
00647 ////////////////////////////////////////////////////////////////////
00648 void PaletteGroup::
00649 update_images(bool redo_all) {
00650   Pages::iterator pai;
00651   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00652     PalettePage *page = (*pai).second;
00653     page->update_images(redo_all);
00654   }
00655 }
00656 
00657 ////////////////////////////////////////////////////////////////////
00658 //     Function: PaletteGroup::register_with_read_factory
00659 //       Access: Public, Static
00660 //  Description: Registers the current object as something that can be
00661 //               read from a Bam file.
00662 ////////////////////////////////////////////////////////////////////
00663 void PaletteGroup::
00664 register_with_read_factory() {
00665   BamReader::get_factory()->
00666     register_factory(get_class_type(), make_PaletteGroup);
00667 }
00668 
00669 ////////////////////////////////////////////////////////////////////
00670 //     Function: PaletteGroup::write_datagram
00671 //       Access: Public, Virtual
00672 //  Description: Fills the indicated datagram up with a binary
00673 //               representation of the current object, in preparation
00674 //               for writing to a Bam file.
00675 ////////////////////////////////////////////////////////////////////
00676 void PaletteGroup::
00677 write_datagram(BamWriter *writer, Datagram &datagram) {
00678   TypedWritable::write_datagram(writer, datagram);
00679   datagram.add_string(get_name());
00680   datagram.add_string(_dirname);
00681   _dependent.write_datagram(writer, datagram);
00682 
00683   datagram.add_int32(_dependency_level);
00684   datagram.add_int32(_dependency_order);
00685   datagram.add_int32(_dirname_order);
00686 
00687   datagram.add_uint32(_placements.size());
00688   Placements::const_iterator pli;
00689   for (pli = _placements.begin(); pli != _placements.end(); ++pli) {
00690     writer->write_pointer(datagram, (*pli));
00691   }
00692 
00693   datagram.add_uint32(_pages.size());
00694   Pages::const_iterator pai;
00695   for (pai = _pages.begin(); pai != _pages.end(); ++pai) {
00696     writer->write_pointer(datagram, (*pai).second);
00697   }
00698   datagram.add_bool(_has_margin_override);
00699   datagram.add_int16(_margin_override);
00700 
00701 }
00702 
00703 ////////////////////////////////////////////////////////////////////
00704 //     Function: PaletteGroup::complete_pointers
00705 //       Access: Public, Virtual
00706 //  Description: Called after the object is otherwise completely read
00707 //               from a Bam file, this function's job is to store the
00708 //               pointers that were retrieved from the Bam file for
00709 //               each pointer object written.  The return value is the
00710 //               number of pointers processed from the list.
00711 ////////////////////////////////////////////////////////////////////
00712 int PaletteGroup::
00713 complete_pointers(TypedWritable **p_list, BamReader *manager) {
00714   int pi = TypedWritable::complete_pointers(p_list, manager);
00715 
00716   pi += _dependent.complete_pointers(p_list + pi, manager);
00717 
00718   int i;
00719   for (i = 0; i < _num_placements; i++) {
00720     TexturePlacement *placement;
00721     DCAST_INTO_R(placement, p_list[pi++], pi);
00722     bool inserted = _placements.insert(placement).second;
00723     nassertr(inserted, pi);
00724   }
00725 
00726   // We must store the list of pages in a temporary vector first.  We
00727   // can't put them directly into the map because the map requires
00728   // that all the pointers in the page's get_properties() member have
00729   // been filled in, which may not have happened yet.
00730   _load_pages.reserve(_num_pages);
00731   for (i = 0; i < _num_pages; i++) {
00732     PalettePage *page;
00733     DCAST_INTO_R(page, p_list[pi++], pi);
00734     _load_pages.push_back(page);
00735   }
00736 
00737   return pi;
00738 }
00739 
00740 ////////////////////////////////////////////////////////////////////
00741 //     Function: PaletteGroup::finalize
00742 //       Access: Public, Virtual
00743 //  Description: This method is called by the BamReader after all
00744 //               pointers everywhere in the world have been completely
00745 //               read in.  It's a hook at which the object can do
00746 //               whatever final setup it requires that depends on
00747 //               other pointers being valid.
00748 ////////////////////////////////////////////////////////////////////
00749 void PaletteGroup::
00750 finalize(BamReader *) {
00751   // Now we can copy the pages into the actual map.
00752   pvector<PalettePage *>::const_iterator pi;
00753   for (pi = _load_pages.begin(); pi != _load_pages.end(); ++pi) {
00754     PalettePage *page = (*pi);
00755     bool inserted = _pages.
00756       insert(Pages::value_type(page->get_properties(), page)).second;
00757     nassertv(inserted);
00758   }
00759 
00760   _load_pages.clear();
00761 }
00762 
00763 ////////////////////////////////////////////////////////////////////
00764 //     Function: PaletteGroup::make_PaletteGroup
00765 //       Access: Protected, Static
00766 //  Description: This method is called by the BamReader when an object
00767 //               of this type is encountered in a Bam file; it should
00768 //               allocate and return a new object with all the data
00769 //               read.
00770 ////////////////////////////////////////////////////////////////////
00771 TypedWritable *PaletteGroup::
00772 make_PaletteGroup(const FactoryParams &params) {
00773   PaletteGroup *me = new PaletteGroup;
00774   DatagramIterator scan;
00775   BamReader *manager;
00776 
00777   parse_params(params, scan, manager);
00778   me->fillin(scan, manager);
00779   manager->register_finalize(me);
00780   return me;
00781 }
00782 
00783 ////////////////////////////////////////////////////////////////////
00784 //     Function: PaletteGroup::fillin
00785 //       Access: Protected
00786 //  Description: Reads the binary data from the given datagram
00787 //               iterator, which was written by a previous call to
00788 //               write_datagram().
00789 ////////////////////////////////////////////////////////////////////
00790 void PaletteGroup::
00791 fillin(DatagramIterator &scan, BamReader *manager) {
00792   TypedWritable::fillin(scan, manager);
00793   set_name(scan.get_string());
00794   _dirname = scan.get_string();
00795   _dependent.fillin(scan, manager);
00796 
00797   _dependency_level = scan.get_int32();
00798   _dependency_order = scan.get_int32();
00799   _dirname_order = scan.get_int32();
00800 
00801   _num_placements = scan.get_uint32();
00802   manager->read_pointers(scan, _num_placements);
00803 
00804   _num_pages = scan.get_uint32();
00805   manager->read_pointers(scan, _num_pages);
00806 
00807   if(Palettizer::_read_pi_version >= 19) {    
00808     _has_margin_override = scan.get_bool();
00809     _margin_override = scan.get_int16();
00810   } 
00811 }
00812 
00813 ////////////////////////////////////////////////////////////////////
00814 //     Function: PaletteGroup::add_texture_swap_info
00815 //       Access: Public
00816 //  Description: Store textureswap information from textures.txa
00817 ////////////////////////////////////////////////////////////////////
00818 void PaletteGroup::
00819 add_texture_swap_info(const string sourceTextureName, const vector_string &swapTextures) {
00820   TextureSwapInfo::iterator tsi = _textureSwapInfo.find(sourceTextureName);
00821   if (tsi != _textureSwapInfo.end()) {
00822     _textureSwapInfo.erase(tsi);
00823   }
00824   _textureSwapInfo.insert(TextureSwapInfo::value_type(sourceTextureName, swapTextures));
00825 }
00826 
00827 ////////////////////////////////////////////////////////////////////
00828 //     Function: PaletteGroup::is_none_texture_swap
00829 //       Access: Public
00830 //  Description: Returns textureswap information is set or not,
00831 //               True if it's not set.
00832 ////////////////////////////////////////////////////////////////////
00833 bool PaletteGroup::
00834 is_none_texture_swap() const {
00835   return _textureSwapInfo.empty();
00836 }
 All Classes Functions Variables Enumerations