Wise&mystical  1.0
Project about Europe
Loading...
Searching...
No Matches
rshapes.c
Go to the documentation of this file.
1
48#include "raylib.h" // Declares module functions
49
50// Check if config flags have been externally provided on compilation line
51#if !defined(EXTERNAL_CONFIG_FLAGS)
52 #include "config.h" // Defines module configuration flags
53#endif
54
55#if defined(SUPPORT_MODULE_RSHAPES)
56
57#include "rlgl.h" // OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
58
59#include <math.h> // Required for: sinf(), asinf(), cosf(), acosf(), sqrtf(), fabsf()
60#include <float.h> // Required for: FLT_EPSILON
61
62//----------------------------------------------------------------------------------
63// Defines and Macros
64//----------------------------------------------------------------------------------
65// Error rate to calculate how many segments we need to draw a smooth circle,
66// taken from https://stackoverflow.com/a/2244088
67#ifndef SMOOTH_CIRCLE_ERROR_RATE
68 #define SMOOTH_CIRCLE_ERROR_RATE 0.5f // Circle error rate
69#endif
70#ifndef BEZIER_LINE_DIVISIONS
71 #define BEZIER_LINE_DIVISIONS 24 // Bezier line divisions
72#endif
73
74
75//----------------------------------------------------------------------------------
76// Types and Structures Definition
77//----------------------------------------------------------------------------------
78// Not here...
79
80//----------------------------------------------------------------------------------
81// Global Variables Definition
82//----------------------------------------------------------------------------------
83Texture2D texShapes = { 1, 1, 1, 1, 7 }; // Texture used on shapes drawing (usually a white pixel)
84Rectangle texShapesRec = { 0.0f, 0.0f, 1.0f, 1.0f }; // Texture source rectangle used on shapes drawing
85
86//----------------------------------------------------------------------------------
87// Module specific Functions Declaration
88//----------------------------------------------------------------------------------
89static float EaseCubicInOut(float t, float b, float c, float d); // Cubic easing
90
91//----------------------------------------------------------------------------------
92// Module Functions Definition
93//----------------------------------------------------------------------------------
94
95// Set texture and rectangle to be used on shapes drawing
96// NOTE: It can be useful when using basic shapes and one single font,
97// defining a font char white rectangle would allow drawing everything in a single draw call
99{
100 texShapes = texture;
101 texShapesRec = source;
102}
103
104// Draw a pixel
105void DrawPixel(int posX, int posY, Color color)
106{
108 rlColor4ub(color.r, color.g, color.b, color.a);
109 rlVertex2i(posX, posY);
110 rlVertex2i(posX + 1, posY + 1);
111 rlEnd();
112}
113
114// Draw a pixel (Vector version)
115void DrawPixelV(Vector2 position, Color color)
116{
118 rlColor4ub(color.r, color.g, color.b, color.a);
119 rlVertex2f(position.x, position.y);
120 rlVertex2f(position.x + 1.0f, position.y + 1.0f);
121 rlEnd();
122}
123
124// Draw a line
125void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
126{
128 rlColor4ub(color.r, color.g, color.b, color.a);
129 rlVertex2i(startPosX, startPosY);
130 rlVertex2i(endPosX, endPosY);
131 rlEnd();
132}
133
134// Draw a line (Vector version)
135void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
136{
138 rlColor4ub(color.r, color.g, color.b, color.a);
139 rlVertex2f(startPos.x, startPos.y);
140 rlVertex2f(endPos.x, endPos.y);
141 rlEnd();
142}
143
144// Draw a line defining thickness
145void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
146{
147 Vector2 delta = { endPos.x - startPos.x, endPos.y - startPos.y };
148 float length = sqrtf(delta.x*delta.x + delta.y*delta.y);
149
150 if ((length > 0) && (thick > 0))
151 {
152 float scale = thick/(2*length);
153 Vector2 radius = { -scale*delta.y, scale*delta.x };
154 Vector2 strip[4] = {
155 { startPos.x - radius.x, startPos.y - radius.y },
156 { startPos.x + radius.x, startPos.y + radius.y },
157 { endPos.x - radius.x, endPos.y - radius.y },
158 { endPos.x + radius.x, endPos.y + radius.y }
159 };
160
161 DrawTriangleStrip(strip, 4, color);
162 }
163}
164
165// Draw line using cubic-bezier curves in-out
166void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
167{
168 Vector2 previous = startPos;
169 Vector2 current = { 0 };
170
171 for (int i = 1; i <= BEZIER_LINE_DIVISIONS; i++)
172 {
173 // Cubic easing in-out
174 // NOTE: Easing is calculated only for y position value
175 current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)BEZIER_LINE_DIVISIONS);
176 current.x = previous.x + (endPos.x - startPos.x)/ (float)BEZIER_LINE_DIVISIONS;
177
178 DrawLineEx(previous, current, thick, color);
179
180 previous = current;
181 }
182}
183
184// Draw line using quadratic bezier curves with a control point
185void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
186{
187 const float step = 1.0f/BEZIER_LINE_DIVISIONS;
188
189 Vector2 previous = startPos;
190 Vector2 current = { 0 };
191 float t = 0.0f;
192
193 for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
194 {
195 t = step*i;
196 float a = powf(1 - t, 2);
197 float b = 2*(1 - t)*t;
198 float c = powf(t, 2);
199
200 // NOTE: The easing functions aren't suitable here because they don't take a control point
201 current.y = a*startPos.y + b*controlPos.y + c*endPos.y;
202 current.x = a*startPos.x + b*controlPos.x + c*endPos.x;
203
204 DrawLineEx(previous, current, thick, color);
205
206 previous = current;
207 }
208}
209
210// Draw line using cubic bezier curves with 2 control points
211void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
212{
213 const float step = 1.0f/BEZIER_LINE_DIVISIONS;
214
215 Vector2 previous = startPos;
216 Vector2 current = { 0 };
217 float t = 0.0f;
218
219 for (int i = 0; i <= BEZIER_LINE_DIVISIONS; i++)
220 {
221 t = step*i;
222 float a = powf(1 - t, 3);
223 float b = 3*powf(1 - t, 2)*t;
224 float c = 3*(1-t)*powf(t, 2);
225 float d = powf(t, 3);
226
227 current.y = a*startPos.y + b*startControlPos.y + c*endControlPos.y + d*endPos.y;
228 current.x = a*startPos.x + b*startControlPos.x + c*endControlPos.x + d*endPos.x;
229
230 DrawLineEx(previous, current, thick, color);
231
232 previous = current;
233 }
234}
235
236// Draw lines sequence
237void DrawLineStrip(Vector2 *points, int pointCount, Color color)
238{
239 if (pointCount >= 2)
240 {
241 rlCheckRenderBatchLimit(pointCount);
242
244 rlColor4ub(color.r, color.g, color.b, color.a);
245
246 for (int i = 0; i < pointCount - 1; i++)
247 {
248 rlVertex2f(points[i].x, points[i].y);
249 rlVertex2f(points[i + 1].x, points[i + 1].y);
250 }
251 rlEnd();
252 }
253}
254
255// Draw a color-filled circle
256void DrawCircle(int centerX, int centerY, float radius, Color color)
257{
258 DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
259}
260
261// Draw a piece of a circle
262void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
263{
264 if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero
265
266 // Function expects (endAngle > startAngle)
267 if (endAngle < startAngle)
268 {
269 // Swap values
270 float tmp = startAngle;
271 startAngle = endAngle;
272 endAngle = tmp;
273 }
274
275 int minSegments = (int)ceilf((endAngle - startAngle)/90);
276
277 if (segments < minSegments)
278 {
279 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
280 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
281 segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
282
283 if (segments <= 0) segments = minSegments;
284 }
285
286 float stepLength = (endAngle - startAngle)/(float)segments;
287 float angle = startAngle;
288
289#if defined(SUPPORT_QUADS_DRAW_MODE)
290 rlCheckRenderBatchLimit(4*segments/2);
291
293
295 // NOTE: Every QUAD actually represents two segments
296 for (int i = 0; i < segments/2; i++)
297 {
298 rlColor4ub(color.r, color.g, color.b, color.a);
299
301 rlVertex2f(center.x, center.y);
302
304 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
305
307 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
308
310 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
311
312 angle += (stepLength*2);
313 }
314
315 // NOTE: In case number of segments is odd, we add one last piece to the cake
316 if (segments%2)
317 {
318 rlColor4ub(color.r, color.g, color.b, color.a);
319
321 rlVertex2f(center.x, center.y);
322
324 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
325
327 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
328
330 rlVertex2f(center.x, center.y);
331 }
332 rlEnd();
333
334 rlSetTexture(0);
335#else
336 rlCheckRenderBatchLimit(3*segments);
337
339 for (int i = 0; i < segments; i++)
340 {
341 rlColor4ub(color.r, color.g, color.b, color.a);
342
343 rlVertex2f(center.x, center.y);
344 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
345 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
346
347 angle += stepLength;
348 }
349 rlEnd();
350#endif
351}
352
353// Draw a piece of a circle outlines
354void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
355{
356 if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero issue
357
358 // Function expects (endAngle > startAngle)
359 if (endAngle < startAngle)
360 {
361 // Swap values
362 float tmp = startAngle;
363 startAngle = endAngle;
364 endAngle = tmp;
365 }
366
367 int minSegments = (int)ceilf((endAngle - startAngle)/90);
368
369 if (segments < minSegments)
370 {
371 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
372 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
373 segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
374
375 if (segments <= 0) segments = minSegments;
376 }
377
378 float stepLength = (endAngle - startAngle)/(float)segments;
379 float angle = startAngle;
380
381 // Hide the cap lines when the circle is full
382 bool showCapLines = true;
383 int limit = 2*(segments + 2);
384 if ((int)(endAngle - startAngle)%360 == 0) { limit = 2*segments; showCapLines = false; }
385
387
389 if (showCapLines)
390 {
391 rlColor4ub(color.r, color.g, color.b, color.a);
392 rlVertex2f(center.x, center.y);
393 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
394 }
395
396 for (int i = 0; i < segments; i++)
397 {
398 rlColor4ub(color.r, color.g, color.b, color.a);
399
400 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
401 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
402
403 angle += stepLength;
404 }
405
406 if (showCapLines)
407 {
408 rlColor4ub(color.r, color.g, color.b, color.a);
409 rlVertex2f(center.x, center.y);
410 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
411 }
412 rlEnd();
413}
414
415// Draw a gradient-filled circle
416// NOTE: Gradient goes from center (color1) to border (color2)
417void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
418{
420
422 for (int i = 0; i < 360; i += 10)
423 {
424 rlColor4ub(color1.r, color1.g, color1.b, color1.a);
425 rlVertex2f((float)centerX, (float)centerY);
426 rlColor4ub(color2.r, color2.g, color2.b, color2.a);
427 rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radius, (float)centerY + cosf(DEG2RAD*i)*radius);
428 rlColor4ub(color2.r, color2.g, color2.b, color2.a);
429 rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radius, (float)centerY + cosf(DEG2RAD*(i + 10))*radius);
430 }
431 rlEnd();
432}
433
434// Draw a color-filled circle (Vector version)
435// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
436void DrawCircleV(Vector2 center, float radius, Color color)
437{
438 DrawCircleSector(center, radius, 0, 360, 36, color);
439}
440
441// Draw circle outline
442void DrawCircleLines(int centerX, int centerY, float radius, Color color)
443{
445
447 rlColor4ub(color.r, color.g, color.b, color.a);
448
449 // NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
450 for (int i = 0; i < 360; i += 10)
451 {
452 rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
453 rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
454 }
455 rlEnd();
456}
457
458// Draw ellipse
459void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
460{
462
464 for (int i = 0; i < 360; i += 10)
465 {
466 rlColor4ub(color.r, color.g, color.b, color.a);
467 rlVertex2f((float)centerX, (float)centerY);
468 rlVertex2f((float)centerX + sinf(DEG2RAD*i)*radiusH, (float)centerY + cosf(DEG2RAD*i)*radiusV);
469 rlVertex2f((float)centerX + sinf(DEG2RAD*(i + 10))*radiusH, (float)centerY + cosf(DEG2RAD*(i + 10))*radiusV);
470 }
471 rlEnd();
472}
473
474// Draw ellipse outline
475void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
476{
478
480 for (int i = 0; i < 360; i += 10)
481 {
482 rlColor4ub(color.r, color.g, color.b, color.a);
483 rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
484 rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
485 }
486 rlEnd();
487}
488
489// Draw ring
490void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
491{
492 if (startAngle == endAngle) return;
493
494 // Function expects (outerRadius > innerRadius)
495 if (outerRadius < innerRadius)
496 {
497 float tmp = outerRadius;
498 outerRadius = innerRadius;
499 innerRadius = tmp;
500
501 if (outerRadius <= 0.0f) outerRadius = 0.1f;
502 }
503
504 // Function expects (endAngle > startAngle)
505 if (endAngle < startAngle)
506 {
507 // Swap values
508 float tmp = startAngle;
509 startAngle = endAngle;
510 endAngle = tmp;
511 }
512
513 int minSegments = (int)ceilf((endAngle - startAngle)/90);
514
515 if (segments < minSegments)
516 {
517 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
518 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
519 segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
520
521 if (segments <= 0) segments = minSegments;
522 }
523
524 // Not a ring
525 if (innerRadius <= 0.0f)
526 {
527 DrawCircleSector(center, outerRadius, startAngle, endAngle, segments, color);
528 return;
529 }
530
531 float stepLength = (endAngle - startAngle)/(float)segments;
532 float angle = startAngle;
533
534#if defined(SUPPORT_QUADS_DRAW_MODE)
535 rlCheckRenderBatchLimit(4*segments);
536
538
540 for (int i = 0; i < segments; i++)
541 {
542 rlColor4ub(color.r, color.g, color.b, color.a);
543
545 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
546
548 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
549
551 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
552
554 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
555
556 angle += stepLength;
557 }
558 rlEnd();
559
560 rlSetTexture(0);
561#else
562 rlCheckRenderBatchLimit(6*segments);
563
565 for (int i = 0; i < segments; i++)
566 {
567 rlColor4ub(color.r, color.g, color.b, color.a);
568
569 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
570 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
571 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
572
573 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
574 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
575 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
576
577 angle += stepLength;
578 }
579 rlEnd();
580#endif
581}
582
583// Draw ring outline
584void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
585{
586 if (startAngle == endAngle) return;
587
588 // Function expects (outerRadius > innerRadius)
589 if (outerRadius < innerRadius)
590 {
591 float tmp = outerRadius;
592 outerRadius = innerRadius;
593 innerRadius = tmp;
594
595 if (outerRadius <= 0.0f) outerRadius = 0.1f;
596 }
597
598 // Function expects (endAngle > startAngle)
599 if (endAngle < startAngle)
600 {
601 // Swap values
602 float tmp = startAngle;
603 startAngle = endAngle;
604 endAngle = tmp;
605 }
606
607 int minSegments = (int)ceilf((endAngle - startAngle)/90);
608
609 if (segments < minSegments)
610 {
611 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
612 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
613 segments = (int)((endAngle - startAngle)*ceilf(2*PI/th)/360);
614
615 if (segments <= 0) segments = minSegments;
616 }
617
618 if (innerRadius <= 0.0f)
619 {
620 DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, segments, color);
621 return;
622 }
623
624 float stepLength = (endAngle - startAngle)/(float)segments;
625 float angle = startAngle;
626
627 bool showCapLines = true;
628 int limit = 4*(segments + 1);
629 if ((int)(endAngle - startAngle)%360 == 0) { limit = 4*segments; showCapLines = false; }
630
632
634 if (showCapLines)
635 {
636 rlColor4ub(color.r, color.g, color.b, color.a);
637 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
638 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
639 }
640
641 for (int i = 0; i < segments; i++)
642 {
643 rlColor4ub(color.r, color.g, color.b, color.a);
644
645 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
646 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
647
648 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
649 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
650
651 angle += stepLength;
652 }
653
654 if (showCapLines)
655 {
656 rlColor4ub(color.r, color.g, color.b, color.a);
657 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
658 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
659 }
660 rlEnd();
661}
662
663// Draw a color-filled rectangle
664void DrawRectangle(int posX, int posY, int width, int height, Color color)
665{
666 DrawRectangleV((Vector2){ (float)posX, (float)posY }, (Vector2){ (float)width, (float)height }, color);
667}
668
669// Draw a color-filled rectangle (Vector version)
670// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
671void DrawRectangleV(Vector2 position, Vector2 size, Color color)
672{
673 DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
674}
675
676// Draw a color-filled rectangle
678{
679 DrawRectanglePro(rec, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
680}
681
682// Draw a color-filled rectangle with pro parameters
683void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
684{
685 Vector2 topLeft = { 0 };
686 Vector2 topRight = { 0 };
687 Vector2 bottomLeft = { 0 };
688 Vector2 bottomRight = { 0 };
689
690 // Only calculate rotation if needed
691 if (rotation == 0.0f)
692 {
693 float x = rec.x - origin.x;
694 float y = rec.y - origin.y;
695 topLeft = (Vector2){ x, y };
696 topRight = (Vector2){ x + rec.width, y };
697 bottomLeft = (Vector2){ x, y + rec.height };
698 bottomRight = (Vector2){ x + rec.width, y + rec.height };
699 }
700 else
701 {
702 float sinRotation = sinf(rotation*DEG2RAD);
703 float cosRotation = cosf(rotation*DEG2RAD);
704 float x = rec.x;
705 float y = rec.y;
706 float dx = -origin.x;
707 float dy = -origin.y;
708
709 topLeft.x = x + dx*cosRotation - dy*sinRotation;
710 topLeft.y = y + dx*sinRotation + dy*cosRotation;
711
712 topRight.x = x + (dx + rec.width)*cosRotation - dy*sinRotation;
713 topRight.y = y + (dx + rec.width)*sinRotation + dy*cosRotation;
714
715 bottomLeft.x = x + dx*cosRotation - (dy + rec.height)*sinRotation;
716 bottomLeft.y = y + dx*sinRotation + (dy + rec.height)*cosRotation;
717
718 bottomRight.x = x + (dx + rec.width)*cosRotation - (dy + rec.height)*sinRotation;
719 bottomRight.y = y + (dx + rec.width)*sinRotation + (dy + rec.height)*cosRotation;
720 }
721
722#if defined(SUPPORT_QUADS_DRAW_MODE)
724
726
728
729 rlNormal3f(0.0f, 0.0f, 1.0f);
730 rlColor4ub(color.r, color.g, color.b, color.a);
731
733 rlVertex2f(topLeft.x, topLeft.y);
734
736 rlVertex2f(bottomLeft.x, bottomLeft.y);
737
739 rlVertex2f(bottomRight.x, bottomRight.y);
740
742 rlVertex2f(topRight.x, topRight.y);
743
744 rlEnd();
745
746 rlSetTexture(0);
747#else
749
751
752 rlColor4ub(color.r, color.g, color.b, color.a);
753
754 rlVertex2f(topLeft.x, topLeft.y);
755 rlVertex2f(bottomLeft.x, bottomLeft.y);
756 rlVertex2f(topRight.x, topRight.y);
757
758 rlVertex2f(topRight.x, topRight.y);
759 rlVertex2f(bottomLeft.x, bottomLeft.y);
760 rlVertex2f(bottomRight.x, bottomRight.y);
761
762 rlEnd();
763#endif
764}
765
766// Draw a vertical-gradient-filled rectangle
767// NOTE: Gradient goes from bottom (color1) to top (color2)
768void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
769{
770 DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1);
771}
772
773// Draw a horizontal-gradient-filled rectangle
774// NOTE: Gradient goes from bottom (color1) to top (color2)
775void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
776{
777 DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2);
778}
779
780// Draw a gradient-filled rectangle
781// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
782void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
783{
785
787
788 rlPushMatrix();
790 rlNormal3f(0.0f, 0.0f, 1.0f);
791
792 // NOTE: Default raylib font character 95 is a white square
793 rlColor4ub(col1.r, col1.g, col1.b, col1.a);
795 rlVertex2f(rec.x, rec.y);
796
797 rlColor4ub(col2.r, col2.g, col2.b, col2.a);
799 rlVertex2f(rec.x, rec.y + rec.height);
800
801 rlColor4ub(col3.r, col3.g, col3.b, col3.a);
803 rlVertex2f(rec.x + rec.width, rec.y + rec.height);
804
805 rlColor4ub(col4.r, col4.g, col4.b, col4.a);
807 rlVertex2f(rec.x + rec.width, rec.y);
808 rlEnd();
809 rlPopMatrix();
810
811 rlSetTexture(0);
812}
813
814// Draw rectangle outline
815// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues
816void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
817{
818#if defined(SUPPORT_QUADS_DRAW_MODE)
819 DrawRectangle(posX, posY, width, 1, color);
820 DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
821 DrawRectangle(posX, posY + height - 1, width, 1, color);
822 DrawRectangle(posX, posY + 1, 1, height - 2, color);
823#else
825 rlColor4ub(color.r, color.g, color.b, color.a);
826 rlVertex2i(posX + 1, posY + 1);
827 rlVertex2i(posX + width, posY + 1);
828
829 rlVertex2i(posX + width, posY + 1);
830 rlVertex2i(posX + width, posY + height);
831
832 rlVertex2i(posX + width, posY + height);
833 rlVertex2i(posX + 1, posY + height);
834
835 rlVertex2i(posX + 1, posY + height);
836 rlVertex2i(posX + 1, posY + 1);
837 rlEnd();
838#endif
839}
840
841// Draw rectangle outline with extended parameters
842void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
843{
844 if ((lineThick > rec.width) || (lineThick > rec.height))
845 {
846 if (rec.width > rec.height) lineThick = rec.height/2;
847 else if (rec.width < rec.height) lineThick = rec.width/2;
848 }
849
850 // When rec = { x, y, 8.0f, 6.0f } and lineThick = 2, the following
851 // four rectangles are drawn ([T]op, [B]ottom, [L]eft, [R]ight):
852 //
853 // TTTTTTTT
854 // TTTTTTTT
855 // LL RR
856 // LL RR
857 // BBBBBBBB
858 // BBBBBBBB
859 //
860
861 Rectangle top = { rec.x, rec.y, rec.width, lineThick };
862 Rectangle bottom = { rec.x, rec.y - lineThick + rec.height, rec.width, lineThick };
863 Rectangle left = { rec.x, rec.y + lineThick, lineThick, rec.height - lineThick*2.0f };
864 Rectangle right = { rec.x - lineThick + rec.width, rec.y + lineThick, lineThick, rec.height - lineThick*2.0f };
865
866 DrawRectangleRec(top, color);
867 DrawRectangleRec(bottom, color);
868 DrawRectangleRec(left, color);
869 DrawRectangleRec(right, color);
870}
871
872// Draw rectangle with rounded edges
873void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
874{
875 // Not a rounded rectangle
876 if ((roundness <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
877 {
878 DrawRectangleRec(rec, color);
879 return;
880 }
881
882 if (roundness >= 1.0f) roundness = 1.0f;
883
884 // Calculate corner radius
885 float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
886 if (radius <= 0.0f) return;
887
888 // Calculate number of segments to use for the corners
889 if (segments < 4)
890 {
891 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
892 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
893 segments = (int)(ceilf(2*PI/th)/4.0f);
894 if (segments <= 0) segments = 4;
895 }
896
897 float stepLength = 90.0f/(float)segments;
898
899 /*
900 Quick sketch to make sense of all of this,
901 there are 9 parts to draw, also mark the 12 points we'll use
902
903 P0____________________P1
904 /| |\
905 /1| 2 |3\
906 P7 /__|____________________|__\ P2
907 | |P8 P9| |
908 | 8 | 9 | 4 |
909 | __|____________________|__ |
910 P6 \ |P11 P10| / P3
911 \7| 6 |5/
912 \|____________________|/
913 P5 P4
914 */
915 // Coordinates of the 12 points that define the rounded rect
916 const Vector2 point[12] = {
917 {(float)rec.x + radius, rec.y}, {(float)(rec.x + rec.width) - radius, rec.y}, { rec.x + rec.width, (float)rec.y + radius }, // PO, P1, P2
918 {rec.x + rec.width, (float)(rec.y + rec.height) - radius}, {(float)(rec.x + rec.width) - radius, rec.y + rec.height}, // P3, P4
919 {(float)rec.x + radius, rec.y + rec.height}, { rec.x, (float)(rec.y + rec.height) - radius}, {rec.x, (float)rec.y + radius}, // P5, P6, P7
920 {(float)rec.x + radius, (float)rec.y + radius}, {(float)(rec.x + rec.width) - radius, (float)rec.y + radius}, // P8, P9
921 {(float)(rec.x + rec.width) - radius, (float)(rec.y + rec.height) - radius}, {(float)rec.x + radius, (float)(rec.y + rec.height) - radius} // P10, P11
922 };
923
924 const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
925 const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
926
927#if defined(SUPPORT_QUADS_DRAW_MODE)
928 rlCheckRenderBatchLimit(16*segments/2 + 5*4);
929
931
933 // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
934 for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
935 {
936 float angle = angles[k];
937 const Vector2 center = centers[k];
938
939 // NOTE: Every QUAD actually represents two segments
940 for (int i = 0; i < segments/2; i++)
941 {
942 rlColor4ub(color.r, color.g, color.b, color.a);
944 rlVertex2f(center.x, center.y);
946 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
948 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
950 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
951 angle += (stepLength*2);
952 }
953
954 // NOTE: In case number of segments is odd, we add one last piece to the cake
955 if (segments%2)
956 {
957 rlColor4ub(color.r, color.g, color.b, color.a);
959 rlVertex2f(center.x, center.y);
961 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
963 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
965 rlVertex2f(center.x, center.y);
966 }
967 }
968
969 // [2] Upper Rectangle
970 rlColor4ub(color.r, color.g, color.b, color.a);
972 rlVertex2f(point[0].x, point[0].y);
974 rlVertex2f(point[8].x, point[8].y);
976 rlVertex2f(point[9].x, point[9].y);
978 rlVertex2f(point[1].x, point[1].y);
979
980 // [4] Right Rectangle
981 rlColor4ub(color.r, color.g, color.b, color.a);
983 rlVertex2f(point[2].x, point[2].y);
985 rlVertex2f(point[9].x, point[9].y);
987 rlVertex2f(point[10].x, point[10].y);
989 rlVertex2f(point[3].x, point[3].y);
990
991 // [6] Bottom Rectangle
992 rlColor4ub(color.r, color.g, color.b, color.a);
994 rlVertex2f(point[11].x, point[11].y);
996 rlVertex2f(point[5].x, point[5].y);
998 rlVertex2f(point[4].x, point[4].y);
1000 rlVertex2f(point[10].x, point[10].y);
1001
1002 // [8] Left Rectangle
1003 rlColor4ub(color.r, color.g, color.b, color.a);
1005 rlVertex2f(point[7].x, point[7].y);
1007 rlVertex2f(point[6].x, point[6].y);
1009 rlVertex2f(point[11].x, point[11].y);
1011 rlVertex2f(point[8].x, point[8].y);
1012
1013 // [9] Middle Rectangle
1014 rlColor4ub(color.r, color.g, color.b, color.a);
1016 rlVertex2f(point[8].x, point[8].y);
1018 rlVertex2f(point[11].x, point[11].y);
1020 rlVertex2f(point[10].x, point[10].y);
1022 rlVertex2f(point[9].x, point[9].y);
1023
1024 rlEnd();
1025 rlSetTexture(0);
1026#else
1027 rlCheckRenderBatchLimit(12*segments + 5*6); // 4 corners with 3 vertices per segment + 5 rectangles with 6 vertices each
1028
1030
1031 // Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
1032 for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1033 {
1034 float angle = angles[k];
1035 const Vector2 center = centers[k];
1036 for (int i = 0; i < segments; i++)
1037 {
1038 rlColor4ub(color.r, color.g, color.b, color.a);
1039 rlVertex2f(center.x, center.y);
1040 rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
1041 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
1042 angle += stepLength;
1043 }
1044 }
1045
1046 // [2] Upper Rectangle
1047 rlColor4ub(color.r, color.g, color.b, color.a);
1048 rlVertex2f(point[0].x, point[0].y);
1049 rlVertex2f(point[8].x, point[8].y);
1050 rlVertex2f(point[9].x, point[9].y);
1051 rlVertex2f(point[1].x, point[1].y);
1052 rlVertex2f(point[0].x, point[0].y);
1053 rlVertex2f(point[9].x, point[9].y);
1054
1055 // [4] Right Rectangle
1056 rlColor4ub(color.r, color.g, color.b, color.a);
1057 rlVertex2f(point[9].x, point[9].y);
1058 rlVertex2f(point[10].x, point[10].y);
1059 rlVertex2f(point[3].x, point[3].y);
1060 rlVertex2f(point[2].x, point[2].y);
1061 rlVertex2f(point[9].x, point[9].y);
1062 rlVertex2f(point[3].x, point[3].y);
1063
1064 // [6] Bottom Rectangle
1065 rlColor4ub(color.r, color.g, color.b, color.a);
1066 rlVertex2f(point[11].x, point[11].y);
1067 rlVertex2f(point[5].x, point[5].y);
1068 rlVertex2f(point[4].x, point[4].y);
1069 rlVertex2f(point[10].x, point[10].y);
1070 rlVertex2f(point[11].x, point[11].y);
1071 rlVertex2f(point[4].x, point[4].y);
1072
1073 // [8] Left Rectangle
1074 rlColor4ub(color.r, color.g, color.b, color.a);
1075 rlVertex2f(point[7].x, point[7].y);
1076 rlVertex2f(point[6].x, point[6].y);
1077 rlVertex2f(point[11].x, point[11].y);
1078 rlVertex2f(point[8].x, point[8].y);
1079 rlVertex2f(point[7].x, point[7].y);
1080 rlVertex2f(point[11].x, point[11].y);
1081
1082 // [9] Middle Rectangle
1083 rlColor4ub(color.r, color.g, color.b, color.a);
1084 rlVertex2f(point[8].x, point[8].y);
1085 rlVertex2f(point[11].x, point[11].y);
1086 rlVertex2f(point[10].x, point[10].y);
1087 rlVertex2f(point[9].x, point[9].y);
1088 rlVertex2f(point[8].x, point[8].y);
1089 rlVertex2f(point[10].x, point[10].y);
1090 rlEnd();
1091#endif
1092}
1093
1094// Draw rectangle with rounded edges outline
1095void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color)
1096{
1097 if (lineThick < 0) lineThick = 0;
1098
1099 // Not a rounded rectangle
1100 if (roundness <= 0.0f)
1101 {
1102 DrawRectangleLinesEx((Rectangle){rec.x-lineThick, rec.y-lineThick, rec.width+2*lineThick, rec.height+2*lineThick}, lineThick, color);
1103 return;
1104 }
1105
1106 if (roundness >= 1.0f) roundness = 1.0f;
1107
1108 // Calculate corner radius
1109 float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
1110 if (radius <= 0.0f) return;
1111
1112 // Calculate number of segments to use for the corners
1113 if (segments < 4)
1114 {
1115 // Calculate the maximum angle between segments based on the error rate (usually 0.5f)
1116 float th = acosf(2*powf(1 - SMOOTH_CIRCLE_ERROR_RATE/radius, 2) - 1);
1117 segments = (int)(ceilf(2*PI/th)/2.0f);
1118 if (segments <= 0) segments = 4;
1119 }
1120
1121 float stepLength = 90.0f/(float)segments;
1122 const float outerRadius = radius + lineThick, innerRadius = radius;
1123
1124 /*
1125 Quick sketch to make sense of all of this,
1126 marks the 16 + 4(corner centers P16-19) points we'll use
1127
1128 P0 ================== P1
1129 // P8 P9 \\
1130 // \\
1131 P7 // P15 P10 \\ P2
1132 || *P16 P17* ||
1133 || ||
1134 || P14 P11 ||
1135 P6 \\ *P19 P18* // P3
1136 \\ //
1137 \\ P13 P12 //
1138 P5 ================== P4
1139 */
1140 const Vector2 point[16] = {
1141 {(float)rec.x + innerRadius, rec.y - lineThick}, {(float)(rec.x + rec.width) - innerRadius, rec.y - lineThick}, { rec.x + rec.width + lineThick, (float)rec.y + innerRadius }, // PO, P1, P2
1142 {rec.x + rec.width + lineThick, (float)(rec.y + rec.height) - innerRadius}, {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height + lineThick}, // P3, P4
1143 {(float)rec.x + innerRadius, rec.y + rec.height + lineThick}, { rec.x - lineThick, (float)(rec.y + rec.height) - innerRadius}, {rec.x - lineThick, (float)rec.y + innerRadius}, // P5, P6, P7
1144 {(float)rec.x + innerRadius, rec.y}, {(float)(rec.x + rec.width) - innerRadius, rec.y}, // P8, P9
1145 { rec.x + rec.width, (float)rec.y + innerRadius }, {rec.x + rec.width, (float)(rec.y + rec.height) - innerRadius}, // P10, P11
1146 {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height}, {(float)rec.x + innerRadius, rec.y + rec.height}, // P12, P13
1147 { rec.x, (float)(rec.y + rec.height) - innerRadius}, {rec.x, (float)rec.y + innerRadius} // P14, P15
1148 };
1149
1150 const Vector2 centers[4] = {
1151 {(float)rec.x + innerRadius, (float)rec.y + innerRadius}, {(float)(rec.x + rec.width) - innerRadius, (float)rec.y + innerRadius}, // P16, P17
1152 {(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
1153 };
1154
1155 const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
1156
1157 if (lineThick > 1)
1158 {
1159#if defined(SUPPORT_QUADS_DRAW_MODE)
1160 rlCheckRenderBatchLimit(4*4*segments + 4*4); // 4 corners with 4 vertices for each segment + 4 rectangles with 4 vertices each
1161
1163
1165
1166 // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1167 for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1168 {
1169 float angle = angles[k];
1170 const Vector2 center = centers[k];
1171 for (int i = 0; i < segments; i++)
1172 {
1173 rlColor4ub(color.r, color.g, color.b, color.a);
1175 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
1177 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1179 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1181 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1182
1183 angle += stepLength;
1184 }
1185 }
1186
1187 // Upper rectangle
1188 rlColor4ub(color.r, color.g, color.b, color.a);
1190 rlVertex2f(point[0].x, point[0].y);
1192 rlVertex2f(point[8].x, point[8].y);
1194 rlVertex2f(point[9].x, point[9].y);
1196 rlVertex2f(point[1].x, point[1].y);
1197
1198 // Right rectangle
1199 rlColor4ub(color.r, color.g, color.b, color.a);
1201 rlVertex2f(point[2].x, point[2].y);
1203 rlVertex2f(point[10].x, point[10].y);
1205 rlVertex2f(point[11].x, point[11].y);
1207 rlVertex2f(point[3].x, point[3].y);
1208
1209 // Lower rectangle
1210 rlColor4ub(color.r, color.g, color.b, color.a);
1212 rlVertex2f(point[13].x, point[13].y);
1214 rlVertex2f(point[5].x, point[5].y);
1216 rlVertex2f(point[4].x, point[4].y);
1218 rlVertex2f(point[12].x, point[12].y);
1219
1220 // Left rectangle
1221 rlColor4ub(color.r, color.g, color.b, color.a);
1223 rlVertex2f(point[15].x, point[15].y);
1225 rlVertex2f(point[7].x, point[7].y);
1227 rlVertex2f(point[6].x, point[6].y);
1229 rlVertex2f(point[14].x, point[14].y);
1230
1231 rlEnd();
1232 rlSetTexture(0);
1233#else
1234 rlCheckRenderBatchLimit(4*6*segments + 4*6); // 4 corners with 6(2*3) vertices for each segment + 4 rectangles with 6 vertices each
1235
1237
1238 // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1239 for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1240 {
1241 float angle = angles[k];
1242 const Vector2 center = centers[k];
1243
1244 for (int i = 0; i < segments; i++)
1245 {
1246 rlColor4ub(color.r, color.g, color.b, color.a);
1247
1248 rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
1249 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1250 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1251
1252 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
1253 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1254 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1255
1256 angle += stepLength;
1257 }
1258 }
1259
1260 // Upper rectangle
1261 rlColor4ub(color.r, color.g, color.b, color.a);
1262 rlVertex2f(point[0].x, point[0].y);
1263 rlVertex2f(point[8].x, point[8].y);
1264 rlVertex2f(point[9].x, point[9].y);
1265 rlVertex2f(point[1].x, point[1].y);
1266 rlVertex2f(point[0].x, point[0].y);
1267 rlVertex2f(point[9].x, point[9].y);
1268
1269 // Right rectangle
1270 rlColor4ub(color.r, color.g, color.b, color.a);
1271 rlVertex2f(point[10].x, point[10].y);
1272 rlVertex2f(point[11].x, point[11].y);
1273 rlVertex2f(point[3].x, point[3].y);
1274 rlVertex2f(point[2].x, point[2].y);
1275 rlVertex2f(point[10].x, point[10].y);
1276 rlVertex2f(point[3].x, point[3].y);
1277
1278 // Lower rectangle
1279 rlColor4ub(color.r, color.g, color.b, color.a);
1280 rlVertex2f(point[13].x, point[13].y);
1281 rlVertex2f(point[5].x, point[5].y);
1282 rlVertex2f(point[4].x, point[4].y);
1283 rlVertex2f(point[12].x, point[12].y);
1284 rlVertex2f(point[13].x, point[13].y);
1285 rlVertex2f(point[4].x, point[4].y);
1286
1287 // Left rectangle
1288 rlColor4ub(color.r, color.g, color.b, color.a);
1289 rlVertex2f(point[7].x, point[7].y);
1290 rlVertex2f(point[6].x, point[6].y);
1291 rlVertex2f(point[14].x, point[14].y);
1292 rlVertex2f(point[15].x, point[15].y);
1293 rlVertex2f(point[7].x, point[7].y);
1294 rlVertex2f(point[14].x, point[14].y);
1295 rlEnd();
1296#endif
1297 }
1298 else
1299 {
1300 // Use LINES to draw the outline
1301 rlCheckRenderBatchLimit(8*segments + 4*2); // 4 corners with 2 vertices for each segment + 4 rectangles with 2 vertices each
1302
1304
1305 // Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
1306 for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
1307 {
1308 float angle = angles[k];
1309 const Vector2 center = centers[k];
1310
1311 for (int i = 0; i < segments; i++)
1312 {
1313 rlColor4ub(color.r, color.g, color.b, color.a);
1314 rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
1315 rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
1316 angle += stepLength;
1317 }
1318 }
1319
1320 // And now the remaining 4 lines
1321 for (int i = 0; i < 8; i += 2)
1322 {
1323 rlColor4ub(color.r, color.g, color.b, color.a);
1324 rlVertex2f(point[i].x, point[i].y);
1325 rlVertex2f(point[i + 1].x, point[i + 1].y);
1326 }
1327
1328 rlEnd();
1329 }
1330}
1331
1332// Draw a triangle
1333// NOTE: Vertex must be provided in counter-clockwise order
1335{
1336#if defined(SUPPORT_QUADS_DRAW_MODE)
1338
1340
1342 rlColor4ub(color.r, color.g, color.b, color.a);
1343
1345 rlVertex2f(v1.x, v1.y);
1346
1348 rlVertex2f(v2.x, v2.y);
1349
1351 rlVertex2f(v2.x, v2.y);
1352
1354 rlVertex2f(v3.x, v3.y);
1355 rlEnd();
1356
1357 rlSetTexture(0);
1358#else
1360
1362 rlColor4ub(color.r, color.g, color.b, color.a);
1363 rlVertex2f(v1.x, v1.y);
1364 rlVertex2f(v2.x, v2.y);
1365 rlVertex2f(v3.x, v3.y);
1366 rlEnd();
1367#endif
1368}
1369
1370// Draw a triangle using lines
1371// NOTE: Vertex must be provided in counter-clockwise order
1373{
1375
1377 rlColor4ub(color.r, color.g, color.b, color.a);
1378 rlVertex2f(v1.x, v1.y);
1379 rlVertex2f(v2.x, v2.y);
1380
1381 rlVertex2f(v2.x, v2.y);
1382 rlVertex2f(v3.x, v3.y);
1383
1384 rlVertex2f(v3.x, v3.y);
1385 rlVertex2f(v1.x, v1.y);
1386 rlEnd();
1387}
1388
1389// Draw a triangle fan defined by points
1390// NOTE: First vertex provided is the center, shared by all triangles
1391// By default, following vertex should be provided in counter-clockwise order
1392void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
1393{
1394 if (pointCount >= 3)
1395 {
1396 rlCheckRenderBatchLimit((pointCount - 2)*4);
1397
1400 rlColor4ub(color.r, color.g, color.b, color.a);
1401
1402 for (int i = 1; i < pointCount - 1; i++)
1403 {
1405 rlVertex2f(points[0].x, points[0].y);
1406
1408 rlVertex2f(points[i].x, points[i].y);
1409
1411 rlVertex2f(points[i + 1].x, points[i + 1].y);
1412
1414 rlVertex2f(points[i + 1].x, points[i + 1].y);
1415 }
1416 rlEnd();
1417 rlSetTexture(0);
1418 }
1419}
1420
1421// Draw a triangle strip defined by points
1422// NOTE: Every new vertex connects with previous two
1423void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
1424{
1425 if (pointCount >= 3)
1426 {
1427 rlCheckRenderBatchLimit(3*(pointCount - 2));
1428
1430 rlColor4ub(color.r, color.g, color.b, color.a);
1431
1432 for (int i = 2; i < pointCount; i++)
1433 {
1434 if ((i%2) == 0)
1435 {
1436 rlVertex2f(points[i].x, points[i].y);
1437 rlVertex2f(points[i - 2].x, points[i - 2].y);
1438 rlVertex2f(points[i - 1].x, points[i - 1].y);
1439 }
1440 else
1441 {
1442 rlVertex2f(points[i].x, points[i].y);
1443 rlVertex2f(points[i - 1].x, points[i - 1].y);
1444 rlVertex2f(points[i - 2].x, points[i - 2].y);
1445 }
1446 }
1447 rlEnd();
1448 }
1449}
1450
1451// Draw a regular polygon of n sides (Vector version)
1452void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
1453{
1454 if (sides < 3) sides = 3;
1455 float centralAngle = 0.0f;
1456
1457#if defined(SUPPORT_QUADS_DRAW_MODE)
1458 rlCheckRenderBatchLimit(4*sides); // Each side is a quad
1459#else
1460 rlCheckRenderBatchLimit(3*sides);
1461#endif
1462
1463 rlPushMatrix();
1464 rlTranslatef(center.x, center.y, 0.0f);
1465 rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
1466
1467#if defined(SUPPORT_QUADS_DRAW_MODE)
1469
1471 for (int i = 0; i < sides; i++)
1472 {
1473 rlColor4ub(color.r, color.g, color.b, color.a);
1474
1476 rlVertex2f(0, 0);
1477
1479 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1480
1482 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1483
1484 centralAngle += 360.0f/(float)sides;
1486 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1487 }
1488 rlEnd();
1489 rlSetTexture(0);
1490#else
1492 for (int i = 0; i < sides; i++)
1493 {
1494 rlColor4ub(color.r, color.g, color.b, color.a);
1495
1496 rlVertex2f(0, 0);
1497 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1498
1499 centralAngle += 360.0f/(float)sides;
1500 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1501 }
1502 rlEnd();
1503#endif
1504 rlPopMatrix();
1505}
1506
1507// Draw a polygon outline of n sides
1508void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
1509{
1510 if (sides < 3) sides = 3;
1511 float centralAngle = 0.0f;
1512
1513 rlCheckRenderBatchLimit(2*sides);
1514
1515 rlPushMatrix();
1516 rlTranslatef(center.x, center.y, 0.0f);
1517 rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
1518
1520 for (int i = 0; i < sides; i++)
1521 {
1522 rlColor4ub(color.r, color.g, color.b, color.a);
1523
1524 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1525 centralAngle += 360.0f/(float)sides;
1526 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1527 }
1528 rlEnd();
1529 rlPopMatrix();
1530}
1531
1532void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
1533{
1534 if (sides < 3) sides = 3;
1535 float centralAngle = 0.0f;
1536 float exteriorAngle = 360.0f/(float)sides;
1537 float innerRadius = radius - (lineThick*cosf(DEG2RAD*exteriorAngle/2.0f));
1538
1539#if defined(SUPPORT_QUADS_DRAW_MODE)
1540 rlCheckRenderBatchLimit(4*sides);
1541#else
1542 rlCheckRenderBatchLimit(6*sides);
1543#endif
1544
1545 rlPushMatrix();
1546 rlTranslatef(center.x, center.y, 0.0f);
1547 rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
1548
1549#if defined(SUPPORT_QUADS_DRAW_MODE)
1551
1553 for (int i = 0; i < sides; i++)
1554 {
1555 rlColor4ub(color.r, color.g, color.b, color.a);
1556
1558 rlVertex2f(sinf(DEG2RAD*centralAngle)*innerRadius, cosf(DEG2RAD*centralAngle)*innerRadius);
1559
1561 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1562
1563 centralAngle += exteriorAngle;
1565 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1566
1568 rlVertex2f(sinf(DEG2RAD*centralAngle)*innerRadius, cosf(DEG2RAD*centralAngle)*innerRadius);
1569 }
1570 rlEnd();
1571 rlSetTexture(0);
1572#else
1574 for (int i = 0; i < sides; i++)
1575 {
1576 rlColor4ub(color.r, color.g, color.b, color.a);
1577 float nextAngle = centralAngle + exteriorAngle;
1578
1579 rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
1580 rlVertex2f(sinf(DEG2RAD*centralAngle)*innerRadius, cosf(DEG2RAD*centralAngle)*innerRadius);
1581 rlVertex2f(sinf(DEG2RAD*nextAngle)*radius, cosf(DEG2RAD*nextAngle)*radius);
1582
1583 rlVertex2f(sinf(DEG2RAD*centralAngle)*innerRadius, cosf(DEG2RAD*centralAngle)*innerRadius);
1584 rlVertex2f(sinf(DEG2RAD*nextAngle)*radius, cosf(DEG2RAD*nextAngle)*radius);
1585 rlVertex2f(sinf(DEG2RAD*nextAngle)*innerRadius, cosf(DEG2RAD*nextAngle)*innerRadius);
1586
1587 centralAngle = nextAngle;
1588 }
1589 rlEnd();
1590#endif
1591 rlPopMatrix();
1592}
1593
1594//----------------------------------------------------------------------------------
1595// Module Functions Definition - Collision Detection functions
1596//----------------------------------------------------------------------------------
1597
1598// Check if point is inside rectangle
1600{
1601 bool collision = false;
1602
1603 if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
1604
1605 return collision;
1606}
1607
1608// Check if point is inside circle
1609bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
1610{
1611 bool collision = false;
1612
1613 collision = CheckCollisionCircles(point, 0, center, radius);
1614
1615 return collision;
1616}
1617
1618// Check if point is inside a triangle defined by three points (p1, p2, p3)
1620{
1621 bool collision = false;
1622
1623 float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
1624 ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
1625
1626 float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
1627 ((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
1628
1629 float gamma = 1.0f - alpha - beta;
1630
1631 if ((alpha > 0) && (beta > 0) && (gamma > 0)) collision = true;
1632
1633 return collision;
1634}
1635
1636// Check collision between two rectangles
1638{
1639 bool collision = false;
1640
1641 if ((rec1.x < (rec2.x + rec2.width) && (rec1.x + rec1.width) > rec2.x) &&
1642 (rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
1643
1644 return collision;
1645}
1646
1647// Check collision between two circles
1648bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
1649{
1650 bool collision = false;
1651
1652 float dx = center2.x - center1.x; // X distance between centers
1653 float dy = center2.y - center1.y; // Y distance between centers
1654
1655 float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
1656
1657 if (distance <= (radius1 + radius2)) collision = true;
1658
1659 return collision;
1660}
1661
1662// Check collision between circle and rectangle
1663// NOTE: Reviewed version to take into account corner limit case
1664bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
1665{
1666 bool collision = false;
1667
1668 int recCenterX = (int)(rec.x + rec.width/2.0f);
1669 int recCenterY = (int)(rec.y + rec.height/2.0f);
1670
1671 float dx = fabsf(center.x - (float)recCenterX);
1672 float dy = fabsf(center.y - (float)recCenterY);
1673
1674 if (dx > (rec.width/2.0f + radius)) { return false; }
1675 if (dy > (rec.height/2.0f + radius)) { return false; }
1676
1677 if (dx <= (rec.width/2.0f)) { return true; }
1678 if (dy <= (rec.height/2.0f)) { return true; }
1679
1680 float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
1681 (dy - rec.height/2.0f)*(dy - rec.height/2.0f);
1682
1683 collision = (cornerDistanceSq <= (radius*radius));
1684
1685 return collision;
1686}
1687
1688// Check the collision between two lines defined by two points each, returns collision point by reference
1689bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint)
1690{
1691 bool collision = false;
1692
1693 float div = (endPos2.y - startPos2.y)*(endPos1.x - startPos1.x) - (endPos2.x - startPos2.x)*(endPos1.y - startPos1.y);
1694
1695 if (fabsf(div) >= FLT_EPSILON)
1696 {
1697 collision = true;
1698
1699 float xi = ((startPos2.x - endPos2.x)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.x - endPos1.x)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
1700 float yi = ((startPos2.y - endPos2.y)*(startPos1.x*endPos1.y - startPos1.y*endPos1.x) - (startPos1.y - endPos1.y)*(startPos2.x*endPos2.y - startPos2.y*endPos2.x))/div;
1701
1702 if (((fabsf(startPos1.x - endPos1.x) > FLT_EPSILON) && (xi < fminf(startPos1.x, endPos1.x) || (xi > fmaxf(startPos1.x, endPos1.x)))) ||
1703 ((fabsf(startPos2.x - endPos2.x) > FLT_EPSILON) && (xi < fminf(startPos2.x, endPos2.x) || (xi > fmaxf(startPos2.x, endPos2.x)))) ||
1704 ((fabsf(startPos1.y - endPos1.y) > FLT_EPSILON) && (yi < fminf(startPos1.y, endPos1.y) || (yi > fmaxf(startPos1.y, endPos1.y)))) ||
1705 ((fabsf(startPos2.y - endPos2.y) > FLT_EPSILON) && (yi < fminf(startPos2.y, endPos2.y) || (yi > fmaxf(startPos2.y, endPos2.y))))) collision = false;
1706
1707 if (collision && (collisionPoint != 0))
1708 {
1709 collisionPoint->x = xi;
1710 collisionPoint->y = yi;
1711 }
1712 }
1713
1714 return collision;
1715}
1716
1717// Check if point belongs to line created between two points [p1] and [p2] with defined margin in pixels [threshold]
1718bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold)
1719{
1720 bool collision = false;
1721
1722 float dxc = point.x - p1.x;
1723 float dyc = point.y - p1.y;
1724 float dxl = p2.x - p1.x;
1725 float dyl = p2.y - p1.y;
1726 float cross = dxc*dyl - dyc*dxl;
1727
1728 if (fabsf(cross) < (threshold*fmaxf(fabsf(dxl), fabsf(dyl))))
1729 {
1730 if (fabsf(dxl) >= fabsf(dyl)) collision = (dxl > 0)? ((p1.x <= point.x) && (point.x <= p2.x)) : ((p2.x <= point.x) && (point.x <= p1.x));
1731 else collision = (dyl > 0)? ((p1.y <= point.y) && (point.y <= p2.y)) : ((p2.y <= point.y) && (point.y <= p1.y));
1732 }
1733
1734 return collision;
1735}
1736
1737// Get collision rectangle for two rectangles collision
1739{
1740 Rectangle rec = { 0, 0, 0, 0 };
1741
1742 if (CheckCollisionRecs(rec1, rec2))
1743 {
1744 float dxx = fabsf(rec1.x - rec2.x);
1745 float dyy = fabsf(rec1.y - rec2.y);
1746
1747 if (rec1.x <= rec2.x)
1748 {
1749 if (rec1.y <= rec2.y)
1750 {
1751 rec.x = rec2.x;
1752 rec.y = rec2.y;
1753 rec.width = rec1.width - dxx;
1754 rec.height = rec1.height - dyy;
1755 }
1756 else
1757 {
1758 rec.x = rec2.x;
1759 rec.y = rec1.y;
1760 rec.width = rec1.width - dxx;
1761 rec.height = rec2.height - dyy;
1762 }
1763 }
1764 else
1765 {
1766 if (rec1.y <= rec2.y)
1767 {
1768 rec.x = rec1.x;
1769 rec.y = rec2.y;
1770 rec.width = rec2.width - dxx;
1771 rec.height = rec1.height - dyy;
1772 }
1773 else
1774 {
1775 rec.x = rec1.x;
1776 rec.y = rec1.y;
1777 rec.width = rec2.width - dxx;
1778 rec.height = rec2.height - dyy;
1779 }
1780 }
1781
1782 if (rec1.width > rec2.width)
1783 {
1784 if (rec.width >= rec2.width) rec.width = rec2.width;
1785 }
1786 else
1787 {
1788 if (rec.width >= rec1.width) rec.width = rec1.width;
1789 }
1790
1791 if (rec1.height > rec2.height)
1792 {
1793 if (rec.height >= rec2.height) rec.height = rec2.height;
1794 }
1795 else
1796 {
1797 if (rec.height >= rec1.height) rec.height = rec1.height;
1798 }
1799 }
1800
1801 return rec;
1802}
1803
1804//----------------------------------------------------------------------------------
1805// Module specific Functions Definition
1806//----------------------------------------------------------------------------------
1807
1808// Cubic easing in-out
1809// NOTE: Used by DrawLineBezier() only
1810static float EaseCubicInOut(float t, float b, float c, float d)
1811{
1812 if ((t /= 0.5f*d) < 1) return 0.5f*c*t*t*t + b;
1813
1814 t -= 2;
1815
1816 return 0.5f*c*(t*t*t + 2.0f) + b;
1817}
1818
1819#endif // SUPPORT_MODULE_RSHAPES
EASEDEF float EaseCubicInOut(float t, float b, float c, float d)
Definition: easings.h:126
#define PI
Definition: easings.h:96
#define DEG2RAD
Definition: raylib.h:106
RLAPI void rlNormal3f(float x, float y, float z)
#define RL_QUADS
Definition: rlgl.h:260
RLAPI void rlEnd(void)
RLAPI void rlColor4ub(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
#define RL_TRIANGLES
Definition: rlgl.h:259
RLAPI void rlVertex2i(int x, int y)
RLAPI void rlPushMatrix(void)
RLAPI void rlVertex2f(float x, float y)
RLAPI void rlBegin(int mode)
RLAPI void rlTexCoord2f(float x, float y)
RLAPI void rlRotatef(float angle, float x, float y, float z)
RLAPI void rlPopMatrix(void)
RLAPI void rlSetTexture(unsigned int id)
RLAPI bool rlCheckRenderBatchLimit(int vCount)
#define RL_LINES
Definition: rlgl.h:258
RLAPI void rlTranslatef(float x, float y, float z)
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
Definition: rshapes.c:125
void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
Definition: rshapes.c:683
bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
Definition: rshapes.c:1648
void DrawLineBezierCubic(Vector2 startPos, Vector2 endPos, Vector2 startControlPos, Vector2 endControlPos, float thick, Color color)
Definition: rshapes.c:211
void DrawPolyLinesEx(Vector2 center, int sides, float radius, float rotation, float lineThick, Color color)
Definition: rshapes.c:1532
Texture2D texShapes
Definition: rshapes.c:83
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
Definition: rshapes.c:1452
void DrawTriangleStrip(Vector2 *points, int pointCount, Color color)
Definition: rshapes.c:1423
void DrawCircleSectorLines(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
Definition: rshapes.c:354
bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
Definition: rshapes.c:1637
void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
Definition: rshapes.c:873
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
Definition: rshapes.c:816
void DrawPixel(int posX, int posY, Color color)
Definition: rshapes.c:105
void DrawPixelV(Vector2 position, Color color)
Definition: rshapes.c:115
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
Definition: rshapes.c:768
void DrawCircleV(Vector2 center, float radius, Color color)
Definition: rshapes.c:436
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
Definition: rshapes.c:417
void DrawRectangleRec(Rectangle rec, Color color)
Definition: rshapes.c:677
bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3)
Definition: rshapes.c:1619
void DrawTriangleFan(Vector2 *points, int pointCount, Color color)
Definition: rshapes.c:1392
void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
Definition: rshapes.c:459
void SetShapesTexture(Texture2D texture, Rectangle source)
Definition: rshapes.c:98
void DrawLineBezierQuad(Vector2 startPos, Vector2 endPos, Vector2 controlPos, float thick, Color color)
Definition: rshapes.c:185
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
Definition: rshapes.c:775
Rectangle texShapesRec
Definition: rshapes.c:84
bool CheckCollisionLines(Vector2 startPos1, Vector2 endPos1, Vector2 startPos2, Vector2 endPos2, Vector2 *collisionPoint)
Definition: rshapes.c:1689
void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
Definition: rshapes.c:584
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, float lineThick, Color color)
Definition: rshapes.c:1095
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
Definition: rshapes.c:135
void DrawRing(Vector2 center, float innerRadius, float outerRadius, float startAngle, float endAngle, int segments, Color color)
Definition: rshapes.c:490
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
Definition: rshapes.c:1738
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
Definition: rshapes.c:782
bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
Definition: rshapes.c:1609
void DrawRectangleLinesEx(Rectangle rec, float lineThick, Color color)
Definition: rshapes.c:842
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
Definition: rshapes.c:1372
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
Definition: rshapes.c:1508
bool CheckCollisionPointLine(Vector2 point, Vector2 p1, Vector2 p2, int threshold)
Definition: rshapes.c:1718
void DrawRectangle(int posX, int posY, int width, int height, Color color)
Definition: rshapes.c:664
void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
Definition: rshapes.c:145
void DrawCircleSector(Vector2 center, float radius, float startAngle, float endAngle, int segments, Color color)
Definition: rshapes.c:262
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
Definition: rshapes.c:442
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
Definition: rshapes.c:1334
#define SMOOTH_CIRCLE_ERROR_RATE
rshapes - Basic functions to draw 2d shapes and check collisions
Definition: rshapes.c:68
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
Definition: rshapes.c:1599
void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
Definition: rshapes.c:475
bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
Definition: rshapes.c:1664
void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
Definition: rshapes.c:166
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
Definition: rshapes.c:671
#define BEZIER_LINE_DIVISIONS
Definition: rshapes.c:71
void DrawCircle(int centerX, int centerY, float radius, Color color)
Definition: rshapes.c:256
void DrawLineStrip(Vector2 *points, int pointCount, Color color)
Definition: rshapes.c:237
Definition: raylib.h:220
unsigned char a
Definition: raylib.h:224
unsigned char b
Definition: raylib.h:223
unsigned char r
Definition: raylib.h:221
unsigned char g
Definition: raylib.h:222
float height
Definition: raylib.h:232
float x
Definition: raylib.h:229
float y
Definition: raylib.h:230
float width
Definition: raylib.h:231
int width
Definition: raylib.h:247
int height
Definition: raylib.h:248
unsigned int id
Definition: raylib.h:246
float x
Definition: physac.h:130
float y
Definition: physac.h:131