Explorar o código

*** empty log message ***

David Rose %!s(int64=25) %!d(string=hai) anos
pai
achega
a2d31d523c
Modificáronse 43 ficheiros con 1009 adicións e 6429 borrados
  1. 1 4
      panda/src/egg2sg/characterMaker.cxx
  2. 5 2
      panda/src/putil/Sources.pp
  3. 16 0
      panda/src/putil/indirectCompareNames.I
  4. 29 0
      panda/src/putil/indirectCompareNames.h
  5. 1 0
      panda/src/putil/indirectCompareTo.I
  6. 0 22
      pandatool/src/egg-palettize-old/Sources.pp
  7. 0 1634
      pandatool/src/egg-palettize-old/attribFile.cxx
  8. 0 167
      pandatool/src/egg-palettize-old/attribFile.h
  9. 0 14
      pandatool/src/egg-palettize-old/config_egg_palettize.cxx
  10. 0 737
      pandatool/src/egg-palettize-old/eggPalettize.cxx
  11. 0 82
      pandatool/src/egg-palettize-old/eggPalettize.h
  12. 0 436
      pandatool/src/egg-palettize-old/pTexture.cxx
  13. 0 111
      pandatool/src/egg-palettize-old/pTexture.h
  14. 0 591
      pandatool/src/egg-palettize-old/palette.cxx
  15. 0 100
      pandatool/src/egg-palettize-old/palette.h
  16. 0 316
      pandatool/src/egg-palettize-old/paletteGroup.cxx
  17. 0 87
      pandatool/src/egg-palettize-old/paletteGroup.h
  18. 0 496
      pandatool/src/egg-palettize-old/sourceEgg.cxx
  19. 0 79
      pandatool/src/egg-palettize-old/sourceEgg.h
  20. 0 80
      pandatool/src/egg-palettize-old/string_utils.cxx
  21. 0 21
      pandatool/src/egg-palettize-old/string_utils.h
  22. 0 69
      pandatool/src/egg-palettize-old/textureEggRef.cxx
  23. 0 43
      pandatool/src/egg-palettize-old/textureEggRef.h
  24. 0 26
      pandatool/src/egg-palettize-old/textureOmitReason.h
  25. 0 614
      pandatool/src/egg-palettize-old/texturePacking.cxx
  26. 0 90
      pandatool/src/egg-palettize-old/texturePacking.h
  27. 0 504
      pandatool/src/egg-palettize-old/userAttribLine.cxx
  28. 0 91
      pandatool/src/egg-palettize-old/userAttribLine.h
  29. 14 5
      pandatool/src/eggbase/Sources.pp
  30. 27 0
      pandatool/src/eggbase/eggCharacterData.I
  31. 452 0
      pandatool/src/eggbase/eggCharacterData.cxx
  32. 82 0
      pandatool/src/eggbase/eggCharacterData.h
  33. 75 0
      pandatool/src/eggbase/eggCharacterFilter.cxx
  34. 41 0
      pandatool/src/eggbase/eggCharacterFilter.h
  35. 26 0
      pandatool/src/eggbase/eggJointData.I
  36. 93 0
      pandatool/src/eggbase/eggJointData.cxx
  37. 63 0
      pandatool/src/eggbase/eggJointData.h
  38. 2 4
      pandatool/src/eggbase/eggMultiBase.cxx
  39. 4 3
      pandatool/src/eggbase/eggMultiBase.h
  40. 1 1
      pandatool/src/eggbase/eggMultiFilter.cxx
  41. 8 0
      pandatool/src/eggprogs/Sources.pp
  42. 40 0
      pandatool/src/eggprogs/eggTopstrip.cxx
  43. 29 0
      pandatool/src/eggprogs/eggTopstrip.h

+ 1 - 4
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);

+ 5 - 2
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 \

+ 16 - 0
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<class ObjectType>
+INLINE bool IndirectCompareNames<ObjectType>::
+operator () (const ObjectType *a, const ObjectType *b) const {
+  return (a != b && a->get_name() < b->get_name());
+}

+ 29 - 0
panda/src/putil/indirectCompareNames.h

@@ -0,0 +1,29 @@
+// Filename: indirectCompareNames.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef INDIRECTCOMPARENAMES_H
+#define INDIRECTCOMPARENAMES_H
+
+#include <pandabase.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 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 ObjectType>
+class IndirectCompareNames {
+public:
+  INLINE bool operator () (const ObjectType *a, const ObjectType *b) const;
+};
+
+#include "indirectCompareNames.I"
+
+#endif
+

+ 1 - 0
panda/src/putil/indirectCompareTo.I

@@ -3,6 +3,7 @@
 // 
 ////////////////////////////////////////////////////////////////////
 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: IndirectCompareTo::operator ()
 //       Access: Public

