1+ package com .fix3dll .skyblockaddons .core .render .state ;
2+
3+ import com .mojang .blaze3d .pipeline .RenderPipeline ;
4+ import com .mojang .blaze3d .vertex .VertexConsumer ;
5+ import net .minecraft .client .gui .navigation .ScreenRectangle ;
6+ import net .minecraft .client .gui .render .TextureSetup ;
7+ import net .minecraft .client .gui .render .state .GuiElementRenderState ;
8+ import org .joml .Matrix3x2f ;
9+
10+ import static net .minecraft .util .Mth .HALF_PI ;
11+
12+ public record RoundedRectRenderState (
13+ RenderPipeline pipeline ,
14+ TextureSetup textureSetup ,
15+ Matrix3x2f pose ,
16+ float x ,
17+ float y ,
18+ float width ,
19+ float height ,
20+ float radius ,
21+ int color ,
22+ ScreenRectangle scissorArea ,
23+ ScreenRectangle bounds
24+ ) implements GuiElementRenderState {
25+
26+ public RoundedRectRenderState {
27+ pose = new Matrix3x2f (pose );
28+ }
29+
30+ public RoundedRectRenderState (
31+ RenderPipeline pipeline ,
32+ TextureSetup textureSetup ,
33+ Matrix3x2f pose ,
34+ float x ,
35+ float y ,
36+ float width ,
37+ float height ,
38+ float radius ,
39+ int color ,
40+ ScreenRectangle scissorArea
41+ ) {
42+ this (pipeline , textureSetup , pose , x , y , width , height , radius , color , scissorArea ,
43+ getBounds (Math .round (x ), Math .round (y ), Math .round (x + width ), Math .round (y + height ), pose , scissorArea ));
44+ }
45+
46+ @ Override
47+ public void buildVertices (VertexConsumer consumer ) {
48+ // 1. Draw the 3 central filling rectangles (cross shape)
49+ addQuad (consumer , x + radius , y , x + width - radius , y + height ); // Center vertical
50+ addQuad (consumer , x , y + radius , x + radius , y + height - radius ); // Left horizontal
51+ addQuad (consumer , x + width - radius , y + radius , x + width , y + height - radius ); // Right horizontal
52+
53+ // 2. Draw the 4 corners using pie slices converted into QUADS
54+ drawCorner (consumer , x + radius , y + radius , -HALF_PI ); // TOP_LEFT
55+ drawCorner (consumer , x + width - radius , y + radius , 0 ); // TOP_RIGHT
56+ drawCorner (consumer , x + radius , y + height - radius , Math .PI ); // BOTTOM_LEFT
57+ drawCorner (consumer , x + width - radius , y + height - radius , HALF_PI ); // BOTTOM_RIGHT
58+ }
59+
60+ /**
61+ * Appends 4 vertices to draw a standard rectangle (Quad).
62+ */
63+ private void addQuad (VertexConsumer consumer , float minX , float minY , float maxX , float maxY ) {
64+ consumer .addVertexWith2DPose (pose , minX , minY ).setColor (color );
65+ consumer .addVertexWith2DPose (pose , minX , maxY ).setColor (color );
66+ consumer .addVertexWith2DPose (pose , maxX , maxY ).setColor (color );
67+ consumer .addVertexWith2DPose (pose , maxX , minY ).setColor (color );
68+ }
69+
70+ /**
71+ * Draws a radial corner.
72+ * Since we are using QUADS, each "slice" of the pie is defined by 4 vertices:
73+ * the center, two points on the arc, and a duplicate of the center point to satisfy the Quad requirement.
74+ */
75+ private void drawCorner (VertexConsumer consumer , float centerX , float centerY , double startAngle ) {
76+ int segments = 16 ;
77+ double angleStep = HALF_PI / (float ) segments ;
78+
79+ for (int i = 0 ; i < segments ; i ++) {
80+ double angle1 = startAngle - angleStep * i ;
81+ double angle2 = startAngle - angleStep * (i + 1 );
82+
83+ float p1X = centerX + (float ) (Math .cos (angle1 ) * radius );
84+ float p1Y = centerY + (float ) (Math .sin (angle1 ) * radius );
85+
86+ float p2X = centerX + (float ) (Math .cos (angle2 ) * radius );
87+ float p2Y = centerY + (float ) (Math .sin (angle2 ) * radius );
88+
89+ // Emit 4 vertices for a Quad. The first and last are the same center point,
90+ // creating a triangle that fits the QUAD pipeline without bleeding.
91+ consumer .addVertexWith2DPose (pose , centerX , centerY ).setColor (color );
92+ consumer .addVertexWith2DPose (pose , p1X , p1Y ).setColor (color );
93+ consumer .addVertexWith2DPose (pose , p2X , p2Y ).setColor (color );
94+ consumer .addVertexWith2DPose (pose , centerX , centerY ).setColor (color );
95+ }
96+ }
97+
98+ private static ScreenRectangle getBounds (int x0 , int y0 , int x1 , int y1 , Matrix3x2f pose , ScreenRectangle scissorArea ) {
99+ ScreenRectangle screenRectangle = new ScreenRectangle (x0 , y0 , x1 - x0 , y1 - y0 ).transformMaxBounds (pose );
100+ return scissorArea != null ? scissorArea .intersection (screenRectangle ) : screenRectangle ;
101+ }
102+
103+ }
0 commit comments