diff infinite_canvas/main.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
line wrap: on
line diff
--- a/infinite_canvas/main.c	Mon Aug 17 17:01:40 2026 -0700
+++ b/infinite_canvas/main.c	Mon Aug 17 22:16:14 2026 -0700
@@ -40,21 +40,68 @@
 #if defined(INFINITE_CANVAS_DEV_UI)
     block_pointer_input = Canvas_Dev_UI_Contains_Pointer(&g_app->dev_ui);
 #endif
-    boolean web_input = Canvas_Web_Surface_Update_Input(
+    Canvas_Web_Surface_Set_Dark_Mode(
         &g_app->web_surface,
-        &g_app->camera,
-        &g_app->scene);
-    block_pointer_input = block_pointer_input || web_input;
+        g_app->theme.resolved_mode == CANVAS_THEME_DARK ? TRUE : FALSE);
+    Canvas_Web_Chrome_Action chrome_action = CANVAS_WEB_CHROME_NONE;
+    if (!block_pointer_input) {
+        const char *p_current_url = NULL;
+        if (g_app->scene.selected_index >= 0 &&
+            g_app->scene.selected_index <
+                (int32)Dowa_Array_Length(g_app->scene.p_entities)) {
+            const Canvas_Entity *p_selected =
+                &g_app->scene.p_entities[g_app->scene.selected_index];
+            p_current_url = Canvas_Web_Surface_URL(
+                &g_app->web_surface,
+                p_selected->id);
+        }
+        chrome_action = Canvas_Web_Chrome_Update_Input(
+            &g_app->camera,
+            &g_app->scene,
+            g_app->font,
+            p_current_url);
+    }
+    if (chrome_action == CANVAS_WEB_CHROME_BACK ||
+        chrome_action == CANVAS_WEB_CHROME_FORWARD) {
+        const Canvas_Entity *p_selected =
+            &g_app->scene.p_entities[g_app->scene.selected_index];
+        if (chrome_action == CANVAS_WEB_CHROME_BACK) {
+            Canvas_Web_Surface_Go_Back(
+                &g_app->web_surface,
+                p_selected->id);
+        } else {
+            Canvas_Web_Surface_Go_Forward(
+                &g_app->web_surface,
+                p_selected->id);
+        }
+    }
+    boolean web_input = FALSE;
+    if (!block_pointer_input && chrome_action == CANVAS_WEB_CHROME_NONE) {
+        web_input = Canvas_Web_Surface_Update_Input(
+            &g_app->web_surface,
+            &g_app->camera,
+            &g_app->scene);
+    }
+    block_pointer_input =
+        block_pointer_input ||
+        chrome_action != CANVAS_WEB_CHROME_NONE ||
+        web_input;
     boolean entity_input = Canvas_Scene_Update_Interaction(
         &g_app->scene,
         &g_app->camera,
+        g_app->font,
         block_pointer_input);
     boolean keyboard_focus =
         Canvas_Scene_Is_Text_Editing(&g_app->scene) ||
+        Canvas_Web_Chrome_Is_Editing(&g_app->scene) ||
         Canvas_Web_Surface_Is_Focused(&g_app->web_surface);
     if (!keyboard_focus && IsKeyPressed(KEY_P)) {
         Canvas_Scene_Toggle_Selected_Pin(&g_app->scene, &g_app->camera);
     }
+    if (!keyboard_focus &&
+        (IsKeyPressed(KEY_DELETE) || IsKeyPressed(KEY_BACKSPACE))) {
+        Canvas_Scene_Fade_Out_Selected(&g_app->scene);
+    }
     Canvas_Update_Camera_Input(
         &g_app->camera,
         block_pointer_input || entity_input,
@@ -66,12 +113,47 @@
 
     BeginDrawing();
     ClearBackground(g_app->theme.background);
-    Canvas_Draw_World(
+    Canvas_Draw_World_Background(
+        &g_app->camera,
+        &g_app->scene,
+        &g_app->theme);
+    for (size_t index = 0;
+        index < Dowa_Array_Length(g_app->scene.p_entities);
+        index++) {
+        Canvas_Draw_World_Entity(
+            &g_app->camera,
+            &g_app->scene,
+            index,
+            g_app->font,
+            &g_app->theme);
+        Canvas_Web_Surface_Draw_Entity(
+            &g_app->web_surface,
+            &g_app->camera,
+            &g_app->scene,
+            index);
+        const Canvas_Entity *p_entity = &g_app->scene.p_entities[index];
+        const char *p_url = Canvas_Web_Surface_URL(
+            &g_app->web_surface,
+            p_entity->id);
+        Canvas_Draw_Web_Chrome_Entity(
+            &g_app->camera,
+            &g_app->scene,
+            index,
+            g_app->font,
+            &g_app->theme,
+            p_url ? p_url : p_entity->text,
+            Canvas_Web_Surface_Can_Go_Back(
+                &g_app->web_surface,
+                p_entity->id),
+            Canvas_Web_Surface_Can_Go_Forward(
+                &g_app->web_surface,
+                p_entity->id));
+    }
+    Canvas_Draw_World_Overlays(
         &g_app->camera,
         &g_app->scene,
         g_app->font,
         &g_app->theme);
-    Canvas_Web_Surface_Draw(&g_app->web_surface, &g_app->camera, &g_app->scene);
 #if defined(INFINITE_CANVAS_DEV_UI)
     Canvas_Dev_UI_Draw(
         &g_app->dev_ui,
@@ -131,7 +213,10 @@
 #if !defined(PLATFORM_WEB)
     SetWindowFocused();
 #endif
-    if (!Canvas_Web_Surface_Init(&g_app->web_surface, p_arena)) {
+    if (!Canvas_Web_Surface_Init(
+            &g_app->web_surface,
+            p_arena,
+            g_app->theme.resolved_mode == CANVAS_THEME_DARK ? TRUE : FALSE)) {
         TraceLog(LOG_WARNING, "Web surface initialization failed");
     }