From d8bb6aa2fcb75d03f325d327b21cde15aabe756a Mon Sep 17 00:00:00 2001 From: Jonas Kulla Date: Sun, 31 Aug 2014 00:51:23 +0200 Subject: [PATCH] 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. --- src/scene.cpp | 21 ++++----------------- src/scene.h | 14 +++++++++++--- src/sprite.cpp | 2 +- src/tilemap.cpp | 15 ++------------- src/viewport.cpp | 8 ++------ src/viewport.h | 3 +-- src/windowvx.cpp | 6 ++++-- 7 files changed, 25 insertions(+), 44 deletions(-) diff --git a/src/scene.cpp b/src/scene.cpp index c352eb7..9f660f7 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -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; diff --git a/src/scene.h b/src/scene.h index 0e6113b..d32dc8b 100644 --- a/src/scene.h +++ b/src/scene.h @@ -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 diff --git a/src/sprite.cpp b/src/sprite.cpp index 21af6d0..50a2415 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -290,7 +290,7 @@ struct SpritePrivate }; Sprite::Sprite(Viewport *viewport) - : ViewportElement(viewport, 0, true) + : ViewportElement(viewport) { p = new SpritePrivate; onGeometryChange(scene->getGeometry()); diff --git a/src/tilemap.cpp b/src/tilemap.cpp index 05cbd54..d0601e2 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -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), diff --git a/src/viewport.cpp b/src/viewport.cpp index 96fd50b..38aa89f 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -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; diff --git a/src/viewport.h b/src/viewport.h index ecb646a..6d340b6 100644 --- a/src/viewport.h +++ b/src/viewport.h @@ -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* ) diff --git a/src/windowvx.cpp b/src/windowvx.cpp index 11aed18..936792f 100644 --- a/src/windowvx.cpp +++ b/src/windowvx.cpp @@ -32,12 +32,14 @@ #include "glstate.h" #include "shader.h" +#include #include #include #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::max() : 0) /* See scene.h */ template 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());