You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

348 regels
16 KiB

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