diff --git a/src/etc-internal.h b/src/etc-internal.h index 0b4624c..c9bd520 100644 --- a/src/etc-internal.h +++ b/src/etc-internal.h @@ -79,19 +79,68 @@ struct Vec2i : x(x), y(y) {} + explicit Vec2i(int xy) + : x(xy), y(xy) + {} + bool operator==(const Vec2i &other) const { return x == other.x && y == other.y; } - Vec2i &operator+=(const Vec2i &other) + Vec2i &operator+=(const Vec2i &value) { - x += other.x; - y += other.y; + x += value.x; + y += value.y; return *this; } + Vec2i &operator-=(const Vec2i &value) + { + x -= value.x; + y -= value.y; + + return *this; + } + + Vec2i operator+(const Vec2i &value) const + { + return Vec2i(x + value.x, y + value.y); + } + + Vec2i operator-(const Vec2i &value) const + { + return Vec2i(x - value.x, y - value.y); + } + + template + Vec2i operator*(T value) const + { + return Vec2i(x * value, y * value); + } + + template + Vec2i operator/(T value) const + { + return Vec2i(x / value, y / value); + } + + Vec2i operator%(int value) const + { + return Vec2i(x % value, y % value); + } + + Vec2i operator-() const + { + return Vec2i(-x, -y); + } + + Vec2i operator!() const + { + return Vec2i(!x, !y); + } + operator Vec2() const { return Vec2(x, y); @@ -113,6 +162,14 @@ struct IntRect : SDL_Rect this->h = h; } + IntRect(const Vec2i &pos, const Vec2i &size) + { + x = pos.x; + y = pos.y; + w = size.x; + h = size.y; + } + bool operator==(const IntRect &other) const { return (x == other.x && y == other.y && @@ -129,10 +186,16 @@ struct IntRect : SDL_Rect return Vec2i(w, h); } - operator SDL_Rect() const + void setPos(const Vec2i &value) { - SDL_Rect r = { x, y, w, h }; - return r; + x = value.x; + y = value.y; + } + + void setSize(const Vec2i &value) + { + w = value.x; + h = value.y; } bool encloses(const IntRect &o) const @@ -176,35 +239,10 @@ struct FloatRect Vec2 topRight() const { return Vec2(x+w, y); } Vec2 bottomRight() const { return Vec2(x+w, y+h); } - void shrinkHalf() - { - x += 0.5; - y += 0.5; - w -= 1.0; - h -= 1.0; - } - - FloatRect vFlipped() const - { - return FloatRect(x, y+h, w, -h); - } - FloatRect hFlipped() const { return FloatRect(x+w, y, -w, h); } - - Vec2 corner(int i) const - { - switch (i) - { - case 0 : return topLeft(); - case 1 : return topRight(); - case 2 : return bottomRight(); - case 3 : return bottomLeft(); - default : return Vec2(); - } - } }; /* Value between 0 and 255 with internal diff --git a/src/plane.cpp b/src/plane.cpp index 3df691e..f275e85 100644 --- a/src/plane.cpp +++ b/src/plane.cpp @@ -90,8 +90,8 @@ struct PlanePrivate if (gl.npot_repeat) { FloatRect srcRect; - srcRect.x = (sceneGeo.xOrigin + ox) / zoomX; - srcRect.y = (sceneGeo.yOrigin + oy) / zoomY; + srcRect.x = (sceneGeo.orig.x + ox) / zoomX; + srcRect.y = (sceneGeo.orig.y + oy) / zoomY; srcRect.w = sceneGeo.rect.w / zoomX; srcRect.h = sceneGeo.rect.h / zoomY; diff --git a/src/scene.cpp b/src/scene.cpp index a642288..2c3388c 100644 --- a/src/scene.cpp +++ b/src/scene.cpp @@ -23,10 +23,7 @@ #include "sharedstate.h" Scene::Scene() -{ - geometry.xOrigin = geometry.yOrigin = 0; - geometry.rect = IntRect(); -} +{} Scene::~Scene() { diff --git a/src/scene.h b/src/scene.h index 4dd46b3..edee331 100644 --- a/src/scene.h +++ b/src/scene.h @@ -39,8 +39,16 @@ class Scene public: struct Geometry { - int xOrigin, yOrigin; + /* Position and size relative to parent */ IntRect rect; + + /* Origin of contents */ + Vec2i orig; + + Vec2i offset() const + { + return rect.pos() - orig; + } }; Scene(); diff --git a/src/sprite.cpp b/src/sprite.cpp index d6bd9ae..0313444 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp @@ -57,7 +57,7 @@ struct SpritePrivate NormValue opacity; BlendType blendType; - SDL_Rect sceneRect; + IntRect sceneRect; Vec2i sceneOrig; /* Would this sprite be visible on @@ -183,9 +183,8 @@ struct SpritePrivate return; } - SDL_Rect self; - self.x = trans.getPosition().x - (trans.getOrigin().x + sceneOrig.x); - self.y = trans.getPosition().y - (trans.getOrigin().y + sceneOrig.y); + IntRect self; + self.setPos(trans.getPositionI() - (trans.getOriginI() + sceneOrig)); self.w = bitmap->width(); self.h = bitmap->height(); @@ -577,15 +576,10 @@ void Sprite::onGeometryChange(const Scene::Geometry &geo) { /* Offset at which the sprite will be drawn * relative to screen origin */ - int xOffset = geo.rect.x - geo.xOrigin; - int yOffset = geo.rect.y - geo.yOrigin; + p->trans.setGlobalOffset(geo.offset()); - p->trans.setGlobalOffset(xOffset, yOffset); - - p->sceneRect.w = geo.rect.w; - p->sceneRect.h = geo.rect.h; - p->sceneOrig.x = geo.xOrigin; - p->sceneOrig.y = geo.yOrigin; + p->sceneRect.setSize(geo.rect.size()); + p->sceneOrig = geo.orig; } void Sprite::releaseResources() diff --git a/src/tilemap.cpp b/src/tilemap.cpp index 92a1dde..d3cf437 100644 --- a/src/tilemap.cpp +++ b/src/tilemap.cpp @@ -442,15 +442,13 @@ struct TilemapPrivate void updateSceneGeometry(const Scene::Geometry &geo) { - elem.sceneOffset.x = geo.rect.x - geo.xOrigin; - elem.sceneOffset.y = geo.rect.y - geo.yOrigin; + elem.sceneOffset = geo.offset(); elem.sceneGeo = geo; } void updatePosition() { - dispPos.x = -(offset.x - viewpPos.x * 32) + elem.sceneOffset.x; - dispPos.y = -(offset.y - viewpPos.y * 32) + elem.sceneOffset.y; + dispPos = -(offset - viewpPos * 32) + elem.sceneOffset; } void invalidateAtlasSize() diff --git a/src/tilemapvx.cpp b/src/tilemapvx.cpp index a405cb8..6291fd9 100644 --- a/src/tilemapvx.cpp +++ b/src/tilemapvx.cpp @@ -366,11 +366,10 @@ struct TilemapVXPrivate : public ViewportElement, TileAtlasVX::Reader void onGeometryChange(const Scene::Geometry &geo) { - mapViewp.w = (geo.rect.w / 32) + !!(geo.rect.w % 32) + 1; - mapViewp.h = (geo.rect.h / 32) + !!(geo.rect.h % 32) + 1; + const Vec2i geoSize = geo.rect.size(); + mapViewp.setSize((geoSize / 32) + !!(geoSize % 32) + Vec2i(1)); - sceneOffset.x = geo.rect.x - geo.xOrigin; - sceneOffset.y = geo.rect.y - geo.yOrigin; + sceneOffset = geo.offset(); sceneGeo = geo; buffersDirty = true; diff --git a/src/transform.h b/src/transform.h index fc8bab9..cefd09f 100644 --- a/src/transform.h +++ b/src/transform.h @@ -58,7 +58,6 @@ public: Transform() : scale(1, 1), rotation(0), - xOffset(0), yOffset(0), dirty(true) { memset(matrix, 0, sizeof(matrix)); @@ -68,38 +67,47 @@ public: } Vec2 &getPosition() { return position; } - Vec2 &getScale() { return scale; } Vec2 &getOrigin() { return origin; } + Vec2 &getScale() { return scale; } float getRotation() { return rotation; } + Vec2i getPositionI() const + { + return Vec2i(position.x, position.y); + } + + Vec2i getOriginI() const + { + return Vec2i(origin.x, origin.y); + } + void setPosition(const Vec2 &value) { position = value; dirty = true; } - void setScale(const Vec2 &value) - { - scale = value; - dirty = true; - } - void setOrigin(const Vec2 &value) { origin = value; dirty = true; } + void setScale(const Vec2 &value) + { + scale = value; + dirty = true; + } + void setRotation(float value) { rotation = value; dirty = true; } - void setGlobalOffset(int x, int y) + void setGlobalOffset(const Vec2i &value) { - xOffset = x; - yOffset = y; + offset = value; dirty = true; } @@ -129,8 +137,8 @@ private: float syc = scale.y * cosine; float sxs = scale.x * sine; float sys = scale.y * sine; - float tx = -origin.x * sxc - origin.y * sys + position.x + xOffset; - float ty = origin.x * sxs - origin.y * syc + position.y + yOffset; + float tx = -origin.x * sxc - origin.y * sys + position.x + offset.x; + float ty = origin.x * sxs - origin.y * syc + position.y + offset.y; matrix[0] = sxc; matrix[1] = -sxs; @@ -146,7 +154,7 @@ private: float rotation; /* Silently added to position */ - int xOffset, yOffset; + Vec2i offset; float matrix[16]; diff --git a/src/viewport.cpp b/src/viewport.cpp index eba2ccc..fe4131f 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -144,8 +144,8 @@ void Viewport::update() Flashable::update(); } -DEF_ATTR_RD_SIMPLE(Viewport, OX, int, geometry.xOrigin) -DEF_ATTR_RD_SIMPLE(Viewport, OY, int, geometry.yOrigin) +DEF_ATTR_RD_SIMPLE(Viewport, OX, int, geometry.orig.x) +DEF_ATTR_RD_SIMPLE(Viewport, OY, int, geometry.orig.y) DEF_ATTR_SIMPLE(Viewport, Rect, Rect&, *p->rect) DEF_ATTR_SIMPLE(Viewport, Color, Color&, *p->color) @@ -155,10 +155,10 @@ void Viewport::setOX(int value) { guardDisposed(); - if (geometry.xOrigin == value) + if (geometry.orig.x == value) return; - geometry.xOrigin = value; + geometry.orig.x = value; notifyGeometryChange(); } @@ -166,10 +166,10 @@ void Viewport::setOY(int value) { guardDisposed(); - if (geometry.yOrigin == value) + if (geometry.orig.y == value) return; - geometry.yOrigin = value; + geometry.orig.y = value; notifyGeometryChange(); } diff --git a/src/window.cpp b/src/window.cpp index 0e78521..a32481d 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -471,16 +471,15 @@ struct WindowPrivate i += TileQuads::buildFrame(effectRect, cursorVert.vert); } - /* Scroll arrows */ - int scrollLRY = (size.y - 16) / 2; - int scrollTBX = (size.x - 16) / 2; + /* Scroll arrow position: Top Bottom X, Left Right Y */ + const Vec2i scroll = (size - Vec2i(16)) / 2; Sides scrollArrows; - scrollArrows.l = IntRect(4, scrollLRY, 8, 16); - scrollArrows.r = IntRect(size.x - 12, scrollLRY, 8, 16); - scrollArrows.t = IntRect(scrollTBX, 4, 16, 8); - scrollArrows.b = IntRect(scrollTBX, size.y - 12, 16, 8); + scrollArrows.l = IntRect(4, scroll.y, 8, 16); + scrollArrows.r = IntRect(size.x - 12, scroll.y, 8, 16); + scrollArrows.t = IntRect(scroll.x, 4, 16, 8); + scrollArrows.b = IntRect(scroll.x, size.y - 12, 16, 8); if (contents) { @@ -557,13 +556,10 @@ struct WindowPrivate if (size == Vec2i(0, 0)) return; - Vec2i trans(position.x + sceneOffset.x, - position.y + sceneOffset.y); - SimpleAlphaShader &shader = shState->shaders().simpleAlpha; shader.bind(); shader.applyViewportProj(); - shader.setTranslation(trans); + shader.setTranslation(position + sceneOffset); if (useBaseTex) { @@ -598,12 +594,11 @@ struct WindowPrivate controlsVertDirty = false; } - /* Actual on screen coordinates */ - int effectX = position.x + sceneOffset.x; - int effectY = position.y + sceneOffset.y; + /* Effective on screen coordinates */ + const Vec2i efPos = position + sceneOffset; - IntRect windowRect(effectX, effectY, size.x, size.y); - IntRect contentsRect(effectX+16, effectY+16, size.x-32, size.y-32); + const IntRect windowRect(efPos, size); + const IntRect contentsRect(efPos + Vec2i(16), size - Vec2i(32)); glState.scissorTest.pushSet(true); glState.scissorBox.push(); @@ -615,7 +610,7 @@ struct WindowPrivate if (!nullOrDisposed(windowskin)) { - shader.setTranslation(Vec2i(effectX, effectY)); + shader.setTranslation(efPos); /* Draw arrows / cursors */ windowskin->bindTex(shader); @@ -631,9 +626,7 @@ struct WindowPrivate /* Draw contents bitmap */ glState.scissorBox.setIntersect(contentsRect); - effectX += 16-contentsOffset.x; - effectY += 16-contentsOffset.y; - shader.setTranslation(Vec2i(effectX, effectY)); + shader.setTranslation(efPos + (Vec2i(16) - contentsOffset)); contents->bindTex(shader); contentsQuad.draw(); @@ -876,8 +869,7 @@ void Window::draw() void Window::onGeometryChange(const Scene::Geometry &geo) { - p->sceneOffset.x = geo.rect.x - geo.xOrigin; - p->sceneOffset.y = geo.rect.y - geo.yOrigin; + p->sceneOffset = geo.offset(); } void Window::setZ(int value) diff --git a/src/windowvx.cpp b/src/windowvx.cpp index 9af98ad..0bafb5b 100644 --- a/src/windowvx.cpp +++ b/src/windowvx.cpp @@ -506,15 +506,15 @@ struct WindowVXPrivate void rebuildCtrlVert() { - const int arrowTBX = (geo.w - 16) / 2; - const int arrowLRY = (geo.h - 16) / 2; + /* Scroll arrow position: Top Bottom X, Left Right Y */ + const Vec2i arrow = (geo.size() - Vec2i(16)) / 2; const Sides arrowPos = { - FloatRect( 4, arrowLRY, 8, 16 ), /* Left */ - FloatRect( geo.w - 12, arrowLRY, 8, 16 ), /* Right */ - FloatRect( arrowTBX, 4, 16, 8 ), /* Top */ - FloatRect( arrowTBX, geo.h - 12, 16, 8 ) /* Bottom */ + FloatRect( 4, arrow.y, 8, 16 ), /* Left */ + FloatRect( geo.w - 12, arrow.y, 8, 16 ), /* Right */ + FloatRect( arrow.x, 4, 16, 8 ), /* Top */ + FloatRect( arrow.x, geo.h - 12, 16, 8 ) /* Bottom */ }; size_t i = 0; @@ -538,7 +538,7 @@ struct WindowVXPrivate if (pause) { - const FloatRect pausePos(arrowTBX, geo.h - 16, 16, 16); + const FloatRect pausePos(arrow.x, geo.h - 16, 16, 16); pauseVert = &vert[i*4]; i += Quad::setTexPosRect(&vert[i*4], pauseSrc[0], pausePos); @@ -730,8 +730,7 @@ struct WindowVXPrivate bool windowskinValid = !nullOrDisposed(windowskin); bool contentsValid = !nullOrDisposed(contents); - Vec2i trans(geo.x + sceneOffset.x, - geo.y + sceneOffset.y); + Vec2i trans = geo.pos() + sceneOffset; SimpleAlphaShader &shader = shState->shaders().simpleAlpha; shader.bind(); @@ -764,8 +763,7 @@ struct WindowVXPrivate { /* Translate cliprect from local into screen space */ IntRect clip = clipRect; - clip.x += trans.x; - clip.y += trans.y; + clip.setPos(clip.pos() + trans); glState.scissorBox.push(); glState.scissorTest.pushSet(true); @@ -773,11 +771,10 @@ struct WindowVXPrivate if (rgssVer >= 3) glState.scissorBox.setIntersect(clip); else - glState.scissorBox.setIntersect(IntRect(trans.x, trans.y, geo.w, geo.h)); + glState.scissorBox.setIntersect(IntRect(trans, geo.size())); IntRect pad = padRect; - pad.x += trans.x; - pad.y += trans.y; + pad.setPos(pad.pos() + trans); if (drawCursor) { @@ -786,10 +783,7 @@ struct WindowVXPrivate contTrans.y += cursorRect->y; if (rgssVer >= 3) - { - contTrans.x -= contentsOff.x; - contTrans.y -= contentsOff.y; - } + contTrans -= contentsOff; shader.setTranslation(contTrans); @@ -804,8 +798,7 @@ struct WindowVXPrivate glState.scissorBox.setIntersect(clip); Vec2i contTrans = pad.pos(); - contTrans.x -= contentsOff.x; - contTrans.y -= contentsOff.y; + contTrans -= contentsOff; shader.setTranslation(contTrans); TEX::setSmooth(false); // XXX @@ -1105,8 +1098,7 @@ void WindowVX::draw() void WindowVX::onGeometryChange(const Scene::Geometry &geo) { - p->sceneOffset.x = geo.rect.x - geo.xOrigin; - p->sceneOffset.y = geo.rect.y - geo.yOrigin; + p->sceneOffset = geo.offset(); } void WindowVX::releaseResources()