From 1b73eea70aafe0cfccdf40cd085c2cc31391e2ac Mon Sep 17 00:00:00 2001
From: DBotThePony <dbotthepony@yandex.ru>
Date: Thu, 19 Aug 2021 22:16:50 +0700
Subject: [PATCH] Render helper

---
 .../mc/otm/screen/RenderHelper.java           | 287 ++++++++++++++++++
 .../textures/gui/widgets.png                  | Bin 1814 -> 1911 bytes
 .../textures/gui/widgets.xcf                  |   4 +-
 3 files changed, 289 insertions(+), 2 deletions(-)
 create mode 100644 src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java

diff --git a/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java b/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java
new file mode 100644
index 000000000..dc3eaccc3
--- /dev/null
+++ b/src/main/java/ru/dbotthepony/mc/otm/screen/RenderHelper.java
@@ -0,0 +1,287 @@
+package ru.dbotthepony.mc.otm.screen;
+
+import com.mojang.blaze3d.systems.RenderSystem;
+import com.mojang.blaze3d.vertex.*;
+import com.mojang.math.Matrix4f;
+import net.minecraft.client.renderer.GameRenderer;
+import net.minecraft.resources.ResourceLocation;
+import ru.dbotthepony.mc.otm.OverdriveThatMatters;
+
+/**
+ * I am too lazy to learn how Mojang's API works
+ * so I just recreate part of GMod's API in here
+ */
+public class RenderHelper {
+	private static final Matrix4f identity = new Matrix4f();
+	public static final ResourceLocation WIDGETS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets.png");
+
+	static {
+		identity.setIdentity();
+	}
+
+	// Regular functions
+
+	/**
+	 * Draws a textured rectangle on screen
+	 * translated by a given matrix
+	 *
+	 * @param matrix Matrix translation to use
+	 * @param x screen X position (with matrix transformation)
+	 * @param y screen Y position (with matrix transformation)
+	 * @param width width of drawn rectangle
+	 * @param height height of drawn rectangle
+	 * @param u0 initial U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v0 initial V position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param u1 final U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v1 final V position ranging from 0-1 (single) or beyond (repetitive)
+	 */
+	public static void drawTexturedRectUV(
+		Matrix4f matrix,
+		float x,
+		float y,
+		float width,
+		float height,
+		float u0,
+		float v0,
+		float u1,
+		float v1
+	) {
+		RenderSystem.setShader(GameRenderer::getPositionTexShader);
+
+		var builder = Tesselator.getInstance().getBuilder();
+		builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
+		builder.vertex(matrix, x, y + height, 0).uv(u0, v1).endVertex();
+		builder.vertex(matrix, x + width, y + height, 0).uv(u1, v1).endVertex();
+		builder.vertex(matrix, x + width, y, 0).uv(u1, v0).endVertex();
+		builder.vertex(matrix, x, y, 0).uv(u0, v0).endVertex();
+		builder.end();
+		BufferUploader.end(builder);
+	}
+
+	/**
+	 * Draws a textured rectangle on screen
+	 *
+	 * @param x screen X position (with matrix transformation)
+	 * @param y screen Y position (with matrix transformation)
+	 * @param width width of drawn rectangle
+	 * @param height height of drawn rectangle
+	 * @param u0 initial U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v0 initial V position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param u1 final U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v1 final V position ranging from 0-1 (single) or beyond (repetitive)
+	 */
+	public static void drawTexturedRectUV(
+		float x,
+		float y,
+		float width,
+		float height,
+		float u0,
+		float v0,
+		float u1,
+		float v1
+	) {
+		drawTexturedRectUV(identity, x, y, width, height, u0, v0, u1, v1);
+	}
+
+	/**
+	 * Draws a textured rectangle on screen
+	 * with matrix from pose
+	 *
+	 * @param stack PoseStack containing translation matrix
+	 * @param x screen X position (with matrix transformation)
+	 * @param y screen Y position (with matrix transformation)
+	 * @param width width of drawn rectangle
+	 * @param height height of drawn rectangle
+	 * @param u0 initial U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v0 initial V position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param u1 final U position ranging from 0-1 (single) or beyond (repetitive)
+	 * @param v1 final V position ranging from 0-1 (single) or beyond (repetitive)
+	 */
+	public static void drawTexturedRectUV(
+		PoseStack stack,
+		float x,
+		float y,
+		float width,
+		float height,
+		float u0,
+		float v0,
+		float u1,
+		float v1
+	) {
+		drawTexturedRectUV(stack.last().pose(), x, y, width, height, u0, v0, u1, v1);
+	}
+
+	/**
+	 * Draws a textured rectangle on screen
+	 * with matrix from pose
+	 * UVs are 0-1
+	 *
+	 * @param stack PoseStack containing translation matrix
+	 * @param x screen X position (with matrix transformation)
+	 * @param y screen Y position (with matrix transformation)
+	 * @param width width of drawn rectangle
+	 * @param height height of drawn rectangle
+	 */
+	public static void drawTexturedRect(
+		PoseStack stack,
+		float x,
+		float y,
+		float width,
+		float height
+	) {
+		drawTexturedRectUV(stack, x, y, width, height, 0, 0, 1, 1);
+	}
+
+	public record SkinElement(ResourceLocation texture, float image_x, float image_y, float rect_w, float rect_h, float defined_width, float defined_height) {
+		public void render(PoseStack stack, float x, float y, float width, float height) {
+			RenderSystem.setShaderTexture(0, texture);
+
+			drawTexturedRectUV(
+				stack,
+				x,
+				y,
+				width,
+				height,
+				image_x / defined_width,
+				image_y / defined_height,
+				(image_x + rect_w) / defined_width,
+				(image_y + rect_h) / defined_height);
+		}
+
+		public void renderRaw(PoseStack stack, float x, float y, float width, float height) {
+			// RenderSystem.setShader(GameRenderer::getPositionTexShader);
+			// RenderSystem.setShaderTexture(0, texture);
+
+			drawTexturedRectUV(
+				stack,
+				x,
+				y,
+				width,
+				height,
+				image_x / defined_width,
+				image_y / defined_height,
+				(image_x + rect_w) / defined_width,
+				(image_y + rect_h) / defined_height);
+		}
+	}
+
+	public static final SkinElement upper_left_window_corner = new SkinElement(
+		WIDGETS,
+		18,
+		0,
+		6,
+		6,
+		256,
+		256
+	);
+
+	public static final SkinElement upper_right_window_corner = new SkinElement(
+		WIDGETS,
+		24,
+		0,
+		6,
+		6,
+		256,
+		256
+	);
+
+	public static final SkinElement bottom_left_window_corner = new SkinElement(
+		WIDGETS,
+		18,
+		6,
+		6,
+		6,
+		256,
+		256
+	);
+
+	public static final SkinElement bottom_right_window_corner = new SkinElement(
+		WIDGETS,
+		24,
+		6,
+		6,
+		6,
+		256,
+		256
+	);
+
+	public static final SkinElement left_window_border = new SkinElement(
+		WIDGETS,
+		18,
+		4,
+		3,
+		5,
+		256,
+		256
+	);
+
+	public static final SkinElement right_window_border = new SkinElement(
+		WIDGETS,
+		27,
+		3,
+		3,
+		5,
+		256,
+		256
+	);
+
+	public static final SkinElement top_window_border = new SkinElement(
+		WIDGETS,
+		22,
+		0,
+		5,
+		3,
+		256,
+		256
+	);
+
+	public static final SkinElement bottom_window_border = new SkinElement(
+		WIDGETS,
+		21,
+		9,
+		5,
+		3,
+		256,
+		256
+	);
+
+	public static final SkinElement window_background = new SkinElement(
+		WIDGETS,
+		22,
+		4,
+		4,
+		4,
+		256,
+		256
+	);
+
+	public static void drawWindowBackground(
+		PoseStack stack,
+		float x,
+		float y,
+		float width,
+		float height
+	) {
+		float bg_width = width - 4;
+		float bg_height = height - 4;
+
+		// background
+		if (bg_width > 0 && bg_height > 0) {
+			window_background.render(stack, x + 3, y + 3, bg_width, bg_height);
+		}
+
+		// borders
+		left_window_border.render(stack, x, y + 4, 3, height - 8);
+		right_window_border.renderRaw(stack, x + width - 3, y + 4, 3, height - 6);
+
+		top_window_border.renderRaw(stack, x + 4, y, width - 8, 3);
+		bottom_window_border.renderRaw(stack, x + 4, y + height - 3, width - 8, 3);
+
+		// corners
+		upper_left_window_corner.renderRaw(stack, x, y, 6, 6);
+		upper_right_window_corner.renderRaw(stack, x + width - 6, y, 6, 6);
+
+		bottom_left_window_corner.renderRaw(stack, x, y + height - 6, 6, 6);
+		bottom_right_window_corner.renderRaw(stack, x + width - 6, y + height - 6, 6, 6);
+	}
+}
diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.png b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.png
index 25976bebc4e3d9be5f36681877c16f8231a2ba34..90a4a9675316f0b7b1e68b963613be2ea1cc7f99 100644
GIT binary patch
delta 1367
zcmaKmSx{346o$`DLP$e^#D!2nlA(hGNGU?9U<AUV4$6|MQ$+?6Dj_OM8W3E-+zVA2
zD+pF941xj`K}A56#VRHgQITqB8C=L90-?cLG#WOOz-^p9bo%1UdHDZt{_~x-nYC&9
z9YGh{S~--3-{AsS<b{O>Z96bHIkYNm>-Ht&7wPtil$8{YTgb^A=ZE_C2h=V8GtkjO
zWqQWje*M$Z^UeCQC0=g3`+0UnVRfn0m;Rf*n?*(Psn@feUiO^alUmcPV*4LkS4V6e
zwTpcsN`8I8c(ZpNxS4^@)hX(hHKmcY43zP9EJ{%<ags4@odSNav{e)o;@NT(U+@W#
znO4g1X|1ejv)e0epwDqSHZPU*J0u<}eJD}f(f+L+xHar+VlbFYX4{vf7fEZdh^)hI
zen)}=?};8Bk{vvFa8mW?(WBA#daYC@YxqPNz`^bXnli_%^AsxCyWUOi$*WP55|JR)
zp&HXhMP^BOfzu@lCU<qI_Ml~ZnyC5fAn`aFXY>(jkRry(d4u3|8~Kbcm#g31b@qn(
z8tB=sRx!EV`S*WIlS<>C#^=Xi9wC+!g~Y}o&D`AFU88ScV4D;RNrF`z?AbMNd3>A9
z)~fWw*Ux~BJ9s;z=`$WY)TyYZ-a#B<^Yb8~ex1dRZ^n6GF9prJUsGqQn#oNj(FVI!
zkU`?zNmeO}DWXg-$mfE0uc-z1^Du};W|eYcW#|T*%L@a3*fh)Ck7(~n+LGs=Lx6#D
zgqDQ|EZJg#?If6)hN*>ZNaYETyLLHXX`(eK<oiO})%lWW2UkWb@FR%#FOT8RvXIfi
ztlS(1nRm>aHB&BFR<B@}Qei0vbDTkLI9l<R#$YwRUIxAxXiU;qcvTs+w+?S7RGx($
zgKt%hbPbKZHwn5dkmGhA9O?tK0uP+8vSX)@_$$ZvI>5F*Fc^keDB%c`5WHRtdVx`8
z=`+uN@+t4`s2G{R`C(98)6J@Lg*?NX6eV8(#Ye{#=%UK=Yhk(^35`B5E%3Zfs663=
zHS02VgPGTu#yWSs{4Dqi&JP03t*MfUMp8M$rNhPE#t)w3(tTsr2F1Aw{PVa)?N1S&
ze+)K&M$cBU`B9J%`e&^trJA6udT?P+YQ>9&SM}3;qaE0n7#WNdbwfwzzO@B%`7G=4
z{`q@_<z!_iS-IkQhh7-eg6K5IEUh*$A?jQP<EqR`Hx<o{twk_0_!5BwypJCA<Mn?n
z9hLzFtbt_SC75HR62YMF-*urQqMM0W9CcfOe%B@`lTUEW4TwSMn$XV~Z*|CsEpc+M
z<3MVEYf5-+e+4d9w-)pyIOhw`ph#cqBy*^zrzgyD`SR|P=c*NWWFi%w{+Q)NpaTX#
z0yY3*{>=j*!2ctmU`V1~9T^$9ZV`VMu{3<e4Qr=OO%`x>8K~Q3>~Aroj}sxy5Y~A?
zy@|gErn)54-#;KIbs;rn7u@z=T&P8BYsZsx6*-eVH(wiDkUBOT0o{7F86oDeyiCdw
znqngY0Dom3I`qpaJ@Uou(MIiAIv{Kk4=4y7f`Nq5F==lsZ8E{TCzf_a#lrkkp$sUP
z*@qi_QE)r^C6}yD9#F@P8%NN$qut^wj~nAUc5+RP0)=O*1$NjPOQ|=VyYxPfHIr@C
z)H^7di!UU8kVJ%YRlzs2FTF{(rRNaEbI7SGa_p%lvb8;i_oJ!+=do(eG}WvJVe2D9
J8-j(o{{ToULOcKf

delta 1255
zcmbu6|5MTj7{{LvAYh9xTAF4PmZNOBw4GnO5)5)@HbX}@$xJI#aZ@~t<!SQyv^eE%
zrd^hqY>DQ~FDogheQ^`0FejEeXW!64j?~kcHA_qdhPNN~2kiaB`|i2t?)82@_gJXq
zR8>EMQt34M&_c^i04G)yFG7&}Y-)IOme;2%i6#pHDT$%CM|rxPNURl}3yWynCi}hY
zvI(i>s=A%yQWYzM<8FR-Xbd81GU86R@BOWgl~C*R@^}?Rd)@u|wL6P5y{Fft4g|7Z
z_Dd3p0b!S2Trv$We@?!&FOqk!lx>ac2wOlmUHpDqX<C}GbBaCvr%`P$HW<_+mL$}j
zo-K><&O1;p@7W`aFX$PZ9$9zCj92n_8^UA}47_fLcHay9rE^ndtClDAO3ml52(nik
z_?yDq$-9c`@*eqLaD_%PCii946cdk^gyUAwut9SbWAXif*U%;JlG^+g(Reg@1nHZ$
zochA5GZp2PgRqd=Cnn)q2^=A9u}k7}8u(F=!W*54#iVRz^fhPl9)ji(7h|;r6EIN-
z_WG#!FYaMV^2|W7-$9sg<PBD$J}%uEhoItXNGX4N#D1jWjefjWBXe|*q_)_G!?Aaa
zkDlT^sJIPxD^U)DWz0fhE6P~bfa83O@Ynj>$W!}hm1jWid-pvo=gT126$&{+Hhm-I
zEIAtL>k#wstbL*to(F09TsZ4Hsl7OPNjs0%3ZPzzm{ruS2l3DtkNfK0iE5gJsL5u^
z=V^lk4QaA~1ryHLDL4DPjG2$|6Yw4=mEgA*1T7?$wL<-QM0E{|Gddomd6DG_f<Bm^
zH;Qqx^|<Xj@?o;nx^U9d%75(5>74ro-k|j#LU*T`CRhnvtL2mAdVlCnpPyzBd>g2o
zZTS!z*=y6sZiI;^c;8FCTs*cD$9ycNd3%XnGHgZ59K#Q49*VkVN1lCiCOLEzaxM3D
z>;1>o9nb7u4Cj46g7P9uGaGNIWAb+|z2H8T5Q~`N4-W)dN=#QLd*1RFT%n?TKrU~~
zJhor8Z<Ej3k>Q2mM7!=tJCgkq@`^4t-WKvR;k&AKVZbfOeb@M{d^j3A-+X&~3k3o}
z;|)p_fz_b=|As*ya3CF+4ldn+Bm)Hq81Y~D02vEuR)pH67ANuk5SM<@QsOLNQC)Rg
zMBN3eB#Gy<+ytw^A~FP*>tAT?Et!VS<Ke3!RlSgIn2j~21S@np-HxrZ3tP>`Uw0vp
zpEKfKHs-`YIRLu{MTWM`iU&i^_1BP|v6&&#4Oc$|YanXEAJPaV0Z>`DA%;}A46o^-
zog;GCa}R8MA$TnE8|p;eV*<PGU~C7G?fIl?aY&*L1~&pm2k%xtST5C=NXw<BT%x)i
z9FipXxs#qUUL8%E%ZrgYF8ly+D2I#z9mfP2>`L%H*!OU3X6rrWTO0nB%nMrwIOgcg
zyNJ|@rlyVT%}>&r{;>ENX*RuH?_YVPxw-im)uvE*MMG{QqAI;$KNMs%6|L_egr-b|
z%sqD|VOmFDhq-Mra|@DgpCGRZJIPpT@}J6RBz_s4MDdtoTS=leTW3eL<lNFaYDWz3
J>h|Ps{sHtK69)hQ

diff --git a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf
index fa56b0d7c..702d1ed0f 100644
--- a/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf
+++ b/src/main/resources/assets/overdrive_that_matters/textures/gui/widgets.xcf
@@ -1,3 +1,3 @@
 version https://git-lfs.github.com/spec/v1
-oid sha256:6d3c951d9fd4bf3a35c714cd22159fef1fea42c0f9b621202340c297bb62b338
-size 7712
+oid sha256:1e15d574534de8d8ca9126e07638dc455f0de6afe2e9d7c126876104cdbfd9bd
+size 10004