Implement RGSS2 Tilemap class (TilemapVX)

This commit is contained in:
Jonas Kulla 2014-08-15 13:59:28 +02:00
parent 3717609142
commit 7790bd6c2c
12 changed files with 1797 additions and 9 deletions

View File

@ -61,6 +61,7 @@ void tilemapBindingInit();
#ifdef RGSS2 #ifdef RGSS2
void windowVXBindingInit(); void windowVXBindingInit();
void tilemapVXBindingInit();
#endif #endif
void inputBindingInit(); void inputBindingInit();
@ -87,12 +88,13 @@ static void mriBindingInit()
spriteBindingInit(); spriteBindingInit();
viewportBindingInit(); viewportBindingInit();
planeBindingInit(); planeBindingInit();
tilemapBindingInit();
#ifdef RGSS2 #ifdef RGSS2
windowVXBindingInit(); windowVXBindingInit();
tilemapVXBindingInit();
#else #else
windowBindingInit(); windowBindingInit();
tilemapBindingInit();
#endif #endif
inputBindingInit(); inputBindingInit();

View File

@ -126,9 +126,10 @@ setPrivateData(VALUE self, void *p)
} }
inline VALUE inline VALUE
wrapObject(void *p, const rb_data_type_struct &type) wrapObject(void *p, const rb_data_type_struct &type,
VALUE underKlass = rb_cObject)
{ {
VALUE klass = rb_const_get(rb_cObject, rb_intern(type.wrap_struct_name)); VALUE klass = rb_const_get(underKlass, rb_intern(type.wrap_struct_name));
VALUE obj = rb_obj_alloc(klass); VALUE obj = rb_obj_alloc(klass);
setPrivateData(obj, p); setPrivateData(obj, p);
@ -138,9 +139,10 @@ wrapObject(void *p, const rb_data_type_struct &type)
inline VALUE inline VALUE
wrapProperty(VALUE self, void *prop, const char *iv, wrapProperty(VALUE self, void *prop, const char *iv,
const rb_data_type_struct &type) const rb_data_type_struct &type,
VALUE underKlass = rb_cObject)
{ {
VALUE propObj = wrapObject(prop, type); VALUE propObj = wrapObject(prop, type, underKlass);
rb_iv_set(self, iv, propObj); rb_iv_set(self, iv, propObj);

View File

@ -0,0 +1,158 @@
/*
** tilemapvx-binding.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2014 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tilemapvx.h"
#include "viewport.h"
#include "bitmap.h"
#include "table.h"
#include "disposable-binding.h"
#include "binding-util.h"
#include "binding-types.h"
DEF_TYPE(TilemapVX);
rb_data_type_struct BitmapArrayType;
RB_METHOD(tilemapVXInitialize)
{
TilemapVX *t;
/* Get parameters */
VALUE viewportObj = Qnil;
Viewport *viewport = 0;
rb_get_args(argc, argv, "|o", &viewportObj RB_ARG_END);
if (!NIL_P(viewportObj))
viewport = getPrivateDataCheck<Viewport>(viewportObj, ViewportType);
/* Construct object */
t = new TilemapVX(viewport);
setPrivateData(self, t);
rb_iv_set(self, "viewport", viewportObj);
wrapProperty(self, &t->getBitmapArray(), "bitmap_array", BitmapArrayType,
rb_const_get(rb_cObject, rb_intern("Tilemap")));
VALUE autotilesObj = rb_iv_get(self, "bitmap_array");
VALUE ary = rb_ary_new2(7);
for (int i = 0; i < 7; ++i)
rb_ary_push(ary, Qnil);
rb_iv_set(autotilesObj, "array", ary);
return self;
}
RB_METHOD(tilemapVXGetBitmapArray)
{
RB_UNUSED_PARAM;
return rb_iv_get(self, "bitmap_array");
}
RB_METHOD(tilemapVXUpdate)
{
RB_UNUSED_PARAM;
TilemapVX *t = getPrivateData<TilemapVX>(self);
t->update();
return Qnil;
}
DEF_PROP_OBJ_NIL(TilemapVX, Viewport, Viewport, "viewport")
DEF_PROP_OBJ(TilemapVX, Table, MapData, "map_data")
DEF_PROP_OBJ(TilemapVX, Table, FlashData, "flash_data")
DEF_PROP_OBJ(TilemapVX, Table, Flags, "flags")
DEF_PROP_B(TilemapVX, Visible)
DEF_PROP_I(TilemapVX, OX)
DEF_PROP_I(TilemapVX, OY)
RB_METHOD(tilemapVXBitmapsSet)
{
TilemapVX::BitmapArray *a = getPrivateData<TilemapVX::BitmapArray>(self);
int i;
VALUE bitmapObj;
rb_get_args(argc, argv, "io", &i, &bitmapObj RB_ARG_END);
Bitmap *bitmap = getPrivateDataCheck<Bitmap>(bitmapObj, BitmapType);
a->set(i, bitmap);
VALUE ary = rb_iv_get(self, "array");
rb_ary_store(ary, i, bitmapObj);
return self;
}
RB_METHOD(tilemapVXBitmapsGet)
{
int i;
rb_get_args (argc, argv, "i", &i RB_ARG_END);
if (i < 0 || i > 6)
return Qnil;
VALUE ary = rb_iv_get(self, "array");
return rb_ary_entry(ary, i);
}
void
tilemapVXBindingInit()
{
initType(TilemapVXType, "Tilemap", freeInstance<TilemapVX>);
VALUE klass = rb_define_class("Tilemap", rb_cObject);
rb_define_alloc_func(klass, classAllocate<&TilemapVXType>);
disposableBindingInit<TilemapVX>(klass);
_rb_define_method(klass, "initialize", tilemapVXInitialize);
_rb_define_method(klass, "bitmaps", tilemapVXGetBitmapArray);
_rb_define_method(klass, "update", tilemapVXUpdate);
INIT_PROP_BIND( TilemapVX, Viewport, "viewport" );
INIT_PROP_BIND( TilemapVX, MapData, "map_data" );
INIT_PROP_BIND( TilemapVX, FlashData, "flash_data" );
INIT_PROP_BIND( TilemapVX, Flags, "flags" );
INIT_PROP_BIND( TilemapVX, Visible, "visible" );
INIT_PROP_BIND( TilemapVX, OX, "ox" );
INIT_PROP_BIND( TilemapVX, OY, "oy" );
initType(BitmapArrayType, "BitmapArray", 0);
klass = rb_define_class_under(klass, "BitmapArray", rb_cObject);
rb_define_alloc_func(klass, classAllocate<&BitmapArrayType>);
_rb_define_method(klass, "[]=", tilemapVXBitmapsSet);
_rb_define_method(klass, "[]", tilemapVXBitmapsGet);
}

View File

@ -197,17 +197,23 @@ EMBED = \
RGSS2 { RGSS2 {
HEADERS += \ HEADERS += \
src/windowvx.h src/windowvx.h \
src/tilemapvx.h \
src/tileatlasvx.h
SOURCES += \ SOURCES += \
src/vorbissource.cpp \ src/vorbissource.cpp \
src/windowvx.cpp src/windowvx.cpp \
src/tilemapvx.cpp \
src/tileatlasvx.cpp \
src/autotilesvx.cpp
EMBED += \ EMBED += \
shader/blur.frag \ shader/blur.frag \
shader/blurH.vert \ shader/blurH.vert \
shader/blurV.vert \ shader/blurV.vert \
shader/simpleMatrix.vert shader/simpleMatrix.vert \
shader/tilemapvx.vert
} }
MIDI { MIDI {
@ -318,7 +324,8 @@ BINDING_MRI {
RGSS2 { RGSS2 {
SOURCES += \ SOURCES += \
binding-mri/windowvx-binding.cpp binding-mri/windowvx-binding.cpp \
binding-mri/tilemapvx-binding.cpp
} }
} }

33
shader/tilemapvx.vert Normal file
View File

@ -0,0 +1,33 @@
uniform mat4 projMat;
uniform vec2 texSizeInv;
uniform vec2 translation;
uniform vec2 aniOffset;
attribute vec2 position;
attribute vec2 texCoord;
varying vec2 v_texCoord;
const vec2 atAreaA = vec2(9.0*32.0, 12.0*32.0);
const float atAreaCX = 12.0*32.0;
const float atAreaCW = 4.0*32.0;
void main()
{
vec2 tex = texCoord;
/* Type A autotiles shift horizontally */
if (tex.x <= atAreaA.x && tex.y <= atAreaA.y)
tex.x += aniOffset.x;
/* Type C autotiles shift vertically */
if (tex.x >= atAreaCX && tex.x <= (atAreaCX+atAreaCW) && tex.y <= atAreaA.y)
tex.y += aniOffset.y;
gl_Position = projMat * vec4(position + translation, 0, 1);
v_texCoord = tex * texSizeInv;
}

269
src/autotilesvx.cpp Normal file
View File

@ -0,0 +1,269 @@
struct StaticRect { float x, y, w, h; };
extern const StaticRect autotileVXRectsA[] =
{
{ 32.5, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 64.5, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 48.5, 80.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 48.5, 80.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 16, 64.5, 15, 15 },
{ 0, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 0, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 0, 80.5, 15, 15 },
{ 16, 80.5, 15, 15 },
{ 0, 64.5, 15, 15 },
{ 48.5, 64.5, 15, 15 },
{ 0, 80.5, 15, 15 },
{ 48.5, 80.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 32.5, 80.5, 15, 15 },
{ 48.5, 80.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 0, 80.5, 15, 15 },
{ 48.5, 80.5, 15, 15 },
{ 0, 0, 15, 15 },
{ 16, 0, 15, 15 },
{ 0, 16, 15, 15 },
{ 16, 16, 15, 15 }
};
extern const int autotileVXRectsAN = sizeof(autotileVXRectsA) / sizeof(autotileVXRectsA[0]);
extern const StaticRect autotileVXRectsB[] =
{
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 16, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 0, 16, 15, 15 },
{ 16, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 16, 16, 15, 15 },
{ 0, 0, 15, 15 },
{ 16, 0, 15, 15 },
{ 0, 16, 15, 15 },
{ 16, 16, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 0, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 0, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 0, 16, 15, 15 },
{ 48.5, 16, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 16, 32.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 16, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 0, 0, 15, 15 },
{ 16, 0, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 16, 48.5, 15, 15 },
{ 32.5, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 0, 32.5, 15, 15 },
{ 48.5, 32.5, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 32.5, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 32.5, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 },
{ 0, 0, 15, 15 },
{ 48.5, 0, 15, 15 },
{ 0, 48.5, 15, 15 },
{ 48.5, 48.5, 15, 15 }
};
extern const int autotileVXRectsBN = sizeof(autotileVXRectsB) / sizeof(autotileVXRectsB[0]);

View File

@ -48,6 +48,7 @@
#include "../simpleMatrix.vert.xxd" #include "../simpleMatrix.vert.xxd"
#include "../blurH.vert.xxd" #include "../blurH.vert.xxd"
#include "../blurV.vert.xxd" #include "../blurV.vert.xxd"
#include "../tilemapvx.vert.xxd"
#endif #endif
@ -535,6 +536,21 @@ BlurShader::VPass::VPass()
ShaderBase::init(); ShaderBase::init();
} }
TilemapVXShader::TilemapVXShader()
{
INIT_SHADER(tilemapvx, simple, TilemapVXShader);
ShaderBase::init();
GET_U(aniOffset);
}
void TilemapVXShader::setAniOffset(const Vec2 &value)
{
gl.Uniform2f(u_aniOffset, value.x, value.y);
}
#endif #endif

View File

@ -243,6 +243,18 @@ struct BlurShader
HPass pass1; HPass pass1;
VPass pass2; VPass pass2;
}; };
class TilemapVXShader : public ShaderBase
{
public:
TilemapVXShader();
void setAniOffset(const Vec2 &value);
private:
GLint u_aniOffset;
};
#endif #endif
/* Bitmap blit */ /* Bitmap blit */
@ -280,6 +292,7 @@ struct ShaderSet
#ifdef RGSS2 #ifdef RGSS2
SimpleMatrixShader simpleMatrix; SimpleMatrixShader simpleMatrix;
BlurShader blur; BlurShader blur;
TilemapVXShader tilemapVX;
#endif #endif
}; };

