From 2740913c60f6cd4ac739c40ffd9bbfa90d2fa2be Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@users.noreply.github.com>
Date: Thu, 21 Nov 2019 19:30:27 +0100
Subject: [PATCH] - added a redirection hack for rotatesprite so that it can be
 transitionally used in the 2D drawer.

---
 source/build/src/engine.cpp     |  9 +++++++
 source/common/2d/v_2ddrawer.cpp | 47 +++++++++++++++++++++++++++++++++
 source/common/2d/v_2ddrawer.h   |  7 ++++-
 source/glbackend/hw_draw2d.cpp  | 19 +++++++++++++
 4 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp
index 428344c19..0a9f5070e 100644
--- a/source/build/src/engine.cpp
+++ b/source/build/src/engine.cpp
@@ -11398,6 +11398,9 @@ void renderFlushPerms(void)
 }
 
 
+bool rotatesprite_2doverride;	// gross hack alert. Thanks to the insufficient abstraction the only chance to redirect rotatesprite calls
+								// to the 2D drawer is to use a global flag and check in rotatesprite_.
+#include "v_2ddrawer.h"
 //
 // rotatesprite
 //
@@ -11415,6 +11418,12 @@ void rotatesprite_(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
     tileUpdatePicnum(&picnum, (int16_t)0xc000);
     if ((tilesiz[picnum].x <= 0) || (tilesiz[picnum].y <= 0)) return;
 
+	if (rotatesprite_2doverride)
+	{
+		twod.rotatesprite(sx, sy, z, a, picnum, dashade, dapalnum, dastat, daalpha, dablend, cx1, cy1, cx2, cy2);
+		return;
+	}
+
     // Experimental / development bits. ONLY FOR INTERNAL USE!
     //  bit RS_CENTERORIGIN: see dorotspr_handle_bit2
     ////////////////////
diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp
index bdc0da2f5..92b499f06 100644
--- a/source/common/2d/v_2ddrawer.cpp
+++ b/source/common/2d/v_2ddrawer.cpp
@@ -31,6 +31,7 @@
 #include "renderstyle.h"
 #include "drawparms.h"
 #include "vectors.h"
+#include "gamecvars.h"
 //#include "doomtype.h"
 #include "templates.h"
 //#include "r_utility.h"
@@ -554,3 +555,49 @@ void F2DDrawer::Clear()
 	mData.Clear();
 	mIsFirstPass = true;
 }
+
+//==========================================================================
+//
+//
+//
+//==========================================================================
+
+
+#include "build.h"
+#include "../src/engine_priv.h"
+
+void F2DDrawer::rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
+	int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
+	int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2)
+{
+	if (r_rotatespritenowidescreen)
+	{
+		dastat |= RS_STRETCH;
+		dastat &= ~RS_ALIGN_MASK;
+	}
+
+	// This is mainly a hack because the rotatesprite code is far too messed up to integrate into the 2D drawer.
+	// This merely stores the parameters and later just calls polymost_rotatesprite do do the work.
+	// Cleanup can be done once everything is working - but for the menu's transition the original calls should be preserved.
+	RenderCommand dg;
+
+	dg.mType = DrawTypeRotateSprite;
+
+	// Just store the values in the otherwise useless fields of the draw command instead of allocating separate memory.
+	dg.mVertIndex = sx;
+	dg.mVertCount = sy;
+	dg.mIndexIndex = z;
+	dg.mIndexCount = a;
+	dg.mSpecialColormap[0].d = picnum;
+	dg.mRemapIndex = dashade;
+	dg.mFlags = dapalnum;
+	dg.mSpecialColormap[1].d = dastat;
+	dg.mDesaturate = daalpha;
+	dg.mColor1.d = dablend;
+	dg.mScissor[0] = cx1;
+	dg.mScissor[1] = cy1;
+	dg.mScissor[2] = cx2;
+	dg.mScissor[3] = cy2;
+	mData.Push(dg);	// don't even try to merge.
+}
+
diff --git a/source/common/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h
index 8e2d52e6e..0641d42b1 100644
--- a/source/common/2d/v_2ddrawer.h
+++ b/source/common/2d/v_2ddrawer.h
@@ -19,6 +19,7 @@ public:
 		DrawTypeTriangles,
 		DrawTypeLines,
 		DrawTypePoints,
+		DrawTypeRotateSprite,
 	};
 
 	enum ETextureFlags : uint8_t
@@ -85,7 +86,7 @@ public:
 		bool isCompatible(const RenderCommand &other) const
 		{
 			return mTexture == other.mTexture &&
-				mType == other.mType &&
+				mType == other.mType && mType != DrawTypeRotateSprite &&
 				mRemapIndex == other.mRemapIndex &&
 				mSpecialColormap[0].d == other.mSpecialColormap[0].d &&
 				mSpecialColormap[1].d == other.mSpecialColormap[1].d &&
@@ -122,6 +123,10 @@ public:
 	void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255);
 	void AddPixel(int x1, int y1, uint32_t color);
 
+	void rotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum,
+		int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend,
+		int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2);
+
 	void Clear();
 
 	bool mIsFirstPass = true;
diff --git a/source/glbackend/hw_draw2d.cpp b/source/glbackend/hw_draw2d.cpp
index 46b278652..bdd0f08f7 100644
--- a/source/glbackend/hw_draw2d.cpp
+++ b/source/glbackend/hw_draw2d.cpp
@@ -82,6 +82,7 @@ public:
 // Draws the 2D stuff. This is the version for OpenGL 3 and later.
 //
 //===========================================================================
+void polymost_dorotatesprite(int32_t sx, int32_t sy, int32_t z, int16_t a, int16_t picnum, int8_t dashade, uint8_t dapalnum, int32_t dastat, uint8_t daalpha, uint8_t dablend, int32_t cx1, int32_t cy1, int32_t cx2, int32_t cy2, int32_t uniqid);
 
 void GLInstance::Draw2D(F2DDrawer *drawer)
 {
@@ -123,6 +124,24 @@ void GLInstance::Draw2D(F2DDrawer *drawer)
 
 	for(auto &cmd : commands)
 	{
+		if (cmd.mType == F2DDrawer::DrawTypeRotateSprite)
+		{
+			// This just gets forwarded to the original drawer. Long term this should not survive and all calls be refactored.
+			UseColorOnly(false);
+			SetFadeDisable(false);
+			polymost_dorotatesprite(cmd.mVertIndex, cmd.mVertCount, cmd.mIndexIndex, cmd.mIndexCount, cmd.mSpecialColormap[0].d, cmd.mRemapIndex, cmd.mFlags, cmd.mSpecialColormap[1].d,
+				cmd.mDesaturate, cmd.mColor1.d, cmd.mScissor[0], cmd.mScissor[1], cmd.mScissor[2], cmd.mScissor[3], 0);
+			// Reset everything to the default.
+			SetFadeDisable(true);
+			EnableDepthTest(false);
+			EnableMultisampling(false);
+			EnableBlend(true);
+			EnableAlphaTest(true);
+			SetBlendFunc(STYLEALPHA_Src, STYLEALPHA_InvSrc);
+
+			continue;
+		}
+
 
 		int gltrans = -1;
 		//state.SetRenderStyle(cmd.mRenderStyle);