shapes_rectangle_advanced.c 17 KB

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