635
src/tileatlasvx.cpp Normal file
View File

@ -0,0 +1,635 @@
/*
** tileatlasvx.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2014 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tileatlasvx.h"
#include "bitmap.h"
#include "table.h"
#include "etc-internal.h"
#include "gl-util.h"
#include "gl-meta.h"
#include "sharedstate.h"
#include "glstate.h"
#include "texpool.h"
#include "util.h"
#include <assert.h>
#include <vector>
/* Regular autotile patterns */
extern const StaticRect autotileVXRectsA[];
extern const int autotileVXRectsAN;
/* Wall autotile patterns */
extern const StaticRect autotileVXRectsB[];
extern const int autotileVXRectsBN;
static const StaticRect autotileVXRectsC[] =
{
{ 32.5, 0.5, 15, 31 },
{ 16.5, 0.5, 15, 31 },
{ 0.0, 0.5, 15, 31 },
{ 16.5, 0.5, 15, 31 },
{ 32.5, 0.5, 15, 31 },
{ 48.5, 0.5, 15, 31 },
{ 0.0, 0.5, 15, 31 },
{ 48.5, 0.5, 15, 31 }
};
static elementsN(autotileVXRectsC);
namespace TileAtlasVX
{
static int
wrap(int value, int range)
{
int res = value % range;
return res < 0 ? res + range : res;
}
static int16_t
tableGetWrapped(const Table &t, int x, int y, int z = 0)
{
return t.at(wrap(x, t.xSize()),
wrap(y, t.ySize()),
z);
}
static int16_t
tableGetSafe(const Table *t, int x)
{
if (!t)
return 0;
if (x < 0 || x >= t->xSize())
return 0;
return t->at(x);
}
/* All below constants are in tiles (= 32 pixels) */
struct Size
{
int w, h;
Size(int w, int h)
: w(w), h(h)
{}
};
static const Size bmSizes[BM_COUNT] =
{
Size(16, 12), /* A1 */
Size(16, 12), /* A2 */
Size(16, 8), /* A3 */
Size(16, 15), /* A4 */
Size( 8, 16), /* A5 */
Size(16, 16), /* B */
Size(16, 16), /* C */
Size(16, 16), /* D */
Size(16, 16), /* E */
};
static const Size atArea(16, 13);
static const Vec2i freeArea(8, 48);
static const Vec2i CDEArea(16, 0);
struct Blit
{
IntRect src;
Vec2i dst;
Blit(int srcX, int srcY, int w, int h, int dstX, int dstY)
: src(srcX, srcY, w, h),
dst(dstX, dstY)
{}
Blit(int srcX, int srcY, const Size &size, int dstX, int dstY)
: src(srcX, srcY, size.w, size.h),
dst(dstX, dstY)
{}
};
static const Blit blitsA1[] =
{
/* Animated A autotiles */
Blit(0, 0, 6, 12, 0, 0),
Blit(8, 0, 6, 12, 6, 0),
/* Unanimated A autotiles */
Blit(6, 0, 2, 6, freeArea.x, freeArea.y),
/* C autotiles */
Blit(14, 0, 2, 6, 12, 0),
Blit(6, 6, 2, 6, 14, 0),
Blit(14, 6, 2, 6, 12, 6)
};
static const Blit blitsA2[] =
{
Blit(0, 0, bmSizes[BM_A2], 0, atArea.h)
};
static const Blit blitsA3[] =
{
Blit(0, 0, bmSizes[BM_A3], 0, blitsA2[0].dst.y+blitsA2[0].src.h)
};
static const Blit blitsA4[] =
{
Blit(0, 0, bmSizes[BM_A4], 0, blitsA3[0].dst.y+blitsA3[0].src.h)
};
static const Blit blitsA5[] =
{
Blit(0, 0, bmSizes[BM_A5], 0, blitsA4[0].dst.y+blitsA4[0].src.h)
};
static const Blit blitsB[] =
{
Blit(0, 0, bmSizes[BM_B], atArea.w, 0)
};
static const Blit blitsC[] =
{
Blit(0, 0, bmSizes[BM_C], blitsA2[0].src.w, blitsB[0].dst.y+blitsB[0].src.h)
};
static const Blit blitsD[] =
{
Blit(0, 0, bmSizes[BM_D], blitsC[0].dst.x, blitsC[0].dst.y+blitsC[0].src.h)
};
static const Blit blitsE[] =
{
Blit(0, 0, bmSizes[BM_E], blitsD[0].dst.x, blitsD[0].dst.y+blitsD[0].src.h)
};
static elementsN(blitsA1);
static elementsN(blitsA2);
static elementsN(blitsA3);
static elementsN(blitsA4);
static elementsN(blitsA5);
static elementsN(blitsB);
static elementsN(blitsC);
static elementsN(blitsD);
static elementsN(blitsE);
/* 'Waterfall' autotiles atlas origin */
static const Vec2i AEPartsDst[] =
{
Vec2i(12, 0),
Vec2i(12, 3),
Vec2i(14, 0),
Vec2i(14, 3),
Vec2i(12, 6),
Vec2i(12, 9)
};
static const Vec2i shadowArea(freeArea.x+2, freeArea.y);
static SDL_Surface*
createShadowSet()
{
int bpp;
Uint32 rm, gm, bm, am;
SDL_PixelFormatEnumToMasks(SDL_PIXELFORMAT_ABGR8888, &bpp, &rm, &gm, &bm, &am);
SDL_Surface *surf = SDL_CreateRGBSurface(0, 1*32, 16*32, bpp, rm, gm, bm, am);
std::vector<SDL_Rect> rects;
SDL_Rect rect = { 0, 0, 16, 16 };
for (int val = 0; val < 16; ++val)
{
int origY = val*32;
/* Top left */
if (val & (1 << 0))
{
rect.x = 0;
rect.y = origY;
rects.push_back(rect);
}
/* Top Right */
if (val & (1 << 1))
{
rect.x = 16;
rect.y = origY;
rects.push_back(rect);
}
/* Bottom left */
if (val & (1 << 2))
{
rect.x = 0;
rect.y = origY+16;
rects.push_back(rect);
}
/* Bottom right */
if (val & (1 << 3))
{
rect.x = 16;
rect.y = origY+16;
rects.push_back(rect);
}
}
/* Fill rects with half opacity black */
uint32_t color = (0x80808080 & am);
SDL_FillRects(surf, &rects[0], rects.size(), color);
return surf;
}
void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT])
{
assert(tf.width == ATLASVX_W && tf.height == ATLASVX_H);
GLMeta::blitBegin(tf);
glState.clearColor.pushSet(Vec4());
FBO::clear();
glState.clearColor.pop();
SDL_Surface *shadow = createShadowSet();
TEX::bind(tf.tex);
TEX::uploadSubImage(shadowArea.x*32, shadowArea.y*32,
shadow->w, shadow->h, shadow->pixels, GL_RGBA);
SDL_FreeSurface(shadow);
Bitmap *bm;
#define EXEC_BLITS(part) \
if ((bm = bitmaps[BM_##part])) \
{ \
GLMeta::blitSource(bm->getGLTypes()); \
for (size_t i = 0; i < blits##part##N; ++i) \
{\
IntRect src = blits##part[i].src; \
src = IntRect(src.x*32, src.y*32, src.w*32, src.h*32); \
Vec2i dst = blits##part[i].dst; \
dst = Vec2i(dst.x*32, dst.y*32); \
GLMeta::blitRectangle(src, dst); \
} \
}
EXEC_BLITS(A1);
EXEC_BLITS(A2);
EXEC_BLITS(A3);
EXEC_BLITS(A4);
EXEC_BLITS(A5);
EXEC_BLITS(B);
EXEC_BLITS(C);
EXEC_BLITS(D);
EXEC_BLITS(E);
#undef EXEC_BLITS
GLMeta::blitEnd();
}
#define OVER_PLAYER_FLAG (1 << 4)
static void
atSelectSubPos(FloatRect &pos, int i)
{
switch (i)
{
case 0:
return;
case 1:
pos.x += 16;
return;
case 2:
pos.y += 16;
return;
case 3:
pos.x += 16;
pos.y += 16;
return;
default:
assert(!"Unreachable");
}
}
/* Reference: http://www.tktkgame.com/tkool/memo/vx/tile_id.html */
static void
readAutotile(Reader &reader, int patternID,
const Vec2i &orig, int x, int y,
const StaticRect rectSource[], int rectSourceN)
{
FloatRect tex[4], pos[4];
for (int i = 0; i < 4; ++i)
{
assert((patternID*4 + i) < rectSourceN);
tex[i] = FloatRect(rectSource[patternID*4 + i]);
tex[i].x += orig.x*32;
tex[i].y += orig.y*32;
pos[i] = FloatRect(x*32, y*32, 16, 16);
atSelectSubPos(pos[i], i);
}
reader.onQuads4(tex, pos);
}
static void
readAutotileA(Reader &reader, int patternID,
const Vec2i &orig, int x, int y)
{
readAutotile(reader, patternID, orig, x, y,
autotileVXRectsA, autotileVXRectsAN);
}
static void
readAutotileB(Reader &reader, int patternID,
const Vec2i &orig, int x, int y)
{
if (patternID >= 0x10)
return;
readAutotile(reader, patternID, orig, x, y,
autotileVXRectsB, autotileVXRectsBN);
}
static void
readAutotileC(Reader &reader, int patternID,
const Vec2i &orig, int x, int y)
{
if (patternID > 0x3)
return;
FloatRect tex[2], pos[2];
for (size_t i = 0; i < 2; ++i)
{
tex[i] = autotileVXRectsC[patternID*2+i];
tex[i].x += orig.x*32;
tex[i].y += orig.y*32;
pos[i] = FloatRect(x*32, y*32, 16, 32);
pos[i].x += i*16;
}
reader.onQuads2(tex, pos);
}
static void
onTileA1(Reader &reader, int16_t tileID,
const int x, const int y)
{
tileID -= 0x0800;
int patternID = tileID % 0x30;
int autotileID = tileID / 0x30;
const Vec2i autotileC(-1, -1);
const Vec2i atOrig[] =
{
Vec2i(0, 0),
Vec2i(0, 3),
Vec2i(freeArea),
Vec2i(freeArea.x, freeArea.y+3),
Vec2i(6, 0),
autotileC,
Vec2i(6, 3),
autotileC,
Vec2i(0, 6),
autotileC,
Vec2i(0, 9),
autotileC,
Vec2i(6, 6),
autotileC,
Vec2i(6, 9),
autotileC
};
const Vec2i orig = atOrig[autotileID];
if (orig.x == -1)
{
int cID = (autotileID - 5) / 2;
const Vec2i orig = AEPartsDst[cID];
readAutotileC(reader, patternID, orig, x, y);
return;
}
readAutotileA(reader, patternID, orig, x, y);
}
static void
onTileA2(Reader &reader, int16_t tileID,
int x, int y)
{
Vec2i orig = blitsA2[0].dst;
tileID -= 0x0B00;
int patternID = tileID % 0x30;
int autotileID = tileID / 0x30;
orig.x += (autotileID % 8) * 2;
orig.y += (autotileID / 8) * 3;
readAutotileA(reader, patternID, orig, x, y);
}
static void
onTileA3(Reader &reader, int16_t tileID,
int x, int y)
{
Vec2i orig = blitsA3[0].dst;
tileID -= 0x1100;
int patternID = tileID % 0x30;
int autotileID = tileID / 0x30;
orig.x += (autotileID % 8) * 2;
orig.y += (autotileID / 8) * 2;
readAutotileB(reader, patternID, orig, x, y);
}
static void
onTileA4(Reader &reader, int16_t tileID,
int x, int y)
{
Vec2i orig = blitsA4[0].dst;
tileID -= 0x1700;
const int offY[] = { 0, 3, 5, 8, 10, 13 };
int patternID = tileID % 0x30;
int autotileID = tileID / 0x30;
int offYI = autotileID / 8;
orig.x += (autotileID % 8) * 2;
orig.y += offY[offYI];
if ((offYI % 2) == 0)
readAutotileA(reader, patternID, orig, x, y);
else
readAutotileB(reader, patternID, orig, x, y);
}
static void
onTileA5(Reader &reader, int16_t tileID,
int x, int y, bool overPlayer)
{
const Vec2i orig = blitsA5[0].dst;
tileID -= 0x0600;
int ox = tileID % 0x8;
int oy = tileID / 0x8;
FloatRect tex((orig.x+ox)*32+0.5, (orig.y+oy)*32+0.5, 31, 31);
FloatRect pos(x*32, y*32, 32, 32);
reader.onQuads1(tex, pos, overPlayer);
}
static void
onTileBCDE(Reader &reader, int16_t tileID,
int x, int y, bool overPlayer)
{
int ox = tileID % 0x8;
int oy = (tileID / 0x8) % 0x10;
int ob = tileID / (0x8*0x10);
ox += (ob % 2) * 0x8;
oy += (ob / 2) * 0x10;
FloatRect tex((CDEArea.x+ox)*32+0.5, (CDEArea.y+oy)*32+0.5, 31, 31);
FloatRect pos(x*32, y*32, 32, 32);
reader.onQuads1(tex, pos, overPlayer);
}
static void
onTile(Reader &reader, int16_t tileID,
int x, int y, bool overPlayer)
{
/* B ~ E */
if (tileID < 0x0400)
{
onTileBCDE(reader, tileID, x, y, overPlayer);
return;
}
/* A5 */
if (tileID >= 0x0600 && tileID < 0x0680)
{
onTileA5(reader, tileID, x, y, overPlayer);
return;
}
if (tileID >= 0x0800 && tileID < 0x0B00)
{
onTileA1(reader, tileID, x, y);
return;
}
/* A2 */
if (tileID >= 0x0B00 && tileID < 0x1100)
{
onTileA2(reader, tileID, x, y);
return;
}
/* A3 */
if (tileID < 0x1700)
{
onTileA3(reader, tileID, x, y);
return;
}
/* A4 */
if (tileID < 0x2000)
{
onTileA4(reader, tileID, x, y);
return;
}
}
static void
readLayer(Reader &reader, const Table &data,
const Table *flags, int ox, int oy, int w, int h, int z)
{
for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x)
{
int16_t tileID = tableGetWrapped(data, x+ox, y+oy, z);
bool overPlayer = tableGetSafe(flags, tileID) & OVER_PLAYER_FLAG;
if (tileID <= 0)
continue;
onTile(reader, tileID, x, y, overPlayer);
}
}
static void
onShadowTile(Reader &reader, int8_t value,
int x, int y)
{
if (value == 0)
return;
int oy = value;
FloatRect tex((shadowArea.x)*32+0.5, (shadowArea.y+oy)*32+0.5, 31, 31);
FloatRect pos(x*32, y*32, 32, 32);
reader.onQuads1(tex, pos, false);
}
static void
readShadowLayer(Reader &reader, const Table &data,
int ox, int oy, int w, int h)
{
for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x)
{
int16_t value = tableGetWrapped(data, x+ox, y+oy, 3);
onShadowTile(reader, value & 0xF, x, y);
}
}
void readTiles(Reader &reader, const Table &data,
const Table *flags, int ox, int oy, int w, int h)
{
for (int i = 0; i < 2; ++i)
readLayer(reader, data, flags, ox, oy, w, h, i);
readShadowLayer(reader, data, ox, oy, w, h);
readLayer(reader, data, flags, ox, oy, w, h, 2);
}
}

67
src/tileatlasvx.h Normal file
View File

@ -0,0 +1,67 @@
/*
** tileatlasvx.h
**
** This file is part of mkxp.
**
** Copyright (C) 2014 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TILEATLASVX_H
#define TILEATLASVX_H
#include <stdlib.h>
struct FloatRect;
struct TEXFBO;
class Bitmap;
class Table;
#define ATLASVX_W 1024
#define ATLASVX_H 2048
/* Bitmap indices */
enum
{
BM_A1 = 0,
BM_A2 = 1,
BM_A3 = 2,
BM_A4 = 3,
BM_A5 = 4,
BM_B = 5,
BM_C = 6,
BM_D = 7,
BM_E = 8,
BM_COUNT
};
namespace TileAtlasVX
{
struct Reader
{
virtual void onQuads1(const FloatRect &t, const FloatRect &p,
bool overPlayer) = 0;
virtual void onQuads2(const FloatRect t[2], const FloatRect p[2]) = 0;
virtual void onQuads4(const FloatRect t[4], const FloatRect p[4]) = 0;
};
void build(TEXFBO &tf, Bitmap *bitmaps[BM_COUNT]);
void readTiles(Reader &reader, const Table &data,
const Table *flags, int ox, int oy, int w, int h);
}
#endif // TILEATLASVX_H

515
src/tilemapvx.cpp Normal file
View File

@ -0,0 +1,515 @@
/*
** tilemapvx.cpp
**
** This file is part of mkxp.
**
** Copyright (C) 2014 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#include "tilemapvx.h"
#include "tileatlasvx.h"
#include "etc-internal.h"
#include "bitmap.h"
#include "table.h"
#include "viewport.h"
#include "gl-util.h"
#include "sharedstate.h"
#include "glstate.h"
#include "vertex.h"
#include "quad.h"
#include "quadarray.h"
#include "shader.h"
#include <vector>
#include <sigc++/connection.h>
#include <sigc++/bind.h>
/* Map viewport size */
// FIXME: This will be wrong if resolution is changed
static const int viewpW = 18;
static const int viewpH = 14;
/* How many tiles are max visible on screen at once */
static const Vec2i screenTiles(18, 14);
// FIXME: Implement flash
struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
{
TilemapVX::BitmapArray bitmapsProxy;
Bitmap *bitmaps[BM_COUNT];
Table *mapData;
Table *flashData;
Table *flags;
Vec2i offset;
Vec2i dispPos;
/* Map viewport position */
Vec2i viewpPos;
Vec2i sceneOffset;
Scene::Geometry sceneGeo;
std::vector<SVertex> groundVert;
std::vector<SVertex> aboveVert;
TEXFBO atlas;
VBO::ID vbo;
GLMeta::VAO vao;
size_t allocQuads;
size_t groundQuads;
size_t aboveQuads;
uint16_t frameIdx;
uint8_t aniIdxA;
uint8_t aniIdxC;
Vec2 aniOffset;
bool atlasDirty;
bool buffersDirty;
bool mapViewportDirty;
sigc::connection mapDataCon;
sigc::connection flagsCon;
sigc::connection prepareCon;
sigc::connection bmChangedCons[BM_COUNT];
sigc::connection bmDisposedCons[BM_COUNT];
struct AboveLayer : public ViewportElement
{
TilemapVXPrivate *p;
AboveLayer(TilemapVXPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 200),
p(p)
{}
void draw()
{
p->drawAbove();
}
};
AboveLayer above;
TilemapVXPrivate(Viewport *viewport)
: ViewportElement(viewport),
mapData(0),
flashData(0),
flags(0),
allocQuads(0),
groundQuads(0),
aboveQuads(0),
frameIdx(0),
aniIdxA(0),
aniIdxC(0),
atlasDirty(true),
buffersDirty(false),
mapViewportDirty(false),
above(this, viewport)
{
memset(bitmaps, 0, sizeof(bitmaps));
shState->requestAtlasTex(ATLASVX_W, ATLASVX_H, atlas);
vbo = VBO::gen();
GLMeta::vaoFillInVertexData<SVertex>(vao);
vao.vbo = vbo;
vao.ibo = shState->globalIBO().ibo;
GLMeta::vaoInit(vao);
prepareCon = shState->prepareDraw.connect
(sigc::mem_fun(this, &TilemapVXPrivate::prepare));
}
virtual ~TilemapVXPrivate()
{
GLMeta::vaoFini(vao);
VBO::del(vbo);
shState->releaseAtlasTex(atlas);
prepareCon.disconnect();
mapDataCon.disconnect();
flagsCon.disconnect();
for (size_t i = 0; i < BM_COUNT; ++i)
{
bmChangedCons[i].disconnect();
bmDisposedCons[i].disconnect();
}
}
void invalidateAtlas()
{
atlasDirty = true;
}
void onBitmapDisposed(int i)
{
bitmaps[i] = 0;
bmChangedCons[i].disconnect();
bmDisposedCons[i].disconnect();
atlasDirty = true;
}
void invalidateBuffers()
{
buffersDirty = true;
}
void rebuildAtlas()
{
TileAtlasVX::build(atlas, bitmaps);
}
void updatePosition()
{
dispPos.x = -(offset.x - viewpPos.x * 32) + sceneOffset.x;
dispPos.y = -(offset.y - viewpPos.y * 32) + sceneOffset.y;
}
void onGeometryChange(const Scene::Geometry &geo)
{
sceneOffset.x = geo.rect.x - geo.xOrigin;
sceneOffset.y = geo.rect.y - geo.yOrigin;
sceneGeo = geo;
updatePosition();
}
void updateMapViewport()
{
int tileOX, tileOY;
if (offset.x >= 0)
tileOX = offset.x / 32;
else
tileOX = -(-(offset.x-31) / 32);
if (offset.y >= 0)
tileOY = offset.y / 32;
else
tileOY = -(-(offset.y-31) / 32);
bool dirty = false;
if (tileOX < viewpPos.x || tileOX + screenTiles.x > viewpPos.x + viewpW)
{
viewpPos.x = tileOX;
dirty = true;
}
if (tileOY < viewpPos.y || tileOY + screenTiles.y > viewpPos.y + viewpH)
{
viewpPos.y = tileOY;
dirty = true;
}
if (dirty)
{
buffersDirty = true;
}
updatePosition();
}
static size_t quadBytes(size_t quads)
{
return quads * 4 * sizeof(SVertex);
}
void rebuildBuffers()
{
if (!mapData)
return;
groundVert.clear();
aboveVert.clear();
TileAtlasVX::readTiles(*this, *mapData, flags,
viewpPos.x, viewpPos.y, viewpW, viewpH);
groundQuads = groundVert.size() / 4;
aboveQuads = aboveVert.size() / 4;
size_t totalQuads = groundQuads + aboveQuads;
VBO::bind(vbo);
if (totalQuads > allocQuads)
{
VBO::allocEmpty(quadBytes(totalQuads), GL_DYNAMIC_DRAW);
allocQuads = totalQuads;
}
VBO::uploadSubData(0, quadBytes(groundQuads), &groundVert[0]);
VBO::uploadSubData(quadBytes(groundQuads), quadBytes(aboveQuads), &aboveVert[0]);
VBO::unbind();
shState->ensureQuadIBO(totalQuads);
}
void prepare()
{
if (!mapData)
return;
if (atlasDirty)
{
rebuildAtlas();
atlasDirty = false;
}
if (mapViewportDirty)
{
updateMapViewport();
mapViewportDirty = false;
}
if (buffersDirty)
{
rebuildBuffers();
buffersDirty = false;
}
}
SVertex *allocVert(std::vector<SVertex> &vec, size_t count)
{
size_t size = vec.size();
vec.resize(size + count);
return &vec[size];
}
/* SceneElement */
void draw()
{
TilemapVXShader &shader = shState->shaders().tilemapVX;
shader.bind();
shader.setTexSize(Vec2i(atlas.width, atlas.height));
shader.applyViewportProj();
shader.setTranslation(dispPos);
shader.setAniOffset(aniOffset);
TEX::bind(atlas.tex);
GLMeta::vaoBind(vao);
gl.DrawElements(GL_TRIANGLES, groundQuads*6, _GL_INDEX_TYPE, 0);
GLMeta::vaoUnbind(vao);
}
void drawAbove()
{
if (aboveQuads == 0)
return;
SimpleShader &shader = shState->shaders().simple;
shader.bind();
shader.setTexSize(Vec2i(atlas.width, atlas.height));
shader.applyViewportProj();
shader.setTranslation(dispPos);
TEX::bind(atlas.tex);
GLMeta::vaoBind(vao);
gl.DrawElements(GL_TRIANGLES, aboveQuads*6, _GL_INDEX_TYPE,
(GLvoid*) (groundQuads*6*sizeof(index_t)));
GLMeta::vaoUnbind(vao);
}
/* TileAtlasVX::Reader */
void onQuads1(const FloatRect &t1, const FloatRect &p1,
bool overPlayer)
{
SVertex *vert;
if (overPlayer)
vert = allocVert(aboveVert, 4);
else
vert = allocVert(groundVert, 4);
Quad::setTexPosRect(vert, t1, p1);
}
void onQuads2(const FloatRect t[2], const FloatRect p[2])
{
SVertex *vert = allocVert(groundVert, 8);
Quad::setTexPosRect(&vert[0], t[0], p[0]);
Quad::setTexPosRect(&vert[4], t[1], p[1]);
}
void onQuads4(const FloatRect t[4], const FloatRect p[4])
{
SVertex *vert = allocVert(groundVert, 16);
Quad::setTexPosRect(&vert[ 0], t[0], p[0]);
Quad::setTexPosRect(&vert[ 4], t[1], p[1]);
Quad::setTexPosRect(&vert[ 8], t[2], p[2]);
Quad::setTexPosRect(&vert[12], t[3], p[3]);
}
};
void TilemapVX::BitmapArray::set(int i, Bitmap *bitmap)
{
if (i < 0 || i >= BM_COUNT)
return;
if (p->bitmaps[i] == bitmap)
return;
p->bitmaps[i] = bitmap;
p->atlasDirty = true;
p->bmChangedCons[i].disconnect();
p->bmChangedCons[i] = bitmap->modified.connect
(sigc::mem_fun(p, &TilemapVXPrivate::invalidateAtlas));
p->bmDisposedCons[i].disconnect();
p->bmDisposedCons[i] = bitmap->wasDisposed.connect
(sigc::bind(sigc::mem_fun(p, &TilemapVXPrivate::onBitmapDisposed), i));
}
Bitmap *TilemapVX::BitmapArray::get(int i) const
{
if (i < 0 || i >= BM_COUNT)
return 0;
return p->bitmaps[i];
}
TilemapVX::TilemapVX(Viewport *viewport)
{
(void) viewport;
p = new TilemapVXPrivate(viewport);
p->bitmapsProxy.p = p;
}
TilemapVX::~TilemapVX()
{
delete p;
}
void TilemapVX::update()
{
if (++p->frameIdx >= 30*3*4)
p->frameIdx = 0;
const uint8_t aniIndicesA[3*4] =
{ 0, 1, 2, 1, 0, 1, 2, 1, 0, 1, 2, 1 };
const uint8_t aniIndicesC[3*4] =
{ 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2 };
p->aniIdxA = aniIndicesA[p->frameIdx / 30];
p->aniIdxC = aniIndicesC[p->frameIdx / 30];
p->aniOffset = Vec2(p->aniIdxA * 2 * 32, p->aniIdxC * 32);
}
TilemapVX::BitmapArray &TilemapVX::getBitmapArray() const
{
return p->bitmapsProxy;
}
DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
DEF_ATTR_RD_SIMPLE(TilemapVX, FlashData, Table*, p->flashData)
DEF_ATTR_RD_SIMPLE(TilemapVX, Flags, Table*, p->flags)
DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->offset.x)
DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->offset.y)
Viewport *TilemapVX::getViewport() const
{
return p->getViewport();
}
bool TilemapVX::getVisible() const
{
return p->getVisible();
}
void TilemapVX::setViewport(Viewport *value)
{
p->setViewport(value);
p->above.setViewport(value);
}
void TilemapVX::setMapData(Table *value)
{
if (p->mapData == value)
return;
p->mapData = value;
p->buffersDirty = true;
p->mapDataCon.disconnect();
p->mapDataCon = value->modified.connect
(sigc::mem_fun(p, &TilemapVXPrivate::invalidateBuffers));
}
void TilemapVX::setFlashData(Table *value)
{
if (p->flashData == value)
return;
p->flashData = value;
}
void TilemapVX::setFlags(Table *value)
{
if (p->flags == value)
return;
p->flags = value;
p->buffersDirty = true;
p->flagsCon.disconnect();
p->flagsCon = value->modified.connect
(sigc::mem_fun(p, &TilemapVXPrivate::invalidateBuffers));
}
void TilemapVX::setVisible(bool value)
{
p->setVisible(value);
p->above.setVisible(value);
}
void TilemapVX::setOX(int value)
{
if (p->offset.x == value)
return;
p->offset.x = value;
p->mapViewportDirty = true;
}
void TilemapVX::setOY(int value)
{
if (p->offset.y == value)
return;
p->offset.y = value;
p->mapViewportDirty = true;
}

