Replicate RMVX/VXA's broken sprite Z sorting implementation

Fixes Window_NameBox visual appearance in Skyborn.

Also nuke the second SceneElement constructor that has been
obsolete since the Tilemap mapViewport rewrite.
This commit is contained in:
Jonas Kulla 2014-08-31 00:51:23 +02:00
parent 1a98760b31
commit d8bb6aa2fc
7 changed files with 25 additions and 44 deletions

View File

@ -105,26 +105,13 @@ void Scene::composite()
} }
SceneElement::SceneElement(Scene &scene, int z, bool isSprite) SceneElement::SceneElement(Scene &scene, int z, int spriteY)
: link(this), : link(this),
creationStamp(shState->genTimeStamp()), creationStamp(shState->genTimeStamp()),
z(z), z(z),
visible(true), visible(true),
scene(&scene), scene(&scene),
spriteY(0), spriteY(spriteY)
isSprite(isSprite)
{
scene.insert(*this);
}
SceneElement::SceneElement(Scene &scene, int z, unsigned int cStamp)
: link(this),
creationStamp(cStamp),
z(z),
visible(true),
scene(&scene),
spriteY(0),
isSprite(false)
{ {
scene.insert(*this); scene.insert(*this);
} }
@ -184,11 +171,11 @@ bool SceneElement::operator<(const SceneElement &o) const
/* RGSS2: If two sprites' Z values collide, /* RGSS2: If two sprites' Z values collide,
* their Y coordinates decide draw order. Only * their Y coordinates decide draw order. Only
* on equal Y does the creation time take effect */ * on equal Y does the creation time take effect */
if (isSprite && o.isSprite && spriteY != o.spriteY) if (spriteY != o.spriteY)
return (spriteY < o.spriteY); return (spriteY < o.spriteY);
} }
return (creationStamp <= o.creationStamp); return (creationStamp < o.creationStamp);
} }
return true; return true;

View File

@ -71,8 +71,7 @@ protected:
class SceneElement class SceneElement
{ {
public: public:
SceneElement(Scene &scene, int z = 0, bool isSprite = false); SceneElement(Scene &scene, int z = 0, int spriteY = 0);
SceneElement(Scene &scene, int z, unsigned int cStamp);
virtual ~SceneElement(); virtual ~SceneElement();
void setScene(Scene &scene); void setScene(Scene &scene);
@ -122,8 +121,17 @@ protected:
friend struct TilemapPrivate; friend struct TilemapPrivate;
private: private:
/* RGSS2 introduced an enhanced type of Z ordering: sprites with
* the same Z are first ordered by their Y value (higher Y = closer
* to player) and then by creation time. However, the Enterbrain devs
* botched their implementation, and now every other scene element
* subclass is sorted as if it was a sprite with a fixed Y of 0.
* In RGSS3, they tried to fix this for the Window class, badly. It
* now behaves as if it was a sprite with fixed Y of infinity. This
* means that sprites created _after_ a window with the same Z will
* still always be displayed below said window. */
int spriteY; int spriteY;
const bool isSprite;
}; };
#endif // SCENE_H #endif // SCENE_H

View File

@ -290,7 +290,7 @@ struct SpritePrivate
}; };
Sprite::Sprite(Viewport *viewport) Sprite::Sprite(Viewport *viewport)
: ViewportElement(viewport, 0, true) : ViewportElement(viewport)
{ {
p = new SpritePrivate; p = new SpritePrivate;
onGeometryChange(scene->getGeometry()); onGeometryChange(scene->getGeometry());

View File

@ -313,14 +313,6 @@ struct TilemapPrivate
size_t activeLayers; size_t activeLayers;
Scene::Geometry sceneGeo; Scene::Geometry sceneGeo;
Vec2i sceneOffset; Vec2i sceneOffset;
/* The ground and zlayer elements' creationStamp
* should be aquired once (at Tilemap construction)
* instead of regenerated everytime the elements are
* (re)created. ZLayers can share one stamp because
* their z always differs anway */
unsigned int groundStamp;
unsigned int zlayerStamp;
} elem; } elem;
/* Affected by: autotiles, tileset */ /* Affected by: autotiles, tileset */
@ -398,9 +390,6 @@ struct TilemapPrivate
flash.quadCount = 0; flash.quadCount = 0;
flash.alphaIdx = 0; flash.alphaIdx = 0;
elem.groundStamp = shState->genTimeStamp();
elem.zlayerStamp = shState->genTimeStamp();
elem.ground = new GroundLayer(this, viewport); elem.ground = new GroundLayer(this, viewport);
for (size_t i = 0; i < zlayersMax; ++i) for (size_t i = 0; i < zlayersMax; ++i)
@ -1077,7 +1066,7 @@ struct TilemapPrivate
}; };
GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport) GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 0, p->elem.groundStamp), : ViewportElement(viewport, 0),
vboCount(0), vboCount(0),
p(p) p(p)
{ {
@ -1139,7 +1128,7 @@ void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
} }
ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport) ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 0, p->elem.zlayerStamp), : ViewportElement(viewport, 0),
index(0), index(0),
vboOffset(0), vboOffset(0),
vboCount(0), vboCount(0),

