mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 16:58:40 -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);
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -779,3 +809,17 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
_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 "pvector.h"
|
||||
#include "vector_string.h"
|
||||
|
||||
class EggFile;
|
||||
class TexturePlacement;
|
||||
@ -89,6 +90,8 @@ public:
|
||||
void setup_shadow_images();
|
||||
void update_images(bool redo_all);
|
||||
|
||||
void add_texture_swap_info(const string sourceTextureName, const vector_string &swapTextures);
|
||||
|
||||
private:
|
||||
string _dirname;
|
||||
int _egg_count;
|
||||
@ -103,6 +106,9 @@ private:
|
||||
typedef pmap<TextureProperties, PalettePage *> Pages;
|
||||
Pages _pages;
|
||||
|
||||
typedef pmap<string, vector_string> TextureSwapInfo;
|
||||
TextureSwapInfo _textureSwapInfo;
|
||||
|
||||
// The TypedWritable interface follows.
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
@ -155,6 +155,8 @@ PaletteImage() {
|
||||
_index = 0;
|
||||
_new_image = false;
|
||||
_got_image = false;
|
||||
|
||||
_swapped_image = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
@ -173,10 +175,33 @@ PaletteImage(PalettePage *page, int index) :
|
||||
_y_size = pal->_pal_y_size;
|
||||
_new_image = true;
|
||||
_got_image = false;
|
||||
_swapped_image = 0;
|
||||
|
||||
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
|
||||
// Access: Public
|
||||
@ -293,6 +318,17 @@ place(TexturePlacement *placement) {
|
||||
if (find_hole(x, y, placement->get_x_size(), placement->get_y_size())) {
|
||||
placement->place_at(this, x, y);
|
||||
_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;
|
||||
}
|
||||
|
||||
@ -314,7 +350,6 @@ unplace(TexturePlacement *placement) {
|
||||
_placements.erase(pi);
|
||||
pi = find(_placements.begin(), _placements.end(), placement);
|
||||
}
|
||||
|
||||
_cleared_regions.push_back(ClearedRegion(placement));
|
||||
}
|
||||
|
||||
@ -373,7 +408,7 @@ check_solitary() {
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PaletteImage::
|
||||
optimal_resize() {
|
||||
if (is_empty()) {
|
||||
if (is_empty()) { // && (_swapped_image == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -392,12 +427,20 @@ optimal_resize() {
|
||||
success = true;
|
||||
resized_any = true;
|
||||
}
|
||||
|
||||
} while (success);
|
||||
|
||||
if (resized_any) {
|
||||
nout << "Resizing "
|
||||
<< FilenameUnifier::make_user_filename(get_filename()) << " to "
|
||||
<< _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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// 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
|
||||
// Access: Public
|
||||
@ -518,6 +577,13 @@ reset_image() {
|
||||
void PaletteImage::
|
||||
setup_shadow_image() {
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
||||
// [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();
|
||||
// [gjeon] get swapped images, too
|
||||
get_swapped_images();
|
||||
|
||||
// Set to black any parts of the image that we recently unplaced.
|
||||
ClearedRegions::iterator ci;
|
||||
for (ci = _cleared_regions.begin(); ci != _cleared_regions.end(); ++ci) {
|
||||
ClearedRegion ®ion = (*ci);
|
||||
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();
|
||||
|
||||
@ -599,6 +693,14 @@ update_image(bool redo_all) {
|
||||
TexturePlacement *placement = (*pi);
|
||||
if (!placement->is_filled()) {
|
||||
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();
|
||||
|
||||
// [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;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PaletteImage::setup_filename
|
||||
// Access: Private
|
||||
@ -713,6 +825,11 @@ setup_filename() {
|
||||
++si;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// to have a filename extension. Otherwise, an embedded dot in the
|
||||
@ -731,7 +848,7 @@ setup_filename() {
|
||||
if (_shadow_image.make_shadow_image(_basename)) {
|
||||
any_changed = true;
|
||||
}
|
||||
|
||||
|
||||
return any_changed;
|
||||
}
|
||||
|
||||
@ -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
|
||||
// Access: Public
|
||||
|
@ -39,6 +39,7 @@ private:
|
||||
|
||||
public:
|
||||
PaletteImage(PalettePage *page, int index);
|
||||
PaletteImage(PalettePage *page, int index, unsigned swapIndex);
|
||||
|
||||
PalettePage *get_page() const;
|
||||
|
||||
@ -52,6 +53,7 @@ public:
|
||||
|
||||
void optimal_resize();
|
||||
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 reset_image();
|
||||
@ -67,6 +69,8 @@ private:
|
||||
void get_image();
|
||||
void release_image();
|
||||
void remove_image();
|
||||
void get_swapped_image(int index);
|
||||
void get_swapped_images();
|
||||
|
||||
// The ClearedRegion object keeps track of TexturePlacements that
|
||||
// were recently removed and thus need to be set to black.
|
||||
@ -92,6 +96,8 @@ private:
|
||||
typedef pvector<TexturePlacement *> Placements;
|
||||
Placements _placements;
|
||||
|
||||
Placements *_masterPlacements;
|
||||
|
||||
PalettePage *_page;
|
||||
int _index;
|
||||
string _basename;
|
||||
@ -99,9 +105,14 @@ private:
|
||||
bool _new_image;
|
||||
bool _got_image;
|
||||
PNMImage _image;
|
||||
|
||||
unsigned _swapped_image; // 0 for non swapped image
|
||||
|
||||
ImageFile _shadow_image;
|
||||
|
||||
typedef pvector<PaletteImage *> SwappedImages;
|
||||
SwappedImages _swappedImages;
|
||||
|
||||
// The TypedWritable interface follows.
|
||||
public:
|
||||
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
|
||||
// information to its pi file, without having it increment the bam
|
||||
// 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 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.
|
||||
@ -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 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 20 on 7/27/09 to add TexturePlacement::_swapTextures
|
||||
|
||||
int Palettizer::_min_pi_version = 8;
|
||||
// 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;
|
||||
for (efi = _egg_files.begin(); efi != _egg_files.end(); ++efi) {
|
||||
EggFile *egg_file = (*efi).second;
|
||||
|
||||
egg_file->pre_txa_file();
|
||||
_txa_file.match_egg(egg_file);
|
||||
egg_file->post_txa_file();
|
||||
@ -583,7 +582,6 @@ process_all(bool force_texture_read, const Filename &state_filename) {
|
||||
// .txa file.
|
||||
for (ti = _textures.begin(); ti != _textures.end(); ++ti) {
|
||||
TextureImage *texture = (*ti).second;
|
||||
|
||||
if (force_texture_read || texture->is_newer_than(state_filename)) {
|
||||
texture->read_source_image();
|
||||
}
|
||||
|
@ -885,6 +885,109 @@ fill_image(PNMImage &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
|
||||
// Access: Public
|
||||
@ -1003,6 +1106,12 @@ write_datagram(BamWriter *writer, Datagram &datagram) {
|
||||
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++;
|
||||
}
|
||||
|
||||
for (i = 0; i < _num_textureSwaps; i++) {
|
||||
TextureImage *swapTexture;
|
||||
DCAST_INTO_R(swapTexture, p_list[index], index);
|
||||
_textureSwaps.push_back(swapTexture);
|
||||
index++;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@ -1094,6 +1210,13 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
|
||||
_num_references = scan.get_int32();
|
||||
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;
|
||||
void mark_unfilled();
|
||||
void fill_image(PNMImage &image);
|
||||
void fill_swapped_image(PNMImage &image, int index);
|
||||
void flag_error_image(PNMImage &image);
|
||||
|
||||
typedef pvector<TextureImage *> TextureSwaps;
|
||||
TextureSwaps _textureSwaps;
|
||||
|
||||
private:
|
||||
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;
|
||||
// don't use it otherwise.
|
||||
int _num_references;
|
||||
|
||||
int _margin_override;
|
||||
int _num_textureSwaps;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
@ -91,6 +91,9 @@ read(istream &in, const string &filename) {
|
||||
} else if (words[0] == ":cutout") {
|
||||
okflag = parse_cutout_line(words);
|
||||
|
||||
} else if (words[0] == ":textureswap") {
|
||||
okflag = parse_textureswap_line(words);
|
||||
|
||||
} else {
|
||||
nout << "Invalid keyword " << words[0] << "\n";
|
||||
okflag = false;
|
||||
@ -577,6 +580,7 @@ parse_remap_line(const vector_string &words) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TxaFile::parse_cutout_line
|
||||
// Access: Private
|
||||
@ -608,3 +612,36 @@ parse_cutout_line(const vector_string &words) {
|
||||
|
||||
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_remap_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;
|
||||
Lines _lines;
|
||||
|
Loading…
x
Reference in New Issue
Block a user