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 ¶ms) { 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 }