edit mode

This commit is contained in:
jacob 2025-12-16 20:47:21 -06:00
parent 0efcc35696
commit 81990f81a4
5 changed files with 265 additions and 91 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}