Fix Tilemap's scanrow z sorting for good

Also make it a tad faster.
This commit is contained in:
Jonas Kulla 2013-09-27 04:42:22 +02:00
parent 97d0794c7c
commit 12c92d6dd0
5 changed files with 47 additions and 17 deletions

View File

@ -88,6 +88,16 @@ SceneElement::SceneElement(Scene &scene, int z)
scene.insert(*this); scene.insert(*this);
} }
SceneElement::SceneElement(Scene &scene, int z, unsigned int cStamp)
: link(this),
creationStamp(cStamp),
z(z),
visible(true),
scene(&scene)
{
scene.insert(*this);
}
SceneElement::~SceneElement() SceneElement::~SceneElement()
{ {
unlink(); unlink();

View File

@ -30,6 +30,7 @@
class SceneElement; class SceneElement;
class Viewport; class Viewport;
class Window; class Window;
class ScanRow;
class Scene class Scene
{ {
@ -60,12 +61,14 @@ protected:
friend class SceneElement; friend class SceneElement;
friend class Window; friend class Window;
friend class ScanRow;
}; };
class SceneElement class SceneElement
{ {
public: public:
SceneElement(Scene &scene, int z = 0); SceneElement(Scene &scene, int z = 0);
SceneElement(Scene &scene, int z, unsigned int cStamp);
virtual ~SceneElement(); virtual ~SceneElement();
void setScene(Scene &scene); void setScene(Scene &scene);

View File

@ -217,7 +217,8 @@ struct ScanRow : public ViewportElement
void draw(); void draw();
void drawInt(); void drawInt();
void updateZ(); void initUpdateZ();
void finiUpdateZ();
}; };
struct TilemapPrivate struct TilemapPrivate
@ -236,9 +237,6 @@ struct TilemapPrivate
Vec2i dispPos; Vec2i dispPos;
/* For updating scanrow z */
int tileYOffset;
/* Tile atlas */ /* Tile atlas */
struct { struct {
TEXFBO gl; TEXFBO gl;
@ -299,6 +297,14 @@ struct TilemapPrivate
QVector<ScanRow*> scanrows; QVector<ScanRow*> scanrows;
Scene::Geometry sceneGeo; Scene::Geometry sceneGeo;
Vec2i sceneOffset; Vec2i sceneOffset;
/* The ground and scanrow elements' creationStamp
* should be aquired once (at Tilemap construction)
* instead of regenerated everytime the elements are
* (re)created. Scanrows can share one stamp because
* their z always differs anway */
unsigned int groundStamp;
unsigned int scanrowStamp;
} elem; } elem;
/* Replica bitmask */ /* Replica bitmask */
@ -338,7 +344,6 @@ struct TilemapPrivate
flashData(0), flashData(0),
priorities(0), priorities(0),
visible(true), visible(true),
tileYOffset(0),
mapWidth(0), mapWidth(0),
mapHeight(0), mapHeight(0),
replicas(Normal), replicas(Normal),
@ -398,6 +403,9 @@ struct TilemapPrivate
elem.ground = 0; elem.ground = 0;
elem.groundStamp = gState->genTimeStamp();
elem.scanrowStamp = gState->genTimeStamp();
prepareCon = gState->prepareDraw.connect prepareCon = gState->prepareDraw.connect
(sigc::mem_fun(this, &TilemapPrivate::prepare)); (sigc::mem_fun(this, &TilemapPrivate::prepare));
} }
@ -974,7 +982,10 @@ struct TilemapPrivate
void updateZOrder() void updateZOrder()
{ {
for (int i = 0; i < elem.scanrows.count(); ++i) for (int i = 0; i < elem.scanrows.count(); ++i)
elem.scanrows[i]->updateZ(); elem.scanrows[i]->initUpdateZ();
for (int i = 0; i < elem.scanrows.count(); ++i)
elem.scanrows[i]->finiUpdateZ();
} }
void prepare() void prepare()
@ -1024,7 +1035,7 @@ struct TilemapPrivate
}; };
GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport) GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport), : ViewportElement(viewport, 0, p->elem.groundStamp),
p(p) p(p)
{ {
vboCount = p->scanrowBases[0] * 6; vboCount = p->scanrowBases[0] * 6;
@ -1105,7 +1116,7 @@ void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
} }
ScanRow::ScanRow(TilemapPrivate *p, Viewport *viewport, int index) ScanRow::ScanRow(TilemapPrivate *p, Viewport *viewport, int index)
: ViewportElement(viewport, 32 + index*32), : ViewportElement(viewport, 32 + index*32, p->elem.scanrowStamp),
index(index), index(index),
p(p) p(p)
{ {
@ -1146,10 +1157,16 @@ void ScanRow::drawInt()
GL_UNSIGNED_INT, (GLvoid*) (vboOffset + p->tiles.frameIdx * p->tiles.bufferFrameSize)); GL_UNSIGNED_INT, (GLvoid*) (vboOffset + p->tiles.frameIdx * p->tiles.bufferFrameSize));
} }
void ScanRow::updateZ() void ScanRow::initUpdateZ()
{ {
int y = (p->offset.y > 0) ? -p->offset.y : 0; unlink();
setZ(32 + (((y) / 32) + index) * 32); }
void ScanRow::finiUpdateZ()
{
z = 32 * (index+1) - p->offset.y;
scene->insert(*this);
} }
void Tilemap::Autotiles::set(int i, Bitmap *bitmap) void Tilemap::Autotiles::set(int i, Bitmap *bitmap)
@ -1362,13 +1379,8 @@ void Tilemap::setOY(int value)
p->updatePosition(); p->updatePosition();
p->updateReplicas(); p->updateReplicas();
int tileYOffset = value / 32;
if (tileYOffset != p->tileYOffset)
{
p->tileYOffset = tileYOffset;
p->zOrderDirty = true; p->zOrderDirty = true;
} }
}
void Tilemap::releaseResources() void Tilemap::releaseResources()

View File

@ -231,6 +231,10 @@ ViewportElement::ViewportElement(Viewport *viewport, int z)
m_viewport(viewport) m_viewport(viewport)
{} {}
ViewportElement::ViewportElement(Viewport *viewport, int z, unsigned int cStamp)
: SceneElement(viewport ? *viewport : *gState->screen(), z, cStamp)
{}
Viewport *ViewportElement::getViewport() const Viewport *ViewportElement::getViewport() const
{ {
return m_viewport; return m_viewport;

View File

@ -65,6 +65,7 @@ class ViewportElement : public SceneElement
{ {
public: public:
ViewportElement(Viewport *viewport = 0, int z = 0); ViewportElement(Viewport *viewport = 0, int z = 0);
ViewportElement(Viewport *viewport, int z, unsigned int cStamp);
Viewport *getViewport() const; Viewport *getViewport() const;