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.

330 lines
15 KiB

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