+ 0 - 22
pandatool/src/egg-palettize-old/Sources.pp

@@ -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

+ 0 - 1634
pandatool/src/egg-palettize-old/attribFile.cxx

@@ -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 <pnmImage.h>
-#include <pnmFileType.h>
-#include <pnmFileTypeRegistry.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdio.h>
-#include <map>
-#include <set>
-#include <fcntl.h>
-
-#ifdef WIN32_VC
-#include <io.h>
-#include <share.h>
-#include <sys/stat.h>
-#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<TexturePacking *> textures;
-  get_eligible_textures(textures);
-  
-  // Now pack all the textures.  This will create new palettes.
-  vector<TexturePacking *>::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<TexturePacking *> textures;
-  get_eligible_textures(textures);
-  
-  // Now pack whatever textures are currently unpacked.
-  vector<TexturePacking *>::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<TexturePacking *> &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<int, map<int, set<TexturePacking *> > > 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<int, set<TexturePacking *> >::const_iterator t2;
-    for (t2 = (*t1).second.begin(); t2 != (*t1).second.end(); ++t2) {
-      set<TexturePacking *>::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<string, PTexture *> &textures,
-		   map<string, int> &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<string, PTexture *>::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<string, int>::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<double, PTexture *> 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;
-}

+ 0 - 167
pandatool/src/egg-palettize-old/attribFile.h

@@ -1,167 +0,0 @@
-// Filename: attribFile.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef ATTRIBFILE_H
-#define ATTRIBFILE_H
-
-#include <pandatoolbase.h>
-
-#include <filename.h>
-#include <vector_string.h>
-
-#include <map>
-#include <vector>
-
-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<TexturePacking *> &textures);
-  SourceEgg *get_egg(Filename name);
-
-  bool generate_palette_images();
-  bool transfer_unplaced_images(bool force_redo_all);
-
-  void check_dup_textures(map<string, PTexture *> &textures,
-			  map<string, int> &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<UserAttribLine *> UserLines;
-  UserLines _user_lines;
-
-  typedef map<string, SourceEgg *> Eggs;
-  Eggs _eggs;
-
-  typedef map<string, PaletteGroup *> Groups;
-  Groups _groups;
-
-  typedef map<string, PTexture *> PTextures;
-  PTextures _textures;
-
-  typedef vector<TexturePacking *> 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

+ 0 - 14
pandatool/src/egg-palettize-old/config_egg_palettize.cxx

@@ -1,14 +0,0 @@
-// Filename: config_egg_palettize.cxx
-// Created by:  drose (02Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include <dconfig.h>
-
-#include "sourceEgg.h"
-
-Configure(config_egg_palettize);
-
-ConfigureFn(config_egg_palettize) {
-  SourceEgg::init_type();
-}

+ 0 - 737
pandatool/src/egg-palettize-old/eggPalettize.cxx

@@ -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 <pnmImage.h>
-#include <pnmFileTypeRegistry.h>
-#include <pnmFileType.h>
-#include <stdio.h>
-
-////////////////////////////////////////////////////////////////////
-//     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<string, PTexture *> textures;
-  map<string, int> 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<string, int>::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<TextureOmitReason, pair<int, int> > UnplacedReasons;
-  UnplacedReasons unplaced_reasons;
-
-  map<string, PTexture *>::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<int, int>(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;
-}

+ 0 - 82
pandatool/src/egg-palettize-old/eggPalettize.h

@@ -1,82 +0,0 @@
-// Filename: eggPalettize.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef EGGPALETTIZE_H
-#define EGGPALETTIZE_H
-
-#include <pandatoolbase.h>
-
-#include "attribFile.h"
-#include <eggMultiFilter.h>
-
-#include <vector>
-
-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<AttribFile *> 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

+ 0 - 436
pandatool/src/egg-palettize-old/pTexture.cxx

@@ -1,436 +0,0 @@
-// Filename: pTexture.cxx
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include "pTexture.h"
-#include "texturePacking.h"
-#include "palette.h"
-#include "attribFile.h"
-
-#include <pnmImage.h>
-#include <pnmReader.h>
-
-////////////////////////////////////////////////////////////////////
-//     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;
-}

+ 0 - 111
pandatool/src/egg-palettize-old/pTexture.h

@@ -1,111 +0,0 @@
-// Filename: pTexture.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef PTEXTURE_H
-#define PTEXTURE_H
-
-#include <pandatoolbase.h>
-
-#include <filename.h>
-
-#include <set>
-#include <map>
-
-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<TextureEggRef *> 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<Filename> 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<PaletteGroup *, TexturePacking *> Packing;
-  Packing _packing;
-
-  friend class TexturePacking;
-};
-
-
-#endif

