From 1da28ec40ac83032bbf25980835734d24f718703 Mon Sep 17 00:00:00 2001 From: fgenesis Date: Fri, 14 Jul 2023 05:21:16 +0200 Subject: [PATCH] fix tile repeat, works now --- Aquaria/SceneEditor.cpp | 11 +++-- Aquaria/TileMgr.cpp | 13 +++--- BBGE/Tile.cpp | 95 ++++++++++++++++++++++++++++++++++++++--- BBGE/Tile.h | 23 +++++++++- BBGE/TileRender.cpp | 19 +++++++-- 5 files changed, 142 insertions(+), 19 deletions(-) diff --git a/Aquaria/SceneEditor.cpp b/Aquaria/SceneEditor.cpp index 527b936..6abcdf0 100644 --- a/Aquaria/SceneEditor.cpp +++ b/Aquaria/SceneEditor.cpp @@ -277,8 +277,11 @@ public: q->setTexturePointer(t.et->tex); q->fhTo(!!(t.flags & TILEFLAG_FH)); q->rotation.z = t.rotation; - q->repeatToFillScale = Vector(t.texscaleX, t.texscaleY); - q->repeatTextureToFill(!!(t.flags & TILEFLAG_REPEAT)); + if(t.flags & TILEFLAG_REPEAT && t.rep) + { + q->repeatToFillScale = Vector(t.rep->texscaleX, t.rep->texscaleY); + q->repeatTextureToFill(true); + } th->addChild(q, PM_POINTER, RBP_ON); th->_quads.push_back(q); } @@ -1046,7 +1049,9 @@ void SceneEditor::enterAnyStateHelper(EditorStates newstate) if(selectedTiles.size() == 1) { const TileData& t = getCurrentLayerTiles().tiles[selectedTiles[0]]; - oldRepeatScale = Vector(t.texscaleX, t.texscaleY); + oldRepeatScale = Vector(1,1); + if(t.flags & TILEFLAG_REPEAT) + oldRepeatScale = Vector(t.rep->texscaleX, t.rep->texscaleY); oldScale = Vector(t.scalex, t.scaley); oldRotation = t.rotation; } diff --git a/Aquaria/TileMgr.cpp b/Aquaria/TileMgr.cpp index 2206138..c94c609 100644 --- a/Aquaria/TileMgr.cpp +++ b/Aquaria/TileMgr.cpp @@ -123,13 +123,11 @@ void TileMgr::createTiles(const TileDef* defs, size_t n) if(d.fh) t->flags |= TILEFLAG_FH; if(d.repeat) - t->flags |= TILEFLAG_REPEAT; + t->setRepeatOn(d.rsx, d.rsy); // FIXME: handle fv t->rotation = d.rot; - t->texscaleX = d.rsx; - t->texscaleY = d.rsy; t->tag = d.tag; t->scalex = d.sx; t->scaley = d.sy; @@ -183,8 +181,6 @@ TileData* TileMgr::_createTile(unsigned tilesetID, unsigned layer, float x, flo t.x = x; t.y = y; t.rotation = 0; - t.texscaleX = 1; - t.texscaleY = 1; t.scalex = 1; t.scaley = 1; //t.beforeScaleOffsetX = 0; @@ -273,6 +269,11 @@ TileDef::TileDef(unsigned lr, const TileData& t) , repeat(!!(t.flags & TILEFLAG_REPEAT)) , tag(t.tag) , sx(t.scalex), sy(t.scaley) - , rsx(t.texscaleX), rsy(t.texscaleY) + , rsx(1), rsy(1) { + if(t.flags & TILEFLAG_REPEAT) + { + rsx = t.rep->texscaleX; + rsy = t.rep->texscaleY; + } } diff --git a/BBGE/Tile.cpp b/BBGE/Tile.cpp index 7b0db47..24ad28f 100644 --- a/BBGE/Tile.cpp +++ b/BBGE/Tile.cpp @@ -3,6 +3,7 @@ #include "Tileset.h" #include "Base.h" #include +#include "Texture.h" TileStorage::TileStorage() { @@ -133,7 +134,7 @@ size_t TileStorage::moveToOther(TileStorage& other, const size_t *indices, size_ return firstNewIdx; } -static void dropAttachments(TileData& t) +static void dropEffect(TileData& t) { if(t.flags & TILEFLAG_OWN_EFFDATA) { @@ -143,6 +144,23 @@ static void dropAttachments(TileData& t) t.eff = NULL; } +static void dropRepeat(TileData& t) +{ + if(t.flags & TILEFLAG_OWN_REPEAT) + { + delete t.rep; + t.flags &= ~TILEFLAG_OWN_REPEAT; + } + t.rep = NULL; +} + +static void dropAll(TileData& t) +{ + dropEffect(t); + dropRepeat(t); +} + + void TileStorage::deleteSome(const size_t* indices, size_t n) { std::vector tmp; @@ -154,7 +172,7 @@ void TileStorage::deleteSome(const size_t* indices, size_t n) for(size_t k = 0; k < n; ++i) // not particularly efficient, could be much better by sorting first but eh if(indices[k] == i) { - dropAttachments(tmp[i]); + dropAll(tmp[i]); goto skip; } @@ -170,7 +188,7 @@ void TileStorage::destroyAll() { const size_t n = tiles.size(); for(size_t i = 0; i < n; ++i) - dropAttachments(tiles[i]); + dropAll(tiles[i]); tiles.clear(); indicesToCollide.clear(); indicesToUpdate.clear(); @@ -221,6 +239,10 @@ size_t TileStorage::cloneSome(const TileEffectStorage& effstore, const size_t* i t.flags &= TILEFLAG_OWN_EFFDATA; effstore.assignEffect(t, efx); // recreate effect properly } + if((t.flags & TILEFLAG_OWN_REPEAT) && t.rep) + { + t.rep = new TileRepeatData(*t.rep); + } } refreshAll(); @@ -236,7 +258,8 @@ void TileStorage::refreshAll() const size_t n = tiles.size(); for(size_t i = 0; i < n; ++i) { - const TileData& t = tiles[i]; + TileData& t = tiles[i]; + t.refreshRepeat(); if(!(t.flags & TILEFLAG_HIDDEN)) { if(const TileEffectData *e = t.eff) @@ -434,7 +457,7 @@ TileEffectStorage::~TileEffectStorage() void TileEffectStorage::assignEffect(TileData& t, int index) const { - dropAttachments(t); + dropEffect(t); if(index < 0) return; @@ -507,3 +530,65 @@ bool TileData::isCoordinateInside(float cx, float cy, float minsize) const return cx >= x - hw && cx <= x + hw && cy >= y - hh && cy <= y + hh; } + +void TileRepeatData::refresh(const ElementTemplate& et, float scalex, float scaley) +{ + float tw, th; + if(et.tex) + { + tw = et.tex->width; + th = et.tex->height; + } + else + { + tw = et.w; + th = et.h; + } + + const float tu1 = texOffX; + const float tv1 = texOffY; + const float tu2 = (et.w*scalex*texscaleX)/tw + texOffX; + const float tv2 = (et.h*scaley*texscaleY)/th + texOffY; + + this->tu1 = tu1; + this->tv1 = tv1; + this->tu2 = tu2; + this->tv2 = tv2; + + texcoords[0] = tu1; + texcoords[1] = 1.0f-tv1; + texcoords[2] = tu2; + texcoords[3] = 1.0f-tv1; + texcoords[4] = tu2; + texcoords[5] = 1.0f-tv2; + texcoords[6] = tu1; + texcoords[7] = 1.0f-tv2; +} + +TileRepeatData* TileData::setRepeatOn(float texscalex, float texscaley, float offx, float offy) +{ + if(rep && !(flags & TILEFLAG_OWN_REPEAT)) + rep = NULL; + flags |= (TILEFLAG_OWN_REPEAT | TILEFLAG_REPEAT); + if(!rep) + rep = new TileRepeatData; + rep->texscaleX = texscalex; + rep->texscaleY = texscaley; + rep->texOffX = offx; + rep->texOffY = offy; + rep->refresh(*et, scalex, scaley); + return rep; +} + +void TileData::setRepeatOff() +{ + flags &= ~TILEFLAG_REPEAT; +} + +void TileData::refreshRepeat() +{ + if((flags & TILEFLAG_OWN_REPEAT) && rep) + { + rep->refresh(*et, scalex, scaley); + } +} diff --git a/BBGE/Tile.h b/BBGE/Tile.h index d3997af..fc9ee56 100644 --- a/BBGE/Tile.h +++ b/BBGE/Tile.h @@ -94,7 +94,8 @@ enum TileFlags TILEFLAG_OWN_EFFDATA = 0x40, // tile owns its TileEffectData, can update, must delete TILEFLAG_HIDDEN = 0x80, // don't render tile TILEFLAG_SELECTED = 0x100, // ephemeral: selected in editor - TILEFLAG_EDITOR_HIDDEN = 0x200 // tile is hidden for editor reasons. temporarily set when multi-selecting and moving. doesn't count as hidden externally and is only for rendering. + TILEFLAG_EDITOR_HIDDEN = 0x200, // tile is hidden for editor reasons. temporarily set when multi-selecting and moving. doesn't count as hidden externally and is only for rendering. + TILEFLAG_OWN_REPEAT = 0x400 // owns TileRepeatData, may update, must delete }; struct TileData; @@ -128,23 +129,41 @@ private: TileEffectData(const TileEffectData&); // no-copy }; +struct TileRepeatData +{ + // written via refresh() + float texcoords[8]; + float tu1, tv1, tu2, tv2; + + // set by user + float texscaleX, texscaleY; + float texOffX, texOffY; + + // pass ET & scale of owning tile + void refresh(const ElementTemplate& et, float scalex, float scaley); +}; + // POD and as compact as possible. Intended for rendering as quickly as possible. // the idea is that these are linearly adjacent in memory in the order they are rendered, // to maximize cache & prefetch efficiency struct TileData { - float x, y, scalex, scaley, texscaleX, texscaleY; + float x, y, scalex, scaley; //float beforeScaleOffsetX, beforeScaleOffsetY; // almost always 0. // TODO: this is nasty, ideally get rid of this float rotation; unsigned flags; // TileFlags unsigned tag; // FIXME: make this int const ElementTemplate *et; // never NULL. texture, texcoords, etc is here. // TODO: maybe replace with unsigned tilesetID? but that's an extra indirection or two during rendering... TileEffectData *eff; // mostly NULL + TileRepeatData *rep; // helpers for external access inline void setVisible(bool on) { if(on) flags &= ~TILEFLAG_HIDDEN; else flags |= TILEFLAG_HIDDEN; } inline bool isVisible() const { return !(flags & TILEFLAG_HIDDEN); } bool isCoordinateInside(float cx, float cy, float minsize = 0) const; + TileRepeatData *setRepeatOn(float texscalex = 1, float texscaley = 1, float offx = 0, float offy = 0); + void setRepeatOff(); + void refreshRepeat(); }; class TileEffectStorage diff --git a/BBGE/TileRender.cpp b/BBGE/TileRender.cpp index 63f5859..146b783 100644 --- a/BBGE/TileRender.cpp +++ b/BBGE/TileRender.cpp @@ -155,7 +155,9 @@ void TileRender::onRender(const RenderState& rs) const if(!grid) { - const float *tcbuf = tile.et->texcoordQuadPtr; + const float *tcbuf = (tile.flags & TILEFLAG_REPEAT) + ? &tile.rep->texcoords[0] + : tile.et->texcoordQuadPtr; assert(tcbuf); if(lastTexcoordBuf != tcbuf) { @@ -167,8 +169,19 @@ void TileRender::onRender(const RenderState& rs) const else { rx.alpha = alpha; - const Vector upperLeftTextureCoordinates(et->tu1, et->tv1); - const Vector lowerRightTextureCoordinates(et->tu2, et->tv2); + + Vector upperLeftTextureCoordinates, lowerRightTextureCoordinates; + if(tile.flags & TILEFLAG_REPEAT) + { + upperLeftTextureCoordinates = Vector(tile.rep->tu1, tile.rep->tv1); + lowerRightTextureCoordinates = Vector(tile.rep->tu2, tile.rep->tv2); + } + else + { + upperLeftTextureCoordinates = Vector(et->tu1, et->tv1); + lowerRightTextureCoordinates = Vector(et->tu2, et->tv2); + } + grid->render(rx, upperLeftTextureCoordinates, lowerRightTextureCoordinates); }