TilemapVX: Clean up the horrible map viewport calculation code

Also rename "offset" to "origin" which makes a lot more sense
for ox/oy attributes.
This commit is contained in:
Jonas Kulla 2015-07-16 19:05:15 +02:00
parent 5aaeb0206c
commit dd7545fcf2
3 changed files with 36 additions and 47 deletions

View File

@ -136,6 +136,11 @@ struct Vec2i
return Vec2i(x % value, y % value); return Vec2i(x % value, y % value);
} }
Vec2i operator&(unsigned value) const
{
return Vec2i(x & value, y & value);
}
Vec2i operator-() const Vec2i operator-() const
{ {
return Vec2i(-x, -y); return Vec2i(-x, -y);

View File

@ -46,6 +46,13 @@ wrap(int value, int range)
return res < 0 ? res + range : res; return res < 0 ? res + range : res;
} }
static inline Vec2i
wrap(const Vec2i &value, int range)
{
return Vec2i(wrap(value.x, range),
wrap(value.y, range));
}
static inline int16_t static inline int16_t
tableGetWrapped(const Table &t, int x, int y, int z = 0) tableGetWrapped(const Table &t, int x, int y, int z = 0)
{ {

View File

@ -57,12 +57,12 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
Table *mapData; Table *mapData;
Table *flags; Table *flags;
Vec2i offset; Vec2i origin;
Vec2i dispPos; /* Subregion of the map that is drawn to screen (map viewport) */
/* Map viewport position */
IntRect mapViewp; IntRect mapViewp;
Vec2i sceneOffset; /* Position on screen the map subregion is drawn at */
Vec2i dispPos;
Scene::Geometry sceneGeo; Scene::Geometry sceneGeo;
std::vector<SVertex> groundVert; std::vector<SVertex> groundVert;
@ -179,48 +179,29 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
TileAtlasVX::build(atlas, bitmaps); TileAtlasVX::build(atlas, bitmaps);
} }
void updatePosition()
{
dispPos = -(offset - mapViewp.pos() * 32) + sceneOffset;
}
void updateMapViewport() void updateMapViewport()
{ {
int tileOX, tileOY; IntRect newMvp;
Vec2i offs = offset + sceneGeo.orig; const Vec2i combOrigin = origin + sceneGeo.orig;
const Vec2i geoSize = sceneGeo.rect.size();
if (offs.x >= 0) /* Round the combined origin (which is in pixels) down to the nearest
tileOX = offs.x / 32; * top left tile boundary, by masking off the lower 5 bits (2^5 = 32) */
else newMvp.setPos((combOrigin & ~(32-1)) / 32);
tileOX = -(-(offs.x-31) / 32);
if (offs.y >= 0) /* Ensure that the size is big enough to cover the whole viewport,
tileOY = offs.y / 32; * and add one tile row/column as a buffer for scrolling */
else newMvp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1));
tileOY = -(-(offs.y-31) / 32);
bool dirty = false; if (newMvp != mapViewp)
if (tileOX < mapViewp.x || tileOX > mapViewp.x)
{
mapViewp.x = tileOX;
dirty = true;
}
if (tileOY < mapViewp.y || tileOY > mapViewp.y)
{
mapViewp.y = tileOY;
dirty = true;
}
if (dirty)
{ {
mapViewp = newMvp;
flashMap.setViewport(newMvp);
buffersDirty = true; buffersDirty = true;
} }
updatePosition(); dispPos = sceneGeo.rect.pos() - wrap(combOrigin, 32);
flashMap.setViewport(mapViewp);
} }
static size_t quadBytes(size_t quads) static size_t quadBytes(size_t quads)
@ -365,10 +346,6 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
void onGeometryChange(const Scene::Geometry &geo) void onGeometryChange(const Scene::Geometry &geo)
{ {
const Vec2i geoSize = geo.rect.size();
mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1));
sceneOffset = geo.offset();
sceneGeo = geo; sceneGeo = geo;
buffersDirty = true; buffersDirty = true;
@ -379,7 +356,7 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader
/* TileAtlasVX::Reader */ /* TileAtlasVX::Reader */
void onQuads(const FloatRect *t, const FloatRect *p, void onQuads(const FloatRect *t, const FloatRect *p,
size_t n, bool overPlayer) size_t n, bool overPlayer)
{ {
SVertex *vert = allocVert(overPlayer ? aboveVert : groundVert, n*4); SVertex *vert = allocVert(overPlayer ? aboveVert : groundVert, n*4);
@ -466,8 +443,8 @@ TilemapVX::BitmapArray &TilemapVX::getBitmapArray()
DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData) DEF_ATTR_RD_SIMPLE(TilemapVX, MapData, Table*, p->mapData)
DEF_ATTR_RD_SIMPLE(TilemapVX, FlashData, Table*, p->flashMap.getData()) DEF_ATTR_RD_SIMPLE(TilemapVX, FlashData, Table*, p->flashMap.getData())
DEF_ATTR_RD_SIMPLE(TilemapVX, Flags, Table*, p->flags) DEF_ATTR_RD_SIMPLE(TilemapVX, Flags, Table*, p->flags)
DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->offset.x) DEF_ATTR_RD_SIMPLE(TilemapVX, OX, int, p->origin.x)
DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->offset.y) DEF_ATTR_RD_SIMPLE(TilemapVX, OY, int, p->origin.y)
Viewport *TilemapVX::getViewport() const Viewport *TilemapVX::getViewport() const
{ {
@ -540,10 +517,10 @@ void TilemapVX::setOX(int value)
{ {
guardDisposed(); guardDisposed();
if (p->offset.x == value) if (p->origin.x == value)
return; return;
p->offset.x = value; p->origin.x = value;
p->mapViewportDirty = true; p->mapViewportDirty = true;
} }
@ -551,10 +528,10 @@ void TilemapVX::setOY(int value)
{ {
guardDisposed(); guardDisposed();
if (p->offset.y == value) if (p->origin.y == value)
return; return;
p->offset.y = value; p->origin.y = value;
p->mapViewportDirty = true; p->mapViewportDirty = true;
} }