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&Oc$|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