mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2024-10-28 11:19:36 +01:00
Brought the tilemap class mostly in line with Essential's CustomTilemap wrt animations, though at the cost of backwards compatibility.
(This could be rescued by per-tile animation lentghs in tilemap.vert, but this should suffice for now.)
This commit is contained in:
parent
647d5339f4
commit
050da27ca0
12 changed files with 322 additions and 80 deletions
|
@ -742,13 +742,23 @@ static void mriBindingExecute() {
|
|||
char **argv = 0;
|
||||
ruby_sysinit(&argc, &argv);
|
||||
|
||||
ruby_setup();
|
||||
RUBY_INIT_STACK;
|
||||
ruby_init();
|
||||
rb_enc_set_default_external(rb_enc_from_encoding(rb_utf8_encoding()));
|
||||
#else
|
||||
ruby_init();
|
||||
rb_eval_string("$KCODE='U'");
|
||||
#endif
|
||||
|
||||
#ifdef JIT
|
||||
const char* rboptions[] = {"", "--disable-gems", "--jit-verbose=1", "--jit-max-cache=100", "--jit-min-calls=100000", "-e "};
|
||||
void* node = ruby_process_options(6, const_cast<char**>(rboptions));
|
||||
int state;
|
||||
bool valid = ruby_executable_node(node, &state);
|
||||
state = ruby_exec_node(node);
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(EASY_POKE) && !defined(__WIN32__)
|
||||
char *tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir)
|
||||
|
|
|
@ -85,12 +85,17 @@ RB_METHOD(tilemapInitialize) {
|
|||
/* Construct object */
|
||||
t = new Tilemap(viewport);
|
||||
|
||||
setPrivateData(self, t);
|
||||
|
||||
rb_iv_set(self, "viewport", viewportObj);
|
||||
|
||||
setPrivateData(self, t);
|
||||
|
||||
t->initDynAttribs();
|
||||
|
||||
wrapProperty(self, &t->getAutotiles(), "autotiles", TilemapAutotilesType);
|
||||
|
||||
wrapProperty(self, &t->getColor(), "color", ColorType);
|
||||
wrapProperty(self, &t->getTone(), "tone", ToneType);
|
||||
|
||||
VALUE autotilesObj = rb_iv_get(self, "autotiles");
|
||||
|
||||
VALUE ary = rb_ary_new2(7);
|
||||
|
@ -137,11 +142,17 @@ DEF_PROP_OBJ_REF(Tilemap, Table, MapData, "map_data")
|
|||
DEF_PROP_OBJ_REF(Tilemap, Table, FlashData, "flash_data")
|
||||
DEF_PROP_OBJ_REF(Tilemap, Table, Priorities, "priorities")
|
||||
|
||||
DEF_PROP_OBJ_VAL(Tilemap, Color, Color, "color")
|
||||
DEF_PROP_OBJ_VAL(Tilemap, Tone, Tone, "tone")
|
||||
|
||||
DEF_PROP_B(Tilemap, Visible)
|
||||
|
||||
DEF_PROP_I(Tilemap, OX)
|
||||
DEF_PROP_I(Tilemap, OY)
|
||||
|
||||
DEF_PROP_I(Tilemap, Opacity)
|
||||
DEF_PROP_I(Tilemap, BlendType)
|
||||
|
||||
void tilemapBindingInit() {
|
||||
VALUE klass = rb_define_class("TilemapAutotiles", rb_cObject);
|
||||
#if RAPI_FULL > 187
|
||||
|
@ -173,4 +184,9 @@ void tilemapBindingInit() {
|
|||
INIT_PROP_BIND(Tilemap, Visible, "visible");
|
||||
INIT_PROP_BIND(Tilemap, OX, "ox");
|
||||
INIT_PROP_BIND(Tilemap, OY, "oy");
|
||||
|
||||
INIT_PROP_BIND(Tilemap, Opacity, "opacity");
|
||||
INIT_PROP_BIND(Tilemap, BlendType, "blend_type");
|
||||
INIT_PROP_BIND(Tilemap, Color, "color");
|
||||
INIT_PROP_BIND(Tilemap, Tone, "tone");
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ embedded_shaders = [
|
|||
'simpleColor.frag',
|
||||
'simpleAlpha.frag',
|
||||
'simpleAlphaUni.frag',
|
||||
'tilemap.frag',
|
||||
'flashMap.frag',
|
||||
'minimal.vert',
|
||||
'simple.vert',
|
||||
|
|
33
shader/tilemap.frag
Normal file
33
shader/tilemap.frag
Normal file
|
@ -0,0 +1,33 @@
|
|||
|
||||
uniform sampler2D v_texture;
|
||||
|
||||
uniform lowp vec4 tone;
|
||||
|
||||
uniform lowp float opacity;
|
||||
uniform lowp vec4 color;
|
||||
|
||||
in vec2 v_texCoord;
|
||||
|
||||
const vec3 lumaF = vec3(.299, .587, .114);
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
/* Sample source color */
|
||||
vec4 frag = texture(v_texture, v_texCoord);
|
||||
|
||||
/* Apply gray */
|
||||
float luma = dot(frag.rgb, lumaF);
|
||||
frag.rgb = mix(frag.rgb, vec3(luma), tone.w);
|
||||
|
||||
/* Apply tone */
|
||||
frag.rgb += tone.rgb;
|
||||
|
||||
/* Apply opacity */
|
||||
frag.a *= opacity;
|
||||
|
||||
/* Apply color */
|
||||
frag.rgb = mix(frag.rgb, color.rgb, color.a);
|
||||
|
||||
fragColor = frag;
|
||||
}
|
|
@ -4,23 +4,36 @@ uniform mat4 projMat;
|
|||
uniform vec2 texSizeInv;
|
||||
uniform vec2 translation;
|
||||
|
||||
uniform float aniIndex;
|
||||
uniform highp int aniIndex;
|
||||
|
||||
attribute vec2 position;
|
||||
attribute vec2 texCoord;
|
||||
|
||||
varying vec2 v_texCoord;
|
||||
|
||||
const float atAreaW = 96.0;
|
||||
const float atAreaH = 128.0*7.0;
|
||||
const float atAniOffset = 32.0*3.0;
|
||||
const int nAutotiles = 7;
|
||||
const float tileW = 32.0;
|
||||
const float tileH = 32.0;
|
||||
const float autotileW = 3.0*tileW;
|
||||
const float autotileH = 4.0*tileW;
|
||||
const float atAreaW = autotileW;
|
||||
const float atAreaH = autotileH*nAutotiles;
|
||||
const float atAniOffsetX = 3.0*tileW;
|
||||
const float atAniOffsetY = tileH;
|
||||
|
||||
uniform lowp int atFrames[nAutotiles];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 tex = texCoord;
|
||||
lowp uint atIndex = uint(tex.y / autotileH);
|
||||
|
||||
lowp float pred = float(tex.x <= atAreaW && tex.y <= atAreaH);
|
||||
tex.x += aniIndex * atAniOffset * pred;
|
||||
lowp uint pred = uint(tex.x <= atAreaW && tex.y <= atAreaH);
|
||||
lowp uint frame = uint(aniIndex % atFrames[atIndex]);
|
||||
lowp uint col = frame % 8;
|
||||
lowp uint row = frame / 8;
|
||||
tex.x += atAniOffsetX * (col * pred);
|
||||
tex.y += atAniOffsetY * (row * pred);
|
||||
|
||||
gl_Position = projMat * vec4(position + translation, 0, 1);
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ typedef void (APIENTRYP _PFNGLUNIFORM1FPROC) (GLint location, GLfloat v0);
|
|||
typedef void (APIENTRYP _PFNGLUNIFORM2FPROC) (GLint location, GLfloat v0, GLfloat v1);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM4FPROC) (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM1IPROC) (GLint location, GLint v0);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORM1IVPROC) (GLint location, GLsizei count, const GLint *value);
|
||||
typedef void (APIENTRYP _PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
|
||||
|
||||
/* Vertex attribute */
|
||||
|
@ -174,6 +175,7 @@ typedef void (APIENTRYP _PFNGLRELEASESHADERCOMPILERPROC) (void);
|
|||
GL_FUN(Uniform2f, _PFNGLUNIFORM2FPROC) \
|
||||
GL_FUN(Uniform4f, _PFNGLUNIFORM4FPROC) \
|
||||
GL_FUN(Uniform1i, _PFNGLUNIFORM1IPROC) \
|
||||
GL_FUN(Uniform1iv, _PFNGLUNIFORM1IVPROC) \
|
||||
GL_FUN(UniformMatrix4fv, _PFNGLUNIFORMMATRIX4FVPROC) \
|
||||
/* Vertex attribute */ \
|
||||
GL_FUN(BindAttribLocation, _PFNGLBINDATTRIBLOCATIONPROC) \
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "simpleColor.frag.xxd"
|
||||
#include "simpleAlpha.frag.xxd"
|
||||
#include "simpleAlphaUni.frag.xxd"
|
||||
#include "tilemap.frag.xxd"
|
||||
#include "flashMap.frag.xxd"
|
||||
#include "minimal.vert.xxd"
|
||||
#include "simple.vert.xxd"
|
||||
|
@ -515,16 +516,41 @@ void GrayShader::setGray(float value)
|
|||
|
||||
TilemapShader::TilemapShader()
|
||||
{
|
||||
INIT_SHADER(tilemap, simple, TilemapShader);
|
||||
INIT_SHADER(tilemap, tilemap, TilemapShader);
|
||||
|
||||
ShaderBase::init();
|
||||
|
||||
GET_U(tone);
|
||||
GET_U(color);
|
||||
GET_U(opacity);
|
||||
|
||||
GET_U(aniIndex);
|
||||
GET_U(atFrames);
|
||||
}
|
||||
|
||||
void TilemapShader::setTone(const Vec4 &tone)
|
||||
{
|
||||
setVec4Uniform(u_tone, tone);
|
||||
}
|
||||
|
||||
void TilemapShader::setColor(const Vec4 &color)
|
||||
{
|
||||
setVec4Uniform(u_color, color);
|
||||
}
|
||||
|
||||
void TilemapShader::setOpacity(float value)
|
||||
{
|
||||
gl.Uniform1f(u_opacity, value);
|
||||
}
|
||||
|
||||
void TilemapShader::setAniIndex(int value)
|
||||
{
|
||||
gl.Uniform1f(u_aniIndex, value);
|
||||
gl.Uniform1i(u_aniIndex, value);
|
||||
}
|
||||
|
||||
void TilemapShader::setATFrames(int values[7])
|
||||
{
|
||||
gl.Uniform1iv(u_atFrames, 7, values);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -220,8 +220,14 @@ public:
|
|||
|
||||
void setAniIndex(int value);
|
||||
|
||||
void setTone(const Vec4 &value);
|
||||
void setColor(const Vec4 &value);
|
||||
void setOpacity(float value);
|
||||
|
||||
void setATFrames(int values[7]);
|
||||
|
||||
private:
|
||||
GLint u_aniIndex;
|
||||
GLint u_aniIndex, u_tone, u_color, u_opacity, u_atFrames;
|
||||
};
|
||||
|
||||
class FlashMapShader : public ShaderBase
|
||||
|
|
|
@ -212,7 +212,7 @@ struct SpritePrivate
|
|||
FloatRect pos = tex;
|
||||
pos.x = chunkX;
|
||||
|
||||
Quad::setTexPosRect(vert, tex, pos);
|
||||
Quad::setTexPosRect(vert, mirrored ? tex.hFlipped() : tex, pos);
|
||||
vert += 4;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,14 +40,16 @@ typedef std::vector<Column> ColumnVec;
|
|||
/* Buffer between autotile area and tileset */
|
||||
static const int atBuffer = 32;
|
||||
/* Autotile area width */
|
||||
static const int atAreaW = 96*4;
|
||||
static const int atAreaW = 32*3*8;
|
||||
/* Autotile area height */
|
||||
static const int atAreaH = 128*7 + atBuffer;
|
||||
/* Autotile area */
|
||||
static const int atArea = atAreaW * atAreaH;
|
||||
static const int atAreaH = 32*4*7 + atBuffer;
|
||||
|
||||
static const int tilesetW = 256;
|
||||
static const int tsLaneW = tilesetW / 2;
|
||||
static const int tilesetW = 32*8;
|
||||
static const int tsLaneW = tilesetW / 1;
|
||||
static const int underAtLanes = atAreaW / tsLaneW + !!(atAreaW % tsLaneW);
|
||||
|
||||
/* Autotile area */
|
||||
static const int atArea = underAtLanes * tsLaneW * atAreaH;
|
||||
|
||||
static int freeArea(int width, int height)
|
||||
{
|
||||
|
@ -56,7 +58,7 @@ static int freeArea(int width, int height)
|
|||
|
||||
Vec2i minSize(int tilesetH, int maxAtlasSize)
|
||||
{
|
||||
int width = atAreaW;
|
||||
int width = underAtLanes * tsLaneW;
|
||||
int height = atAreaH;
|
||||
|
||||
const int tsArea = tilesetW * tilesetH;
|
||||
|
@ -81,10 +83,10 @@ Vec2i minSize(int tilesetH, int maxAtlasSize)
|
|||
static ColumnVec calcSrcCols(int tilesetH)
|
||||
{
|
||||
ColumnVec cols;
|
||||
cols.reserve(2);
|
||||
// cols.reserve(2);
|
||||
|
||||
cols.push_back(Column(0, 0, tilesetH));
|
||||
cols.push_back(Column(tsLaneW, 0, tilesetH));
|
||||
// cols.push_back(Column(tsLaneW, 0, tilesetH));
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
@ -92,21 +94,19 @@ static ColumnVec calcSrcCols(int tilesetH)
|
|||
static ColumnVec calcDstCols(int atlasW, int atlasH)
|
||||
{
|
||||
ColumnVec cols;
|
||||
cols.reserve(3);
|
||||
cols.reserve(underAtLanes);
|
||||
|
||||
/* Columns below the autotile area */
|
||||
const int underAt = atlasH - atAreaH;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < underAtLanes; ++i)
|
||||
cols.push_back(Column(i*tsLaneW, atAreaH, underAt));
|
||||
|
||||
if (atlasW <= atAreaW)
|
||||
return cols;
|
||||
const int remCols = atlasW / tsLaneW - underAtLanes;
|
||||
|
||||
const int remCols = (atlasW - atAreaW) / tsLaneW;
|
||||
|
||||
for (int i = 0; i < remCols; ++i)
|
||||
cols.push_back(Column(i*tsLaneW + atAreaW, 0, atlasH));
|
||||
if (remCols > 0)
|
||||
for (int i = 0; i < remCols; ++i)
|
||||
cols.push_back(Column((underAtLanes+i)*tsLaneW, 0, atlasH));
|
||||
|
||||
return cols;
|
||||
}
|
||||
|
@ -178,17 +178,17 @@ Vec2i tileToAtlasCoor(int tileX, int tileY, int tilesetH, int atlasH)
|
|||
int longlaneH = atlasH;
|
||||
int shortlaneH = longlaneH - atAreaH;
|
||||
|
||||
int longlaneOffset = shortlaneH * 3;
|
||||
int longlaneOffset = shortlaneH * underAtLanes;
|
||||
|
||||
int laneIdx = 0;
|
||||
int atlasY = 0;
|
||||
|
||||
/* Check if we're inside the 2nd lane */
|
||||
if (laneX >= tsLaneW)
|
||||
{
|
||||
laneY += tilesetH;
|
||||
laneX -= tsLaneW;
|
||||
}
|
||||
// if (laneX >= tsLaneW)
|
||||
// {
|
||||
// laneY += tilesetH;
|
||||
// laneX -= tsLaneW;
|
||||
// }
|
||||
|
||||
if (laneY < longlaneOffset)
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ Vec2i tileToAtlasCoor(int tileX, int tileY, int tilesetH, int atlasH)
|
|||
{
|
||||
/* Right of autotile area */
|
||||
int _y = laneY - longlaneOffset;
|
||||
laneIdx = 3 + _y / longlaneH;
|
||||
laneIdx = underAtLanes + _y / longlaneH;
|
||||
atlasY = _y % longlaneH;
|
||||
}
|
||||
|
||||
|
|
211
src/tilemap.cpp
211
src/tilemap.cpp
|
@ -58,10 +58,12 @@ static const int autotileH = 4 * 32;
|
|||
|
||||
static const int autotileCount = 7;
|
||||
|
||||
static const int atAreaW = autotileW * 4;
|
||||
static const int atFrames = 8;
|
||||
static const int atFrameDur = 15;
|
||||
static const int atAreaW = autotileW * atFrames;
|
||||
static const int atAreaH = autotileH * autotileCount;
|
||||
|
||||
static const int tsLaneW = tilesetW / 2;
|
||||
static const int tsLaneW = tilesetW / 1;
|
||||
|
||||
/* Map viewport size */
|
||||
static const int viewpW = 21;
|
||||
|
@ -155,15 +157,19 @@ static const size_t zlayersMax = viewpH + 5;
|
|||
*/
|
||||
|
||||
/* Autotile animation */
|
||||
static const uint8_t atAnimation[16*4] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
|
||||
};
|
||||
// static const uint8_t atAnimation[16*8] =
|
||||
// {
|
||||
// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
// 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
// 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
// 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
// 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
// 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
// 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
|
||||
// };
|
||||
|
||||
static elementsN(atAnimation);
|
||||
// static elementsN(atAnimation);
|
||||
|
||||
/* Flash tiles pulsing opacity */
|
||||
static const uint8_t flashAlpha[] =
|
||||
|
@ -256,6 +262,12 @@ struct TilemapPrivate
|
|||
|
||||
/* Indices of animated autotiles */
|
||||
std::vector<uint8_t> animatedATs;
|
||||
|
||||
/* Whether each autotile is 3x4 or not */
|
||||
bool smallATs[autotileCount] = {false};
|
||||
|
||||
/* The number of frames for each autotile */
|
||||
int nATFrames[autotileCount] = {1};
|
||||
} atlas;
|
||||
|
||||
/* Map viewport position */
|
||||
|
@ -279,8 +291,7 @@ struct TilemapPrivate
|
|||
bool animated;
|
||||
|
||||
/* Animation state */
|
||||
uint8_t frameIdx;
|
||||
uint8_t aniIdx;
|
||||
uint32_t aniIdx;
|
||||
} tiles;
|
||||
|
||||
FlashMap flashMap;
|
||||
|
@ -322,6 +333,13 @@ struct TilemapPrivate
|
|||
/* Draw prepare call */
|
||||
sigc::connection prepareCon;
|
||||
|
||||
NormValue opacity;
|
||||
BlendType blendType;
|
||||
Color *color;
|
||||
Tone *tone;
|
||||
|
||||
EtcTemps tmp;
|
||||
|
||||
TilemapPrivate(Viewport *viewport)
|
||||
: viewport(viewport),
|
||||
tileset(0),
|
||||
|
@ -334,7 +352,12 @@ struct TilemapPrivate
|
|||
buffersDirty(false),
|
||||
mapViewportDirty(false),
|
||||
zOrderDirty(false),
|
||||
tilemapReady(false)
|
||||
tilemapReady(false),
|
||||
|
||||
opacity(255),
|
||||
blendType(BlendNormal),
|
||||
color(&tmp.color),
|
||||
tone(&tmp.tone)
|
||||
{
|
||||
memset(autotiles, 0, sizeof(autotiles));
|
||||
|
||||
|
@ -342,7 +365,6 @@ struct TilemapPrivate
|
|||
atlas.efTilesetH = 0;
|
||||
|
||||
tiles.animated = false;
|
||||
tiles.frameIdx = 0;
|
||||
tiles.aniIdx = 0;
|
||||
|
||||
/* Init tile buffers */
|
||||
|
@ -432,8 +454,18 @@ struct TilemapPrivate
|
|||
|
||||
usableATs.push_back(i);
|
||||
|
||||
if (autotiles[i]->width() > autotileW)
|
||||
if (autotiles[i]->height() == 32)
|
||||
{
|
||||
atlas.smallATs[i] = true;
|
||||
atlas.nATFrames[i] = autotiles[i]->width()/32;
|
||||
animatedATs.push_back(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
atlas.nATFrames[i] = autotiles[i]->width()/autotileW;
|
||||
if (atlas.nATFrames[i] > 1)
|
||||
animatedATs.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
tiles.animated = !animatedATs.empty();
|
||||
|
@ -509,23 +541,35 @@ struct TilemapPrivate
|
|||
const uint8_t atInd = atlas.usableATs[i];
|
||||
Bitmap *autotile = autotiles[atInd];
|
||||
|
||||
int blitW = std::min(autotile->width(), atAreaW);
|
||||
int blitH = std::min(autotile->height(), atAreaH);
|
||||
int atW = autotile->width();
|
||||
int atH = autotile->height();
|
||||
int blitW = std::min(atW, atAreaW);
|
||||
int blitH = std::min(atH, autotileH);
|
||||
|
||||
GLMeta::blitSource(autotile->getGLTypes());
|
||||
|
||||
if (blitW <= autotileW && tiles.animated)
|
||||
if (atW <= autotileW && tiles.animated && !atlas.smallATs[atInd])
|
||||
{
|
||||
/* Static autotile */
|
||||
for (int j = 0; j < 4; ++j)
|
||||
for (int j = 0; j < atFrames; ++j)
|
||||
GLMeta::blitRectangle(IntRect(0, 0, blitW, blitH),
|
||||
Vec2i(autotileW*j, atInd*autotileH));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Animated autotile */
|
||||
GLMeta::blitRectangle(IntRect(0, 0, blitW, blitH),
|
||||
Vec2i(0, atInd*autotileH));
|
||||
if (atlas.smallATs[atInd])
|
||||
{
|
||||
int frames = atW/32;
|
||||
for (int j = 0; j < atFrames*autotileH/32; ++j)
|
||||
{
|
||||
GLMeta::blitRectangle(IntRect(32*(j % frames), 0, 32, 32),
|
||||
Vec2i(autotileW*(j % atFrames), atInd*autotileH + 32*(j / atFrames)));
|
||||
}
|
||||
}
|
||||
else
|
||||
GLMeta::blitRectangle(IntRect(0, 0, blitW, blitH),
|
||||
Vec2i(0, atInd*autotileH));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -627,28 +671,42 @@ struct TilemapPrivate
|
|||
{
|
||||
/* Which autotile [0-7] */
|
||||
int atInd = tileInd / 48 - 1;
|
||||
/* Which tile pattern of the autotile [0-47] */
|
||||
int subInd = tileInd % 48;
|
||||
|
||||
const StaticRect *pieceRect = &autotileRects[subInd*4];
|
||||
|
||||
/* Iterate over the 4 tile pieces */
|
||||
for (int i = 0; i < 4; ++i)
|
||||
if (!atlas.smallATs[atInd])
|
||||
{
|
||||
FloatRect posRect(x*32, y*32, 16, 16);
|
||||
atSelectSubPos(posRect, i);
|
||||
/* Which tile pattern of the autotile [0-47] */
|
||||
int subInd = tileInd % 48;
|
||||
|
||||
FloatRect texRect = pieceRect[i];
|
||||
const StaticRect *pieceRect = &autotileRects[subInd*4];
|
||||
|
||||
/* Adjust to atlas coordinates */
|
||||
texRect.y += atInd * autotileH;
|
||||
/* Iterate over the 4 tile pieces */
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
FloatRect posRect(x*32, y*32, 16, 16);
|
||||
atSelectSubPos(posRect, i);
|
||||
|
||||
FloatRect texRect = pieceRect[i];
|
||||
|
||||
/* Adjust to atlas coordinates */
|
||||
texRect.y += atInd * autotileH;
|
||||
|
||||
SVertex v[4];
|
||||
Quad::setTexPosRect(v, texRect, posRect);
|
||||
|
||||
/* Iterate over 4 vertices */
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
array->push_back(v[j]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatRect posRect(x*32, y*32, 32, 32);
|
||||
FloatRect texRect(0.5f, atInd * autotileH + 0.5f, 31, 31);
|
||||
SVertex v[4];
|
||||
Quad::setTexPosRect(v, texRect, posRect);
|
||||
|
||||
/* Iterate over 4 vertices */
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
array->push_back(v[i]);
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
array->push_back(v[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -677,6 +735,8 @@ struct TilemapPrivate
|
|||
else
|
||||
{
|
||||
int layerInd = y + prio;
|
||||
if (layerInd >= zlayersMax)
|
||||
return;
|
||||
targetArray = &zlayerVert[layerInd];
|
||||
}
|
||||
|
||||
|
@ -714,8 +774,30 @@ struct TilemapPrivate
|
|||
{
|
||||
clearQuadArrays();
|
||||
|
||||
for (int x = 0; x < viewpW; ++x)
|
||||
for (int y = 0; y < viewpH; ++y)
|
||||
int ox = viewpPos.x;
|
||||
int oy = viewpPos.y;
|
||||
int mapW = mapData->xSize();
|
||||
int mapH = mapData->ySize();
|
||||
|
||||
int minX = 0;
|
||||
int minY = 0;
|
||||
if (ox < 0)
|
||||
minX = -ox;
|
||||
if (oy < 0)
|
||||
minY = -oy;
|
||||
|
||||
// There could be off-by-one issues in these couple sections.
|
||||
int maxX = viewpW;
|
||||
int maxY = viewpH;
|
||||
if (ox + maxX >= mapW)
|
||||
maxX = mapW - ox - 1;
|
||||
if (oy + maxY >= mapH)
|
||||
maxY = mapH - oy - 1;
|
||||
|
||||
if ((minX > maxX) || (minY > maxY))
|
||||
return;
|
||||
for (int x = minX; x <= maxX; ++x)
|
||||
for (int y = minY; y <= maxY; ++y)
|
||||
for (int z = 0; z < mapData->zSize(); ++z)
|
||||
handleTile(x, y, z);
|
||||
}
|
||||
|
@ -766,11 +848,16 @@ struct TilemapPrivate
|
|||
|
||||
void bindShader(ShaderBase *&shaderVar)
|
||||
{
|
||||
if (tiles.animated)
|
||||
if (tiles.animated || color->hasEffect() || tone->hasEffect() || opacity != 255)
|
||||
{
|
||||
TilemapShader &tilemapShader = shState->shaders().tilemap;
|
||||
tilemapShader.bind();
|
||||
tilemapShader.setAniIndex(tiles.frameIdx);
|
||||
tilemapShader.applyViewportProj();
|
||||
tilemapShader.setTone(tone->norm);
|
||||
tilemapShader.setColor(color->norm);
|
||||
tilemapShader.setOpacity(opacity.norm);
|
||||
tilemapShader.setAniIndex(tiles.aniIdx / atFrameDur);
|
||||
tilemapShader.setATFrames(atlas.nATFrames);
|
||||
shaderVar = &tilemapShader;
|
||||
}
|
||||
else
|
||||
|
@ -974,11 +1061,16 @@ void GroundLayer::draw()
|
|||
if (p->groundVert.size() == 0)
|
||||
return;
|
||||
|
||||
if (!p->opacity)
|
||||
return;
|
||||
|
||||
ShaderBase *shader;
|
||||
|
||||
p->bindShader(shader);
|
||||
p->bindAtlas(*shader);
|
||||
|
||||
glState.blendMode.pushSet(p->blendType);
|
||||
|
||||
GLMeta::vaoBind(p->tiles.vao);
|
||||
|
||||
shader->setTranslation(p->dispPos);
|
||||
|
@ -987,6 +1079,8 @@ void GroundLayer::draw()
|
|||
GLMeta::vaoUnbind(p->tiles.vao);
|
||||
|
||||
p->flashMap.draw(flashAlpha[p->flashAlphaIdx] / 255.f, p->dispPos);
|
||||
|
||||
glState.blendMode.pop();
|
||||
}
|
||||
|
||||
void GroundLayer::drawInt()
|
||||
|
@ -1029,12 +1123,16 @@ void ZLayer::draw()
|
|||
p->bindShader(shader);
|
||||
p->bindAtlas(*shader);
|
||||
|
||||
glState.blendMode.pushSet(p->blendType);
|
||||
|
||||
GLMeta::vaoBind(p->tiles.vao);
|
||||
|
||||
shader->setTranslation(p->dispPos);
|
||||
drawInt();
|
||||
|
||||
GLMeta::vaoUnbind(p->tiles.vao);
|
||||
|
||||
glState.blendMode.pop();
|
||||
}
|
||||
|
||||
void ZLayer::drawInt()
|
||||
|
@ -1125,10 +1223,7 @@ void Tilemap::update()
|
|||
if (!p->tiles.animated)
|
||||
return;
|
||||
|
||||
p->tiles.frameIdx = atAnimation[p->tiles.aniIdx];
|
||||
|
||||
if (++p->tiles.aniIdx >= atAnimationN)
|
||||
p->tiles.aniIdx = 0;
|
||||
++p->tiles.aniIdx;
|
||||
}
|
||||
|
||||
Tilemap::Autotiles &Tilemap::getAutotiles()
|
||||
|
@ -1147,6 +1242,11 @@ DEF_ATTR_RD_SIMPLE(Tilemap, Visible, bool, p->visible)
|
|||
DEF_ATTR_RD_SIMPLE(Tilemap, OX, int, p->origin.x)
|
||||
DEF_ATTR_RD_SIMPLE(Tilemap, OY, int, p->origin.y)
|
||||
|
||||
DEF_ATTR_RD_SIMPLE(Tilemap, BlendType, int, p->blendType)
|
||||
DEF_ATTR_SIMPLE(Tilemap, Opacity, int, p->opacity)
|
||||
DEF_ATTR_SIMPLE(Tilemap, Color, Color&, *p->color)
|
||||
DEF_ATTR_SIMPLE(Tilemap, Tone, Tone&, *p->tone)
|
||||
|
||||
void Tilemap::setTileset(Bitmap *value)
|
||||
{
|
||||
guardDisposed();
|
||||
|
@ -1250,6 +1350,31 @@ void Tilemap::setOY(int value)
|
|||
p->mapViewportDirty = true;
|
||||
}
|
||||
|
||||
void Tilemap::setBlendType(int value)
|
||||
{
|
||||
guardDisposed();
|
||||
|
||||
switch (value)
|
||||
{
|
||||
default :
|
||||
case BlendNormal :
|
||||
p->blendType = BlendNormal;
|
||||
return;
|
||||
case BlendAddition :
|
||||
p->blendType = BlendAddition;
|
||||
return;
|
||||
case BlendSubstraction :
|
||||
p->blendType = BlendSubstraction;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Tilemap::initDynAttribs()
|
||||
{
|
||||
p->color = new Color;
|
||||
p->tone = new Tone;
|
||||
}
|
||||
|
||||
void Tilemap::releaseResources()
|
||||
{
|
||||
delete p;
|
||||
|
|
|
@ -30,6 +30,9 @@ class Viewport;
|
|||
class Bitmap;
|
||||
class Table;
|
||||
|
||||
struct Color;
|
||||
struct Tone;
|
||||
|
||||
struct TilemapPrivate;
|
||||
|
||||
class Tilemap : public Disposable
|
||||
|
@ -66,6 +69,13 @@ public:
|
|||
DECL_ATTR( OX, int )
|
||||
DECL_ATTR( OY, int )
|
||||
|
||||
DECL_ATTR( Opacity, int )
|
||||
DECL_ATTR( BlendType, int )
|
||||
DECL_ATTR( Color, Color& )
|
||||
DECL_ATTR( Tone, Tone& )
|
||||
|
||||
void initDynAttribs();
|
||||
|
||||
private:
|
||||
TilemapPrivate *p;
|
||||
Autotiles atProxy;
|
||||
|
|
Loading…
Reference in a new issue