From 81990f81a41fde75898b0b5eded1a7fd8269c08b Mon Sep 17 00:00:00 2001 From: jacob Date: Tue, 16 Dec 2025 20:47:21 -0600 Subject: [PATCH] edit mode --- src/gpu/gpu_dx12/gpu_dx12_core.c | 2 +- src/pp/pp_vis/pp_vis_core.c | 295 ++++++++++++++++++++++--------- src/pp/pp_vis/pp_vis_core.h | 11 ++ src/pp/pp_vis/pp_vis_shaders.cgh | 5 + src/pp/pp_vis/pp_vis_shaders.g | 43 +++-- 5 files changed, 265 insertions(+), 91 deletions(-) diff --git a/src/gpu/gpu_dx12/gpu_dx12_core.c b/src/gpu/gpu_dx12/gpu_dx12_core.c index c485338d..3b3a7618 100644 --- a/src/gpu/gpu_dx12/gpu_dx12_core.c +++ b/src/gpu/gpu_dx12/gpu_dx12_core.c @@ -889,7 +889,7 @@ G_ResourceHandle G_PushResource(G_ArenaHandle arena_handle, G_ResourceDesc desc) /* Create d3d heap */ { D3D12_HEAP_DESC d3d_desc = Zi; - d3d_desc.SizeInBytes = Mebi(512); + d3d_desc.SizeInBytes = Mebi(256); if (heap_kind == G_D12_ResourceHeapKind_Cpu) { d3d_desc.Properties.Type = D3D12_HEAP_TYPE_CUSTOM; diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 88fd0bac..f203f65e 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -43,6 +43,11 @@ void V_TickForever(WaveLaneCtx *lane) Struct(Persist) { V_CommandsWidget commands_widget; + + b32 edit_mode; + Vec2 edit_camera_pos; + f32 edit_camera_zoom; + b32 ui_debug; b32 show_command_palette; b32 show_console; @@ -50,8 +55,6 @@ void V_TickForever(WaveLaneCtx *lane) Persist persist = Zi; String window_restore = Zi; - Button held_buttons[Button_Count] = Zi; - /* Init shortcuts */ u64 shortcut_bins_count = 1024; V_ShortcutBin *shortcut_bins = PushStructs(perm, V_ShortcutBin, shortcut_bins_count); @@ -137,6 +140,8 @@ void V_TickForever(WaveLaneCtx *lane) ResetArena(frame->dvert_idxs_arena); G_ResetArena(frame->cl, frame->gpu_arena); + CopyBytes(frame->held_buttons, last_frame->held_buttons, sizeof(frame->held_buttons)); + frame->time_ns = TimeNs(); frame->tick = last_frame->tick + 1; frame->dt_ns = frame->time_ns - last_frame->time_ns; @@ -222,8 +227,8 @@ void V_TickForever(WaveLaneCtx *lane) UI_Report vis_rep = UI_ReportFromKey(vis_box); draw_size = RoundVec2ToI32(DimsFromRng2(vis_rep.screen_rect)); } - draw_size.x = MaxI32(draw_size.x, 1); - draw_size.y = MaxI32(draw_size.y, 1); + draw_size.x = MaxI32(draw_size.x, 64); + draw_size.y = MaxI32(draw_size.y, 64); ////////////////////////////// //- Pop sim output @@ -247,27 +252,127 @@ void V_TickForever(WaveLaneCtx *lane) V.lookup = S_LookupFromWorld(V.world_arena, V.world); } + ////////////////////////////// + //- Process controller events into vis cmds + + u64 cmds_count = 0; + V_CmdNode *first_cmd_node = 0; + V_CmdNode *last_cmd_node = 0; + + if (!window_frame.has_focus) + { + ZeroStructs(frame->held_buttons, countof(frame->held_buttons)); + } + for (u64 i = 0; i < window_frame.controller_events.count; ++i) + { + ControllerEvent cev = window_frame.controller_events.events[i]; + b32 down = cev.kind == ControllerEventKind_ButtonDown; + b32 up = cev.kind == ControllerEventKind_ButtonUp; + if (down || up) + { + V_Hotkey hotkey = Zi; + hotkey.button = cev.button; + hotkey.ctrl = frame->held_buttons[Button_Ctrl]; + hotkey.shift = frame->held_buttons[Button_Shift]; + hotkey.alt = frame->held_buttons[Button_Alt]; + { + u64 hotkey_hash = HashFnv64(Fnv64Basis, StringFromStruct(&hotkey)); + V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count]; + V_Shortcut *shortcut = bin->first; + for (; shortcut; shortcut = shortcut->next_in_bin) + { + if (shortcut->hotkey_hash == hotkey_hash && MatchStruct(&shortcut->hotkey, &hotkey)) + { + break; + } + } + if (shortcut != 0 && down) + { + V_CmdNode *cmd_node = PushStruct(frame->arena, V_CmdNode); + cmd_node->cmd.name = shortcut->cmd_name; + SllQueuePush(first_cmd_node, last_cmd_node, cmd_node); + ++cmds_count; + } + } + frame->held_buttons[hotkey.button] = down; + } + } + + ////////////////////////////// + //- Update edit mode camera position + + f32 zoom_rate = 2; + f32 min_zoom = 0.03; + f32 max_zoom = 50.0; + f32 world_size = 256; + // if (persist.edit_mode) + // { + // if (V.is_panning) + // { + // Vec2 pan_diff = SubVec2(V.pan_end, V.pan_start); + // persist.edit_camera_pos = pan_diff; + // } + // } + if (persist.edit_camera_zoom <= 0) + { + persist.edit_camera_zoom = 1; + } + persist.edit_camera_zoom = ClampF32(persist.edit_camera_zoom, min_zoom, max_zoom); + persist.edit_camera_pos.x = ClampF32(persist.edit_camera_pos.x, -world_size / 2, world_size / 2); + persist.edit_camera_pos.y = ClampF32(persist.edit_camera_pos.y, -world_size / 2, world_size / 2); + ////////////////////////////// //- Initialize camera f32 meters_per_draw_width = 20; - { - f32 lerp_ratio = 20 * frame->dt; - Vec2 look_ratio = Zi; - look_ratio.y = 0.25; - look_ratio.x = look_ratio.y / (16.0 / 9.0); - - Vec2 target_camera_pos = Zi; - f32 target_camera_zoom = 1; + f32 pos_lerp_ratio = 1; + f32 zoom_lerp_ratio = 1; + if (last_frame->tick > 0) { - S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); - target_camera_pos = MulXformV2(player->xf, player->local_shape.centroid); - target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio)); + if (persist.edit_mode) + { + pos_lerp_ratio = 30.0 * frame->dt; + zoom_lerp_ratio = 30.0 * frame->dt; + } + else + { + pos_lerp_ratio = 20.0 * frame->dt; + zoom_lerp_ratio = 20.0 * frame->dt; + } } - frame->camera_pos = LerpVec2(last_frame->camera_pos, target_camera_pos, lerp_ratio); - frame->camera_zoom = LerpF32(last_frame->camera_zoom, target_camera_zoom, lerp_ratio); + + // if (persist.edit_mode && V.is_panning) + // { + // persist.edit_camera_pos = V.pan_begin; + // } + + Vec2 target_camera_pos = persist.edit_camera_pos; + f32 target_camera_zoom = persist.edit_camera_zoom; + { + if (!persist.edit_mode) + { + Vec2 look_ratio = Zi; + look_ratio.y = 0.25; + look_ratio.x = look_ratio.y / (16.0 / 9.0); + S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); + target_camera_pos = MulXformV2(player->xf, player->local_shape.centroid); + target_camera_pos = AddVec2(target_camera_pos, MulVec2Vec2(player->look, look_ratio)); + target_camera_zoom = 1; + } + if (target_camera_zoom <= 0) + { + target_camera_zoom = 1; + } + } + + frame->camera_pos = LerpVec2(last_frame->camera_pos, target_camera_pos, pos_lerp_ratio); + frame->camera_zoom = LerpF32(last_frame->camera_zoom, target_camera_zoom, zoom_lerp_ratio); + + frame->camera_zoom = ClampF32(frame->camera_zoom, min_zoom, max_zoom); + + meters_per_draw_width /= frame->camera_zoom; } ////////////////////////////// @@ -306,52 +411,6 @@ void V_TickForever(WaveLaneCtx *lane) Vec2 draw_cursor = MulXformV2(ui_to_draw_xf, ui_cursor); Vec2 world_cursor = MulXformV2(ui_to_world_xf, ui_cursor); - ////////////////////////////// - //- Process controller events into vis cmds - - u64 cmds_count = 0; - V_CmdNode *first_cmd_node = 0; - V_CmdNode *last_cmd_node = 0; - - if (!window_frame.has_focus) - { - ZeroStructs(held_buttons, countof(held_buttons)); - } - for (u64 i = 0; i < window_frame.controller_events.count; ++i) - { - ControllerEvent cev = window_frame.controller_events.events[i]; - b32 down = cev.kind == ControllerEventKind_ButtonDown; - b32 up = cev.kind == ControllerEventKind_ButtonUp; - if (down || up) - { - V_Hotkey hotkey = Zi; - hotkey.button = cev.button; - hotkey.ctrl = held_buttons[Button_Ctrl]; - hotkey.shift = held_buttons[Button_Shift]; - hotkey.alt = held_buttons[Button_Alt]; - { - u64 hotkey_hash = HashFnv64(Fnv64Basis, StringFromStruct(&hotkey)); - V_ShortcutBin *bin = &shortcut_bins[hotkey_hash % shortcut_bins_count]; - V_Shortcut *shortcut = bin->first; - for (; shortcut; shortcut = shortcut->next_in_bin) - { - if (shortcut->hotkey_hash == hotkey_hash && MatchStruct(&shortcut->hotkey, &hotkey)) - { - break; - } - } - if (shortcut != 0 && down) - { - V_CmdNode *cmd_node = PushStruct(frame->arena, V_CmdNode); - cmd_node->cmd.name = shortcut->cmd_name; - SllQueuePush(first_cmd_node, last_cmd_node, cmd_node); - ++cmds_count; - } - } - held_buttons[hotkey.button] = down; - } - } - ////////////////////////////// //- Build command palette @@ -382,7 +441,7 @@ void V_TickForever(WaveLaneCtx *lane) } ////////////////////////////// - //- Build console + //- Build console UI if (persist.show_console) { @@ -391,7 +450,7 @@ void V_TickForever(WaveLaneCtx *lane) } ////////////////////////////// - //- Build debug info + //- Build debug info UI if (persist.show_console) { @@ -421,9 +480,17 @@ void V_TickForever(WaveLaneCtx *lane) UI_PopCP(UI_TopCP()); } + ////////////////////////////// + //- Build edit mode UI + + if (persist.edit_mode) + { + } + ////////////////////////////// //- Process vis commands + i32 edit_zooms = 0; for (V_CmdNode *cmd_node = first_cmd_node; cmd_node; cmd_node = cmd_node->next) { String cmd_name = cmd_node->cmd.name; @@ -450,6 +517,36 @@ void V_TickForever(WaveLaneCtx *lane) persist.show_command_palette = !persist.show_command_palette; } break; + case V_CmdKind_zoom_in: + { + if (persist.edit_mode) + { + edit_zooms += 1; + } + } break; + + case V_CmdKind_zoom_out: + { + if (persist.edit_mode) + { + edit_zooms -= 1; + } + } break; + + case V_CmdKind_toggle_edit_mode: + { + b32 new = !persist.edit_mode; + if (new) + { + LogInfoF("Enabled edit mode"); + } + else + { + LogInfoF("Disabled edit mode"); + } + persist.edit_mode = new; + } break; + case V_CmdKind_toggle_ui_debug: { persist.ui_debug = !persist.ui_debug; @@ -485,6 +582,52 @@ void V_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Update edit camera + + if (persist.edit_mode) + { + b32 pan_button = Button_M3; + b32 old_is_panning = V.is_panning; + V.is_panning = frame->held_buttons[pan_button] != 0; + b32 is_begin_panning = V.is_panning && !old_is_panning; + if (is_begin_panning) + { + V.ui_pan_begin_cursor = ui_cursor; + } + if (V.is_panning) + { + Vec2 ui_pan_diff = SubVec2(ui_cursor, V.ui_pan_begin_cursor); + Vec2 world_pan_diff = MulXformBasisV2(ui_to_world_xf, ui_pan_diff); + persist.edit_camera_pos = SubVec2(persist.edit_camera_pos, world_pan_diff); + V.ui_pan_begin_cursor = ui_cursor; + } + persist.edit_camera_zoom *= PowF32(zoom_rate, edit_zooms); + } + + ////////////////////////////// + //- Calculate movement & look + + frame->look = last_frame->look; + if (!persist.edit_mode) + { + Vec2 move = Zi; + { + if (frame->held_buttons[Button_A]) move.x -= 1; + if (frame->held_buttons[Button_D]) move.x += 1; + if (frame->held_buttons[Button_W]) move.y -= 1; + if (frame->held_buttons[Button_S]) move.y += 1; + } + Vec2 look = Zi; + { + S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); + Vec2 center = MulXformV2(player->xf, player->local_shape.centroid); + look = SubVec2(world_cursor, center); + } + frame->move = move; + frame->look = look; + } + ////////////////////////////// //- Submit sim commands @@ -502,22 +645,9 @@ void V_TickForever(WaveLaneCtx *lane) cmd = &cmd_node->cmd; } cmd->kind = S_CmdKind_Control; - Vec2 move = Zi; - { - if (held_buttons[Button_A]) move.x -= 1; - if (held_buttons[Button_D]) move.x += 1; - if (held_buttons[Button_W]) move.y -= 1; - if (held_buttons[Button_S]) move.y += 1; - } - Vec2 look = Zi; - { - S_Ent *player = S_EntFromKey(&V.lookup, V.player_key); - Vec2 center = MulXformV2(player->xf, player->local_shape.centroid); - look = SubVec2(world_cursor, center); - } cmd->target = V.player_key; - cmd->move = move; - cmd->look = look; + cmd->move = frame->move; + cmd->look = frame->look; } /* Submit spawn cmds */ @@ -622,6 +752,11 @@ void V_TickForever(WaveLaneCtx *lane) params.background_color_a = LinearFromSrgb(VEC4(0.30, 0.30, 0.30, 1)); params.background_color_b = LinearFromSrgb(VEC4(0.15, 0.15, 0.15, 1)); + params.x_axis_color = LinearFromSrgb(VEC4(0.75, 0, 0, 1)); + params.y_axis_color = LinearFromSrgb(VEC4(0, 0.75, 0, 1)); + params.bounds_color = LinearFromSrgb(VEC4(0.75, 0.75, 0, 1)); + + params.world_size = world_size; params.world_to_draw_xf = world_to_draw_xf; params.draw_to_world_xf = draw_to_world_xf; diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 84f1d82b..e0b6e725 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -5,6 +5,9 @@ X(nop, NOP, V_CmdDescFlag_HideFromPalette, V_HOTKEY(0), ) \ X(exit_program, Exit Program, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_Escape ) ) \ X(toggle_command_palette, Toggle Command Palette, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_P, .ctrl = 1, .shift = 1 ), ) \ + X(zoom_in, Zoom In, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelUp ), ) \ + X(zoom_out, Zoom Out, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_MWheelDown ), ) \ + X(toggle_edit_mode, Toggle Edit Mode, V_CmdDescFlag_None, V_HOTKEY( Button_F1 ), ) \ X(toggle_ui_debug, Toggle UI Debug, V_CmdDescFlag_None, V_HOTKEY( Button_F5 ), ) \ X(toggle_console, Toggle Developer Console, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent ), ) \ X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \ @@ -80,9 +83,14 @@ Struct(V_Frame) Arena *dvert_idxs_arena; G_ArenaHandle gpu_arena; + Button held_buttons[Button_Count]; + Vec2 camera_pos; f32 camera_zoom; + Vec2 move; + Vec2 look; + i64 tick; i64 time_ns; i64 dt_ns; @@ -97,6 +105,9 @@ Struct(V_Ctx) S_Lookup lookup; S_Key player_key; + b32 is_panning; + Vec2 ui_pan_begin_cursor; + Atomic32 shutdown; Fence shutdown_complete; diff --git a/src/pp/pp_vis/pp_vis_shaders.cgh b/src/pp/pp_vis/pp_vis_shaders.cgh index 8a4af443..d1263d35 100644 --- a/src/pp/pp_vis/pp_vis_shaders.cgh +++ b/src/pp/pp_vis/pp_vis_shaders.cgh @@ -16,6 +16,11 @@ Struct(V_DParams) Vec4 background_color_a; Vec4 background_color_b; + Vec4 x_axis_color; + Vec4 y_axis_color; + Vec4 bounds_color; + + f32 world_size; Xform world_to_draw_xf; Xform draw_to_world_xf; diff --git a/src/pp/pp_vis/pp_vis_shaders.g b/src/pp/pp_vis/pp_vis_shaders.g index 2eed9026..09ca60e6 100644 --- a/src/pp/pp_vis/pp_vis_shaders.g +++ b/src/pp/pp_vis/pp_vis_shaders.g @@ -40,22 +40,45 @@ ComputeShader2D(V_BackdropCS, 8, 8) result = colors[color_idx]; } - /* Axis color */ { f32 half_thickness = 1; - Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1)); - f32 x_dist = abs(target_pos.x - zero_screen.x); - f32 y_dist = abs(target_pos.y - zero_screen.y); - if (y_dist <= half_thickness) + f32 half_bounds_size = params.world_size * 0.5; + Vec2 bounds_screen_p0 = mul(params.world_to_draw_xf, Vec3(-half_bounds_size, -half_bounds_size, 1)); + Vec2 bounds_screen_p1 = mul(params.world_to_draw_xf, Vec3(half_bounds_size, half_bounds_size, 1)); + if (target_pos.x > (bounds_screen_p0.x - half_thickness) && target_pos.y > (bounds_screen_p0.y - half_thickness) && + target_pos.x < (bounds_screen_p1.x + half_thickness) && target_pos.y < (bounds_screen_p1.y + half_thickness)) { - result = Color_Red; - } - else if (x_dist <= half_thickness) - { - result = Color_Green; + /* Axis color */ + { + f32 half_thickness = 1; + Vec2 zero_screen = mul(params.world_to_draw_xf, Vec3(0, 0, 1)); + f32 x_dist = abs(target_pos.x - zero_screen.x); + f32 y_dist = abs(target_pos.y - zero_screen.y); + if (y_dist <= half_thickness) + { + result = params.x_axis_color; + } + else if (x_dist <= half_thickness) + { + result = params.y_axis_color; + } + } + /* World bounds color */ + { + f32 bounds_dist = 100000; + bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p0.x)); + bounds_dist = min(bounds_dist, abs(target_pos.x - bounds_screen_p1.x)); + bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p0.y)); + bounds_dist = min(bounds_dist, abs(target_pos.y - bounds_screen_p1.y)); + if (bounds_dist <= half_thickness) + { + result = params.bounds_color; + } + } } } + target[target_pos] = result; } }