REVIEWED: Code formating

This commit is contained in:
Ray 2023-06-17 16:47:51 +02:00
parent c17e0cd5d9
commit e6860d2e06
3 changed files with 272 additions and 232 deletions

View File

@ -37,7 +37,7 @@
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Helper function // Helper function
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
void LoadCurveDefaults(GuiCurveEditState curves[]); void LoadCurveDefaults(GuiCurveEditorState curves[]);
//------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------
// Program main entry point // Program main entry point
@ -73,16 +73,16 @@ int main()
bool showHelp = true; bool showHelp = true;
Rectangle settingsRect = (Rectangle){ screenWidth - screenWidth/3, 0, screenWidth/3, screenHeight }; Rectangle settingsRect = (Rectangle){ screenWidth - screenWidth/3, 0, screenWidth/3, screenHeight };
// Animation curves // Animation curves
// 0 -> Ball X position // 0 -> Ball X position
// 1 -> Ball Y position // 1 -> Ball Y position
// 2 -> Ball Width // 2 -> Ball Width
// 3 -> Ball Height // 3 -> Ball Height
// 4 -> Ball rotation // 4 -> Ball rotation
GuiCurveEditState curves[5] = { 0 }; GuiCurveEditorState curves[5] = { 0 };
LoadCurveDefaults(curves); LoadCurveDefaults(curves);
// Animation time // Animation time
float time = 0.0f; float time = 0.0f;
float animationTime = 4.0f; float animationTime = 4.0f;
@ -102,9 +102,9 @@ int main()
// Ball animation // Ball animation
const float t = time/animationTime; const float t = time/animationTime;
Vector2 ballPos = (Vector2){ EvalGuiCurve(&curves[0], t), EvalGuiCurve(&curves[1], t) }; Vector2 ballPos = (Vector2){ GuiCurveEval(&curves[0], t), GuiCurveEval(&curves[1], t) };
Vector2 ballSize = (Vector2){ EvalGuiCurve(&curves[2], t), EvalGuiCurve(&curves[3], t) }; Vector2 ballSize = (Vector2){ GuiCurveEval(&curves[2], t), GuiCurveEval(&curves[3], t) };
float ballRotation = EvalGuiCurve(&curves[4], t); float ballRotation = GuiCurveEval(&curves[4], t);
// Update style // Update style
if (visualStyleActive != prevVisualStyleActive) if (visualStyleActive != prevVisualStyleActive)
@ -166,11 +166,11 @@ int main()
// Bounds // Bounds
DrawRectangleLines(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL))); DrawRectangleLines(curves[0].start, curves[1].end, curves[0].end-curves[0].start, curves[1].start-curves[1].end+32, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// GUI // GUI
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
if (showHelp) if (showHelp)
{ {
if (GuiWindowBox((Rectangle) {margin, margin, settingsRect.x-2*margin, curves[1].end-2*margin}, "help")) showHelp = false; if (GuiWindowBox((Rectangle) {margin, margin, settingsRect.x-2*margin, curves[1].end-2*margin}, "help")) showHelp = false;
@ -184,7 +184,7 @@ int main()
GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Right click to remove a point"); GuiLabel((Rectangle) {helpTextRect.x, helpTextRect.y+helpTextRect.height, helpTextRect.width, fontSize}, "- Right click to remove a point");
helpTextRect.height += fontSize+margin/2; helpTextRect.height += fontSize+margin/2;
DrawRectangleGradientV(margin, margin+curves[1].end - 2*margin, settingsRect.x - 2*margin, 12, (Color){ 0,0,0,100 }, BLANK); DrawRectangleGradientV(margin, margin+curves[1].end - 2*margin, settingsRect.x - 2*margin, 12, (Color){ 0,0,0,100 }, BLANK);
} }
// Settings panel // Settings panel
GuiScrollPanel(settingsRect, "Settings", contentRect, &scrollOffset, NULL); GuiScrollPanel(settingsRect, "Settings", contentRect, &scrollOffset, NULL);
@ -218,7 +218,7 @@ int main()
GuiComboBox((Rectangle){contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal", &visualStyleActive); GuiComboBox((Rectangle){contentRect.x, contentRect.y+contentRect.height+scrollOffset.y, contentRect.width, 1.5*fontSize }, "default;Jungle;Lavanda;Dark;Bluish;Cyber;Terminal", &visualStyleActive);
contentRect.height += 1.5f*fontSize + margin; contentRect.height += 1.5f*fontSize + margin;
// Draw curves with their controls // Draw curves with their controls
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
@ -229,7 +229,7 @@ int main()
if (GuiLabelButton(headerRect, GuiIconText(sectionActive[i] ? ICON_ARROW_DOWN_FILL : ICON_ARROW_RIGHT_FILL, sectionNames[i]))) sectionActive[i] = !sectionActive[i]; if (GuiLabelButton(headerRect, GuiIconText(sectionActive[i] ? ICON_ARROW_DOWN_FILL : ICON_ARROW_RIGHT_FILL, sectionNames[i]))) sectionActive[i] = !sectionActive[i];
contentRect.height += 1.5f*fontSize + margin; contentRect.height += 1.5f*fontSize + margin;
// Skip this section // Skip this section
if (!sectionActive[i]) continue; if (!sectionActive[i]) continue;
@ -239,15 +239,15 @@ int main()
// Curves can leaks from control boundary... scissor it ! // Curves can leaks from control boundary... scissor it !
BeginScissorMode(curveRect.x, curveRect.y, curveRect.width, curveRect.height); BeginScissorMode(curveRect.x, curveRect.y, curveRect.width, curveRect.height);
GuiCurveEdit(&curves[i],curveRect); GuiCurveEditor(&curves[i],curveRect);
EndScissorMode(); EndScissorMode();
// Resume clipping from setting rect // Resume clipping from setting rect
BeginScissorMode(settingsRect.x, settingsRect.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height); BeginScissorMode(settingsRect.x, settingsRect.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT, settingsRect.width, settingsRect.height);
contentRect.height += fontSize*12 + margin; contentRect.height += fontSize*12 + margin;
// Draw selected point controls // Draw selected point controls
GuiCurveEditPoint *p = &(curves[i].points[curves[i].selectedIndex]); GuiCurveEditorPoint *p = &(curves[i].points[curves[i].selectedIndex]);
GuiCheckBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Left Linear", &p->leftLinear); GuiCheckBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Left Linear", &p->leftLinear);
GuiCheckBox((Rectangle){ contentRect.x+contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Right Linear", &p->rightLinear); GuiCheckBox((Rectangle){ contentRect.x+contentRect.width/2, contentRect.y + contentRect.height + scrollOffset.y, 1.5f*fontSize, 1.5f*fontSize }, "Right Linear", &p->rightLinear);
contentRect.height += 1.5f*fontSize + margin; contentRect.height += 1.5f*fontSize + margin;
@ -257,7 +257,7 @@ int main()
contentRect.height += fontSize; contentRect.height += fontSize;
if (!editValueBox[i][0]) gcvt(p->position.x, 6, valTextBox[i][0]); // Transform x position to string if (!editValueBox[i][0]) gcvt(p->position.x, 6, valTextBox[i][0]); // Transform x position to string
if (!editValueBox[i][1]) gcvt(curves[i].start + (curves[i].end-curves[i].start)*p->position.y, 6, valTextBox[i][1]); // Transform y position to string if (!editValueBox[i][1]) gcvt(curves[i].start + (curves[i].end-curves[i].start)*p->position.y, 6, valTextBox[i][1]); // Transform y position to string
// X pos // X pos
@ -286,15 +286,15 @@ int main()
{ {
// Try to convert text to float and assign it to the point // Try to convert text to float and assign it to the point
char *endPtr = NULL; char *endPtr = NULL;
double value = strtod((char *)valTextBox[i][1], &endPtr); double value = strtod((char *)valTextBox[i][1], &endPtr);
if (endPtr != (char *)valTextBox[i][1]) if (endPtr != (char *)valTextBox[i][1])
{ {
float normalizedVal = (value - curves[i].start)/(curves[i].end - curves[i].start); float normalizedVal = (value - curves[i].start)/(curves[i].end - curves[i].start);
p->position.y = (normalizedVal < 0)? 0 : (normalizedVal > 1)? 1 : normalizedVal; p->position.y = (normalizedVal < 0)? 0 : (normalizedVal > 1)? 1 : normalizedVal;
} }
} }
} }
contentRect.height += 1.5f*fontSize + margin; contentRect.height += 1.5f*fontSize + margin;
@ -311,13 +311,13 @@ int main()
if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2 - margin, 1.5f*fontSize }, valTextBox[i][2], 20, editValueBox[i][2])) if (GuiTextBox((Rectangle){ contentRect.x, contentRect.y + contentRect.height + scrollOffset.y, contentRect.width/2 - margin, 1.5f*fontSize }, valTextBox[i][2], 20, editValueBox[i][2]))
{ {
editValueBox[i][2] = !editValueBox[i][2]; editValueBox[i][2] = !editValueBox[i][2];
// Input ended // Input ended
if (!editValueBox[i][2]) if (!editValueBox[i][2])
{ {
// Try to convert text to float and assign it to the point // Try to convert text to float and assign it to the point
char *endPtr = NULL; char *endPtr = NULL;
double value = strtod((char *)valTextBox[i][2], &endPtr); double value = strtod((char *)valTextBox[i][2], &endPtr);
if (endPtr != (char *)valTextBox[i][2]) p->tangents.x = value; if (endPtr != (char *)valTextBox[i][2]) p->tangents.x = value;
} }
} }
@ -332,7 +332,7 @@ int main()
{ {
// Try to convert text to float and assign it to the point // Try to convert text to float and assign it to the point
char *endPtr = NULL; char *endPtr = NULL;
double value = strtod((char *)valTextBox[i][3], &endPtr); double value = strtod((char *)valTextBox[i][3], &endPtr);
if (endPtr != (char *)valTextBox[i][3]) p->tangents.y = value; if (endPtr != (char *)valTextBox[i][3]) p->tangents.y = value;
} }
} }
@ -341,7 +341,7 @@ int main()
} }
contentRect.height += margin; contentRect.height += margin;
EndScissorMode(); EndScissorMode();
// Settings panel shadow // Settings panel shadow
@ -381,7 +381,7 @@ int main()
return 0; return 0;
} }
void LoadCurveDefaults(GuiCurveEditState curves[]) void LoadCurveDefaults(GuiCurveEditorState curves[])
{ {
// X pos // X pos
curves[0].start = 28; curves[0].start = 28;

View File

@ -8,9 +8,9 @@
* *
* INIT: GuiCurveEditState state = InitCurveEdit(); * INIT: GuiCurveEditState state = InitCurveEdit();
* EVALUATE: float y = EvalGuiCurve(&state, t); // 0 <= t <= 1 * EVALUATE: float y = EvalGuiCurve(&state, t); // 0 <= t <= 1
* DRAW: BeginScissorMode(bounds.x,bounds.y,bounds.width,bounds.height); * DRAW: BeginScissorMode(bounds.x,bounds.y,bounds.width,bounds.height);
* GuiCurveEdit(&state, bounds, pointSize); * GuiCurveEdit(&state, bounds, pointSize);
* EndScissorMode(); * EndScissorMode();
* *
* NOTE: See 'Module Structures Declaration' section for more informations. * NOTE: See 'Module Structures Declaration' section for more informations.
* *
@ -19,7 +19,7 @@
* *
* NOTE: Built-in interactions: * NOTE: Built-in interactions:
* - Left click to move/add point or move tangents * - Left click to move/add point or move tangents
* - While moving a tangent, hold (left/right) SHIFT to disable tangent symetry * - While moving a tangent, hold (left/right) SHIFT to disable tangent symetry
* - Right click to remove a point * - Right click to remove a point
* *
* *
@ -52,34 +52,37 @@
#ifndef GUI_CURVE_EDIT_MAX_POINTS #ifndef GUI_CURVE_EDIT_MAX_POINTS
#define GUI_CURVE_EDIT_MAX_POINTS 30 #define GUI_CURVE_EDIT_MAX_POINTS 30
#endif #endif
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Module Structures Declaration // Module Structures Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
typedef struct { typedef struct {
Vector2 position; // In normalized space [0.f, 1.f] Vector2 position; // In normalized space [0.0f, 1.0f]
Vector2 tangents; // The derivatives (left/right) of the 1D curve Vector2 tangents; // The derivatives (left/right) of the 1D curve
// Let the curve editor calculate tangents to linearize part of the curve // Let the curve editor calculate tangents to linearize part of the curve
bool leftLinear; bool leftLinear;
bool rightLinear; bool rightLinear;
} GuiCurveEditPoint; } GuiCurveEditorPoint;
typedef struct { typedef struct {
float start; // Value at y = 0 float start; // Value at y = 0
float end; // Value at y = 1 float end; // Value at y = 1
// Always valid (unless you manualy change state's point array). Make sure to set it to -1 before init // Always valid (unless you manualy change state's point array). Make sure to set it to -1 before init
int selectedIndex; int selectedIndex;
// Unsorted array with at least one point (constant curve) // Unsorted array with at least one point (constant curve)
GuiCurveEditPoint points[GUI_CURVE_EDIT_MAX_POINTS]; GuiCurveEditorPoint points[GUI_CURVE_EDIT_MAX_POINTS];
int numPoints; int numPoints;
// private part // Private variables
bool editLeftTangent; bool editLeftTangent;
bool editRightTangent; bool editRightTangent;
Vector2 mouseOffset; Vector2 mouseOffset;
} GuiCurveEditState; } GuiCurveEditorState;
#ifdef __cplusplus #ifdef __cplusplus
@ -90,15 +93,14 @@ extern "C" { // Prevents name mangling of functions
// Module Functions Declaration // Module Functions Declaration
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Initialize state
GuiCurveEditState InitGuiCurveEdit(); GuiCurveEditorState GuiInitCurveEditor(); // Initialize curve editor state
// Draw and update curve control void GuiCurveEditor(GuiCurveEditorState *state, Rectangle bounds); // Draw and update curve control
void GuiCurveEdit(GuiCurveEditState *state, Rectangle bounds);
// 1D Interpolation // 1D Interpolation
// Returns the y value (in [start, end]) of the curve at x = t // Returns the y value (in [start, end]) of the curve at x = t
// t must be normalized [0.f, 1.f] // t must be normalized [0.f, 1.f]
float EvalGuiCurve(GuiCurveEditState *state, float t); float GuiCurveEval(GuiCurveEditorState *state, float t);
#ifdef __cplusplus #ifdef __cplusplus
} }
@ -121,177 +123,186 @@ float EvalGuiCurve(GuiCurveEditState *state, float t);
// Module Functions Definition // Module Functions Definition
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
GuiCurveEditState InitGuiCurveEdit() GuiCurveEditorState GuiInitCurveEditor()
{ {
GuiCurveEditState state; GuiCurveEditorState state = { 0 };
state.start = 0; state.start = 0;
state.end = 1; state.end = 1;
state.selectedIndex = 0; state.selectedIndex = 0;
state.editLeftTangent = false; state.editLeftTangent = false;
state.editRightTangent = false; state.editRightTangent = false;
state.mouseOffset = (Vector2) {0.f,0.f}; state.mouseOffset = (Vector2){ 0.0f, 0.0f };
// At least one point (AVG by default) // At least one point (AVG by default)
state.numPoints = 1; state.numPoints = 1;
state.points[0].position = (Vector2) {0.5f,0.5f}; state.points[0].position = (Vector2){ 0.5f, 0.5f };
state.points[0].tangents = (Vector2) {0.f,0.f}; state.points[0].tangents = (Vector2){ 0.0f, 0.0f };
state.points[0].leftLinear = false; state.points[0].leftLinear = false;
state.points[0].rightLinear = false; state.points[0].rightLinear = false;
return state; return state;
} }
int CompareGuiCurveEditPointPtr (const void * a, const void * b) static int CompareGuiCurveEditPointPtr(const void *a, const void *b)
{ {
float fa = (*(GuiCurveEditPoint**)a)->position.x; float fa = (*(GuiCurveEditorPoint**)a)->position.x;
float fb = (*(GuiCurveEditPoint**)b)->position.x; float fb = (*(GuiCurveEditorPoint**)b)->position.x;
return (fa > fb) - (fa < fb);
return ((fa > fb) - (fa < fb));
} }
float EvalGuiCurve(GuiCurveEditState *state, float t){ float GuiCurveEval(GuiCurveEditorState *state, float t)
{
// Sort points // Sort points
GuiCurveEditPoint* sortedPoints[GUI_CURVE_EDIT_MAX_POINTS]; GuiCurveEditorPoint* sortedPoints[GUI_CURVE_EDIT_MAX_POINTS];
for(int i=0; i < state->numPoints; i++){
sortedPoints[i] = &state->points[i];
}
qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditPoint*), CompareGuiCurveEditPointPtr);
if(state->numPoints == 0) for (int i=0; i < state->numPoints; i++) sortedPoints[i] = &state->points[i];
return state->start;
qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditorPoint*), CompareGuiCurveEditPointPtr);
if (state->numPoints == 0) return state->start;
// Constants part on edges // Constants part on edges
if(t <= sortedPoints[0]->position.x) if (t <= sortedPoints[0]->position.x) return state->start + (state->end-state->start)*sortedPoints[0]->position.y;
return state->start + (state->end-state->start) * sortedPoints[0]->position.y; if (t >= sortedPoints[state->numPoints-1]->position.x) return state->start + (state->end-state->start)*sortedPoints[state->numPoints-1]->position.y;
if(t >= sortedPoints[state->numPoints-1]->position.x)
return state->start + (state->end-state->start) * sortedPoints[state->numPoints-1]->position.y;
// Find curve portion // Find curve portion
for(int i=0; i < state->numPoints-1; i++){ for (int i=0; i < state->numPoints-1; i++)
const GuiCurveEditPoint* p1 = sortedPoints[i]; {
const GuiCurveEditPoint* p2 = sortedPoints[i+1]; const GuiCurveEditorPoint *p1 = sortedPoints[i];
const GuiCurveEditorPoint *p2 = sortedPoints[i+1];
// Skip this range // Skip this range
if(!(t >= p1->position.x && t < p2->position.x) || p1->position.x == p2->position.x) if (!((t >= p1->position.x) && (t < p2->position.x)) || (p1->position.x == p2->position.x)) continue;
continue;
float scale = (p2->position.x-p1->position.x); float scale = (p2->position.x-p1->position.x);
float T = (t-p1->position.x)/scale; float T = (t-p1->position.x)/scale;
float startTangent = scale * p1->tangents.y; float startTangent = scale*p1->tangents.y;
float endTangent = scale * p2->tangents.x; float endTangent = scale*p2->tangents.x;
float T2 = T*T; float T2 = T*T;
float T3 = T*T*T; float T3 = T*T*T;
return state->start + (state->end-state->start) * ((2*T3-3*T2+1)*p1->position.y+(T3-2*T2+T)*startTangent+(3*T2-2*T3)*p2->position.y+(T3-T2)*endTangent);
return (state->start + (state->end-state->start)*((2*T3 - 3*T2 + 1)*p1->position.y + (T3 - 2*T2 + T)*startTangent + (3*T2 - 2*T3)*p2->position.y + (T3 - T2)*endTangent));
} }
return state->start; return state->start;
} }
void GuiCurveEdit(GuiCurveEditState *state, Rectangle bounds){ void GuiCurveEditor(GuiCurveEditorState *state, Rectangle bounds)
{
//----------------------------------------------------------------------------------
// CONST // CONST
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
const float pointSize = 10; const float pointSize = 10.0f;
const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE); const float fontSize = GuiGetStyle(DEFAULT, TEXT_SIZE);
const float handleLength = pointSize*2.5; const float handleLength = pointSize*2.5f;
const float handleSize = pointSize/1.5f; const float handleSize = pointSize/1.5f;
const Rectangle innerBounds = (Rectangle){bounds.x+fontSize, bounds.y+fontSize, bounds.width-2*fontSize, bounds.height-2*fontSize}; const Rectangle innerBounds = (Rectangle){ bounds.x + fontSize, bounds.y + fontSize, bounds.width - 2*fontSize, bounds.height - 2*fontSize };
const Vector2 mouse = GetMousePosition(); const Vector2 mouse = GetMousePosition();
const Vector2 mouseLocal = (Vector2) {(mouse.x-innerBounds.x)/innerBounds.width, (innerBounds.y+innerBounds.height-mouse.y)/innerBounds.height}; const Vector2 mouseLocal = (Vector2){ (mouse.x - innerBounds.x)/innerBounds.width, (innerBounds.y + innerBounds.height-mouse.y)/innerBounds.height};
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// UPDATE STATE // UPDATE STATE
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Find first point under mouse (-1 if not found) // Find first point under mouse (-1 if not found)
int hoveredPointIndex = -1; int hoveredPointIndex = -1;
for(int i=0; i < state->numPoints; i++){ for (int i = 0; i < state->numPoints; i++)
const GuiCurveEditPoint* p = &state->points[i]; {
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; const GuiCurveEditorPoint *p = &state->points[i];
const Rectangle pointRect = (Rectangle) {screenPos.x-pointSize/2.f, screenPos.y-pointSize/2.f, pointSize, pointSize}; const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height-p->position.y*innerBounds.height };
if(CheckCollisionPointRec(mouse, pointRect)){ const Rectangle pointRect = (Rectangle){ screenPos.x - pointSize/2.0f, screenPos.y - pointSize/2.0f, pointSize, pointSize };
if (CheckCollisionPointRec(mouse, pointRect))
{
hoveredPointIndex = i; hoveredPointIndex = i;
break; break;
} }
} }
// Unselect tangents // Unselect tangents
if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){ if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT))
{
state->editLeftTangent = false; state->editLeftTangent = false;
state->editRightTangent = false; state->editRightTangent = false;
} }
// Select a tangent if possible // Select a tangent if possible
if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && state->selectedIndex != -1 && CheckCollisionPointRec(mouse, bounds)){ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (state->selectedIndex != -1) && CheckCollisionPointRec(mouse, bounds))
const GuiCurveEditPoint* p = &state->points[state->selectedIndex]; {
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; const GuiCurveEditorPoint* p = &state->points[state->selectedIndex];
const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height };
// Left control // Left control
Vector2 target = (Vector2) {(p->position.x-1)*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-(p->position.y-p->tangents.x)*innerBounds.height}; Vector2 target = (Vector2){ (p->position.x-1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y-p->tangents.x)*innerBounds.height };
Vector2 dir = (Vector2) {target.x-screenPos.x, target.y-screenPos.y}; Vector2 dir = (Vector2){ target.x-screenPos.x, target.y-screenPos.y };
float d = sqrt(dir.x*dir.x+dir.y*dir.y); float d = sqrt(dir.x*dir.x + dir.y*dir.y);
Vector2 control = (Vector2) {screenPos.x+dir.x/d*handleLength, screenPos.y+dir.y/d*handleLength}; Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
Rectangle controlRect = (Rectangle) {control.x-handleSize/2.f, control.y-handleSize/2.f, handleSize, handleSize}; Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
// Edit left tangent // Edit left tangent
if(CheckCollisionPointRec(mouse, controlRect)){ if (CheckCollisionPointRec(mouse, controlRect)) state->editLeftTangent = true;
state->editLeftTangent = true;
}
// Right control // Right control
target = (Vector2) {(p->position.x+1)*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-(p->position.y+p->tangents.y)*innerBounds.height}; target = (Vector2){ (p->position.x + 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y + p->tangents.y)*innerBounds.height };
dir = (Vector2) {target.x-screenPos.x, target.y-screenPos.y}; dir = (Vector2){ target.x-screenPos.x, target.y-screenPos.y };
d = sqrt(dir.x*dir.x+dir.y*dir.y); d = sqrt(dir.x*dir.x + dir.y*dir.y);
control = (Vector2) {screenPos.x+dir.x/d*handleLength, screenPos.y+dir.y/d*handleLength}; control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
controlRect = (Rectangle) {control.x-handleSize/2.f, control.y-handleSize/2.f, handleSize, handleSize}; controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
// Edit right tangent // Edit right tangent
if(CheckCollisionPointRec(mouse, controlRect)){ if (CheckCollisionPointRec(mouse, controlRect)) state->editRightTangent = true;
state->editRightTangent = true;
}
} }
// Move tangents // Move tangents
if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editRightTangent){ if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editRightTangent)
{
// editRightTangent == true implies selectedIndex != -1 // editRightTangent == true implies selectedIndex != -1
GuiCurveEditPoint* p = &state->points[state->selectedIndex]; GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height-p->position.y*innerBounds.height };
const Vector2 dir = (Vector2){mouseLocal.x-p->position.x, mouseLocal.y-p->position.y}; const Vector2 dir = (Vector2){ mouseLocal.x - p->position.x, mouseLocal.y - p->position.y};
// Calculate right tangent slope
p->tangents.y = dir.x < 0.001f ? dir.y/0.001f : dir.y/dir.x; // Calculate right tangent slope
p->tangents.y = (dir.x < 0.001f)? dir.y/0.001f : dir.y/dir.x;
p->rightLinear = false; // Stop right linearization update p->rightLinear = false; // Stop right linearization update
// Tangents are symetric by default unless SHIFT is pressed // Tangents are symetric by default unless SHIFT is pressed
if(!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT))){ if (!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)))
{
p->tangents.x = p->tangents.y; p->tangents.x = p->tangents.y;
p->leftLinear = false; // Stop left linearization update p->leftLinear = false; // Stop left linearization update
} }
} else if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editLeftTangent){ }
else if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && state->editLeftTangent)
{
// editLeftTangent == true implies selectedIndex != -1 // editLeftTangent == true implies selectedIndex != -1
GuiCurveEditPoint* p = &state->points[state->selectedIndex]; GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height-p->position.y*innerBounds.height };
const Vector2 dir = (Vector2){mouseLocal.x-p->position.x, mouseLocal.y-p->position.y}; const Vector2 dir = (Vector2){ mouseLocal.x - p->position.x, mouseLocal.y - p->position.y };
// Calculate left tangent slope
p->tangents.x = dir.x > -0.001f ? dir.y/(-0.001f) : dir.y/dir.x; // Calculate left tangent slope
p->tangents.x = (dir.x > -0.001f)? dir.y/(-0.001f) : dir.y/dir.x;
p->leftLinear = false; // Stop left linearization update p->leftLinear = false; // Stop left linearization update
// Tangents are symetric by default unless SHIFT is pressed // Tangents are symetric by default unless SHIFT is pressed
if(!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT))){ if (!(IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT)))
{
p->tangents.y = p->tangents.x; p->tangents.y = p->tangents.x;
p->rightLinear = false; // Stop right linearization update p->rightLinear = false; // Stop right linearization update
} }
} }
// Select a point // Select a point
else if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && hoveredPointIndex != -1 && CheckCollisionPointRec(mouse, bounds)){ else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && (hoveredPointIndex != -1) && CheckCollisionPointRec(mouse, bounds))
{
state->selectedIndex = hoveredPointIndex; state->selectedIndex = hoveredPointIndex;
const GuiCurveEditPoint* p = &state->points[state->selectedIndex]; const GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p->position.y*innerBounds.height };
state->mouseOffset = (Vector2) {p->position.x - mouseLocal.x, p->position.y - mouseLocal.y}; state->mouseOffset = (Vector2){ p->position.x - mouseLocal.x, p->position.y - mouseLocal.y };
} }
// Remove a point (check against bounds) // Remove a point (check against bounds)
else if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) && hoveredPointIndex != -1 && CheckCollisionPointRec(mouse, bounds) && state->numPoints > 1){ else if (IsMouseButtonPressed(MOUSE_BUTTON_RIGHT) && (hoveredPointIndex != -1) && CheckCollisionPointRec(mouse, bounds) && (state->numPoints > 1))
{
// Deselect everything // Deselect everything
state->selectedIndex = 0; // select first point by default state->selectedIndex = 0; // select first point by default
state->editLeftTangent = false; state->editLeftTangent = false;
@ -299,70 +310,72 @@ void GuiCurveEdit(GuiCurveEditState *state, Rectangle bounds){
// Remove point // Remove point
state->numPoints -= 1; state->numPoints -= 1;
for(int i=hoveredPointIndex; i < state->numPoints; i++ ){ for (int i = hoveredPointIndex; i < state->numPoints; i++) state->points[i] = state->points[i+1];
state->points[i] = state->points[i+1]; }
}
// Add a point (check against innerBounds) // Add a point (check against innerBounds)
} else if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, innerBounds) && state->numPoints < GUI_CURVE_EDIT_MAX_POINTS){ else if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, innerBounds) && (state->numPoints < GUI_CURVE_EDIT_MAX_POINTS))
{
state->editLeftTangent = false; state->editLeftTangent = false;
state->editRightTangent = false; state->editRightTangent = false;
// Create new point // Create new point
GuiCurveEditPoint p; GuiCurveEditorPoint p;
p.tangents = (Vector2) {0.f, 0.f}; p.tangents = (Vector2){ 0.0f, 0.0f };
p.position = mouseLocal; p.position = mouseLocal;
p.leftLinear = false; p.leftLinear = false;
p.rightLinear = false; p.rightLinear = false;
// Append point // Append point
state->points[state->numPoints] = p; state->points[state->numPoints] = p;
state->selectedIndex = state->numPoints; // select new point state->selectedIndex = state->numPoints; // select new point
state->numPoints += 1; state->numPoints += 1;
// Point is add on mouse pos
state->mouseOffset = (Vector2) {0,0};
// Point is add on mouse pos
state->mouseOffset = (Vector2){ 0, 0 };
}
// Move selected point // Move selected point
} else if(state->selectedIndex != -1 && IsMouseButtonDown(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, bounds) ){ else if ((state->selectedIndex != -1) && IsMouseButtonDown(MOUSE_BUTTON_LEFT) && CheckCollisionPointRec(mouse, bounds))
GuiCurveEditPoint* p = &state->points[state->selectedIndex]; {
GuiCurveEditorPoint *p = &state->points[state->selectedIndex];
// use mouse offset on click to prevent point teleporting to mouse // use mouse offset on click to prevent point teleporting to mouse
const Vector2 newLocalPos = (Vector2){mouseLocal.x + state->mouseOffset.x, mouseLocal.y + state->mouseOffset.y}; const Vector2 newLocalPos = (Vector2){ mouseLocal.x + state->mouseOffset.x, mouseLocal.y + state->mouseOffset.y };
// Clamp to innerbounds // Clamp to innerbounds
p->position.x = newLocalPos.x < 0 ? 0 : newLocalPos.x > 1 ? 1 : newLocalPos.x; p->position.x = (newLocalPos.x < 0)? 0 : ((newLocalPos.x > 1)? 1 : newLocalPos.x);
p->position.y = newLocalPos.y < 0 ? 0 : newLocalPos.y > 1 ? 1 : newLocalPos.y; p->position.y = (newLocalPos.y < 0)? 0 : ((newLocalPos.y > 1)? 1 : newLocalPos.y);
} }
// Sort points // Sort points
GuiCurveEditPoint* sortedPoints[GUI_CURVE_EDIT_MAX_POINTS]; GuiCurveEditorPoint *sortedPoints[GUI_CURVE_EDIT_MAX_POINTS] = { 0 };
for(int i=0; i < state->numPoints; i++){ for (int i = 0; i < state->numPoints; i++) sortedPoints[i] = &state->points[i];
sortedPoints[i] = &state->points[i]; qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditorPoint*), CompareGuiCurveEditPointPtr);
}
qsort(sortedPoints, state->numPoints, sizeof(GuiCurveEditPoint*), CompareGuiCurveEditPointPtr);
// Update linear tangents // Update linear tangents
for(int i=0; i < state->numPoints; i++){ for (int i = 0; i < state->numPoints; i++)
GuiCurveEditPoint* p = sortedPoints[i]; {
GuiCurveEditorPoint *p = sortedPoints[i];
// Left tangent // Left tangent
if(i > 0 && p->leftLinear){ if ((i > 0) && p->leftLinear)
const GuiCurveEditPoint* p2 = sortedPoints[i-1]; {
Vector2 dir = (Vector2) {p2->position.x-p->position.x, p2->position.y-p->position.y}; const GuiCurveEditorPoint *p2 = sortedPoints[i - 1];
p->tangents.x = dir.x == 0 ? 0 : dir.y/dir.x; Vector2 dir = (Vector2){ p2->position.x - p->position.x, p2->position.y - p->position.y };
p->tangents.x = (dir.x == 0)? 0 : dir.y/dir.x;
} }
// Right tangent // Right tangent
if(i < state->numPoints-1 && p->rightLinear){ if ((i < state->numPoints - 1) && p->rightLinear)
const GuiCurveEditPoint* p2 = sortedPoints[i+1]; {
Vector2 dir = (Vector2) {p2->position.x-p->position.x, p2->position.y-p->position.y}; const GuiCurveEditorPoint *p2 = sortedPoints[i + 1];
p->tangents.y = dir.x == 0 ? 0 : dir.y/dir.x; Vector2 dir = (Vector2){ p2->position.x - p->position.x, p2->position.y - p->position.y };
p->tangents.y = (dir.x == 0)? 0 : dir.y/dir.x;
} }
} }
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// DRAWING // DRAWING
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
// Draw bg
DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); DrawRectangle(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
// Draw grid // Draw grid
@ -374,88 +387,103 @@ void GuiCurveEdit(GuiCurveEditState *state, Rectangle bounds){
// V lines // V lines
DrawLine(innerBounds.x, bounds.y, innerBounds.x, bounds.y+bounds.height, lineColor); // 0 DrawLine(innerBounds.x, bounds.y, innerBounds.x, bounds.y+bounds.height, lineColor); // 0
DrawLine(innerBounds.x+innerBounds.width/4, bounds.y, innerBounds.x+innerBounds.width/4, bounds.y+bounds.height, lineColor); // 0.25 DrawLine(innerBounds.x + innerBounds.width/4, bounds.y, innerBounds.x + innerBounds.width/4, bounds.y + bounds.height, lineColor); // 0.25
DrawLine(innerBounds.x+innerBounds.width/2, bounds.y, innerBounds.x+innerBounds.width/2, bounds.y+bounds.height, lineColor); // 0.5 DrawLine(innerBounds.x + innerBounds.width/2, bounds.y, innerBounds.x + innerBounds.width/2, bounds.y + bounds.height, lineColor); // 0.5
DrawLine(innerBounds.x+3*innerBounds.width/4, bounds.y, innerBounds.x+3*innerBounds.width/4, bounds.y+bounds.height, lineColor); // 0.75 DrawLine(innerBounds.x + 3*innerBounds.width/4, bounds.y, innerBounds.x + 3*innerBounds.width/4, bounds.y + bounds.height, lineColor); // 0.75
DrawLine(innerBounds.x+innerBounds.width, bounds.y, innerBounds.x+innerBounds.width, bounds.y+bounds.height, lineColor); // 1 DrawLine(innerBounds.x + innerBounds.width, bounds.y, innerBounds.x + innerBounds.width, bounds.y + bounds.height, lineColor); // 1
Font font = GuiGetFont(); Font font = GuiGetFont();
// V labels // V labels
DrawTextEx(font, "0", (Vector2) {innerBounds.x, bounds.y+bounds.height-fontSize}, fontSize,GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, "0", (Vector2){ innerBounds.x, bounds.y + bounds.height-fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, "0.25", (Vector2) {innerBounds.x+innerBounds.width/4.f, bounds.y+bounds.height-fontSize}, fontSize,GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, "0.25", (Vector2){ innerBounds.x + innerBounds.width/4.0f, bounds.y + bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, "0.5", (Vector2) {innerBounds.x+innerBounds.width/2.f, bounds.y+bounds.height-fontSize}, fontSize,GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, "0.5", (Vector2){ innerBounds.x + innerBounds.width/2.0f, bounds.y + bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, "0.75", (Vector2) {innerBounds.x+3.f*innerBounds.width/4.f, bounds.y+bounds.height-fontSize}, fontSize,GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, "0.75", (Vector2){ innerBounds.x + 3.0f*innerBounds.width/4.0f, bounds.y + bounds.height-fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, "1", (Vector2) {innerBounds.x+innerBounds.width, bounds.y+bounds.height-fontSize}, fontSize,GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, "1", (Vector2){ innerBounds.x + innerBounds.width, bounds.y+bounds.height - fontSize}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
// H labels // H labels
DrawTextEx(font, TextFormat("%.2f", state->start), (Vector2) {innerBounds.x, innerBounds.y-fontSize+innerBounds.height}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, TextFormat("%.2f", state->start), (Vector2){ innerBounds.x, innerBounds.y - fontSize+innerBounds.height }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, TextFormat("%.2f", state->start + (state->end-state->start)/2.f), (Vector2) {innerBounds.x, innerBounds.y-fontSize+innerBounds.height/2.f}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, TextFormat("%.2f", state->start + (state->end-state->start)/2.f), (Vector2){ innerBounds.x, innerBounds.y - fontSize + innerBounds.height/2.0f }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
DrawTextEx(font, TextFormat("%.2f", state->end), (Vector2) {innerBounds.x, innerBounds.y}, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor); DrawTextEx(font, TextFormat("%.2f", state->end), (Vector2){ innerBounds.x, innerBounds.y }, fontSize, GuiGetStyle(DEFAULT, TEXT_SPACING), lineColor);
// Draw contours // Draw contours
if(CheckCollisionPointRec(mouse, bounds)) if (CheckCollisionPointRec(mouse, bounds)) DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_FOCUSED)));
DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_FOCUSED))); else DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
else
DrawRectangleLines(bounds.x, bounds.y, bounds.width, bounds.height, GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)));
// Draw points // Draw points
for(int i=0; i < state->numPoints; i++){ for (int i = 0; i < state->numPoints; i++)
{
const GuiCurveEditorPoint *p = sortedPoints[i];
const GuiCurveEditPoint* p = sortedPoints[i]; const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p->position.y*innerBounds.height };
const Rectangle pointRect = (Rectangle){ screenPos.x - pointSize/2.0f, screenPos.y - pointSize/2.0f, pointSize, pointSize };
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; Color pointColor = { 0 };
const Rectangle pointRect = (Rectangle) {screenPos.x-pointSize/2.f, screenPos.y-pointSize/2.f, pointSize, pointSize}; Color pointBorderColor = { 0 };
Color pointColor;
Color pointBorderColor;
// Draw point // Draw point
if(&state->points[state->selectedIndex] == p){ if (&state->points[state->selectedIndex] == p)
{
// Draw left handle // Draw left handle
if(i > 0){ if (i > 0)
const Vector2 target = (Vector2) {(p->position.x-1)*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-(p->position.y-p->tangents.x)*innerBounds.height}; {
const Vector2 dir = (Vector2) {target.x-screenPos.x, target.y-screenPos.y}; const Vector2 target = (Vector2){ (p->position.x - 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y - p->tangents.x)*innerBounds.height };
const float d = sqrt(dir.x*dir.x+dir.y*dir.y); const Vector2 dir = (Vector2){ target.x - screenPos.x, target.y - screenPos.y };
const Vector2 control = (Vector2) {screenPos.x+dir.x/d*handleLength, screenPos.y+dir.y/d*handleLength}; const float d = sqrt(dir.x*dir.x + dir.y*dir.y);
const Rectangle controlRect = (Rectangle) {control.x-handleSize/2.f, control.y-handleSize/2.f, handleSize, handleSize}; const Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
const Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
Color controlColor; Color controlColor = { 0 };
Color controlBorderColor; Color controlBorderColor = { 0 };
if(state->editLeftTangent){
if (state->editLeftTangent)
{
controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED)); controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
} else if(CheckCollisionPointRec(mouse, controlRect)){ }
else if (CheckCollisionPointRec(mouse, controlRect))
{
controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED)); controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
}else{ }
else
{
controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)); controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
controlBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL));
} }
DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor); DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor);
DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor); DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor); DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
} }
// Draw right handle
if(i < state->numPoints-1){
const Vector2 target = (Vector2) {(p->position.x+1)*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-(p->position.y+p->tangents.y)*innerBounds.height};
const Vector2 dir = (Vector2) {target.x-screenPos.x, target.y-screenPos.y};
const float d = sqrt(dir.x*dir.x+dir.y*dir.y);
const Vector2 control = (Vector2) {screenPos.x+dir.x/d*handleLength, screenPos.y+dir.y/d*handleLength};
const Rectangle controlRect = (Rectangle) {control.x-handleSize/2.f, control.y-handleSize/2.f, handleSize, handleSize};
Color controlColor; // Draw right handle
Color controlBorderColor; if (i < state->numPoints - 1)
if(state->editRightTangent){ {
const Vector2 target = (Vector2){ (p->position.x + 1)*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - (p->position.y + p->tangents.y)*innerBounds.height };
const Vector2 dir = (Vector2){ target.x - screenPos.x, target.y - screenPos.y };
const float d = sqrt(dir.x*dir.x + dir.y*dir.y);
const Vector2 control = (Vector2){ screenPos.x + dir.x/d*handleLength, screenPos.y + dir.y/d*handleLength };
const Rectangle controlRect = (Rectangle){ control.x - handleSize/2.0f, control.y - handleSize/2.0f, handleSize, handleSize };
Color controlColor = { 0 };
Color controlBorderColor = { 0 };
if (state->editRightTangent)
{
controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED)); controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
} else if(CheckCollisionPointRec(mouse, controlRect)){ }
else if (CheckCollisionPointRec(mouse, controlRect))
{
controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED)); controlColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
}else{ }
else
{
controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)); controlColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
controlBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL)); controlBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL));
} }
DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor); DrawLine(screenPos.x,screenPos.y, control.x, control.y, controlColor);
DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor); DrawRectangle(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor); DrawRectangleLines(controlRect.x, controlRect.y, controlRect.width, controlRect.height, controlColor);
@ -464,49 +492,61 @@ void GuiCurveEdit(GuiCurveEditState *state, Rectangle bounds){
pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED)); pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_PRESSED));
pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
} else if(&state->points[hoveredPointIndex] == p) { }
else if (&state->points[hoveredPointIndex] == p)
{
pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED)); pointColor = GetColor(GuiGetStyle(DEFAULT, BASE_COLOR_FOCUSED));
pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL)); pointBorderColor = GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_NORMAL));
} else { }
else
{
pointColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL)); pointColor = GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL));
pointBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL)); pointBorderColor = GetColor(GuiGetStyle(BUTTON, BORDER_COLOR_NORMAL));
} }
DrawRectangle(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointColor); DrawRectangle(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointColor);
DrawRectangleLines(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointBorderColor); DrawRectangleLines(pointRect.x, pointRect.y, pointRect.width, pointRect.height, pointBorderColor);
} }
// Draw curve // Draw curve
Color curveColor = GetColor(GuiGetStyle(LABEL, TEXT_COLOR_FOCUSED)); Color curveColor = GetColor(GuiGetStyle(LABEL, TEXT_COLOR_FOCUSED));
if(state->numPoints == 1){
const GuiCurveEditPoint* p = sortedPoints[0]; if (state->numPoints == 1)
const Vector2 screenPos = (Vector2){p->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p->position.y*innerBounds.height}; {
const GuiCurveEditorPoint *p = sortedPoints[0];
const Vector2 screenPos = (Vector2){ p->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p->position.y*innerBounds.height };
DrawLine(innerBounds.x, screenPos.y, innerBounds.x+innerBounds.width, screenPos.y, curveColor); DrawLine(innerBounds.x, screenPos.y, innerBounds.x+innerBounds.width, screenPos.y, curveColor);
}else { }
for(int i=0; i < state->numPoints-1; i++){ else
const GuiCurveEditPoint* p1 = sortedPoints[i]; {
const GuiCurveEditPoint* p2 = sortedPoints[i+1]; for (int i = 0; i < state->numPoints - 1; i++)
const Vector2 screenPos1 = (Vector2){p1->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p1->position.y*innerBounds.height}; {
const Vector2 screenPos2 = (Vector2){p2->position.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-p2->position.y*innerBounds.height}; const GuiCurveEditorPoint *p1 = sortedPoints[i];
const GuiCurveEditorPoint *p2 = sortedPoints[i + 1];
const Vector2 screenPos1 = (Vector2){ p1->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p1->position.y*innerBounds.height };
const Vector2 screenPos2 = (Vector2){ p2->position.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - p2->position.y*innerBounds.height };
// Constant on edge // Constant on edge
if(screenPos1.x > innerBounds.x && i == 0){ if ((screenPos1.x > innerBounds.x) && (i == 0))
{
DrawLine(innerBounds.x, screenPos1.y, screenPos1.x, screenPos1.y, curveColor); DrawLine(innerBounds.x, screenPos1.y, screenPos1.x, screenPos1.y, curveColor);
} }
if(screenPos2.x < innerBounds.x+innerBounds.width && i == (state->numPoints-2)){ if ((screenPos2.x < innerBounds.x + innerBounds.width) && (i == (state->numPoints - 2)))
{
DrawLine(screenPos2.x, screenPos2.y, innerBounds.x+innerBounds.width, screenPos2.y, curveColor); DrawLine(screenPos2.x, screenPos2.y, innerBounds.x+innerBounds.width, screenPos2.y, curveColor);
} }
// Draw cubic Hermite curve // Draw cubic Hermite curve
const float scale = (p2->position.x-p1->position.x)/3.f; const float scale = (p2->position.x - p1->position.x)/3.0f;
const Vector2 offset1 = (Vector2) {scale, scale*p1->tangents.y}; const Vector2 offset1 = (Vector2){ scale, scale*p1->tangents.y };
// negative endTangent => top part => need to invert value to calculate offset // negative endTangent => top part => need to invert value to calculate offset
const Vector2 offset2 = (Vector2) {-scale, -scale*p2->tangents.x}; const Vector2 offset2 = (Vector2){ -scale, -scale*p2->tangents.x };
const Vector2 c1 = (Vector2) {p1->position.x+offset1.x, p1->position.y+offset1.y}; const Vector2 c1 = (Vector2){ p1->position.x + offset1.x, p1->position.y + offset1.y };
const Vector2 c2 = (Vector2) {p2->position.x+offset2.x, p2->position.y+offset2.y}; const Vector2 c2 = (Vector2){ p2->position.x + offset2.x, p2->position.y + offset2.y };
const Vector2 screenC1 = (Vector2) {c1.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-c1.y*innerBounds.height}; const Vector2 screenC1 = (Vector2){ c1.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - c1.y*innerBounds.height };
const Vector2 screenC2 = (Vector2) {c2.x*innerBounds.width+innerBounds.x, innerBounds.y+innerBounds.height-c2.y*innerBounds.height}; const Vector2 screenC2 = (Vector2){ c2.x*innerBounds.width + innerBounds.x, innerBounds.y + innerBounds.height - c2.y*innerBounds.height };
DrawLineBezierCubic(screenPos1, screenPos2, screenC1, screenC2, 1, curveColor); DrawLineBezierCubic(screenPos1, screenPos2, screenC1, screenC2, 1, curveColor);
} }

View File

@ -2361,7 +2361,7 @@ int GuiTextBox(Rectangle bounds, char *text, int bufferSize, bool editMode)
text[textLength] = '\0'; text[textLength] = '\0';
} }
} }
// Delete codepoint from text, before current cursor position // Delete codepoint from text, before current cursor position
if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN)))) if ((textLength > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && (autoCursorCooldownCounter >= RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN))))
{ {
@ -3349,9 +3349,9 @@ int GuiColorPicker(Rectangle bounds, const char *text, Color *color)
//Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) };
Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f });
GuiColorBarHue(boundsHue, NULL, &hsv.x); GuiColorBarHue(boundsHue, NULL, &hsv.x);
//color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f);
Vector3 rgb = ConvertHSVtoRGB(hsv); Vector3 rgb = ConvertHSVtoRGB(hsv);