From a2d31d523cd8dc13139cc906d739d47fbb99dc11 Mon Sep 17 00:00:00 2001 From: David Rose Date: Sat, 24 Feb 2001 04:12:27 +0000 Subject: [PATCH] *** empty log message *** --- panda/src/egg2sg/characterMaker.cxx | 5 +- panda/src/putil/Sources.pp | 7 +- panda/src/putil/indirectCompareNames.I | 16 + panda/src/putil/indirectCompareNames.h | 29 + panda/src/putil/indirectCompareTo.I | 1 + pandatool/src/egg-palettize-old/Sources.pp | 22 - .../src/egg-palettize-old/attribFile.cxx | 1634 ----------------- pandatool/src/egg-palettize-old/attribFile.h | 167 -- .../config_egg_palettize.cxx | 14 - .../src/egg-palettize-old/eggPalettize.cxx | 737 -------- .../src/egg-palettize-old/eggPalettize.h | 82 - pandatool/src/egg-palettize-old/pTexture.cxx | 436 ----- pandatool/src/egg-palettize-old/pTexture.h | 111 -- pandatool/src/egg-palettize-old/palette.cxx | 591 ------ pandatool/src/egg-palettize-old/palette.h | 100 - .../src/egg-palettize-old/paletteGroup.cxx | 316 ---- .../src/egg-palettize-old/paletteGroup.h | 87 - pandatool/src/egg-palettize-old/sourceEgg.cxx | 496 ----- pandatool/src/egg-palettize-old/sourceEgg.h | 79 - .../src/egg-palettize-old/string_utils.cxx | 80 - .../src/egg-palettize-old/string_utils.h | 21 - .../src/egg-palettize-old/textureEggRef.cxx | 69 - .../src/egg-palettize-old/textureEggRef.h | 43 - .../src/egg-palettize-old/textureOmitReason.h | 26 - .../src/egg-palettize-old/texturePacking.cxx | 614 ------- .../src/egg-palettize-old/texturePacking.h | 90 - .../src/egg-palettize-old/userAttribLine.cxx | 504 ----- .../src/egg-palettize-old/userAttribLine.h | 91 - pandatool/src/eggbase/Sources.pp | 19 +- pandatool/src/eggbase/eggCharacterData.I | 27 + pandatool/src/eggbase/eggCharacterData.cxx | 452 +++++ pandatool/src/eggbase/eggCharacterData.h | 82 + pandatool/src/eggbase/eggCharacterFilter.cxx | 75 + pandatool/src/eggbase/eggCharacterFilter.h | 41 + pandatool/src/eggbase/eggJointData.I | 26 + pandatool/src/eggbase/eggJointData.cxx | 93 + pandatool/src/eggbase/eggJointData.h | 63 + pandatool/src/eggbase/eggMultiBase.cxx | 6 +- pandatool/src/eggbase/eggMultiBase.h | 7 +- pandatool/src/eggbase/eggMultiFilter.cxx | 2 +- pandatool/src/eggprogs/Sources.pp | 8 + pandatool/src/eggprogs/eggTopstrip.cxx | 40 + pandatool/src/eggprogs/eggTopstrip.h | 29 + 43 files changed, 1009 insertions(+), 6429 deletions(-) create mode 100644 panda/src/putil/indirectCompareNames.I create mode 100644 panda/src/putil/indirectCompareNames.h delete mode 100644 pandatool/src/egg-palettize-old/Sources.pp delete mode 100644 pandatool/src/egg-palettize-old/attribFile.cxx delete mode 100644 pandatool/src/egg-palettize-old/attribFile.h delete mode 100644 pandatool/src/egg-palettize-old/config_egg_palettize.cxx delete mode 100644 pandatool/src/egg-palettize-old/eggPalettize.cxx delete mode 100644 pandatool/src/egg-palettize-old/eggPalettize.h delete mode 100644 pandatool/src/egg-palettize-old/pTexture.cxx delete mode 100644 pandatool/src/egg-palettize-old/pTexture.h delete mode 100644 pandatool/src/egg-palettize-old/palette.cxx delete mode 100644 pandatool/src/egg-palettize-old/palette.h delete mode 100644 pandatool/src/egg-palettize-old/paletteGroup.cxx delete mode 100644 pandatool/src/egg-palettize-old/paletteGroup.h delete mode 100644 pandatool/src/egg-palettize-old/sourceEgg.cxx delete mode 100644 pandatool/src/egg-palettize-old/sourceEgg.h delete mode 100644 pandatool/src/egg-palettize-old/string_utils.cxx delete mode 100644 pandatool/src/egg-palettize-old/string_utils.h delete mode 100644 pandatool/src/egg-palettize-old/textureEggRef.cxx delete mode 100644 pandatool/src/egg-palettize-old/textureEggRef.h delete mode 100644 pandatool/src/egg-palettize-old/textureOmitReason.h delete mode 100644 pandatool/src/egg-palettize-old/texturePacking.cxx delete mode 100644 pandatool/src/egg-palettize-old/texturePacking.h delete mode 100644 pandatool/src/egg-palettize-old/userAttribLine.cxx delete mode 100644 pandatool/src/egg-palettize-old/userAttribLine.h create mode 100644 pandatool/src/eggbase/eggCharacterData.I create mode 100644 pandatool/src/eggbase/eggCharacterData.cxx create mode 100644 pandatool/src/eggbase/eggCharacterData.h create mode 100644 pandatool/src/eggbase/eggCharacterFilter.cxx create mode 100644 pandatool/src/eggbase/eggCharacterFilter.h create mode 100644 pandatool/src/eggbase/eggJointData.I create mode 100644 pandatool/src/eggbase/eggJointData.cxx create mode 100644 pandatool/src/eggbase/eggJointData.h create mode 100644 pandatool/src/eggprogs/eggTopstrip.cxx create mode 100644 pandatool/src/eggprogs/eggTopstrip.h diff --git a/panda/src/egg2sg/characterMaker.cxx b/panda/src/egg2sg/characterMaker.cxx index 7728af80f2..01d1cadea2 100644 --- a/panda/src/egg2sg/characterMaker.cxx +++ b/panda/src/egg2sg/characterMaker.cxx @@ -166,10 +166,7 @@ build_joint_hierarchy(EggNode *egg_node, PartGroup *part) { matd = LMatrix4d::ident_mat(); } - LMatrix4f matf(matd(0,0), matd(0,1), matd(0,2), matd(0,3), - matd(1,0), matd(1,1), matd(1,2), matd(1,3), - matd(2,0), matd(2,1), matd(2,2), matd(2,3), - matd(3,0), matd(3,1), matd(3,2), matd(3,3)); + LMatrix4f matf = LCAST(float, matd); CharacterJoint *joint = new CharacterJoint(part, egg_group->get_name(), matf); diff --git a/panda/src/putil/Sources.pp b/panda/src/putil/Sources.pp index 3cf1d59d66..0f1a650605 100644 --- a/panda/src/putil/Sources.pp +++ b/panda/src/putil/Sources.pp @@ -19,7 +19,9 @@ factoryParams.cxx factoryParams.h \ globPattern.I globPattern.cxx \ globPattern.h globalPointerRegistry.I globalPointerRegistry.cxx \ - globalPointerRegistry.h ioPtaDatagramFloat.cxx ioPtaDatagramFloat.h \ + globalPointerRegistry.h indirectCompareNames.I \ + indirectCompareNames.h indirectCompareTo.I \ + indirectCompareTo.h ioPtaDatagramFloat.cxx ioPtaDatagramFloat.h \ ioPtaDatagramInt.cxx ioPtaDatagramInt.h ioPtaDatagramShort.cxx \ ioPtaDatagramShort.h keyboardButton.cxx keyboardButton.h \ lineStream.I lineStream.cxx lineStream.h lineStreamBuf.I \ @@ -51,7 +53,8 @@ factoryBase.I factoryBase.h factoryParam.I factoryParam.h \ factoryParams.I factoryParams.h \ globPattern.I globPattern.h \ - globalPointerRegistry.I globalPointerRegistry.h indirectCompareTo.I \ + globalPointerRegistry.I globalPointerRegistry.h \ + indirectCompareNames.I indirectCompareNames.h indirectCompareTo.I \ indirectCompareTo.h ioPtaDatagramFloat.h ioPtaDatagramInt.h \ ioPtaDatagramShort.h iterator_types.h keyboardButton.h lineStream.I \ lineStream.h lineStreamBuf.I lineStreamBuf.h modifierButtons.I \ diff --git a/panda/src/putil/indirectCompareNames.I b/panda/src/putil/indirectCompareNames.I new file mode 100644 index 0000000000..730741341e --- /dev/null +++ b/panda/src/putil/indirectCompareNames.I @@ -0,0 +1,16 @@ +// Filename: indirectCompareNames.I +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: IndirectCompareNames::operator () +// Access: Public +// Description: Returns true if a sorts before b, false otherwise. +//////////////////////////////////////////////////////////////////// +template +INLINE bool IndirectCompareNames:: +operator () (const ObjectType *a, const ObjectType *b) const { + return (a != b && a->get_name() < b->get_name()); +} diff --git a/panda/src/putil/indirectCompareNames.h b/panda/src/putil/indirectCompareNames.h new file mode 100644 index 0000000000..ac98adf0a0 --- /dev/null +++ b/panda/src/putil/indirectCompareNames.h @@ -0,0 +1,29 @@ +// Filename: indirectCompareNames.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef INDIRECTCOMPARENAMES_H +#define INDIRECTCOMPARENAMES_H + +#include + +//////////////////////////////////////////////////////////////////// +// Class : IndirectCompareNames +// Description : An STL function object class, this is intended to be +// used on any ordered collection of pointers to classes +// that define a get_name() method, particularly for +// things that derive from Namable. It defines the +// order of the pointers by case-sensitive name +// comparison. +//////////////////////////////////////////////////////////////////// +template +class IndirectCompareNames { +public: + INLINE bool operator () (const ObjectType *a, const ObjectType *b) const; +}; + +#include "indirectCompareNames.I" + +#endif + diff --git a/panda/src/putil/indirectCompareTo.I b/panda/src/putil/indirectCompareTo.I index 9b597df6da..40f8f2d236 100644 --- a/panda/src/putil/indirectCompareTo.I +++ b/panda/src/putil/indirectCompareTo.I @@ -3,6 +3,7 @@ // //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// // Function: IndirectCompareTo::operator () // Access: Public diff --git a/pandatool/src/egg-palettize-old/Sources.pp b/pandatool/src/egg-palettize-old/Sources.pp deleted file mode 100644 index 54a0035cf6..0000000000 --- a/pandatool/src/egg-palettize-old/Sources.pp +++ /dev/null @@ -1,22 +0,0 @@ -// #begin bin_target -// #define TARGET egg-palettize-new -// #define LOCAL_LIBS \ -// eggbase progbase -// #define OTHER_LIBS \ -// egg:c linmath:c putil:c express:c pnmimage:c pnmimagetypes:c \ -// pandaegg:m panda:m pandaexpress:m \ -// dtoolutil:c dconfig:c dtool:m pystub - -// #define SOURCES \ -// attribFile.cxx attribFile.h config_egg_palettize.cxx \ -// eggPalettize.cxx eggPalettize.h \ -// palette.cxx palette.h paletteGroup.cxx \ -// paletteGroup.h pTexture.cxx pTexture.h sourceEgg.cxx \ -// sourceEgg.h string_utils.cxx string_utils.h \ -// textureEggRef.cxx textureEggRef.h textureOmitReason.h \ -// texturePacking.cxx \ -// texturePacking.h userAttribLine.cxx userAttribLine.h - -// #define INSTALL_HEADERS - -// #end bin_target diff --git a/pandatool/src/egg-palettize-old/attribFile.cxx b/pandatool/src/egg-palettize-old/attribFile.cxx deleted file mode 100644 index cdbc9a0a43..0000000000 --- a/pandatool/src/egg-palettize-old/attribFile.cxx +++ /dev/null @@ -1,1634 +0,0 @@ -// Filename: attribFile.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "attribFile.h" -#include "userAttribLine.h" -#include "eggPalettize.h" -#include "string_utils.h" -#include "pTexture.h" -#include "texturePacking.h" -#include "paletteGroup.h" -#include "palette.h" -#include "sourceEgg.h" - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef WIN32_VC -#include -#include -#include -#endif - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -AttribFile:: -AttribFile(const Filename &filename) { - _name = filename.get_basename_wo_extension(); - _txa_filename = filename; - _txa_filename.set_extension("txa"); - _txa_filename.set_text(); - _pi_filename = filename; - _pi_filename.set_extension("pi"); - _pi_filename.set_text(); - _txa_fd = -1; - - - _pi_dir = _pi_filename; - _pi_dir.set_basename(""); - _pi_dir.make_canonical(); - - _default_group = (PaletteGroup *)NULL; - - _optimal = false; - _txa_needs_rewrite = false; - - _map_dirname = "%s"; - _pal_xsize = 512; - _pal_ysize = 512; - _default_margin = 2; - _force_power_2 = false; - _aggressively_clean_mapdir = false; - _color_type = (PNMFileType *)NULL; - _alpha_type = (PNMFileType *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_name -// Access: Public -// Description: Returns the name of the AttribFile. This is derived -// from, but is not equivalent to, the filename. -//////////////////////////////////////////////////////////////////// -string AttribFile:: -get_name() const { - return _name; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::open_and_lock -// Access: Public -// Description: Opens the .txa file and simultaneously locks it (if -// lock is true) for exclusive read/write access. -// Returns true if successful, false on failure. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -open_and_lock(bool lock) { - if (!_txa_filename.exists()) { - nout << "Attributes file " << _txa_filename << " does not exist.\n"; - } - -#ifdef WIN32_VC - if (lock) { - nout << "File locking unimplemented on Windows. Specify -nolock.\n"; - return false; - } - - /* - _txa_fd = _sopen(_txa_filename.c_str(), _O_RDWR | _O_CREAT, _SH_DENYRW, - _S_IREAD | _S_IWRITE); - - if (_txa_fd < 0) { - perror(_txa_filename.c_str()); - return false; - } - - _txa_fstrm.attach(_txa_fd); - */ - - if (!_txa_filename.open_read_write(_txa_fstrm)) { - cerr << "Unable to read " << _txa_filename << "\n"; - return false; - } - return true; - -#else - // Unix-style - _txa_fd = open(_txa_filename.c_str(), O_RDWR | O_CREAT, 0666); - - if (_txa_fd < 0) { - perror(_txa_filename.c_str()); - return false; - } - - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - - if (lock) { - if (fcntl(_txa_fd, F_SETLK, &fl) < 0) { - if (errno != EACCES) { - perror(_txa_filename.c_str()); - nout << "Unable to lock file; try running with -nolock.\n"; - return false; - } - - nout << "Waiting for lock on " << _txa_filename << "\n"; - while (fcntl(_txa_fd, F_SETLKW, &fl) < 0) { - if (errno != EINTR) { - perror(_txa_filename.c_str()); - return false; - } - } - } - } - - _txa_fstrm.attach(_txa_fd); -#endif - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::close_and_unlock -// Access: Public -// Description: Simultaneously closes the .txa file and releases the -// lock. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -close_and_unlock() { - // Closing the fstream will close the fd, and thus release all the - // file locks. - _txa_fstrm.close(); - _txa_fd = -1; - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::rewind_and_truncate -// Access: Public -// Description: Rewinds the .txa file to the beginning and truncates -// it in preparation for rewriting it, without releasing -// the lock. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -rewind_and_truncate() { -#ifdef WIN32_VC - // In Windows, since we're not implementing file locking right now, - // we might as well just close and reopen the file. Which is good - // since I don't know how to truncate an already-opened file in - // Windows. - _txa_fstrm.close(); - _txa_filename.unlink(); - _txa_filename.open_read_write(_txa_fstrm); -#else - // In Unix, we need to keep the file open so we don't lose the lock, - // so we just rewind and then explicitly truncate the file with a - // system call. - _txa_fstrm.clear(); - _txa_fstrm.seekp(0, ios::beg); - ftruncate(_txa_fd, 0); -#endif - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::read -// Access: Public -// Description: Reads the .txa and .pi files. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -read(bool force_redo_all) { - bool okflag = true; - - okflag = read_txa(_txa_fstrm); - - if (!_pi_filename.exists()) { - nout << "Palette information file " << _pi_filename << " does not exist.\n"; - } else { - ifstream infile; - if (!_pi_filename.open_read(infile)) { - nout << "Palette information file " << _pi_filename << " exists, but cannot be read.\n"; - return false; - } - - okflag = read_pi(infile, force_redo_all); - } - - return okflag; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::write -// Access: Public -// Description: Rewrites the .txa and .pi files, if necessary. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -write() { - bool okflag = true; - - if (_txa_needs_rewrite) { - rewind_and_truncate(); - okflag = write_txa(_txa_fstrm) && okflag; - _txa_fstrm << flush; - } - - { - ofstream outfile; - if (!_pi_filename.open_write(outfile)) { - nout << "Unable to write file " << _pi_filename << "\n"; - return false; - } - - okflag = write_pi(outfile) && okflag; - } - - return okflag; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::write_pi_filename -// Access: Public -// Description: Returns a new filename that's made relative to the -// .pi file itself, suitable for writing to the .pi file. -//////////////////////////////////////////////////////////////////// -Filename AttribFile:: -write_pi_filename(Filename filename) const { - filename.make_canonical(); - filename.make_relative_to(_pi_dir); - return filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::read_pi_filename -// Access: Public -// Description: Returns an absolute pathname based on the given -// relative pathname, presumably read from the .pi file -// and relative to the .pi file. -//////////////////////////////////////////////////////////////////// -Filename AttribFile:: -read_pi_filename(Filename filename) const { - if (!filename.empty()) { - filename.make_absolute(_pi_dir); - } - return filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::write_egg_filename -// Access: Public -// Description: Returns a new filename that's made relative to the -// rel_directory, suitable for writing out within egg -// files. -//////////////////////////////////////////////////////////////////// -Filename AttribFile:: -write_egg_filename(Filename filename) const { - filename.make_canonical(); - filename.make_relative_to(_rel_dirname); - return filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::update_params -// Access: Public -// Description: Reads the program parameters from the command line -// (if they were specified), overriding whatever was -// read from the .pi file. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -update_params(EggPalettize *prog) { - if (prog->_got_map_dirname) { - _map_dirname = prog->_map_dirname; - } - if (prog->_got_rel_dirname) { - _rel_dirname = prog->_rel_dirname; - } - if (prog->_got_palette_size) { - _pal_xsize = prog->_pal_size[0]; - _pal_ysize = prog->_pal_size[1]; - } - if (prog->_got_default_margin) { - _default_margin = prog->_default_margin; - } - if (prog->_got_force_power_2) { - _force_power_2 = prog->_force_power_2; - } - if (prog->_got_aggressively_clean_mapdir) { - _aggressively_clean_mapdir = prog->_aggressively_clean_mapdir; - } - if (prog->_got_image_type) { - _color_type = prog->_color_type; - _alpha_type = prog->_alpha_type; - } - - if (!_rel_dirname.empty()) { - _rel_dirname.make_canonical(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_group -// Access: Public -// Description: Returns a pointer to the PaletteGroup object with the -// given name. If there is not yet any such -// PaletteGroup, creates one. -//////////////////////////////////////////////////////////////////// -PaletteGroup *AttribFile:: -get_group(const string &group_name) { - Groups::iterator gi; - gi = _groups.find(group_name); - if (gi != _groups.end()) { - return (*gi).second; - } - - PaletteGroup *new_group = new PaletteGroup(group_name); - _groups[group_name] = new_group; - return new_group; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::set_default_group -// Access: Public -// Description: Sets the PaletteGroup that should be associated -// with any textures or egg files not explicitly placed -// in a different group. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -set_default_group(PaletteGroup *default_group) { - _default_group = default_group; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_default_group -// Access: Public -// Description: Returns the PaletteGroup that should be associated -// with any textures or egg files not explicitly placed -// in a different group. -//////////////////////////////////////////////////////////////////// -PaletteGroup *AttribFile:: -get_default_group() { - if (_default_group == (PaletteGroup *)NULL) { - _default_group = get_group(_name); - } - return _default_group; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_egg_group_requests -// Access: Public -// Description: Checks all of the known egg filenames against the egg -// files named in the .txa file, looking to see which -// egg files as assigned to which groups. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -get_egg_group_requests() { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - UserLines::const_iterator ui; - - bool matched = false; - for (ui = _user_lines.begin(); - ui != _user_lines.end() && !matched; - ++ui) { - matched = (*ui)->get_group_request(egg); - } - - if (matched) { - egg->set_matched_anything(true); - } - } - - // Now go back and make sure that all textures are assigned to - // *something*. - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - egg->all_textures_assigned(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_size_requests -// Access: Public -// Description: Determines the size/scaling requested for each -// texture by scanning the .txa file. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -get_size_requests() { - PTextures::iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - PTexture *tex = (*ti).second; - tex->clear_req(); - - int margin = _default_margin; - UserLines::const_iterator ui; - - bool matched = false; - for (ui = _user_lines.begin(); - ui != _user_lines.end() && !matched; - ++ui) { - matched = (*ui)->get_size_request(tex, margin); - } - - if (matched) { - tex->set_matched_anything(true); - } - } -} - - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::update_texture_flags -// Access: Public -// Description: Update the unused flags on all textures to accurately -// reflect those that are unused by any egg files. Omit -// unused textures from the palettizing set. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -update_texture_flags() { - // First, clear all the flags. - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - TexturePacking *packing = (*pi); - packing->set_unused(true); - packing->set_uses_alpha(false); - } - - // Then, for each egg file, mark all the textures it's known to be - // using, and update the repeat and alpha flags. - Eggs::const_iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - egg->mark_texture_flags(); - } - - // Now go back through and omit any unused textures. This is also a - // fine time to mark the textures' original packing state, so we can - // check later to see if they've been repacked elsewhere. - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - TexturePacking *packing = (*pi); - packing->record_orig_state(); - - if (packing->unused()) { - packing->set_omit(OR_unused); - } - } -} - - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::repack_all_textures -// Access: Public -// Description: Clear out all the old packing order and start again -// from the top. This should get as nearly optimal a -// packing as this poor little algorithm can manage. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -repack_all_textures() { - // First, empty all the existing palette groups. - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - if (_aggressively_clean_mapdir) { - group->remove_palette_files(); - } - group->clear_palettes(); - } - - // Reorder the textures in descending order by height and width for - // optimal packing. - vector textures; - get_eligible_textures(textures); - - // Now pack all the textures. This will create new palettes. - vector::iterator ti; - for (ti = textures.begin(); ti != textures.end(); ++ti) { - (*ti)->pack(); - } - - _optimal = true; -} - - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::repack_some_textures -// Access: Public -// Description: Add new textures into the palettes without disturbing -// whatever was already there. This won't generate an -// optimal palette, but it won't require rebuilding -// every egg file that already uses this palette. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -repack_some_textures() { - bool empty_before = _groups.empty(); - bool any_added = false; - - // Reorder the textures in descending order by height and width for - // optimal packing. - vector textures; - get_eligible_textures(textures); - - // Now pack whatever textures are currently unpacked. - vector::iterator ti; - for (ti = textures.begin(); ti != textures.end(); ++ti) { - TexturePacking *packing = (*ti); - if (packing->pack()) { - any_added = true; - } - } - - _optimal = (empty_before || !any_added); -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::optimal_resize -// Access: Public -// Description: Resizes each palette texture as small as it can be. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -optimal_resize() { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - (*gi).second->optimal_resize(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::finalize_palettes -// Access: Public -// Description: Sets up some final state on each palette, necessary -// before writing them out. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -finalize_palettes() { - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - (*gi).second->finalize_palettes(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::remove_unused_lines -// Access: Public -// Description: Removes any lines from the .txa file that weren't -// used by any texture, presumably in response to -k on -// the command line and in preparation for rewriting the -// .txa file. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -remove_unused_lines() { - UserLines::iterator read, write; - - read = _user_lines.begin(); - write = _user_lines.begin(); - while (read != _user_lines.end()) { - if ((*read)->was_used()) { - (*write++) = (*read++); - } else { - delete (*read); - _txa_needs_rewrite = true; - read++; - } - } - _user_lines.erase(write, _user_lines.end()); -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::prepare_repack -// Access: Public -// Description: Checks if any texture needs to be repacked into a -// different location on the palette (for instance, -// because it has changed size). If so, unpacks it and -// returns true; otherwise, leaves it alone and returns -// false. -// -// If force_optimal is true, returns true if anything -// has changed at all that would result in a suboptimal -// palette. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -prepare_repack(bool force_optimal) { - bool needs_repack = false; - - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - TexturePacking *packing = (*pi); - if (packing->prepare_repack(_optimal)) { - needs_repack = true; - } - } - - if (force_optimal && !_optimal) { - // If the user wants to insist on an optimal packing, we'll have - // to give it to him. - needs_repack = true; - } - - return needs_repack; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::touch_dirty_egg_files -// Access: Public -// Description: Updates the timestamp on each egg file that will need -// to be rebuilt, so that a future make process will -// pick it up. This is only necessary to update egg -// files that may not have been included on the command -// line, and which we don't have direct access to. -//////////////////////////////////////////////////////////////////// -void AttribFile:: -touch_dirty_egg_files(bool force_redo_all, - bool eggs_include_images) { - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - - if (egg->needs_rebuild(force_redo_all, eggs_include_images)) { - Filename filename = egg->get_egg_filename(); - filename.set_extension("pt"); - nout << "Touching " << filename << "\n"; - if (!filename.touch()) { - nout << "unable to touch " << filename << "\n"; - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::get_texture -// Access: Public -// Description: Returns a pointer to the particular texture with the -// indicated name. If the named PTexture does not exist -// in the AttribFile structure, creates one and returns -// it. -//////////////////////////////////////////////////////////////////// -PTexture *AttribFile:: -get_texture(const string &name) { - PTextures::iterator ti; - ti = _textures.find(name); - if (ti != _textures.end()) { - return (*ti).second; - } - - PTexture *texture = new PTexture(this, name); - _textures[name] = texture; - return texture; -} - -void AttribFile:: -get_eligible_textures(vector &textures) { - // First, copy the texture pointers into this map structure to sort - // them in descending order by size. This is a 2-d map such that - // each map[ysize][xsize] is a set of texture pointers. - typedef map > > TexBySize; - TexBySize tex_by_size; - int num_textures = 0; - - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - TexturePacking *packing = (*pi); - PTexture *texture = packing->get_texture(); - - if (packing->get_omit() == OR_none) { - int xsize, ysize; - if (texture->get_req(xsize, ysize)) { - tex_by_size[-ysize][-xsize].insert(packing); - num_textures++; - } - } - } - - // Now walk through this map and get out our textures, nicely sorted - // in descending order by height and width. - textures.clear(); - textures.reserve(num_textures); - - TexBySize::const_iterator t1; - for (t1 = tex_by_size.begin(); t1 != tex_by_size.end(); ++t1) { - map >::const_iterator t2; - for (t2 = (*t1).second.begin(); t2 != (*t1).second.end(); ++t2) { - set::const_iterator t3; - for (t3 = (*t2).second.begin(); t3 != (*t2).second.end(); ++t3) { - textures.push_back(*t3); - } - } - } -} - -SourceEgg *AttribFile:: -get_egg(Filename name) { - string basename = name.get_basename(); - Eggs::iterator ei; - ei = _eggs.find(basename); - if (ei != _eggs.end()) { - return (*ei).second; - } - - SourceEgg *egg = new SourceEgg(this); - egg->resolve_egg_filename(name); - egg->set_egg_filename(name); - _eggs[basename] = egg; - return egg; -} - -bool AttribFile:: -generate_palette_images() { - bool okflag = true; - - Groups::iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - PaletteGroup *group = (*gi).second; - okflag = group->generate_palette_images() && okflag; - } - - return okflag; -} - -bool AttribFile:: -transfer_unplaced_images(bool force_redo_all) { - bool okflag = true; - - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - TexturePacking *packing = (*pi); - PTexture *texture = packing->get_texture(); - - if (packing->get_omit() != OR_none && - packing->get_omit() != OR_unused) { - // Here's a texture that needs to be moved to our mapdir. But - // maybe it's already there and hasn't changed recently. - if (force_redo_all || packing->needs_refresh()) { - // Nope, needs to be updated. - okflag = packing->transfer() && okflag; - } - } else { - if (_aggressively_clean_mapdir && texture->is_unused()) { - Filename new_filename = packing->get_new_filename(); - if (new_filename.exists()) { - nout << "Deleting " << new_filename << "\n"; - new_filename.unlink(); - } - if (packing->has_alpha_filename()) { - Filename alpha_filename = packing->get_alpha_filename(); - if (alpha_filename.exists()) { - nout << "Deleting " << alpha_filename << "\n"; - alpha_filename.unlink(); - } - } - } - } - } - - return okflag; -} - - -void AttribFile:: -check_dup_textures(map &textures, - map &dup_textures) const { - /* - PTextures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - PTexture *texture = (*ti).second; - string name = texture->get_name(); - - map::iterator mi = textures.find(name); - if (mi == textures.end()) { - // This texture hasn't been used yet. - textures[name] = texture; - - } else { - // This texture has already been used in another palette. The - // smaller of the two is considered wasted space. - PTexture *other = (*mi).second; - - if (!other->is_really_packed() && !texture->is_really_packed()) { - // No, neither one is packed, so it's not wasted space. - - } else { - int txsize, tysize; - int oxsize, oysize; - int wasted_size = 0; - - if (other->is_really_packed() != texture->is_really_packed()) { - // If one texture is packed and the other isn't, the packed - // one is considered wasted space. - if (other->is_really_packed()) { - if (other->get_req(oxsize, oysize)) { - wasted_size = oxsize * oysize; - } - (*mi).second = texture; - } else { - if (texture->get_req(txsize, tysize)) { - wasted_size = txsize * tysize; - } - } - - } else { - // Both textures are packed. The smaller one is considered - // wasted space. - assert(other->is_really_packed() && texture->is_really_packed()); - - if (texture->get_req(txsize, tysize) && - other->get_req(oxsize, oysize)) { - if (txsize * tysize <= oxsize * oysize) { - wasted_size = txsize * tysize; - } else { - wasted_size = oxsize * oysize; - (*mi).second = texture; - } - } - } - - // Now update the wasted space total for this texture. - map::iterator di = dup_textures.find(name); - if (di != dup_textures.end()) { - (*di).second += wasted_size; - } else { - dup_textures[name] = wasted_size; - } - } - } - } - */ -} - -void AttribFile:: -collect_statistics(int &num_textures, int &num_placed, int &num_palettes, - int &orig_size, int &resized_size, - int &palette_size, int &unplaced_size) const { - /* - num_textures = _textures.size(); - num_palettes = 0; //_palettes.size(); - num_placed = 0; - orig_size = 0; - resized_size = 0; - palette_size = 0; - unplaced_size = 0; - - PTextures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - PTexture *texture = (*ti).second; - - int xsize, ysize, zsize; - int rxsize, rysize; - int rsize = 0; - if (texture->get_size(xsize, ysize, zsize) && - texture->get_last_req(rxsize, rysize)) { - orig_size += xsize * ysize; - resized_size += rxsize * rysize; - rsize = rxsize * rysize; - } - - if (texture->is_really_packed()) { - num_placed++; - } else { - unplaced_size += rsize; - } - } - - Palettes::const_iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - Palette *palette = (*pi); - if (palette->get_num_textures() > 1) { - int xsize, ysize, zsize; - palette->get_size(xsize, ysize, zsize); - palette_size += xsize * ysize; - } - } - */ -} - - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::make_color_filename -// Access: Public -// Description: Adjusts an image filename to a suitable filename for -// saving the color channel. -//////////////////////////////////////////////////////////////////// -Filename AttribFile:: -make_color_filename(const Filename &filename) const { - Filename color_filename = filename; - if (_color_type != (PNMFileType *)NULL) { - color_filename.set_extension(_color_type->get_suggested_extension()); - } - return color_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::make_alpha_filename -// Access: Public -// Description: Adjusts an image filename to a suitable filename for -// saving the alpha channel, if one is to be saved. -//////////////////////////////////////////////////////////////////// -Filename AttribFile:: -make_alpha_filename(const Filename &filename) const { - Filename alpha_filename; - if (_alpha_type != (PNMFileType *)NULL) { - alpha_filename = filename; - alpha_filename.set_basename - (filename.get_basename_wo_extension() + "_alpha." + - _alpha_type->get_suggested_extension()); - } - return alpha_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::write_image_file -// Access: Public -// Description: Writes out the indicated image, either as a single -// file with or without alpha, or as two separate files -// if necessary. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -write_image_file(PNMImage &image, const Filename &filename, - const Filename &alpha_filename) const { - if (!image.has_alpha() || _alpha_type == (PNMFileType *)NULL) { - if (!alpha_filename.empty() && alpha_filename.exists()) { - alpha_filename.unlink(); - } - return image.write(filename, _color_type); - } - - // Write out a separate color image and an alpha channel image. - PNMImage alpha_image(image.get_x_size(), image.get_y_size(), 1, - image.get_maxval()); - for (int y = 0; y < image.get_y_size(); y++) { - for (int x = 0; x < image.get_x_size(); x++) { - alpha_image.set_gray_val(x, y, image.get_alpha_val(x, y)); - } - } - - image.remove_alpha(); - return - image.write(filename, _color_type) && - alpha_image.write(alpha_filename, _alpha_type); -} - -//////////////////////////////////////////////////////////////////// -// Function: AttribFile::read_image_file -// Access: Public -// Description: Reads in the indicated image, either as a single -// file with or without alpha, or as two separate files -// if necessary. -//////////////////////////////////////////////////////////////////// -bool AttribFile:: -read_image_file(PNMImage &image, const Filename &filename, - const Filename &alpha_filename) const { - image.set_type(_color_type); - if (!image.read(filename)) { - return false; - } - - if (!alpha_filename.empty() && alpha_filename.exists()) { - // Read in a separate color image and an alpha channel image. - PNMImage alpha_image; - alpha_image.set_type(_alpha_type); - if (!alpha_image.read(alpha_filename)) { - return false; - } - if (image.get_x_size() != alpha_image.get_x_size() || - image.get_y_size() != alpha_image.get_y_size()) { - return false; - } - - image.add_alpha(); - for (int y = 0; y < image.get_y_size(); y++) { - for (int x = 0; x < image.get_x_size(); x++) { - image.set_alpha(x, y, alpha_image.get_gray(x, y)); - } - } - } - - return true; -} - - -bool AttribFile:: -read_txa(istream &infile) { - string line; - - getline(infile, line); - int line_num = 1; - - while (!infile.eof()) { - UserAttribLine *ul = new UserAttribLine(line, this); - if (!ul->is_valid()) { - nout << "Error at line " << line_num << " of " << _txa_filename << "\n"; - return false; - } - if (ul->is_old_style()) { - _txa_needs_rewrite = true; - } - _user_lines.push_back(ul); - - getline(infile, line); - line_num++; - } - return true; -} - -bool AttribFile:: -read_pi(istream &infile, bool force_redo_all) { - string line; - - getline(infile, line); - int line_num = 1; - - while (!infile.eof()) { - // First, strip off the comment. - if (!line.empty()) { - if (line[0] == '#') { - line = ""; - } else { - size_t pos = line.find(" #"); - if (pos != string::npos) { - line = line.substr(0, pos - 1); - } - } - } - - vector_string words = extract_words(line); - bool okflag = true; - - if (words.empty()) { - getline(infile, line); - line_num++; - - } else if (words[0] == "params") { - okflag = parse_params(words, infile, line, line_num); - - } else if (words[0] == "packing") { - okflag = parse_packing(words, infile, line, line_num); - - } else if (words[0] == "textures") { - okflag = parse_texture(words, infile, line, line_num); - - } else if (words[0] == "pathnames") { - okflag = parse_pathname(words, infile, line, line_num); - - } else if (words[0] == "egg") { - okflag = parse_egg(words, infile, line, line_num, force_redo_all); - - } else if (words[0] == "group") { - okflag = parse_group(words, infile, line, line_num); - - } else if (words[0] == "palette") { - okflag = parse_palette(words, infile, line, line_num); - - } else if (words[0] == "unplaced") { - okflag = parse_unplaced(words, infile, line, line_num); - - } else if (words[0] == "surprises") { - okflag = parse_surprises(words, infile, line, line_num); - - } else { - nout << "Invalid keyword: " << words[0] << "\n"; - okflag = false; - } - - if (!okflag) { - nout << "Error at line " << line_num << " of " << _pi_filename << "\n"; - return false; - } - } - - return true; -} - -bool AttribFile:: -write_txa(ostream &out) const { - UserLines::const_iterator ui; - - for (ui = _user_lines.begin(); ui != _user_lines.end(); ++ui) { - (*ui)->write(out); - } - - if (!out) { - nout << "I/O error when writing to " << _txa_filename << "\n"; - return false; - } - return true; -} - -bool AttribFile:: -write_pi(ostream &out) const { - bool any_surprises = false; - - out << - "# This file was generated by egg-palettize. Edit it at your own peril.\n"; - - out << "\nparams\n" - << " map_directory " << _map_dirname << "\n" - << " rel_directory " << write_pi_filename(_rel_dirname) << "\n" - << " pal_xsize " << _pal_xsize << "\n" - << " pal_ysize " << _pal_ysize << "\n" - << " default_margin " << _default_margin << "\n" - << " force_power_2 " << _force_power_2 << "\n" - << " aggressively_clean_mapdir " << _aggressively_clean_mapdir << "\n" - << " color_type"; - if (_color_type != (PNMFileType *)NULL) { - out << " " << _color_type->get_suggested_extension(); - } - out << "\n alpha_type"; - if (_alpha_type != (PNMFileType *)NULL) { - out << " " << _alpha_type->get_suggested_extension(); - } - out << "\n"; - - if (_optimal) { - out << "\npacking is optimal\n"; - // Well, as nearly as this program can do it, anyway. - } else { - out << "\npacking is suboptimal\n"; - } - - out << "\npathnames\n"; - PTextures::const_iterator ti; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - (*ti).second->write_pathname(out); - } - - Eggs::const_iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - out << "\n"; - egg->write_pi(out); - any_surprises = any_surprises || !egg->matched_anything(); - } - - out << "\n"; - Groups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - (*gi).second->write_pi(out); - } - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - (*gi).second->write_palettes_pi(out); - } - - out << "\n"; - Packing::const_iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - (*pi)->write_unplaced(out); - } - - // Sort textures in descending order by scale percent. - typedef multimap SortPTextures; - SortPTextures sort_textures; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - PTexture *texture = (*ti).second; - sort_textures.insert(SortPTextures::value_type(-texture->get_scale_pct(), - texture)); - } - - out << "\ntextures\n"; - SortPTextures::const_iterator sti; - for (sti = sort_textures.begin(); sti != sort_textures.end(); ++sti) { - PTexture *texture = (*sti).second; - texture->write_size(out); - any_surprises = any_surprises || !texture->matched_anything(); - } - - if (any_surprises) { - // Some textures or egg files didn't match any commands; they're - // "surprises". - out << "\nsurprises\n"; - for (ti = _textures.begin(); ti != _textures.end(); ++ti) { - PTexture *texture = (*ti).second; - if (!texture->matched_anything()) { - out << " " << texture->get_name() << "\n"; - } - } - Eggs::const_iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = (*ei).second; - if (!egg->matched_anything()) { - out << " " << egg->get_egg_filename().get_basename() << "\n"; - } - } - } - - if (!out) { - nout << "I/O error when writing to " << _pi_filename << "\n"; - return false; - } - - return true; -} - -bool AttribFile:: -parse_params(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 1) { - nout << "Unexpected keywords on line.\n"; - return false; - } - - getline(infile, line); - line = trim_right(line); - line_num++; - while (!infile.eof() && !line.empty() && isspace(line[0])) { - string param, value; - extract_param_value(line, param, value); - - if (param == "map_directory") { - _map_dirname = value; - } else if (param == "rel_directory") { - _rel_dirname = read_pi_filename(value); - } else if (param == "pal_xsize") { - _pal_xsize = atoi(value.c_str()); - } else if (param == "pal_ysize") { - _pal_ysize = atoi(value.c_str()); - } else if (param == "default_margin") { - _default_margin = atoi(value.c_str()); - } else if (param == "force_power_2") { - _force_power_2 = (atoi(value.c_str()) != 0); - } else if (param == "aggressively_clean_mapdir") { - _aggressively_clean_mapdir = (atoi(value.c_str()) != 0); - } else if (param == "color_type") { - if (value.empty()) { - _color_type = (PNMFileType *)NULL; - } else { - PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr(); - _color_type = registry->get_type_from_extension(value); - if (_color_type == (PNMFileType *)NULL) { - nout << "Warning: unknown image file type: " << value << "\n"; - } - } - } else if (param == "alpha_type") { - if (value.empty()) { - _alpha_type = (PNMFileType *)NULL; - } else { - PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr(); - _alpha_type = registry->get_type_from_extension(value); - if (_alpha_type == (PNMFileType *)NULL) { - nout << "Warning: unknown image file type: " << value << "\n"; - } - } - } else { - nout << "Unexpected keyword: " << param << "\n"; - return false; - } - - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} - -bool AttribFile:: -parse_packing(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (!(words.size() == 3 && words[1] == "is" && - (words[2] == "optimal" || words[2] == "suboptimal"))) { - nout << "Expected 'packing is {optimal|suboptimal}'\n"; - return false; - } - - _optimal = (words[2] == "optimal"); - - getline(infile, line); - line_num++; - return true; -} - - -bool AttribFile:: -parse_texture(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 1) { - nout << "Unexpected words on line.\n"; - return false; - } - - getline(infile, line); - line = trim_right(line); - line_num++; - while (!infile.eof() && !line.empty() && isspace(line[0])) { - vector_string twords = extract_words(line); - if (twords.size() < 1) { - nout << "Expected texture name and additional parameters.\n"; - return false; - } - PTexture *texture = get_texture(twords[0]); - - int kw = 1; - while (kw < (int)twords.size()) { - if (kw + 3 <= (int)twords.size() && twords[kw] == "orig") { - texture->set_size(atoi(twords[kw + 1].c_str()), - atoi(twords[kw + 2].c_str()), - atoi(twords[kw + 3].c_str())); - kw += 4; - - } else if (kw + 3 <= (int)twords.size() && twords[kw] == "new") { - texture->set_last_req(atoi(twords[kw + 1].c_str()), - atoi(twords[kw + 2].c_str())); - kw += 3; - - } else if (twords[kw].find('%') != string::npos) { - // Ignore scale percentage. - kw++; - - } else { - nout << "Unexpected keyword: " << twords[kw] << "\n"; - } - } - - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} - -bool AttribFile:: -parse_pathname(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 1) { - nout << "Unexpected words on line.\n"; - return false; - } - - getline(infile, line); - line = trim_right(line); - line_num++; - PTexture *texture = NULL; - - while (!infile.eof() && !line.empty() && isspace(line[0])) { - vector_string twords = extract_words(line); - if (twords.size() == 1) { - // Only one word on the line means it's an alternate filename - // for the previous texture. - if (texture == NULL) { - nout << "Expected texture name and pathname.\n"; - return false; - } - texture->add_filename(read_pi_filename(twords[0])); - - } else if (twords.size() == 2) { - // Two words on the line means it's a texture name and filename. - texture = get_texture(twords[0]); - texture->add_filename(read_pi_filename(twords[1])); - - } else { - // Anything else is a mistake. - nout << "Expected texture name and pathname.\n"; - return false; - } - - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} - -bool AttribFile:: -parse_egg(const vector_string &words, istream &infile, - string &line, int &line_num, bool force_redo_all) { - if (words.size() < 2) { - nout << "Egg filename expected.\n"; - return false; - } - - SourceEgg *egg = get_egg(read_pi_filename(words[1])); - - if (words.size() > 2 && words[2] == "in") { - // Get the group names. - for (int i = 3; i < (int)words.size(); i++) { - egg->add_group(get_group(words[i])); - } - } - - getline(infile, line); - line = trim_right(line); - line_num++; - while (!infile.eof() && !line.empty() && isspace(line[0])) { - vector_string twords = extract_words(line); - if (twords.size() < 1) { - nout << "Expected texture name\n"; - return false; - } - - string name = twords[0]; - bool repeats = false; - bool alpha = false; - PaletteGroup *group = (PaletteGroup *)NULL; - - int kw = 1; - while (kw < (int)twords.size()) { - if (twords[kw] == "in") { - kw++; - if (kw >= (int)twords.size()) { - nout << "Expected group name\n"; - return false; - } - group = get_group(twords[kw]); - kw++; - - } else if (twords[kw] == "repeats") { - repeats = true; - kw++; - - } else if (twords[kw] == "alpha") { - alpha = true; - kw++; - - } else { - nout << "Unexpected keyword " << twords[kw] << "\n"; - return false; - } - } - - PTexture *texture = get_texture(name); - TexturePacking *packing = (TexturePacking *)NULL; - - if (!force_redo_all) { - packing = texture->add_to_group(group); - } - - egg->add_texture(texture, packing, repeats, alpha); - - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} - - -bool AttribFile:: -parse_group(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() == 2) { - // Just a group name by itself; ignore it. - return true; - } - - if (words.size() != 4) { - nout << "Group dirname expected.\n"; - return false; - } - - if (!(words[2] == "dir")) { - nout << "Expected keyword 'dir'\n"; - return false; - } - PaletteGroup *group = get_group(words[1]); - - group->set_dirname(words[3]); - - getline(infile, line); - line_num++; - return true; -} - -bool AttribFile:: -parse_palette(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 8) { - nout << "Palette filename, group, size, and number of components expected.\n"; - return false; - } - - string filename = read_pi_filename(words[1]); - if (!(words[2] == "in")) { - nout << "Expected keyword 'in'\n"; - return false; - } - PaletteGroup *group = get_group(words[3]); - - if (!(words[4] == "size")) { - nout << "Expected keyword 'size'\n"; - return false; - } - int xsize = atoi(words[5].c_str()); - int ysize = atoi(words[6].c_str()); - int components = atoi(words[7].c_str()); - - Palette *palette = - new Palette(filename, group, xsize, ysize, components, this); - group->add_palette(palette); - - getline(infile, line); - line = trim_right(line); - line_num++; - while (!infile.eof() && !line.empty() && isspace(line[0])) { - vector_string twords = extract_words(line); - if (twords.size() != 9) { - nout << "Expected texture placement line.\n"; - return false; - } - - PTexture *texture = get_texture(twords[0]); - TexturePacking *packing = texture->add_to_group(group); - - if (!(twords[1] == "at")) { - nout << "Expected keyword 'at'\n"; - return false; - } - int left = atoi(twords[2].c_str()); - int top = atoi(twords[3].c_str()); - - if (!(twords[4] == "size")) { - nout << "Expected keyword 'size'\n"; - return false; - } - int xsize = atoi(twords[5].c_str()); - int ysize = atoi(twords[6].c_str()); - - if (!(twords[7] == "margin")) { - nout << "Expected keyword 'margin'\n"; - return false; - } - int margin = atoi(twords[8].c_str()); - - palette->place_texture_at(packing, left, top, xsize, ysize, margin); - - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} - - - -bool AttribFile:: -parse_unplaced(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 6) { - nout << "Unplaced texture description expected.\n"; - return false; - } - - PTexture *texture = get_texture(words[1]); - - if (!(words[2] == "in")) { - nout << "Expected keyword 'in'\n"; - return false; - } - - PaletteGroup *group = get_group(words[3]); - TexturePacking *packing = texture->add_to_group(group); - - if (!(words[4] == "because")) { - nout << "Expected keyword 'because'\n"; - return false; - } - - if (words[5] == "size") { - packing->set_omit(OR_size); - } else if (words[5] == "repeats") { - packing->set_omit(OR_repeats); - } else if (words[5] == "omitted") { - packing->set_omit(OR_omitted); - } else if (words[5] == "unused") { - packing->set_omit(OR_unused); - } else if (words[5] == "unknown") { - packing->set_omit(OR_unknown); - } else if (words[5] == "solitary") { - packing->set_omit(OR_solitary); - } else { - nout << "Unknown keyword " << words[5] << "\n"; - return false; - } - - getline(infile, line); - line_num++; - return true; -} - -bool AttribFile:: -parse_surprises(const vector_string &words, istream &infile, - string &line, int &line_num) { - if (words.size() != 1) { - nout << "Unexpected words on line.\n"; - return false; - } - - // This is just the list of surprise textures from last time. Its - // only purpose is to inform the user; we can completely ignore it. - - getline(infile, line); - line = trim_right(line); - line_num++; - while (!infile.eof() && !line.empty() && isspace(line[0])) { - getline(infile, line); - line = trim_right(line); - line_num++; - } - - return true; -} diff --git a/pandatool/src/egg-palettize-old/attribFile.h b/pandatool/src/egg-palettize-old/attribFile.h deleted file mode 100644 index 5db174c0bb..0000000000 --- a/pandatool/src/egg-palettize-old/attribFile.h +++ /dev/null @@ -1,167 +0,0 @@ -// Filename: attribFile.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef ATTRIBFILE_H -#define ATTRIBFILE_H - -#include - -#include -#include - -#include -#include - -class UserAttribLine; -class PTexture; -class TexturePacking; -class PaletteGroup; -class Palette; -class SourceEgg; -class EggPalettize; -class PNMImage; -class PNMFileType; - -//////////////////////////////////////////////////////////////////// -// Class : AttribFile -// Description : The primary driving object behind egg-palettize, this -// class represents both a .txa file and its associated -// .pi file, as well as containing pointers to all the -// textures, palettes, and egg files referenced. -//////////////////////////////////////////////////////////////////// -class AttribFile { -public: - AttribFile(const Filename &filename); - - string get_name() const; - - bool open_and_lock(bool lock); - bool close_and_unlock(); - bool rewind_and_truncate(); - - bool read(bool force_redo_all); - bool write(); - - Filename write_pi_filename(Filename filename) const; - Filename read_pi_filename(Filename filename) const; - Filename write_egg_filename(Filename filename) const; - - void update_params(EggPalettize *prog); - - PaletteGroup *get_group(const string &group_name); - void set_default_group(PaletteGroup *default_group); - PaletteGroup *get_default_group(); - - void get_egg_group_requests(); - void get_size_requests(); - void update_texture_flags(); - - void repack_all_textures(); - void repack_some_textures(); - void optimal_resize(); - void finalize_palettes(); - void remove_unused_lines(); - bool prepare_repack(bool force_optimal); - - void touch_dirty_egg_files(bool force_redo_all, - bool eggs_include_images); - - PTexture *get_texture(const string &name); - void get_eligible_textures(vector &textures); - SourceEgg *get_egg(Filename name); - - bool generate_palette_images(); - bool transfer_unplaced_images(bool force_redo_all); - - void check_dup_textures(map &textures, - map &dup_textures) const; - - void collect_statistics(int &num_textures, int &num_placed, - int &num_palettes, - int &orig_size, int &resized_size, - int &palette_size, int &unplaced_size) const; - - Filename make_color_filename(const Filename &filename) const; - Filename make_alpha_filename(const Filename &filename) const; - - bool write_image_file(PNMImage &image, const Filename &filename, - const Filename &alpha_filename) const; - bool read_image_file(PNMImage &image, const Filename &filename, - const Filename &alpha_filename) const; - -private: - typedef vector UserLines; - UserLines _user_lines; - - typedef map Eggs; - Eggs _eggs; - - typedef map Groups; - Groups _groups; - - typedef map PTextures; - PTextures _textures; - - typedef vector Packing; - Packing _packing; - - bool read_txa(istream &outfile); - bool read_pi(istream &outfile, bool force_redo_all); - bool write_txa(ostream &outfile) const; - bool write_pi(ostream &outfile) const; - - bool parse_params(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_packing(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_texture(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_pathname(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_egg(const vector_string &words, istream &infile, - string &line, int &line_num, bool force_redo_all); - bool parse_group(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_palette(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_unplaced(const vector_string &words, istream &infile, - string &line, int &line_num); - bool parse_surprises(const vector_string &words, istream &infile, - string &line, int &line_num); - - bool _optimal; - bool _txa_needs_rewrite; - - string _name; - Filename _txa_filename; - Filename _pi_filename; - - Filename _pi_dir; - - PaletteGroup *_default_group; - -public: - // These parameter values come from the command line, or from the - // .pi file if omitted from the command line. These are the - // parameter values that specifically refer to textures and - // palettes, and thus should be stored in the .pi file for future - // reference. - string _map_dirname; - Filename _rel_dirname; - int _pal_xsize, _pal_ysize; - int _default_margin; - bool _force_power_2; - bool _aggressively_clean_mapdir; - - PNMFileType *_color_type; - PNMFileType *_alpha_type; - - int _txa_fd; - fstream _txa_fstrm; - - friend class PTexture; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/config_egg_palettize.cxx b/pandatool/src/egg-palettize-old/config_egg_palettize.cxx deleted file mode 100644 index 8466eb85a0..0000000000 --- a/pandatool/src/egg-palettize-old/config_egg_palettize.cxx +++ /dev/null @@ -1,14 +0,0 @@ -// Filename: config_egg_palettize.cxx -// Created by: drose (02Nov00) -// -//////////////////////////////////////////////////////////////////// - -#include - -#include "sourceEgg.h" - -Configure(config_egg_palettize); - -ConfigureFn(config_egg_palettize) { - SourceEgg::init_type(); -} diff --git a/pandatool/src/egg-palettize-old/eggPalettize.cxx b/pandatool/src/egg-palettize-old/eggPalettize.cxx deleted file mode 100644 index aa37eb1067..0000000000 --- a/pandatool/src/egg-palettize-old/eggPalettize.cxx +++ /dev/null @@ -1,737 +0,0 @@ -// Filename: eggPalettize.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "eggPalettize.h" -#include "attribFile.h" -#include "pTexture.h" -#include "string_utils.h" -#include "sourceEgg.h" -#include "textureOmitReason.h" - -#include -#include -#include -#include - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -EggPalettize:: -EggPalettize() : EggMultiFilter(true) { - set_program_description - ("egg-palettize attempts to pack several texture maps from various models " - "together into one or more palette images, for improved rendering performance " - "and ease of texture management. It can also resize textures on the fly, " - "whether or not they are actually placed on a palette.\n\n" - - "egg-palettize reads and writes an AttributesFile, which contains instructions " - "from the user about resizing particular textures, as well as the complete " - "information necessary to reconstruct the palettization from past runs, " - "including references to other egg files that may share this palette. This " - "is designed to allow multiple egg files to use the same palette, without " - "having to process them all at once.\n\n" - - "Note that it is not even necessary to specify any egg files at all on the " - "command line; egg-palettize can be run on an existing AttributesFiles by " - "itself to freshen up a palette when necessary."); - - - clear_runlines(); - add_runline("[opts] attribfile.txa file.egg [file.egg ...]"); - - // We always have EggMultiBase's -f on: force complete load. In - // fact, we use -f for our own purposes, below. - remove_option("f"); - _force_complete = true; - - add_option - ("s", "", 0, - "Do not process anything, but report statistics on all palette " - "information files read.", - &EggPalettize::dispatch_none, &_statistics_only); - - // We redefine -d using add_option() instead of redescribe_option() - // so it gets listed along with these other options that relate. - add_option - ("d", "dirname", 0, - "The directory in which to write the palettized egg files. This is " - "only necessary if more than one egg file is processed at the same " - "time; if it is included, each egg file will be processed and written " - "into the indicated directory.", - &EggPalettize::dispatch_filename, &_got_output_dirname, &_output_dirname); - add_option - ("dm", "dirname", 0, - "The directory in which to place all maps: generated palettes, " - "as well as images which were not placed on palettes " - "(but may have been resized). If this contains the string %s, " - "this will be replaced with the \"dir\" string associated with a " - "palette group.", - &EggPalettize::dispatch_string, &_got_map_dirname, &_map_dirname); - add_option - ("dr", "dirname", 0, - "The directory to make map filenames relative to when writing egg " - "files. If specified, this should be an initial substring of -dm.", - &EggPalettize::dispatch_filename, &_got_rel_dirname, &_rel_dirname); - add_option - ("g", "group", 0, - "The default palette group that egg files will be assigned to if they " - "are not explicitly assigned to any other group.", - &EggPalettize::dispatch_string, &_got_default_groupname, &_default_groupname); - add_option - ("gdir", "name", 0, - "The \"dir\" string to associate with the default palette group " - "specified with -g, if no other dir name is given in the .txa file.", - &EggPalettize::dispatch_string, &_got_default_groupdir, &_default_groupdir); - - add_option - ("f", "", 0, - "Force an optimal packing. By default, textures are added to " - "existing palettes without disturbing them, which can lead to " - "suboptimal packing. Including this switch forces the palettes " - "to be rebuilt if necessary to optimize the packing, but this " - "may invalidate other egg files which share this palette.", - &EggPalettize::dispatch_none, &_force_optimal); - add_option - ("F", "", 0, - "Force a redo of everything. This is useful in case something " - "has gotten out of sync and the old palettes are just bad.", - &EggPalettize::dispatch_none, &_force_redo_all); - add_option - ("R", "", 0, - "Resize mostly-empty palettes to their minimal size.", - &EggPalettize::dispatch_none, &_optimal_resize); - add_option - ("t", "", 0, - "Touch any additional egg files that share this palette and will " - "need to be refreshed, but were not included on the command " - "line. Presumably a future make pass will cause them to be run " - "through egg-palettize again.", - &EggPalettize::dispatch_none, &_touch_eggs); - add_option - ("T", "", 0, - "When touching egg files, consider an egg file to be invalidated " - "if textures have changed in any way, rather than simply moving " - "around within their palettes. You should use this switch " - "if the texture images themselves are to be stored within bam files " - "generated from the eggs, or some such nonsense.", - &EggPalettize::dispatch_none, &_eggs_include_images); - add_option - ("C", "", 0, - "Aggressively keep the map directory clean by deleting unused " - "textures from previous passes.", - &EggPalettize::dispatch_none, &_got_aggressively_clean_mapdir); - add_option - ("type", "imagetype[,alphatype]", 0, - "Specify the type of image file to output. All image files, whether " - "palettes or unplaced textures, will be converted to files of this " - "type. If the optional alpha type is specified, then an alpha channel, " - "if present, will be written as a separate file of the indicated " - "type--useful if the primary image type does not support alpha. " - "Use '-type list' to show the available image types.", - &EggPalettize::dispatch_string, &_got_image_type, &_image_type); - add_option - ("r", "", 0, - "Respect any repeat/clamp flags given in the egg files. The " - "default is to override a repeat flag if a texture's UV's don't " - "exceed the range [0..1].", - &EggPalettize::dispatch_none, &_dont_override_repeats); - add_option - ("z", "fuzz", 0, - "The fuzz factor when applying the above repeat test. UV's are " - "considered to be in the range [0..1] if they are actually in " - "the range [0-fuzz .. 1+fuzz]. The default is 0.01.", - &EggPalettize::dispatch_double, NULL, &_fuzz_factor); - add_option - ("m", "margin", 0, - "Specify the default margin size.", - &EggPalettize::dispatch_int, &_got_default_margin, &_default_margin); - add_option - ("P", "x,y", 0, - "Specify the default palette size.", - &EggPalettize::dispatch_int_pair, &_got_palette_size, _pal_size); - add_option - ("2", "", 0, - "Force textures that have been left out of the palette to a size " - "which is an integer power of 2. They will be scaled down to " - "achieve this.", - &EggPalettize::dispatch_none, &_got_force_power_2); - add_option - ("nolock", "", 0, - "Don't attempt to lock the .pi file before rewriting it. Use " - "with extreme caution, as multiple processes running on the same " - ".pi file may overwrite each other. Use this only if the lock " - "cannot be achieved for some reason.", - &EggPalettize::dispatch_none, &_dont_lock_pi); - add_option - ("k", "", 0, - "Kill lines from the attributes file that aren't used on any " - "texture.", - &EggPalettize::dispatch_none, &_remove_unused_lines); - add_option - ("H", "", 0, - "Describe the syntax of the attributes file.", - &EggPalettize::dispatch_none, &_describe_input_file); - - _fuzz_factor = 0.01; - _aggressively_clean_mapdir = false; - _force_power_2 = false; - _color_type = (PNMFileType *)NULL; - _alpha_type = (PNMFileType *)NULL; -} - - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::handle_args -// Access: Protected, Virtual -// Description: Does something with the additional arguments on the -// command line (after all the -options have been -// parsed). Returns true if the arguments are good, -// false otherwise. -//////////////////////////////////////////////////////////////////// -bool EggPalettize:: -handle_args(ProgramBase::Args &args) { - if (_describe_input_file) { - describe_input_file(); - exit(1); - } - - if (_got_image_type) { - PNMFileTypeRegistry *registry = PNMFileTypeRegistry::get_ptr(); - - if (_image_type == "list") { - nout << "Known image types are:\n"; - registry->write_types(nout, 2); - nout << "\n"; - exit(1); - } - - string color_name = _image_type; - string alpha_name; - size_t comma = _image_type.find(','); - if (comma != string::npos) { - // If we have a comma in the image_type, it's two types: a color - // type and an alpha type. - color_name = _image_type.substr(0, comma); - alpha_name = _image_type.substr(comma + 1); - } - - bool okflag = true; - - if (!color_name.empty()) { - _color_type = registry->get_type_from_extension(color_name); - if (_color_type == (PNMFileType *)NULL) { - nout << "Image file type '" << color_name << "' is unknown.\n"; - okflag = false; - } - } - - if (!alpha_name.empty()) { - _alpha_type = registry->get_type_from_extension(alpha_name); - if (_alpha_type == (PNMFileType *)NULL) { - nout << "Image file type '" << alpha_name << "' is unknown.\n"; - okflag = false; - } - } - - if (!okflag) { - nout << "\nKnown image types are:\n"; - registry->write_types(nout, 2); - nout << "\n"; - exit(1); - } - - /* - if (_color_type != (PNMFileType *)NULL && - _alpha_type != (PNMFileType *)NULL) { - nout << "Writing color components to " << _color_type->get_name() - << " and alpha components to " << _alpha_type->get_name() - << " files.\n"; - - } else if (_color_type != (PNMFileType *)NULL) { - nout << "Converting images to " << _color_type->get_name() - << " files.\n"; - } - */ - } - - Args egg_names; - Args txa_names; - - // First, collect all the filenames. - Args::iterator ai; - for (ai = args.begin(); ai != args.end(); ++ai) { - Filename filename = (*ai); - string ext = filename.get_extension(); - - if (ext == "egg") { - egg_names.push_back(filename); - } else if (ext == "txa" || ext == "pi") { - txa_names.push_back(filename); - } else { - nout << "Don't know what kind of file " << filename << " is.\n"; - return false; - } - } - - // Now sanity check them. Either we have zero egg files, and one or - // more txa files, or we have some egg files and exactly one txa - // file. - if (egg_names.empty()) { - if (txa_names.empty()) { - nout << "No files specified.\n"; - return false; - } - - for (ai = txa_names.begin(); ai != txa_names.end(); ++ai) { - AttribFile *af = new AttribFile(*ai); - _attrib_files.push_back(af); - } - - } else { - if (txa_names.empty()) { - nout << "Must include an attribs.txa file.\n"; - return false; - } - if (txa_names.size() != 1) { - nout << "Can only read one attribs.txa file when processing egg files.\n"; - return false; - } - - AttribFile *af = new AttribFile(txa_names[0]); - _attrib_files.push_back(af); - } - - return EggMultiFilter::handle_args(egg_names); -} - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::read_egg -// Access: Protected, Virtual -// Description: Allocates and returns a new EggData structure that -// represents the indicated egg file. If the egg file -// cannot be read for some reason, returns NULL. -// -// This can be overridden by derived classes to control -// how the egg files are read, or to extend the -// information stored with each egg structure, by -// deriving from EggData. -//////////////////////////////////////////////////////////////////// -EggData *EggPalettize:: -read_egg(const Filename &filename) { - // We should only call this function if we have exactly one .txa file. - nassertr(_attrib_files.size() == 1, (EggData *)NULL); - - SourceEgg *data = _attrib_files[0]->get_egg(filename); - if (!data->read(filename)) { - // Failure reading. - delete data; - return (EggData *)NULL; - } - - if (_force_complete) { - if (!data->resolve_externals()) { - delete data; - return (EggData *)NULL; - } - } - - return data; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::describe_input_file -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void EggPalettize:: -describe_input_file() { - nout << - "An attributes file consists mostly of lines describing desired sizes of " - "texture maps. The format resembles, but is not identical to, that of " - "the qtess input file. Examples:\n\n" - - " texturename.rgb : 64 64\n" - " texture-a.rgb texture-b.rgb : 32 16 2\n" - " *.rgb : 50%\n" - " eyelids.rgb : 16 16 omit\n\n" - - "In general, each line consists of one or more filenames (and can " - "contain shell globbing characters like '*' or '?'), and a colon " - "followed by a size request. For each texture appearing in an egg " - "file, the input list is scanned from the beginning and the first " - "line that matches the filename defines the size of the texture.\n\n" - - "A size request may be either a pair of numbers, giving a specific x y " - "size of the texture, or it may be a scale factor in the form of a " - "percentage. It may also include an additional number, giving a margin " - "for this particular texture (otherwise the default margin is " - "applied). Finally, the keyword 'omit' may be included along with the " - "size to specify that the texture should not be placed in a palette.\n\n" - - "The attributes file may also assign certain egg files into various " - "named palette groups. The syntax is similar to the above:\n\n" - - " car-blue.egg : main\n" - " road.egg house.egg : main\n" - " plane.egg : phase2 main\n" - " car*.egg : phase2\n\n" - - "Any number of egg files may be named on one line, and the group of " - "egg files may be simultaneously assigned to one or more groups. Each " - "named group represents a semi-independent collection of textures; a " - "different set of palette images will be created for each group. Each " - "texture that is referenced by a given egg file will be palettized " - "in one of the groups assigned to the egg file. Also see the " - ":group command, below, which defines relationships between the " - "different groups.\n\n" - - "There are some other special lines that may appear in this second, " - "along with the resize commands. They begin with a colon to " - "distinguish them from the resize commands. They are:\n\n" - - " :palette xsize ysize\n\n" - - "This specifies the size of the palette file(s) to be created. It " - "overrides the -s command-line option.\n\n" - - " :margin msize\n\n" - - "This specifies the size of the default margin for all subsequent " - "resize commands. This may appear several times in a given file.\n\n" - - " :group groupname1 with groupname2 [groupname3 ...]\n\n" - - "This indicates that the palette group named by groupname1 should " - "be allowed to shared textures with those on groupname2 or groupname3, " - "etc. In other words, that whenever palette group groupname1 is in " - "texture memory, we can assume that palette groups groupname2 and " - "groupname3 will also be in memory. Textures that already exist on " - "groupname2 and other dependent groups will not be added to groupname1; " - "instead, egg files will reference the textures directly from the " - "other palettes.\n\n" - - "Comments may appear freely throughout the file, and are set off by a " - "hash mark (#).\n"; -} - - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::format_space -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -string EggPalettize:: -format_space(int size_pixels, bool verbose) { - int size_bytes = size_pixels * 4; - int size_k = (size_bytes + 512) / 1024; - int mm_size_k = (size_bytes * 4 / 3 + 512) / 1024; - char str[128]; - if (verbose) { - sprintf(str, "%dk, w/mm %dk", size_k, mm_size_k); - } else { - sprintf(str, "%dk, %dk", size_k, mm_size_k); - } - assert(strlen(str) < 128); - - return str; -} - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::report_statistics -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void EggPalettize:: -report_statistics() { - /* - // Look for textures in common. - map textures; - map dup_textures; - - AttribFiles::iterator afi; - for (afi = _attrib_files.begin(); afi != _attrib_files.end(); ++afi) { - AttribFile &af = *(*afi); - af.check_dup_textures(textures, dup_textures); - } - - if (dup_textures.empty()) { - cout << "\nEach texture appears in only one palette group.\n"; - } else { - cout << "\nThe following textures appear in more than one palette group:\n"; - int net_wasted_size = 0; - map::const_iterator di; - for (di = dup_textures.begin(); di != dup_textures.end(); ++di) { - cout << " " << (*di).first << " (" - << format_space((*di).second) << ")\n"; - net_wasted_size += (*di).second; - } - cout << "Total wasted memory from common textures is " - << format_space(net_wasted_size, true) << "\n"; - } - - int net_palette_size = 0; - int net_num_palettes = 0; - - for (afi = _attrib_files.begin(); afi != _attrib_files.end(); ++afi) { - AttribFile &af = *(*afi); - int num_textures, num_placed, num_palettes; - int orig_size, resized_size, palette_size, unplaced_size; - af.collect_statistics(num_textures, num_placed, num_palettes, - orig_size, resized_size, - palette_size, unplaced_size); - cout << "\nPalette group " << af.get_name() << ":\n" - << " " << num_textures << " textures, " - << num_placed << " of which are packed onto " - << num_palettes << " palettes (" << num_textures - num_placed - << " unplaced)" - << "\n Original texture memory: " - << format_space(orig_size, true) - << "\n After resizing: " - << format_space(resized_size, true) - << "\n After palettizing: " - << format_space(palette_size + unplaced_size, true) - << "\n"; - - net_palette_size += palette_size; - net_num_palettes += num_palettes; - } - - int net_num_textures = textures.size(); - int net_num_placed = 0; - int net_orig_size = 0; - int net_resized_size = 0; - int net_unplaced_size = 0; - typedef map > UnplacedReasons; - UnplacedReasons unplaced_reasons; - - map::iterator ti; - for (ti = textures.begin(); ti != textures.end(); ++ti) { - PTexture *texture = (*ti).second; - - int xsize, ysize, zsize; - int rxsize, rysize; - int rsize = 0; - if (texture->get_size(xsize, ysize, zsize) && - texture->get_last_req(rxsize, rysize)) { - net_orig_size += xsize * ysize; - net_resized_size += rxsize * rysize; - rsize = rxsize * rysize; - } - - - if (texture->is_really_packed()) { - net_num_placed++; - - } else { - net_unplaced_size += rsize; - - // Here's an unplaced texture; add its size to the unplaced - // reasons table. - UnplacedReasons::iterator uri = - unplaced_reasons.find(texture->get_omit()); - if (uri == unplaced_reasons.end()) { - unplaced_reasons.insert - (UnplacedReasons::value_type(texture->get_omit(), - pair(1, rsize))); - } else { - (*uri).second.first++; - (*uri).second.second += rsize; - } - } - } - - cout << "\nOverall:\n" - << " " << net_num_textures << " textures, " - << net_num_placed << " of which are packed onto " - << net_num_palettes << " palettes (" - << net_num_textures - net_num_placed << " unplaced)" - << "\n Original texture memory: " - << format_space(net_orig_size, true) - << "\n After resizing: " - << format_space(net_resized_size, true) - << "\n After palettizing: " - << format_space(net_palette_size + net_unplaced_size, true) - << "\n\n"; - - UnplacedReasons::iterator uri; - for (uri = unplaced_reasons.begin(); - uri != unplaced_reasons.end(); - ++uri) { - TextureOmitReason reason = (*uri).first; - int count = (*uri).second.first; - int size = (*uri).second.second; - cout << count << " textures (" << format_space(size) - << ") unplaced because "; - switch (reason) { - case PTexture::OR_none: - cout << "of no reason--textures should have been placed\n"; - break; - - case PTexture::OR_size: - cout << "size was too large for palette\n"; - break; - - case PTexture::OR_repeats: - cout << "repeating\n"; - break; - - case PTexture::OR_omitted: - cout << "explicitly omitted\n"; - break; - - case PTexture::OR_unused: - cout << "unused by any egg file\n"; - break; - - case PTexture::OR_unknown: - cout << "texture file is missing\n"; - break; - - case PTexture::OR_cmdline: - cout << "-x was given on command line\n"; - break; - - case PTexture::OR_solitary: - cout << "texture was alone on a palette\n"; - break; - - default: - cout << "unknown reason\n"; - } - } - - cout << "\n"; - */ -} - -//////////////////////////////////////////////////////////////////// -// Function: EggPalettize::run -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -void EggPalettize:: -run() { - _force_power_2 = _got_force_power_2; - _aggressively_clean_mapdir = _got_aggressively_clean_mapdir; - - bool okflag = true; - - // We'll repeat the processing steps for each attrib file. If we - // have multiple attrib files, then we have no egg files, so all of - // the egg loops below fall out. On the other hand, if we do have - // egg files, then we have only one attrib file, so this outer loop - // falls out. - - AttribFiles::iterator afi; - for (afi = _attrib_files.begin(); afi != _attrib_files.end(); ++afi) { - AttribFile &af = *(*afi); - - if (_got_default_groupname) { - PaletteGroup *group = af.get_group(_default_groupname); - if (_got_default_groupdir) { - group->set_dirname(_default_groupdir); - } - af.set_default_group(group); - } - - if (!af.open_and_lock(!_dont_lock_pi)) { - // Failing to open, or failing to grab the write lock, on the - // attribute file is a fatal error. - exit(1); - } - - if (_statistics_only) { - nout << "Reading " << af.get_name() << "\n"; - okflag = af.read(false); - - } else { - nout << "Processing " << af.get_name() << "\n"; - - if (!af.read(_force_redo_all)) { - // Failing to read the attribute file is a fatal error. - exit(1); - } - - af.update_params(this); - - // Get all the texture references out of the egg files. - Eggs::iterator ei; - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = DCAST(SourceEgg, *ei); - egg->get_textures(this); - } - - // Assign textures into the appropriate groups. - af.get_egg_group_requests(); - - // Apply the user's requested size changes onto the textures. - af.get_size_requests(); - af.update_texture_flags(); - - if (af.prepare_repack(_force_optimal) || _force_redo_all) { - if (_force_redo_all || _force_optimal) { - af.repack_all_textures(); - } else { - af.repack_some_textures(); - } - - } else { - nout << "No changes to palette arrangement are required.\n"; - } - - af.finalize_palettes(); - - if (_optimal_resize) { - af.optimal_resize(); - } - - if (_remove_unused_lines) { - af.remove_unused_lines(); - } - - if (!af.write()) { - // Failing to rewrite the attribute file is a fatal error. - exit(1); - } - - // And rebuild whatever images are necessary. - okflag = af.generate_palette_images() && okflag; - okflag = af.transfer_unplaced_images(_force_redo_all) && okflag; - - // Now apply the palettization effects to the egg files. - for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { - SourceEgg *egg = DCAST(SourceEgg, *ei); - egg->update_trefs(); - } - - // Write out the egg files. - write_eggs(); - - if (_touch_eggs) { - af.touch_dirty_egg_files(_force_redo_all, _eggs_include_images); - } - } - - okflag = af.close_and_unlock() && okflag; - } - - if (_statistics_only) { - report_statistics(); - } - - if (!okflag) { - exit(1); - } -} - -int -main(int argc, char *argv[]) { - EggPalettize prog; - prog.parse_command_line(argc, argv); - prog.run(); - return 0; -} diff --git a/pandatool/src/egg-palettize-old/eggPalettize.h b/pandatool/src/egg-palettize-old/eggPalettize.h deleted file mode 100644 index b8d1b4ec56..0000000000 --- a/pandatool/src/egg-palettize-old/eggPalettize.h +++ /dev/null @@ -1,82 +0,0 @@ -// Filename: eggPalettize.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef EGGPALETTIZE_H -#define EGGPALETTIZE_H - -#include - -#include "attribFile.h" -#include - -#include - -class PTexture; -class PNMFileType; - -//////////////////////////////////////////////////////////////////// -// Class : EggPalettize -// Description : This is the heart of the program. -//////////////////////////////////////////////////////////////////// -class EggPalettize : public EggMultiFilter { -public: - EggPalettize(); - - virtual bool handle_args(Args &args); - virtual EggData *read_egg(const Filename &filename); - - void describe_input_file(); - - string format_space(int size_pixels, bool verbose = false); - void report_statistics(); - void run(); - - typedef vector AttribFiles; - AttribFiles _attrib_files; - - // The following parameter values specifically relate to textures - // and palettes. These values are stored in the .pi file for future - // reference. - string _map_dirname; - bool _got_map_dirname; - Filename _rel_dirname; - bool _got_rel_dirname; - string _default_groupname; - bool _got_default_groupname; - string _default_groupdir; - bool _got_default_groupdir; - int _pal_size[2]; - bool _got_palette_size; - int _default_margin; - bool _got_default_margin; - bool _force_power_2; - bool _got_force_power_2; - bool _aggressively_clean_mapdir; - bool _got_aggressively_clean_mapdir; - string _image_type; - bool _got_image_type; - PNMFileType *_color_type; - PNMFileType *_alpha_type; - - // The following values relate specifically to egg files. They're - // not saved for future sessions. - double _fuzz_factor; - bool _dont_override_repeats; - - // The following values control behavior specific to this session. - // They're not saved either. - bool _statistics_only; - bool _force_optimal; - bool _force_redo_all; - bool _optimal_resize; - bool _touch_eggs; - bool _eggs_include_images; - bool _dont_lock_pi; - bool _remove_unused_lines; - - bool _describe_input_file; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/pTexture.cxx b/pandatool/src/egg-palettize-old/pTexture.cxx deleted file mode 100644 index 386ef90800..0000000000 --- a/pandatool/src/egg-palettize-old/pTexture.cxx +++ /dev/null @@ -1,436 +0,0 @@ -// Filename: pTexture.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "pTexture.h" -#include "texturePacking.h" -#include "palette.h" -#include "attribFile.h" - -#include -#include - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PTexture:: -PTexture(AttribFile *attrib_file, const Filename &name) : - _name(name), - _attrib_file(attrib_file) -{ - _got_filename = false; - _file_exists = false; - _texture_changed = false; - _matched_anything = false; - _got_size = false; - _got_req = false; - _got_last_req = false; - _margin = _attrib_file->_default_margin; - _omit = false; - _read_header = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PTexture:: -~PTexture() { - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - delete (*pi).second; - } -} - -Filename PTexture:: -get_name() const { - return _name; -} - -void PTexture:: -add_filename(Filename filename) { - filename.make_absolute(); - - if (!filename.exists()) { - // Store the filename, even though it doesn't exist. - if (!_got_filename) { - _got_filename = true; - _filename = filename; - _file_exists = false; - } - - } else { - bool inserted = _filenames.insert(filename).second; - - if (!_got_filename || !_file_exists) { - // This was the first filename we encountered; no sweat. - _got_filename = true; - _file_exists = true; - _filename = filename; - - check_size(); - - } else if (inserted) { - // We had been using a different filename previously. Now we've - // got a new one. Maybe this one is better? - - // First, read the headers. We'll consider the larger image to - // be the better choice. - if (!_got_size) { - read_header(); - } - - int oxsize, oysize, ozsize; - bool got_other_size = - read_image_header(filename, oxsize, oysize, ozsize); - - if (got_other_size) { - if (!_got_size || oxsize * oysize > _xsize * _ysize) { - _filename = filename; - _xsize = oxsize; - _ysize = oysize; - _zsize = ozsize; - _got_size = true; - _texture_changed = true; - - } else if (oxsize * oysize == _xsize * _ysize) { - // If the sizes are the same, we'll consider the newer image - // to be the better choice. - if (filename.compare_timestamps(_filename, false, false) > 0) { - _filename = filename; - _texture_changed = true; - } - } - } - } - } -} - -bool PTexture:: -get_size(int &xsize, int &ysize, int &zsize) { - if (!_got_size) { - read_header(); - } - - if (!_got_size) { - return false; - } - - xsize = _xsize; - ysize = _ysize; - zsize = _zsize; - return true; -} - -void PTexture:: -set_size(int xsize, int ysize, int zsize) { - // If we've already read the file header, don't let anyone tell us - // differently. - if (!_read_header) { - _xsize = xsize; - _ysize = ysize; - _zsize = zsize; - _got_size = true; - } -} - -bool PTexture:: -get_req(int &xsize, int &ysize) { - if (!_got_req) { - int zsize; - return get_size(xsize, ysize, zsize); - } - xsize = _req_xsize; - ysize = _req_ysize; - return true; -} - -bool PTexture:: -get_last_req(int &xsize, int &ysize) { - if (!_got_last_req) { - int zsize; - return get_size(xsize, ysize, zsize); - } - xsize = _last_req_xsize; - ysize = _last_req_ysize; - return true; -} - -void PTexture:: -set_last_req(int xsize, int ysize) { - _last_req_xsize = xsize; - _last_req_ysize = ysize; - _got_last_req = true; -} - -void PTexture:: -reset_req(int xsize, int ysize) { - if (_got_last_req && - (_last_req_xsize != xsize || _last_req_ysize != ysize)) { - // We've changed the requested size from the last time we ran. - // That constitutes a change to the texture. - _texture_changed = true; - } - - _req_xsize = xsize; - _req_ysize = ysize; - _got_req = true; -} - -void PTexture:: -scale_req(double scale_pct) { - if (!_got_size) { - read_header(); - } - if (_got_size) { - reset_req(_xsize * scale_pct / 100.0, - _ysize * scale_pct / 100.0); - } -} - -void PTexture:: -clear_req() { - _got_req = false; - _margin = _attrib_file->_default_margin; -} - -double PTexture:: -get_scale_pct() { - if (!_got_size) { - read_header(); - } - if (_got_size && _got_req) { - return - 100.0 * (((double)_req_xsize / (double)_xsize) + - ((double)_req_ysize / (double)_ysize)) / 2.0; - } else { - return 100.0; - } -} - -int PTexture:: -get_margin() const { - return _margin; -} - -void PTexture:: -set_margin(int margin) { - _margin = margin; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::user_omit -// Access: Public -// Description: Omits the texture from all palettes, based on a -// user-supplied "omit" parameter (presumably read from -// the .txa file). -//////////////////////////////////////////////////////////////////// -void PTexture:: -user_omit() { - _omit = true; - - // Also omit each of our already-packed textures. - Packing::iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - (*pi).second->set_omit(OR_omitted); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::add_to_group -// Access: Public -// Description: Adds the texture to the indicated PaletteGroup, if it -// has not already been added. Returns the -// TexturePacking pointer that represents the addition. -//////////////////////////////////////////////////////////////////// -TexturePacking *PTexture:: -add_to_group(PaletteGroup *group) { - Packing::iterator pi; - pi = _packing.find(group); - if (pi != _packing.end()) { - return (*pi).second; - } - - TexturePacking *packing = new TexturePacking(this, group); - _packing[group] = packing; - _attrib_file->_packing.push_back(packing); - return packing; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::check_group -// Access: Public -// Description: If the texture has already been added to the -// indicated PaletteGroup, returns the associated -// TexturePacking object. If it is not yet been added, -// returns NULL. -//////////////////////////////////////////////////////////////////// -TexturePacking *PTexture:: -check_group(PaletteGroup *group) const { - Packing::const_iterator pi; - pi = _packing.find(group); - if (pi != _packing.end()) { - return (*pi).second; - } - - return (TexturePacking *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::set_changed -// Access: Public -// Description: Sets the state of the changed flag. If this is true, -// the texture is known to have changed in some way such -// that files that depend on it will need to be rebuilt. -//////////////////////////////////////////////////////////////////// -void PTexture:: -set_changed(bool changed) { - _texture_changed = changed; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::matched_anything -// Access: Public -// Description: Returns true if the texture matched at least one line -// in the .txa file, false otherwise. -//////////////////////////////////////////////////////////////////// -bool PTexture:: -matched_anything() const { - return _matched_anything; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::set_matched_anything -// Access: Public -// Description: Sets the state of the matched_anything flag. See -// matched_anything(). -//////////////////////////////////////////////////////////////////// -void PTexture:: -set_matched_anything(bool matched_anything) { - _matched_anything = matched_anything; -} - -//////////////////////////////////////////////////////////////////// -// Function: PTexture::is_unused -// Access: Public -// Description: Returns true if the texture is not used by any egg -// file in any palette group, false if it is used by at -// least one in at least one group. -//////////////////////////////////////////////////////////////////// -bool PTexture:: -is_unused() const { - Packing::const_iterator pi; - for (pi = _packing.begin(); pi != _packing.end(); ++pi) { - if (!(*pi).second->unused()) { - return false; - } - } - - return true; -} - - -void PTexture:: -write_size(ostream &out) { - if (!is_unused()) { - if (!_got_size) { - read_header(); - } - out << " " << _name; - if (_got_size) { - out << " orig " << _xsize << " " << _ysize << " " << _zsize; - } - if (_got_req) { - out << " new " << _req_xsize << " " << _req_ysize; - } - out << " " << get_scale_pct() << "%\n"; - } -} - -void PTexture:: -write_pathname(ostream &out) const { - if (_got_filename && !is_unused()) { - if (!_file_exists) { - nout << "Warning: texture " << _filename << " does not exist.\n"; - } - - out << " " << _name << " " << _attrib_file->write_pi_filename(_filename) - << "\n"; - - // Also write out all the alternate filenames. - Filenames::const_iterator fi; - for (fi = _filenames.begin(); fi != _filenames.end(); ++fi) { - if ((*fi) != _filename) { - // Indent by the same number of spaces to line up the filenames. - for (int i = 0; i < (int)_name.length() + 3; i++) { - out << ' '; - } - out << _attrib_file->write_pi_filename(*fi) << "\n"; - } - } - } -} - -PNMImage *PTexture:: -read_image() { - if (!_got_filename || !_file_exists) { - return NULL; - } - - PNMImage *image = new PNMImage; - if (_attrib_file->read_image_file(*image, _filename, Filename())) { - return image; - } - - // Hmm, it wasn't able to read the image successfully. Oh well. - delete image; - return NULL; -} - -void PTexture:: -check_size() { - // Make sure the file has the size it claims to have. - if (_got_size) { - int old_xsize = _xsize; - int old_ysize = _ysize; - read_header(); - if (_xsize != old_xsize && _ysize != old_ysize) { - nout << "Source texture " << _name << " has changed size, from " - << old_xsize << " " << old_ysize << " to " - << _xsize << " " << _ysize << "\n"; - _texture_changed = true; - } - } -} - -void PTexture:: -read_header() { - // Open the file and read its header to determine its size. - if (_got_filename && _file_exists) { - if (!_read_header) { - _read_header = true; - _got_size = read_image_header(_filename, _xsize, _ysize, _zsize); - } - _read_header = true; - } -} - -bool PTexture:: -read_image_header(const Filename &filename, int &xsize, int &ysize, - int &zsize) { - PNMImageHeader header; - if (!header.read_header(filename)) { - nout << "Warning: cannot read texture " << filename << "\n"; - return false; - } - - xsize = header.get_x_size(); - ysize = header.get_y_size(); - zsize = header.get_num_channels(); - - return true; -} diff --git a/pandatool/src/egg-palettize-old/pTexture.h b/pandatool/src/egg-palettize-old/pTexture.h deleted file mode 100644 index df35e9ed05..0000000000 --- a/pandatool/src/egg-palettize-old/pTexture.h +++ /dev/null @@ -1,111 +0,0 @@ -// Filename: pTexture.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef PTEXTURE_H -#define PTEXTURE_H - -#include - -#include - -#include -#include - -class Palette; -class PNMImage; -class AttribFile; -class PaletteGroup; -class TexturePacking; -class TextureEggRef; - -//////////////////////////////////////////////////////////////////// -// Class : PTexture -// Description : A single texture filename, as read from an egg file -// or from a .txa file. This may be considered for -// palettization on a number of different groups, but it -// must have the same size in each group. -//////////////////////////////////////////////////////////////////// -class PTexture { -public: - PTexture(AttribFile *attrib_file, const Filename &name); - ~PTexture(); - - Filename get_name() const; - - void add_filename(Filename filename); - - bool get_size(int &xsize, int &ysize, int &zsize); - void set_size(int xsize, int ysize, int zsize); - - bool get_req(int &xsize, int &ysize); - bool get_last_req(int &xsize, int &ysize); - void set_last_req(int xsize, int ysize); - void reset_req(int xsize, int ysize); - void scale_req(double scale_pct); - void clear_req(); - double get_scale_pct(); - - int get_margin() const; - void set_margin(int margin); - - void user_omit(); - - TexturePacking *add_to_group(PaletteGroup *group); - TexturePacking *check_group(PaletteGroup *group) const; - - void set_changed(bool changed); - - bool matched_anything() const; - void set_matched_anything(bool matched_anything); - bool is_unused() const; - - void write_size(ostream &out); - void write_pathname(ostream &out) const; - - PNMImage *read_image(); - - typedef set Eggs; - Eggs _eggs; - -private: - void check_size(); - void read_header(); - bool read_image_header(const Filename &filename, - int &xsize, int &ysize, int &zsize); - - Filename _name; - - typedef set Filenames; - Filenames _filenames; - - bool _got_filename; - Filename _filename; - bool _file_exists; - bool _texture_changed; - bool _matched_anything; - - bool _got_size; - int _xsize, _ysize; - int _zsize; - - bool _got_req; - int _req_xsize, _req_ysize; - bool _got_last_req; - int _last_req_xsize, _last_req_ysize; - int _margin; - bool _omit; - - bool _read_header; - - AttribFile *_attrib_file; - - typedef map Packing; - Packing _packing; - - friend class TexturePacking; -}; - - -#endif diff --git a/pandatool/src/egg-palettize-old/palette.cxx b/pandatool/src/egg-palettize-old/palette.cxx deleted file mode 100644 index 8a83ee9ebe..0000000000 --- a/pandatool/src/egg-palettize-old/palette.cxx +++ /dev/null @@ -1,591 +0,0 @@ -// Filename: palette.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "palette.h" -#include "paletteGroup.h" -#include "pTexture.h" -#include "texturePacking.h" -#include "attribFile.h" -#include "string_utils.h" - -#include -#include -#include - -bool Palette::TexturePlacement:: -intersects(int hleft, int htop, int xsize, int ysize) const { - int hright = hleft + xsize; - int hbot = htop + ysize; - - int mright = _left + _xsize; - int mbot = _top + _ysize; - - return - !(hleft >= mright || hright <= _left || - htop >= mbot || hbot <= _top); -} - -PNMImage *Palette::TexturePlacement:: -resize_image(PNMImage *source) const { - // Compute need_*size to account for the (interior) margins. - // However, if the size of the texture if very small, we want to - // make exterior margins, so we won't reduce the size past a certain - // point. - int need_xsize = min(_xsize, max(_xsize - 2 * _margin, 8)); - int need_ysize = min(_ysize, max(_ysize - 2 * _margin, 8)); - - if (source->get_x_size() == need_xsize && source->get_y_size() == need_ysize) { - // The image is already the right size. - return source; - } - - PNMImage *new_image = - new PNMImage(need_xsize, need_ysize, source->get_color_type()); - new_image->gaussian_filter_from(0.5, *source); - delete source; - return new_image; -} - -PNMImage *Palette::TexturePlacement:: -add_margins(PNMImage *source) const { - if (_margin == 0) { - // No margins to add. - return source; - } - - int orig_xsize = source->get_x_size(); - int orig_ysize = source->get_y_size(); - - int need_xsize = orig_xsize + _margin * 2; - int need_ysize = orig_ysize + _margin * 2; - - PNMImage *new_image = - new PNMImage(need_xsize, need_ysize, source->get_color_type()); - new_image->copy_sub_image(*source, _margin, _margin); - - // Now extend the margin out to the sides. - for (int i = 0; i < _margin; i++) { - for (int x = 0; x < orig_xsize; x++) { - // top edge - new_image->set_xel(x + _margin, i, source->get_xel(x, 0)); - // bottom edge - new_image->set_xel(x + _margin, need_ysize - 1 - i, - source->get_xel(x, orig_ysize - 1)); - } - for (int y = 0; y < orig_ysize; y++) { - // left edge - new_image->set_xel(i, y + _margin, source->get_xel(0, y)); - // right edge - new_image->set_xel(need_xsize - 1 - i, y + _margin, - source->get_xel(orig_xsize - 1, y)); - } - - for (int j = 0; j < _margin; j++) { - // top-left corner - new_image->set_xel(i, j, source->get_xel(0, 0)); - // top-right corner - new_image->set_xel(need_xsize - 1 - i, j, - source->get_xel(orig_xsize - 1, 0)); - // bottom-left corner - new_image->set_xel(i, need_ysize - 1 - j, - source->get_xel(0, orig_ysize - 1)); - // bottom-right corner - new_image->set_xel(need_xsize - 1 - i, need_ysize - 1 - j, - source->get_xel(orig_xsize - 1, orig_ysize - 1)); - } - } - - if (source->has_alpha()) { - // Now do the same thing in the alpha channel. - for (int i = 0; i < _margin; i++) { - for (int x = 0; x < orig_xsize; x++) { - // top edge - new_image->set_alpha(x + _margin, i, source->get_alpha(x, 0)); - // bottom edge - new_image->set_alpha(x + _margin, need_ysize - 1 - i, - source->get_alpha(x, orig_ysize - 1)); - } - for (int y = 0; y < orig_ysize; y++) { - // left edge - new_image->set_alpha(i, y + _margin, source->get_alpha(0, y)); - // right edge - new_image->set_alpha(need_xsize - 1 - i, y + _margin, - source->get_alpha(orig_xsize - 1, y)); - } - - for (int j = 0; j < _margin; j++) { - // top-left corner - new_image->set_alpha(i, j, source->get_alpha(0, 0)); - // top-right corner - new_image->set_alpha(need_xsize - 1 - i, j, - source->get_alpha(orig_xsize - 1, 0)); - // bottom-left corner - new_image->set_alpha(i, need_ysize - 1 - j, - source->get_alpha(0, orig_ysize - 1)); - // bottom-right corner - new_image->set_alpha(need_xsize - 1 - i, need_ysize - 1 - j, - source->get_alpha(orig_xsize - 1, orig_ysize - 1)); - } - } - } - - delete source; - return new_image; -} - - - -Palette:: -Palette(const Filename &filename, PaletteGroup *group, - int xsize, int ysize, int components, AttribFile *attrib_file) : - _filename(filename), - _group(group), - _xsize(xsize), - _ysize(ysize), - _components(components), - _attrib_file(attrib_file) -{ - _index = -1; - _palette_changed = false; - _new_palette = false; - _uses_alpha = (_components == 2 || _components == 4); -} - -Palette:: -Palette(PaletteGroup *group, int index, - int xsize, int ysize, int components, AttribFile *attrib_file) : - _group(group), - _index(index), - _xsize(xsize), - _ysize(ysize), - _components(components), - _attrib_file(attrib_file) -{ - _palette_changed = false; - _new_palette = true; - _uses_alpha = (_components == 2 || _components == 4); -} - -Palette:: -~Palette() { - // Unmark any textures we've had packed. - TexPlace::iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - (*ti)._packing->mark_unpacked(); - } -} - -Filename Palette:: -get_filename() const { - return _filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: Palette::has_alpha_filename -// Access: Public -// Description: Returns true if this texture requires a separate -// alpha image file. -//////////////////////////////////////////////////////////////////// -bool Palette:: -has_alpha_filename() const { - return _uses_alpha && (_attrib_file->_alpha_type != (PNMFileType *)NULL); -} - -//////////////////////////////////////////////////////////////////// -// Function: Palette::get_alpha_filename -// Access: Public -// Description: Returns the filename for the alpha channel to which -// this texture will be copied, assuming it is not -// placed on a palette. -//////////////////////////////////////////////////////////////////// -Filename Palette:: -get_alpha_filename() const { - return _attrib_file->make_alpha_filename(_filename); -} - -Filename Palette:: -get_basename() const { - return _basename; -} - -bool Palette:: -changed() const { - return _palette_changed; -} - -bool Palette:: -new_palette() const { - return _new_palette; -} - -int Palette:: -get_num_textures() const { - return _texplace.size(); -} - -bool Palette:: -check_uses_alpha() const { - // Returns true if any texture in the palette uses alpha. - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - if ((*ti)._packing->uses_alpha()) { - return true; - } - } - - return false; -} - -void Palette:: -get_size(int &xsize, int &ysize) const { - xsize = _xsize; - ysize = _ysize; -} - - -void Palette:: -place_texture_at(TexturePacking *packing, int left, int top, - int xsize, int ysize, int margin) { - nassertv(_group != (PaletteGroup *)NULL); - TexturePlacement tp; - tp._packing = packing; - tp._left = left; - tp._top = top; - tp._xsize = xsize; - tp._ysize = ysize; - tp._margin = margin; - _texplace.push_back(tp); - - packing->mark_pack_location(this, left, top, xsize, ysize, margin); -} - -bool Palette:: -pack_texture(TexturePacking *packing) { - PTexture *texture = packing->get_texture(); - int xsize, ysize; - if (!texture->get_req(xsize, ysize)) { - return false; - } - - int left, top; - if (find_home(left, top, xsize, ysize)) { - place_texture_at(packing, left, top, xsize, ysize, texture->get_margin()); - _palette_changed = true; - return true; - } - return false; -} - -bool Palette:: -unpack_texture(TexturePacking *packing) { - TexPlace::iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - if ((*ti)._packing == packing) { - _texplace.erase(ti); - packing->mark_unpacked(); - return true; - } - } - return false; -} - -// Attempt to shrink the palette down to the smallest possible (power -// of 2) size that includes all its textures. -void Palette:: -optimal_resize() { - if (_texplace.size() < 2) { - // If we don't have at least two textures, there's no point in - // shrinking the palette because we won't be using it anyway. - // Might as well keep it full-sized so we can better pack future - // textures. - return; - } - - int max_y = get_max_y(); - assert(max_y > 0); - bool resized = false; - - while (max_y <= _ysize / 2) { - // If at least half the palette is empty, we can try resizing. - if (max_y <= _ysize / 4) { - // Wow, three-quarters of the palette is empty. - Palette *np = try_resize(_xsize / 2, _ysize / 2); - if (np != NULL) { - // Excellent! We just reduced the palette size by half in - // both dimensions. - _texplace = np->_texplace; - _xsize = _xsize / 2; - _ysize = _ysize / 2; - _palette_changed = true; - delete np; - } else { - // Well, we couldn't reduce in both dimensions, but we can - // always reduce twice in the y dimension. - _ysize = _ysize / 4; - } - } else { - _ysize = _ysize / 2; - } - resized = true; - max_y = get_max_y(); - } - - assert(get_max_y() <= _ysize); - - if (resized) { - nout << "Resizing " << get_basename() << " to " << _xsize << " " - << _ysize << "\n"; - // If we've resized the palette, all the egg files that reference - // these textures will need to be rebuilt. - TexPlace::iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - (*ti)._packing->set_changed(true); - } - - // And we'll have to mark the palette as a new image. - _new_palette = true; - } -} - - -void Palette:: -finalize_palette() { - if (_filename.empty()) { - // Generate a filename based on the index number. - char index_str[128]; - sprintf(index_str, "%03d", _index); - _basename = _group->get_name() + "-palette." + index_str + ".rgb"; - _basename = _attrib_file->make_color_filename(_basename); - - Filename dirname = _group->get_full_dirname(_attrib_file); - _filename = _basename; - _filename.set_dirname(dirname.get_fullpath()); - } else { - _filename = _attrib_file->make_color_filename(_filename); - _basename = _filename.get_basename(); - } - - _uses_alpha = check_uses_alpha(); - _components = _uses_alpha ? 4 : 3; - - if (_texplace.size() == 1) { - // If we packed exactly one texture, never mind. - TexturePacking *packing = (*_texplace.begin())._packing; - - // This is a little odd: we mark the texture as being omitted, but - // we don't actually unpack it. That way it will still be - // recorded as belonging to this palette (for future - // palettizations), but it will also be copied to the map - // directory, and any egg files that reference it will use the - // texture and not the palette. - packing->set_omit(OR_solitary); - } -} - -void Palette:: -write(ostream &out) const { - out << "palette " << _attrib_file->write_pi_filename(_filename) - << " in " << _group->get_name() - << " size " << _xsize << " " << _ysize << " " << _components - << "\n"; - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - out << " " << (*ti)._packing->get_texture()->get_name() - << " at " << (*ti)._left << " " << (*ti)._top - << " size " << (*ti)._xsize << " " << (*ti)._ysize - << " margin " << (*ti)._margin - << "\n"; - } -} - -bool Palette:: -generate_image() { - bool okflag = true; - - PNMImage palette(_xsize, _ysize, _components); - - nout << "Generating " << _filename << "\n"; - - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - TexturePacking *packing = (*ti)._packing; - PTexture *texture = packing->get_texture(); - nout << " " << texture->get_name() << "\n"; - okflag = copy_texture_image(palette, *ti) && okflag; - } - - _filename.make_dir(); - if (!_attrib_file->write_image_file(palette, _filename, get_alpha_filename())) { - nout << "Error in writing.\n"; - okflag = false; - } - - return okflag; -} - -bool Palette:: -refresh_image() { - if (!_filename.exists()) { - nout << "Palette image " << _filename << " does not exist, rebuilding.\n"; - return generate_image(); - } - Filename alpha_filename = get_alpha_filename(); - if (has_alpha_filename() && !alpha_filename.exists()) { - nout << "Palette alpha image " << alpha_filename - << " does not exist, rebuilding.\n"; - return generate_image(); - } - - bool okflag = true; - - PNMImage palette; - if (!_attrib_file->read_image_file(palette, _filename, alpha_filename)) { - nout << "Unable to read old palette image " << _filename - << ", rebuilding.\n"; - return generate_image(); - } - - bool any_changed = false; - - if (_components == 4 && !palette.has_alpha()) { - palette.add_alpha(); - palette.alpha_fill(1.0); - any_changed = true; - - } else if (_components == 3 && palette.has_alpha()) { - palette.remove_alpha(); - any_changed = true; - } - - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - TexturePacking *packing = (*ti)._packing; - PTexture *texture = packing->get_texture(); - if (packing->needs_refresh()) { - if (!any_changed) { - nout << "Refreshing " << _filename << "\n"; - any_changed = true; - } - - nout << " " << texture->get_name() << "\n"; - okflag = copy_texture_image(palette, *ti) && okflag; - } - } - - if (any_changed) { - if (!_attrib_file->write_image_file(palette, _filename, alpha_filename)) { - nout << "Error in writing.\n"; - okflag = false; - } - } - - return okflag; -} - - -Palette *Palette:: -try_resize(int new_xsize, int new_ysize) const { - Palette *np = - new Palette(_group, _index, new_xsize, new_ysize, - _components, _attrib_file); - - bool okflag = true; - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); - ti != _texplace.end() && okflag; - ++ti) { - okflag = np->pack_texture((*ti)._packing); - } - - if (okflag) { - return np; - } else { - delete np; - return NULL; - } -} - -int Palette:: -get_max_y() const { - int max_y = 0; - - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); ti != _texplace.end(); ++ti) { - max_y = max(max_y, (*ti)._top + (*ti)._ysize); - } - - return max_y; -} - -bool Palette:: -find_home(int &left, int &top, int xsize, int ysize) const { - top = 0; - while (top + ysize <= _ysize) { - int next_y = _ysize; - // Scan along the row at 'top'. - left = 0; - while (left + xsize <= _xsize) { - int next_x = left; - // Consider the spot at left, top. - - // Can we place it here? - bool place_ok = true; - TexPlace::const_iterator ti; - for (ti = _texplace.begin(); - ti != _texplace.end() && place_ok; - ++ti) { - if ((*ti).intersects(left, top, xsize, ysize)) { - // Nope. - place_ok = false; - next_x = (*ti)._left + (*ti)._xsize; - next_y = min(next_y, (*ti)._top + (*ti)._ysize); - } - } - - if (place_ok) { - // Hooray! - return true; - } - - assert(next_x > left); - left = next_x; - } - - assert(next_y > top); - top = next_y; - } - - // Nope, wouldn't fit anywhere. - return false; -} - -bool Palette:: -copy_texture_image(PNMImage &palette, const TexturePlacement &tp) { - bool okflag = true; - PTexture *texture = tp._packing->get_texture(); - PNMImage *image = texture->read_image(); - if (image == NULL) { - nout << " *** Unable to read " << texture->get_name() << "\n"; - okflag = false; - - // Create a solid red texture for images we can't read. - image = new PNMImage(tp._xsize, tp._ysize); - image->fill(1.0, 0.0, 0.0); - - } else { - image = tp.add_margins(tp.resize_image(image)); - } - - if (_components == 4 && !image->has_alpha()) { - // We need to add an alpha channel for the image if the - // palette has an alpha channel. - image->add_alpha(); - image->alpha_fill(1.0); - } - palette.copy_sub_image(*image, tp._left, tp._top); - delete image; - - return okflag; -} diff --git a/pandatool/src/egg-palettize-old/palette.h b/pandatool/src/egg-palettize-old/palette.h deleted file mode 100644 index 8ce827e584..0000000000 --- a/pandatool/src/egg-palettize-old/palette.h +++ /dev/null @@ -1,100 +0,0 @@ -// Filename: palette.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef PALETTE_H -#define PALETTE_H - -#include - -#include - -#include - -class PaletteGroup; -class TexturePacking; -class PNMImage; -class AttribFile; - -//////////////////////////////////////////////////////////////////// -// Class : Palette -// Description : A single palettized image file within a palette -// group. This represents one page of all the -// palettized textures within this group; there might be -// multiple Palette images within a single group, -// depending on the number and size of the palettized -// textures. -//////////////////////////////////////////////////////////////////// -class Palette { -public: - Palette(const Filename &filename, PaletteGroup *group, - int xsize, int ysize, int components, AttribFile *attrib_file); - Palette(PaletteGroup *group, int index, - int xsize, int ysize, int components, AttribFile *attrib_file); - ~Palette(); - - Filename get_filename() const; - bool has_alpha_filename() const; - Filename get_alpha_filename() const; - Filename get_basename() const; - - PaletteGroup *get_group() const; - - bool changed() const; - bool new_palette() const; - int get_num_textures() const; - - bool check_uses_alpha() const; - - void get_size(int &xsize, int &ysize) const; - - void place_texture_at(TexturePacking *packing, int left, int top, - int xsize, int ysize, int margin); - - bool pack_texture(TexturePacking *packing); - bool unpack_texture(TexturePacking *packing); - - void optimal_resize(); - - void finalize_palette(); - - void write(ostream &out) const; - - bool generate_image(); - bool refresh_image(); - -private: - class TexturePlacement { - public: - bool intersects(int left, int top, int xsize, int ysize) const; - PNMImage *resize_image(PNMImage *source) const; - PNMImage *add_margins(PNMImage *source) const; - - TexturePacking *_packing; - int _left, _top; - int _xsize, _ysize, _margin; - }; - - Palette *try_resize(int new_xsize, int new_ysize) const; - int get_max_y() const; - bool find_home(int &left, int &top, int xsize, int ysize) const; - bool copy_texture_image(PNMImage &palette, const TexturePlacement &tp); - - - typedef vector TexPlace; - TexPlace _texplace; - - Filename _filename; - Filename _basename; - PaletteGroup *_group; - int _index; - int _xsize, _ysize, _components; - bool _uses_alpha; - bool _palette_changed; - bool _new_palette; - - AttribFile *_attrib_file; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/paletteGroup.cxx b/pandatool/src/egg-palettize-old/paletteGroup.cxx deleted file mode 100644 index f8a5b883b2..0000000000 --- a/pandatool/src/egg-palettize-old/paletteGroup.cxx +++ /dev/null @@ -1,316 +0,0 @@ -// Filename: paletteGroup.cxx -// Created by: drose (06Nov00) -// -//////////////////////////////////////////////////////////////////// - -#include "paletteGroup.h" -#include "texturePacking.h" -#include "palette.h" -#include "attribFile.h" - -#include // for sprintf() - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PaletteGroup:: -PaletteGroup(const string &name) : Namable(name) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -PaletteGroup:: -~PaletteGroup() { - clear_palettes(); -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::get_num_parents -// Access: Public -// Description: Returns the number of dependent PaletteGroup this -// PaletteGroup can share its textures with. See -// get_parent(). -//////////////////////////////////////////////////////////////////// -int PaletteGroup:: -get_num_parents() const { - return _parents.size(); -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::get_parent -// Access: Public -// Description: Returns the nth dependent PaletteGroup this -// PaletteGroup can share its textures with. If a -// texture is added to this group that already appears -// one of these groups, the reference to the shared -// texture is used instead of adding a new texture. -//////////////////////////////////////////////////////////////////// -PaletteGroup *PaletteGroup:: -get_parent(int n) const { - nassertr(n >= 0 && n < (int)_parents.size(), (PaletteGroup *)NULL); - return _parents[n]; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::add_parent -// Access: Public -// Description: Adds a new PaletteGroup to the set of PaletteGroups -// this one can share its textures with. See -// get_parent(). -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -add_parent(PaletteGroup *parent) { - _parents.push_back(parent); -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::get_dirname -// Access: Public -// Description: Returns the directory name to which palettes and -// textures associated with this group will be written. -//////////////////////////////////////////////////////////////////// -const string &PaletteGroup:: -get_dirname() const { - return _dirname; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::set_dirname -// Access: Public -// Description: Sets the directory name to which palettes and -// textures associated with this group will be written. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -set_dirname(const string &dirname) { - _dirname = dirname; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::get_full_dirname -// Access: Public -// Description: Computes the actual directory name to which palettes -// and textures should be written, based on -// get_dirname() and on the -dm parameter. -//////////////////////////////////////////////////////////////////// -string PaletteGroup:: -get_full_dirname(AttribFile *attrib_file) const { - char buffer[4096]; - sprintf(buffer, attrib_file->_map_dirname.c_str(), _dirname.c_str()); - return buffer; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::pack_texture -// Access: Public -// Description: Adds the texture to some suitable palette image -// within the PaletteGroup. Returns true if -// successfully packed, false otherwise. -//////////////////////////////////////////////////////////////////// -bool PaletteGroup:: -pack_texture(TexturePacking *packing, AttribFile *attrib_file) { - // Now try to place it in each of our existing palettes. - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - if ((*pi)->pack_texture(packing)) { - return true; - } - } - - // It didn't place anywhere; create a new palette for it. - Palette *palette = - new Palette(this, _palettes.size() + 1, - attrib_file->_pal_xsize, attrib_file->_pal_ysize, - 0, attrib_file); - if (!palette->pack_texture(packing)) { - // Hmm, it didn't fit on an empty palette. Must be too big. - packing->set_omit(OR_size); - delete palette; - return false; - } - _palettes.push_back(palette); - - return true; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::generate_palette_images -// Access: Public -// Description: After all of the textures has been placed, generates -// the actual image files for each palette image within -// the group. Returns true if successful, false on -// error. -//////////////////////////////////////////////////////////////////// -bool PaletteGroup:: -generate_palette_images() { - bool okflag = true; - - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - Palette *palette = (*pi); - if (palette->new_palette()) { - // If the palette is a new palette, we'll have to generate a new - // image from scratch. - okflag = palette->generate_image() && okflag; - } else { - // Otherwise, we can probably get by with just updating - // whichever images, if any, have changed. - okflag = palette->refresh_image() && okflag; - } - } - - return okflag; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::optimal_resize -// Access: Public -// Description: Resizes each palette image within the group downward, -// if possible, to the smallest power-of-two size that -// holds all of its images. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -optimal_resize() { - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - (*pi)->optimal_resize(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::finalize_palettes -// Access: Public -// Description: Performs some finalization of the palette images, -// such as generating filenames. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -finalize_palettes() { - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - (*pi)->finalize_palette(); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::add_palette -// Access: Public -// Description: Adds the indicated already-created Palette image to -// the group. This is mainly intended to be called from -// AttribFile when reading in a previously-built .pi -// file. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -add_palette(Palette *palette) { - _palettes.push_back(palette); -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::remove_palette_files -// Access: Public -// Description: Removes all the image files generated for the Palette -// images within the group. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -remove_palette_files() { - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - // Remove the old palette file? - Palette *palette = *pi; - if (!palette->get_filename().empty()) { - if (palette->get_filename().exists()) { - nout << "Deleting " << palette->get_filename() << "\n"; - palette->get_filename().unlink(); - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::clear_palettes -// Access: Public -// Description: Deletes all of the Palette objects within the group. -// This loses all information about where textures are -// packed. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -clear_palettes() { - Palettes::iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - delete *pi; - } - _palettes.clear(); -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::complete_groups -// Access: Public, Static -// Description: Expands the set of PaletteGroups to include all -// parents and parents of parents. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -complete_groups(PaletteGroups &groups) { - // Make a copy so we can safely modify the original set as we - // traverse the copy. - PaletteGroups groups_copy = groups; - PaletteGroups::const_iterator gi; - for (gi = groups_copy.begin(); gi != groups_copy.end(); ++gi) { - (*gi)->add_ancestors(groups); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::add_ancestors -// Access: Public -// Description: Adds all the ancestors of this PaletteGroup to the -// indicated set. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -add_ancestors(PaletteGroups &groups) { - Parents::const_iterator pri; - for (pri = _parents.begin(); pri != _parents.end(); ++pri) { - PaletteGroup *parent = *pri; - bool inserted = groups.insert(parent).second; - if (inserted) { - parent->add_ancestors(groups); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::write_pi -// Access: Public -// Description: Writes out a .pi file description of the group. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -write_pi(ostream &out) const { - if (_dirname.empty() && _palettes.empty()) { - // No real reason to write this group out. - return; - } - - out << "group " << get_name(); - if (!_dirname.empty()) { - out << " dir " << _dirname; - } - out << "\n"; -} - -//////////////////////////////////////////////////////////////////// -// Function: PaletteGroup::write_palettes -// Access: Public -// Description: Writes out a .pi file description of all of the -// individual Palette images. -//////////////////////////////////////////////////////////////////// -void PaletteGroup:: -write_palettes_pi(ostream &out) const { - Palettes::const_iterator pi; - for (pi = _palettes.begin(); pi != _palettes.end(); ++pi) { - out << "\n"; - (*pi)->write(out); - } -} diff --git a/pandatool/src/egg-palettize-old/paletteGroup.h b/pandatool/src/egg-palettize-old/paletteGroup.h deleted file mode 100644 index 23d1efd28b..0000000000 --- a/pandatool/src/egg-palettize-old/paletteGroup.h +++ /dev/null @@ -1,87 +0,0 @@ -// Filename: paletteGroup.h -// Created by: drose (06Nov00) -// -//////////////////////////////////////////////////////////////////// - -#ifndef PALETTEGROUP_H -#define PALETTEGROUP_H - -#include - -#include - -#include -#include - -class Palette; -class TexturePacking; -class AttribFile; -class PaletteGroup; - -typedef set PaletteGroups; - -//////////////////////////////////////////////////////////////////// -// Class : PaletteGroup -// Description : A named collection of textures. This is a group of -// textures that are to be palettized together as a -// unit; all of these textures are expected to be loaded -// into texture memory at one time. The PaletteGroup -// consists of a number of discrete Palette images, as -// many as are necessary to represent all of the -// textures within the PaletteGroup that are to be -// palettized. -// -// A PaletteGroup is also associated with one or more -// other PaletteGroups, which are assumed to be -// available in texture memory whenever this -// PaletteGroup is. If a texture is to be placed on -// this PaletteGroup that already exists on one of the -// dependent PaletteGroups, it is not placed; instead, -// it is referenced directly from the other -// PaletteGroup. This allows an intelligent sharing of -// textures between palettes with a minimum of wasted -// space. -//////////////////////////////////////////////////////////////////// -class PaletteGroup : public Namable { -public: - PaletteGroup(const string &name); - ~PaletteGroup(); - - int get_num_parents() const; - PaletteGroup *get_parent(int n) const; - void add_parent(PaletteGroup *parent); - - const string &get_dirname() const; - void set_dirname(const string &dirname); - - string get_full_dirname(AttribFile *attrib_file) const; - - bool pack_texture(TexturePacking *packing, AttribFile *attrib_file); - bool generate_palette_images(); - void optimal_resize(); - void finalize_palettes(); - - void add_palette(Palette *palette); - - void remove_palette_files(); - void clear_palettes(); - - static void complete_groups(PaletteGroups &groups); - void add_ancestors(PaletteGroups &groups); - - void write_pi(ostream &out) const; - void write_palettes_pi(ostream &out) const; - -private: - typedef vector Parents; - Parents _parents; - - typedef vector Palettes; - Palettes _palettes; - - string _dirname; -}; - - -#endif - diff --git a/pandatool/src/egg-palettize-old/sourceEgg.cxx b/pandatool/src/egg-palettize-old/sourceEgg.cxx deleted file mode 100644 index dbc6f21a20..0000000000 --- a/pandatool/src/egg-palettize-old/sourceEgg.cxx +++ /dev/null @@ -1,496 +0,0 @@ -// Filename: sourceEgg.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "sourceEgg.h" -#include "pTexture.h" -#include "textureEggRef.h" -#include "texturePacking.h" -#include "paletteGroup.h" -#include "eggPalettize.h" -#include "string_utils.h" -#include "palette.h" - -#include -#include -#include -#include -#include -#include - -#include - -TypeHandle SourceEgg::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -SourceEgg:: -SourceEgg(AttribFile *attrib_file) : _attrib_file(attrib_file) { - _matched_anything = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::add_texture -// Access: Public -// Description: Adds a new texture to the set of textures known by -// the egg file. -//////////////////////////////////////////////////////////////////// -TextureEggRef *SourceEgg:: -add_texture(PTexture *texture, TexturePacking *packing, - bool repeats, bool alpha) { - TextureEggRef *ref = - new TextureEggRef(this, texture, packing, repeats, alpha); - _texrefs.insert(ref); - texture->_eggs.insert(ref); - return ref; -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::get_textures -// Access: Public -// Description: Examines the egg file for all of the texture -// references and assigns each texture to a suitable -// palette group. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -get_textures(EggPalettize *prog) { - TexRefs::iterator tri; - for (tri = _texrefs.begin(); tri != _texrefs.end(); ++tri) { - TextureEggRef *texref = (*tri); - texref->_texture->_eggs.erase(texref); - } - _texrefs.clear(); - - EggTextureCollection tc; - tc.find_used_textures(this); - - EggTextureCollection::iterator ti; - for (ti = tc.begin(); ti != tc.end(); ++ti) { - EggTexture *eggtex = (*ti); - string name = eggtex->get_filename().get_basename(); - - PTexture *texture = _attrib_file->get_texture(name); - texture->add_filename(eggtex->get_filename()); - - bool repeats = - eggtex->get_wrap_mode() == EggTexture::WM_repeat || - eggtex->get_wrap_u() == EggTexture::WM_repeat || - eggtex->get_wrap_v() == EggTexture::WM_repeat; - - bool repeat_unspecified = - eggtex->get_wrap_mode() == EggTexture::WM_unspecified && - eggtex->get_wrap_u() == EggTexture::WM_unspecified && - eggtex->get_wrap_v() == EggTexture::WM_unspecified; - - bool alpha = false; - - EggAlphaMode::AlphaMode alpha_mode = eggtex->get_alpha_mode(); - if (alpha_mode == EggAlphaMode::AM_unspecified) { - int xsize, ysize, zsize; - if (texture->get_size(xsize, ysize, zsize)) { - alpha = eggtex->has_alpha_channel(zsize); - } - - } else if (alpha_mode == EggAlphaMode::AM_off) { - alpha = false; - - } else { - alpha = true; - } - - // Check the range of UV's actually used within the egg file. - bool any_uvs = false; - TexCoordd min_uv, max_uv; - get_uv_range(this, eggtex, any_uvs, min_uv, max_uv); - - // Now we need to apply the texture matrix, if there is one, to - // our bounding box UV's. - - if (eggtex->has_transform()) { - // Transforming a bounding box by a matrix requires transforming - // all four corners. - - TexCoordd a(min_uv[0], min_uv[1]); - TexCoordd b(min_uv[0], max_uv[1]); - TexCoordd c(max_uv[0], max_uv[1]); - TexCoordd d(max_uv[0], min_uv[1]); - - LMatrix3d transform = eggtex->get_transform(); - - a = a * transform; - b = b * transform; - c = c * transform; - d = d * transform; - - // Now boil down these four corners into a new bounding box. - - min_uv.set(min(min(a[0], b[0]), min(c[0], d[0])), - min(min(a[1], b[1]), min(c[1], d[1]))); - max_uv.set(max(max(a[0], b[0]), max(c[0], d[0])), - max(max(a[1], b[1]), max(c[1], d[1]))); - } - - bool truly_repeats = - (max_uv[0] > 1.0 + prog->_fuzz_factor || - min_uv[0] < 0.0 - prog->_fuzz_factor || - max_uv[1] > 1.0 + prog->_fuzz_factor || - min_uv[1] < 0.0 - prog->_fuzz_factor); - - if (repeat_unspecified) { - // If the egg file didn't give us any advice regarding - // repeating, we can go entirely based on what we saw in the - // UV's. - repeats = truly_repeats; - - } else { - if (repeats && !truly_repeats) { - // The egg file specified that the texture repeats, but we - // discovered that it doesn't really. Quietly mark it so. - if (!prog->_dont_override_repeats) { - repeats = false; - } - - } else if (!repeats && truly_repeats) { - // The egg file specified that the texture doesn't repeat, but - // its UV's were outside the normal range! That's almost - // certainly a modeling error. - - // We won't trouble the user with this kind of spammy message, - // though. - /* - nout << "Warning: texture " << texture->get_name() << " (tref " - << eggtex->name << ") marked clamped, but UV's range from (" - << min_uv << ") to (" << max_uv << ")\n"; - */ - - } else if (repeats && truly_repeats) { - // Well, it really does repeat. Or does it? - if (fabs(max_uv[0] - min_uv[0]) <= 1.0 + prog->_fuzz_factor && - fabs(max_uv[1] - min_uv[1]) <= 1.0 + prog->_fuzz_factor) { - // It really shouldn't! The UV's fit totally within a unit - // square, just not the square (0,0) - (1,1). This is a - // modeling problem; inform the user. - nout << "Warning: texture " << texture->get_name() - << " cannot be clamped because UV's range from (" - << min_uv << ") to (" << max_uv << ")\n"; - } - } - } - - TextureEggRef *texref = add_texture(texture, (TexturePacking *)NULL, - repeats, alpha); - texref->_eggtex = eggtex; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::add_group -// Access: Public -// Description: Adds the indicated group to the set of groups known -// to be required for the egg file. Typically this is -// done from the .pi file. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -add_group(PaletteGroup *group) { - _groups.insert(group); -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::require_groups -// Access: Public -// Description: Ensures that each texture in the egg file is packed -// into at least one of the indicated groups. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -require_groups(PaletteGroup *preferred, const PaletteGroups &groups) { - _groups = groups; - TexRefs::iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - (*ti)->require_groups(preferred, groups); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::all_textures_assigned -// Access: Public -// Description: Ensures that each texture in the egg file is packed -// into at least one group, any group. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -all_textures_assigned() { - PaletteGroup *default_group; - - if (_groups.empty()) { - default_group = _attrib_file->get_default_group(); - _groups.insert(default_group); - } else { - default_group = *(_groups.begin()); - } - - TexRefs::iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - (*ti)->require_groups(default_group, _groups); - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::mark_texture_flags -// Access: Public -// Description: Updates each PTexture with the flags stored in the -// various egg files. Also marks textures as used. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -mark_texture_flags() { - TexRefs::iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - TexturePacking *packing = (*ti)->_packing; - packing->set_unused(false); - if ((*ti)->_alpha) { - packing->set_uses_alpha(true); - } - if ((*ti)->_repeats) { - packing->set_omit(OR_repeats); - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::update_trefs -// Access: Public -// Description: Updates the egg file to point to the new palettes. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -update_trefs() { - TexRefs::iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - TexturePacking *packing = (*ti)->_packing; - PTexture *texture = packing->get_texture(); - EggTexture *eggtex = (*ti)->_eggtex; - - if (eggtex != NULL) { - // Make the alpha mode explicit if it isn't already. - - if (eggtex->get_alpha_mode() == EggTexture::AM_unspecified) { - int xsize, ysize, zsize; - if (texture->get_size(xsize, ysize, zsize)) { - if (eggtex->has_alpha_channel(zsize)) { - eggtex->set_alpha_mode(EggAlphaMode::AM_on); - } else { - eggtex->set_alpha_mode(EggAlphaMode::AM_off); - } - } - } - - if (!packing->is_packed() || - packing->get_omit() != OR_none) { - // This texture wasn't palettized, so just rename the - // reference to the new one. - eggtex->set_filename(_attrib_file->write_egg_filename(packing->get_new_filename())); - if (packing->has_alpha_filename()) { - eggtex->set_alpha_file(_attrib_file->write_egg_filename(packing->get_alpha_filename())); - } else { - eggtex->clear_alpha_file(); - } - - } else { - // This texture was palettized, so redirect the tref to point - // within the palette. - Palette *palette = packing->get_palette(); - - eggtex->set_filename(_attrib_file->write_egg_filename(palette->get_filename())); - if (palette->has_alpha_filename()) { - eggtex->set_alpha_file(_attrib_file->write_egg_filename(palette->get_alpha_filename())); - } else { - eggtex->clear_alpha_file(); - } - - // Set the texture attributes to be uniform across all palettes. - eggtex->set_minfilter(EggTexture::FT_linear_mipmap_linear); - eggtex->set_magfilter(EggTexture::FT_linear); - eggtex->set_format(EggTexture::F_rgba8); - eggtex->set_wrap_mode(EggTexture::WM_clamp); - eggtex->set_wrap_u(EggTexture::WM_clamp); - eggtex->set_wrap_v(EggTexture::WM_clamp); - - // Build a matrix that will scale the UV's to their new place - // on the palette. - int left, top, xsize, ysize, margin; - packing->get_packed_location(left, top); - packing->get_packed_size(xsize, ysize, margin); - - // Shrink the box to be within the margins. - top += margin; - left += margin; - xsize -= margin*2; - ysize -= margin*2; - - // Now determine the relative size and position within the - // palette. - int bottom = top + ysize; - int palx, paly; - palette->get_size(palx, paly); - LVecBase2d t((double)left / (double)palx, - (double)(paly - bottom) / (double)paly); - - LVecBase2d s((double)xsize / (double)palx, - (double)ysize / (double)paly); - - LMatrix3d texmat - (s[0], 0.0, 0.0, - 0.0, s[1], 0.0, - t[0], t[1], 1.0); - - // Do we already have a texture matrix? If so, compose them. - if (eggtex->has_transform()) { - eggtex->set_transform(eggtex->get_transform() * texmat); - } else { - // Otherwise, just store it. - eggtex->set_transform(texmat); - } - } - } - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::needs_rebuild -// Access: Public -// Description: Returns true if any of the textures referenced by the -// egg file have been adjusted this pass, implying that -// the egg file will have to be re-run through -// egg-palettize, and/or re-pfb'ed. -//////////////////////////////////////////////////////////////////// -bool SourceEgg:: -needs_rebuild(bool force_redo_all, - bool eggs_include_images) const { - // if (!_wrote_egg) { - TexRefs::const_iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - bool dirty = - eggs_include_images ? - (*ti)->_packing->needs_refresh() : - (*ti)->_packing->packing_changed(); - if (force_redo_all || dirty) { - return true; - } - } - // } - - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::matched_anything -// Access: Public -// Description: Returns true if the egg file matched at least one -// line in the .txa file, false otherwise. -//////////////////////////////////////////////////////////////////// -bool SourceEgg:: -matched_anything() const { - return _matched_anything; -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::set_matched_anything -// Access: Public -// Description: Sets the state of the matched_anything flag. See -// matched_anything(). -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -set_matched_anything(bool matched_anything) { - _matched_anything = matched_anything; -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::write_pi -// Access: Public -// Description: Writes the entry for this egg file to the .pi file. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -write_pi(ostream &out) const { - Filename filename = _attrib_file->write_pi_filename(get_egg_filename()); - out << "egg " << filename << " in"; - PaletteGroups::const_iterator gi; - for (gi = _groups.begin(); gi != _groups.end(); ++gi) { - out << " " << (*gi)->get_name(); - } - out << "\n"; - - TexRefs::const_iterator ti; - for (ti = _texrefs.begin(); ti != _texrefs.end(); ++ti) { - out << " " << (*ti)->_packing->get_texture()->get_name() - << " in " << (*ti)->_packing->get_group()->get_name(); - if ((*ti)->_repeats) { - out << " repeats"; - } - if ((*ti)->_alpha) { - out << " alpha"; - } - out << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: SourceEgg::get_uv_range -// Access: Private -// Description: Checks the geometry in the egg file to see what range -// of UV's are requested for this particular texture -// reference. -//////////////////////////////////////////////////////////////////// -void SourceEgg:: -get_uv_range(EggGroupNode *group, EggTexture *tref, - bool &any_uvs, TexCoordd &min_uv, TexCoordd &max_uv) { - EggGroupNode::iterator ci; - - for (ci = group->begin(); ci != group->end(); ci++) { - EggNode *child = (*ci); - if (child->is_of_type(EggNurbsSurface::get_class_type())) { - EggNurbsSurface *nurbs = DCAST(EggNurbsSurface, child); - if (nurbs->has_texture() && nurbs->get_texture() == tref) { - // Here's a NURBS surface that references the texture. Unlike - // other kinds of geometries, NURBS don't store UV's; they're - // implicit in the surface. NURBS UV's will always run in the - // range (0,0) - (1,1). - if (any_uvs) { - min_uv.set(min(min_uv[0], 0.0), min(min_uv[1], 0.0)); - max_uv.set(max(max_uv[0], 1.0), max(max_uv[1], 1.0)); - } else { - min_uv.set(0.0, 0.0); - max_uv.set(1.0, 1.0); - any_uvs = true; - } - } - - } else if (child->is_of_type(EggPrimitive::get_class_type())) { - EggPrimitive *geom = DCAST(EggPrimitive, child); - if (geom->has_texture() && geom->get_texture() == tref) { - // Here's a piece of geometry that references this texture. - // Walk through its vertices at get its UV's. - EggPrimitive::iterator pi; - for (pi = geom->begin(); pi != geom->end(); ++pi) { - EggVertex *vtx = (*pi); - if (vtx->has_uv()) { - const TexCoordd &uv = vtx->get_uv(); - if (any_uvs) { - min_uv.set(min(min_uv[0], uv[0]), min(min_uv[1], uv[1])); - max_uv.set(max(max_uv[0], uv[0]), max(max_uv[1], uv[1])); - } else { - // The first UV. - min_uv = uv; - max_uv = uv; - any_uvs = true; - } - } - } - } - - } else if (child->is_of_type(EggGroupNode::get_class_type())) { - EggGroupNode *cg = DCAST(EggGroupNode, child); - get_uv_range(cg, tref, any_uvs, min_uv, max_uv); - } - } -} diff --git a/pandatool/src/egg-palettize-old/sourceEgg.h b/pandatool/src/egg-palettize-old/sourceEgg.h deleted file mode 100644 index 52a749b4ca..0000000000 --- a/pandatool/src/egg-palettize-old/sourceEgg.h +++ /dev/null @@ -1,79 +0,0 @@ -// Filename: sourceEgg.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef SOURCEGG_H -#define SOURCEGG_H - -#include - -#include "paletteGroup.h" - -#include -#include - -class PTexture; -class TexturePacking; -class AttribFile; -class EggPalettize; -class EggTexture; -class EggGroup; -class TextureEggRef; - -class SourceEgg : public EggData { -public: - SourceEgg(AttribFile *attrib_file); - - TextureEggRef *add_texture(PTexture *texture, TexturePacking *packing, - bool repeats, bool alpha); - void get_textures(EggPalettize *prog); - - void add_group(PaletteGroup *group); - void require_groups(PaletteGroup *preferred, const PaletteGroups &groups); - void all_textures_assigned(); - - void mark_texture_flags(); - void update_trefs(); - - bool needs_rebuild(bool force_redo_all, - bool eggs_include_images) const; - - bool matched_anything() const; - void set_matched_anything(bool matched_anything); - - void write_pi(ostream &out) const; - - - typedef set TexRefs; - TexRefs _texrefs; - -private: - void get_uv_range(EggGroupNode *group, EggTexture *tref, - bool &any_uvs, TexCoordd &min_uv, TexCoordd &max_uv); - - - AttribFile *_attrib_file; - bool _matched_anything; - - PaletteGroups _groups; - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - EggData::init_type(); - register_type(_type_handle, "SourceEgg", - EggData::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/string_utils.cxx b/pandatool/src/egg-palettize-old/string_utils.cxx deleted file mode 100644 index 97b507f64d..0000000000 --- a/pandatool/src/egg-palettize-old/string_utils.cxx +++ /dev/null @@ -1,80 +0,0 @@ -// Filename: string_utils.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "string_utils.h" - - -string -trim_left(const string &str) { - size_t begin = 0; - while (begin < str.size() && isspace(str[begin])) { - begin++; - } - - return str.substr(begin); -} - -string -trim_right(const string &str) { - size_t begin = 0; - size_t end = str.size(); - while (end > begin && isspace(str[end - 1])) { - end--; - } - - return str.substr(begin, end - begin); -} - -vector_string -extract_words(const string &str) { - vector_string result; - - size_t pos = 0; - while (pos < str.length() && isspace(str[pos])) { - pos++; - } - while (pos < str.length()) { - size_t word_start = pos; - while (pos < str.length() && !isspace(str[pos])) { - pos++; - } - result.push_back(str.substr(word_start, pos - word_start)); - - while (pos < str.length() && isspace(str[pos])) { - pos++; - } - } - - return result; -} - -// Extracts the first word of the string into param, and the remainder -// of the line into value. -void -extract_param_value(const string &str, string ¶m, string &value) { - size_t i = 0; - - // First, skip all whitespace at the beginning. - while (i < str.length() && isspace(str[i])) { - i++; - } - - size_t start = i; - - // Now skip to the end of the whitespace. - while (i < str.length() && !isspace(str[i])) { - i++; - } - - size_t end = i; - - param = str.substr(start, end - start); - - // Skip a little bit further to the start of the value. - while (i < str.length() && isspace(str[i])) { - i++; - } - value = trim_right(str.substr(i)); -} diff --git a/pandatool/src/egg-palettize-old/string_utils.h b/pandatool/src/egg-palettize-old/string_utils.h deleted file mode 100644 index 417dfa3110..0000000000 --- a/pandatool/src/egg-palettize-old/string_utils.h +++ /dev/null @@ -1,21 +0,0 @@ -// Filename: string_utils.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef STRING_UTILS_H -#define STRING_UTILS_H - -#include -#include - -#include - -string trim_left(const string &str); -string trim_right(const string &str); - -vector_string extract_words(const string &str); -void extract_param_value(const string &str, string ¶m, string &value); - -#endif - diff --git a/pandatool/src/egg-palettize-old/textureEggRef.cxx b/pandatool/src/egg-palettize-old/textureEggRef.cxx deleted file mode 100644 index 5b3547b916..0000000000 --- a/pandatool/src/egg-palettize-old/textureEggRef.cxx +++ /dev/null @@ -1,69 +0,0 @@ -// Filename: textureEggRef.cxx -// Created by: drose (08Nov00) -// -//////////////////////////////////////////////////////////////////// - -#include "textureEggRef.h" -#include "texturePacking.h" -#include "pTexture.h" - -#include - -#include - -//////////////////////////////////////////////////////////////////// -// Function: TextureEggRef::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -TextureEggRef:: -TextureEggRef(SourceEgg *egg, PTexture *texture, TexturePacking *packing, - bool repeats, bool alpha) : - _egg(egg), - _texture(texture), - _packing(packing), - _repeats(repeats), - _alpha(alpha) -{ - _eggtex = NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureEggRef::require_groups -// Access: Public -// Description: Indicates the set of PaletteGroups that this texture -// (as appearing on this egg file) wants to be listed -// on. If the texture is already listed on one of these -// groups, does nothing; otherwise, moves the texture. -//////////////////////////////////////////////////////////////////// -void TextureEggRef:: -require_groups(PaletteGroup *preferred, const PaletteGroups &groups) { - nassertv(!groups.empty()); - - if (_packing != (TexturePacking *)NULL) { - PaletteGroup *now_on = _packing->get_group(); - if (groups.count(now_on) != 0) { - // The group we're on is on the list; no problem. - return; - } - } - - // Has the texture already been packed into any of the groups? - PaletteGroups::const_iterator gi; - for (gi = groups.begin(); gi != groups.end(); ++gi) { - TexturePacking *packing = _texture->check_group(*gi); - if (packing != (TexturePacking *)NULL) { - // It has, use that group. - _packing = packing; - return; - } - } - - // We need to pack the texture into one of the requested groups. - - // For now, we arbitrarily pick the preferred group. Later, maybe - // we'll try to be smart about this and do some kind of graph - // minimization to choose the group that leads to the least - // redundant packing. - _packing = _texture->add_to_group(preferred); -} diff --git a/pandatool/src/egg-palettize-old/textureEggRef.h b/pandatool/src/egg-palettize-old/textureEggRef.h deleted file mode 100644 index eb0738ca32..0000000000 --- a/pandatool/src/egg-palettize-old/textureEggRef.h +++ /dev/null @@ -1,43 +0,0 @@ -// Filename: textureEggRef.h -// Created by: drose (08Nov00) -// -//////////////////////////////////////////////////////////////////// - -#ifndef TEXTUREEGGREF_H -#define TEXTUREEGGREF_H - -#include - -#include "paletteGroup.h" - -#include - -class SourceEgg; -class PTexture; -class TexturePacking; -class EggTexture; - -//////////////////////////////////////////////////////////////////// -// Class : TextureEggRef -// Description : This associates a texture with the egg files it is -// placed on, and also associates an egg file with the -// various textures it contains. -//////////////////////////////////////////////////////////////////// -class TextureEggRef { -public: - TextureEggRef(SourceEgg *egg, PTexture *texture, - TexturePacking *packing, - bool repeats, bool alpha); - - void require_groups(PaletteGroup *preferred, const PaletteGroups &groups); - - SourceEgg *_egg; - PTexture *_texture; - TexturePacking *_packing; - bool _repeats; - bool _alpha; - - EggTexture *_eggtex; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/textureOmitReason.h b/pandatool/src/egg-palettize-old/textureOmitReason.h deleted file mode 100644 index 8e45f5955f..0000000000 --- a/pandatool/src/egg-palettize-old/textureOmitReason.h +++ /dev/null @@ -1,26 +0,0 @@ -// Filename: textureOmitReason.h -// Created by: drose (06Nov00) -// -//////////////////////////////////////////////////////////////////// - -#ifndef TEXTUREOMITREASON_H -#define TEXTUREOMITREASON_H - -#include - -//////////////////////////////////////////////////////////////////// -// Enum : TextureOmitReason -// Description : This enumerates the various reasons a texture might -// have been omitted from a palette. -//////////////////////////////////////////////////////////////////// -enum TextureOmitReason { - OR_none, // No reason: not omitted - OR_size, // Too big to put on a palette - OR_repeats, // The texture repeats and can't be palettized - OR_omitted, // Explicitly omitted by user in .txa file - OR_unused, // Not used by any egg files - OR_unknown, // The texture file is unknown, so can't determine its size - OR_solitary // Would be palettized, but no other textures are on the palette. -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/texturePacking.cxx b/pandatool/src/egg-palettize-old/texturePacking.cxx deleted file mode 100644 index 5a0fb8dc70..0000000000 --- a/pandatool/src/egg-palettize-old/texturePacking.cxx +++ /dev/null @@ -1,614 +0,0 @@ -// Filename: texturePacking.cxx -// Created by: drose (06Nov00) -// -//////////////////////////////////////////////////////////////////// - -#include "texturePacking.h" -#include "paletteGroup.h" -#include "attribFile.h" -#include "palette.h" -#include "pTexture.h" - -#include - - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::Constructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -TexturePacking:: -TexturePacking(PTexture *texture, PaletteGroup *group) : - _texture(texture), - _group(group) -{ - _attrib_file = _texture->_attrib_file; - _omit = _texture->_omit ? OR_omitted : OR_none; - _unused = true; - _uses_alpha = false; - _is_packed = false; - _palette = NULL; - _packing_changed = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::Destructor -// Access: Public -// Description: -//////////////////////////////////////////////////////////////////// -TexturePacking:: -~TexturePacking() { -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_texture -// Access: Public -// Description: Returns the texture this TexturePacking object refers -// to. -//////////////////////////////////////////////////////////////////// -PTexture *TexturePacking:: -get_texture() const { - return _texture; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_group -// Access: Public -// Description: Returns the palette group this TexturePacking object -// refers to. -//////////////////////////////////////////////////////////////////// -PaletteGroup *TexturePacking:: -get_group() const { - return _group; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_omit -// Access: Public -// Description: Returns the reason this texture was omitted from the -// particular palette group, if it was. -//////////////////////////////////////////////////////////////////// -TextureOmitReason TexturePacking:: -get_omit() const { - return _omit; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::set_omit -// Access: Public -// Description: Indicates the reason this texture was omitted from -// the particular palette group, if it was. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -set_omit(TextureOmitReason omit) { - _omit = omit; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::unused -// Access: Public -// Description: Returns true if this particular texture/group -// combination seems to be unused by any egg files, -// false if at least one egg file uses it. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -unused() const { - return _unused; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::set_unused -// Access: Public -// Description: Sets the state of the unused flag. See unused(). -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -set_unused(bool unused) { - _unused = unused; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::uses_alpha -// Access: Public -// Description: Returns true if this texture seems to require alpha; -// that is, at least one egg file that references the -// texture specifies an alpha mode. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -uses_alpha() const { - return _uses_alpha; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::set_uses_alpha -// Access: Public -// Description: Sets the state of the uses_alpha flag. See -// uses_alpha(). -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -set_uses_alpha(bool uses_alpha) { - _uses_alpha = uses_alpha; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::pack -// Access: Public -// Description: Adds this texture to its appropriate palette group, -// if it has not already been packed. Returns true if -// anything has changed (e.g. it has been packed), false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -pack() { - if (!_is_packed) { - return _group->pack_texture(this, _attrib_file); - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::unpack -// Access: Public -// Description: Removes this texture from its palette image if it is -// on one. Returns true if anything has changed -// (e.g. it has been unpacked), false otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -unpack() { - if (_is_packed) { - return _palette->unpack_texture(this); - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::prepare_repack -// Access: Public -// Description: Checks if the texture needs to be repacked into a -// different location on the palette (for instance, -// because it has changed size). If so, unpacks it and -// returns true; otherwise, leaves it alone and returns -// false. -// -// If unpacking it will leave a hole or some similar -// nonsense, also sets optimal to false. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -prepare_repack(bool &optimal) { - bool needs_repack = false; - - if (get_omit() == OR_none) { - // Here's a texture that thinks it wants to be packed. Does it? - int xsize, ysize; - int pal_xsize = _attrib_file->_pal_xsize; - int pal_ysize = _attrib_file->_pal_ysize; - if (!_texture->get_req(xsize, ysize)) { - // If we don't know the texture's size, we can't place it. - nout << "Warning! Can't determine size of " << _texture->get_name() - << "\n"; - set_omit(OR_unknown); - - } else if ((xsize > pal_xsize || ysize > pal_ysize) || - (xsize == pal_xsize && ysize == pal_ysize)) { - // If the texture is too big for the palette (or exactly fills the - // palette), we can't place it. - set_omit(OR_size); - - } else { - // Ok, this texture really does want to be packed. Is it? - int px, py, m; - if (get_packed_size(px, py, m)) { - // The texture is packed. Does it have the right size? - if (px != xsize || py != ysize) { - // Oops, we'll have to repack it. - unpack(); - optimal = false; - needs_repack = true; - } - if (m != _texture->get_margin()) { - // The margin has changed, although not the size. We - // won't have to repack it, but we do need to update it. - _texture->set_changed(true); - } - } else { - // The texture isn't packed. Need to pack it. - needs_repack = true; - } - } - } - - if (get_omit() != OR_none) { - // Here's a texture that doesn't want to be packed. Is it? - if (unpack()) { - // It was! Not any more. - optimal = false; - } - } - - return needs_repack; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::mark_pack_location -// Access: Public -// Description: Records the location at which the texture has been -// packed. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -mark_pack_location(Palette *palette, int left, int top, - int xsize, int ysize, int margin) { - _is_packed = true; - _palette = palette; - _pleft = left; - _ptop = top; - _pxsize = xsize; - _pysize = ysize; - _pmargin = margin; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::mark_unpacked -// Access: Public -// Description: Records that the texture has not been packed. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -mark_unpacked() { - _is_packed = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::is_packed -// Access: Public -// Description: Returns true if the texture has been packed, false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -is_packed() const { - return _is_packed; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::is_really_packed -// Access: Public -// Description: Returns the same thing as is_packed(), except it -// doesn't consider a texture that has been left alone -// on a palette to be packed. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -is_really_packed() const { - return _is_packed && _omit != OR_solitary; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_palette -// Access: Public -// Description: Returns the particular palette image the texture has -// been packed into, or NULL if the texture is unpacked. -//////////////////////////////////////////////////////////////////// -Palette *TexturePacking:: -get_palette() const { - return _is_packed ? _palette : (Palette *)NULL; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_packed_location -// Access: Public -// Description: Fills left and top with the upper-left corner of the -// rectangle in which the texture has been packed within -// its Palette image. Returns true if the texture has -// been packed, false otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -get_packed_location(int &left, int &top) const { - left = _pleft; - top = _ptop; - return _is_packed; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_packed_size -// Access: Public -// Description: Fills xsize, ysize, and margin with the size of the -// rectangle in which the texture has been packed within -// its Palette image. The margin is an interior margin. -// Returns true if the texture has been packed, false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -get_packed_size(int &xsize, int &ysize, int &margin) const { - xsize = _pxsize; - ysize = _pysize; - margin = _pmargin; - return _is_packed; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::record_orig_state -// Access: Public -// Description: Records the current packing state, storing it aside -// as the state at load time. Later, when the packing -// state may have changed, packing_changed() will return -// true if it has or false if it has not. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -record_orig_state() { - _orig_is_packed = _is_packed; - if (_is_packed) { - _orig_palette_name = _palette->get_filename(); - _opleft = _pleft; - _optop = _ptop; - _opxsize = _pxsize; - _opysize = _pysize; - _opmargin = _pmargin; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::packing_changed -// Access: Public -// Description: Returns true if the packing has changed in any way -// since the last call to record_orig_state(), false -// otherwise. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -packing_changed() const { - if (_orig_is_packed != _is_packed) { - return true; - } - if (_is_packed) { - return _orig_palette_name != _palette->get_filename() || - _opleft != _pleft || - _optop != _ptop || - _opxsize != _pxsize || - _opysize != _pysize || - _opmargin != _pmargin; - } - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::set_changed -// Access: Public -// Description: Sets the state of the changed flag. If this is true, -// the state of this texture on this group is known to -// have changed in some way such that files that depend -// on it will need to be rebuilt. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -set_changed(bool changed) { - _packing_changed = changed; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::needs_refresh -// Access: Public -// Description: Returns true if the texture has changed in any -// significant way and the palette it's placed on needs -// to be regenerated. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -needs_refresh() { - bool any_change = - _texture->_texture_changed || _packing_changed; - - if (!any_change) { - // We consider the texture to be out-of-date if it's moved around - // in the palette. - any_change = packing_changed(); - } - - if (!any_change && _texture->_file_exists) { - // Compare the texture's timestamp to that of its palette (or - // resized copy). If it's newer, it's changed and must be - // replaced. - - Filename target_filename; - if (is_packed() && _omit == OR_none) { - // Compare to the palette file. - target_filename = _palette->get_filename(); - if (_palette->new_palette()) { - // It's a brand new palette; don't even bother comparing - // timestamps. - any_change = true; - } - - } else { - // Compare to the resized file. - target_filename = get_new_filename(); - - if (has_alpha_filename()) { - // If we have an alpha file, compare to the older of the two - // files. - Filename alpha_filename = get_alpha_filename(); - if (target_filename.compare_timestamps(alpha_filename, true, true) > 0) { - target_filename = alpha_filename; - } - } - } - - if (!any_change) { - any_change = - (target_filename.compare_timestamps(get_old_filename(), true, false) < 0); - } - } - - return any_change; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::write_unplaced -// Access: Public -// Description: Writes an "unplaced" entry to the .pi file if this -// texture has not been placed on the group, describing -// the reason for the failure. -//////////////////////////////////////////////////////////////////// -void TexturePacking:: -write_unplaced(ostream &out) const { - if (_omit != OR_none && _omit != OR_unused) { - out << "unplaced " << _texture->get_name() - << " in " << _group->get_name() << " because "; - switch (_omit) { - case OR_size: - out << "size"; - break; - case OR_repeats: - out << "repeats"; - break; - case OR_omitted: - out << "omitted"; - break; - case OR_unused: - out << "unused"; - break; - case OR_unknown: - out << "unknown"; - break; - case OR_solitary: - out << "solitary"; - break; - default: - nout << "Invalid type: " << (int)_omit << "\n"; - abort(); - } - out << "\n"; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_new_filename -// Access: Public -// Description: Returns the filename to which this texture will be -// copied, assuming it is not placed on a palette. -//////////////////////////////////////////////////////////////////// -Filename TexturePacking:: -get_new_filename() const { - Filename dirname = _group->get_full_dirname(_attrib_file); - Filename new_filename(dirname, _texture->get_name()); - new_filename = _attrib_file->make_color_filename(new_filename); - new_filename.standardize(); - return new_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::has_alpha_filename -// Access: Public -// Description: Returns true if this texture requires a separate -// alpha image file. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -has_alpha_filename() const { - return _uses_alpha && (_attrib_file->_alpha_type != (PNMFileType *)NULL); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_alpha_filename -// Access: Public -// Description: Returns the filename for the alpha channel to which -// this texture will be copied, assuming it is not -// placed on a palette. -//////////////////////////////////////////////////////////////////// -Filename TexturePacking:: -get_alpha_filename() const { - return _attrib_file->make_alpha_filename(get_new_filename()); -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::get_old_filename -// Access: Public -// Description: Returns the original filename of this texture. -//////////////////////////////////////////////////////////////////// -Filename TexturePacking:: -get_old_filename() const { - Filename old_filename = _texture->_filename; - old_filename.standardize(); - return old_filename; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::transfer -// Access: Public -// Description: Copies an unpalettized image to the install -// directory, if it is not already there. The -// particular directory it is installed into may depend -// on the PaletteGroup to which it has been added. -// Returns true if successful, false if there is an -// error. -//////////////////////////////////////////////////////////////////// -bool TexturePacking:: -transfer() { - bool okflag = true; - - Filename old_filename = get_old_filename(); - Filename new_filename = get_new_filename(); - if (new_filename == old_filename) { - nout << "*** Texture " << _texture->get_name() - << " is already in the map directory!\n" - << " Cannot modify texture in place!\n"; - return false; - } - - int nx, ny; - if (!_texture->get_req(nx, ny)) { - nout << "Unknown size for image " << _texture->get_name() << "\n"; - nx = 16; - ny = 16; - } - - if (_attrib_file->_force_power_2) { - int newx = to_power_2(nx); - int newy = to_power_2(ny); - if (newx != nx || newy != ny) { - nx = newx; - ny = newy; - } - } - - PNMImage *image = _texture->read_image(); - if (image == NULL) { - nout << "*** Unable to read " << _texture->get_name() << "\n"; - okflag = false; - - // Create a solid red texture for images we can't read. - image = new PNMImage(nx, ny); - image->fill(1.0, 0.0, 0.0); - - } else { - // Should we scale it? - if (nx != image->get_x_size() || ny != image->get_y_size()) { - nout << "Resizing " << new_filename << " to " - << nx << " " << ny << "\n"; - PNMImage *new_image = - new PNMImage(nx, ny, image->get_color_type()); - new_image->gaussian_filter_from(0.5, *image); - delete image; - image = new_image; - - } else { - nout << "Copying " << new_filename - << " (size " << nx << " " << ny << ")\n"; - } - } - - new_filename.make_dir(); - if (!_attrib_file->write_image_file(*image, new_filename, get_alpha_filename())) { - nout << "Error in writing.\n"; - okflag = false; - } - delete image; - - return okflag; -} - -//////////////////////////////////////////////////////////////////// -// Function: TexturePacking::to_power_2 -// Access: Public, Static -// Description: Returns the largest power of 2 less than or equal to -// value. -//////////////////////////////////////////////////////////////////// -int TexturePacking:: -to_power_2(int value) { - int x = 1; - while ((x << 1) <= value) { - x = (x << 1); - } - return x; -} diff --git a/pandatool/src/egg-palettize-old/texturePacking.h b/pandatool/src/egg-palettize-old/texturePacking.h deleted file mode 100644 index 88994dfc4f..0000000000 --- a/pandatool/src/egg-palettize-old/texturePacking.h +++ /dev/null @@ -1,90 +0,0 @@ -// Filename: texturePacking.h -// Created by: drose (06Nov00) -// -//////////////////////////////////////////////////////////////////// - -#ifndef TEXTUREPACKING_H -#define TEXTUREPACKING_H - -#include - -#include "textureOmitReason.h" - -#include - -class PTexture; -class PaletteGroup; -class Palette; -class AttribFile; - -//////////////////////////////////////////////////////////////////// -// Class : TexturePacking -// Description : This structure defines how a particular texture is -// packed into a Palette image, or even whether it is -// packed at all. -//////////////////////////////////////////////////////////////////// -class TexturePacking { -public: - TexturePacking(PTexture *texture, PaletteGroup *group); - ~TexturePacking(); - - PTexture *get_texture() const; - PaletteGroup *get_group() const; - - TextureOmitReason get_omit() const; - void set_omit(TextureOmitReason omit); - - bool unused() const; - void set_unused(bool unused); - - bool uses_alpha() const; - void set_uses_alpha(bool uses_alpha); - - bool pack(); - bool unpack(); - bool prepare_repack(bool &optimal); - - void mark_pack_location(Palette *palette, int left, int top, - int xsize, int ysize, int margin); - void mark_unpacked(); - bool is_packed() const; - bool is_really_packed() const; - Palette *get_palette() const; - bool get_packed_location(int &left, int &top) const; - bool get_packed_size(int &xsize, int &ysize, int &margin) const; - void record_orig_state(); - bool packing_changed() const; - - void set_changed(bool changed); - bool needs_refresh(); - - void write_unplaced(ostream &out) const; - - Filename get_new_filename() const; - bool has_alpha_filename() const; - Filename get_alpha_filename() const; - Filename get_old_filename() const; - bool transfer(); - -private: - static int to_power_2(int value); - - AttribFile *_attrib_file; - PTexture *_texture; - PaletteGroup *_group; - TextureOmitReason _omit; - bool _unused; - bool _uses_alpha; - - bool _is_packed; - Palette *_palette; - int _pleft, _ptop, _pxsize, _pysize, _pmargin; - - bool _orig_is_packed; - Filename _orig_palette_name; - int _opleft, _optop, _opxsize, _opysize, _opmargin; - - bool _packing_changed; -}; - -#endif diff --git a/pandatool/src/egg-palettize-old/userAttribLine.cxx b/pandatool/src/egg-palettize-old/userAttribLine.cxx deleted file mode 100644 index 13056c75d4..0000000000 --- a/pandatool/src/egg-palettize-old/userAttribLine.cxx +++ /dev/null @@ -1,504 +0,0 @@ -// Filename: userAttribLine.cxx -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#include "userAttribLine.h" -#include "string_utils.h" -#include "pTexture.h" -#include "paletteGroup.h" -#include "sourceEgg.h" -#include "attribFile.h" -#include "textureEggRef.h" - -#include - -#include - -UserAttribLine:: -UserAttribLine(const string &cline, AttribFile *af) : _attrib_file(af) { - _is_old_style = false; - - // By default, all lines are marked 'was_used'. That means they'll - // be preserved across a -k on the command line. Lines that name - // textures will have _was_used set false until a texture actually - // matches that line. - _was_used = true; - - _got_dirname = false; - - string line = cline; - - // First, strip off the comment. - if (!line.empty()) { - if (line[0] == '#') { - _comment = line; - line = ""; - } else { - size_t pos = line.find(" #"); - if (pos != string::npos) { - while (pos > 0 && isspace(line[pos])) { - pos--; - } - _comment = line.substr(pos + 1); - line = line.substr(0, pos); - } - } - } - - // Now, analyze the line. - _line_type = LT_invalid; - _xsize = 0; - _ysize = 0; - _scale_pct = 0.0; - _msize = -1; - _omit = false; - - bool is_valid = true; - if (line.empty()) { - _line_type = LT_comment; - - } else if (line[0] == ':') { - is_valid = keyword_line(line); - - } else { - is_valid = texture_line(line); - } - - if (!is_valid) { - _line_type = LT_invalid; - } -} - -UserAttribLine:: -~UserAttribLine() { -} - -bool UserAttribLine:: -is_valid() const { - return _line_type != LT_invalid; -} - -bool UserAttribLine:: -is_old_style() const { - return _is_old_style; -} - -bool UserAttribLine:: -was_used() const { - return _was_used; -} - -void UserAttribLine:: -write(ostream &out) const { - int i; - - switch (_line_type) { - case LT_invalid: - out << "*** invalid line ***\n"; - break; - - case LT_comment: - break; - - case LT_margin: - out << ":margin " << _msize; - break; - - case LT_palette: - out << ":palette " << _xsize << " " << _ysize; - break; - - case LT_group_relate: - out << ":group " << _names[0]; - if (!_got_dirname) { - out << " dir " << _dirname; - } - if (!_names.empty()) { - out << " with"; - for (i = 1; i < (int)_names.size(); i++) { - out << " " << _names[i]; - } - } - out << "\n"; - break; - - case LT_size: - list_patterns(out) << " : " << _xsize << " " << _ysize; - if (_msize > 0) { - out << " " << _msize; - } - if (_omit) { - out << " omit"; - } - break; - - case LT_scale: - list_patterns(out) << " : " << _scale_pct << "%"; - if (_msize > 0) { - out << " " << _msize; - } - if (_omit) { - out << " omit"; - } - break; - - case LT_name: - list_patterns(out) << " :"; - if (_omit) { - out << " omit"; - } - break; - - case LT_group_assign: - list_patterns(out) << " : "; - list_names(out); - break; - - default: - nout << "Unexpected type: " << (int)_line_type << "\n"; - abort(); - }; - - out << _comment << "\n"; -} - -bool UserAttribLine:: -get_size_request(PTexture *texture, int &margin) { - if (_line_type == LT_group_assign) { - // We don't care about group lines for the size check. - return false; - } - - // See if the texture name matches any of the filename patterns on - // this line. - string texture_name = texture->get_name(); - - bool matched_any = false; - Patterns::const_iterator pi; - for (pi = _patterns.begin(); - pi != _patterns.end() && !matched_any; - ++pi) { - if ((*pi).matches(texture_name)) { - matched_any = true; - } - - // Also check if it matches any of the egg files this texture is - // on. - PTexture::Eggs::const_iterator ei; - for (ei = texture->_eggs.begin(); - ei != texture->_eggs.end() && !matched_any; - ++ei) { - string egg_name = (*ei)->_egg->get_egg_filename().get_basename(); - if ((*pi).matches(egg_name)) { - matched_any = true; - } - } - } - - if (matched_any) { - _was_used = true; - - // It does! So do the right thing with this line. - switch (_line_type) { - case LT_invalid: - case LT_comment: - case LT_palette: - case LT_group_relate: - return false; - - case LT_margin: - margin = _msize; - return false; - - case LT_size: - texture->reset_req(_xsize, _ysize); - texture->set_margin(_msize < 0 ? margin : _msize); - if (_omit) { - texture->user_omit(); - } - return true; - - case LT_scale: - texture->scale_req(_scale_pct); - texture->set_margin(_msize < 0 ? margin : _msize); - if (_omit) { - texture->user_omit(); - } - return true; - - case LT_name: - if (_omit) { - texture->user_omit(); - } - return true; - - default: - nout << "Unexpected type: " << (int)_line_type << "\n"; - abort(); - } - } - - return false; -} - -bool UserAttribLine:: -get_group_request(SourceEgg *egg) { - if (_line_type != LT_group_assign) { - // We're only looking for group lines now. - return false; - } - - // See if the egg filename matches any of the filename patterns on - // this line. - string egg_name = egg->get_egg_filename().get_basename(); - - bool matched_any = false; - Patterns::const_iterator pi; - for (pi = _patterns.begin(); - pi != _patterns.end() && !matched_any; - ++pi) { - if ((*pi).matches(egg_name)) { - matched_any = true; - } - } - - if (matched_any) { - _was_used = true; - - // It does! Record the list of required groups with all of the - // textures on this egg file. - nassertr(!_names.empty(), false); - PaletteGroups groups; - Names::const_iterator ni = _names.begin(); - PaletteGroup *group = _attrib_file->get_group(*ni); - groups.insert(group); - - // The first-named group is preferred for any textures not already - // on another group. - PaletteGroup *preferred = group; - - while (ni != _names.end()) { - group = _attrib_file->get_group(*ni); - groups.insert(group); - ++ni; - } - PaletteGroup::complete_groups(groups); - egg->require_groups(preferred, groups); - - return true; - } - - return false; -} - -ostream &UserAttribLine:: -list_patterns(ostream &out) const { - if (!_patterns.empty()) { - out << _patterns[0]; - for (int i = 1; i < (int)_patterns.size(); i++) { - out << " " << _patterns[i]; - } - } - return out; -} - -ostream &UserAttribLine:: -list_names(ostream &out) const { - if (!_names.empty()) { - out << _names[0]; - for (int i = 1; i < (int)_names.size(); i++) { - out << " " << _names[i]; - } - } - return out; -} - -bool UserAttribLine:: -keyword_line(const string &line) { - vector_string words = extract_words(line); - assert(!words.empty()); - - if (words[0] == ":margin") { - _line_type = LT_margin; - if (words.size() != 2) { - nout << "Expected margin size.\n"; - return false; - } - - _msize = atoi(words[1].c_str()); - - } else if (words[0] == ":palette") { - _line_type = LT_palette; - if (words.size() != 3) { - nout << "Expected :palette xsize ysize.\n"; - return false; - } - _xsize = atoi(words[1].c_str()); - _ysize = atoi(words[2].c_str()); - _attrib_file->_pal_xsize = _xsize; - _attrib_file->_pal_ysize = _ysize; - - } else if (words[0] == ":group") { - _line_type = LT_group_relate; - if (words.size() < 2) { - nout << "Expected :group name.\n"; - return false; - } - - PaletteGroup *group = _attrib_file->get_group(words[1]); - - int kw = 2; - while (kw < (int)words.size()) { - if (words[kw] == "with") { - kw++; - - while (kw < (int)words.size()) { - group->add_parent(_attrib_file->get_group(words[kw])); - kw++; - } - - } else if (words[kw] == "dir") { - kw++; - _got_dirname = true; - _dirname = words[kw]; - group->set_dirname(_dirname); - kw++; - - } else { - nout << "Invalid keyword: " << words[kw] << "\n"; - return false; - } - } - - } else { - nout << "Unknown keyword: " << words[0] << "\n"; - return false; - } - - return true; -} - -bool UserAttribLine:: -texture_line(const string &line) { - _was_used = false; - - // Scan for a colon followed by a space. - - size_t colon = line.find(": "); - if (colon == string::npos) { - return old_style_line(line); - } - - // Split the line into two parts at the colon. - vector_string names = extract_words(line.substr(0, colon)); - vector_string params = extract_words(line.substr(colon + 2)); - - vector_string::const_iterator ni; - for (ni = names.begin(); ni != names.end(); ++ni) { - _patterns.push_back(GlobPattern(*ni)); - } - - if (!params.empty() && params[params.size() - 1] == "omit") { - // If the last word is "omit", set the omit flag and remove the - // word. - _omit = true; - params.pop_back(); - } - - if (params.empty()) { - _line_type = LT_name; - return true; - } - - // Is it a group name? If it is, this is an assignment of a texture - // or egg file to one or more groups. - if (!params[0].empty() && isalpha(params[0][0])) { - _names = params; - _line_type = LT_group_assign; - return true; - } - - // Is it a percentage? - if (!params[0].empty() && params[0][params[0].size() - 1] == '%') { - _line_type = LT_scale; - _scale_pct = atof(params[0].c_str()); - if (_scale_pct <= 0.0) { - nout << "Invalid scale percentage for "; - copy(names.begin(), names.end(), ostream_iterator(nout, " ")); - nout << ": " << _scale_pct << "%\n"; - return false; - } - return true; - } - - // It must be xsize ysize [margin] - if (params.size() == 2) { - _line_type = LT_size; - _xsize = atoi(params[0].c_str()); - _ysize = atoi(params[1].c_str()); - if (_xsize <= 0 || _ysize <= 0) { - nout << "Invalid texture size for "; - copy(names.begin(), names.end(), ostream_iterator(nout, " ")); - nout << ": " << _xsize << " " << _ysize << "\n"; - return false; - } - return true; - } - - if (params.size() == 3) { - _line_type = LT_size; - _xsize = atoi(params[0].c_str()); - _ysize = atoi(params[1].c_str()); - _msize = atoi(params[2].c_str()); - if (_xsize <= 0 || _ysize <= 0) { - nout << "Invalid texture size for "; - copy(names.begin(), names.end(), ostream_iterator(nout, " ")); - nout << ": " << _xsize << " " << _ysize << "\n"; - return false; - } - return true; - } - - nout << "Expected xsize ysize [msize]\n"; - return false; -} - - -bool UserAttribLine:: -old_style_line(const string &line) { - vector_string words = extract_words(line); - assert(!words.empty()); - - if (words.size() != 3 && words.size() != 4) { - nout << "Colon omitted.\n"; - return false; - } - - _is_old_style = true; - _line_type = LT_size; - _patterns.push_back(GlobPattern(words[0])); - _xsize = atoi(words[1].c_str()); - _ysize = atoi(words[2].c_str()); - if (words.size() > 3) { - _msize = atoi(words[3].c_str()); - - if (_msize < 0) { - _msize = -1; - _omit = true; - - } else if (_msize == _attrib_file->_default_margin) { - _msize = -1; - } - } else { - _msize = -1; - } - - if (_xsize <= 0 || _ysize <= 0) { - nout << "Invalid texture size for " << words[0] << ": " - << _xsize << " " << _ysize << "\n"; - return false; - } - - return true; -} diff --git a/pandatool/src/egg-palettize-old/userAttribLine.h b/pandatool/src/egg-palettize-old/userAttribLine.h deleted file mode 100644 index ea2b6d4b31..0000000000 --- a/pandatool/src/egg-palettize-old/userAttribLine.h +++ /dev/null @@ -1,91 +0,0 @@ -// Filename: userAttribLine.h -// Created by: drose (02Sep99) -// -//////////////////////////////////////////////////////////////////// - -#ifndef USERATTRIBLINE_H -#define USERATTRIBLINE_H - -#include - -#include -#include - -#include - -class AttribFile; -class PTexture; -class SourceEgg; - -//////////////////////////////////////////////////////////////////// -// Class : UserAttribLine -// Description : A single entry in the .txa file, this defines how the -// user would like some particular texture to be scaled. -//////////////////////////////////////////////////////////////////// - -// -// This might be a line of any of the following forms: -// -// (blank line) -// # Comment -// :margin msize -// :palette xsize ysize -// :group groupname [dir dirname] [with groupname [groupname ...]] -// texturename xsize ysize msize -// texturename [texturename ...] : xsize ysize [msize] [omit] -// texturename [texturename ...] : scale% [msize] [omit] -// texturename [texturename ...] : [omit] -// texturename [texturename ...] : groupname [groupname ...] -// eggname [eggname ...] : groupname [groupname ...] -// - -class UserAttribLine { -public: - UserAttribLine(const string &line, AttribFile *af); - ~UserAttribLine(); - - bool is_valid() const; - bool is_old_style() const; - bool was_used() const; - - void write(ostream &out) const; - - bool get_size_request(PTexture *texture, int &margin); - bool get_group_request(SourceEgg *egg); - -private: - enum LineType { - LT_invalid, - LT_comment, - LT_margin, LT_palette, LT_group_relate, - LT_size, LT_scale, LT_name, - LT_group_assign - }; - - typedef vector Patterns; - Patterns _patterns; - typedef vector_string Names; - Names _names; - - ostream &list_patterns(ostream &out) const; - ostream &list_names(ostream &out) const; - bool keyword_line(const string &line); - bool texture_line(const string &line); - bool old_style_line(const string &line); - - string _comment; - LineType _line_type; - int _xsize, _ysize; - double _scale_pct; - int _msize; - string _dirname; - bool _got_dirname; - bool _omit; - bool _is_old_style; - bool _was_used; - - AttribFile *_attrib_file; -}; - - -#endif diff --git a/pandatool/src/eggbase/Sources.pp b/pandatool/src/eggbase/Sources.pp index 6f7aa8429e..1393ab626b 100644 --- a/pandatool/src/eggbase/Sources.pp +++ b/pandatool/src/eggbase/Sources.pp @@ -6,16 +6,25 @@ egg:c panda:m #define SOURCES \ - eggBase.cxx eggBase.h eggConverter.cxx eggConverter.h eggFilter.cxx \ - eggFilter.h eggMultiBase.cxx eggMultiBase.h \ + eggBase.cxx eggBase.h \ + eggCharacterData.cxx eggCharacterData.h eggCharacterData.I \ + eggCharacterFilter.cxx eggCharacterFilter.h \ + eggConverter.cxx eggConverter.h eggFilter.cxx \ + eggFilter.h eggJointData.cxx eggJointData.h eggJointData.I \ + eggMultiBase.cxx eggMultiBase.h \ eggMultiFilter.cxx eggMultiFilter.h \ - eggReader.cxx eggReader.h eggToSomething.cxx \ + eggReader.cxx eggReader.h \ + eggToSomething.cxx \ eggToSomething.h eggWriter.cxx eggWriter.h somethingToEgg.cxx \ somethingToEgg.h #define INSTALL_HEADERS \ - eggBase.h eggConverter.h eggFilter.h eggMultiBase.h eggMultiFilter.h \ - eggReader.h eggToSomething.h eggWriter.h somethingToEgg.h + eggBase.h eggCharacterData.h \ + eggCharacterData.I eggCharacterFilter.h \ + eggConverter.h eggFilter.h eggJointData.h eggJointData.I \ + eggMultiBase.h eggMultiFilter.h \ + eggReader.h \ + eggToSomething.h eggWriter.h somethingToEgg.h #end ss_lib_target diff --git a/pandatool/src/eggbase/eggCharacterData.I b/pandatool/src/eggbase/eggCharacterData.I new file mode 100644 index 0000000000..b58510ef70 --- /dev/null +++ b/pandatool/src/eggbase/eggCharacterData.I @@ -0,0 +1,27 @@ +// Filename: eggCharacterData.I +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_num_eggs +// Access: Public +// Description: Returns the number of egg files that have +// successfully been added to the Character table. +//////////////////////////////////////////////////////////////////// +INLINE int EggCharacterData:: +get_num_eggs() const { + return _eggs.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_egg +// Access: Public +// Description: Returns the ith egg file. +//////////////////////////////////////////////////////////////////// +INLINE EggData *EggCharacterData:: +get_egg(int i) const { + nassertr(i >= 0 && i < (int)_eggs.size(), (EggData *)NULL); + return _eggs[i]._egg; +} diff --git a/pandatool/src/eggbase/eggCharacterData.cxx b/pandatool/src/eggbase/eggCharacterData.cxx new file mode 100644 index 0000000000..73b9076d60 --- /dev/null +++ b/pandatool/src/eggbase/eggCharacterData.cxx @@ -0,0 +1,452 @@ +// Filename: eggCharacterData.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggCharacterData.h" +#include "eggJointData.h" +#include "eggGroup.h" +#include "eggTable.h" + +#include +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterData:: +EggCharacterData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterData:: +~EggCharacterData() { + Characters::iterator ci; + + for (ci = _characters.begin(); ci != _characters.end(); ++ci) { + CharacterInfo &character_info = (*ci); + delete character_info._root_joint; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::add_egg +// Access: Public +// Description: Adds a new egg file to the list of models and +// animation files for this particular character. +// Returns true if the file is successfully added, or +// false if there is some problem (for instance, it does +// not contain a character model or animation table). +// +// If the joint hierarchy does not match the existing +// joint hierarchy, a best match is attempted. +//////////////////////////////////////////////////////////////////// +bool EggCharacterData:: +add_egg(EggData *egg) { + _top_egg_nodes.clear(); + + if (!scan_hierarchy(egg)) { + return false; + } + + int egg_index = _eggs.size(); + _eggs.push_back(EggInfo()); + EggInfo &egg_info = _eggs.back(); + egg_info._egg = egg; + + // Now, for each model, add an entry in the egg_info and match the + // joint hierarchy to the known joints. + TopEggNodesByName::iterator tni; + for (tni = _top_egg_nodes.begin(); tni != _top_egg_nodes.end(); ++tni) { + string character_name = (*tni).first; + TopEggNodes &top_nodes = (*tni).second; + + TopEggNodes::iterator ti; + for (ti = top_nodes.begin(); ti != top_nodes.end(); ++ti) { + EggNode *model = (*ti).first; + EggNodeList &egg_nodes = (*ti).second; + + int model_index = egg_info._models.size(); + egg_info._models.push_back(model); + match_egg_nodes(get_root_joint(character_name), + egg_nodes, egg_index, model_index); + } + } + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::get_root_joint +// Access: Protected +// Description: Returns the root of the joint hierarchy for the named +// character. This is actually a fictitious node that +// does not correspond to any particular nodes in the +// character hierarchy; it exists to hold all of the top +// joints (if any) read from the character hierarchy. +//////////////////////////////////////////////////////////////////// +EggJointData *EggCharacterData:: +get_root_joint(const string &character_name) { + // Does the named character exist yet? + + Characters::iterator ci; + for (ci = _characters.begin(); ci != _characters.end(); ++ci) { + CharacterInfo &character_info = (*ci); + if (character_info._name == character_name) { + return character_info._root_joint; + } + } + + // Define a new character. + _characters.push_back(CharacterInfo()); + CharacterInfo &character_info = _characters.back(); + character_info._name = character_name; + character_info._root_joint = make_joint_data(); + return character_info._root_joint; +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::make_joint_data +// Access: Protected, Virtual +// Description: Allocates and returns a new EggJointData structure. +// This is primarily intended as a hook so derived +// classes can customize the type of EggJointData nodes +// used to represent the joint hierarchy. +//////////////////////////////////////////////////////////////////// +EggJointData *EggCharacterData:: +make_joint_data() { + return new EggJointData; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::scan_hierarchy +// Access: Private +// Description: Walks the given egg data's hierarchy, looking for +// either the start of an animation channel or the start +// of a character model. Returns true if either (or +// both) is found, false if the model appears to have +// nothing to do with characters. +// +// Fills up the _top_egg_nodes according to the nodes +// found. +//////////////////////////////////////////////////////////////////// +bool EggCharacterData:: +scan_hierarchy(EggNode *egg_node) { + if (egg_node->is_of_type(EggGroup::get_class_type())) { + EggGroup *group = DCAST(EggGroup, egg_node); + if (group->get_dart_type() != EggGroup::DT_none) { + // A group with a flag begins a character model. + scan_for_top_joints(group, group, group->get_name()); + return true; + } + + } else if (egg_node->is_of_type(EggTable::get_class_type())) { + EggTable *table = DCAST(EggTable, egg_node); + if (table->get_table_type() == EggTable::TT_bundle) { + // A begins an animation table. + scan_for_top_tables(table, table, table->get_name()); + return true; + } + } + + bool character_found = false; + if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *group = DCAST(EggGroupNode, egg_node); + EggGroupNode::iterator gi; + for (gi = group->begin(); gi != group->end(); ++gi) { + if (scan_hierarchy(*gi)) { + character_found = true; + } + } + } + + return character_found; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::scan_for_top_joints +// Access: Private +// Description: Once a character model has been found, continue +// scanning the egg hierarchy to look for the topmost +// nodes encountered. +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +scan_for_top_joints(EggNode *egg_node, EggNode *model_root, + const string &character_name) { + if (egg_node->is_of_type(EggGroup::get_class_type())) { + EggGroup *group = DCAST(EggGroup, egg_node); + + if (group->has_lod()) { + // This flag has an LOD specification. + model_root = group; + } + if (group->get_group_type() == EggGroup::GT_joint) { + // A node begins a model hierarchy. + _top_egg_nodes[character_name][model_root].push_back(group); + return; + } + } + + if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *group = DCAST(EggGroupNode, egg_node); + EggGroupNode::iterator gi; + for (gi = group->begin(); gi != group->end(); ++gi) { + scan_for_top_joints(*gi, model_root, character_name); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::scan_for_top_tables +// Access: Private +// Description: Once an animation has been found, continue scanning +// the egg hierarchy to look for the topmost +// nodes encountered. +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +scan_for_top_tables(EggTable *bundle, EggNode *model_root, + const string &character_name) { + // We really only need to check the immediate children of the bundle + // for a table node called "". + EggGroupNode::iterator gi; + for (gi = bundle->begin(); gi != bundle->end(); ++gi) { + EggNode *child = (*gi); + if (child->is_of_type(EggTable::get_class_type())) { + EggTable *table = DCAST(EggTable, child); + if (table->get_name() == "") { + // Here it is! Now the immediate children of this node are + // the top tables. + + EggGroupNode::iterator cgi; + for (cgi = table->begin(); cgi != table->end(); ++cgi) { + EggNode *grandchild = (*cgi); + if (grandchild->is_of_type(EggTable::get_class_type())) { + _top_egg_nodes[character_name][model_root].push_back(grandchild); + } + } + } + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::match_egg_nodes +// Access: Private +// Description: Attempts to match up the indicated list of egg_nodes +// with the children of the given joint_data, by name if +// possible. +// +// Also recurses on each matched joint to build up the +// entire joint hierarchy. +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, + int egg_index, int model_index) { + // Sort the list of egg_nodes in order by name. This will make the + // matching up by names easier and more reliable. + sort(egg_nodes.begin(), egg_nodes.end(), IndirectCompareNames()); + + if (joint_data->_children.empty()) { + // If the EggJointData has no children yet, we must be the first. + // Gleefully define all the joints. + EggNodeList::iterator ei; + for (ei = egg_nodes.begin(); ei != egg_nodes.end(); ++ei) { + EggNode *egg_node = (*ei); + EggJointData *data = make_joint_data(); + joint_data->_children.push_back(data); + found_egg_node_match(data, egg_node, egg_index, model_index); + } + + } else { + // The EggJointData already has children; therefore, we have to + // match our joints up with the already-existing ones. + + EggNodeList extra_egg_nodes; + EggJointData::Children extra_data; + + EggNodeList::iterator ei; + EggJointData::Children::iterator di; + + ei = egg_nodes.begin(); + di = joint_data->_children.begin(); + + while (ei != egg_nodes.end() && di != joint_data->_children.end()) { + EggNode *egg_node = (*ei); + EggJointData *data = (*di); + + if (egg_node->get_name() < data->get_name()) { + // Here's a joint in the egg file, unmatched in the data. + extra_egg_nodes.push_back(egg_node); + ++ei; + + } else if (data->get_name() < egg_node->get_name()) { + // Here's a joint in the data, umatched by the egg file. + extra_data.push_back(data); + ++di; + + } else { + // Hey, these two match! Hooray! + found_egg_node_match(data, egg_node, egg_index, model_index); + ++ei; + ++di; + } + } + + while (ei != egg_nodes.end()) { + EggNode *egg_node = (*ei); + + // Here's a joint in the egg file, unmatched in the data. + extra_egg_nodes.push_back(egg_node); + ++ei; + } + + while (di != joint_data->_children.end()) { + EggJointData *data = (*di); + + // Here's a joint in the data, umatched by the egg file. + extra_data.push_back(data); + ++di; + } + + if (!extra_egg_nodes.empty()) { + // If we have some extra egg_nodes, we have to find a place to + // match them. (If we only had extra data, we don't care.) + + // First, check to see if any of the names match any past-used + // name. + + EggNodeList more_egg_nodes; + + for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) { + EggNode *egg_node = (*ei); + bool matched = false; + for (di = extra_data.begin(); + di != extra_data.end() && !matched; + ++di) { + EggJointData *data = (*di); + if (data->matches_name(egg_node->get_name())) { + matched = true; + found_egg_node_match(data, egg_node, egg_index, model_index); + extra_data.erase(di); + } + } + + if (!matched) { + // This joint name was never seen before. + more_egg_nodes.push_back(egg_node); + } + } + extra_egg_nodes.swap(more_egg_nodes); + } + + if (!extra_egg_nodes.empty()) { + // Ok, we've still got to find a home for these remaining + // egg_nodes. + if (extra_egg_nodes.size() == extra_data.size()) { + // Match 'em up one-for-one. + size_t i; + for (i = 0; i < extra_egg_nodes.size(); i++) { + EggNode *egg_node = extra_egg_nodes[i]; + EggJointData *data = extra_data[i]; + found_egg_node_match(data, egg_node, egg_index, model_index); + } + + } else { + // Just tack 'em on the end. + EggNodeList::iterator ei; + for (ei = extra_egg_nodes.begin(); ei != extra_egg_nodes.end(); ++ei) { + EggNode *egg_node = (*ei); + EggJointData *data = make_joint_data(); + joint_data->_children.push_back(data); + found_egg_node_match(data, egg_node, egg_index, model_index); + } + } + } + } + + // Now sort the generated joint data hierarchy by name, just to be + // sure. + sort(joint_data->_children.begin(), joint_data->_children.end(), + IndirectCompareNames()); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::found_egg_node_match +// Access: Private +// Description: Marks a one-to-one association between the indicated +// EggJointData and the indicated EggNode, and then +// recurses below. +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +found_egg_node_match(EggJointData *data, EggNode *egg_node, + int egg_index, int model_index) { + data->add_egg_node(egg_index, model_index, egg_node); + + if (egg_node->is_of_type(EggGroupNode::get_class_type())) { + EggGroupNode *group_node = DCAST(EggGroupNode, egg_node); + + // Now consider all the children of egg_node that are themselves + // joints or tables. + EggNodeList egg_nodes; + + // Two approaches: either we are scanning a model with joints, or + // an animation bundle with tables. + + if (egg_node->is_of_type(EggGroup::get_class_type())) { + // A model with joints. + EggGroupNode::iterator gi; + for (gi = group_node->begin(); gi != group_node->end(); ++gi) { + EggNode *child = (*gi); + if (child->is_of_type(EggGroup::get_class_type())) { + EggGroup *group = DCAST(EggGroup, child); + if (group->get_group_type() == EggGroup::GT_joint) { + egg_nodes.push_back(group); + } + } + } + + } else { + // An animation bundle with tables. + EggGroupNode::iterator gi; + for (gi = group_node->begin(); gi != group_node->end(); ++gi) { + EggNode *child = (*gi); + if (child->is_of_type(EggTable::get_class_type())) { + EggTable *table = DCAST(EggTable, child); + if (!(table->get_name() == "xform")) { + egg_nodes.push_back(table); + } + } + } + } + + if (!egg_nodes.empty()) { + match_egg_nodes(data, egg_nodes, egg_index, model_index); + } + } +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterData::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void EggCharacterData:: +write(ostream &out, int indent_level) const { + Characters::const_iterator ci; + + for (ci = _characters.begin(); ci != _characters.end(); ++ci) { + const CharacterInfo &character_info = (*ci); + indent(out, indent_level) + << "Character " << character_info._name << ":\n"; + character_info._root_joint->write(out, indent_level + 2); + } +} diff --git a/pandatool/src/eggbase/eggCharacterData.h b/pandatool/src/eggbase/eggCharacterData.h new file mode 100644 index 0000000000..5fdb00c238 --- /dev/null +++ b/pandatool/src/eggbase/eggCharacterData.h @@ -0,0 +1,82 @@ +// Filename: eggCharacterData.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGCHARACTERDATA_H +#define EGGCHARACTERDATA_H + +#include + +#include +#include +#include + +class EggJointData; +class EggTable; + +//////////////////////////////////////////////////////////////////// +// Class : EggCharacterData +// Description : Represents a set of characters, as read and collected +// from several models and animation files. Each +// character is the root of a hierarchy of EggJointData +// nodes. +//////////////////////////////////////////////////////////////////// +class EggCharacterData { +public: + EggCharacterData(); + virtual ~EggCharacterData(); + + bool add_egg(EggData *egg); + + INLINE int get_num_eggs() const; + INLINE EggData *get_egg(int i) const; + + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + virtual EggJointData *make_joint_data(); + EggJointData *get_root_joint(const string &character_name); + + class EggInfo { + public: + PT(EggData) _egg; + typedef vector Models; + Models _models; + }; + + typedef vector Eggs; + Eggs _eggs; + + class CharacterInfo { + public: + string _name; + EggJointData *_root_joint; + }; + + typedef vector Characters; + Characters _characters; + +private: + bool scan_hierarchy(EggNode *egg_node); + void scan_for_top_joints(EggNode *egg_node, EggNode *model_root, + const string &character_name); + void scan_for_top_tables(EggTable *bundle, EggNode *model_root, + const string &character_name); + + typedef vector EggNodeList; + typedef map TopEggNodes; + typedef map TopEggNodesByName; + TopEggNodesByName _top_egg_nodes; + + void match_egg_nodes(EggJointData *joint_data, EggNodeList &egg_nodes, + int egg_index, int model_index); + void found_egg_node_match(EggJointData *data, EggNode *egg_node, + int egg_index, int model_index); +}; + +#include "eggCharacterData.I" + +#endif + + diff --git a/pandatool/src/eggbase/eggCharacterFilter.cxx b/pandatool/src/eggbase/eggCharacterFilter.cxx new file mode 100644 index 0000000000..44557953d4 --- /dev/null +++ b/pandatool/src/eggbase/eggCharacterFilter.cxx @@ -0,0 +1,75 @@ +// Filename: eggCharacterFilter.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggCharacterFilter.h" +#include "eggCharacterData.h" + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterFilter::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterFilter:: +EggCharacterFilter() : EggMultiFilter(false) { + _character_data = (EggCharacterData *)NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterFilter::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +EggCharacterFilter:: +~EggCharacterFilter() { + if (_character_data != (EggCharacterData *)NULL) { + delete _character_data; + } +} + + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterFilter::post_command_line +// Access: Protected, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +bool EggCharacterFilter:: +post_command_line() { + if (_character_data == (EggCharacterData *)NULL) { + _character_data = make_character_data(); + } + + if (!EggMultiFilter::post_command_line()) { + return false; + } + + Eggs::iterator ei; + for (ei = _eggs.begin(); ei != _eggs.end(); ++ei) { + EggData *data = (*ei); + + if (!_character_data->add_egg(data)) { + nout << data->get_egg_filename().get_basename() + << " does not contain a character model or animation channel.\n"; + return false; + } + } + + _character_data->write(cerr); + + return true; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggCharacterFilter::make_character_data +// Access: Protected, Virtual +// Description: Allocates and returns a new EggCharacterData structure. +// This is primarily intended as a hook so derived +// classes can customize the type of EggCharacterData nodes +// used to represent the character information. +//////////////////////////////////////////////////////////////////// +EggCharacterData *EggCharacterFilter:: +make_character_data() { + return new EggCharacterData; +} diff --git a/pandatool/src/eggbase/eggCharacterFilter.h b/pandatool/src/eggbase/eggCharacterFilter.h new file mode 100644 index 0000000000..f3c2b155cb --- /dev/null +++ b/pandatool/src/eggbase/eggCharacterFilter.h @@ -0,0 +1,41 @@ +// Filename: eggCharacterFilter.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGCHARACTERFILTER_H +#define EGGCHARACTERFILTER_H + +#include + +#include "eggMultiFilter.h" + +class EggCharacterData; + +//////////////////////////////////////////////////////////////////// +// Class : EggCharacterFilter +// Description : This is the base class for a family of programs that +// operate on a number of character models and their +// associated animation files together. It reads in a +// number of egg files, any combination of model files +// or character files which must all represent the same +// character skeleton, and maintains a single hierarchy +// of joints and sliders that may be operated on before +// writing the files back out. +//////////////////////////////////////////////////////////////////// +class EggCharacterFilter : public EggMultiFilter { +public: + EggCharacterFilter(); + virtual ~EggCharacterFilter(); + +protected: + virtual bool post_command_line(); + + virtual EggCharacterData *make_character_data(); + + EggCharacterData *_character_data; +}; + +#endif + + diff --git a/pandatool/src/eggbase/eggJointData.I b/pandatool/src/eggbase/eggJointData.I new file mode 100644 index 0000000000..e1d3e8b5d8 --- /dev/null +++ b/pandatool/src/eggbase/eggJointData.I @@ -0,0 +1,26 @@ +// Filename: eggJointData.I +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::get_num_children +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE int EggJointData:: +get_num_children() const { + return _children.size(); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::get_child +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE EggJointData *EggJointData:: +get_child(int n) const { + nassertr(n >= 0 && n < (int)_children.size(), (EggJointData *)NULL); + return _children[n]; +} diff --git a/pandatool/src/eggbase/eggJointData.cxx b/pandatool/src/eggbase/eggJointData.cxx new file mode 100644 index 0000000000..c6715e1fca --- /dev/null +++ b/pandatool/src/eggbase/eggJointData.cxx @@ -0,0 +1,93 @@ +// Filename: eggJointData.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggJointData.h" + +#include + + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggJointData:: +EggJointData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::Destructor +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +EggJointData:: +~EggJointData() { +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::matches_name +// Access: Public +// Description: Returns true if the indicated name matches any name +// that was ever matched with this particular joint, +// false otherwise. +//////////////////////////////////////////////////////////////////// +bool EggJointData:: +matches_name(const string &name) const { + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::add_egg_node +// Access: Public +// Description: Adds the indicated model joint or anim table to the +// data. +//////////////////////////////////////////////////////////////////// +void EggJointData:: +add_egg_node(int egg_index, int model_index, EggNode *egg_node) { + if (!has_name() && egg_node->has_name()) { + set_name(egg_node->get_name()); + } + + while ((int)_joints.size() <= egg_index) { + _joints.push_back(JointNodes()); + } + JointNodes &nodes = _joints[egg_index]; + while ((int)nodes.size() <= model_index) { + nodes.push_back((EggNode *)NULL); + } + nodes[model_index] = egg_node; +} + +//////////////////////////////////////////////////////////////////// +// Function: EggJointData::write +// Access: Public, Virtual +// Description: +//////////////////////////////////////////////////////////////////// +void EggJointData:: +write(ostream &out, int indent_level) const { + indent(out, indent_level) + << "Joint " << get_name() + << " (models:"; + for (size_t egg_index = 0; egg_index < _joints.size(); egg_index++) { + const JointNodes &nodes = _joints[egg_index]; + if (nodes.size() == 1) { + out << " " << egg_index; + } else if (nodes.size() > 1) { + for (size_t model_index = 0; model_index < nodes.size(); model_index++) { + if (nodes[model_index] != (EggNode *)NULL) { + out << " " << egg_index << "/" << model_index; + } + } + } + } + out << ") {\n"; + + Children::const_iterator ci; + for (ci = _children.begin(); ci != _children.end(); ++ci) { + (*ci)->write(out, indent_level + 2); + } + + indent(out, indent_level) << "}\n"; +} diff --git a/pandatool/src/eggbase/eggJointData.h b/pandatool/src/eggbase/eggJointData.h new file mode 100644 index 0000000000..8969a121f8 --- /dev/null +++ b/pandatool/src/eggbase/eggJointData.h @@ -0,0 +1,63 @@ +// Filename: eggJointData.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGJOINTDATA_H +#define EGGJOINTDATA_H + +#include + +#include +#include +#include + +class EggGroup; + +//////////////////////////////////////////////////////////////////// +// Class : EggJointData +// Description : This is one node of a hierarchy of EggJointData +// nodes, each of which represents a single joint of the +// character hierarchy across all loaded files: the +// various models, the LOD's of each model, and the +// various animation channel files. +//////////////////////////////////////////////////////////////////// +class EggJointData : public Namable { +public: + EggJointData(); + virtual ~EggJointData(); + + INLINE int get_num_children() const; + INLINE EggJointData *get_child(int n) const; + + bool matches_name(const string &name) const; + void add_egg_node(int egg_index, int model_index, EggNode *egg_node); + + virtual void write(ostream &out, int indent_level = 0) const; + +protected: + typedef vector JointNodes; + typedef vector Joints; + + Joints _tables; + // _tables[i][anim] is the table for the animth bundle of the ith + // file. + + Joints _joints; + // _joints[i][model] is the joint for the modelth lod of the ith + // file. + + LMatrix4d _rest_transform; + LMatrix4d _net_rest_transform; + + typedef vector Children; + Children _children; + + friend class EggCharacterData; +}; + +#include "eggJointData.I" + +#endif + + diff --git a/pandatool/src/eggbase/eggMultiBase.cxx b/pandatool/src/eggbase/eggMultiBase.cxx index ba9785c57c..601332e44b 100644 --- a/pandatool/src/eggbase/eggMultiBase.cxx +++ b/pandatool/src/eggbase/eggMultiBase.cxx @@ -97,9 +97,9 @@ append_command_comment(EggData &data) { // information stored with each egg structure, by // deriving from EggData. //////////////////////////////////////////////////////////////////// -EggData *EggMultiBase:: +PT(EggData) EggMultiBase:: read_egg(const Filename &filename) { - EggData *data = new EggData; + PT(EggData) data = new EggData; // First, we always try to resolve a filename from the current // directory. This means a local filename will always be found @@ -110,13 +110,11 @@ read_egg(const Filename &filename) { if (!data->read(local_filename)) { // Failure reading. - delete data; return (EggData *)NULL; } if (_force_complete) { if (!data->resolve_externals()) { - delete data; return (EggData *)NULL; } } diff --git a/pandatool/src/eggbase/eggMultiBase.h b/pandatool/src/eggbase/eggMultiBase.h index 818e30afa8..326cbeae69 100644 --- a/pandatool/src/eggbase/eggMultiBase.h +++ b/pandatool/src/eggbase/eggMultiBase.h @@ -10,9 +10,10 @@ #include #include +#include +#include class Filename; -class EggData; //////////////////////////////////////////////////////////////////// // Class : EggMultiBase @@ -30,13 +31,13 @@ public: protected: void append_command_comment(EggData &_data); - virtual EggData *read_egg(const Filename &filename); + virtual PT(EggData) read_egg(const Filename &filename); protected: bool _got_coordinate_system; CoordinateSystem _coordinate_system; - typedef vector Eggs; + typedef vector Eggs; Eggs _eggs; bool _force_complete; diff --git a/pandatool/src/eggbase/eggMultiFilter.cxx b/pandatool/src/eggbase/eggMultiFilter.cxx index 888d7431bd..e6b8b4308e 100644 --- a/pandatool/src/eggbase/eggMultiFilter.cxx +++ b/pandatool/src/eggbase/eggMultiFilter.cxx @@ -93,7 +93,7 @@ handle_args(ProgramBase::Args &args) { Args::const_iterator ai; for (ai = args.begin(); ai != args.end(); ++ai) { - EggData *data = read_egg(*ai); + PT(EggData) data = read_egg(*ai); if (data == (EggData *)NULL) { // Rather than returning false, we simply exit here, so the // ProgramBase won't try to tell the user how to run the program diff --git a/pandatool/src/eggprogs/Sources.pp b/pandatool/src/eggprogs/Sources.pp index 2c33ec3d95..75706996f4 100644 --- a/pandatool/src/eggprogs/Sources.pp +++ b/pandatool/src/eggprogs/Sources.pp @@ -20,3 +20,11 @@ eggTextureCards.cxx eggTextureCards.h #end bin_target + +#begin noinst_bin_target + #define TARGET egg-topstrip + + #define SOURCES \ + eggTopstrip.cxx eggTopstrip.h + +#end noinst_bin_target diff --git a/pandatool/src/eggprogs/eggTopstrip.cxx b/pandatool/src/eggprogs/eggTopstrip.cxx new file mode 100644 index 0000000000..f9aad7f7dd --- /dev/null +++ b/pandatool/src/eggprogs/eggTopstrip.cxx @@ -0,0 +1,40 @@ +// Filename: eggTopstrip.cxx +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#include "eggTopstrip.h" + +//////////////////////////////////////////////////////////////////// +// Function: EggTopstrip::Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +EggTopstrip:: +EggTopstrip() { + set_program_description + ("egg-topstrip reads a character model and its associated animation " + "files, and unapplies the animation from one of the top joints. " + "This effectively freezes that particular joint, and makes the rest " + "of the character relative to that joint.\n\n" + + "This is a particularly useful thing to do to generate character " + "models that can stack one on top of the other in a sensible way."); +} + +//////////////////////////////////////////////////////////////////// +// Function: EggTopstrip::run +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +void EggTopstrip:: +run() { +} + + +int main(int argc, char *argv[]) { + EggTopstrip prog; + prog.parse_command_line(argc, argv); + prog.run(); + return 0; +} diff --git a/pandatool/src/eggprogs/eggTopstrip.h b/pandatool/src/eggprogs/eggTopstrip.h new file mode 100644 index 0000000000..e51f6ac0ff --- /dev/null +++ b/pandatool/src/eggprogs/eggTopstrip.h @@ -0,0 +1,29 @@ +// Filename: eggTopstrip.h +// Created by: drose (23Feb01) +// +//////////////////////////////////////////////////////////////////// + +#ifndef EGGTOPSTRIP_H +#define EGGTOPSTRIP_H + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// Class : EggTopstrip +// Description : Reads a character model and/or animations and strips +// out the animation from one of the top joints from the +// entire character. Particularly useful for generating +// stackable character models from separately-extracted +// characters. +//////////////////////////////////////////////////////////////////// +class EggTopstrip : public EggCharacterFilter { +public: + EggTopstrip(); + + void run(); +}; + +#endif +