/*******************************************************************************************
							 | 
						|
								*
							 | 
						|
								*   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;
							 | 
						|
								}
							 |