summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/rltiles/dc-misc.txt3
-rw-r--r--crawl-ref/source/rltiles/dc-misc/mask_submerged.pngbin0 -> 593 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-player.txt5
-rw-r--r--crawl-ref/source/tilebuf.cc378
-rw-r--r--crawl-ref/source/tilebuf.h89
-rw-r--r--crawl-ref/source/tilemcache.cc7
-rw-r--r--crawl-ref/source/tilemcache.h2
-rw-r--r--crawl-ref/source/tilepick.cc4
-rw-r--r--crawl-ref/source/tilereg.cc97
-rw-r--r--crawl-ref/source/tilereg.h13
-rw-r--r--crawl-ref/source/tiles.h1
-rw-r--r--crawl-ref/source/tilesdl.cc55
-rw-r--r--crawl-ref/source/tilesdl.h25
-rw-r--r--crawl-ref/source/tiletex.h41
14 files changed, 533 insertions, 187 deletions
diff --git a/crawl-ref/source/rltiles/dc-misc.txt b/crawl-ref/source/rltiles/dc-misc.txt
index 8050483dcd..120c455fc1 100644
--- a/crawl-ref/source/rltiles/dc-misc.txt
+++ b/crawl-ref/source/rltiles/dc-misc.txt
@@ -65,6 +65,9 @@ mask_shallow_water_murky MASK_SHALLOW_WATER_MURKY
mask_deep_water_shoals MASK_DEEP_WATER_SHOALS
mask_shallow_water_shoals MASK_SHALLOW_WATER_SHOALS
mask_lava MASK_LAVA
+%shrink 0
+mask_submerged MASK_SUBMERGED
+%shrink 1
cursor CURSOR
cursor_red CURSOR2
cursor_green CURSOR3
diff --git a/crawl-ref/source/rltiles/dc-misc/mask_submerged.png b/crawl-ref/source/rltiles/dc-misc/mask_submerged.png
new file mode 100644
index 0000000000..4ccb0aa8ae
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/mask_submerged.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt
index a85491abe8..dba7424fbb 100644
--- a/crawl-ref/source/rltiles/dc-player.txt
+++ b/crawl-ref/source/rltiles/dc-player.txt
@@ -7,8 +7,11 @@
effect/net_trap TRAP_NET
dc-misc/cursor CURSOR
-
+%rim 0
+%shrink 0
+dc-misc/mask_submerged MASK_SUBMERGED
%rim 1
+%shrink 1
###BASE
%parts_ctg BASE
diff --git a/crawl-ref/source/tilebuf.cc b/crawl-ref/source/tilebuf.cc
index 1c9cbf2763..edaa3a4596 100644
--- a/crawl-ref/source/tilebuf.cc
+++ b/crawl-ref/source/tilebuf.cc
@@ -11,12 +11,87 @@
#include "tilebuf.h"
#include "tilefont.h"
-#include "tilesdl.h"
#include <SDL.h>
#include <SDL_opengl.h>
/////////////////////////////////////////////////////////////////////////////
+// GLState
+
+// Note: these defaults should match the OpenGL defaults
+GLState::GLState() :
+ array_vertex(false),
+ array_texcoord(false),
+ array_colour(false),
+ blend(false),
+ texture(false),
+ depthtest(false),
+ alphatest(false),
+ alpharef(0)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GLStateManager
+
+void GLStateManager::init()
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+ glDepthFunc(GL_LEQUAL);
+}
+
+void GLStateManager::set(const GLState& state)
+{
+ if (state.array_vertex)
+ glEnableClientState(GL_VERTEX_ARRAY);
+ else
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (state.array_texcoord)
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ else
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ if (state.array_colour)
+ {
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ else
+ {
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ // [enne] This should *not* be necessary, but the Linux OpenGL
+ // driver that I'm using sets this to the last colour of the
+ // colour array. So, we need to unset it here.
+ glColor3f(1.0f, 1.0f, 1.0f);
+ }
+
+ if (state.texture)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (state.blend)
+ glEnable(GL_BLEND);
+ else
+ glDisable(GL_BLEND);
+
+ if (state.depthtest)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+
+ if (state.alphatest)
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_NOTEQUAL, state.alpharef);
+ }
+ else
+ glDisable(GL_ALPHA_TEST);
+}
+
+/////////////////////////////////////////////////////////////////////////////
// VColour
VColour VColour::white(255, 255, 255, 255);
@@ -46,6 +121,15 @@ static bool _valid(int num_verts, int prim)
#endif
template<>
+void VertBuffer<PTVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.blend = true;
+ m_state.texture = true;
+}
+
+template<>
void VertBuffer<PTVert>::draw() const
{
if (size() == 0)
@@ -54,12 +138,7 @@ void VertBuffer<PTVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_texcoord = true;
- state.blend = true;
- state.texture = true;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
m_tex->bind();
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
@@ -68,6 +147,15 @@ void VertBuffer<PTVert>::draw() const
}
template<>
+void VertBuffer<PCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = false;
+}
+
+template<>
void VertBuffer<PCVert>::draw() const
{
if (size() == 0)
@@ -76,12 +164,7 @@ void VertBuffer<PCVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(!m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_colour = true;
- state.blend = true;
- state.texture = false;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vert), &(*this)[0].col);
@@ -89,6 +172,16 @@ void VertBuffer<PCVert>::draw() const
}
template<>
+void VertBuffer<PTCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = true;
+}
+
+template<>
void VertBuffer<PTCVert>::draw() const
{
if (size() == 0)
@@ -97,13 +190,7 @@ void VertBuffer<PTCVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_texcoord = true;
- state.array_colour = true;
- state.blend = true;
- state.texture = true;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
m_tex->bind();
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
@@ -112,6 +199,37 @@ void VertBuffer<PTCVert>::draw() const
glDrawArrays(m_prim, 0, size());
}
+template<>
+void VertBuffer<P3TCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = true;
+ m_state.depthtest = true;
+ m_state.alphatest = true;
+ m_state.alpharef = 0;
+}
+
+template<>
+void VertBuffer<P3TCVert>::draw() const
+{
+ if (size() == 0)
+ return;
+
+ ASSERT(_valid(size(), m_prim));
+ ASSERT(m_tex);
+
+ GLStateManager::set(m_state);
+
+ m_tex->bind();
+ glVertexPointer(3, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].tex_x);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vert), &(*this)[0].col);
+ glDrawArrays(m_prim, 0, size());
+}
+
/////////////////////////////////////////////////////////////////////////////
// FontBuffer
@@ -143,23 +261,17 @@ TileBuffer::TileBuffer(const TilesTexture *t) : VertBuffer<PTVert>(t, GL_QUADS)
void TileBuffer::add_unscaled(int idx, float x, float y, int ymax)
{
- const tile_info &inf = ((TilesTexture*)m_tex)->get_info(idx);
-
- float pos_sx = x + inf.offset_x;
- float pos_sy = y + inf.offset_y;
- float pos_ex = pos_sx + (inf.ex - inf.sx);
- int ey = inf.ey;
- if (ymax > 0)
- ey = std::min(inf.sy + ymax - inf.offset_y, ey);
- float pos_ey = pos_sy + (ey - inf.sy);
-
- float fwidth = m_tex->width();
- float fheight = m_tex->height();
+ float pos_sx = x;
+ float pos_sy = y;
+ float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
+ TilesTexture *tex = (TilesTexture *)m_tex;
+ bool drawn = tex->get_coords(idx, 0, 0,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ true, -1, ymax, 1.0f, 1.0f);
- float tex_sx = inf.sx / fwidth;
- float tex_sy = inf.sy / fheight;
- float tex_ex = inf.ex / fwidth;
- float tex_ey = inf.ey / fheight;
+ if (!drawn)
+ return;
size_t last = std::vector<Vert>::size();
std::vector<Vert>::resize(last + 4);
@@ -202,8 +314,13 @@ void TileBuffer::add(int idx, int x, int y, int ox, int oy, bool centre, int yma
float pos_sy = y;
float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
TilesTexture *tex = (TilesTexture *)m_tex;
- tex->get_coords(idx, ox, oy, pos_sx, pos_sy, pos_ex, pos_ey,
- tex_sx, tex_sy, tex_ex, tex_ey, centre, ymax);
+ bool drawn = tex->get_coords(idx, ox, oy,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ centre, -1, ymax, TILE_X, TILE_Y);
+
+ if (!drawn)
+ return;
size_t last = std::vector<Vert>::size();
std::vector<Vert>::resize(last + 4);
@@ -248,6 +365,191 @@ void TileBuffer::set_tex(const TilesTexture *new_tex)
}
/////////////////////////////////////////////////////////////////////////////
+// ColouredTileBuffer
+
+ColouredTileBuffer::ColouredTileBuffer(const TilesTexture *t) :
+ VertBuffer<P3TCVert>(t, GL_QUADS)
+{
+}
+
+static unsigned char _get_alpha(float lerp, int alpha_top, int alpha_bottom)
+{
+ if (lerp < 0.0f)
+ lerp = 0.0f;
+ if (lerp > 1.0f)
+ lerp = 1.0f;
+
+ int ret = alpha_top * (1.0f - lerp) + alpha_bottom * lerp;
+
+ ret = std::min(std::max(0, ret), 255);
+ return (static_cast<unsigned char>(ret));
+}
+
+void ColouredTileBuffer::add(int idx, int x, int y, int z,
+ int ox, int oy, int ymin, int ymax,
+ int alpha_top, int alpha_bottom)
+{
+ float pos_sx = x;
+ float pos_sy = y;
+ float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
+ TilesTexture *tex = (TilesTexture *)m_tex;
+ bool drawn = tex->get_coords(idx, ox, oy,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ true, -1, ymax);
+
+ if (!drawn)
+ return;
+
+ float lerp_s = (pos_sy - y);
+ float lerp_e = (pos_ey - y);
+
+ // Need to calculate the alpha at the top and bottom. As the quad
+ // being drawn may not actually start on the grid boundary, we need
+ // to figure out what alpha value its vertices should use.
+ unsigned char alpha_s = _get_alpha(lerp_s, alpha_top, alpha_bottom);
+ unsigned char alpha_e = _get_alpha(lerp_e, alpha_top, alpha_bottom);
+
+ VColour col_sy(255, 255, 255, alpha_s);
+ VColour col_ey(255, 255, 255, alpha_e);
+
+ float pos_z = (float)z;
+
+ size_t last = std::vector<Vert>::size();
+ std::vector<Vert>::resize(last + 4);
+ {
+ Vert &v = (*this)[last];
+ v.pos_x = pos_sx;
+ v.pos_y = pos_sy;
+ v.pos_z = pos_z;
+ v.tex_x = tex_sx;
+ v.tex_y = tex_sy;
+ v.col = col_sy;
+ }
+
+ {
+ Vert &v = (*this)[last + 1];
+ v.pos_x = pos_sx;
+ v.pos_y = pos_ey;
+ v.pos_z = pos_z;
+ v.tex_x = tex_sx;
+ v.tex_y = tex_ey;
+ v.col = col_ey;
+ }
+
+ {
+ Vert &v = (*this)[last + 2];
+ v.pos_x = pos_ex;
+ v.pos_y = pos_ey;
+ v.pos_z = pos_z;
+ v.tex_x = tex_ex;
+ v.tex_y = tex_ey;
+ v.col = col_ey;
+ }
+
+ {
+ Vert &v = (*this)[last + 3];
+ v.pos_x = pos_ex;
+ v.pos_y = pos_sy;
+ v.pos_z = pos_z;
+ v.tex_x = tex_ex;
+ v.tex_y = tex_sy;
+ v.col = col_sy;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// SubmergedTileBuffer
+
+
+SubmergedTileBuffer::SubmergedTileBuffer(const TilesTexture *tex,
+ int mask_idx, int above_max,
+ int below_min) :
+ m_mask_idx(mask_idx),
+ m_above_max(above_max),
+ m_below_min(below_min),
+ m_max_z(-1000),
+ m_below_water(tex),
+ m_mask(tex),
+ m_above_water(tex)
+{
+ // Adjust the state of the mask buffer so that we can use it to mask out
+ // the bottom half of the tile when drawing the character a second time.
+ // See the draw() function for more details.
+ GLState &state = m_mask.state();
+ state.blend = true;
+ state.depthtest = true;
+ state.alphatest = true;
+ state.alpharef = 255;
+}
+
+void SubmergedTileBuffer::add(int idx, int x, int y, int z, bool submerged,
+ bool ghost, int ox, int oy, int ymax)
+{
+ // Keep track of the maximum z. We'll use this for drawing the mask
+ // later, to ensure it is closer than all other tiles drawn.
+ m_max_z = std::max(m_max_z, z);
+
+ // Arbitrary alpha values for the top and bottom.
+ int alpha_top = ghost ? 100 : 255;
+ int alpha_bottom = ghost ? 0 : 40;
+
+ if (submerged)
+ {
+ m_below_water.add(idx, x, y, z, ox, oy, m_below_min, ymax,
+ alpha_top, alpha_bottom);
+
+ m_mask.add(m_mask_idx, x, y, 0, 0, 0, -1, -1, 255, 255);
+ int above_max = (ymax == -1) ? m_above_max
+ : std::min(ymax, m_above_max);
+ m_above_water.add(idx, x, y, z, ox, oy, -1, above_max,
+ alpha_top, alpha_top);
+ }
+ else
+ {
+ // Unsubmerged tiles don't need a mask.
+ m_above_water.add(idx, x, y, z, ox, oy, -1, ymax, alpha_top, alpha_top);
+ }
+}
+
+void SubmergedTileBuffer::draw() const
+{
+ // First, draw anything below water. Alpha blending is turned on,
+ // so these tiles will blend with anything previously drawn.
+ m_below_water.draw();
+
+ // Second, draw all of the mask tiles. The mask is white (255,255,255,255)
+ // above water and transparent (0,0,0,0) below water.
+ //
+ // Alpha testing is turned on with a ref value of 255, so none of the
+ // white pixels will be drawn because they will culled by alpha testing.
+ // The transparent pixels below water will be "drawn", but because they
+ // are fully transparent, they will not affect any colours on screen.
+ // Instead, they will will set the z-buffer to a z-value (depth) that is
+ // greater than the closest depth in either the below or above buffers.
+ // Because all of the above water tiles are at lower z-values than this
+ // maximum, they will not draw over these transparent pixels, effectively
+ // masking them out. (My kingdom for a shader.)
+
+ glPushMatrix();
+ glTranslatef(0, 0, m_max_z + 1);
+ m_mask.draw();
+ glPopMatrix();
+
+ // Now, draw all the above water tiles. Some of these may draw over top
+ // of part of the below water tiles, but that's fine as the mask will
+ // take care of only drawing the correct parts.
+ m_above_water.draw();
+}
+
+void SubmergedTileBuffer::clear()
+{
+ m_below_water.clear();
+ m_mask.clear();
+ m_above_water.clear();
+}
+
+/////////////////////////////////////////////////////////////////////////////
// ShapeBuffer
// [enne] - GL_POINTS should probably be used here, but there's (apparently)
diff --git a/crawl-ref/source/tilebuf.h b/crawl-ref/source/tilebuf.h
index c13e9cec91..ee315a6eca 100644
--- a/crawl-ref/source/tilebuf.h
+++ b/crawl-ref/source/tilebuf.h
@@ -8,6 +8,34 @@
#include "tiles.h"
+// This struct defines all of the state that any particular rendering needs.
+// If other rendering states are needed, they should be added here so that
+// they do not introduce unneeded side effects for other parts of the code
+// that have not thought about turning that new state off.
+struct GLState
+{
+ GLState();
+
+ // vertex arrays
+ bool array_vertex;
+ bool array_texcoord;
+ bool array_colour;
+
+ // render state
+ bool blend;
+ bool texture;
+ bool depthtest;
+ bool alphatest;
+ unsigned char alpharef;
+};
+
+class GLStateManager
+{
+public:
+ static void init();
+ static void set(const GLState& state);
+};
+
class FTFont;
class formatted_string;
class GenericTexture;
@@ -41,6 +69,16 @@ struct PTCVert
VColour col;
};
+struct P3TCVert
+{
+ float pos_x;
+ float pos_y;
+ float pos_z;
+ float tex_x;
+ float tex_y;
+ VColour col;
+};
+
struct PTVert
{
float pos_x;
@@ -70,9 +108,14 @@ public:
V& get_next();
void draw() const;
+ GLState &state() { return m_state; }
+
protected:
+ void init_state();
+
const GenericTexture *m_tex;
int m_prim;
+ GLState m_state;
};
class FontBuffer : public VertBuffer<PTCVert>
@@ -99,6 +142,51 @@ public:
void set_tex(const TilesTexture *tex);
};
+class ColouredTileBuffer : public VertBuffer<P3TCVert>
+{
+public:
+ ColouredTileBuffer(const TilesTexture *tex = NULL);
+
+ void add(int idx, int x, int y, int z,
+ int ox, int oy, int ymin, int ymax,
+ int alpha_top, int alpha_bottom);
+};
+
+// Helper class for tiles submerged in water.
+class SubmergedTileBuffer
+{
+public:
+ // mask_idx is the tile index in tex of the mask texture
+ // It should be opaque white for water and fully transparent above.
+ //
+ // above_max is the maximum height (from the top of the tile) where
+ // there are still pixels above water.
+ //
+ // below_min is the minimum height (from the top of the tile) where
+ // there are still pixels below water.
+ //
+ // All heights are from 0 (top of the tile) to TILE_Y-1 (bottom of the tile)
+ SubmergedTileBuffer(const TilesTexture *tex,
+ int mask_idx, int above_max, int below_min);
+
+ void add(int idx, int x, int y, int z = 0, bool submerged = false,
+ bool ghost = false, int ox = 0, int oy = 0, int ymax = -1);
+
+ void draw() const;
+ void clear();
+
+protected:
+ int m_mask_idx;
+ int m_above_max;
+ int m_below_min;
+
+ int m_max_z;
+
+ ColouredTileBuffer m_below_water;
+ ColouredTileBuffer m_mask;
+ ColouredTileBuffer m_above_water;
+};
+
class ShapeBuffer : public VertBuffer<PCVert>
{
public:
@@ -121,6 +209,7 @@ template<class V>
inline VertBuffer<V>::VertBuffer(const GenericTexture *tex, int prim) :
m_tex(tex), m_prim(prim)
{
+ init_state();
}
template<class V>
diff --git a/crawl-ref/source/tilemcache.cc b/crawl-ref/source/tilemcache.cc
index 12b4859fcc..8cf4058a91 100644
--- a/crawl-ref/source/tilemcache.cc
+++ b/crawl-ref/source/tilemcache.cc
@@ -104,6 +104,8 @@ public:
virtual void construct(writer &th);
+ virtual bool transparent() const;
+
protected:
dolls_data m_doll;
};
@@ -818,6 +820,11 @@ void mcache_ghost::construct(writer &th)
marshallDoll(th, m_doll);
}
+bool mcache_ghost::transparent() const
+{
+ return (true);
+}
+
/////////////////////////////////////////////////////////////////////////////
// mcache_demon
diff --git a/crawl-ref/source/tilemcache.h b/crawl-ref/source/tilemcache.h
index fef7bd6d77..67ff52f9c1 100644
--- a/crawl-ref/source/tilemcache.h
+++ b/crawl-ref/source/tilemcache.h
@@ -47,6 +47,8 @@ public:
virtual void construct(writer &th);
+ virtual bool transparent() const { return false; }
+
protected:
mcache_entry(reader &th);
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index b1d2024e1d..94d4cb9641 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -5087,6 +5087,10 @@ void tile_finish_dngn(unsigned int *tileb, int cx, int cy)
}
}
+ dungeon_feature_type feat = grd(gc);
+ if (feat_is_water(feat) || feat == DNGN_LAVA)
+ tileb[count+1] |= TILE_FLAG_WATER;
+
if (print_blood && is_bloodcovered(gc))
tileb[count+1] |= TILE_FLAG_BLOOD;
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 8886b5d737..682a4b717e 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -249,7 +249,8 @@ DungeonRegion::DungeonRegion(ImageManager* im, FTFont *tag_font,
m_cx_to_gx(0),
m_cy_to_gy(0),
m_buf_dngn(&im->m_textures[TEX_DUNGEON]),
- m_buf_doll(&im->m_textures[TEX_PLAYER]),
+ m_buf_doll(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16),
+ m_buf_main_trans(&im->m_textures[TEX_DEFAULT], TILE_MASK_SUBMERGED, 18, 16),
m_buf_main(&im->m_textures[TEX_DEFAULT])
{
for (int i = 0; i < CURSOR_MAX; i++)
@@ -805,14 +806,14 @@ void save_doll_file(FILE *dollf)
fprintf(dollf, "net\n");
}
-void DungeonRegion::pack_player(int x, int y)
+void DungeonRegion::pack_player(int x, int y, bool submerged)
{
dolls_data result = player_doll;
_fill_doll_equipment(result);
- pack_doll(result, x, y);
+ pack_doll(result, x, y, submerged, false);
}
-void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
+void pack_doll_buf(SubmergedTileBuffer& buf, const dolls_data &doll, int x, int y, bool submerged, bool ghost)
{
int p_order[TILEP_PART_MAX] =
{
@@ -865,13 +866,22 @@ void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
flags[TILEP_PART_BOOTS] = is_cent ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE;
}
- for (int i = 0; i < TILEP_PART_MAX; i++)
+ // A higher index here means that the part should be drawn on top.
+ // This is drawn in reverse order because this could be a ghost
+ // or being drawn in water, in which case we want the top-most part
+ // to blend with the background underneath and not with the parts
+ // underneath. Parts drawn afterwards will not obscure parts drawn
+ // previously, because "i" is passed as the depth below.
+ for (int i = TILEP_PART_MAX - 1; i >= 0; --i)
{
int p = p_order[i];
if (!doll.parts[p] || flags[p] == TILEP_FLAG_HIDE)
continue;
+ if (p == TILEP_PART_SHADOW && (submerged || ghost))
+ continue;
+
int ymax = TILE_Y;
if (flags[p] == TILEP_FLAG_CUT_CENTAUR
@@ -880,68 +890,51 @@ void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
ymax = 18;
}
- buf.add(doll.parts[p], x, y, 0, 0, true, ymax);
+ buf.add(doll.parts[p], x, y, i, submerged, ghost, 0, 0, ymax);
}
}
-void DungeonRegion::pack_doll(const dolls_data &doll, int x, int y)
+void DungeonRegion::pack_doll(const dolls_data &doll, int x, int y, bool submerged, bool ghost)
{
- pack_doll_buf(m_buf_doll, doll, x, y);
+ pack_doll_buf(m_buf_doll, doll, x, y, submerged, ghost);
}
-void DungeonRegion::pack_mcache(mcache_entry *entry, int x, int y)
+void DungeonRegion::pack_mcache(mcache_entry *entry, int x, int y, bool submerged)
{
ASSERT(entry);
+ bool trans = entry->transparent();
+
const dolls_data *doll = entry->doll();
if (doll)
- pack_doll(*doll, x, y);
+ pack_doll(*doll, x, y, submerged, trans);
tile_draw_info dinfo[3];
unsigned int draw_info_count = entry->info(&dinfo[0]);
ASSERT(draw_info_count <= sizeof(dinfo) / (sizeof(dinfo[0])));
for (unsigned int i = 0; i < draw_info_count; i++)
- m_buf_doll.add(dinfo[i].idx, x, y, dinfo[i].ofs_x, dinfo[i].ofs_y);
+ {
+ m_buf_doll.add(dinfo[i].idx, x, y, 0, submerged, trans,
+ dinfo[i].ofs_x, dinfo[i].ofs_y);
+ }
}
void DungeonRegion::pack_foreground(unsigned int bg, unsigned int fg, int x, int y)
{
unsigned int fg_idx = fg & TILE_FLAG_MASK;
- unsigned int bg_idx = bg & TILE_FLAG_MASK;
if (fg_idx && fg_idx <= TILE_MAIN_MAX)
- m_buf_main.add(fg_idx, x, y);
-
- if (fg_idx && !(fg & TILE_FLAG_FLYING))
{
- if (tile_dngn_equal(TILE_DNGN_LAVA, bg_idx))
- m_buf_main.add(TILE_MASK_LAVA, x, y);
- else if (tile_dngn_equal(TILE_DNGN_SHALLOW_WATER, bg_idx)
- || tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_DISTURBANCE,
- bg_idx))
- {
- m_buf_main.add(TILE_MASK_SHALLOW_WATER, x, y);
- }
- else if (tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_MURKY, bg_idx)
- || tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_MURKY_DISTURBANCE,
- bg_idx))
- {
- m_buf_main.add(TILE_MASK_SHALLOW_WATER_MURKY, x, y);
- }
- else if (tile_dngn_equal(TILE_DNGN_DEEP_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER, x, y);
- else if (tile_dngn_equal(TILE_DNGN_DEEP_WATER_MURKY, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER_MURKY, x, y);
- else if (tile_dngn_equal(TILE_SHOALS_DEEP_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER_SHOALS, x, y);
- else if (tile_dngn_equal(TILE_SHOALS_SHALLOW_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_SHALLOW_WATER_SHOALS, x, y);
+ if (bg & TILE_FLAG_WATER && !(fg & TILE_FLAG_FLYING))
+ m_buf_main_trans.add(fg_idx, x, y, 0, true, false);
+ else
+ m_buf_main.add(fg_idx, x, y);
}
if (fg & TILE_FLAG_NET)
- m_buf_doll.add(TILEP_TRAP_NET, x, y);
+ m_buf_doll.add(TILEP_TRAP_NET, x, y, 0, bg & TILE_FLAG_WATER, false);
if (fg & TILE_FLAG_S_UNDER)
m_buf_main.add(TILE_SOMETHING_UNDER, x, y);
@@ -1058,6 +1051,7 @@ void DungeonRegion::pack_buffers()
{
m_buf_dngn.clear();
m_buf_doll.clear();
+ m_buf_main_trans.clear();
m_buf_main.clear();
if (m_tileb.empty())
@@ -1077,17 +1071,20 @@ void DungeonRegion::pack_buffers()
{
mcache_entry *entry = mcache.get(fg_idx);
if (entry)
- pack_mcache(entry, x, y);
+ pack_mcache(entry, x, y, bg & TILE_FLAG_WATER);
else
- m_buf_doll.add(TILEP_MONS_UNKNOWN, x, y);
+ {
+ m_buf_doll.add(TILEP_MONS_UNKNOWN, x, y, 0,
+ bg & TILE_FLAG_WATER, false);
+ }
}
else if (fg_idx == TILEP_PLAYER)
{
- pack_player(x, y);
+ pack_player(x, y, bg & TILE_FLAG_WATER);
}
else if (fg_idx >= TILE_MAIN_MAX)
{
- m_buf_doll.add(fg_idx, x, y);
+ m_buf_doll.add(fg_idx, x, y, 0, bg & TILE_FLAG_WATER, false);
}
pack_foreground(bg, fg, x, y);
@@ -1146,6 +1143,7 @@ void DungeonRegion::render()
set_transform();
m_buf_dngn.draw();
m_buf_doll.draw();
+ m_buf_main_trans.draw();
m_buf_main.draw();
if (you.berserk())
@@ -4029,7 +4027,9 @@ void TitleRegion::run()
}
DollEditRegion::DollEditRegion(ImageManager *im, FTFont *font) :
- m_font_buf(font)
+ m_font_buf(font),
+ m_tile_buf(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16),
+ m_cur_buf(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16)
{
sx = sy = 0;
dx = dy = 32;
@@ -4040,9 +4040,6 @@ DollEditRegion::DollEditRegion(ImageManager *im, FTFont *font) :
m_doll_idx = 0;
m_cat_idx = TILEP_PART_BASE;
m_copy_valid = false;
-
- m_tile_buf.set_tex(&im->m_textures[TEX_PLAYER]);
- m_cur_buf.set_tex(&im->m_textures[TEX_PLAYER]);
}
void DollEditRegion::clear()
@@ -4188,7 +4185,7 @@ void DollEditRegion::render()
{
dolls_data temp = m_dolls[m_doll_idx];
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 0, 0);
+ pack_doll_buf(m_cur_buf, temp, 0, 0, false, false);
}
// Draw set of dolls.
@@ -4202,7 +4199,7 @@ void DollEditRegion::render()
dolls_data temp = m_dolls[i];
_fill_doll_equipment(temp);
- pack_doll_buf(m_tile_buf, temp, x, y);
+ pack_doll_buf(m_tile_buf, temp, x, y, false, false);
m_shape_buf.add(x, y, x + 1, y + 1, grey);
}
@@ -4261,12 +4258,12 @@ void DollEditRegion::render()
dolls_data temp;
temp = m_job_default;
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 2, 0);
+ pack_doll_buf(m_cur_buf, temp, 2, 0, false, false);
for (unsigned int i = 0; i < TILEP_PART_MAX; ++i)
temp.parts[i] = TILEP_SHOW_EQUIP;
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 4, 0);
+ pack_doll_buf(m_cur_buf, temp, 4, 0, false, false);
if (m_mode == TILEP_MODE_LOADING)
m_cur_buf.add(TILEP_CURSOR, 0, 0);
diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h
index 74fbb18f60..a3584cac8a 100644
--- a/crawl-ref/source/tilereg.h
+++ b/crawl-ref/source/tilereg.h
@@ -276,10 +276,10 @@ public:
protected:
void pack_background(unsigned int bg, int x, int y);
- void pack_mcache(mcache_entry *entry, int x, int y);
- void pack_player(int x, int y);
+ void pack_mcache(mcache_entry *entry, int x, int y, bool submerged);
+ void pack_player(int x, int y, bool submerged);
void pack_foreground(unsigned int bg, unsigned int fg, int x, int y);
- void pack_doll(const dolls_data &doll, int x, int y);
+ void pack_doll(const dolls_data &doll, int x, int y, bool submerged, bool ghost);
void pack_cursor(cursor_type type, unsigned int tile);
void pack_buffers();
@@ -293,7 +293,8 @@ protected:
std::vector<TextTag> m_tags[TAG_MAX];
TileBuffer m_buf_dngn;
- TileBuffer m_buf_doll;
+ SubmergedTileBuffer m_buf_doll;
+ SubmergedTileBuffer m_buf_main_trans;
TileBuffer m_buf_main;
struct tile_overlay
@@ -489,8 +490,8 @@ protected:
ShapeBuffer m_shape_buf;
FontBuffer m_font_buf;
- TileBuffer m_tile_buf;
- TileBuffer m_cur_buf;
+ SubmergedTileBuffer m_tile_buf;
+ SubmergedTileBuffer m_cur_buf;
};
#endif
diff --git a/crawl-ref/source/tiles.h b/crawl-ref/source/tiles.h
index d50482a673..be49c3f12e 100644
--- a/crawl-ref/source/tiles.h
+++ b/crawl-ref/source/tiles.h
@@ -170,6 +170,7 @@ enum tile_flags
TILE_FLAG_TUT_CURSOR = 0x00800000,
TILE_FLAG_RAY_OOR = 0x01000000,
TILE_FLAG_OOR = 0x02000000,
+ TILE_FLAG_WATER = 0x04000000,
// General
TILE_FLAG_MASK = 0x000007FF
diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc
index ff6af904ab..5210eedf81 100644
--- a/crawl-ref/source/tilesdl.cc
+++ b/crawl-ref/source/tilesdl.cc
@@ -49,59 +49,6 @@ static int _screen_sizes[4][8] =
{800, 480, 3, 13, 12, 10, 13, 11}
};
-// Note: these defaults should match the OpenGL defaults
-GLState::GLState() :
- array_vertex(false),
- array_texcoord(false),
- array_colour(false),
- blend(false),
- texture(false)
-{
-}
-
-void GLStateManager::init()
-{
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glClearColor(0.0, 0.0, 0.0, 1.0f);
-}
-
-void GLStateManager::set(const GLState& state)
-{
- if (state.array_vertex)
- glEnableClientState(GL_VERTEX_ARRAY);
- else
- glDisableClientState(GL_VERTEX_ARRAY);
-
- if (state.array_texcoord)
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- if (state.array_colour)
- {
- glEnableClientState(GL_COLOR_ARRAY);
- }
- else
- {
- glDisableClientState(GL_COLOR_ARRAY);
-
- // [enne] This should *not* be necessary, but the Linux OpenGL
- // driver that I'm using sets this to the last colour of the
- // colour array. So, we need to unset it here.
- glColor3f(1.0f, 1.0f, 1.0f);
- }
-
- if (state.texture)
- glEnable(GL_TEXTURE_2D);
- else
- glDisable(GL_TEXTURE_2D);
-
- if (state.blend)
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
-}
-
TilesFramework tiles;
TilesFramework::TilesFramework() :
@@ -486,7 +433,7 @@ void TilesFramework::resize()
glLoadIdentity();
// For ease, vertex positions are pixel positions.
- glOrtho(0, m_windowsz.x, m_windowsz.y, 0, 0, 100);
+ glOrtho(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
}
static unsigned char _get_modifiers(SDL_keysym &keysym)
diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h
index 993de5c302..8e0812e35a 100644
--- a/crawl-ref/source/tilesdl.h
+++ b/crawl-ref/source/tilesdl.h
@@ -11,24 +11,6 @@
#include "externs.h"
#include "tilereg.h"
-// This struct defines all of the state that any particular rendering needs.
-// If other rendering states are needed, they should be added here so that
-// they do not introduce unneeded side effects for other parts of the code
-// that have not thought about turning that new state off.
-struct GLState
-{
- GLState();
-
- // vertex arrays
- bool array_vertex;
- bool array_texcoord;
- bool array_colour;
-
- // render state
- bool blend;
- bool texture;
-};
-
enum key_mod
{
MOD_SHIFT = 0x1,
@@ -68,13 +50,6 @@ struct MouseEvent
unsigned int py;
};
-class GLStateManager
-{
-public:
- static void init();
- static void set(const GLState& state);
-};
-
class SDL_Surface;
class FTFont;
diff --git a/crawl-ref/source/tiletex.h b/crawl-ref/source/tiletex.h
index a50b85dc26..c95067a3fe 100644
--- a/crawl-ref/source/tiletex.h
+++ b/crawl-ref/source/tiletex.h
@@ -76,12 +76,13 @@ public:
void set_info(int max, tile_info_func *info);
inline const tile_info &get_info(int idx) const;
- inline void get_coords(int idx, int ofs_x, int ofs_y,
+ inline bool get_coords(int idx, int ofs_x, int ofs_y,
float &pos_sx, float &pos_sy,
float &pos_ex, float &pos_ey,
float &tex_sx, float &tex_sy,
float &tex_ex, float &tex_ey,
- bool centre = true, int ymax = -1) const;
+ bool centre = true, int ymin = -1, int ymax = -1,
+ float tile_x = TILE_X, float tile_y = TILE_Y) const;
protected:
int m_tile_max;
@@ -94,12 +95,13 @@ inline const tile_info &TilesTexture::get_info(int idx) const
return m_info_func(idx);
}
-inline void TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
+inline bool TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
float &pos_sx, float &pos_sy,
float &pos_ex, float &pos_ey,
float &tex_sx, float &tex_sy,
float &tex_ex, float &tex_ey,
- bool centre, int ymax) const
+ bool centre, int ymin, int ymax,
+ float tile_x, float tile_y) const
{
const tile_info &inf = get_info(idx);
@@ -110,19 +112,32 @@ inline void TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
int size_ox = centre ? TILE_X / 2 - inf.width / 2 : 0;
int size_oy = centre ? TILE_Y - inf.height : 0;
- int ey = inf.ey;
- if (ymax > 0)
- ey = std::min(inf.sy + ymax - inf.offset_y, ey);
+ int pos_sy_adjust = ofs_y + inf.offset_y + size_oy;
+ int pos_ey_adjust = pos_sy_adjust + inf.ey - inf.sy;
- pos_sx += (ofs_x + inf.offset_x + size_ox) / (float) TILE_X;
- pos_sy += (ofs_y + inf.offset_y + size_oy) / (float) TILE_Y;
- pos_ex = pos_sx + (inf.ex - inf.sx) / (float)TILE_X;
- pos_ey = pos_sy + (ey - inf.sy) / (float)TILE_Y;
+ int sy = pos_sy_adjust;
+ if (ymin >= 0)
+ sy = std::max(ymin, sy);
+
+ int ey = pos_ey_adjust;
+ if (ymax >= 0)
+ ey = std::min(ymax, ey);
+
+ // Nothing to draw.
+ if (sy >= ey)
+ return (false);
+
+ pos_sx += (ofs_x + inf.offset_x + size_ox) / tile_x;
+ pos_sy += sy / tile_y;
+ pos_ex = pos_sx + (inf.ex - inf.sx) / tile_x;
+ pos_ey = pos_sy + (ey - sy) / tile_y;
tex_sx = inf.sx / fwidth;
- tex_sy = inf.sy / fheight;
+ tex_sy = (inf.sy + sy - pos_sy_adjust) / fheight;
tex_ex = inf.ex / fwidth;
- tex_ey = ey / fheight;
+ tex_ey = (inf.ey + ey - pos_ey_adjust) / fheight;
+
+ return (true);
}
#endif