diff --git a/pandatool/src/palettizer/eggFile.cxx b/pandatool/src/palettizer/eggFile.cxx index eb43454170..560b602eb4 100644 --- a/pandatool/src/palettizer/eggFile.cxx +++ b/pandatool/src/palettizer/eggFile.cxx @@ -49,10 +49,11 @@ TypeHandle EggFile::_type_handle; EggFile:: EggFile() { _data = (EggData *)NULL; + _first_txa_match = false; _default_group = (PaletteGroup *)NULL; _is_surprise = true; _is_stale = true; - _first_txa_match = false; + _had_data = false; } //////////////////////////////////////////////////////////////////// @@ -67,6 +68,7 @@ from_command_line(EggData *data, const Filename &dest_filename, const string &egg_comment) { _data = data; + _had_data = true; remove_backstage(_data); // We save the current directory at the time the egg file appeared @@ -468,14 +470,25 @@ choose_placements() { //////////////////////////////////////////////////////////////////// // Function: EggFile::has_data // Access: Public -// Description: Returns true if the EggData for this EggFile has ever -// been loaded. +// Description: Returns true if the EggData for this EggFile has +// been loaded, and not yet released. //////////////////////////////////////////////////////////////////// bool EggFile:: has_data() const { return (_data != (EggData *)NULL); } +//////////////////////////////////////////////////////////////////// +// Function: EggFile::had_data +// Access: Public +// Description: Returns true if the EggData for this EggFile has ever +// been loaded. +//////////////////////////////////////////////////////////////////// +bool EggFile:: +had_data() const { + return _had_data; +} + //////////////////////////////////////////////////////////////////// // Function: EggFile::update_egg // Access: Public @@ -485,6 +498,8 @@ has_data() const { //////////////////////////////////////////////////////////////////// void EggFile:: update_egg() { + nassertv(_data != (EggData *)NULL); + Textures::iterator ti; for (ti = _textures.begin(); ti != _textures.end(); ++ti) { TextureReference *reference = (*ti); @@ -515,6 +530,10 @@ remove_egg() { // is only valid to call this if it has not already been // read in, e.g. from the command line. Returns true if // successful, false if there is an error. +// +// This may also be called after a previous call to +// release_egg_data(), in order to re-read the same egg +// file. //////////////////////////////////////////////////////////////////// bool EggFile:: read_egg() { @@ -529,13 +548,24 @@ read_egg() { return false; } - EggData *data = new EggData; + PT(EggData) data = new EggData; if (!data->read(_source_filename, user_source_filename)) { // Failure reading. - delete data; return false; } + + // Extract the set of textures referenced by this egg file. + EggTextureCollection tc; + tc.find_used_textures(_data); + + // Make sure each tref name is unique within a given file. + tc.uniquify_trefs(); + + // Now build up a list of new TextureReference objects that + // represent the textures actually used and their uv range, etc. + Textures new_textures; + // We want to search for filenames based on the egg directory, and // also on our current directory from which we originally loaded the // egg file. This is important because it's possible the egg file @@ -551,20 +581,43 @@ read_egg() { if (!data->load_externals()) { // Failure reading an external. - delete data; return false; } _data = data; + _had_data = true; remove_backstage(_data); - // Replace the comment that shows how we first generated the egg - // file. - _data->insert(_data->begin(), new EggComment("", _egg_comment)); + // Insert a comment that shows how we first generated the egg file. + PT(EggNode) comment = new EggComment("", _egg_comment); + _data->insert(_data->begin(), comment); + + if (!_textures.empty()) { + // If we already have textures, assume we're re-reading the file. + rescan_textures(); + } return true; } +//////////////////////////////////////////////////////////////////// +// Function: EggFile::release_egg_data +// Access: Public +// Description: Releases the memory that was loaded by a previous +// call to read_egg(). +//////////////////////////////////////////////////////////////////// +void EggFile:: +release_egg_data() { + if (_data != (EggData *)NULL) { + _data = NULL; + } + Textures::iterator ti; + for (ti = _textures.begin(); ti != _textures.end(); ++ti) { + TextureReference *reference = (*ti); + reference->release_egg_data(); + } +} + //////////////////////////////////////////////////////////////////// // Function: EggFile::write_egg // Access: Public @@ -663,6 +716,51 @@ remove_backstage(EggGroupNode *node) { } } +//////////////////////////////////////////////////////////////////// +// Function: EggFile::rescan_textures +// Access: Private +// Description: After reloading the egg file for the second time in a +// given session, rematches the texture pointers with +// the TextureReference objects. +//////////////////////////////////////////////////////////////////// +void EggFile:: +rescan_textures() { + nassertv(_data != (EggData *)NULL); + + // Extract the set of textures referenced by this egg file. + EggTextureCollection tc; + tc.find_used_textures(_data); + + // Make sure each tref name is unique within a given file. + tc.uniquify_trefs(); + + typedef pmap ByTRefName; + ByTRefName by_tref_name; + for (Textures::const_iterator ti = _textures.begin(); + ti != _textures.end(); + ++ti) { + TextureReference *ref = (*ti); + by_tref_name[ref->get_tref_name()] = ref; + } + + EggTextureCollection::iterator eti; + for (eti = tc.begin(); eti != tc.end(); ++eti) { + EggTexture *egg_tex = (*eti); + + ByTRefName::const_iterator tni = by_tref_name.find(egg_tex->get_name()); + if (tni == by_tref_name.end()) { + // We didn't find this TRef name last time around! + nout << _source_filename.get_basename() + << " modified during session--TRef " << egg_tex->get_name() + << " is new!\n"; + + } else { + TextureReference *ref = (*tni).second; + ref->rebind_egg_data(_data, egg_tex); + } + } +} + //////////////////////////////////////////////////////////////////// // Function: EggFile::register_with_read_factory // Access: Public, Static diff --git a/pandatool/src/palettizer/eggFile.h b/pandatool/src/palettizer/eggFile.h index 360a46ba7f..7a9e71fa9c 100644 --- a/pandatool/src/palettizer/eggFile.h +++ b/pandatool/src/palettizer/eggFile.h @@ -23,14 +23,13 @@ #include "paletteGroups.h" #include "textureReference.h" - +#include "eggData.h" #include "filename.h" #include "namable.h" #include "typedWritable.h" - +#include "pointerTo.h" #include "pset.h" -class EggData; class TextureImage; //////////////////////////////////////////////////////////////////// @@ -71,10 +70,12 @@ public: void choose_placements(); bool has_data() const; + bool had_data() const; void update_egg(); void remove_egg(); bool read_egg(); + void release_egg_data(); bool write_egg(); void write_description(ostream &out, int indent_level = 0) const; @@ -82,9 +83,10 @@ public: private: void remove_backstage(EggGroupNode *node); + void rescan_textures(); private: - EggData *_data; + PT(EggData) _data; Filename _current_directory; Filename _source_filename; Filename _dest_filename; @@ -99,6 +101,7 @@ private: PaletteGroups _complete_groups; bool _is_surprise; bool _is_stale; + bool _had_data; // The TypedWritable interface follows. diff --git a/pandatool/src/palettizer/palettizer.cxx b/pandatool/src/palettizer/palettizer.cxx index ffb3a77aad..80b1feb7f9 100644 --- a/pandatool/src/palettizer/palettizer.cxx +++ b/pandatool/src/palettizer/palettizer.cxx @@ -652,7 +652,7 @@ generate_images(bool redo_all) { bool Palettizer:: read_stale_eggs(bool redo_all) { bool okflag = true; - + pvector invalid_eggs; EggFiles::iterator ei; @@ -666,6 +666,7 @@ read_stale_eggs(bool redo_all) { } else { egg_file->scan_textures(); egg_file->choose_placements(); + egg_file->release_egg_data(); } } } @@ -697,10 +698,22 @@ write_eggs() { EggFiles::iterator ei; for (ei = _egg_files.begin(); ei != _egg_files.end(); ++ei) { EggFile *egg_file = (*ei).second; - if (egg_file->has_data()) { - egg_file->update_egg(); - if (!egg_file->write_egg()) { - okflag = false; + if (egg_file->had_data()) { + if (!egg_file->has_data()) { + // Re-read the egg file. + bool read_ok = egg_file->read_egg(); + if (!read_ok) { + nout << "Error! Unable to re-read egg file.\n"; + okflag = false; + } + } + + if (egg_file->has_data()) { + egg_file->update_egg(); + if (!egg_file->write_egg()) { + okflag = false; + } + egg_file->release_egg_data(); } } } diff --git a/pandatool/src/palettizer/textureMemoryCounter.cxx b/pandatool/src/palettizer/textureMemoryCounter.cxx index c63e5facb4..19c4948f86 100644 --- a/pandatool/src/palettizer/textureMemoryCounter.cxx +++ b/pandatool/src/palettizer/textureMemoryCounter.cxx @@ -78,13 +78,13 @@ add_placement(TexturePlacement *placement) { } else { DestTextureImage *dest = placement->get_dest(); - nassertv(dest != (DestTextureImage *)NULL); - - int bytes = count_bytes(dest); - add_texture(texture, bytes); - - _bytes += bytes; - _num_unplaced++; + if (dest != (DestTextureImage *)NULL) { + int bytes = count_bytes(dest); + add_texture(texture, bytes); + + _bytes += bytes; + _num_unplaced++; + } } } diff --git a/pandatool/src/palettizer/texturePlacement.cxx b/pandatool/src/palettizer/texturePlacement.cxx index 1daf64dc23..ca80169553 100644 --- a/pandatool/src/palettizer/texturePlacement.cxx +++ b/pandatool/src/palettizer/texturePlacement.cxx @@ -862,6 +862,8 @@ fill_image(PNMImage &image) { } } } + + _texture->release_source_image(); } //////////////////////////////////////////////////////////////////// diff --git a/pandatool/src/palettizer/textureReference.cxx b/pandatool/src/palettizer/textureReference.cxx index 5528ab740c..0cc57e68a6 100644 --- a/pandatool/src/palettizer/textureReference.cxx +++ b/pandatool/src/palettizer/textureReference.cxx @@ -154,6 +154,34 @@ from_egg_quick(const TextureReference &other) { _egg_data = other._egg_data; } +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::release_egg_data +// Access: Public +// Description: Called to indicate that the EggData previously passed +// to from_egg() is about to be deallocated, and all of +// its pointers should be cleared. +//////////////////////////////////////////////////////////////////// +void TextureReference:: +release_egg_data() { + _egg_tex = NULL; + _egg_data = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: TextureReference::rebind_egg_data +// Access: Public +// Description: After an EggData has previously been released via +// release_egg_data(), this can be called to indicate +// that the egg file has been reloaded and we should +// assign the indicated pointers. +//////////////////////////////////////////////////////////////////// +void TextureReference:: +rebind_egg_data(EggData *data, EggTexture *egg_tex) { + nassertv(_tref_name == egg_tex->get_name()); + _egg_data = data; + _egg_tex = egg_tex; +} + //////////////////////////////////////////////////////////////////// // Function: TextureReference::get_egg_file // Access: Public diff --git a/pandatool/src/palettizer/textureReference.h b/pandatool/src/palettizer/textureReference.h index 15a2a5fa04..4df513fcee 100644 --- a/pandatool/src/palettizer/textureReference.h +++ b/pandatool/src/palettizer/textureReference.h @@ -51,6 +51,8 @@ public: void from_egg(EggFile *egg_file, EggData *data, EggTexture *egg_tex); void from_egg_quick(const TextureReference &other); + void release_egg_data(); + void rebind_egg_data(EggData *data, EggTexture *egg_tex); EggFile *get_egg_file() const; SourceTextureImage *get_source() const; @@ -79,6 +81,7 @@ public: void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; + private: bool get_uv_range(EggGroupNode *group, Palettizer::RemapUV remap); void update_uv_range(EggGroupNode *group, Palettizer::RemapUV remap);