View File

@ -214,15 +214,11 @@ void Viewport::onGeometryChange(const Geometry &geo)
} }
ViewportElement::ViewportElement(Viewport *viewport, int z, bool isSprite) ViewportElement::ViewportElement(Viewport *viewport, int z, int spriteY)
: SceneElement(viewport ? *viewport : *shState->screen(), z, isSprite), : SceneElement(viewport ? *viewport : *shState->screen(), z, spriteY),
m_viewport(viewport) m_viewport(viewport)
{} {}
ViewportElement::ViewportElement(Viewport *viewport, int z, unsigned int cStamp)
: SceneElement(viewport ? *viewport : *shState->screen(), z, cStamp)
{}
Viewport *ViewportElement::getViewport() const Viewport *ViewportElement::getViewport() const
{ {
return m_viewport; return m_viewport;

View File

@ -61,8 +61,7 @@ private:
class ViewportElement : public SceneElement class ViewportElement : public SceneElement
{ {
public: public:
ViewportElement(Viewport *viewport = 0, int z = 0, bool isSprite = false); ViewportElement(Viewport *viewport = 0, int z = 0, int spriteY = 0);
ViewportElement(Viewport *viewport, int z, unsigned int cStamp);
DECL_ATTR( Viewport, Viewport* ) DECL_ATTR( Viewport, Viewport* )

View File

@ -32,12 +32,14 @@
#include "glstate.h" #include "glstate.h"
#include "shader.h" #include "shader.h"
#include <limits>
#include <algorithm> #include <algorithm>
#include <sigc++/connection.h> #include <sigc++/connection.h>
#define DEF_Z (rgssVer >= 3 ? 100 : 0) #define DEF_Z (rgssVer >= 3 ? 100 : 0)
#define DEF_PADDING (rgssVer >= 3 ? 12 : 16) #define DEF_PADDING (rgssVer >= 3 ? 12 : 16)
#define DEF_BACK_OPAC (rgssVer >= 3 ? 192 : 255) #define DEF_BACK_OPAC (rgssVer >= 3 ? 192 : 255)
#define DEF_SPRITE_Y (rgssVer >= 3 ? std::numeric_limits<int>::max() : 0) /* See scene.h */
template<typename T> template<typename T>
struct Sides struct Sides
@ -811,14 +813,14 @@ struct WindowVXPrivate
}; };
WindowVX::WindowVX(Viewport *viewport) WindowVX::WindowVX(Viewport *viewport)
: ViewportElement(viewport, DEF_Z) : ViewportElement(viewport, DEF_Z, DEF_SPRITE_Y)
{ {
p = new WindowVXPrivate(0, 0, 0, 0); p = new WindowVXPrivate(0, 0, 0, 0);
onGeometryChange(scene->getGeometry()); onGeometryChange(scene->getGeometry());
} }
WindowVX::WindowVX(int x, int y, int width, int height) WindowVX::WindowVX(int x, int y, int width, int height)
: ViewportElement(0, DEF_Z) : ViewportElement(0, DEF_Z, DEF_SPRITE_Y)
{ {
p = new WindowVXPrivate(x, y, width, height); p = new WindowVXPrivate(x, y, width, height);
onGeometryChange(scene->getGeometry()); onGeometryChange(scene->getGeometry());