diff options
Diffstat (limited to 'raylib/examples/shapes')
| -rw-r--r-- | raylib/examples/shapes/raygui.h | 102 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_bouncing_ball.c | 3 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_draw_circle_sector.c | 2 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_lines_bezier.c | 41 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_lines_bezier.png | bin | 17537 -> 17953 bytes | |||
| -rw-r--r-- | raylib/examples/shapes/shapes_lines_splines.c | 155 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_splines_drawing.c | 247 | ||||
| -rw-r--r-- | raylib/examples/shapes/shapes_splines_drawing.png | bin | 0 -> 26123 bytes | |||
| -rw-r--r-- | raylib/examples/shapes/shapes_top_down_lights.c | 1 |
9 files changed, 321 insertions, 230 deletions
diff --git a/raylib/examples/shapes/raygui.h b/raylib/examples/shapes/raygui.h index 26d6bac..9127710 100644 --- a/raylib/examples/shapes/raygui.h +++ b/raylib/examples/shapes/raygui.h @@ -136,7 +136,7 @@ * * #define RAYGUI_DEBUG_RECS_BOUNDS * Draw control bounds rectangles for debug -* +* * #define RAYGUI_DEBUG_TEXT_BOUNDS * Draw text bounds rectangles for debug * @@ -246,7 +246,7 @@ * 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria. * * DEPENDENCIES: -* raylib 4.6-dev Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing * * STANDALONE MODE: * By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled @@ -498,7 +498,7 @@ typedef enum { typedef enum { // Default -> populates to all controls when set DEFAULT = 0, - + // Basic controls LABEL, // Used also for: LABELBUTTON BUTTON, @@ -1775,7 +1775,7 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector { #define RAYGUI_MIN_SCROLLBAR_WIDTH 40 #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40 - + int result = 0; GuiState state = guiState; float mouseWheelSpeed = 20.0f; // Default movement speed with mouse wheel @@ -1806,27 +1806,27 @@ int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; - Rectangle horizontalScrollBar = { - (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), - (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), - (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), - (float)horizontalScrollBarWidth + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth }; - Rectangle verticalScrollBar = { - (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), - (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), - (float)verticalScrollBarWidth, - (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) }; // Make sure scroll bars have a minimum width/height // NOTE: If content >>> bounds, size could be very small or even 0 - if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) + if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) { horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.height vs bounds.height } - if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) + if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) { verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; mouseWheelSpeed = 30.0f; // TODO: Calculate speed increment based on content.width vs bounds.width @@ -2155,7 +2155,7 @@ int GuiToggleSlider(Rectangle bounds, const char *text, int *active) } else state = STATE_FOCUSED; } - + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; } @@ -2625,8 +2625,6 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text { float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; - int codepoint = 0; - int codepointSize = 0; int codepointIndex = 0; float glyphWidth = 0.0f; float widthToMouseX = 0; @@ -2646,7 +2644,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) mouseCursorIndex = i; break; } - + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); } @@ -2655,7 +2653,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode) if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) { mouseCursor.x = textBounds.x + textEndWidth; - mouseCursorIndex = strlen(text); + mouseCursorIndex = (int)strlen(text); } // Place cursor at required index on mouse click @@ -2743,7 +2741,7 @@ bool GuiTextBoxMulti(Rectangle bounds, char *text, int bufferSize, bool editMode GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); - + return pressed; } */ @@ -2937,6 +2935,7 @@ int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, in int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue, int sliderWidth) { int result = 0; + float oldValue = *value; GuiState state = guiState; float temp = (maxValue - minValue)/2.0f; @@ -3006,6 +3005,10 @@ int GuiSliderPro(Rectangle bounds, const char *textLeft, const char *textRight, else if (*value < minValue) *value = minValue; } + // Control value change check + if(oldValue == *value) result = 0; + else result = 1; + // Bar limits check if (sliderWidth > 0) // Slider { @@ -3085,7 +3088,7 @@ int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight if (*value > maxValue) *value = maxValue; // WARNING: Working with floats could lead to rounding issues - if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue) ? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f); + if ((state != STATE_DISABLED)) progress.width = (float)(*value/(maxValue - minValue))*bounds.width - ((*value >= maxValue)? (float)(2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)) : 0.0f); //-------------------------------------------------------------------- // Draw control @@ -3366,8 +3369,7 @@ int GuiColorPanel(Rectangle bounds, const char *text, Color *color) pickerSelector.x = bounds.x + (float)hsv.y*bounds.width; // HSV: Saturation pickerSelector.y = bounds.y + (1.0f - (float)hsv.z)*bounds.height; // HSV: Value - float hue = -1.0f; - Vector3 maxHue = { hue >= 0.0f ? hue : hsv.x, 1.0f, 1.0f }; + Vector3 maxHue = { hsv.x, 1.0f, 1.0f }; Vector3 rgbHue = ConvertHSVtoRGB(maxHue); Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), (unsigned char)(255.0f*rgbHue.y), @@ -3680,8 +3682,7 @@ int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value - float hue = -1.0f; - Vector3 maxHue = { hue >= 0.0f ? hue : colorHsv->x, 1.0f, 1.0f }; + Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f }; Vector3 rgbHue = ConvertHSVtoRGB(maxHue); Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), (unsigned char)(255.0f*rgbHue.y), @@ -3894,12 +3895,14 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect GuiState state = guiState; Vector2 mousePoint = GetMousePosition(); - Vector2 currentMouseCell = { 0 }; + Vector2 currentMouseCell = { -1, -1 }; float spaceWidth = spacing/(float)subdivs; int linesV = (int)(bounds.width/spaceWidth) + 1; int linesH = (int)(bounds.height/spaceWidth) + 1; + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + // Update control //-------------------------------------------------------------------- if ((state != STATE_DISABLED) && !guiLocked && !guiSliderDragging) @@ -3915,28 +3918,23 @@ int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vect // Draw control //-------------------------------------------------------------------- - switch (state) + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) { - case STATE_NORMAL: + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) { - if (subdivs > 0) - { - // Draw vertical grid lines - for (int i = 0; i < linesV; i++) - { - Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height }; - GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA)); - } + Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height }; + GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } - // Draw horizontal grid lines - for (int i = 0; i < linesH; i++) - { - Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 }; - GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(GuiGetStyle(DEFAULT, LINE_COLOR)), RAYGUI_GRID_ALPHA)); - } - } - } break; - default: break; + // Draw horizontal grid lines + for (int i = 0; i < linesH; i++) + { + Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } } if (mouseCell != NULL) *mouseCell = currentMouseCell; @@ -4101,7 +4099,7 @@ void GuiLoadStyleDefault(void) GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); GuiSetStyle(DEFAULT, TEXT_PADDING, 0); GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); - + // Initialize default extended property values // NOTE: By default, extended property values are initialized to 0 GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls @@ -4189,7 +4187,7 @@ const char *GuiIconText(int iconId, const char *text) return NULL; #else static char buffer[1024] = { 0 }; - static char iconBuffer[6] = { 0 }; + static char iconBuffer[16] = { 0 }; if (text != NULL) { @@ -4206,7 +4204,7 @@ const char *GuiIconText(int iconId, const char *text) } else { - sprintf(iconBuffer, "#%03i#", iconId & 0x1ff); + sprintf(iconBuffer, "#%03i#", iconId); return iconBuffer; } @@ -4876,7 +4874,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint else { - // TODO: There are multiple types of spaces in Unicode, + // TODO: There are multiple types of spaces in Unicode, // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph { @@ -4888,7 +4886,7 @@ static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, C DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); } } - else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) { // Draw only glyphs inside the bounds if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) diff --git a/raylib/examples/shapes/shapes_bouncing_ball.c b/raylib/examples/shapes/shapes_bouncing_ball.c index 203d88a..38fade6 100644 --- a/raylib/examples/shapes/shapes_bouncing_ball.c +++ b/raylib/examples/shapes/shapes_bouncing_ball.c @@ -67,9 +67,6 @@ int main(void) // On pause, we draw a blinking message if (pause && ((framesCounter/30)%2)) DrawText("PAUSED", 350, 200, 30, GRAY); - DrawCircle(400.5, 300.5, 50, BLACK); - DrawCircle(528.0, 172.0, 26, BLACK); - DrawFPS(10, 10); EndDrawing(); diff --git a/raylib/examples/shapes/shapes_draw_circle_sector.c b/raylib/examples/shapes/shapes_draw_circle_sector.c index 1c283e1..90e8e6a 100644 --- a/raylib/examples/shapes/shapes_draw_circle_sector.c +++ b/raylib/examples/shapes/shapes_draw_circle_sector.c @@ -70,7 +70,7 @@ int main(void) GuiSliderBar((Rectangle){ 600, 170, 120, 20}, "Segments", NULL, &segments, 0, 100); //------------------------------------------------------------------------------ - minSegments = (int)ceilf((endAngle - startAngle) / 90); + minSegments = truncf(ceilf((endAngle - startAngle) / 90)); DrawText(TextFormat("MODE: %s", (segments >= minSegments)? "MANUAL" : "AUTO"), 600, 200, 10, (segments >= minSegments)? MAROON : DARKGRAY); DrawFPS(10, 10); diff --git a/raylib/examples/shapes/shapes_lines_bezier.c b/raylib/examples/shapes/shapes_lines_bezier.c index f015768..aaad680 100644 --- a/raylib/examples/shapes/shapes_lines_bezier.c +++ b/raylib/examples/shapes/shapes_lines_bezier.c @@ -26,11 +26,10 @@ int main(void) SetConfigFlags(FLAG_MSAA_4X_HINT); InitWindow(screenWidth, screenHeight, "raylib [shapes] example - cubic-bezier lines"); - Vector2 start = { 0, 0 }; - Vector2 end = { (float)screenWidth, (float)screenHeight }; - - Vector2 startControl = { 100, 0 }; - Vector2 endControl = { GetScreenWidth() - 100, GetScreenHeight() }; + Vector2 startPoint = { 30, 30 }; + Vector2 endPoint = { (float)screenWidth - 30, (float)screenHeight - 30 }; + bool moveStartPoint = false; + bool moveEndPoint = false; SetTargetFPS(60); // Set our game to run at 60 frames-per-second //-------------------------------------------------------------------------------------- @@ -40,15 +39,21 @@ int main(void) { // Update //---------------------------------------------------------------------------------- - if (IsKeyDown(KEY_LEFT_CONTROL)) + Vector2 mouse = GetMousePosition(); + + if (CheckCollisionPointCircle(mouse, startPoint, 10.0f) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) moveStartPoint = true; + else if (CheckCollisionPointCircle(mouse, endPoint, 10.0f) && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) moveEndPoint = true; + + if (moveStartPoint) { - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) startControl = GetMousePosition(); - else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) endControl = GetMousePosition(); + startPoint = mouse; + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) moveStartPoint = false; } - else + + if (moveEndPoint) { - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) start = GetMousePosition(); - else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) end = GetMousePosition(); + endPoint = mouse; + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) moveEndPoint = false; } //---------------------------------------------------------------------------------- @@ -58,16 +63,14 @@ int main(void) ClearBackground(RAYWHITE); - DrawText("USE MOUSE LEFT-RIGHT CLICK to DEFINE LINE START and END POINTS", 15, 20, 20, GRAY); + DrawText("MOVE START-END POINTS WITH MOUSE", 15, 20, 20, GRAY); - //DrawLineBezier(start, end, 2.0f, RED); - - DrawLineBezierCubic(start, end, startControl, endControl, 2.0f, RED); + // Draw line Cubic Bezier, in-out interpolation (easing), no control points + DrawLineBezier(startPoint, endPoint, 4.0f, BLUE); - DrawLineEx(start, startControl, 1.0, LIGHTGRAY); - DrawLineEx(end, endControl, 1.0, LIGHTGRAY); - DrawCircleV(startControl, 10, RED); - DrawCircleV(endControl, 10, RED); + // Draw start-end spline circles with some details + DrawCircleV(startPoint, CheckCollisionPointCircle(mouse, startPoint, 10.0f)? 14 : 8, moveStartPoint? RED : BLUE); + DrawCircleV(endPoint, CheckCollisionPointCircle(mouse, endPoint, 10.0f)? 14 : 8, moveEndPoint? RED : BLUE); EndDrawing(); //---------------------------------------------------------------------------------- diff --git a/raylib/examples/shapes/shapes_lines_bezier.png b/raylib/examples/shapes/shapes_lines_bezier.png Binary files differindex 390a49a..aa5edf3 100644 --- a/raylib/examples/shapes/shapes_lines_bezier.png +++ b/raylib/examples/shapes/shapes_lines_bezier.png diff --git a/raylib/examples/shapes/shapes_lines_splines.c b/raylib/examples/shapes/shapes_lines_splines.c deleted file mode 100644 index c020c60..0000000 --- a/raylib/examples/shapes/shapes_lines_splines.c +++ /dev/null @@ -1,155 +0,0 @@ -/******************************************************************************************* -* -* raylib [shapes] example - splines drawing -* -* Example originally created with raylib 4.6-dev, last time updated with raylib 4.6-dev -* -* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, -* BSD-like license that allows static linking with closed source software -* -* Copyright (c) 2023 Ramon Santamaria (@raysan5) -* -********************************************************************************************/ - -#include "raylib.h" - -#define MAX_CONTROL_POINTS 32 - -typedef struct { - Vector2 start; - Vector2 end; -} ControlPoint; - -//------------------------------------------------------------------------------------ -// Program main entry point -//------------------------------------------------------------------------------------ -int main(void) -{ - // Initialization - //-------------------------------------------------------------------------------------- - const int screenWidth = 800; - const int screenHeight = 450; - - SetConfigFlags(FLAG_MSAA_4X_HINT); - InitWindow(screenWidth, screenHeight, "raylib [shapes] example - splines drawing"); - - Vector2 points[MAX_CONTROL_POINTS] = { - { 100.0f, 200.0f }, - { 300.0f, 400.0f }, - { 500.0f, 300.0f }, - { 700.0f, 100.0f }, - { 200.0f, 100.0f }, - }; - - int pointCount = 5; - int selectedPoint = -1; - - int splineType = 0; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier - - // Cubic Bezier control points - ControlPoint control[MAX_CONTROL_POINTS] = { 0 }; - for (int i = 0; i < pointCount - 1; i++) - { - control[i].start = points[i]; - control[i].end = points[i + 1]; - } - - SetTargetFPS(60); // Set our game to run at 60 frames-per-second - //-------------------------------------------------------------------------------------- - - // Main game loop - while (!WindowShouldClose()) // Detect window close button or ESC key - { - // Update - //---------------------------------------------------------------------------------- - // Points movement logic - if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && (pointCount < MAX_CONTROL_POINTS)) - { - points[pointCount] = GetMousePosition(); - pointCount++; - } - - for (int i = 0; i < pointCount; i++) - { - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && CheckCollisionPointCircle(GetMousePosition(), points[i], 6.0f)) - { - selectedPoint = i; - break; - } - } - - if (selectedPoint >= 0) - { - points[selectedPoint] = GetMousePosition(); - if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedPoint = -1; - } - - // TODO: Cubic Bezier spline control points logic - - - // Spline selection logic - if (IsKeyPressed(KEY_ONE)) splineType = 0; - else if (IsKeyPressed(KEY_TWO)) splineType = 1; - else if (IsKeyPressed(KEY_THREE)) splineType = 2; - else if (IsKeyPressed(KEY_FOUR)) splineType = 3; - //---------------------------------------------------------------------------------- - - // Draw - //---------------------------------------------------------------------------------- - BeginDrawing(); - - ClearBackground(RAYWHITE); - - if (splineType == 0) // Linear - { - // Draw linear spline - for (int i = 0; i < pointCount - 1; i++) - { - DrawLineEx(points[i], points[i + 1], 2.0f, RED); - } - } - else if (splineType == 1) // B-Spline - { - // Draw b-spline - DrawLineBSpline(points, pointCount, 2.0f, RED); - //for (int i = 0; i < (pointCount - 3); i++) DrawLineBSplineSegment(points[i], points[i + 1], points[i + 2], points[i + 3], 24.0f, BLUE); - } - else if (splineType == 2) // CatmullRom Spline - { - // Draw spline: catmull-rom - DrawLineCatmullRom(points, pointCount, 2.0f, RED); - //for (int i = 0; i < (pointCount - 3); i++) DrawLineCatmullRomSegment(points[i], points[i + 1], points[i + 2], points[i + 3], 24.0f, Fade(BLUE, 0.4f)); - } - else if (splineType == 3) // Cubic Bezier - { - // Draw line bezier cubic (with control points) - for (int i = 0; i < pointCount - 1; i++) - { - DrawLineBezierCubic(points[i], points[i + 1], control[i].start, control[i + 1].end, 2.0f, RED); - - // TODO: Every cubic bezier point should have two control points - DrawCircleV(control[i].start, 4, GOLD); - DrawCircleV(control[i].end, 4, GOLD); - DrawLineEx(points[i], control[i].start, 1.0, LIGHTGRAY); - DrawLineEx(points[i + 1], control[i].end, 1.0, LIGHTGRAY); - } - } - - // Draw control points - for (int i = 0; i < pointCount; i++) - { - DrawCircleV(points[i], 6.0f, RED); - if ((splineType != 0) && (i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY); - } - - EndDrawing(); - //---------------------------------------------------------------------------------- - } - - // De-Initialization - //-------------------------------------------------------------------------------------- - CloseWindow(); // Close window and OpenGL context - //-------------------------------------------------------------------------------------- - - return 0; -}
\ No newline at end of file diff --git a/raylib/examples/shapes/shapes_splines_drawing.c b/raylib/examples/shapes/shapes_splines_drawing.c new file mode 100644 index 0000000..8df5f09 --- /dev/null +++ b/raylib/examples/shapes/shapes_splines_drawing.c @@ -0,0 +1,247 @@ +/******************************************************************************************* +* +* raylib [shapes] example - splines drawing +* +* Example originally created with raylib 5.0, last time updated with raylib 5.0 +* +* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified, +* BSD-like license that allows static linking with closed source software +* +* Copyright (c) 2023 Ramon Santamaria (@raysan5) +* +********************************************************************************************/ + +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" // Required for UI controls + +#include <stdlib.h> // Required for: NULL + +#define MAX_SPLINE_POINTS 32 + +// Cubic Bezier spline control points +// NOTE: Every segment has two control points +typedef struct { + Vector2 start; + Vector2 end; +} ControlPoint; + +// Spline types +typedef enum { + SPLINE_LINEAR = 0, // Linear + SPLINE_BASIS, // B-Spline + SPLINE_CATMULLROM, // Catmull-Rom + SPLINE_BEZIER // Cubic Bezier +} SplineType; + +//------------------------------------------------------------------------------------ +// Program main entry point +//------------------------------------------------------------------------------------ +int main(void) +{ + // Initialization + //-------------------------------------------------------------------------------------- + const int screenWidth = 800; + const int screenHeight = 450; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(screenWidth, screenHeight, "raylib [shapes] example - splines drawing"); + + Vector2 points[MAX_SPLINE_POINTS] = { + { 50.0f, 400.0f }, + { 160.0f, 220.0f }, + { 340.0f, 380.0f }, + { 520.0f, 60.0f }, + { 710.0f, 260.0f }, + }; + + int pointCount = 5; + int selectedPoint = -1; + int focusedPoint = -1; + Vector2 *selectedControlPoint = NULL; + Vector2 *focusedControlPoint = NULL; + + // Cubic Bezier control points initialization + ControlPoint control[MAX_SPLINE_POINTS] = { 0 }; + for (int i = 0; i < pointCount - 1; i++) + { + control[i].start = (Vector2){ points[i].x + 50, points[i].y }; + control[i].end = (Vector2){ points[i + 1].x - 50, points[i + 1].y }; + } + + // Spline config variables + float splineThickness = 8.0f; + int splineTypeActive = SPLINE_LINEAR; // 0-Linear, 1-BSpline, 2-CatmullRom, 3-Bezier + bool splineTypeEditMode = false; + bool splineHelpersActive = true; + + SetTargetFPS(60); // Set our game to run at 60 frames-per-second + //-------------------------------------------------------------------------------------- + + // Main game loop + while (!WindowShouldClose()) // Detect window close button or ESC key + { + // Update + //---------------------------------------------------------------------------------- + // Spline points creation logic (at the end of spline) + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON) && (pointCount < MAX_SPLINE_POINTS)) + { + points[pointCount] = GetMousePosition(); + pointCount++; + } + + // Spline point focus and selection logic + for (int i = 0; i < pointCount; i++) + { + if (CheckCollisionPointCircle(GetMousePosition(), points[i], 8.0f)) + { + focusedPoint = i; + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) selectedPoint = i; + break; + } + else focusedPoint = -1; + } + + // Spline point movement logic + if (selectedPoint >= 0) + { + points[selectedPoint] = GetMousePosition(); + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedPoint = -1; + } + + // Cubic Bezier spline control points logic + if ((splineTypeActive == SPLINE_BEZIER) && (focusedPoint == -1)) + { + // Spline control point focus and selection logic + for (int i = 0; i < pointCount; i++) + { + if (CheckCollisionPointCircle(GetMousePosition(), control[i].start, 6.0f)) + { + focusedControlPoint = &control[i].start; + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) selectedControlPoint = &control[i].start; + break; + } + else if (CheckCollisionPointCircle(GetMousePosition(), control[i].end, 6.0f)) + { + focusedControlPoint = &control[i].end; + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) selectedControlPoint = &control[i].end; + break; + } + else focusedControlPoint = NULL; + } + + // Spline control point movement logic + if (selectedControlPoint != NULL) + { + *selectedControlPoint = GetMousePosition(); + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) selectedControlPoint = NULL; + } + } + + // Spline selection logic + if (IsKeyPressed(KEY_ONE)) splineTypeActive = 0; + else if (IsKeyPressed(KEY_TWO)) splineTypeActive = 1; + else if (IsKeyPressed(KEY_THREE)) splineTypeActive = 2; + else if (IsKeyPressed(KEY_FOUR)) splineTypeActive = 3; + //---------------------------------------------------------------------------------- + + // Draw + //---------------------------------------------------------------------------------- + BeginDrawing(); + + ClearBackground(RAYWHITE); + + if (splineTypeActive == SPLINE_LINEAR) + { + // Draw spline: linear + DrawSplineLinear(points, pointCount, splineThickness, RED); + } + else if (splineTypeActive == SPLINE_BASIS) + { + // Draw spline: basis + DrawSplineBasis(points, pointCount, splineThickness, RED); // Provide connected points array + + /* + for (int i = 0; i < (pointCount - 3); i++) + { + // Drawing individual segments, not considering thickness connection compensation + DrawSplineSegmentBasis(points[i], points[i + 1], points[i + 2], points[i + 3], splineThickness, MAROON); + } + */ + } + else if (splineTypeActive == SPLINE_CATMULLROM) + { + // Draw spline: catmull-rom + DrawSplineCatmullRom(points, pointCount, splineThickness, RED); // Provide connected points array + + /* + for (int i = 0; i < (pointCount - 3); i++) + { + // Drawing individual segments, not considering thickness connection compensation + DrawSplineSegmentCatmullRom(points[i], points[i + 1], points[i + 2], points[i + 3], splineThickness, MAROON); + } + */ + } + else if (splineTypeActive == SPLINE_BEZIER) + { + // Draw spline: cubic-bezier (with control points) + for (int i = 0; i < pointCount - 1; i++) + { + // Drawing individual segments, not considering thickness connection compensation + DrawSplineSegmentBezierCubic(points[i], control[i].start, control[i].end, points[i + 1], splineThickness, RED); + + // Every cubic bezier point should have two control points + DrawCircleV(control[i].start, 6, GOLD); + DrawCircleV(control[i].end, 6, GOLD); + if (focusedControlPoint == &control[i].start) DrawCircleV(control[i].start, 8, GREEN); + else if (focusedControlPoint == &control[i].end) DrawCircleV(control[i].end, 8, GREEN); + DrawLineEx(points[i], control[i].start, 1.0f, LIGHTGRAY); + DrawLineEx(points[i + 1], control[i].end, 1.0f, LIGHTGRAY); + + // Draw spline control lines + DrawLineV(points[i], control[i].start, GRAY); + //DrawLineV(control[i].start, control[i].end, LIGHTGRAY); + DrawLineV(control[i].end, points[i + 1], GRAY); + } + } + + if (splineHelpersActive) + { + // Draw spline point helpers + for (int i = 0; i < pointCount; i++) + { + DrawCircleLinesV(points[i], (focusedPoint == i)? 12.0f : 8.0f, (focusedPoint == i)? BLUE: DARKBLUE); + if ((splineTypeActive != SPLINE_LINEAR) && + (splineTypeActive != SPLINE_BEZIER) && + (i < pointCount - 1)) DrawLineV(points[i], points[i + 1], GRAY); + + DrawText(TextFormat("[%.0f, %.0f]", points[i].x, points[i].y), points[i].x, points[i].y + 10, 10, BLACK); + } + } + + // Check all possible UI states that require controls lock + if (splineTypeEditMode) GuiLock(); + + // Draw spline config + GuiLabel((Rectangle){ 12, 62, 140, 24 }, TextFormat("Spline thickness: %i", (int)splineThickness)); + GuiSliderBar((Rectangle){ 12, 60 + 24, 140, 16 }, NULL, NULL, &splineThickness, 1.0f, 40.0f); + + GuiCheckBox((Rectangle){ 12, 110, 20, 20 }, "Show point helpers", &splineHelpersActive); + + GuiUnlock(); + + GuiLabel((Rectangle){ 12, 10, 140, 24 }, "Spline type:"); + if (GuiDropdownBox((Rectangle){ 12, 8 + 24, 140, 28 }, "LINEAR;BSPLINE;CATMULLROM;BEZIER", &splineTypeActive, splineTypeEditMode)) splineTypeEditMode = !splineTypeEditMode; + + EndDrawing(); + //---------------------------------------------------------------------------------- + } + + // De-Initialization + //-------------------------------------------------------------------------------------- + CloseWindow(); // Close window and OpenGL context + //-------------------------------------------------------------------------------------- + + return 0; +}
\ No newline at end of file diff --git a/raylib/examples/shapes/shapes_splines_drawing.png b/raylib/examples/shapes/shapes_splines_drawing.png Binary files differnew file mode 100644 index 0000000..686f04c --- /dev/null +++ b/raylib/examples/shapes/shapes_splines_drawing.png diff --git a/raylib/examples/shapes/shapes_top_down_lights.c b/raylib/examples/shapes/shapes_top_down_lights.c index b09137c..f22cf3c 100644 --- a/raylib/examples/shapes/shapes_top_down_lights.c +++ b/raylib/examples/shapes/shapes_top_down_lights.c @@ -335,6 +335,7 @@ int main(void) DrawFPS(screenWidth - 80, 10); DrawText("Drag to move light #1", 10, 10, 10, DARKGREEN); DrawText("Right click to add new light", 10, 30, 10, DARKGREEN); + EndDrawing(); //---------------------------------------------------------------------------------- } |