+ 0 - 591
pandatool/src/egg-palettize-old/palette.cxx

@@ -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 <notify.h>
-#include <pnmImage.h>
-#include <pnmFileType.h>
-
-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;
-}

+ 0 - 100
pandatool/src/egg-palettize-old/palette.h

@@ -1,100 +0,0 @@
-// Filename: palette.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef PALETTE_H
-#define PALETTE_H
-
-#include <pandatoolbase.h>
-
-#include <filename.h>
-
-#include <vector>
-
-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<TexturePlacement> 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

+ 0 - 316
pandatool/src/egg-palettize-old/paletteGroup.cxx

@@ -1,316 +0,0 @@
-// Filename: paletteGroup.cxx
-// Created by:  drose (06Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include "paletteGroup.h"
-#include "texturePacking.h"
-#include "palette.h"
-#include "attribFile.h"
-
-#include <stdio.h> // 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);
-  }
-}

+ 0 - 87
pandatool/src/egg-palettize-old/paletteGroup.h

@@ -1,87 +0,0 @@
-// Filename: paletteGroup.h
-// Created by:  drose (06Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef PALETTEGROUP_H
-#define PALETTEGROUP_H
-
-#include <pandatoolbase.h>
-
-#include <namable.h>
-
-#include <vector>
-#include <set>
-
-class Palette;
-class TexturePacking;
-class AttribFile;
-class PaletteGroup;
-
-typedef set<PaletteGroup *> 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<PaletteGroup *> Parents;
-  Parents _parents;
-
-  typedef vector<Palette *> Palettes;
-  Palettes _palettes;
-
-  string _dirname;
-};
-
-
-#endif
-

+ 0 - 496
pandatool/src/egg-palettize-old/sourceEgg.cxx

@@ -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 <eggAttributes.h>
-#include <eggVertex.h>
-#include <eggNurbsSurface.h>
-#include <eggPrimitive.h>
-#include <eggTextureCollection.h>
-#include <eggAlphaMode.h>
-
-#include <algorithm>
-
-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);
-    }
-  }
-}	

+ 0 - 79
pandatool/src/egg-palettize-old/sourceEgg.h

@@ -1,79 +0,0 @@
-// Filename: sourceEgg.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef SOURCEGG_H
-#define SOURCEGG_H
-
-#include <pandatoolbase.h>
-
-#include "paletteGroup.h"
-
-#include <eggData.h>
-#include <luse.h>
-
-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<TextureEggRef *> 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

+ 0 - 80
pandatool/src/egg-palettize-old/string_utils.cxx

@@ -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 &param, 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));
-}

+ 0 - 21
pandatool/src/egg-palettize-old/string_utils.h

@@ -1,21 +0,0 @@
-// Filename: string_utils.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef STRING_UTILS_H
-#define STRING_UTILS_H
-
-#include <pandatoolbase.h>
-#include <vector_string.h>
-
-#include <vector>
-
-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 &param, string &value);
-
-#endif
-

+ 0 - 69
pandatool/src/egg-palettize-old/textureEggRef.cxx

@@ -1,69 +0,0 @@
-// Filename: textureEggRef.cxx
-// Created by:  drose (08Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#include "textureEggRef.h"
-#include "texturePacking.h"
-#include "pTexture.h"
-
-#include <notify.h>
-
-#include <algorithm>
-
-////////////////////////////////////////////////////////////////////
-//     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);
-}

+ 0 - 43
pandatool/src/egg-palettize-old/textureEggRef.h

@@ -1,43 +0,0 @@
-// Filename: textureEggRef.h
-// Created by:  drose (08Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef TEXTUREEGGREF_H
-#define TEXTUREEGGREF_H
-
-#include <pandatoolbase.h>
-
-#include "paletteGroup.h"
-
-#include <vector>
-
-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

+ 0 - 26
pandatool/src/egg-palettize-old/textureOmitReason.h

@@ -1,26 +0,0 @@
-// Filename: textureOmitReason.h
-// Created by:  drose (06Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef TEXTUREOMITREASON_H
-#define TEXTUREOMITREASON_H
-
-#include <pandatoolbase.h>
-
-////////////////////////////////////////////////////////////////////
-// 	  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

+ 0 - 614
pandatool/src/egg-palettize-old/texturePacking.cxx

@@ -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 <pnmImage.h>
-
-
-////////////////////////////////////////////////////////////////////
-//     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;
-}

+ 0 - 90
pandatool/src/egg-palettize-old/texturePacking.h

@@ -1,90 +0,0 @@
-// Filename: texturePacking.h
-// Created by:  drose (06Nov00)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef TEXTUREPACKING_H
-#define TEXTUREPACKING_H
-
-#include <pandatoolbase.h>
-
-#include "textureOmitReason.h"
-
-#include <filename.h>
-
-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

