#include "layout_editor.h" #include "raylib.h" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-parameter" #define RAYGUI_IMPLEMENTATION #include "raygui.h" #pragma GCC diagnostic pop #define TITLE_W 400.0f #define TITLE_H 70.0f #define TIME_W 80.0f #define PCT_W 60.0f #define PCT_H 30.0f #define STATUS_W 120.0f #define STATUS_H 40.0f #define HELP_W 600.0f #define HELP_H 30.0f static int dragIndex = -1; static float dragOffsetX = 0.0f; static float dragOffsetY = 0.0f; void layout_editor_init(void) { GuiLoadStyleDefault(); } static Color fillColor = { 60, 60, 80, 100 }; static Color borderColor = { 180, 180, 200, 200 }; static Color highlightColor = { 233, 69, 96, 150 }; static Color labelColor = { 234, 234, 234, 255 }; static const int labelFontSize = 20; static void draw_label(const char *text, Rectangle r, Color fill, Color border) { DrawRectangleRec(r, fill); DrawRectangleLinesEx(r, 2.0f, border); int textY = (int)(r.y + r.height / 2.0f - (float)labelFontSize / 2.0f); DrawText(text, (int)r.x + 10, textY, labelFontSize, labelColor); } void layout_editor_draw(const char *exePath, UILayout *layout) { (void)exePath; Vector2 mouse = GetMousePosition(); /* --- Hit detection on press --- */ if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { dragIndex = -1; /* Check element 6 first, then 5, 4, 3, 2, 1, 0. Later checks overwrite earlier ones if they overlap — priority goes to elements drawn last / on top. */ /* 6: Section nav buttons (two circles) */ { float secPrevX = layout->secNavX - 65.0f; float secNextX = layout->secNavX + 65.0f; float secBtnRadius = 35.0f; float dx1 = mouse.x - secPrevX; float dy1 = mouse.y - layout->secNavY; float dx2 = mouse.x - secNextX; float dy2 = mouse.y - layout->secNavY; if ((dx1 * dx1 + dy1 * dy1 <= secBtnRadius * secBtnRadius) || (dx2 * dx2 + dy2 * dy2 <= secBtnRadius * secBtnRadius)) { dragIndex = 6; dragOffsetX = mouse.x - layout->secNavX; dragOffsetY = mouse.y - layout->secNavY; } } /* 5: Smart play button (HOLD) */ { Rectangle r = { layout->smartPlayX, layout->smartPlayY, 200.0f, 80.0f }; if (CheckCollisionPointRec(mouse, r)) { dragIndex = 5; dragOffsetX = mouse.x - layout->smartPlayX; dragOffsetY = mouse.y - layout->smartPlayY; } } /* 4: Help */ { Rectangle r = { layout->helpX, layout->helpY, HELP_W, HELP_H }; if (CheckCollisionPointRec(mouse, r)) { dragIndex = 4; dragOffsetX = mouse.x - layout->helpX; dragOffsetY = mouse.y - layout->helpY; } } /* 3: Play button (circle) */ { float dx = mouse.x - layout->btnCenterX; float dy = mouse.y - layout->btnY; if (dx * dx + dy * dy <= layout->btnRadius * layout->btnRadius) { dragIndex = 3; dragOffsetX = mouse.x - layout->btnCenterX; dragOffsetY = mouse.y - layout->btnY; } } /* 2: Status */ { Rectangle r = { layout->statusX - STATUS_W / 2.0f, layout->statusY, STATUS_W, STATUS_H }; if (CheckCollisionPointRec(mouse, r)) { dragIndex = 2; dragOffsetX = mouse.x - layout->statusX; dragOffsetY = mouse.y - layout->statusY; } } /* 1: Bar group (bar + time labels + percentage) */ { float gx = layout->barX - 90.0f; float gw = layout->barWidth + 10.0f + 80.0f + 90.0f; float gy = layout->barY - 40.0f; float gh = layout->barHeight + 40.0f; Rectangle group = { gx, gy, gw, gh }; if (CheckCollisionPointRec(mouse, group)) { dragIndex = 1; dragOffsetX = mouse.x - layout->barX; dragOffsetY = mouse.y - layout->barY; } } /* 0: Title */ { Rectangle r = { layout->titleX - TITLE_W / 2.0f, layout->titleY, TITLE_W, TITLE_H }; if (CheckCollisionPointRec(mouse, r)) { dragIndex = 0; dragOffsetX = mouse.x - layout->titleX; dragOffsetY = mouse.y - layout->titleY; } } } /* --- Drag update --- */ if (IsMouseButtonDown(MOUSE_BUTTON_LEFT) && dragIndex >= 0) { switch (dragIndex) { case 0: /* Title */ layout->titleX = mouse.x - dragOffsetX; layout->titleY = mouse.y - dragOffsetY; break; case 1: /* Bar group */ layout->barX = mouse.x - dragOffsetX; layout->barY = mouse.y - dragOffsetY; break; case 2: /* Status */ layout->statusX = mouse.x - dragOffsetX; layout->statusY = mouse.y - dragOffsetY; break; case 3: /* Play button */ layout->btnCenterX = mouse.x - dragOffsetX; layout->btnY = mouse.y - dragOffsetY; break; case 4: /* Help */ layout->helpX = mouse.x - dragOffsetX; layout->helpY = mouse.y - dragOffsetY; break; case 5: /* Smart play */ layout->smartPlayX = mouse.x - dragOffsetX; layout->smartPlayY = mouse.y - dragOffsetY; break; case 6: /* Section nav */ layout->secNavX = mouse.x - dragOffsetX; layout->secNavY = mouse.y - dragOffsetY; break; } } /* --- Release --- */ if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { dragIndex = -1; } Color barFill = (dragIndex == 1) ? highlightColor : fillColor; /* --- 0: Title --- */ { Color f = (dragIndex == 0) ? highlightColor : fillColor; Rectangle r = { layout->titleX - TITLE_W / 2.0f, layout->titleY, TITLE_W, TITLE_H }; draw_label("Title", r, f, borderColor); } /* --- 1: Bar group --- */ /* Percentage above bar (centered on bar's X) */ { Rectangle r = { layout->barX + layout->barWidth / 2.0f - PCT_W / 2.0f, layout->barY - 40.0f, PCT_W, PCT_H }; draw_label("%", r, barFill, borderColor); } /* Elapsed time */ { Rectangle r = { layout->barX - 90.0f, layout->barY, TIME_W, layout->barHeight }; draw_label("Time", r, barFill, borderColor); } /* Bar */ { Rectangle r = { layout->barX, layout->barY, layout->barWidth, layout->barHeight }; draw_label("Bar", r, barFill, borderColor); } /* Remaining time */ { Rectangle r = { layout->barX + layout->barWidth + 10.0f, layout->barY, TIME_W, layout->barHeight }; draw_label("Time", r, barFill, borderColor); } /* --- 2: Status --- */ { Color f = (dragIndex == 2) ? highlightColor : fillColor; Rectangle r = { layout->statusX - STATUS_W / 2.0f, layout->statusY, STATUS_W, STATUS_H }; draw_label("Status", r, f, borderColor); } /* --- 3: Play button --- */ { float cx = layout->btnCenterX; float cy = layout->btnY; float r = layout->btnRadius; Color f = (dragIndex == 3) ? highlightColor : fillColor; DrawCircle((int)cx, (int)cy, r, f); DrawCircleLines((int)cx, (int)cy, r, borderColor); float half = r * 0.5f; Vector2 v1 = { cx - half * 0.7f, cy - half }; Vector2 v2 = { cx - half * 0.7f, cy + half }; Vector2 v3 = { cx + half * 0.8f, cy }; DrawTriangle(v1, v2, v3, labelColor); } /* --- 4: Help --- */ { Color f = (dragIndex == 4) ? highlightColor : fillColor; Rectangle r = { layout->helpX, layout->helpY, HELP_W, HELP_H }; draw_label("Help", r, f, borderColor); } /* --- 5: Smart play button --- */ { Color f = (dragIndex == 5) ? highlightColor : fillColor; Rectangle r = { layout->smartPlayX, layout->smartPlayY, 200.0f, 80.0f }; draw_label("HOLD", r, f, borderColor); } /* --- 6: Section nav buttons --- */ { Color f = (dragIndex == 6) ? highlightColor : fillColor; float secBtnRadius = 35.0f; float secPrevX = layout->secNavX - 65.0f; float secNextX = layout->secNavX + 65.0f; float secCenterY = layout->secNavY; DrawCircle((int)secPrevX, (int)secCenterY, secBtnRadius, f); DrawCircleLines((int)secPrevX, (int)secCenterY, secBtnRadius, borderColor); DrawText("<", (int)secPrevX - MeasureText("<", labelFontSize) / 2, (int)secCenterY - labelFontSize / 2, labelFontSize, labelColor); DrawCircle((int)secNextX, (int)secCenterY, secBtnRadius, f); DrawCircleLines((int)secNextX, (int)secCenterY, secBtnRadius, borderColor); DrawText(">", (int)secNextX - MeasureText(">", labelFontSize) / 2, (int)secCenterY - labelFontSize / 2, labelFontSize, labelColor); const char *secLabel = "Sec"; int secLabelW = MeasureText(secLabel, labelFontSize); DrawText(secLabel, (int)(layout->secNavX - secLabelW / 2.0f), (int)secCenterY - labelFontSize / 2, labelFontSize, labelColor); } }