From 87462fd7b0785fcc2181603d310b46ba9919d569 Mon Sep 17 00:00:00 2001
From: Jonas Kulla <Nyocurio@gmail.com>
Date: Tue, 10 Feb 2015 16:42:32 +0100
Subject: [PATCH] Use more explicit vector math via method overloads

---
 src/etc-internal.h | 100 +++++++++++++++++++++++++++++++--------------
 src/plane.cpp      |   4 +-
 src/scene.cpp      |   5 +--
 src/scene.h        |  10 ++++-
 src/sprite.cpp     |  18 +++-----
 src/tilemap.cpp    |   6 +--
 src/tilemapvx.cpp  |   7 ++--
 src/transform.h    |  36 +++++++++-------
 src/viewport.cpp   |  12 +++---
 src/window.cpp     |  36 +++++++---------
 src/windowvx.cpp   |  36 +++++++---------
 11 files changed, 148 insertions(+), 122 deletions(-)

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<typename T>
+	Vec2i operator*(T value) const
+	{
+		return Vec2i(x * value, y * value);
+	}
+
+	template<typename T>
+	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<IntRect> 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<FloatRect> 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()