+ 0 - 504
pandatool/src/egg-palettize-old/userAttribLine.cxx

@@ -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 <notify.h>
-
-#include <ctype.h>
-
-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<string>(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<string>(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<string>(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;
-}

+ 0 - 91
pandatool/src/egg-palettize-old/userAttribLine.h

@@ -1,91 +0,0 @@
-// Filename: userAttribLine.h
-// Created by:  drose (02Sep99)
-// 
-////////////////////////////////////////////////////////////////////
-
-#ifndef USERATTRIBLINE_H
-#define USERATTRIBLINE_H
-
-#include <pandatoolbase.h>
-
-#include <globPattern.h>
-#include <vector_string.h>
-
-#include <vector>
-
-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<GlobPattern> 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

+ 14 - 5
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
 

+ 27 - 0
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;
+}

+ 452 - 0
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 <indirectCompareNames.h>
+#include <indent.h>
+
+#include <algorithm>
+
+////////////////////////////////////////////////////////////////////
+//     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 <Dart> 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 <Bundle> 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
+//               <Joint> 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 <Joint> 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 <Table>
+//               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 "<skeleton>".
+  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() == "<skeleton>") {
+	// 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<Namable>());
+  
+  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<Namable>());
+}
+
+////////////////////////////////////////////////////////////////////
+//     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);
+  }
+}

+ 82 - 0
pandatool/src/eggbase/eggCharacterData.h

@@ -0,0 +1,82 @@
+// Filename: eggCharacterData.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGCHARACTERDATA_H
+#define EGGCHARACTERDATA_H
+
+#include <pandatoolbase.h>
+
+#include <eggData.h>
+#include <eggNode.h>
+#include <pointerTo.h>
+
+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<PT(EggNode)> Models;
+    Models _models;
+  };
+  
+  typedef vector<EggInfo> Eggs;
+  Eggs _eggs;
+
+  class CharacterInfo {
+  public:
+    string _name;
+    EggJointData *_root_joint;
+  };
+
+  typedef vector<CharacterInfo> 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<EggNode *> EggNodeList;
+  typedef map<EggNode *, EggNodeList> TopEggNodes;
+  typedef map<string, TopEggNodes> 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
+
+

+ 75 - 0
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;
+}

+ 41 - 0
pandatool/src/eggbase/eggCharacterFilter.h

@@ -0,0 +1,41 @@
+// Filename: eggCharacterFilter.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGCHARACTERFILTER_H
+#define EGGCHARACTERFILTER_H
+
+#include <pandatoolbase.h>
+
+#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
+
+

+ 26 - 0
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];
+}

+ 93 - 0
pandatool/src/eggbase/eggJointData.cxx

@@ -0,0 +1,93 @@
+// Filename: eggJointData.cxx
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "eggJointData.h"
+
+#include <indent.h>
+
+
+////////////////////////////////////////////////////////////////////
+//     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";
+}

+ 63 - 0
pandatool/src/eggbase/eggJointData.h

@@ -0,0 +1,63 @@
+// Filename: eggJointData.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGJOINTDATA_H
+#define EGGJOINTDATA_H
+
+#include <pandatoolbase.h>
+
+#include <eggNode.h>
+#include <pointerTo.h>
+#include <namable.h>
+
+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<PT(EggNode)> JointNodes;
+  typedef vector<JointNodes> 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<EggJointData *> Children;
+  Children _children;
+
+  friend class EggCharacterData;
+};
+
+#include "eggJointData.I"
+
+#endif
+
+

+ 2 - 4
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;
     }
   }

+ 4 - 3
pandatool/src/eggbase/eggMultiBase.h

@@ -10,9 +10,10 @@
 
 #include <programBase.h>
 #include <coordinateSystem.h>
+#include <eggData.h>
+#include <pointerTo.h>
 
 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<EggData *> Eggs;
+  typedef vector<PT(EggData)> Eggs;
   Eggs _eggs;
 
   bool _force_complete;

+ 1 - 1
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

+ 8 - 0
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

+ 40 - 0
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;
+}

+ 29 - 0
pandatool/src/eggprogs/eggTopstrip.h

@@ -0,0 +1,29 @@
+// Filename: eggTopstrip.h
+// Created by:  drose (23Feb01)
+// 
+////////////////////////////////////////////////////////////////////
+
+#ifndef EGGTOPSTRIP_H
+#define EGGTOPSTRIP_H
+
+#include <pandatoolbase.h>
+
+#include <eggCharacterFilter.h>
+
+////////////////////////////////////////////////////////////////////
+// 	 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
+