2014-09-16 22:51:31 +02:00
|
|
|
/**********************************************************************************************
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
2017-02-16 00:50:02 +01:00
|
|
|
* raylib.shapes - Basic functions to draw 2d Shapes and check collisions
|
2016-11-16 18:46:13 +01:00
|
|
|
*
|
2017-02-16 00:19:03 +01:00
|
|
|
* CONFIGURATION:
|
|
|
|
*
|
2018-04-29 12:53:32 +02:00
|
|
|
* #define SUPPORT_FONT_TEXTURE
|
2018-01-01 16:54:32 +01:00
|
|
|
* Draw rectangle shapes using font texture white character instead of default white texture
|
|
|
|
* Allows drawing rectangles and text with a single draw call, very useful for GUI systems!
|
|
|
|
*
|
2018-04-29 12:53:32 +02:00
|
|
|
* #define SUPPORT_QUADS_DRAW_MODE
|
2018-11-06 15:10:50 +01:00
|
|
|
* Use QUADS instead of TRIANGLES for drawing when possible.
|
2018-04-29 12:53:32 +02:00
|
|
|
* Some lines-based shapes could still use lines
|
2017-02-16 00:19:03 +01:00
|
|
|
*
|
|
|
|
* LICENSE: zlib/libpng
|
2016-11-16 18:46:13 +01:00
|
|
|
*
|
2020-01-05 20:01:54 +01:00
|
|
|
* Copyright (c) 2013-2020 Ramon Santamaria (@raysan5)
|
2014-09-03 16:51:28 +02:00
|
|
|
*
|
|
|
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
2013-11-23 13:30:54 +01:00
|
|
|
* will the authors be held liable for any damages arising from the use of this software.
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
2014-09-03 16:51:28 +02:00
|
|
|
* Permission is granted to anyone to use this software for any purpose, including commercial
|
2013-11-23 13:30:54 +01:00
|
|
|
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
2014-09-03 16:51:28 +02:00
|
|
|
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
|
|
|
* wrote the original software. If you use this software in a product, an acknowledgment
|
2013-11-23 13:30:54 +01:00
|
|
|
* in the product documentation would be appreciated but is not required.
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
2013-11-23 13:30:54 +01:00
|
|
|
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
|
|
|
* as being the original software.
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
2013-11-23 13:30:54 +01:00
|
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
2013-11-18 23:38:44 +01:00
|
|
|
*
|
|
|
|
**********************************************************************************************/
|
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
#include "raylib.h" // Declares module functions
|
2013-11-18 23:38:44 +01:00
|
|
|
|
2018-12-18 00:20:08 +01:00
|
|
|
// Check if config flags have been externally provided on compilation line
|
|
|
|
#if !defined(EXTERNAL_CONFIG_FLAGS)
|
|
|
|
#include "config.h" // Defines module configuration flags
|
|
|
|
#endif
|
|
|
|
|
2016-11-16 18:46:13 +01:00
|
|
|
#include "rlgl.h" // raylib OpenGL abstraction layer to OpenGL 1.1, 2.1, 3.3+ or ES2
|
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
#include <stdlib.h> // Required for: abs(), fabs()
|
2016-10-31 20:39:03 +01:00
|
|
|
#include <math.h> // Required for: sinf(), cosf(), sqrtf()
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Defines and Macros
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Nop...
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Types and Structures Definition
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Not here...
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Global Variables Definition
|
|
|
|
//----------------------------------------------------------------------------------
|
2020-01-08 18:21:08 +01:00
|
|
|
static Texture2D texShapes = { 0 }; // Texture used on shapes drawing (usually a white)
|
|
|
|
static Rectangle recTexShapes = { 0 }; // Texture source rectangle used on shapes drawing
|
2013-11-18 23:38:44 +01:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Module specific Functions Declaration
|
|
|
|
//----------------------------------------------------------------------------------
|
2017-03-14 00:22:53 +01:00
|
|
|
static float EaseCubicInOut(float t, float b, float c, float d); // Cubic easing
|
2018-11-06 15:06:01 +01:00
|
|
|
static Texture2D GetShapesTexture(void); // Get texture to draw shapes
|
2013-11-18 23:38:44 +01:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Module Functions Definition
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Draw a pixel
|
|
|
|
void DrawPixel(int posX, int posY, Color color)
|
|
|
|
{
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2i(posX, posY);
|
|
|
|
rlVertex2i(posX + 1, posY + 1);
|
2014-04-04 20:11:57 +02:00
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a pixel (Vector version)
|
|
|
|
void DrawPixelV(Vector2 position, Color color)
|
|
|
|
{
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(position.x, position.y);
|
2016-10-17 00:03:38 +02:00
|
|
|
rlVertex2f(position.x + 1.0f, position.y + 1.0f);
|
2014-03-25 12:40:35 +01:00
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a line
|
|
|
|
void DrawLine(int startPosX, int startPosY, int endPosX, int endPosY, Color color)
|
|
|
|
{
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2i(startPosX, startPosY);
|
|
|
|
rlVertex2i(endPosX, endPosY);
|
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a line (Vector version)
|
|
|
|
void DrawLineV(Vector2 startPos, Vector2 endPos, Color color)
|
|
|
|
{
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(startPos.x, startPos.y);
|
|
|
|
rlVertex2f(endPos.x, endPos.y);
|
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2017-03-05 21:04:07 +01:00
|
|
|
// Draw a line defining thickness
|
|
|
|
void DrawLineEx(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
|
|
|
{
|
2017-03-14 00:22:53 +01:00
|
|
|
if (startPos.x > endPos.x)
|
|
|
|
{
|
|
|
|
Vector2 tempPos = startPos;
|
|
|
|
startPos = endPos;
|
|
|
|
endPos = tempPos;
|
|
|
|
}
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2017-03-05 21:04:07 +01:00
|
|
|
float dx = endPos.x - startPos.x;
|
|
|
|
float dy = endPos.y - startPos.y;
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2017-03-05 21:04:07 +01:00
|
|
|
float d = sqrtf(dx*dx + dy*dy);
|
|
|
|
float angle = asinf(dy/d);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2017-03-05 21:04:07 +01:00
|
|
|
|
|
|
|
rlPushMatrix();
|
2018-12-26 10:51:13 +01:00
|
|
|
rlTranslatef((float)startPos.x, (float)startPos.y, 0.0f);
|
|
|
|
rlRotatef(RAD2DEG*angle, 0.0f, 0.0f, 1.0f);
|
2019-02-22 13:13:11 +01:00
|
|
|
rlTranslatef(0, (thick > 1.0f)? -thick/2.0f : -1.0f, 0.0f);
|
2017-03-05 21:04:07 +01:00
|
|
|
|
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
|
|
|
|
2018-11-07 22:31:35 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2017-03-05 21:04:07 +01:00
|
|
|
rlVertex2f(0.0f, 0.0f);
|
2018-11-07 22:31:35 +01:00
|
|
|
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2017-03-05 21:04:07 +01:00
|
|
|
rlVertex2f(0.0f, thick);
|
2019-02-21 18:45:19 +01:00
|
|
|
|
2018-11-07 22:31:35 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2017-03-05 21:04:07 +01:00
|
|
|
rlVertex2f(d, thick);
|
2018-11-07 22:31:35 +01:00
|
|
|
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2017-03-05 21:04:07 +01:00
|
|
|
rlVertex2f(d, 0.0f);
|
|
|
|
rlEnd();
|
|
|
|
rlPopMatrix();
|
|
|
|
|
|
|
|
rlDisableTexture();
|
|
|
|
}
|
|
|
|
|
2017-03-14 00:22:53 +01:00
|
|
|
// Draw line using cubic-bezier curves in-out
|
|
|
|
void DrawLineBezier(Vector2 startPos, Vector2 endPos, float thick, Color color)
|
|
|
|
{
|
|
|
|
#define LINE_DIVISIONS 24 // Bezier line divisions
|
|
|
|
|
|
|
|
Vector2 previous = startPos;
|
|
|
|
Vector2 current;
|
|
|
|
|
|
|
|
for (int i = 1; i <= LINE_DIVISIONS; i++)
|
|
|
|
{
|
|
|
|
// Cubic easing in-out
|
2018-11-06 15:10:50 +01:00
|
|
|
// NOTE: Easing is calculated only for y position value
|
2018-08-06 20:49:47 +02:00
|
|
|
current.y = EaseCubicInOut((float)i, startPos.y, endPos.y - startPos.y, (float)LINE_DIVISIONS);
|
|
|
|
current.x = previous.x + (endPos.x - startPos.x)/ (float)LINE_DIVISIONS;
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2017-03-14 00:22:53 +01:00
|
|
|
DrawLineEx(previous, current, thick, color);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2017-03-14 00:22:53 +01:00
|
|
|
previous = current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-28 14:45:46 +02:00
|
|
|
// Draw lines sequence
|
|
|
|
void DrawLineStrip(Vector2 *points, int pointsCount, Color color)
|
|
|
|
{
|
|
|
|
if (pointsCount >= 2)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit(pointsCount)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
for (int i = 0; i < pointsCount - 1; i++)
|
|
|
|
{
|
|
|
|
rlVertex2f(points[i].x, points[i].y);
|
|
|
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
// Draw a color-filled circle
|
|
|
|
void DrawCircle(int centerX, int centerY, float radius, Color color)
|
|
|
|
{
|
2016-10-17 00:03:38 +02:00
|
|
|
DrawCircleV((Vector2){ (float)centerX, (float)centerY }, radius, color);
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2019-02-13 00:06:06 +01:00
|
|
|
// Draw a piece of a circle
|
2019-03-28 18:53:41 +01:00
|
|
|
void DrawCircleSector(Vector2 center, float radius, int startAngle, int endAngle, int segments, Color color)
|
2018-11-06 15:10:50 +01:00
|
|
|
{
|
2019-03-29 19:43:27 +01:00
|
|
|
if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
// Function expects (endAngle > startAngle)
|
2019-04-04 13:50:28 +02:00
|
|
|
if (endAngle < startAngle)
|
2019-03-28 18:53:41 +01:00
|
|
|
{
|
|
|
|
// Swap values
|
|
|
|
int tmp = startAngle;
|
|
|
|
startAngle = endAngle;
|
|
|
|
endAngle = tmp;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1);
|
|
|
|
segments = (endAngle - startAngle)*ceilf(2*PI/th)/360;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
float stepLength = (float)(endAngle - startAngle)/(float)segments;
|
|
|
|
float angle = startAngle;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
2019-03-28 18:53:41 +01:00
|
|
|
if (rlCheckBufferLimit(4*segments/2)) rlglDraw();
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2016-03-17 13:51:48 +01:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlBegin(RL_QUADS);
|
2019-03-28 18:53:41 +01:00
|
|
|
// NOTE: Every QUAD actually represents two segments
|
|
|
|
for (int i = 0; i < segments/2; i++)
|
2018-04-29 12:53:32 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(center.x, center.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-28 18:53:41 +01:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
|
|
|
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
angle += (stepLength*2);
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
|
|
|
if (segments%2)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(center.x, center.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-28 18:53:41 +01:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-28 18:53:41 +01:00
|
|
|
rlVertex2f(center.x, center.y);
|
2018-04-29 12:53:32 +02:00
|
|
|
}
|
|
|
|
rlEnd();
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlDisableTexture();
|
|
|
|
#else
|
2019-03-28 18:53:41 +01:00
|
|
|
if (rlCheckBufferLimit(3*segments)) rlglDraw();
|
2018-05-20 01:55:46 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlBegin(RL_TRIANGLES);
|
2019-03-28 18:53:41 +01:00
|
|
|
for (int i = 0; i < segments; i++)
|
2018-04-29 12:53:32 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(center.x, center.y);
|
2019-03-28 18:53:41 +01:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-28 18:53:41 +01:00
|
|
|
angle += stepLength;
|
2018-04-29 12:53:32 +02:00
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
void DrawCircleSectorLines(Vector2 center, float radius, int startAngle, int endAngle, int segments, Color color)
|
|
|
|
{
|
2019-03-29 19:43:27 +01:00
|
|
|
if (radius <= 0.0f) radius = 0.1f; // Avoid div by zero issue
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Function expects (endAngle > startAngle)
|
2019-04-04 13:50:28 +02:00
|
|
|
if (endAngle < startAngle)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
// Swap values
|
|
|
|
int tmp = startAngle;
|
|
|
|
startAngle = endAngle;
|
|
|
|
endAngle = tmp;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#ifndef CIRCLE_ERROR_RATE
|
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
|
|
|
#endif
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1);
|
|
|
|
segments = (endAngle - startAngle)*ceilf(2*PI/th)/360;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
float stepLength = (float)(endAngle - startAngle)/(float)segments;
|
|
|
|
float angle = startAngle;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Hide the cap lines when the circle is full
|
|
|
|
bool showCapLines = true;
|
|
|
|
int limit = 2*(segments + 2);
|
2019-03-29 19:43:27 +01:00
|
|
|
if ((endAngle - startAngle)%360 == 0) { limit = 2*segments; showCapLines = false; }
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (rlCheckBufferLimit(limit)) rlglDraw();
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlBegin(RL_LINES);
|
2019-03-29 19:43:27 +01:00
|
|
|
if (showCapLines)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x, center.y);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 19:43:27 +01:00
|
|
|
if (showCapLines)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x, center.y);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
|
2019-02-13 00:06:06 +01:00
|
|
|
// Draw a gradient-filled circle
|
|
|
|
// NOTE: Gradient goes from center (color1) to border (color2)
|
|
|
|
void DrawCircleGradient(int centerX, int centerY, float radius, Color color1, Color color2)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit(3*36)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_TRIANGLES);
|
|
|
|
for (int i = 0; i < 360; i += 10)
|
|
|
|
{
|
|
|
|
rlColor4ub(color1.r, color1.g, color1.b, color1.a);
|
2019-03-28 13:03:25 +01:00
|
|
|
rlVertex2f(centerX, centerY);
|
2019-02-13 00:06:06 +01:00
|
|
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
|
|
|
rlColor4ub(color2.r, color2.g, color2.b, color2.a);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw a color-filled circle (Vector version)
|
|
|
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
|
|
|
void DrawCircleV(Vector2 center, float radius, Color color)
|
|
|
|
{
|
2019-03-28 18:53:41 +01:00
|
|
|
DrawCircleSector(center, radius, 0, 360, 36, color);
|
2019-02-13 00:06:06 +01:00
|
|
|
}
|
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
// Draw circle outline
|
|
|
|
void DrawCircleLines(int centerX, int centerY, float radius, Color color)
|
|
|
|
{
|
2018-12-24 14:09:51 +01:00
|
|
|
if (rlCheckBufferLimit(2*36)) rlglDraw();
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-23 13:30:54 +01:00
|
|
|
// NOTE: Circle outline is drawn pixel by pixel every degree (0 to 360)
|
2015-04-06 14:02:29 +02:00
|
|
|
for (int i = 0; i < 360; i += 10)
|
2013-11-23 13:30:54 +01:00
|
|
|
{
|
2016-10-17 00:03:38 +02:00
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radius, centerY + cosf(DEG2RAD*i)*radius);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radius, centerY + cosf(DEG2RAD*(i + 10))*radius);
|
2013-11-23 13:30:54 +01:00
|
|
|
}
|
2020-01-27 16:21:37 +01:00
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw ellipse
|
|
|
|
void DrawEllipse(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit(3*36)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_TRIANGLES);
|
|
|
|
for (int i = 0; i < 360; i += 10)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(centerX, centerY);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw ellipse outline
|
|
|
|
void DrawEllipseLines(int centerX, int centerY, float radiusH, float radiusV, Color color)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit(2*36)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_LINES);
|
|
|
|
for (int i = 0; i < 360; i += 10)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*i)*radiusH, centerY + cosf(DEG2RAD*i)*radiusV);
|
|
|
|
rlVertex2f(centerX + sinf(DEG2RAD*(i + 10))*radiusH, centerY + cosf(DEG2RAD*(i + 10))*radiusV);
|
|
|
|
}
|
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
void DrawRing(Vector2 center, float innerRadius, float outerRadius, int startAngle, int endAngle, int segments, Color color)
|
|
|
|
{
|
2019-03-29 19:43:27 +01:00
|
|
|
if (startAngle == endAngle) return;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Function expects (outerRadius > innerRadius)
|
2019-03-29 19:43:27 +01:00
|
|
|
if (outerRadius < innerRadius)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
float tmp = outerRadius;
|
|
|
|
outerRadius = innerRadius;
|
|
|
|
innerRadius = tmp;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 19:43:27 +01:00
|
|
|
if (outerRadius <= 0.0f) outerRadius = 0.1f;
|
2019-03-29 16:22:09 +02:00
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Function expects (endAngle > startAngle)
|
2019-04-04 13:50:28 +02:00
|
|
|
if (endAngle < startAngle)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
// Swap values
|
|
|
|
int tmp = startAngle;
|
|
|
|
startAngle = endAngle;
|
|
|
|
endAngle = tmp;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#ifndef CIRCLE_ERROR_RATE
|
2019-03-29 19:43:27 +01:00
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
2019-03-29 16:22:09 +02:00
|
|
|
#endif
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
|
|
|
|
segments = (endAngle - startAngle)*ceilf(2*PI/th)/360;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Not a ring
|
2019-04-04 13:50:28 +02:00
|
|
|
if (innerRadius <= 0.0f)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
DrawCircleSector(center, outerRadius, startAngle, endAngle, segments, color);
|
|
|
|
return;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
float stepLength = (float)(endAngle - startAngle)/(float)segments;
|
|
|
|
float angle = startAngle;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
|
|
|
if (rlCheckBufferLimit(4*segments)) rlglDraw();
|
|
|
|
|
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
|
|
|
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
|
|
|
|
rlDisableTexture();
|
|
|
|
#else
|
|
|
|
if (rlCheckBufferLimit(6*segments)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_TRIANGLES);
|
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void DrawRingLines(Vector2 center, float innerRadius, float outerRadius, int startAngle, int endAngle, int segments, Color color)
|
|
|
|
{
|
2019-03-29 19:43:27 +01:00
|
|
|
if (startAngle == endAngle) return;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Function expects (outerRadius > innerRadius)
|
2019-03-29 19:43:27 +01:00
|
|
|
if (outerRadius < innerRadius)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
float tmp = outerRadius;
|
|
|
|
outerRadius = innerRadius;
|
|
|
|
innerRadius = tmp;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 19:43:27 +01:00
|
|
|
if (outerRadius <= 0.0f) outerRadius = 0.1f;
|
2019-03-29 16:22:09 +02:00
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Function expects (endAngle > startAngle)
|
2019-04-04 13:50:28 +02:00
|
|
|
if (endAngle < startAngle)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
// Swap values
|
|
|
|
int tmp = startAngle;
|
|
|
|
startAngle = endAngle;
|
|
|
|
endAngle = tmp;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#ifndef CIRCLE_ERROR_RATE
|
2019-03-29 19:43:27 +01:00
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
2019-03-29 16:22:09 +02:00
|
|
|
#endif
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/outerRadius, 2) - 1);
|
|
|
|
segments = (endAngle - startAngle)*ceilf(2*PI/th)/360;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
if (innerRadius <= 0.0f)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
DrawCircleSectorLines(center, outerRadius, startAngle, endAngle, segments, color);
|
|
|
|
return;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
float stepLength = (float)(endAngle - startAngle)/(float)segments;
|
2019-04-04 13:50:28 +02:00
|
|
|
float angle = startAngle;
|
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
bool showCapLines = true;
|
|
|
|
int limit = 4*(segments + 1);
|
2019-03-29 19:43:27 +01:00
|
|
|
if ((endAngle - startAngle)%360 == 0) { limit = 4*segments; showCapLines = false; }
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
if (rlCheckBufferLimit(limit)) rlglDraw();
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlBegin(RL_LINES);
|
2019-03-29 19:43:27 +01:00
|
|
|
if (showCapLines)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 16:22:09 +02:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-29 19:43:27 +01:00
|
|
|
if (showCapLines)
|
2019-03-29 16:22:09 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
// Draw a color-filled rectangle
|
|
|
|
void DrawRectangle(int posX, int posY, int width, int height, Color color)
|
|
|
|
{
|
2018-11-06 15:06:01 +01:00
|
|
|
DrawRectangleV((Vector2){ (float)posX, (float)posY }, (Vector2){ (float)width, (float)height }, color);
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2018-01-01 16:54:32 +01:00
|
|
|
// Draw a color-filled rectangle (Vector version)
|
|
|
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
|
|
|
void DrawRectangleV(Vector2 position, Vector2 size, Color color)
|
|
|
|
{
|
2018-12-26 10:51:13 +01:00
|
|
|
DrawRectanglePro((Rectangle){ position.x, position.y, size.x, size.y }, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
|
2018-01-01 16:54:32 +01:00
|
|
|
}
|
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
// Draw a color-filled rectangle
|
|
|
|
void DrawRectangleRec(Rectangle rec, Color color)
|
|
|
|
{
|
2018-12-26 10:51:13 +01:00
|
|
|
DrawRectanglePro(rec, (Vector2){ 0.0f, 0.0f }, 0.0f, color);
|
2014-09-03 16:51:28 +02:00
|
|
|
}
|
2013-11-18 23:38:44 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
// Draw a color-filled rectangle with pro parameters
|
2018-12-26 10:51:13 +01:00
|
|
|
void DrawRectanglePro(Rectangle rec, Vector2 origin, float rotation, Color color)
|
2017-02-16 00:19:03 +01:00
|
|
|
{
|
2018-11-06 15:06:01 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2017-02-16 00:19:03 +01:00
|
|
|
|
|
|
|
rlPushMatrix();
|
2018-12-26 10:51:13 +01:00
|
|
|
rlTranslatef(rec.x, rec.y, 0.0f);
|
|
|
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
|
|
|
rlTranslatef(-origin.x, -origin.y, 0.0f);
|
2017-02-16 00:19:03 +01:00
|
|
|
|
|
|
|
rlBegin(RL_QUADS);
|
2018-11-06 15:06:01 +01:00
|
|
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
2018-12-26 10:51:13 +01:00
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2017-02-16 00:19:03 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-12-26 10:51:13 +01:00
|
|
|
rlVertex2f(0.0f, 0.0f);
|
2019-02-21 18:45:19 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2018-12-26 10:51:13 +01:00
|
|
|
rlVertex2f(0.0f, rec.height);
|
2019-02-21 18:45:19 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2018-12-26 10:51:13 +01:00
|
|
|
rlVertex2f(rec.width, rec.height);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-12-26 10:51:13 +01:00
|
|
|
rlVertex2f(rec.width, 0.0f);
|
2017-02-16 00:19:03 +01:00
|
|
|
rlEnd();
|
|
|
|
rlPopMatrix();
|
|
|
|
|
|
|
|
rlDisableTexture();
|
|
|
|
}
|
|
|
|
|
2017-09-30 00:46:31 +02:00
|
|
|
// Draw a vertical-gradient-filled rectangle
|
2013-11-18 23:38:44 +01:00
|
|
|
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
2017-09-30 00:46:31 +02:00
|
|
|
void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2)
|
2013-11-18 23:38:44 +01:00
|
|
|
{
|
2018-08-05 00:34:35 +02:00
|
|
|
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color2, color2, color1);
|
2017-09-30 00:46:31 +02:00
|
|
|
}
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2017-09-30 00:46:31 +02:00
|
|
|
// Draw a horizontal-gradient-filled rectangle
|
|
|
|
// NOTE: Gradient goes from bottom (color1) to top (color2)
|
|
|
|
void DrawRectangleGradientH(int posX, int posY, int width, int height, Color color1, Color color2)
|
|
|
|
{
|
2018-08-05 00:34:35 +02:00
|
|
|
DrawRectangleGradientEx((Rectangle){ (float)posX, (float)posY, (float)width, (float)height }, color1, color1, color2, color2);
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2017-08-27 21:02:24 +02:00
|
|
|
// Draw a gradient-filled rectangle
|
2017-09-30 00:46:31 +02:00
|
|
|
// NOTE: Colors refer to corners, starting at top-lef corner and counter-clockwise
|
2017-08-27 21:02:24 +02:00
|
|
|
void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4)
|
|
|
|
{
|
2018-12-26 10:51:13 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
|
|
|
|
|
|
|
rlPushMatrix();
|
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
rlNormal3f(0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
// NOTE: Default raylib font character 95 is a white square
|
|
|
|
rlColor4ub(col1.r, col1.g, col1.b, col1.a);
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(rec.x, rec.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-12-26 10:51:13 +01:00
|
|
|
rlColor4ub(col2.r, col2.g, col2.b, col2.a);
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(rec.x, rec.y + rec.height);
|
|
|
|
|
|
|
|
rlColor4ub(col3.r, col3.g, col3.b, col3.a);
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(rec.x + rec.width, rec.y + rec.height);
|
|
|
|
|
|
|
|
rlColor4ub(col4.r, col4.g, col4.b, col4.a);
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(rec.x + rec.width, rec.y);
|
|
|
|
rlEnd();
|
|
|
|
rlPopMatrix();
|
|
|
|
|
|
|
|
rlDisableTexture();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Draw rectangle outline
|
2016-03-17 13:51:48 +01:00
|
|
|
// NOTE: On OpenGL 3.3 and ES2 we use QUADS to avoid drawing order issues (view rlglDraw)
|
2013-11-18 23:38:44 +01:00
|
|
|
void DrawRectangleLines(int posX, int posY, int width, int height, Color color)
|
2018-11-06 15:10:50 +01:00
|
|
|
{
|
2018-04-29 12:53:32 +02:00
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
|
|
|
DrawRectangle(posX, posY, width, 1, color);
|
|
|
|
DrawRectangle(posX + width - 1, posY + 1, 1, height - 2, color);
|
|
|
|
DrawRectangle(posX, posY + height - 1, width, 1, color);
|
|
|
|
DrawRectangle(posX, posY + 1, 1, height - 2, color);
|
|
|
|
#else
|
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2i(posX + 1, posY + 1);
|
|
|
|
rlVertex2i(posX + width, posY + 1);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2i(posX + width, posY + 1);
|
|
|
|
rlVertex2i(posX + width, posY + height);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2i(posX + width, posY + height);
|
|
|
|
rlVertex2i(posX + 1, posY + height);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2i(posX + 1, posY + height);
|
|
|
|
rlVertex2i(posX + 1, posY + 1);
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2018-02-02 11:01:38 +01:00
|
|
|
// Draw rectangle outline with extended parameters
|
|
|
|
void DrawRectangleLinesEx(Rectangle rec, int lineThick, Color color)
|
2018-11-06 15:10:50 +01:00
|
|
|
{
|
2018-02-02 11:01:38 +01:00
|
|
|
if (lineThick > rec.width || lineThick > rec.height)
|
|
|
|
{
|
2019-02-28 23:06:37 +01:00
|
|
|
if (rec.width > rec.height) lineThick = (int)rec.height/2;
|
2018-08-05 23:53:34 +02:00
|
|
|
else if (rec.width < rec.height) lineThick = (int)rec.width/2;
|
2018-11-06 15:10:50 +01:00
|
|
|
}
|
|
|
|
|
2018-08-05 23:53:34 +02:00
|
|
|
DrawRectangle( (int)rec.x, (int)rec.y, (int)rec.width, lineThick, color);
|
|
|
|
DrawRectangle( (int)(rec.x - lineThick + rec.width), (int)(rec.y + lineThick), lineThick, (int)(rec.height - lineThick*2.0f), color);
|
|
|
|
DrawRectangle( (int)rec.x, (int)(rec.y + rec.height - lineThick), (int)rec.width, lineThick, color);
|
|
|
|
DrawRectangle( (int)rec.x, (int)(rec.y + lineThick), lineThick, (int)(rec.height - lineThick*2), color);
|
2018-02-02 11:01:38 +01:00
|
|
|
}
|
|
|
|
|
2019-04-04 13:50:28 +02:00
|
|
|
// Draw rectangle with rounded edges
|
|
|
|
void DrawRectangleRounded(Rectangle rec, float roundness, int segments, Color color)
|
2019-03-30 22:18:29 +02:00
|
|
|
{
|
|
|
|
// Not a rounded rectangle
|
2019-04-04 13:50:28 +02:00
|
|
|
if ((roundness <= 0.0f) || (rec.width < 1) || (rec.height < 1 ))
|
2019-03-30 22:18:29 +02:00
|
|
|
{
|
|
|
|
DrawRectangleRec(rec, color);
|
|
|
|
return;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
if (roundness >= 1.0f) roundness = 1.0f;
|
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// Calculate corner radius
|
2019-04-04 13:50:28 +02:00
|
|
|
float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
|
|
|
|
if (radius <= 0.0f) return;
|
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// Calculate number of segments to use for the corners
|
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#ifndef CIRCLE_ERROR_RATE
|
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
|
|
|
#endif
|
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1);
|
|
|
|
segments = ceilf(2*PI/th)/4;
|
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
float stepLength = 90.0f/(float)segments;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
/* Quick sketch to make sense of all of this (there are 9 parts to draw, also mark the 12 points we'll use below)
|
2019-03-31 16:15:40 +03:00
|
|
|
* Not my best attempt at ASCII art, just preted it's rounded rectangle :)
|
2019-03-30 22:18:29 +02:00
|
|
|
* P0 P1
|
|
|
|
* ____________________
|
|
|
|
* /| |\
|
|
|
|
* /1| 2 |3\
|
|
|
|
*P7 /__|____________________|__\ P2
|
|
|
|
* | |P8 P9| |
|
|
|
|
* | 8 | 9 | 4 |
|
|
|
|
* | __|____________________|__ |
|
|
|
|
*P6 \ |P11 P10| / P3
|
|
|
|
* \7| 6 |5/
|
|
|
|
* \|____________________|/
|
|
|
|
* P5 P4
|
|
|
|
*/
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
const Vector2 point[12] = { // coordinates of the 12 points that define the rounded rect (the idea here is to make things easier)
|
|
|
|
{(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
|
|
|
|
{rec.x + rec.width, (float)(rec.y + rec.height) - radius}, {(float)(rec.x + rec.width) - radius, rec.y + rec.height}, // P3, P4
|
|
|
|
{(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
|
|
|
|
{(float)rec.x + radius, (float)rec.y + radius}, {(float)(rec.x + rec.width) - radius, (float)rec.y + radius}, // P8, P9
|
|
|
|
{(float)(rec.x + rec.width) - radius, (float)(rec.y + rec.height) - radius}, {(float)rec.x + radius, (float)(rec.y + rec.height) - radius} // P10, P11
|
|
|
|
};
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 16:15:40 +03:00
|
|
|
const Vector2 centers[4] = { point[8], point[9], point[10], point[11] };
|
2019-04-04 13:50:28 +02:00
|
|
|
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
2019-03-30 22:18:29 +02:00
|
|
|
|
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
|
|
|
if (rlCheckBufferLimit(16*segments/2 + 5*4)) rlglDraw();
|
2019-05-08 18:33:09 +02:00
|
|
|
|
2019-04-23 20:48:00 +03:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2019-05-08 18:33:09 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
rlBegin(RL_QUADS);
|
2019-04-04 13:50:28 +02:00
|
|
|
// Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
|
|
|
|
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
2019-03-30 22:18:29 +02:00
|
|
|
{
|
|
|
|
float angle = angles[k];
|
|
|
|
const Vector2 center = centers[k];
|
|
|
|
// NOTE: Every QUAD actually represents two segments
|
|
|
|
for (int i = 0; i < segments/2; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x, center.y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength*2))*radius, center.y + cosf(DEG2RAD*(angle + stepLength*2))*radius);
|
|
|
|
angle += (stepLength*2);
|
|
|
|
}
|
|
|
|
// NOTE: In case number of segments is odd, we add one last piece to the cake
|
|
|
|
if (segments%2)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x, center.y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(center.x, center.y);
|
|
|
|
}
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [2] Upper Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[1].x, point[1].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [4] Right Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[2].x, point[2].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [6] Bottom Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[5].x, point[5].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [8] Left Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[6].x, point[6].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [9] Middle Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-30 22:18:29 +02:00
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
rlEnd();
|
2019-04-23 20:48:00 +03:00
|
|
|
rlDisableTexture();
|
2019-03-30 22:18:29 +02:00
|
|
|
#else
|
|
|
|
if (rlCheckBufferLimit(12*segments + 5*6)) rlglDraw(); // 4 corners with 3 vertices per segment + 5 rectangles with 6 vertices each
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
rlBegin(RL_TRIANGLES);
|
2019-04-04 13:50:28 +02:00
|
|
|
// Draw all of the 4 corners: [1] Upper Left Corner, [3] Upper Right Corner, [5] Lower Right Corner, [7] Lower Left Corner
|
|
|
|
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
2019-03-30 22:18:29 +02:00
|
|
|
{
|
|
|
|
float angle = angles[k];
|
|
|
|
const Vector2 center = centers[k];
|
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x, center.y);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*radius, center.y + cosf(DEG2RAD*angle)*radius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*radius, center.y + cosf(DEG2RAD*(angle + stepLength))*radius);
|
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// [2] Upper Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
|
|
|
rlVertex2f(point[1].x, point[1].y);
|
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [4] Right Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
|
|
|
rlVertex2f(point[2].x, point[2].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [6] Bottom Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
|
|
|
rlVertex2f(point[5].x, point[5].y);
|
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [8] Left Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
|
|
|
rlVertex2f(point[6].x, point[6].y);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-30 22:18:29 +02:00
|
|
|
// [9] Middle Rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-04-04 13:50:28 +02:00
|
|
|
// Draw rectangle with rounded edges outline
|
|
|
|
void DrawRectangleRoundedLines(Rectangle rec, float roundness, int segments, int lineThick, Color color)
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
2019-04-04 13:50:28 +02:00
|
|
|
if (lineThick < 0) lineThick = 0;
|
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Not a rounded rectangle
|
2019-04-04 13:50:28 +02:00
|
|
|
if (roundness <= 0.0f)
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
2019-03-31 16:15:40 +03:00
|
|
|
DrawRectangleLinesEx((Rectangle){rec.x-lineThick, rec.y-lineThick, rec.width+2*lineThick, rec.height+2*lineThick}, lineThick, color);
|
2019-03-31 13:22:50 +03:00
|
|
|
return;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
if (roundness >= 1.0f) roundness = 1.0f;
|
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Calculate corner radius
|
2019-04-04 13:50:28 +02:00
|
|
|
float radius = (rec.width > rec.height)? (rec.height*roundness)/2 : (rec.width*roundness)/2;
|
|
|
|
if (radius <= 0.0f) return;
|
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Calculate number of segments to use for the corners
|
|
|
|
if (segments < 4)
|
|
|
|
{
|
|
|
|
// Calculate how many segments we need to draw a smooth circle, taken from https://stackoverflow.com/a/2244088
|
|
|
|
#ifndef CIRCLE_ERROR_RATE
|
|
|
|
#define CIRCLE_ERROR_RATE 0.5f
|
|
|
|
#endif
|
|
|
|
// Calculate the maximum angle between segments based on the error rate.
|
|
|
|
float th = acosf(2*powf(1 - CIRCLE_ERROR_RATE/radius, 2) - 1);
|
2019-03-31 16:15:40 +03:00
|
|
|
segments = ceilf(2*PI/th)/2;
|
2019-03-31 13:22:50 +03:00
|
|
|
if (segments <= 0) segments = 4;
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
float stepLength = 90.0f/(float)segments;
|
2019-03-31 16:15:40 +03:00
|
|
|
const float outerRadius = radius + (float)lineThick, innerRadius = radius;
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
/* Quick sketch to make sense of all of this (mark the 16 + 4(corner centers P16-19) points we'll use below)
|
|
|
|
* Not my best attempt at ASCII art, just preted it's rounded rectangle :)
|
|
|
|
* P0 P1
|
|
|
|
* ====================
|
|
|
|
* // P8 P9 \\
|
|
|
|
* // \\
|
|
|
|
*P7 // P15 P10 \\ P2
|
|
|
|
* || *P16 P17* ||
|
|
|
|
* || ||
|
|
|
|
* || P14 P11 ||
|
|
|
|
*P6 \\ *P19 P18* // P3
|
|
|
|
* \\ //
|
|
|
|
* \\ P13 P12 //
|
|
|
|
* ====================
|
|
|
|
* P5 P4
|
|
|
|
*/
|
2019-04-04 13:50:28 +02:00
|
|
|
const Vector2 point[16] = {
|
2019-03-31 16:15:40 +03:00
|
|
|
{(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
|
|
|
|
{rec.x + rec.width + lineThick, (float)(rec.y + rec.height) - innerRadius}, {(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height + lineThick}, // P3, P4
|
|
|
|
{(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
|
|
|
|
{(float)rec.x + innerRadius, rec.y}, {(float)(rec.x + rec.width) - innerRadius, rec.y}, // P8, P9
|
|
|
|
{ rec.x + rec.width, (float)rec.y + innerRadius }, {rec.x + rec.width, (float)(rec.y + rec.height) - innerRadius}, // P10, P11
|
|
|
|
{(float)(rec.x + rec.width) - innerRadius, rec.y + rec.height}, {(float)rec.x + innerRadius, rec.y + rec.height}, // P12, P13
|
|
|
|
{ rec.x, (float)(rec.y + rec.height) - innerRadius}, {rec.x, (float)rec.y + innerRadius} // P14, P15
|
2019-03-31 13:22:50 +03:00
|
|
|
};
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
const Vector2 centers[4] = {
|
2019-03-31 16:15:40 +03:00
|
|
|
{(float)rec.x + innerRadius, (float)rec.y + innerRadius}, {(float)(rec.x + rec.width) - innerRadius, (float)rec.y + innerRadius}, // P16, P17
|
2019-04-04 13:50:28 +02:00
|
|
|
{(float)(rec.x + rec.width) - innerRadius, (float)(rec.y + rec.height) - innerRadius}, {(float)rec.x + innerRadius, (float)(rec.y + rec.height) - innerRadius} // P18, P19
|
2019-03-31 13:22:50 +03:00
|
|
|
};
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
const float angles[4] = { 180.0f, 90.0f, 0.0f, 270.0f };
|
|
|
|
|
|
|
|
if (lineThick > 1)
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
|
|
|
if (rlCheckBufferLimit(4*4*segments + 4*4)) rlglDraw(); // 4 corners with 4 vertices for each segment + 4 rectangles with 4 vertices each
|
2019-05-08 18:33:09 +02:00
|
|
|
|
2019-04-23 20:48:00 +03:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2019-05-08 18:33:09 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
// Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
2019-04-04 13:50:28 +02:00
|
|
|
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
|
|
|
float angle = angles[k];
|
2019-04-04 13:50:28 +02:00
|
|
|
const Vector2 center = centers[k];
|
2019-03-31 13:22:50 +03:00
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Upper rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[1].x, point[1].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Right rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[2].x, point[2].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Lower rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[13].x, point[13].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[5].x, point[5].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[12].x, point[12].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Left rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[15].x, point[15].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[6].x, point[6].y);
|
2019-04-23 20:48:00 +03:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(point[14].x, point[14].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlEnd();
|
2019-04-23 20:48:00 +03:00
|
|
|
rlDisableTexture();
|
2019-03-31 13:22:50 +03:00
|
|
|
#else
|
|
|
|
if (rlCheckBufferLimit(4*6*segments + 4*6)) rlglDraw(); // 4 corners with 6(2*3) vertices for each segment + 4 rectangles with 6 vertices each
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlBegin(RL_TRIANGLES);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
|
|
|
// Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
|
|
|
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
|
|
|
float angle = angles[k];
|
|
|
|
const Vector2 center = centers[k];
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*innerRadius, center.y + cosf(DEG2RAD*angle)*innerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*innerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*innerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
}
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Upper rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
|
|
|
rlVertex2f(point[8].x, point[8].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
|
|
|
rlVertex2f(point[1].x, point[1].y);
|
|
|
|
rlVertex2f(point[0].x, point[0].y);
|
|
|
|
rlVertex2f(point[9].x, point[9].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Right rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlVertex2f(point[11].x, point[11].y);
|
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
|
|
|
rlVertex2f(point[2].x, point[2].y);
|
|
|
|
rlVertex2f(point[10].x, point[10].y);
|
|
|
|
rlVertex2f(point[3].x, point[3].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Lower rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[13].x, point[13].y);
|
|
|
|
rlVertex2f(point[5].x, point[5].y);
|
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
|
|
|
rlVertex2f(point[12].x, point[12].y);
|
|
|
|
rlVertex2f(point[13].x, point[13].y);
|
|
|
|
rlVertex2f(point[4].x, point[4].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Left rectangle
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
|
|
|
rlVertex2f(point[6].x, point[6].y);
|
|
|
|
rlVertex2f(point[14].x, point[14].y);
|
|
|
|
rlVertex2f(point[15].x, point[15].y);
|
|
|
|
rlVertex2f(point[7].x, point[7].y);
|
|
|
|
rlVertex2f(point[14].x, point[14].y);
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Use LINES to draw the outline
|
|
|
|
if (rlCheckBufferLimit(8*segments + 4*2)) rlglDraw(); // 4 corners with 2 vertices for each segment + 4 rectangles with 2 vertices each
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
rlBegin(RL_LINES);
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
// Draw all of the 4 corners first: Upper Left Corner, Upper Right Corner, Lower Right Corner, Lower Left Corner
|
2019-04-04 13:50:28 +02:00
|
|
|
for (int k = 0; k < 4; ++k) // Hope the compiler is smart enough to unroll this loop
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
|
|
|
float angle = angles[k];
|
|
|
|
const Vector2 center = centers[k];
|
2019-04-04 13:50:28 +02:00
|
|
|
|
2019-03-31 13:22:50 +03:00
|
|
|
for (int i = 0; i < segments; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*angle)*outerRadius, center.y + cosf(DEG2RAD*angle)*outerRadius);
|
|
|
|
rlVertex2f(center.x + sinf(DEG2RAD*(angle + stepLength))*outerRadius, center.y + cosf(DEG2RAD*(angle + stepLength))*outerRadius);
|
|
|
|
angle += stepLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// And now the remaining 4 lines
|
2019-04-04 13:50:28 +02:00
|
|
|
for(int i = 0; i < 8; i += 2)
|
2019-03-31 13:22:50 +03:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(point[i].x, point[i].y);
|
2019-04-04 13:50:28 +02:00
|
|
|
rlVertex2f(point[i + 1].x, point[i + 1].y);
|
2019-03-31 13:22:50 +03:00
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-18 23:38:44 +01:00
|
|
|
// Draw a triangle
|
2019-08-11 21:26:12 +02:00
|
|
|
// NOTE: Vertex must be provided in counter-clockwise order
|
2013-11-18 23:38:44 +01:00
|
|
|
void DrawTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
|
|
|
{
|
2019-06-17 10:29:58 +02:00
|
|
|
if (rlCheckBufferLimit(4)) rlglDraw();
|
2019-09-22 22:25:39 +03:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
2018-11-06 15:06:01 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2016-07-17 12:40:56 +02:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(v1.x, v1.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(v2.x, v2.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(v2.x, v2.y);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(v3.x, v3.y);
|
|
|
|
rlEnd();
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
rlDisableTexture();
|
|
|
|
#else
|
|
|
|
rlBegin(RL_TRIANGLES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(v1.x, v1.y);
|
|
|
|
rlVertex2f(v2.x, v2.y);
|
|
|
|
rlVertex2f(v3.x, v3.y);
|
|
|
|
rlEnd();
|
|
|
|
#endif
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2018-04-29 12:53:32 +02:00
|
|
|
// Draw a triangle using lines
|
2019-08-11 21:26:12 +02:00
|
|
|
// NOTE: Vertex must be provided in counter-clockwise order
|
2013-11-18 23:38:44 +01:00
|
|
|
void DrawTriangleLines(Vector2 v1, Vector2 v2, Vector2 v3, Color color)
|
|
|
|
{
|
2019-06-17 10:29:58 +02:00
|
|
|
if (rlCheckBufferLimit(6)) rlglDraw();
|
2019-09-22 22:25:39 +03:00
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_LINES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
rlVertex2f(v1.x, v1.y);
|
|
|
|
rlVertex2f(v2.x, v2.y);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
rlVertex2f(v2.x, v2.y);
|
|
|
|
rlVertex2f(v3.x, v3.y);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
rlVertex2f(v3.x, v3.y);
|
|
|
|
rlVertex2f(v1.x, v1.y);
|
|
|
|
rlEnd();
|
2013-11-18 23:38:44 +01:00
|
|
|
}
|
|
|
|
|
2019-04-28 14:45:46 +02:00
|
|
|
// Draw a triangle fan defined by points
|
2019-08-11 21:26:12 +02:00
|
|
|
// NOTE: First vertex provided is the center, shared by all triangles
|
2019-04-28 14:45:46 +02:00
|
|
|
void DrawTriangleFan(Vector2 *points, int pointsCount, Color color)
|
|
|
|
{
|
|
|
|
if (pointsCount >= 3)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit((pointsCount - 2)*4)) rlglDraw();
|
|
|
|
|
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
|
|
|
rlBegin(RL_QUADS);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
for (int i = 1; i < pointsCount - 1; i++)
|
|
|
|
{
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(points[0].x, points[0].y);
|
|
|
|
|
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(points[i].x, points[i].y);
|
|
|
|
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
|
|
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
|
|
|
|
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
|
|
|
rlVertex2f(points[i + 1].x, points[i + 1].y);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
rlDisableTexture();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-17 10:29:58 +02:00
|
|
|
// Draw a triangle strip defined by points
|
2019-08-11 21:26:12 +02:00
|
|
|
// NOTE: Every new vertex connects with previous two
|
2019-06-17 10:29:58 +02:00
|
|
|
void DrawTriangleStrip(Vector2 *points, int pointsCount, Color color)
|
|
|
|
{
|
|
|
|
if (pointsCount >= 3)
|
|
|
|
{
|
|
|
|
if (rlCheckBufferLimit(pointsCount)) rlglDraw();
|
|
|
|
|
|
|
|
rlBegin(RL_TRIANGLES);
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
for (int i = 2; i < pointsCount; i++)
|
|
|
|
{
|
|
|
|
if ((i%2) == 0)
|
|
|
|
{
|
|
|
|
rlVertex2f(points[i].x, points[i].y);
|
|
|
|
rlVertex2f(points[i - 2].x, points[i - 2].y);
|
|
|
|
rlVertex2f(points[i - 1].x, points[i - 1].y);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rlVertex2f(points[i].x, points[i].y);
|
|
|
|
rlVertex2f(points[i - 1].x, points[i - 1].y);
|
|
|
|
rlVertex2f(points[i - 2].x, points[i - 2].y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
// Draw a regular polygon of n sides (Vector version)
|
|
|
|
void DrawPoly(Vector2 center, int sides, float radius, float rotation, Color color)
|
|
|
|
{
|
|
|
|
if (sides < 3) sides = 3;
|
2019-09-25 00:08:07 +03:00
|
|
|
float centralAngle = 0.0f;
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-12-24 14:09:51 +01:00
|
|
|
if (rlCheckBufferLimit(4*(360/sides))) rlglDraw();
|
2013-12-19 12:08:06 +01:00
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
rlPushMatrix();
|
2018-12-26 10:51:13 +01:00
|
|
|
rlTranslatef(center.x, center.y, 0.0f);
|
|
|
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-19 09:23:38 +01:00
|
|
|
#if defined(SUPPORT_QUADS_DRAW_MODE)
|
2018-11-06 15:06:01 +01:00
|
|
|
rlEnableTexture(GetShapesTexture().id);
|
2018-04-29 12:53:32 +02:00
|
|
|
|
|
|
|
rlBegin(RL_QUADS);
|
2019-09-22 22:25:39 +03:00
|
|
|
for (int i = 0; i < sides; i++)
|
2018-04-29 12:53:32 +02:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, recTexShapes.y/texShapes.height);
|
2018-04-29 12:53:32 +02:00
|
|
|
rlVertex2f(0, 0);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f(recTexShapes.x/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-09-25 00:08:07 +03:00
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, (recTexShapes.y + recTexShapes.height)/texShapes.height);
|
2019-09-25 00:08:07 +03:00
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2019-09-25 00:08:07 +03:00
|
|
|
centralAngle += 360.0f/(float)sides;
|
2018-11-06 15:06:01 +01:00
|
|
|
rlTexCoord2f((recTexShapes.x + recTexShapes.width)/texShapes.width, recTexShapes.y/texShapes.height);
|
2019-09-25 00:08:07 +03:00
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
2018-04-29 12:53:32 +02:00
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
rlDisableTexture();
|
2018-11-19 09:23:38 +01:00
|
|
|
#else
|
2014-03-25 12:40:35 +01:00
|
|
|
rlBegin(RL_TRIANGLES);
|
2019-09-22 22:25:39 +03:00
|
|
|
for (int i = 0; i < sides; i++)
|
2014-03-25 12:40:35 +01:00
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2016-10-09 20:57:14 +02:00
|
|
|
rlVertex2f(0, 0);
|
2019-09-25 00:08:07 +03:00
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
2019-09-22 22:25:39 +03:00
|
|
|
|
2019-09-25 00:08:07 +03:00
|
|
|
centralAngle += 360.0f/(float)sides;
|
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
2013-12-19 12:08:06 +01:00
|
|
|
}
|
2014-03-25 12:40:35 +01:00
|
|
|
rlEnd();
|
2018-11-19 09:23:38 +01:00
|
|
|
#endif
|
2014-03-25 12:40:35 +01:00
|
|
|
rlPopMatrix();
|
2013-12-19 12:08:06 +01:00
|
|
|
}
|
|
|
|
|
2020-01-09 18:34:20 +01:00
|
|
|
// Draw a polygon outline of n sides
|
|
|
|
void DrawPolyLines(Vector2 center, int sides, float radius, float rotation, Color color)
|
|
|
|
{
|
|
|
|
if (sides < 3) sides = 3;
|
|
|
|
float centralAngle = 0.0f;
|
|
|
|
|
|
|
|
if (rlCheckBufferLimit(3*(360/sides))) rlglDraw();
|
|
|
|
|
|
|
|
rlPushMatrix();
|
|
|
|
rlTranslatef(center.x, center.y, 0.0f);
|
|
|
|
rlRotatef(rotation, 0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
|
|
rlBegin(RL_LINES);
|
|
|
|
for (int i = 0; i < sides; i++)
|
|
|
|
{
|
|
|
|
rlColor4ub(color.r, color.g, color.b, color.a);
|
|
|
|
|
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
|
|
|
centralAngle += 360.0f/(float)sides;
|
|
|
|
rlVertex2f(sinf(DEG2RAD*centralAngle)*radius, cosf(DEG2RAD*centralAngle)*radius);
|
|
|
|
}
|
|
|
|
rlEnd();
|
|
|
|
rlPopMatrix();
|
|
|
|
}
|
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
// Define default texture used to draw shapes
|
|
|
|
void SetShapesTexture(Texture2D texture, Rectangle source)
|
|
|
|
{
|
|
|
|
texShapes = texture;
|
|
|
|
recTexShapes = source;
|
|
|
|
}
|
|
|
|
|
2014-03-25 12:40:35 +01:00
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Module Functions Definition - Collision Detection functions
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
// Check if point is inside rectangle
|
|
|
|
bool CheckCollisionPointRec(Vector2 point, Rectangle rec)
|
|
|
|
{
|
|
|
|
bool collision = false;
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true;
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
return collision;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if point is inside circle
|
|
|
|
bool CheckCollisionPointCircle(Vector2 point, Vector2 center, float radius)
|
|
|
|
{
|
|
|
|
return CheckCollisionCircles(point, 0, center, radius);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if point is inside a triangle defined by three points (p1, p2, p3)
|
|
|
|
bool CheckCollisionPointTriangle(Vector2 point, Vector2 p1, Vector2 p2, Vector2 p3)
|
|
|
|
{
|
|
|
|
bool collision = false;
|
|
|
|
|
|
|
|
float alpha = ((p2.y - p3.y)*(point.x - p3.x) + (p3.x - p2.x)*(point.y - p3.y)) /
|
|
|
|
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
float beta = ((p3.y - p1.y)*(point.x - p3.x) + (p1.x - p3.x)*(point.y - p3.y)) /
|
|
|
|
((p2.y - p3.y)*(p1.x - p3.x) + (p3.x - p2.x)*(p1.y - p3.y));
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
float gamma = 1.0f - alpha - beta;
|
|
|
|
|
|
|
|
if ((alpha > 0) && (beta > 0) & (gamma > 0)) collision = true;
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-12-19 12:08:06 +01:00
|
|
|
return collision;
|
|
|
|
}
|
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
// Check collision between two rectangles
|
|
|
|
bool CheckCollisionRecs(Rectangle rec1, Rectangle rec2)
|
|
|
|
{
|
2018-08-14 09:57:31 +02:00
|
|
|
bool collision = false;
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2019-08-19 12:32:17 +01:00
|
|
|
if ((rec1.x < (rec2.x + rec2.width) && (rec1.x + rec1.width) > rec2.x) &&
|
|
|
|
(rec1.y < (rec2.y + rec2.height) && (rec1.y + rec1.height) > rec2.y)) collision = true;
|
2018-08-14 09:57:31 +02:00
|
|
|
|
|
|
|
return collision;
|
2013-11-30 18:12:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check collision between two circles
|
|
|
|
bool CheckCollisionCircles(Vector2 center1, float radius1, Vector2 center2, float radius2)
|
|
|
|
{
|
|
|
|
bool collision = false;
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
float dx = center2.x - center1.x; // X distance between centers
|
|
|
|
float dy = center2.y - center1.y; // Y distance between centers
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2016-10-31 20:39:03 +01:00
|
|
|
float distance = sqrtf(dx*dx + dy*dy); // Distance between centers
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
if (distance <= (radius1 + radius2)) collision = true;
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
return collision;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check collision between circle and rectangle
|
2015-12-30 13:34:00 +01:00
|
|
|
// NOTE: Reviewed version to take into account corner limit case
|
2013-11-30 18:12:40 +01:00
|
|
|
bool CheckCollisionCircleRec(Vector2 center, float radius, Rectangle rec)
|
|
|
|
{
|
2018-08-05 23:53:34 +02:00
|
|
|
int recCenterX = (int)(rec.x + rec.width/2.0f);
|
|
|
|
int recCenterY = (int)(rec.y + rec.height/2.0f);
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-08-05 23:53:34 +02:00
|
|
|
float dx = (float)fabs(center.x - recCenterX);
|
|
|
|
float dy = (float)fabs(center.y - recCenterY);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-05-04 16:25:31 +02:00
|
|
|
if (dx > (rec.width/2.0f + radius)) { return false; }
|
|
|
|
if (dy > (rec.height/2.0f + radius)) { return false; }
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-05-04 16:25:31 +02:00
|
|
|
if (dx <= (rec.width/2.0f)) { return true; }
|
|
|
|
if (dy <= (rec.height/2.0f)) { return true; }
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2018-11-06 15:10:50 +01:00
|
|
|
float cornerDistanceSq = (dx - rec.width/2.0f)*(dx - rec.width/2.0f) +
|
2019-02-22 12:12:21 +01:00
|
|
|
(dy - rec.height/2.0f)*(dy - rec.height/2.0f);
|
2015-12-30 13:34:00 +01:00
|
|
|
|
|
|
|
return (cornerDistanceSq <= (radius*radius));
|
2013-11-30 18:12:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get collision rectangle for two rectangles collision
|
|
|
|
Rectangle GetCollisionRec(Rectangle rec1, Rectangle rec2)
|
|
|
|
{
|
|
|
|
Rectangle retRec = { 0, 0, 0, 0 };
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
if (CheckCollisionRecs(rec1, rec2))
|
|
|
|
{
|
2018-08-05 23:53:34 +02:00
|
|
|
float dxx = (float)fabs(rec1.x - rec2.x);
|
|
|
|
float dyy = (float)fabs(rec1.y - rec2.y);
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
if (rec1.x <= rec2.x)
|
|
|
|
{
|
|
|
|
if (rec1.y <= rec2.y)
|
2014-09-03 16:51:28 +02:00
|
|
|
{
|
2013-11-30 18:12:40 +01:00
|
|
|
retRec.x = rec2.x;
|
|
|
|
retRec.y = rec2.y;
|
|
|
|
retRec.width = rec1.width - dxx;
|
|
|
|
retRec.height = rec1.height - dyy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
retRec.x = rec2.x;
|
|
|
|
retRec.y = rec1.y;
|
|
|
|
retRec.width = rec1.width - dxx;
|
|
|
|
retRec.height = rec2.height - dyy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (rec1.y <= rec2.y)
|
2014-09-03 16:51:28 +02:00
|
|
|
{
|
2013-11-30 18:12:40 +01:00
|
|
|
retRec.x = rec1.x;
|
|
|
|
retRec.y = rec2.y;
|
|
|
|
retRec.width = rec2.width - dxx;
|
|
|
|
retRec.height = rec1.height - dyy;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
retRec.x = rec1.x;
|
|
|
|
retRec.y = rec1.y;
|
|
|
|
retRec.width = rec2.width - dxx;
|
|
|
|
retRec.height = rec2.height - dyy;
|
|
|
|
}
|
|
|
|
}
|
2016-05-31 19:12:37 +02:00
|
|
|
|
2016-03-16 17:50:51 +01:00
|
|
|
if (rec1.width > rec2.width)
|
|
|
|
{
|
|
|
|
if (retRec.width >= rec2.width) retRec.width = rec2.width;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (retRec.width >= rec1.width) retRec.width = rec1.width;
|
|
|
|
}
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2016-03-16 17:50:51 +01:00
|
|
|
if (rec1.height > rec2.height)
|
|
|
|
{
|
|
|
|
if (retRec.height >= rec2.height) retRec.height = rec2.height;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (retRec.height >= rec1.height) retRec.height = rec1.height;
|
|
|
|
}
|
2013-11-30 18:12:40 +01:00
|
|
|
}
|
2014-09-03 16:51:28 +02:00
|
|
|
|
2013-11-30 18:12:40 +01:00
|
|
|
return retRec;
|
2016-12-31 15:06:39 -08:00
|
|
|
}
|
2017-03-14 00:22:53 +01:00
|
|
|
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
// Module specific Functions Definition
|
|
|
|
//----------------------------------------------------------------------------------
|
|
|
|
|
2018-11-06 15:10:50 +01:00
|
|
|
// Cubic easing in-out
|
2017-03-14 00:22:53 +01:00
|
|
|
// NOTE: Required for DrawLineBezier()
|
2018-11-06 15:10:50 +01:00
|
|
|
static float EaseCubicInOut(float t, float b, float c, float d)
|
|
|
|
{
|
2019-06-16 23:37:16 +02:00
|
|
|
if ((t /= 0.5f*d) < 1) return 0.5f*c*t*t*t + b;
|
2019-09-22 22:25:39 +03:00
|
|
|
|
2017-10-13 13:55:01 +02:00
|
|
|
t -= 2;
|
2019-09-22 22:25:39 +03:00
|
|
|
|
2018-08-05 23:53:34 +02:00
|
|
|
return 0.5f*c*(t*t*t + 2.0f) + b;
|
2017-10-12 19:51:21 +02:00
|
|
|
}
|
2018-11-06 15:06:01 +01:00
|
|
|
|
|
|
|
// Get texture to draw shapes (RAII)
|
|
|
|
static Texture2D GetShapesTexture(void)
|
|
|
|
{
|
2019-10-29 16:03:21 +01:00
|
|
|
if (texShapes.id == 0)
|
2018-11-06 15:06:01 +01:00
|
|
|
{
|
|
|
|
#if defined(SUPPORT_FONT_TEXTURE)
|
|
|
|
texShapes = GetFontDefault().texture; // Use font texture white character
|
BREAKING CHANGE: Read description
Changes:
- Font structure has been redesigned, CharInfo structure contained character rectangle within font texture, it has not much sense, considering that it was an information relative to the font atlas generated and not the character itself, so character rectangles have been moved out from CharInfo to Font.
- CharInfo included a data parameters to contain character pixel data (usually grayscale), generated on TTF font generation. It was inconsistent with other fonts types, so, now CharInfo includes directly an Image of the glyph.
- REDESIGNED: GenImageFontAtlas(), additional recs parameter added, loaded and filled inside the function to export atlas characters rectangles, instead of silently modify the input CharInfo data.
- REVIEWED: ImageTextEx(), funtion retrieved the font atlas image from the GPU, that was slow and problematic in several platforms. Now it uses directly the CharInfo image. Support for unicode codepoints has also been added.
- REDESIGNED: ImageDraw(), now it includes an additional parameter, the color tint, not only it could be useful for several situations but also function signature is more consistent with similar functions.
- ADDED: ImageFromImage() to generate a new image from a piece of another image.
- REVIEWED: GetNextCodepoint(), renamed parameters to be more clear.
Also all examples and games that were affected by those changes have been reviewed.
2019-07-24 15:05:14 +02:00
|
|
|
Rectangle rec = GetFontDefault().recs[95];
|
2018-11-19 09:23:38 +01:00
|
|
|
// NOTE: We setup a 1px padding on char rectangle to avoid texture bleeding on MSAA filtering
|
|
|
|
recTexShapes = (Rectangle){ rec.x + 1, rec.y + 1, rec.width - 2, rec.height - 2 };
|
2018-11-06 15:06:01 +01:00
|
|
|
#else
|
|
|
|
texShapes = GetTextureDefault(); // Use default white texture
|
2019-02-14 12:32:23 +02:00
|
|
|
recTexShapes = (Rectangle){ 0.0f, 0.0f, 1.0f, 1.0f };
|
2018-11-06 15:06:01 +01:00
|
|
|
#endif
|
|
|
|
}
|
2018-11-06 15:10:50 +01:00
|
|
|
|
2018-11-06 15:06:01 +01:00
|
|
|
return texShapes;
|
|
|
|
}
|