1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2024-11-29 03:33:48 +00:00

fix tile repeat, works now

This commit is contained in:
fgenesis 2023-07-14 05:21:16 +02:00
parent 9b1c3bba18
commit 1da28ec40a
5 changed files with 142 additions and 19 deletions

View file

@ -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;
}

View file

@ -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;
}
}

View file

@ -3,6 +3,7 @@
#include "Tileset.h"
#include "Base.h"
#include <algorithm>
#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<TileData> 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);
}
}

View file

@ -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

View file

@ -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);
}