summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/tiletex.cc
diff options
context:
space:
mode:
authorEnne Walker <ennewalker@users.sourceforge.net>2010-04-14 15:30:43 -0400
committerEnne Walker <ennewalker@users.sourceforge.net>2010-04-25 19:15:12 -0400
commitedacdc0db313c0f5385631dfcf560f1fdf8e7c8a (patch)
tree9ca983514587f7c8bdab279afc92f08098f92cac /crawl-ref/source/tiletex.cc
parent255e8100b2ff33fcb7eb3560168e8243ed193ef8 (diff)
downloadcrawl-ref-edacdc0db313c0f5385631dfcf560f1fdf8e7c8a.tar.gz
crawl-ref-edacdc0db313c0f5385631dfcf560f1fdf8e7c8a.zip
Reduce dependencies on tilereg.h.
This was done by pushing ImageManager to tiletex.h, where it better belongs.
Diffstat (limited to 'crawl-ref/source/tiletex.cc')
-rw-r--r--crawl-ref/source/tiletex.cc232
1 files changed, 232 insertions, 0 deletions
diff --git a/crawl-ref/source/tiletex.cc b/crawl-ref/source/tiletex.cc
index df55e8aec3..a22c219a7e 100644
--- a/crawl-ref/source/tiletex.cc
+++ b/crawl-ref/source/tiletex.cc
@@ -2,8 +2,13 @@
#ifdef USE_TILE
+#include "describe.h"
#include "files.h"
#include "glwrapper.h"
+#include "tiledef-dngn.h"
+#include "tiledef-gui.h"
+#include "tiledef-main.h"
+#include "tiledef-player.h"
#include "tiletex.h"
#include "windowmanager.h"
@@ -76,4 +81,231 @@ void TilesTexture::set_info(int tile_max, tile_info_func *info_func)
m_info_func = info_func;
}
+const char *ImageManager::filenames[TEX_MAX] =
+{
+ "dngn.png",
+ "player.png",
+ "main.png",
+ "gui.png"
+};
+
+ImageManager::ImageManager()
+{
+}
+
+ImageManager::~ImageManager()
+{
+ unload_textures();
+}
+
+bool ImageManager::load_textures(bool need_mips)
+{
+ MipMapOptions mip = need_mips ?
+ MIPMAP_CREATE : MIPMAP_NONE;
+ if (!m_textures[TEX_DUNGEON].load_texture(filenames[TEX_DUNGEON], mip))
+ return (false);
+
+ if (!m_textures[TEX_PLAYER].load_texture(filenames[TEX_PLAYER], mip))
+ return (false);
+
+ if (!m_textures[TEX_GUI].load_texture(filenames[TEX_GUI], mip))
+ return (false);
+
+ m_textures[TEX_DUNGEON].set_info(TILE_DNGN_MAX, &tile_dngn_info);
+ m_textures[TEX_PLAYER].set_info(TILEP_PLAYER_MAX, &tile_player_info);
+ m_textures[TEX_GUI].set_info(TILEG_GUI_MAX, &tile_gui_info);
+
+ return (true);
+}
+
+static void _copy_onto(unsigned char *pixels, int width,
+ int height, unsigned char *src,
+ const tile_info &inf, bool blend)
+{
+ unsigned char *dest = &pixels[4 * (inf.sy * width + inf.sx)];
+
+ size_t dest_row_size = width * 4;
+ size_t src_row_size = inf.width * 4;
+
+ if (blend)
+ {
+ for (int r = 0; r < inf.height; r++)
+ {
+ for (int c = 0; c < inf.width; c++)
+ {
+ unsigned char a = src[3];
+ unsigned char inv_a = 255 - src[3];
+ dest[0] = (src[0] * a + dest[0] * inv_a) / 255;
+ dest[1] = (src[1] * a + dest[1] * inv_a) / 255;
+ dest[2] = (src[2] * a + dest[2] * inv_a) / 255;
+ dest[3] = (src[3] * a + dest[3] * inv_a) / 255;
+
+ dest += 4;
+ src += 4;
+ }
+ dest += dest_row_size - src_row_size;
+ }
+ }
+ else
+ {
+ for (int r = 0; r < inf.height; r++)
+ {
+ memcpy(dest, src, src_row_size);
+
+ dest += dest_row_size;
+ src += src_row_size;
+ }
+ }
+}
+
+// Copy an image at inf from pixels into dest.
+static void _copy_into(unsigned char *dest, unsigned char *pixels,
+ int width, int height, const tile_info &inf,
+ int ofs_x = 0, int ofs_y = 0)
+{
+ unsigned char *src = &pixels[4 * (inf.sy * width + inf.sx)];
+
+ size_t src_row_size = width * 4;
+ size_t dest_row_size = inf.width * 4;
+
+ memset(dest, 0, 4 * inf.width * inf.height);
+
+ int total_ofs_x = inf.offset_x + ofs_x;
+ int total_ofs_y = inf.offset_y + ofs_y;
+ int src_height = inf.ey - inf.sy;
+ int src_width = inf.ex - inf.sx;
+
+ if (total_ofs_x < 0)
+ {
+ src_width += total_ofs_x;
+ src -= 4 * total_ofs_x;
+ total_ofs_x = 0;
+ }
+ if (total_ofs_y < 0)
+ {
+ src_height += total_ofs_y;
+ src -= 4 * width * total_ofs_y;
+ total_ofs_y = 0;
+ }
+
+ dest += total_ofs_x * 4 + total_ofs_y * dest_row_size;
+
+ for (int r = 0; r < src_height; r++)
+ {
+ memcpy(dest, src, src_width * 4);
+
+ dest += dest_row_size;
+ src += src_row_size;
+ }
+}
+
+// Stores "over" on top of "under" in the location of "over".
+static bool _copy_under(unsigned char *pixels, int width,
+ int height, int idx_under, int idx_over,
+ int uofs_x = 0, int uofs_y = 0)
+{
+ const tile_info &under = tile_main_info(idx_under);
+ const tile_info &over = tile_main_info(idx_over);
+
+ if (over.width != under.width || over.height != under.height)
+ return (false);
+
+ if (over.ex - over.sx != over.width || over.ey - over.sy != over.height)
+ return (false);
+
+ if (over.offset_x != 0 || over.offset_y != 0)
+ return (false);
+
+ size_t image_size = under.width * under.height * 4;
+
+ // Make a copy of the original images.
+ unsigned char *under_pixels = new unsigned char[image_size];
+ _copy_into(under_pixels, pixels, width, height, under, uofs_x, uofs_y);
+ unsigned char *over_pixels = new unsigned char[image_size];
+ _copy_into(over_pixels, pixels, width, height, over);
+
+ // Replace the over image with the under image
+ _copy_onto(pixels, width, height, under_pixels, over, false);
+ // Blend the over image over top.
+ _copy_onto(pixels, width, height, over_pixels, over, true);
+
+ delete[] under_pixels;
+ delete[] over_pixels;
+
+ return (true);
+}
+
+static bool _process_item_image(unsigned char *pixels, unsigned int width,
+ unsigned int height)
+{
+ bool success = true;
+ for (int i = 0; i < NUM_POTIONS; i++)
+ {
+ int special = you.item_description[IDESC_POTIONS][i];
+ int tile0 = TILE_POTION_OFFSET + special % 14;
+ int tile1 = TILE_POT_HEALING + i;
+ success &= _copy_under(pixels, width, height, tile0, tile1);
+ }
+
+ for (int i = 0; i < NUM_WANDS; i++)
+ {
+ int special = you.item_description[IDESC_WANDS][i];
+ int tile0 = TILE_WAND_OFFSET + special % 12;
+ int tile1 = TILE_WAND_FLAME + i;
+ success &= _copy_under(pixels, width, height, tile0, tile1);
+ }
+
+ for (int i = 0; i < STAFF_SMITING; i++)
+ {
+ int special = you.item_description[IDESC_STAVES][i];
+ int tile0 = TILE_STAFF_OFFSET + (special / 4) % 10;
+ int tile1 = TILE_STAFF_WIZARDRY + i;
+ success &= _copy_under(pixels, width, height, tile0, tile1);
+ }
+ for (int i = STAFF_SMITING; i < NUM_STAVES; i++)
+ {
+ int special = you.item_description[IDESC_STAVES][i];
+ int tile0 = TILE_ROD_OFFSET + (special / 4) % 10;
+ int tile1 = TILE_ROD_SMITING + i - STAFF_SMITING;
+ success &= _copy_under(pixels, width, height, tile0, tile1);
+ }
+ for (int i = RING_FIRST_RING; i < NUM_RINGS; i++)
+ {
+ int special = you.item_description[IDESC_RINGS][i];
+ int tile0 = TILE_RING_NORMAL_OFFSET + special % 13;
+ int tile1 = TILE_RING_REGENERATION + i - RING_FIRST_RING;
+ success &= _copy_under(pixels, width, height, tile0, tile1, -5, -6);
+ }
+ for (int i = AMU_FIRST_AMULET; i < NUM_JEWELLERY; i++)
+ {
+ int special = you.item_description[IDESC_RINGS][i];
+ int tile0 = TILE_AMU_NORMAL_OFFSET + special % 13;
+ int tile1 = TILE_AMU_RAGE + i - AMU_FIRST_AMULET;
+ success &= _copy_under(pixels, width, height, tile0, tile1);
+ }
+
+ return (true);
+}
+
+bool ImageManager::load_item_texture()
+{
+ // We need to load images in two passes: one for the title and one
+ // for the items. To handle identifiable items, the texture itself
+ // is modified. So, it cannot be loaded until after the item
+ // description table has been initialised.
+ MipMapOptions mip = MIPMAP_CREATE;
+ const char *fname = filenames[TEX_DEFAULT];
+ bool success = m_textures[TEX_DEFAULT].load_texture(fname, mip,
+ &_process_item_image);
+ m_textures[TEX_DEFAULT].set_info(TILE_MAIN_MAX, tile_main_info);
+
+ return success;
+}
+
+void ImageManager::unload_textures()
+{
+ for (int i = 0; i < TEX_MAX; i++)
+ m_textures[i].unload_texture();
+}
+
#endif