Mercurial
comparison infinite_canvas/dev_ui.c @ 278:8d560f50ed4c
Improve infinite canvas interactions and browser chrome
Render Lucide icons directly with Raylib, add searchable icon browsing, robust text editing, entity lifecycle animations, z-order-safe input, semantic themes, and animated editable browser controls. Document rendering, pinning, context, and component extension for future agents.
Co-authored-by: Copilot <[email protected]>
Copilot-Session: f68442b1-fa8f-46a0-9689-81710613bbd4
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Mon, 17 Aug 2026 22:16:14 -0700 |
| parents | b55c22cff335 |
| children | 49e9e591c9bb |
comparison
equal
deleted
inserted
replaced
| 277:1d99147f520c | 278:8d560f50ed4c |
|---|---|
| 3 #include <math.h> | 3 #include <math.h> |
| 4 | 4 |
| 5 #define RAYGUI_IMPLEMENTATION | 5 #define RAYGUI_IMPLEMENTATION |
| 6 #include "third_party/raylib/include/raygui.h" | 6 #include "third_party/raylib/include/raygui.h" |
| 7 | 7 |
| 8 static const Rectangle DEV_PANEL = {18.0f, 18.0f, 264.0f, 436.0f}; | 8 static const Rectangle DEV_PANEL = {18.0f, 18.0f, 264.0f, 478.0f}; |
| 9 | 9 |
| 10 static Rectangle Canvas_Dev_UI_Context_Bounds(void) | 10 static Rectangle Canvas_Dev_UI_Context_Bounds(void) |
| 11 { | 11 { |
| 12 float width = 610.0f; | 12 float width = 610.0f; |
| 13 float x = (float)GetScreenWidth() - width - 18.0f; | 13 float x = (float)GetScreenWidth() - width - 18.0f; |
| 112 (int)p_snapshot->visible_count, | 112 (int)p_snapshot->visible_count, |
| 113 p_snapshot->truncated ? " - output truncated" : ""), | 113 p_snapshot->truncated ? " - output truncated" : ""), |
| 114 (Vector2){panel.x + 20.0f, panel.y + 48.0f}, | 114 (Vector2){panel.x + 20.0f, panel.y + 48.0f}, |
| 115 13.0f, | 115 13.0f, |
| 116 0.0f, | 116 0.0f, |
| 117 p_snapshot->truncated ? (Color){220, 38, 38, 255} : p_theme->text_muted); | 117 p_snapshot->truncated ? p_theme->danger : p_theme->text_muted); |
| 118 | 118 |
| 119 Rectangle close = { | 119 Rectangle close = { |
| 120 panel.x + panel.width - 76.0f, | 120 panel.x + panel.width - 76.0f, |
| 121 panel.y + 16.0f, | 121 panel.y + 16.0f, |
| 122 56.0f, | 122 56.0f, |
| 212 Canvas_Dev_UI_Set_Style(font, p_theme); | 212 Canvas_Dev_UI_Set_Style(font, p_theme); |
| 213 } | 213 } |
| 214 | 214 |
| 215 boolean Canvas_Dev_UI_Contains_Pointer(const Canvas_Dev_UI *p_ui) | 215 boolean Canvas_Dev_UI_Contains_Pointer(const Canvas_Dev_UI *p_ui) |
| 216 { | 216 { |
| 217 // The expanded dropdown is modal: it draws outside DEV_PANEL and also | |
| 218 // consumes outside clicks to close itself. | |
| 219 if (p_ui->dropdown_open) return TRUE; | |
| 220 | |
| 217 Vector2 pointer = GetMousePosition(); | 221 Vector2 pointer = GetMousePosition(); |
| 218 if (CheckCollisionPointRec(pointer, DEV_PANEL)) return TRUE; | 222 if (CheckCollisionPointRec(pointer, DEV_PANEL)) return TRUE; |
| 219 if (p_ui->context_open && | 223 if (p_ui->context_open && |
| 220 CheckCollisionPointRec(pointer, Canvas_Dev_UI_Context_Bounds())) { | 224 CheckCollisionPointRec(pointer, Canvas_Dev_UI_Context_Bounds())) { |
| 221 return TRUE; | 225 return TRUE; |
| 251 (Vector2){34.0f, 61.0f}, | 255 (Vector2){34.0f, 61.0f}, |
| 252 12.0f, | 256 12.0f, |
| 253 0.1f, | 257 0.1f, |
| 254 p_theme->text_muted); | 258 p_theme->text_muted); |
| 255 | 259 |
| 260 if (p_ui->dropdown_open) GuiLock(); | |
| 261 | |
| 256 if (GuiButtonRounded((Rectangle){34.0f, 126.0f, 112.0f, 34.0f}, "Add entity", 0.32f, 10)) { | 262 if (GuiButtonRounded((Rectangle){34.0f, 126.0f, 112.0f, 34.0f}, "Add entity", 0.32f, 10)) { |
| 257 Canvas_Scene_Add( | 263 Canvas_Scene_Add( |
| 258 p_scene, | 264 p_scene, |
| 259 (Canvas_Entity_Type)p_ui->selected_type, | 265 (Canvas_Entity_Type)p_ui->selected_type, |
| 260 p_camera->target); | 266 p_camera->target); |
| 261 } | 267 } |
| 262 if (GuiButtonRounded((Rectangle){154.0f, 126.0f, 112.0f, 34.0f}, "Clear", 0.32f, 10)) { | 268 if (GuiButtonRounded((Rectangle){154.0f, 126.0f, 112.0f, 34.0f}, "Clear", 0.32f, 10)) { |
| 263 Canvas_Scene_Clear(p_scene); | 269 Canvas_Scene_Fade_Out_All(p_scene); |
| 264 } | 270 } |
| 265 if (GuiButtonRounded((Rectangle){34.0f, 168.0f, 72.0f, 34.0f}, "Demo", 0.32f, 10)) { | 271 if (GuiButtonRounded((Rectangle){34.0f, 168.0f, 72.0f, 34.0f}, "Demo", 0.32f, 10)) { |
| 266 Canvas_Scene_Add_Demo(p_scene); | 272 Canvas_Scene_Add_Demo(p_scene); |
| 267 } | 273 } |
| 268 if (GuiButtonRounded((Rectangle){114.0f, 168.0f, 88.0f, 34.0f}, "Reset", 0.32f, 10)) { | 274 if (GuiButtonRounded((Rectangle){114.0f, 168.0f, 88.0f, 34.0f}, "Reset", 0.32f, 10)) { |
| 306 10)) { | 312 10)) { |
| 307 p_ui->context_open = !p_ui->context_open; | 313 p_ui->context_open = !p_ui->context_open; |
| 308 p_ui->context_scroll = 0.0f; | 314 p_ui->context_scroll = 0.0f; |
| 309 } | 315 } |
| 310 | 316 |
| 311 DrawTextEx(font, TextFormat("%d FPS", GetFPS()), (Vector2){34.0f, 354.0f}, 12.0f, 0.0f, p_theme->text_muted); | 317 if (GuiButtonRounded( |
| 312 DrawTextEx(font, TextFormat("%.2fx zoom", p_camera->zoom), (Vector2){104.0f, 354.0f}, 12.0f, 0.0f, p_theme->text_muted); | 318 (Rectangle){34.0f, 336.0f, 232.0f, 34.0f}, |
| 319 "Lucide icon gallery", | |
| 320 0.32f, | |
| 321 10)) { | |
| 322 Canvas_Scene_Show_Lucide_Gallery(p_scene, p_camera); | |
| 323 } | |
| 324 | |
| 325 DrawTextEx(font, TextFormat("%d FPS", GetFPS()), (Vector2){34.0f, 396.0f}, 12.0f, 0.0f, p_theme->text_muted); | |
| 326 DrawTextEx(font, TextFormat("%.2fx zoom", p_camera->zoom), (Vector2){104.0f, 396.0f}, 12.0f, 0.0f, p_theme->text_muted); | |
| 313 DrawTextEx( | 327 DrawTextEx( |
| 314 font, | 328 font, |
| 315 TextFormat("%d objects", (int)Dowa_Array_Length(p_scene->p_entities)), | 329 TextFormat("%d objects", (int)Dowa_Array_Length(p_scene->p_entities)), |
| 316 (Vector2){196.0f, 354.0f}, | 330 (Vector2){196.0f, 396.0f}, |
| 317 12.0f, | 331 12.0f, |
| 318 0.0f, | 332 0.0f, |
| 319 p_theme->text_muted); | 333 p_theme->text_muted); |
| 320 DrawTextEx( | 334 DrawTextEx( |
| 321 font, | 335 font, |
| 322 "Drag objects directly on the canvas", | 336 "Drag objects directly on the canvas", |
| 323 (Vector2){34.0f, 400.0f}, | 337 (Vector2){34.0f, 442.0f}, |
| 324 12.0f, | 338 12.0f, |
| 325 0.0f, | 339 0.0f, |
| 326 p_theme->text_muted); | 340 p_theme->text_muted); |
| 327 | 341 |
| 328 if (p_ui->context_open) { | 342 if (p_ui->context_open) { |
| 332 font, | 346 font, |
| 333 p_theme); | 347 p_theme); |
| 334 } | 348 } |
| 335 | 349 |
| 336 // Draw last so the expanded list overlays the other developer controls. | 350 // Draw last so the expanded list overlays the other developer controls. |
| 351 if (p_ui->dropdown_open) GuiUnlock(); | |
| 337 Rectangle dropdown = {34.0f, 84.0f, 232.0f, 34.0f}; | 352 Rectangle dropdown = {34.0f, 84.0f, 232.0f, 34.0f}; |
| 338 if (GuiDropdownBoxRounded( | 353 if (GuiDropdownBoxRounded( |
| 339 dropdown, | 354 dropdown, |
| 340 "Rectangle;Circle;Line;Text;Button;Text area;Dropdown;Accordion;Card;Calendar;Switch;Table;Notification;Scrollable area;Image;Web content", | 355 "Rectangle;Circle;Line;Text;Button;Text area;Dropdown;Accordion;Card;Calendar;Switch;Table;Notification;Scrollable area;Image;Web content", |
| 341 &p_ui->selected_type, | 356 &p_ui->selected_type, |