diff --git a/binding/binding-mri.cpp b/binding/binding-mri.cpp index 8cf1bde7..c034c61c 100644 --- a/binding/binding-mri.cpp +++ b/binding/binding-mri.cpp @@ -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(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) diff --git a/binding/tilemap-binding.cpp b/binding/tilemap-binding.cpp index 3e802a8f..1d6ef7dc 100644 --- a/binding/tilemap-binding.cpp +++ b/binding/tilemap-binding.cpp @@ -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"); } diff --git a/shader/meson.build b/shader/meson.build index 8eb0c6d5..1290460f 100644 --- a/shader/meson.build +++ b/shader/meson.build @@ -13,6 +13,7 @@ embedded_shaders = [ 'simpleColor.frag', 'simpleAlpha.frag', 'simpleAlphaUni.frag', + 'tilemap.frag', 'flashMap.frag', 'minimal.vert', 'simple.vert', diff --git a/shader/tilemap.frag b/shader/tilemap.frag new file mode 100644 index 00000000..7f988839 --- /dev/null +++ b/shader/tilemap.frag @@ -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; +} diff --git a/shader/tilemap.vert b/shader/tilemap.vert index 05c5f72c..333de6cb 100644 --- a/shader/tilemap.vert +++ b/shader/tilemap.vert @@ -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); diff --git a/src/gl-fun.h b/src/gl-fun.h index b989ba9e..811be8fa 100644 --- a/src/gl-fun.h +++ b/src/gl-fun.h @@ -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) \ diff --git a/src/shader.cpp b/src/shader.cpp index f423969c..260e250a 100644 --- a/src/shader.cpp +++ b/src/shader.cpp @@ -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); } diff --git a/src/shader.h b/src/shader.h index 7b4eb025..cdfc9f6e 100644 --- a/src/shader.h +++ b/src/shader.h @@ -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 diff --git a/src/sprite.cpp b/src/sprite.cpp index f4c8f892..3391af8c 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -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; } diff --git a/src/tileatlas.cpp b/src/tileatlas.cpp index 109d7339..e382b115 100644 --- a/src/tileatlas.cpp +++ b/src/tileatlas.cpp @@ -40,14 +40,16 @@ typedef std::vector 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; } diff --git a/src/tilemap.cpp b/src/tilemap.cpp index 8b61ea77..8a009d97 100644 --- a/src/tilemap.cpp +++ b/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 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; diff --git a/src/tilemap.h b/src/tilemap.h index 9afe00fc..0f984d6d 100644 --- a/src/tilemap.h +++ b/src/tilemap.h @@ -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;