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),
creationStamp(shState->genTimeStamp()),
z(z),
visible(true),
scene(&scene),
spriteY(0),
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)
spriteY(spriteY)
{
scene.insert(*this);
}
@ -184,11 +171,11 @@ bool SceneElement::operator<(const SceneElement &o) const
/* RGSS2: If two sprites' Z values collide,
* their Y coordinates decide draw order. Only
* 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 (creationStamp <= o.creationStamp);
return (creationStamp < o.creationStamp);
}
return true;

View File

@ -71,8 +71,7 @@ protected:
class SceneElement
{
public:
SceneElement(Scene &scene, int z = 0, bool isSprite = false);
SceneElement(Scene &scene, int z, unsigned int cStamp);
SceneElement(Scene &scene, int z = 0, int spriteY = 0);
virtual ~SceneElement();
void setScene(Scene &scene);
@ -122,8 +121,17 @@ protected:
friend struct TilemapPrivate;
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;
const bool isSprite;
};
#endif // SCENE_H

View File

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

View File

@ -313,14 +313,6 @@ struct TilemapPrivate
size_t activeLayers;
Scene::Geometry sceneGeo;
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;
/* Affected by: autotiles, tileset */
@ -398,9 +390,6 @@ struct TilemapPrivate
flash.quadCount = 0;
flash.alphaIdx = 0;
elem.groundStamp = shState->genTimeStamp();
elem.zlayerStamp = shState->genTimeStamp();
elem.ground = new GroundLayer(this, viewport);
for (size_t i = 0; i < zlayersMax; ++i)
@ -1077,7 +1066,7 @@ struct TilemapPrivate
};
GroundLayer::GroundLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 0, p->elem.groundStamp),
: ViewportElement(viewport, 0),
vboCount(0),
p(p)
{
@ -1139,7 +1128,7 @@ void GroundLayer::onGeometryChange(const Scene::Geometry &geo)
}
ZLayer::ZLayer(TilemapPrivate *p, Viewport *viewport)
: ViewportElement(viewport, 0, p->elem.zlayerStamp),
: ViewportElement(viewport, 0),
index(0),
vboOffset(0),
vboCount(0),

View File

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

View File

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

View File

@ -32,12 +32,14 @@
#include "glstate.h"
#include "shader.h"
#include <limits>
#include <algorithm>
#include <sigc++/connection.h>
#define DEF_Z (rgssVer >= 3 ? 100 : 0)
#define DEF_PADDING (rgssVer >= 3 ? 12 : 16)
#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>
struct Sides
@ -811,14 +813,14 @@ struct WindowVXPrivate
};
WindowVX::WindowVX(Viewport *viewport)
: ViewportElement(viewport, DEF_Z)
: ViewportElement(viewport, DEF_Z, DEF_SPRITE_Y)
{
p = new WindowVXPrivate(0, 0, 0, 0);
onGeometryChange(scene->getGeometry());
}
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);
onGeometryChange(scene->getGeometry());