71
src/tilemapvx.h Normal file
View File

@ -0,0 +1,71 @@
/*
** tilemapvx.h
**
** This file is part of mkxp.
**
** Copyright (C) 2014 Jonas Kulla <Nyocurio@gmail.com>
**
** mkxp is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 2 of the License, or
** (at your option) any later version.
**
** mkxp is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with mkxp. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef TILEMAPVX_H
#define TILEMAPVX_H
#include "disposable.h"
#include "util.h"
class Viewport;
class Bitmap;
class Table;
struct TilemapVXPrivate;
class TilemapVX : public Disposable
{
public:
class BitmapArray
{
public:
void set(int i, Bitmap *bitmap);
Bitmap *get(int i) const;
private:
BitmapArray() {}
~BitmapArray() {}
TilemapVXPrivate *p;
friend class TilemapVX;
friend struct TilemapVXPrivate;
};
TilemapVX(Viewport *viewport = 0);
~TilemapVX();
void update();
BitmapArray &getBitmapArray() const;
DECL_ATTR( Viewport, Viewport* )
DECL_ATTR( MapData, Table* )
DECL_ATTR( FlashData, Table* )
DECL_ATTR( Flags, Table* )
DECL_ATTR( Visible, bool )
DECL_ATTR( OX, int )
DECL_ATTR( OY, int )
private:
TilemapVXPrivate *p;
};
#endif // TILEMAPVX_H