Skip to content

Commit ad79d4a

Browse files
authored
[shapes] Add shapes_rectangle_advanced example implementing a DrawRectangleRoundedGradientH function (#4435)
* [rshapes] Add function * "[shapes] rectangle advanced: fix screen width and height to fit with other examples"
1 parent d15e583 commit ad79d4a

File tree

7 files changed

+809
-82
lines changed

7 files changed

+809
-82
lines changed

examples/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,8 @@ SHAPES = \
532532
shapes/shapes_logo_raylib_anim \
533533
shapes/shapes_rectangle_scaling \
534534
shapes/shapes_splines_drawing \
535-
shapes/shapes_top_down_lights
535+
shapes/shapes_top_down_lights \
536+
shapes/shapes_rectangle_advanced
536537

537538
TEXTURES = \
538539
textures/textures_background_scrolling \

examples/Makefile.Web

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,9 @@ shapes/shapes_splines_drawing: shapes/shapes_splines_drawing.c
696696
shapes/shapes_top_down_lights: shapes/shapes_top_down_lights.c
697697
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
698698

699+
shapes/shapes_rectangle_advanced: shapes/shapes_rectangle_advanced.c
700+
$(CC) -o $@$(EXT) $< $(CFLAGS) $(INCLUDE_PATHS) $(LDFLAGS) $(LDLIBS) -D$(PLATFORM)
701+
699702

700703
# Compile TEXTURES examples
701704
textures/textures_background_scrolling: textures/textures_background_scrolling.c

examples/README.md

Lines changed: 82 additions & 81 deletions
Large diffs are not rendered by default.
Lines changed: 330 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,330 @@
1+
#include "raylib.h"
2+
#include "rlgl.h"
3+
#include <math.h>
4+
5+
// Draw rectangle with rounded edges and horizontal gradient, with options to choose side of roundness
6+
// Adapted from both `DrawRectangleRounded` and `DrawRectangleGradientH`
7+
void DrawRectangleRoundedGradientH(Rectangle rec, float roundnessLeft, float roundnessRight, int segments, Color left, Color right)
8+
{
9+
// Neither side is rounded
10+
if ((roundnessLeft <= 0.0f && roundnessRight <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
11+
{
12+
DrawRectangleGradientEx(rec, left, left, right, right);
13+
return;
14+
}
15+
16+
if (roundnessLeft >= 1.0f) roundnessLeft = 1.0f;
17+
if (roundnessRight >= 1.0f) roundnessRight = 1.0f;
18+
19+
// Calculate corner radius both from right and left
20+
float recSize = rec.width > rec.height ? rec.height : rec.width;
21+
float radiusLeft = (recSize*roundnessLeft)/2;
22+
float radiusRight = (recSize*roundnessRight)/2;
23+
24+
if (radiusLeft <= 0.0f) radiusLeft = 0.0f;
25+
if (radiusRight <= 0.0f) radiusRight = 0.0f;
26+
27+
if (radiusRight <= 0.0f && radiusLeft <= 0.0f) return;
28+
29+
float stepLength = 90.0f/(float)segments;
30+
31+
/*
32+
Diagram Copied here for reference, original at `DrawRectangleRounded` source code
33+
34+
P0____________________P1
35+
/| |\
36+
/1| 2 |3\
37+
P7 /__|____________________|__\ P2
38+
| |P8 P9| |
39+
| 8 | 9 | 4 |
40+
| __|____________________|__ |
41+
P6 \ |P11 P10| / P3
42+
\7| 6 |5/
43+
\|____________________|/
44+
P5 P4
45+
*/
46+
47+
// Coordinates of the 12 points also apdated from `DrawRectangleRounded`
48+
const Vector2 point[12] = {
49+
// PO, P1, P2
50+
{(float)rec.x + radiusLeft, rec.y}, {(float)(rec.x + rec.width) - radiusRight, rec.y}, { rec.x + rec.width, (float)rec.y + radiusRight },
51+
// P3, P4
52+
{rec.x + rec.width, (float)(rec.y + rec.height) - radiusRight}, {(float)(rec.x + rec.width) - radiusRight, rec.y + rec.height},
53+
// P5, P6, P7
54+
{(float)rec.x + radiusLeft, rec.y + rec.height}, { rec.x, (float)(rec.y + rec.height) - radiusLeft}, {rec.x, (float)rec.y + radiusLeft},
55+
// P8, P9
56+
{(float)rec.x + radiusLeft, (float)rec.y + radiusLeft}, {(float)(rec.x + rec.width) - radiusRight, (float)rec.y + radiusRight},
57+
// P10, P11
58+
{(float)(rec.x + rec.width) - radiusRight, (float)(rec.y + rec.height) - radiusRight}, {(float)rec.x + radiusLeft, (float)(rec.y + rec.height) - radiusLeft}
59+
};
60+
61+
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
62+
const float angles[4] = { 180.0f, 270.0f, 0.0f, 90.0f };
63+
64+
#if defined(SUPPORT_QUADS_DRAW_MODE)
65+
rlSetTexture(GetShapesTexture().id);
66+
Rectangle shapeRect = GetShapesTextureRectangle();
67+
68+
rlBegin(RL_QUADS);
69+
// Draw all the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
70+
for (int k = 0; k < 4; ++k)
71+
{
72+
Color color;
73+
float radius;
74+
if (k == 0) color = left, radius = radiusLeft; // [1] Upper Left Corner
75+
if (k == 1) color = right, radius = radiusRight; // [3] Upper Right Corner
76+
if (k == 2) color = right, radius = radiusRight; // [5] Lower Right Corner
77+
if (k == 3) color = left, radius = radiusLeft; // [7] Lower Left Corner
78+
float angle = angles[k];
79+
const Vector2 center = centers[k];
80+
81+
for (int i = 0; i < segments/2; i++)
82+
{
83+
rlColor4ub(color.r, color.g, color.b, color.a);
84+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
85+
rlVertex2f(center.x, center.y);
86+
87+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
88+
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength*2))*radius, center.y + sinf(DEG2RAD*(angle + stepLength*2))*radius);
89+
90+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
91+
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
92+
93+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
94+
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
95+
96+
angle += (stepLength*2);
97+
}
98+
99+
// End one even segments
100+
if ( segments % 2)
101+
{
102+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
103+
rlVertex2f(center.x, center.y);
104+
105+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
106+
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
107+
108+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
109+
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
110+
111+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
112+
rlVertex2f(center.x, center.y);
113+
}
114+
}
115+
116+
//
117+
// Here we use the `Diagram` to guide ourselves to which point receives what color.
118+
//
119+
// By choosing the color correctly associated with a pointe the gradient effect
120+
// will naturally come from OpenGL interpolation.
121+
//
122+
123+
// [2] Upper Rectangle
124+
rlColor4ub(left.r, left.g, left.b, left.a);
125+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
126+
rlVertex2f(point[0].x, point[0].y);
127+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
128+
rlVertex2f(point[8].x, point[8].y);
129+
130+
rlColor4ub(right.r, right.g, right.b, right.a);
131+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
132+
rlVertex2f(point[9].x, point[9].y);
133+
134+
rlColor4ub(right.r, right.g, right.b, right.a);
135+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
136+
rlVertex2f(point[1].x, point[1].y);
137+
138+
// [4] Left Rectangle
139+
rlColor4ub(right.r, right.g, right.b, right.a);
140+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
141+
rlVertex2f(point[2].x, point[2].y);
142+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
143+
rlVertex2f(point[9].x, point[9].y);
144+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
145+
rlVertex2f(point[10].x, point[10].y);
146+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
147+
rlVertex2f(point[3].x, point[3].y);
148+
149+
// [6] Bottom Rectangle
150+
rlColor4ub(left.r, left.g, left.b, left.a);
151+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
152+
rlVertex2f(point[11].x, point[11].y);
153+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
154+
rlVertex2f(point[5].x, point[5].y);
155+
156+
rlColor4ub(right.r, right.g, right.b, right.a);
157+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
158+
rlVertex2f(point[4].x, point[4].y);
159+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
160+
rlVertex2f(point[10].x, point[10].y);
161+
162+
// [8] left Rectangle
163+
rlColor4ub(left.r, left.g, left.b, left.a);
164+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
165+
rlVertex2f(point[7].x, point[7].y);
166+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
167+
rlVertex2f(point[6].x, point[6].y);
168+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
169+
rlVertex2f(point[11].x, point[11].y);
170+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
171+
rlVertex2f(point[8].x, point[8].y);
172+
173+
// [9] Middle Rectangle
174+
rlColor4ub(left.r, left.g, left.b, left.a);
175+
rlTexCoord2f(shapeRect.x/texShapes.width, shapeRect.y/texShapes.height);
176+
rlVertex2f(point[8].x, point[8].y);
177+
rlTexCoord2f(shapeRect.x/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
178+
rlVertex2f(point[11].x, point[11].y);
179+
180+
rlColor4ub(right.r, right.g, right.b, right.a);
181+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, (shapeRect.y + shapeRect.height)/texShapes.height);
182+
rlVertex2f(point[10].x, point[10].y);
183+
rlTexCoord2f((shapeRect.x + shapeRect.width)/texShapes.width, shapeRect.y/texShapes.height);
184+
rlVertex2f(point[9].x, point[9].y);
185+
186+
rlEnd();
187+
rlSetTexture(0);
188+
#else
189+
190+
//
191+
// Here we use the `Diagram` to guide ourselves to which point receives what color.
192+
//
193+
// By choosing the color correctly associated with a pointe the gradient effect
194+
// will naturally come from OpenGL interpolation.
195+
// But this time instead of Quad, we think in triangles.
196+
//
197+
198+
rlBegin(RL_TRIANGLES);
199+
200+
// Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
201+
for (int k = 0; k < 4; ++k)
202+
{
203+
Color color;
204+
float radius;
205+
if (k == 0) color = left, radius = radiusLeft; // [1] Upper Left Corner
206+
if (k == 1) color = right, radius = radiusRight; // [3] Upper Right Corner
207+
if (k == 2) color = right, radius = radiusRight; // [5] Lower Right Corner
208+
if (k == 3) color = left, radius = radiusLeft; // [7] Lower Left Corner
209+
float angle = angles[k];
210+
const Vector2 center = centers[k];
211+
for (int i = 0; i < segments; i++)
212+
{
213+
rlColor4ub(color.r, color.g, color.b, color.a);
214+
rlVertex2f(center.x, center.y);
215+
rlVertex2f(center.x + cosf(DEG2RAD*(angle + stepLength))*radius, center.y + sinf(DEG2RAD*(angle + stepLength))*radius);
216+
rlVertex2f(center.x + cosf(DEG2RAD*angle)*radius, center.y + sinf(DEG2RAD*angle)*radius);
217+
angle += stepLength;
218+
}
219+
}
220+
221+
// [2] Upper Rectangle
222+
rlColor4ub(left.r, left.g, left.b, left.a);
223+
rlVertex2f(point[0].x, point[0].y);
224+
rlVertex2f(point[8].x, point[8].y);
225+
rlColor4ub(right.r, right.g, right.b, right.a);
226+
rlVertex2f(point[9].x, point[9].y);
227+
rlVertex2f(point[1].x, point[1].y);
228+
rlColor4ub(left.r, left.g, left.b, left.a);
229+
rlVertex2f(point[0].x, point[0].y);
230+
rlColor4ub(right.r, right.g, right.b, right.a);
231+
rlVertex2f(point[9].x, point[9].y);
232+
233+
// [4] Right Rectangle
234+
rlColor4ub(right.r, right.g, right.b, right.a);
235+
rlVertex2f(point[9].x, point[9].y);
236+
rlVertex2f(point[10].x, point[10].y);
237+
rlVertex2f(point[3].x, point[3].y);
238+
rlVertex2f(point[2].x, point[2].y);
239+
rlVertex2f(point[9].x, point[9].y);
240+
rlVertex2f(point[3].x, point[3].y);
241+
242+
// [6] Bottom Rectangle
243+
rlColor4ub(left.r, left.g, left.b, left.a);
244+
rlVertex2f(point[11].x, point[11].y);
245+
rlVertex2f(point[5].x, point[5].y);
246+
rlColor4ub(right.r, right.g, right.b, right.a);
247+
rlVertex2f(point[4].x, point[4].y);
248+
rlVertex2f(point[10].x, point[10].y);
249+
rlColor4ub(left.r, left.g, left.b, left.a);
250+
rlVertex2f(point[11].x, point[11].y);
251+
rlColor4ub(right.r, right.g, right.b, right.a);
252+
rlVertex2f(point[4].x, point[4].y);
253+
254+
// [8] Left Rectangle
255+
rlColor4ub(left.r, left.g, left.b, left.a);
256+
rlVertex2f(point[7].x, point[7].y);
257+
rlVertex2f(point[6].x, point[6].y);
258+
rlVertex2f(point[11].x, point[11].y);
259+
rlVertex2f(point[8].x, point[8].y);
260+
rlVertex2f(point[7].x, point[7].y);
261+
rlVertex2f(point[11].x, point[11].y);
262+
263+
// [9] Middle Rectangle
264+
rlColor4ub(left.r, left.g, left.b, left.a);
265+
rlVertex2f(point[8].x, point[8].y);
266+
rlVertex2f(point[11].x, point[11].y);
267+
rlColor4ub(right.r, right.g, right.b, right.a);
268+
rlVertex2f(point[10].x, point[10].y);
269+
rlVertex2f(point[9].x, point[9].y);
270+
rlColor4ub(left.r, left.g, left.b, left.a);
271+
rlVertex2f(point[8].x, point[8].y);
272+
rlColor4ub(right.r, right.g, right.b, right.a);
273+
rlVertex2f(point[10].x, point[10].y);
274+
rlEnd();
275+
#endif
276+
}
277+
278+
int main(int argc, char *argv[])
279+
{
280+
// Initialization
281+
//--------------------------------------------------------------------------------------
282+
const int screenWidth = 800;
283+
const int screenHeight = 450;
284+
InitWindow(screenWidth, screenHeight, "raylib [shapes] example - rectangle avanced");
285+
SetTargetFPS(60);
286+
//--------------------------------------------------------------------------------------
287+
288+
// Main game loop
289+
while (!WindowShouldClose()) // Detect window close button or ESC key
290+
{
291+
// Update rectangle bounds
292+
//----------------------------------------------------------------------------------
293+
double width = GetScreenWidth()/2.0, height = GetScreenHeight()/6.0;
294+
Rectangle rec = {
295+
GetScreenWidth() / 2.0 - width/2,
296+
GetScreenHeight() / 2.0 - (5)*(height/2),
297+
width, height
298+
};
299+
//--------------------------------------------------------------------------------------
300+
301+
// Draw
302+
//----------------------------------------------------------------------------------
303+
BeginDrawing();
304+
ClearBackground(RAYWHITE);
305+
306+
// Draw All Rectangles with different roundess for each side and different gradients
307+
DrawRectangleRoundedGradientH(rec, 0.8, 0.8, 36, BLUE, RED);
308+
309+
rec.y += rec.height + 1;
310+
DrawRectangleRoundedGradientH(rec, 0.5, 1.0, 36, RED, PINK);
311+
312+
rec.y += rec.height + 1;
313+
DrawRectangleRoundedGradientH(rec, 1.0, 0.5, 36, RED, BLUE);
314+
315+
rec.y += rec.height + 1;
316+
DrawRectangleRoundedGradientH(rec, 0.0, 1.0, 36, BLUE, BLACK);
317+
318+
rec.y += rec.height + 1;
319+
DrawRectangleRoundedGradientH(rec, 1.0, 0.0, 36, BLUE, PINK);
320+
EndDrawing();
321+
//--------------------------------------------------------------------------------------
322+
}
323+
324+
// De-Initialization
325+
//--------------------------------------------------------------------------------------
326+
CloseWindow(); // Close window and OpenGL context
327+
//--------------------------------------------------------------------------------------
328+
return 0;
329+
}
330+
6.68 KB
Loading

0 commit comments

Comments
 (0)