mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-03 10:22:45 -04:00
Added :textureswap feature to create extra palettes with swapped textures
This commit is contained in:
parent
18af305b4a
commit
81bdd7146e
@ -424,6 +424,36 @@ prepare(TextureImage *texture) {
|
|||||||
TexturePlacement *placement = new TexturePlacement(texture, this);
|
TexturePlacement *placement = new TexturePlacement(texture, this);
|
||||||
_placements.insert(placement);
|
_placements.insert(placement);
|
||||||
|
|
||||||
|
// [gjeon] update swapTexture information
|
||||||
|
TextureSwapInfo::iterator tsi = _textureSwapInfo.find(texture->get_name());
|
||||||
|
if (tsi != _textureSwapInfo.end()) {
|
||||||
|
vector_string swapTextures = (*tsi).second;
|
||||||
|
|
||||||
|
vector_string::const_iterator wi;
|
||||||
|
wi = swapTextures.begin();
|
||||||
|
++wi;
|
||||||
|
++wi;
|
||||||
|
|
||||||
|
// [gjeon] since swapped texture usually didn't mapped to any egg file
|
||||||
|
// we need to create soucreTextureImage by using original texture file's info
|
||||||
|
const string originalTextureName = (*wi);
|
||||||
|
TextureImage *originalTexture = pal->get_texture(originalTextureName);
|
||||||
|
SourceTextureImage *source = originalTexture->get_preferred_source();
|
||||||
|
const Filename originalTextureFilename = source->get_filename();
|
||||||
|
const Filename originalTextureAlphaFilename = source->get_alpha_filename();
|
||||||
|
int originalTextureAlphaFileChannel = source->get_alpha_file_channel();
|
||||||
|
|
||||||
|
++wi;
|
||||||
|
while (wi != swapTextures.end()) {
|
||||||
|
const string &swapTextureName = (*wi);
|
||||||
|
TextureImage *swapTextureImage = pal->get_texture(swapTextureName);
|
||||||
|
Filename swapTextureFilename = Filename(originalTextureFilename.get_dirname(), swapTextureName + "." + originalTextureFilename.get_extension());
|
||||||
|
swapTextureImage->get_source(swapTextureFilename, originalTextureAlphaFilename, originalTextureAlphaFileChannel);
|
||||||
|
placement->_textureSwaps.push_back(swapTextureImage);
|
||||||
|
++wi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return placement;
|
return placement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -779,3 +809,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
_margin_override = scan.get_int16();
|
_margin_override = scan.get_int16();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PaletteGroup::add_texture_swap_info
|
||||||
|
// Access: Public
|
||||||
|
// Description: Store textureswap information from textures.txa
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PaletteGroup::
|
||||||
|
add_texture_swap_info(const string sourceTextureName, const vector_string &swapTextures) {
|
||||||
|
TextureSwapInfo::iterator tsi = _textureSwapInfo.find(sourceTextureName);
|
||||||
|
if (tsi != _textureSwapInfo.end()) {
|
||||||
|
_textureSwapInfo.erase(tsi);
|
||||||
|
}
|
||||||
|
_textureSwapInfo.insert(TextureSwapInfo::value_type(sourceTextureName, swapTextures));
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "pset.h"
|
#include "pset.h"
|
||||||
#include "pvector.h"
|
#include "pvector.h"
|
||||||
|
#include "vector_string.h"
|
||||||
|
|
||||||
class EggFile;
|
class EggFile;
|
||||||
class TexturePlacement;
|
class TexturePlacement;
|
||||||
@ -89,6 +90,8 @@ public:
|
|||||||
void setup_shadow_images();
|
void setup_shadow_images();
|
||||||
void update_images(bool redo_all);
|
void update_images(bool redo_all);
|
||||||
|
|
||||||
|
void add_texture_swap_info(const string sourceTextureName, const vector_string &swapTextures);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string _dirname;
|
string _dirname;
|
||||||
int _egg_count;
|
int _egg_count;
|
||||||
@ -103,6 +106,9 @@ private:
|
|||||||
typedef pmap<TextureProperties, PalettePage *> Pages;
|
typedef pmap<TextureProperties, PalettePage *> Pages;
|
||||||
Pages _pages;
|
Pages _pages;
|
||||||
|
|
||||||
|
typedef pmap<string, vector_string> TextureSwapInfo;
|
||||||
|
TextureSwapInfo _textureSwapInfo;
|
||||||
|
|
||||||
// The TypedWritable interface follows.
|
// The TypedWritable interface follows.
|
||||||
public:
|
public:
|
||||||
static void register_with_read_factory();
|
static void register_with_read_factory();
|
||||||
|
@ -155,6 +155,8 @@ PaletteImage() {
|
|||||||
_index = 0;
|
_index = 0;
|
||||||
_new_image = false;
|
_new_image = false;
|
||||||
_got_image = false;
|
_got_image = false;
|
||||||
|
|
||||||
|
_swapped_image = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -173,10 +175,33 @@ PaletteImage(PalettePage *page, int index) :
|
|||||||
_y_size = pal->_pal_y_size;
|
_y_size = pal->_pal_y_size;
|
||||||
_new_image = true;
|
_new_image = true;
|
||||||
_got_image = false;
|
_got_image = false;
|
||||||
|
_swapped_image = 0;
|
||||||
|
|
||||||
setup_filename();
|
setup_filename();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PaletteImage::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PaletteImage::
|
||||||
|
PaletteImage(PalettePage *page, int index, unsigned swapIndex) :
|
||||||
|
_page(page),
|
||||||
|
_index(index),
|
||||||
|
_swapped_image(swapIndex)
|
||||||
|
{
|
||||||
|
_properties = page->get_properties();
|
||||||
|
_size_known = true;
|
||||||
|
_x_size = pal->_pal_x_size;
|
||||||
|
_y_size = pal->_pal_y_size;
|
||||||
|
_new_image = true;
|
||||||
|
_got_image = false;
|
||||||
|
|
||||||
|
setup_filename();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PaletteImage::get_page
|
// Function: PaletteImage::get_page
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -293,6 +318,17 @@ place(TexturePlacement *placement) {
|
|||||||
if (find_hole(x, y, placement->get_x_size(), placement->get_y_size())) {
|
if (find_hole(x, y, placement->get_x_size(), placement->get_y_size())) {
|
||||||
placement->place_at(this, x, y);
|
placement->place_at(this, x, y);
|
||||||
_placements.push_back(placement);
|
_placements.push_back(placement);
|
||||||
|
|
||||||
|
// [gjeon] create swappedImages
|
||||||
|
TexturePlacement::TextureSwaps::iterator tsi;
|
||||||
|
for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
|
||||||
|
if ((tsi - placement->_textureSwaps.begin()) >= _swappedImages.size()) {
|
||||||
|
PaletteImage *swappedImage = new PaletteImage(_page, _swappedImages.size(), tsi - placement->_textureSwaps.begin() + 1);
|
||||||
|
swappedImage->_masterPlacements = &_placements;
|
||||||
|
_swappedImages.push_back(swappedImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +350,6 @@ unplace(TexturePlacement *placement) {
|
|||||||
_placements.erase(pi);
|
_placements.erase(pi);
|
||||||
pi = find(_placements.begin(), _placements.end(), placement);
|
pi = find(_placements.begin(), _placements.end(), placement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_cleared_regions.push_back(ClearedRegion(placement));
|
_cleared_regions.push_back(ClearedRegion(placement));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +408,7 @@ check_solitary() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
void PaletteImage::
|
void PaletteImage::
|
||||||
optimal_resize() {
|
optimal_resize() {
|
||||||
if (is_empty()) {
|
if (is_empty()) { // && (_swapped_image == 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,12 +427,20 @@ optimal_resize() {
|
|||||||
success = true;
|
success = true;
|
||||||
resized_any = true;
|
resized_any = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} while (success);
|
} while (success);
|
||||||
|
|
||||||
if (resized_any) {
|
if (resized_any) {
|
||||||
nout << "Resizing "
|
nout << "Resizing "
|
||||||
<< FilenameUnifier::make_user_filename(get_filename()) << " to "
|
<< FilenameUnifier::make_user_filename(get_filename()) << " to "
|
||||||
<< _x_size << " " << _y_size << "\n";
|
<< _x_size << " " << _y_size << "\n";
|
||||||
|
|
||||||
|
// [gjeon] resize swapped images, also
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
swappedImage->resize_swapped_image(_x_size, _y_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,6 +514,22 @@ resize_image(int x_size, int y_size) {
|
|||||||
return packed;
|
return packed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PaletteImage::resize_swapped_image
|
||||||
|
// Access: Public
|
||||||
|
// Description: Attempts to resize the palette image, and repack all
|
||||||
|
// of the textures within the new size. Returns true if
|
||||||
|
// successful, false otherwise. If this fails, it will
|
||||||
|
// still result in repacking all the textures in the
|
||||||
|
// original size.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PaletteImage::
|
||||||
|
resize_swapped_image(int x_size, int y_size) {
|
||||||
|
// Finally, apply the new size and try to fit all the textures.
|
||||||
|
_x_size = x_size;
|
||||||
|
_y_size = y_size;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PaletteImage::write_placements
|
// Function: PaletteImage::write_placements
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -518,6 +577,13 @@ reset_image() {
|
|||||||
void PaletteImage::
|
void PaletteImage::
|
||||||
setup_shadow_image() {
|
setup_shadow_image() {
|
||||||
_shadow_image.make_shadow_image(_basename);
|
_shadow_image.make_shadow_image(_basename);
|
||||||
|
|
||||||
|
// [gjeon] setup shadoe_image of swappedImages
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
swappedImage->setup_shadow_image();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -576,6 +642,25 @@ update_image(bool redo_all) {
|
|||||||
needs_update = true;
|
needs_update = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [gjeon] to find out all of the swappable textures is up to date
|
||||||
|
TexturePlacement::TextureSwaps::iterator tsi;
|
||||||
|
for (tsi = placement->_textureSwaps.begin(); tsi != placement->_textureSwaps.end(); ++tsi) {
|
||||||
|
TextureImage *swapTexture = (*tsi);
|
||||||
|
|
||||||
|
if (swapTexture->is_texture_named()) {
|
||||||
|
SourceTextureImage *sourceSwapTexture = swapTexture->get_preferred_source();
|
||||||
|
|
||||||
|
if (sourceSwapTexture != (SourceTextureImage *)NULL &&
|
||||||
|
sourceSwapTexture->get_filename().compare_timestamps(get_filename()) > 0) {
|
||||||
|
// The source image is newer than the palette image; we need to
|
||||||
|
// regenerate.
|
||||||
|
placement->mark_unfilled();
|
||||||
|
needs_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,12 +670,21 @@ update_image(bool redo_all) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get_image();
|
get_image();
|
||||||
|
// [gjeon] get swapped images, too
|
||||||
|
get_swapped_images();
|
||||||
|
|
||||||
// Set to black any parts of the image that we recently unplaced.
|
// Set to black any parts of the image that we recently unplaced.
|
||||||
ClearedRegions::iterator ci;
|
ClearedRegions::iterator ci;
|
||||||
for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
|
for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
|
||||||
ClearedRegion ®ion = (*ci);
|
ClearedRegion ®ion = (*ci);
|
||||||
region.clear(_image);
|
region.clear(_image);
|
||||||
|
|
||||||
|
// [gjeon] clear swapped images also
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
region.clear(swappedImage->_image);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_cleared_regions.clear();
|
_cleared_regions.clear();
|
||||||
|
|
||||||
@ -599,6 +693,14 @@ update_image(bool redo_all) {
|
|||||||
TexturePlacement *placement = (*pi);
|
TexturePlacement *placement = (*pi);
|
||||||
if (!placement->is_filled()) {
|
if (!placement->is_filled()) {
|
||||||
placement->fill_image(_image);
|
placement->fill_image(_image);
|
||||||
|
|
||||||
|
// [gjeon] fill swapped images
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
swappedImage->update_filename();
|
||||||
|
placement->fill_swapped_image(swappedImage->_image, si - _swappedImages.begin());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,6 +711,17 @@ update_image(bool redo_all) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
release_image();
|
release_image();
|
||||||
|
|
||||||
|
// [gjeon] write and release swapped images
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
swappedImage->write(swappedImage->_image);
|
||||||
|
if (pal->_shadow_color_type != (PNMFileType *)NULL) {
|
||||||
|
swappedImage->_shadow_image.write(swappedImage->_image);
|
||||||
|
}
|
||||||
|
swappedImage->release_image();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -662,7 +775,6 @@ update_filename() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PaletteImage::setup_filename
|
// Function: PaletteImage::setup_filename
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -714,6 +826,11 @@ setup_filename() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_swapped_image > 0) {
|
||||||
|
_basename += "_swp_";
|
||||||
|
_basename += format_string(_swapped_image);
|
||||||
|
}
|
||||||
|
|
||||||
// We must end the basename with a dot, so that it does not appear
|
// We must end the basename with a dot, so that it does not appear
|
||||||
// to have a filename extension. Otherwise, an embedded dot in the
|
// to have a filename extension. Otherwise, an embedded dot in the
|
||||||
// group's name would make everything following appear to be an
|
// group's name would make everything following appear to be an
|
||||||
@ -849,6 +966,72 @@ get_image() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PaletteImage::get_swapped_image
|
||||||
|
// Access: Public
|
||||||
|
// Description: Reads or generates the PNMImage for swapped textures
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PaletteImage::
|
||||||
|
get_swapped_image(int index) {
|
||||||
|
if (_got_image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_new_image) {
|
||||||
|
if (pal->_shadow_color_type != (PNMFileType *)NULL) {
|
||||||
|
if (_shadow_image.get_filename().exists() && _shadow_image.read(_image)) {
|
||||||
|
_got_image = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (get_filename().exists() && read(_image)) {
|
||||||
|
_got_image = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nout << "Generating new "
|
||||||
|
<< FilenameUnifier::make_user_filename(get_filename()) << "\n";
|
||||||
|
|
||||||
|
// We won't be using this any more.
|
||||||
|
_cleared_regions.clear();
|
||||||
|
|
||||||
|
_image.clear(get_x_size(), get_y_size(), _properties.get_num_channels());
|
||||||
|
_image.fill(pal->_background[0], pal->_background[1], pal->_background[2]);
|
||||||
|
if (_image.has_alpha()) {
|
||||||
|
_image.alpha_fill(pal->_background[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_new_image = false;
|
||||||
|
_got_image = true;
|
||||||
|
|
||||||
|
// Now fill up the image.
|
||||||
|
Placements::iterator pi;
|
||||||
|
for (pi = _masterPlacements->begin(); pi != _masterPlacements->end(); ++pi) {
|
||||||
|
TexturePlacement *placement = (*pi);
|
||||||
|
if (placement->_textureSwaps.size() > index)
|
||||||
|
placement->fill_swapped_image(_image, index);
|
||||||
|
else
|
||||||
|
placement->fill_image(_image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PaletteImage::get_swapped_images
|
||||||
|
// Access: Public
|
||||||
|
// Description: Reads or generates the PNMImage that corresponds to
|
||||||
|
// the palette as it is known so far.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PaletteImage::
|
||||||
|
get_swapped_images() {
|
||||||
|
SwappedImages::iterator si;
|
||||||
|
for (si = _swappedImages.begin(); si != _swappedImages.end(); ++si) {
|
||||||
|
PaletteImage *swappedImage = (*si);
|
||||||
|
swappedImage->get_swapped_image(si - _swappedImages.begin());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PaletteImage::release_image
|
// Function: PaletteImage::release_image
|
||||||
// Access: Public
|
// Access: Public
|
||||||
|
@ -39,6 +39,7 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
PaletteImage(PalettePage *page, int index);
|
PaletteImage(PalettePage *page, int index);
|
||||||
|
PaletteImage(PalettePage *page, int index, unsigned swapIndex);
|
||||||
|
|
||||||
PalettePage *get_page() const;
|
PalettePage *get_page() const;
|
||||||
|
|
||||||
@ -52,6 +53,7 @@ public:
|
|||||||
|
|
||||||
void optimal_resize();
|
void optimal_resize();
|
||||||
bool resize_image(int x_size, int y_size);
|
bool resize_image(int x_size, int y_size);
|
||||||
|
void resize_swapped_image(int x_size, int y_size);
|
||||||
|
|
||||||
void write_placements(ostream &out, int indent_level = 0) const;
|
void write_placements(ostream &out, int indent_level = 0) const;
|
||||||
void reset_image();
|
void reset_image();
|
||||||
@ -67,6 +69,8 @@ private:
|
|||||||
void get_image();
|
void get_image();
|
||||||
void release_image();
|
void release_image();
|
||||||
void remove_image();
|
void remove_image();
|
||||||
|
void get_swapped_image(int index);
|
||||||
|
void get_swapped_images();
|
||||||
|
|
||||||
// The ClearedRegion object keeps track of TexturePlacements that
|
// The ClearedRegion object keeps track of TexturePlacements that
|
||||||
// were recently removed and thus need to be set to black.
|
// were recently removed and thus need to be set to black.
|
||||||
@ -92,6 +96,8 @@ private:
|
|||||||
typedef pvector<TexturePlacement *> Placements;
|
typedef pvector<TexturePlacement *> Placements;
|
||||||
Placements _placements;
|
Placements _placements;
|
||||||
|
|
||||||
|
Placements *_masterPlacements;
|
||||||
|
|
||||||
PalettePage *_page;
|
PalettePage *_page;
|
||||||
int _index;
|
int _index;
|
||||||
string _basename;
|
string _basename;
|
||||||
@ -100,8 +106,13 @@ private:
|
|||||||
bool _got_image;
|
bool _got_image;
|
||||||
PNMImage _image;
|
PNMImage _image;
|
||||||
|
|
||||||
|
unsigned _swapped_image; // 0 for non swapped image
|
||||||
|
|
||||||
ImageFile _shadow_image;
|
ImageFile _shadow_image;
|
||||||
|
|
||||||
|
typedef pvector<PaletteImage *> SwappedImages;
|
||||||
|
SwappedImages _swappedImages;
|
||||||
|
|
||||||
// The TypedWritable interface follows.
|
// The TypedWritable interface follows.
|
||||||
public:
|
public:
|
||||||
static void register_with_read_factory();
|
static void register_with_read_factory();
|
||||||
|
@ -37,7 +37,7 @@ Palettizer *pal = (Palettizer *)NULL;
|
|||||||
// allows us to easily update egg-palettize to write out additional
|
// allows us to easily update egg-palettize to write out additional
|
||||||
// information to its pi file, without having it increment the bam
|
// information to its pi file, without having it increment the bam
|
||||||
// version number for all bam and boo files anywhere in the world.
|
// version number for all bam and boo files anywhere in the world.
|
||||||
int Palettizer::_pi_version = 19;
|
int Palettizer::_pi_version = 20;
|
||||||
// Updated to version 8 on 3/20/03 to remove extensions from texture key names.
|
// Updated to version 8 on 3/20/03 to remove extensions from texture key names.
|
||||||
// Updated to version 9 on 4/13/03 to add a few properties in various places.
|
// Updated to version 9 on 4/13/03 to add a few properties in various places.
|
||||||
// Updated to version 10 on 4/15/03 to add _alpha_file_channel.
|
// Updated to version 10 on 4/15/03 to add _alpha_file_channel.
|
||||||
@ -50,7 +50,7 @@ int Palettizer::_pi_version = 19;
|
|||||||
// Updated to version 17 on 3/02/07 to add TextureImage::_txa_wrap_u etc.
|
// Updated to version 17 on 3/02/07 to add TextureImage::_txa_wrap_u etc.
|
||||||
// Updated to version 18 on 5/13/08 to add TextureProperties::_quality_level.
|
// Updated to version 18 on 5/13/08 to add TextureProperties::_quality_level.
|
||||||
// Updated to version 19 on 7/16/09 to add PaletteGroup::_override_margin
|
// Updated to version 19 on 7/16/09 to add PaletteGroup::_override_margin
|
||||||
|
// Updated to version 20 on 7/27/09 to add TexturePlacement::_swapTextures
|
||||||
|
|
||||||
int Palettizer::_min_pi_version = 8;
|
int Palettizer::_min_pi_version = 8;
|
||||||
// Dropped support for versions 7 and below on 7/14/03.
|
// Dropped support for versions 7 and below on 7/14/03.
|
||||||
@ -562,7 +562,6 @@ process_all(bool force_texture_read, const Filename &state_filename) {
|
|||||||
EggFiles::const_iterator efi;
|
EggFiles::const_iterator efi;
|
||||||
for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
|
for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
|
||||||
EggFile *egg_file = (*efi).second;
|
EggFile *egg_file = (*efi).second;
|
||||||
|
|
||||||
egg_file->pre_txa_file();
|
egg_file->pre_txa_file();
|
||||||
_txa_file.match_egg(egg_file);
|
_txa_file.match_egg(egg_file);
|
||||||
egg_file->post_txa_file();
|
egg_file->post_txa_file();
|
||||||
@ -583,7 +582,6 @@ process_all(bool force_texture_read, const Filename &state_filename) {
|
|||||||
// .txa file.
|
// .txa file.
|
||||||
for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
|
for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
|
||||||
TextureImage *texture = (*ti).second;
|
TextureImage *texture = (*ti).second;
|
||||||
|
|
||||||
if (force_texture_read || texture->is_newer_than(state_filename)) {
|
if (force_texture_read || texture->is_newer_than(state_filename)) {
|
||||||
texture->read_source_image();
|
texture->read_source_image();
|
||||||
}
|
}
|
||||||
|
@ -885,6 +885,109 @@ fill_image(PNMImage &image) {
|
|||||||
_texture->release_source_image();
|
_texture->release_source_image();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TexturePlacement::fill_swapped_image
|
||||||
|
// Access: Public
|
||||||
|
// Description: Fills in the rectangle of the swapped palette image
|
||||||
|
// represented by the texture placement with the image
|
||||||
|
// pixels.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void TexturePlacement::
|
||||||
|
fill_swapped_image(PNMImage &image, int index) {
|
||||||
|
nassertv(is_placed());
|
||||||
|
|
||||||
|
_is_filled = true;
|
||||||
|
|
||||||
|
// We determine the pixels to place the source image at by
|
||||||
|
// transforming the unit texture box: the upper-left and lower-right
|
||||||
|
// corners. These corners, in the final texture coordinate space,
|
||||||
|
// represent where on the palette image the original texture should
|
||||||
|
// be located.
|
||||||
|
|
||||||
|
LMatrix3d transform;
|
||||||
|
compute_tex_matrix(transform);
|
||||||
|
TexCoordd ul = TexCoordd(0.0, 1.0) * transform;
|
||||||
|
TexCoordd lr = TexCoordd(1.0, 0.0) * transform;
|
||||||
|
|
||||||
|
// Now we convert those texture coordinates back to pixel units.
|
||||||
|
int pal_x_size = _image->get_x_size();
|
||||||
|
int pal_y_size = _image->get_y_size();
|
||||||
|
|
||||||
|
int top = (int)floor((1.0 - ul[1]) * pal_y_size + 0.5);
|
||||||
|
int left = (int)floor(ul[0] * pal_x_size + 0.5);
|
||||||
|
int bottom = (int)floor((1.0 - lr[1]) * pal_y_size + 0.5);
|
||||||
|
int right = (int)floor(lr[0] * pal_x_size + 0.5);
|
||||||
|
|
||||||
|
// And now we can determine the size to scale the image to based on
|
||||||
|
// that. This may not be the same as texture->size() because of
|
||||||
|
// margins.
|
||||||
|
int x_size = right - left;
|
||||||
|
int y_size = bottom - top;
|
||||||
|
nassertv(x_size >= 0 && y_size >= 0);
|
||||||
|
|
||||||
|
// Now we get a PNMImage that represents the swapped texture at that
|
||||||
|
// size.
|
||||||
|
TextureSwaps::iterator tsi;
|
||||||
|
tsi = _textureSwaps.begin() + index;
|
||||||
|
TextureImage *swapTexture = (*tsi);
|
||||||
|
const PNMImage &source_full = swapTexture->read_source_image();
|
||||||
|
if (!source_full.is_valid()) {
|
||||||
|
flag_error_image(image);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PNMImage source(x_size, y_size, source_full.get_num_channels(),
|
||||||
|
source_full.get_maxval());
|
||||||
|
source.quick_filter_from(source_full);
|
||||||
|
|
||||||
|
bool alpha = image.has_alpha();
|
||||||
|
bool source_alpha = source.has_alpha();
|
||||||
|
|
||||||
|
// Now copy the pixels. We do this by walking through the
|
||||||
|
// rectangular region on the palette image that we have reserved for
|
||||||
|
// this texture; for each pixel in this region, we determine its
|
||||||
|
// appropriate color based on its relation to the actual texture
|
||||||
|
// image location (determined above), and on whether the texture
|
||||||
|
// wraps or clamps.
|
||||||
|
for (int y = _placed._y; y < _placed._y + _placed._y_size; y++) {
|
||||||
|
int sy = y - top;
|
||||||
|
|
||||||
|
if (_placed._wrap_v == EggTexture::WM_clamp) {
|
||||||
|
// Clamp at [0, y_size).
|
||||||
|
sy = max(min(sy, y_size - 1), 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Wrap: sign-independent modulo.
|
||||||
|
sy = (sy < 0) ? y_size - 1 - ((-sy - 1) % y_size) : sy % y_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int x = _placed._x; x < _placed._x + _placed._x_size; x++) {
|
||||||
|
int sx = x - left;
|
||||||
|
|
||||||
|
if (_placed._wrap_u == EggTexture::WM_clamp) {
|
||||||
|
// Clamp at [0, x_size).
|
||||||
|
sx = max(min(sx, x_size - 1), 0);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Wrap: sign-independent modulo.
|
||||||
|
sx = (sx < 0) ? x_size - 1 - ((-sx - 1) % x_size) : sx % x_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
image.set_xel(x, y, source.get_xel(sx, sy));
|
||||||
|
if (alpha) {
|
||||||
|
if (source_alpha) {
|
||||||
|
image.set_alpha(x, y, source.get_alpha(sx, sy));
|
||||||
|
} else {
|
||||||
|
image.set_alpha(x, y, 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
swapTexture->release_source_image();
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TexturePlacement::flag_error_image
|
// Function: TexturePlacement::flag_error_image
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -1003,6 +1106,12 @@ write_datagram(BamWriter *writer, Datagram &datagram) {
|
|||||||
writer->write_pointer(datagram, (*ri));
|
writer->write_pointer(datagram, (*ri));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
datagram.add_int32(_textureSwaps.size());
|
||||||
|
TextureSwaps::const_iterator tsi;
|
||||||
|
for (tsi = _textureSwaps.begin(); tsi != _textureSwaps.end(); ++tsi) {
|
||||||
|
writer->write_pointer(datagram, (*tsi));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
@ -1046,6 +1155,13 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < _num_textureSwaps; i++) {
|
||||||
|
TextureImage *swapTexture;
|
||||||
|
DCAST_INTO_R(swapTexture, p_list[index], index);
|
||||||
|
_textureSwaps.push_back(swapTexture);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1094,6 +1210,13 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||||||
|
|
||||||
_num_references = scan.get_int32();
|
_num_references = scan.get_int32();
|
||||||
manager->read_pointers(scan, _num_references);
|
manager->read_pointers(scan, _num_references);
|
||||||
|
|
||||||
|
if (Palettizer::_read_pi_version >= 20) {
|
||||||
|
_num_textureSwaps = scan.get_int32();
|
||||||
|
} else {
|
||||||
|
_num_textureSwaps = 0;
|
||||||
|
}
|
||||||
|
manager->read_pointers(scan, _num_textureSwaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,8 +91,12 @@ public:
|
|||||||
bool is_filled() const;
|
bool is_filled() const;
|
||||||
void mark_unfilled();
|
void mark_unfilled();
|
||||||
void fill_image(PNMImage &image);
|
void fill_image(PNMImage &image);
|
||||||
|
void fill_swapped_image(PNMImage &image, int index);
|
||||||
void flag_error_image(PNMImage &image);
|
void flag_error_image(PNMImage &image);
|
||||||
|
|
||||||
|
typedef pvector<TextureImage *> TextureSwaps;
|
||||||
|
TextureSwaps _textureSwaps;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void compute_size_from_uvs(const TexCoordd &min_uv, const TexCoordd &max_uv);
|
void compute_size_from_uvs(const TexCoordd &min_uv, const TexCoordd &max_uv);
|
||||||
|
|
||||||
@ -127,8 +131,8 @@ private:
|
|||||||
// This value is only filled in while reading from the bam file;
|
// This value is only filled in while reading from the bam file;
|
||||||
// don't use it otherwise.
|
// don't use it otherwise.
|
||||||
int _num_references;
|
int _num_references;
|
||||||
|
|
||||||
int _margin_override;
|
int _margin_override;
|
||||||
|
int _num_textureSwaps;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static TypeHandle get_class_type() {
|
static TypeHandle get_class_type() {
|
||||||
|
@ -91,6 +91,9 @@ read(istream &in, const string &filename) {
|
|||||||
} else if (words[0] == ":cutout") {
|
} else if (words[0] == ":cutout") {
|
||||||
okflag = parse_cutout_line(words);
|
okflag = parse_cutout_line(words);
|
||||||
|
|
||||||
|
} else if (words[0] == ":textureswap") {
|
||||||
|
okflag = parse_textureswap_line(words);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nout << "Invalid keyword " << words[0] << "\n";
|
nout << "Invalid keyword " << words[0] << "\n";
|
||||||
okflag = false;
|
okflag = false;
|
||||||
@ -577,6 +580,7 @@ parse_remap_line(const vector_string &words) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: TxaFile::parse_cutout_line
|
// Function: TxaFile::parse_cutout_line
|
||||||
// Access: Private
|
// Access: Private
|
||||||
@ -608,3 +612,36 @@ parse_cutout_line(const vector_string &words) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: TxaFile::parse_textureswap_line
|
||||||
|
// Access: Private
|
||||||
|
// Description: Handles the line in a .txa file that begins with the
|
||||||
|
// keyword ":textureswap" and indicates the relationships
|
||||||
|
// between textures to be swapped.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool TxaFile::
|
||||||
|
parse_textureswap_line(const vector_string &words) {
|
||||||
|
vector_string::const_iterator wi;
|
||||||
|
wi = words.begin();
|
||||||
|
assert (wi != words.end());
|
||||||
|
++wi;
|
||||||
|
|
||||||
|
const string &group_name = (*wi);
|
||||||
|
PaletteGroup *group = pal->get_palette_group(group_name);
|
||||||
|
++wi;
|
||||||
|
|
||||||
|
string sourceTextureName = (*wi);
|
||||||
|
++wi;
|
||||||
|
|
||||||
|
//vector_string swapTextures;
|
||||||
|
//copy(words.begin(), words.end(), swapTextures);
|
||||||
|
//group->add_texture_swap_info(sourceTextureName, swapTextures);
|
||||||
|
size_t dot = sourceTextureName.rfind('.');
|
||||||
|
if (dot != string::npos) {
|
||||||
|
sourceTextureName = sourceTextureName.substr(0, dot);
|
||||||
|
}
|
||||||
|
group->add_texture_swap_info(sourceTextureName, words);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -55,6 +55,7 @@ private:
|
|||||||
bool parse_round_line(const vector_string &words);
|
bool parse_round_line(const vector_string &words);
|
||||||
bool parse_remap_line(const vector_string &words);
|
bool parse_remap_line(const vector_string &words);
|
||||||
bool parse_cutout_line(const vector_string &words);
|
bool parse_cutout_line(const vector_string &words);
|
||||||
|
bool parse_textureswap_line(const vector_string &words);
|
||||||
|
|
||||||
typedef pvector<TxaLine> Lines;
|
typedef pvector<TxaLine> Lines;
|
||||||
Lines _lines;
|
Lines _lines;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user