comparison 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
comparison
equal deleted inserted replaced
277:1d99147f520c 278:8d560f50ed4c
38 38
39 boolean block_pointer_input = FALSE; 39 boolean block_pointer_input = FALSE;
40 #if defined(INFINITE_CANVAS_DEV_UI) 40 #if defined(INFINITE_CANVAS_DEV_UI)
41 block_pointer_input = Canvas_Dev_UI_Contains_Pointer(&g_app->dev_ui); 41 block_pointer_input = Canvas_Dev_UI_Contains_Pointer(&g_app->dev_ui);
42 #endif 42 #endif
43 boolean web_input = Canvas_Web_Surface_Update_Input( 43 Canvas_Web_Surface_Set_Dark_Mode(
44 &g_app->web_surface, 44 &g_app->web_surface,
45 &g_app->camera, 45 g_app->theme.resolved_mode == CANVAS_THEME_DARK ? TRUE : FALSE);
46 &g_app->scene); 46 Canvas_Web_Chrome_Action chrome_action = CANVAS_WEB_CHROME_NONE;
47 block_pointer_input = block_pointer_input || web_input; 47 if (!block_pointer_input) {
48 const char *p_current_url = NULL;
49 if (g_app->scene.selected_index >= 0 &&
50 g_app->scene.selected_index <
51 (int32)Dowa_Array_Length(g_app->scene.p_entities)) {
52 const Canvas_Entity *p_selected =
53 &g_app->scene.p_entities[g_app->scene.selected_index];
54 p_current_url = Canvas_Web_Surface_URL(
55 &g_app->web_surface,
56 p_selected->id);
57 }
58 chrome_action = Canvas_Web_Chrome_Update_Input(
59 &g_app->camera,
60 &g_app->scene,
61 g_app->font,
62 p_current_url);
63 }
64 if (chrome_action == CANVAS_WEB_CHROME_BACK ||
65 chrome_action == CANVAS_WEB_CHROME_FORWARD) {
66 const Canvas_Entity *p_selected =
67 &g_app->scene.p_entities[g_app->scene.selected_index];
68 if (chrome_action == CANVAS_WEB_CHROME_BACK) {
69 Canvas_Web_Surface_Go_Back(
70 &g_app->web_surface,
71 p_selected->id);
72 } else {
73 Canvas_Web_Surface_Go_Forward(
74 &g_app->web_surface,
75 p_selected->id);
76 }
77 }
78 boolean web_input = FALSE;
79 if (!block_pointer_input && chrome_action == CANVAS_WEB_CHROME_NONE) {
80 web_input = Canvas_Web_Surface_Update_Input(
81 &g_app->web_surface,
82 &g_app->camera,
83 &g_app->scene);
84 }
85 block_pointer_input =
86 block_pointer_input ||
87 chrome_action != CANVAS_WEB_CHROME_NONE ||
88 web_input;
48 boolean entity_input = Canvas_Scene_Update_Interaction( 89 boolean entity_input = Canvas_Scene_Update_Interaction(
49 &g_app->scene, 90 &g_app->scene,
50 &g_app->camera, 91 &g_app->camera,
92 g_app->font,
51 block_pointer_input); 93 block_pointer_input);
52 boolean keyboard_focus = 94 boolean keyboard_focus =
53 Canvas_Scene_Is_Text_Editing(&g_app->scene) || 95 Canvas_Scene_Is_Text_Editing(&g_app->scene) ||
96 Canvas_Web_Chrome_Is_Editing(&g_app->scene) ||
54 Canvas_Web_Surface_Is_Focused(&g_app->web_surface); 97 Canvas_Web_Surface_Is_Focused(&g_app->web_surface);
55 if (!keyboard_focus && IsKeyPressed(KEY_P)) { 98 if (!keyboard_focus && IsKeyPressed(KEY_P)) {
56 Canvas_Scene_Toggle_Selected_Pin(&g_app->scene, &g_app->camera); 99 Canvas_Scene_Toggle_Selected_Pin(&g_app->scene, &g_app->camera);
100 }
101 if (!keyboard_focus &&
102 (IsKeyPressed(KEY_DELETE) || IsKeyPressed(KEY_BACKSPACE))) {
103 Canvas_Scene_Fade_Out_Selected(&g_app->scene);
57 } 104 }
58 Canvas_Update_Camera_Input( 105 Canvas_Update_Camera_Input(
59 &g_app->camera, 106 &g_app->camera,
60 block_pointer_input || entity_input, 107 block_pointer_input || entity_input,
61 keyboard_focus); 108 keyboard_focus);
64 111
65 Canvas_Web_Surface_Sync(&g_app->web_surface, &g_app->camera, &g_app->scene); 112 Canvas_Web_Surface_Sync(&g_app->web_surface, &g_app->camera, &g_app->scene);
66 113
67 BeginDrawing(); 114 BeginDrawing();
68 ClearBackground(g_app->theme.background); 115 ClearBackground(g_app->theme.background);
69 Canvas_Draw_World( 116 Canvas_Draw_World_Background(
117 &g_app->camera,
118 &g_app->scene,
119 &g_app->theme);
120 for (size_t index = 0;
121 index < Dowa_Array_Length(g_app->scene.p_entities);
122 index++) {
123 Canvas_Draw_World_Entity(
124 &g_app->camera,
125 &g_app->scene,
126 index,
127 g_app->font,
128 &g_app->theme);
129 Canvas_Web_Surface_Draw_Entity(
130 &g_app->web_surface,
131 &g_app->camera,
132 &g_app->scene,
133 index);
134 const Canvas_Entity *p_entity = &g_app->scene.p_entities[index];
135 const char *p_url = Canvas_Web_Surface_URL(
136 &g_app->web_surface,
137 p_entity->id);
138 Canvas_Draw_Web_Chrome_Entity(
139 &g_app->camera,
140 &g_app->scene,
141 index,
142 g_app->font,
143 &g_app->theme,
144 p_url ? p_url : p_entity->text,
145 Canvas_Web_Surface_Can_Go_Back(
146 &g_app->web_surface,
147 p_entity->id),
148 Canvas_Web_Surface_Can_Go_Forward(
149 &g_app->web_surface,
150 p_entity->id));
151 }
152 Canvas_Draw_World_Overlays(
70 &g_app->camera, 153 &g_app->camera,
71 &g_app->scene, 154 &g_app->scene,
72 g_app->font, 155 g_app->font,
73 &g_app->theme); 156 &g_app->theme);
74 Canvas_Web_Surface_Draw(&g_app->web_surface, &g_app->camera, &g_app->scene);
75 #if defined(INFINITE_CANVAS_DEV_UI) 157 #if defined(INFINITE_CANVAS_DEV_UI)
76 Canvas_Dev_UI_Draw( 158 Canvas_Dev_UI_Draw(
77 &g_app->dev_ui, 159 &g_app->dev_ui,
78 &g_app->camera, 160 &g_app->camera,
79 &g_app->scene, 161 &g_app->scene,
129 #endif 211 #endif
130 SetTargetFPS(60); 212 SetTargetFPS(60);
131 #if !defined(PLATFORM_WEB) 213 #if !defined(PLATFORM_WEB)
132 SetWindowFocused(); 214 SetWindowFocused();
133 #endif 215 #endif
134 if (!Canvas_Web_Surface_Init(&g_app->web_surface, p_arena)) { 216 if (!Canvas_Web_Surface_Init(
217 &g_app->web_surface,
218 p_arena,
219 g_app->theme.resolved_mode == CANVAS_THEME_DARK ? TRUE : FALSE)) {
135 TraceLog(LOG_WARNING, "Web surface initialization failed"); 220 TraceLog(LOG_WARNING, "Web surface initialization failed");
136 } 221 }
137 222
138 g_app->font = LoadFontEx("infinite_canvas/assets/Inter-Variable.ttf", 48, NULL, 0); 223 g_app->font = LoadFontEx("infinite_canvas/assets/Inter-Variable.ttf", 48, NULL, 0);
139 g_app->owns_font = g_app->font.texture.id != 0; 224 g_app->owns_font = g_app->font.texture.id != 0;