base blend time off of accumulated prediction tick
This commit is contained in:
parent
1caf006e33
commit
63c3b4d427
@ -5,9 +5,8 @@ V_Ctx V = Zi;
|
|||||||
|
|
||||||
void V_Bootstrap(void)
|
void V_Bootstrap(void)
|
||||||
{
|
{
|
||||||
V.timeline.transient_markers_arena = AcquireArena(Gibi(64));
|
V.transient_markers_arena = AcquireArena(Gibi(64));
|
||||||
V.timeline.persistent_markers_arena = AcquireArena(Gibi(64));
|
V.persistent_markers_arena = AcquireArena(Gibi(64));
|
||||||
V.timeline.show = 1;
|
|
||||||
DispatchWave(Lit("Vis"), 1, V_TickForever, 0);
|
DispatchWave(Lit("Vis"), 1, V_TickForever, 0);
|
||||||
OnExit(V_Shutdown);
|
OnExit(V_Shutdown);
|
||||||
}
|
}
|
||||||
@ -260,16 +259,17 @@ void V_DrawPoint(Vec2 p, Vec4 srgb)
|
|||||||
|
|
||||||
void V_PushTimelineMarker(i64 time_ns, Vec4 color, b32 transient)
|
void V_PushTimelineMarker(i64 time_ns, Vec4 color, b32 transient)
|
||||||
{
|
{
|
||||||
if (!V.timeline.paused)
|
V_Frame *prev_frame = V_PrevFrame();
|
||||||
|
if (!prev_frame->prev_timeline.paused)
|
||||||
{
|
{
|
||||||
V_TimelineMarker *marker = 0;
|
V_TimelineMarker *marker = 0;
|
||||||
if (transient)
|
if (transient)
|
||||||
{
|
{
|
||||||
marker = PushStruct(V.timeline.transient_markers_arena, V_TimelineMarker);
|
marker = PushStruct(V.transient_markers_arena, V_TimelineMarker);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
marker = PushStruct(V.timeline.persistent_markers_arena, V_TimelineMarker);
|
marker = PushStruct(V.persistent_markers_arena, V_TimelineMarker);
|
||||||
}
|
}
|
||||||
marker->time_ns = time_ns;
|
marker->time_ns = time_ns;
|
||||||
marker->color = color;
|
marker->color = color;
|
||||||
@ -603,9 +603,13 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->equipped_prefab = prev_frame->equipped_prefab ;
|
frame->equipped_prefab = prev_frame->equipped_prefab ;
|
||||||
frame->edit_camera_pos = prev_frame->edit_camera_pos;
|
frame->edit_camera_pos = prev_frame->edit_camera_pos;
|
||||||
frame->edit_camera_zoom = prev_frame->edit_camera_zoom;
|
frame->edit_camera_zoom = prev_frame->edit_camera_zoom;
|
||||||
|
frame->prev_timeline = prev_frame->timeline;
|
||||||
|
frame->timeline = prev_frame->timeline;
|
||||||
frame->sim_key = prev_frame->sim_key;
|
frame->sim_key = prev_frame->sim_key;
|
||||||
frame->desired_sim_key = prev_frame->desired_sim_key;
|
frame->desired_sim_key = prev_frame->desired_sim_key;
|
||||||
|
frame->target_predict_tick_accum = prev_frame->target_predict_tick_accum;
|
||||||
frame->predict_tick_accum = prev_frame->predict_tick_accum;
|
frame->predict_tick_accum = prev_frame->predict_tick_accum;
|
||||||
|
frame->blend_tick = prev_frame->blend_tick;
|
||||||
frame->af = prev_frame->af;
|
frame->af = prev_frame->af;
|
||||||
|
|
||||||
frame->tick = V.cur_frame_tick;
|
frame->tick = V.cur_frame_tick;
|
||||||
@ -621,6 +625,12 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
TrueRand(StringFromStruct(&V.player_key));
|
TrueRand(StringFromStruct(&V.player_key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (frame->tick == 1)
|
||||||
|
{
|
||||||
|
frame->timeline.show = 1;
|
||||||
|
frame->timeline.locked = 1;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Initialize persistent gpu resources
|
//- Initialize persistent gpu resources
|
||||||
|
|
||||||
@ -1359,6 +1369,13 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Determine local simulation bounds
|
//- Determine local simulation bounds
|
||||||
//
|
//
|
||||||
@ -1373,6 +1390,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
f64 dilation_factor = 0;
|
f64 dilation_factor = 0;
|
||||||
{
|
{
|
||||||
|
// TODO: Warm start
|
||||||
|
|
||||||
// How many buffered commands of ours we'd like the server to have
|
// How many buffered commands of ours we'd like the server to have
|
||||||
i64 target_buffered_controls_count = 1;
|
i64 target_buffered_controls_count = 1;
|
||||||
f64 rtt_bias_factor = 10.0;
|
f64 rtt_bias_factor = 10.0;
|
||||||
@ -1383,12 +1402,21 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
target_buffered_controls_count - remote_buffered_controls_count
|
target_buffered_controls_count - remote_buffered_controls_count
|
||||||
) * 2 - 1;
|
) * 2 - 1;
|
||||||
|
|
||||||
f64 predict_dt = frame->dt + frame->dt * dilation_factor;
|
f64 target_predict_dt = frame->dt + frame->dt * dilation_factor;
|
||||||
frame->predict_tick_accum += predict_dt * SIM_TICKS_PER_SECOND;
|
frame->target_predict_tick_accum += target_predict_dt * SIM_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
// Warm start
|
||||||
|
frame->predict_tick_accum += frame->dt * SIM_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
f64 lerp_rate = 5.0 * frame->dt;
|
||||||
|
// f64 lerp_rate = 1.0 * frame->dt;
|
||||||
|
// f64 lerp_rate = 1;
|
||||||
|
frame->predict_tick_accum = LerpF64(frame->predict_tick_accum, frame->target_predict_tick_accum, lerp_rate);
|
||||||
|
|
||||||
if (ack == 0 || AbsF64(frame->predict_tick_accum - ack) > SIM_TICKS_PER_SECOND)
|
if (ack == 0 || AbsF64(frame->predict_tick_accum - ack) > SIM_TICKS_PER_SECOND)
|
||||||
{
|
{
|
||||||
frame->predict_tick_accum = ack + (SIM_TICKS_PER_SECOND * smoothed_rtt * 0.5);
|
frame->target_predict_tick_accum = ack + (SIM_TICKS_PER_SECOND * smoothed_rtt * 0.5);
|
||||||
|
frame->predict_tick_accum = frame->target_predict_tick_accum;
|
||||||
LogDebugF("RESET");
|
LogDebugF("RESET");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1402,10 +1430,98 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// );
|
// );
|
||||||
|
|
||||||
frame->predict_tick_accum = MaxF64(prev_frame->predict_tick_accum, frame->predict_tick_accum);
|
frame->predict_tick_accum = MaxF64(prev_frame->predict_tick_accum, frame->predict_tick_accum);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
V_PushTimelineMarker(frame->predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Red, 1);
|
||||||
|
V_PushTimelineMarker(frame->target_predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||||
}
|
}
|
||||||
i64 prev_frame_predict_to = FloorF64(prev_frame->predict_tick_accum);
|
i64 prev_frame_predict_to = FloorF64(prev_frame->predict_tick_accum);
|
||||||
i64 predict_to = FloorF64(frame->predict_tick_accum);
|
i64 predict_to = FloorF64(frame->predict_tick_accum);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //////////////////////////////
|
||||||
|
// //- Determine local simulation bounds
|
||||||
|
// //
|
||||||
|
// // Prediction rate will increase based on how many commands of ours we know
|
||||||
|
// // that the server has buffered up or is missing.
|
||||||
|
// //
|
||||||
|
// // If the server is missing commands, we increase the rate of prediction
|
||||||
|
// // until the server reports it has enough of our commands buffered up.
|
||||||
|
// //
|
||||||
|
// // If the server reports it has too many of our commands buffered up, we
|
||||||
|
// // slow the rate of prediction.
|
||||||
|
|
||||||
|
// f64 dilation_factor = 0;
|
||||||
|
// {
|
||||||
|
// // TODO: Warm start
|
||||||
|
|
||||||
|
// // How many buffered commands of ours we'd like the server to have
|
||||||
|
// i64 target_buffered_controls_count = 1;
|
||||||
|
// f64 rtt_bias_factor = 10.0;
|
||||||
|
|
||||||
|
// dilation_factor = SmoothstepF64(
|
||||||
|
// -(SIM_TICKS_PER_SECOND * smoothed_rtt * rtt_bias_factor),
|
||||||
|
// (SIM_TICKS_PER_SECOND * smoothed_rtt * rtt_bias_factor),
|
||||||
|
// target_buffered_controls_count - remote_buffered_controls_count
|
||||||
|
// ) * 2 - 1;
|
||||||
|
|
||||||
|
// f64 target_predict_dt = frame->dt + frame->dt * dilation_factor;
|
||||||
|
// frame->target_predict_tick_accum += target_predict_dt * SIM_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
// frame->predict_tick_accum += frame->dt * SIM_TICKS_PER_SECOND;
|
||||||
|
|
||||||
|
// // f64 lerp_rate = 5.0 * frame->dt;
|
||||||
|
// f64 lerp_rate = 1.0 * frame->dt;
|
||||||
|
// // f64 lerp_rate = 1;
|
||||||
|
// frame->predict_tick_accum = LerpF64(frame->predict_tick_accum, frame->target_predict_tick_accum, lerp_rate);
|
||||||
|
|
||||||
|
// if (ack == 0 || AbsF64(frame->predict_tick_accum - ack) > SIM_TICKS_PER_SECOND)
|
||||||
|
// {
|
||||||
|
// frame->target_predict_tick_accum = ack + (SIM_TICKS_PER_SECOND * smoothed_rtt * 0.5);
|
||||||
|
// frame->predict_tick_accum = frame->target_predict_tick_accum;
|
||||||
|
// LogDebugF("RESET");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // LogDebugF(
|
||||||
|
// // "Buffered count: %F. Ack: %F, Predict tick accum: %F, Predict dt: %F, Dilation factor: %F",
|
||||||
|
// // FmtSint(remote_buffered_controls_count),
|
||||||
|
// // FmtFloat(ack),
|
||||||
|
// // FmtFloat(frame->predict_tick_accum),
|
||||||
|
// // FmtFloat(predict_dt),
|
||||||
|
// // FmtFloat(dilation_factor)
|
||||||
|
// // );
|
||||||
|
|
||||||
|
// frame->predict_tick_accum = MaxF64(prev_frame->predict_tick_accum, frame->predict_tick_accum);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// V_PushTimelineMarker(frame->predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Red, 1);
|
||||||
|
// V_PushTimelineMarker(frame->target_predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||||
|
// }
|
||||||
|
// i64 prev_frame_predict_to = FloorF64(prev_frame->predict_tick_accum);
|
||||||
|
// i64 predict_to = FloorF64(frame->predict_tick_accum);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
//- Create player control
|
//- Create player control
|
||||||
|
|
||||||
@ -1636,6 +1752,10 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
ack_frame->base_predict_from = ack_frame->tick;
|
ack_frame->base_predict_from = ack_frame->tick;
|
||||||
ack_frame->base_predict_to = predict_to;
|
ack_frame->base_predict_to = predict_to;
|
||||||
cur_predict_world_seq += 1;
|
cur_predict_world_seq += 1;
|
||||||
|
if (ack != prev_frame_ack)
|
||||||
|
{
|
||||||
|
V_PushTimelineMarker(ack_frame->time_ns, Color_Green, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1875,6 +1995,15 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
P_Frame *prev_local_frame = prev_frame->local_world->last_frame;
|
P_Frame *prev_local_frame = prev_frame->local_world->last_frame;
|
||||||
P_Frame *local_frame = &P_NilFrame;
|
P_Frame *local_frame = &P_NilFrame;
|
||||||
{
|
{
|
||||||
@ -1887,89 +2016,21 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
frame->local_world->seed = predict_world->seed;
|
frame->local_world->seed = predict_world->seed;
|
||||||
P_ClearFrames(frame->local_world, I64Min, I64Max);
|
P_ClearFrames(frame->local_world, I64Min, I64Max);
|
||||||
|
|
||||||
// i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
|
frame->blend_tick += frame->dt * SIM_TICKS_PER_SECOND;
|
||||||
// i64 target_blend_dt_ns = frame->dt_ns;
|
|
||||||
|
|
||||||
i64 blend_dt_ns = frame->dt_ns;
|
|
||||||
// i64 blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
|
|
||||||
|
|
||||||
// V.target_blend_time_ns += target_blend_dt_ns;
|
|
||||||
V.blend_time_ns += blend_dt_ns;
|
|
||||||
|
|
||||||
// How many ticks back in time should the user thread blend between?
|
// How many ticks back in time should the user thread blend between?
|
||||||
// <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
// <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
||||||
// E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
// E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
||||||
f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||||
|
|
||||||
// if (ack != prev_frame_ack)
|
frame->blend_tick = frame->predict_tick_accum - interp_ratio;
|
||||||
// {
|
|
||||||
// i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
|
||||||
// V.target_blend_time_ns = ack_frame->time_ns - delay_ns;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (predict_to != prev_frame_predict_to)
|
|
||||||
// {
|
|
||||||
// i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
|
||||||
// V.target_blend_time_ns = predict_frame->time_ns - delay_ns;
|
|
||||||
// }
|
|
||||||
|
|
||||||
{
|
|
||||||
P_Frame *target_blend_frame = P_FrameFromTick(predict_world, predict_world->last_frame->base_predict_to);
|
|
||||||
|
|
||||||
i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
|
||||||
V.target_blend_time_ns = target_blend_frame->time_ns - delay_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ack != prev_frame_ack)
|
|
||||||
{
|
|
||||||
V_PushTimelineMarker(ack_frame->time_ns, Color_Green, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// f64 blend_to_target_lerp_rate = 0.01 * frame->dt;
|
|
||||||
|
|
||||||
f64 blend_to_target_lerp_rate = 1 * frame->dt;
|
|
||||||
// f64 blend_to_target_lerp_rate = 1 * frame->dt;
|
|
||||||
// f64 blend_to_target_lerp_rate = 0.0 * frame->dt;
|
|
||||||
|
|
||||||
// f64 blend_to_target_lerp_rate = 0.0;
|
|
||||||
// f64 blend_to_target_lerp_rate = 0.05;
|
|
||||||
// f64 blend_to_target_lerp_rate = 1;
|
|
||||||
V.blend_time_ns = LerpI64(V.blend_time_ns, V.target_blend_time_ns, blend_to_target_lerp_rate);
|
|
||||||
if (AbsI64(V.blend_time_ns - V.target_blend_time_ns) > (SIM_TICK_INTERVAL_NS * interp_ratio * 2))
|
|
||||||
{
|
|
||||||
LogDebugF("Blend reset");
|
|
||||||
V.blend_time_ns = V.target_blend_time_ns;
|
|
||||||
|
|
||||||
V_PushTimelineMarker(V.blend_time_ns, Color_Red, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TweakBool("Interpolation enabled", 1))
|
if (TweakBool("Interpolation enabled", 1))
|
||||||
{
|
{
|
||||||
P_Frame *left_predict_frame = &P_NilFrame;
|
P_Frame *left_predict_frame = &P_NilFrame;
|
||||||
P_Frame *right_predict_frame = &P_NilFrame;
|
P_Frame *right_predict_frame = &P_NilFrame;
|
||||||
|
|
||||||
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
// Locate right & left frames
|
||||||
// {
|
|
||||||
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
|
||||||
// {
|
|
||||||
// right_predict_frame = tmp;
|
|
||||||
// left_predict_frame = tmp->prev;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
V_PushTimelineMarker(V.blend_time_ns, Color_Red, 1);
|
|
||||||
V_PushTimelineMarker(V.target_blend_time_ns, Color_Yellow, 1);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
for (
|
for (
|
||||||
i64 predict_world_seq = cur_predict_world_seq;
|
i64 predict_world_seq = cur_predict_world_seq;
|
||||||
@ -1977,97 +2038,65 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
--predict_world_seq
|
--predict_world_seq
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
i64 tmp_right_predict_world_idx = predict_world_seq % countof(predict_worlds);
|
b32 search_right = P_IsFrameNil(right_predict_frame);
|
||||||
i64 tmp_left_predict_world_idx = (predict_world_seq - 1) % countof(predict_worlds);
|
b32 search_left = P_IsFrameNil(left_predict_frame);
|
||||||
P_World *tmp_right_world = predict_worlds[tmp_right_predict_world_idx];
|
|
||||||
P_World *tmp_left_world = predict_worlds[tmp_left_predict_world_idx];
|
|
||||||
|
|
||||||
// P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_from);
|
// Locate right frame
|
||||||
// P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_from);
|
if (search_right)
|
||||||
// i64 right_time_ns = tmp_right->base_time_ns;
|
{
|
||||||
// i64 left_time_ns = tmp_left->base_time_ns;
|
i64 tmp_world_idx = predict_world_seq % countof(predict_worlds);
|
||||||
|
P_World *tmp_world = predict_worlds[tmp_world_idx];
|
||||||
|
for (P_Frame *tmp_right_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_right_frame); tmp_right_frame = tmp_right_frame->prev)
|
||||||
|
{
|
||||||
|
P_Frame *tmp_left_frame = tmp_right_frame->prev;
|
||||||
|
if (tmp_right_frame->tick >= frame->blend_tick && tmp_left_frame->tick <= frame->blend_tick)
|
||||||
P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_to);
|
{
|
||||||
P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_to);
|
right_predict_frame = tmp_right_frame;
|
||||||
|
break;
|
||||||
// P_Frame *tmp_right = tmp_right_world->last_frame;
|
}
|
||||||
// P_Frame *tmp_left = tmp_left_world->last_frame;
|
}
|
||||||
|
}
|
||||||
i64 right_time_ns = tmp_right->time_ns;
|
|
||||||
i64 left_time_ns = tmp_left->time_ns;
|
// Locate left frame
|
||||||
|
if (search_left)
|
||||||
|
{
|
||||||
|
i64 tmp_world_idx = (predict_world_seq - 1) % countof(predict_worlds);
|
||||||
|
P_World *tmp_world = predict_worlds[tmp_world_idx];
|
||||||
V_PushTimelineMarker(left_time_ns, Color_Cyan, 1);
|
for (P_Frame *tmp_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_frame); tmp_frame = tmp_frame->prev)
|
||||||
V_PushTimelineMarker(right_time_ns, Color_Orange, 1);
|
{
|
||||||
|
if (tmp_frame->tick <= frame->blend_tick)
|
||||||
|
{
|
||||||
|
left_predict_frame = tmp_frame;
|
||||||
if (right_time_ns >= V.blend_time_ns && left_time_ns <= V.blend_time_ns)
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// V_PushTimelineMarker(left_time_ns, Color_Cyan, 1);
|
||||||
|
// V_PushTimelineMarker(right_time_ns, Color_Orange, 1);
|
||||||
|
|
||||||
|
if (!search_right && !search_left)
|
||||||
{
|
{
|
||||||
right_predict_frame = tmp_right;
|
|
||||||
left_predict_frame = tmp_left;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
|
||||||
// {
|
{
|
||||||
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
LogDebugF("Missing blend");
|
||||||
// {
|
|
||||||
// right_predict_frame = tmp;
|
|
||||||
// break;
|
right_predict_frame = predict_world->last_frame;
|
||||||
// }
|
left_predict_frame = right_predict_frame;
|
||||||
// }
|
|
||||||
// for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
DEBUGBREAKABLE;
|
||||||
// {
|
|
||||||
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
|
||||||
// {
|
V_PushTimelineMarker(frame->blend_tick * SIM_TICK_INTERVAL_NS, Color_Red, 0);
|
||||||
// left_predict_frame = tmp->prev;
|
}
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
|
||||||
// {
|
|
||||||
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
|
||||||
// {
|
|
||||||
// right_predict_frame = tmp;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
|
||||||
// {
|
|
||||||
// if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
|
||||||
// {
|
|
||||||
// left_predict_frame = tmp->prev;
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
|
|
||||||
{
|
|
||||||
LogDebugF("Missing blend");
|
|
||||||
right_predict_frame = predict_world->last_frame;
|
|
||||||
// left_predict_frame = right_predict_frame->prev;
|
|
||||||
left_predict_frame = right_predict_frame;
|
|
||||||
|
|
||||||
DEBUGBREAKABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
frame->blend_from_tick = left_predict_frame->tick;
|
frame->blend_from_tick = left_predict_frame->tick;
|
||||||
frame->blend_to_tick = right_predict_frame->tick;
|
frame->blend_to_tick = right_predict_frame->tick;
|
||||||
|
|
||||||
@ -2090,7 +2119,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
// P_Frame *left_sim_frame = right_sim_frame->prev;
|
// P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||||
|
|
||||||
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
|
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
|
||||||
f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
|
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
|
||||||
|
f64 blend_t = (f64)(frame->blend_tick - left_predict_frame->tick) / (f64)(right_predict_frame->tick - left_predict_frame->tick);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -2143,6 +2173,312 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// P_Frame *prev_local_frame = prev_frame->local_world->last_frame;
|
||||||
|
// P_Frame *local_frame = &P_NilFrame;
|
||||||
|
// {
|
||||||
|
// if (frame->local_world->tiles_hash != predict_world->tiles_hash)
|
||||||
|
// {
|
||||||
|
// frame->local_world->tiles_hash = predict_world->tiles_hash;
|
||||||
|
// CopyStructs(frame->local_world->tiles, predict_world->tiles, P_TilesCount);
|
||||||
|
// frame->tiles_dirty = 1;
|
||||||
|
// }
|
||||||
|
// frame->local_world->seed = predict_world->seed;
|
||||||
|
// P_ClearFrames(frame->local_world, I64Min, I64Max);
|
||||||
|
|
||||||
|
// // i64 target_blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
|
||||||
|
// // i64 target_blend_dt_ns = frame->dt_ns;
|
||||||
|
|
||||||
|
// i64 blend_dt_ns = frame->dt_ns;
|
||||||
|
// // i64 blend_dt_ns = frame->dt_ns + frame->dt_ns * dilation_factor;
|
||||||
|
|
||||||
|
// // V.target_blend_time_ns += target_blend_dt_ns;
|
||||||
|
// V.blend_time_ns += blend_dt_ns;
|
||||||
|
|
||||||
|
// // How many ticks back in time should the user thread blend between?
|
||||||
|
// // <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
||||||
|
// // E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
||||||
|
// f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||||
|
|
||||||
|
// // if (ack != prev_frame_ack)
|
||||||
|
// // {
|
||||||
|
// // i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
||||||
|
// // V.target_blend_time_ns = ack_frame->time_ns - delay_ns;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// // if (predict_to != prev_frame_predict_to)
|
||||||
|
// // {
|
||||||
|
// // i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
||||||
|
// // V.target_blend_time_ns = predict_frame->time_ns - delay_ns;
|
||||||
|
// // }
|
||||||
|
|
||||||
|
// {
|
||||||
|
// P_Frame *target_blend_frame = P_FrameFromTick(predict_world, predict_world->last_frame->base_predict_to);
|
||||||
|
|
||||||
|
// i64 delay_ns = SIM_TICK_INTERVAL_NS * interp_ratio;
|
||||||
|
// V.target_blend_time_ns = target_blend_frame->time_ns - delay_ns;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (ack != prev_frame_ack)
|
||||||
|
// {
|
||||||
|
// V_PushTimelineMarker(ack_frame->time_ns, Color_Green, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// // f64 blend_to_target_lerp_rate = 0.01 * frame->dt;
|
||||||
|
|
||||||
|
// f64 blend_to_target_lerp_rate = 1 * frame->dt;
|
||||||
|
// // f64 blend_to_target_lerp_rate = 1 * frame->dt;
|
||||||
|
// // f64 blend_to_target_lerp_rate = 0.0 * frame->dt;
|
||||||
|
|
||||||
|
// // f64 blend_to_target_lerp_rate = 0.0;
|
||||||
|
// // f64 blend_to_target_lerp_rate = 0.05;
|
||||||
|
// // f64 blend_to_target_lerp_rate = 1;
|
||||||
|
// V.blend_time_ns = LerpI64(V.blend_time_ns, V.target_blend_time_ns, blend_to_target_lerp_rate);
|
||||||
|
// if (AbsI64(V.blend_time_ns - V.target_blend_time_ns) > (SIM_TICK_INTERVAL_NS * interp_ratio * 2))
|
||||||
|
// {
|
||||||
|
// LogDebugF("Blend reset");
|
||||||
|
// V.blend_time_ns = V.target_blend_time_ns;
|
||||||
|
|
||||||
|
// V_PushTimelineMarker(V.blend_time_ns, Color_Red, 0);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (TweakBool("Interpolation enabled", 1))
|
||||||
|
// {
|
||||||
|
// P_Frame *left_predict_frame = &P_NilFrame;
|
||||||
|
// P_Frame *right_predict_frame = &P_NilFrame;
|
||||||
|
|
||||||
|
// // for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
||||||
|
// // {
|
||||||
|
// // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
||||||
|
// // {
|
||||||
|
// // right_predict_frame = tmp;
|
||||||
|
// // left_predict_frame = tmp->prev;
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// V_PushTimelineMarker(V.blend_time_ns, Color_Red, 1);
|
||||||
|
// V_PushTimelineMarker(V.target_blend_time_ns, Color_Yellow, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// for (
|
||||||
|
// i64 predict_world_seq = cur_predict_world_seq;
|
||||||
|
// predict_world_seq > MaxI64(0, cur_predict_world_seq - countof(predict_worlds));
|
||||||
|
// --predict_world_seq
|
||||||
|
// )
|
||||||
|
// {
|
||||||
|
// i64 tmp_right_predict_world_idx = predict_world_seq % countof(predict_worlds);
|
||||||
|
// i64 tmp_left_predict_world_idx = (predict_world_seq - 1) % countof(predict_worlds);
|
||||||
|
// P_World *tmp_right_world = predict_worlds[tmp_right_predict_world_idx];
|
||||||
|
// P_World *tmp_left_world = predict_worlds[tmp_left_predict_world_idx];
|
||||||
|
|
||||||
|
// // P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_from);
|
||||||
|
// // P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_from);
|
||||||
|
// // i64 right_time_ns = tmp_right->base_time_ns;
|
||||||
|
// // i64 left_time_ns = tmp_left->base_time_ns;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// P_Frame *tmp_right = P_FrameFromTick(tmp_right_world, tmp_right_world->last_frame->base_predict_to);
|
||||||
|
// P_Frame *tmp_left = P_FrameFromTick(tmp_left_world, tmp_left_world->last_frame->base_predict_to);
|
||||||
|
|
||||||
|
// // P_Frame *tmp_right = tmp_right_world->last_frame;
|
||||||
|
// // P_Frame *tmp_left = tmp_left_world->last_frame;
|
||||||
|
|
||||||
|
// i64 right_time_ns = tmp_right->time_ns;
|
||||||
|
// i64 left_time_ns = tmp_left->time_ns;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// V_PushTimelineMarker(left_time_ns, Color_Cyan, 1);
|
||||||
|
// V_PushTimelineMarker(right_time_ns, Color_Orange, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (right_time_ns >= V.blend_time_ns && left_time_ns <= V.blend_time_ns)
|
||||||
|
// {
|
||||||
|
// right_predict_frame = tmp_right;
|
||||||
|
// left_predict_frame = tmp_left;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
||||||
|
// // {
|
||||||
|
// // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
||||||
|
// // {
|
||||||
|
// // right_predict_frame = tmp;
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
||||||
|
// // {
|
||||||
|
// // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
||||||
|
// // {
|
||||||
|
// // left_predict_frame = tmp->prev;
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // for (P_Frame *tmp = predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
||||||
|
// // {
|
||||||
|
// // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
||||||
|
// // {
|
||||||
|
// // right_predict_frame = tmp;
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
// // for (P_Frame *tmp = prev_predict_world->last_frame; !P_IsFrameNil(tmp); tmp = tmp->prev)
|
||||||
|
// // {
|
||||||
|
// // if (tmp->time_ns >= V.blend_time_ns && tmp->prev->time_ns <= V.blend_time_ns)
|
||||||
|
// // {
|
||||||
|
// // left_predict_frame = tmp->prev;
|
||||||
|
// // break;
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
|
||||||
|
// {
|
||||||
|
// LogDebugF("Missing blend");
|
||||||
|
// right_predict_frame = predict_world->last_frame;
|
||||||
|
// // left_predict_frame = right_predict_frame->prev;
|
||||||
|
// left_predict_frame = right_predict_frame;
|
||||||
|
|
||||||
|
// DEBUGBREAKABLE;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// frame->blend_from_tick = left_predict_frame->tick;
|
||||||
|
// frame->blend_to_tick = right_predict_frame->tick;
|
||||||
|
|
||||||
|
// local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick);
|
||||||
|
// {
|
||||||
|
// P_Frame *left_sim_frame = left_predict_frame;
|
||||||
|
// P_Frame *right_sim_frame = right_predict_frame;
|
||||||
|
|
||||||
|
// // P_Frame *left_sim_frame = predict_world->first_frame;
|
||||||
|
// // P_Frame *right_sim_frame = left_sim_frame->next;
|
||||||
|
|
||||||
|
// // P_Frame *right_sim_frame = P_FrameFromTick(predict_world, first_predict_tick);
|
||||||
|
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||||
|
|
||||||
|
|
||||||
|
// // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack - 1);
|
||||||
|
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||||
|
|
||||||
|
// // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick);
|
||||||
|
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||||
|
|
||||||
|
// // f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
|
||||||
|
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// if (IsInf(blend_t))
|
||||||
|
// {
|
||||||
|
// blend_t = 1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||||
|
// {
|
||||||
|
// P_Ent *left = ent;
|
||||||
|
// P_Ent *right = ent;
|
||||||
|
// // if (ent->sim)
|
||||||
|
// if (0)
|
||||||
|
// {
|
||||||
|
// left = ent;
|
||||||
|
// right = P_EntFromKey(right_predict_frame, ent->key);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// left = P_EntFromKey(left_sim_frame, ent->key);
|
||||||
|
// right = P_EntFromKey(right_sim_frame, ent->key);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ent->exists = LerpF32(left->exists, right->exists, blend_t);
|
||||||
|
// if (!P_IsEntNil(right) && right->continuity_gen == left->continuity_gen)
|
||||||
|
// {
|
||||||
|
// ent->health = LerpF32(left->health, right->health, blend_t);
|
||||||
|
// ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t);
|
||||||
|
// ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t);
|
||||||
|
// ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t);
|
||||||
|
// ent->v = LerpVec2(left->v, right->v, blend_t);
|
||||||
|
// ent->w = LerpF32(left->w, right->w, blend_t);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// local_frame = P_PushFrame(frame->local_world, predict_world->last_frame, predict_world->last_frame->tick);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// P_DebugDrawFrame(local_frame);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -4645,30 +4981,31 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
f64 timeline_span_seconds = TweakFloat("Timeline span", 1, 0.01, 5);
|
f64 timeline_span_seconds = TweakFloat("Timeline span", 1, 0.01, 5);
|
||||||
i64 timeline_span_ns = NsFromSeconds(timeline_span_seconds);
|
i64 timeline_span_ns = NsFromSeconds(timeline_span_seconds);
|
||||||
|
|
||||||
|
b32 was_locked = prev_frame->prev_timeline.locked;
|
||||||
|
b32 was_paused = prev_frame->prev_timeline.paused;
|
||||||
|
b32 was_showing = prev_frame->prev_timeline.show;
|
||||||
|
b32 locked = prev_frame->timeline.locked;
|
||||||
|
b32 paused = prev_frame->timeline.paused;
|
||||||
|
b32 showing = prev_frame->timeline.show;
|
||||||
|
|
||||||
// Current frame time marker
|
// Current frame time marker
|
||||||
if (!V.timeline.paused)
|
if (!was_paused)
|
||||||
{
|
{
|
||||||
current_marker_time_ns = frame->time_ns - last_timeline_matchup_ns + timeline_start_ns;
|
current_marker_time_ns = frame->time_ns - last_timeline_matchup_ns + timeline_start_ns;
|
||||||
}
|
}
|
||||||
if (V.timeline.locked)
|
if (locked)
|
||||||
{
|
{
|
||||||
V_PushTimelineMarker(current_marker_time_ns, Color_White, 1);
|
V_PushTimelineMarker(current_marker_time_ns, Color_White, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 was_locked = V.timeline.locked;
|
if (showing)
|
||||||
b32 locked = frame->held_buttons[Button_R];
|
|
||||||
b32 paused = frame->held_buttons[Button_E];
|
|
||||||
V.timeline.locked = locked;
|
|
||||||
V.timeline.paused = paused;
|
|
||||||
|
|
||||||
if (V.timeline.show)
|
|
||||||
{
|
{
|
||||||
UI_Key timeline_key = UI_KeyF("Timeline box");
|
UI_Key timeline_key = UI_KeyF("Timeline box");
|
||||||
|
|
||||||
UI_Size timeline_width = UI_FNT(120, 1);
|
UI_Size timeline_width = UI_FNT(120, 1);
|
||||||
UI_Size timeline_height = UI_FNT(2, 1);
|
UI_Size timeline_height = UI_FNT(2, 1);
|
||||||
Vec4 tmld_bg = Color_Black;
|
Vec4 tmld_bg = Color_Black;
|
||||||
Vec2 timeline_pos = VEC2(frame->screen_dims.x * 0.5, frame->screen_dims.y * 0.25);
|
Vec2 timeline_pos = VEC2(frame->screen_dims.x * 0.5, frame->screen_dims.y * 0.75);
|
||||||
|
|
||||||
f32 timeline_opacity = 0.75;
|
f32 timeline_opacity = 0.75;
|
||||||
f32 marker_opacity = 0.75;
|
f32 marker_opacity = 0.75;
|
||||||
@ -4703,22 +5040,23 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vec2 marker_offset = Zi;
|
Vec2 marker_offset = Zi;
|
||||||
|
marker_offset.x = timeline_width.v * 0.5;
|
||||||
if (locked)
|
if (locked)
|
||||||
{
|
{
|
||||||
i64 offset_ns = current_marker_time_ns;
|
i64 offset_ns = current_marker_time_ns;
|
||||||
marker_offset.x = -((f64)(offset_ns - timeline_start_ns) / (f64)timeline_span_ns) * timeline_width.v + timeline_width.v * 0.5;
|
marker_offset.x += -((f64)(offset_ns - timeline_start_ns) / (f64)timeline_span_ns) * timeline_width.v;
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Build markers
|
//- Build markers
|
||||||
Arena *marker_arenas[] = {
|
Arena *marker_arenas[] = {
|
||||||
V.timeline.transient_markers_arena,
|
V.transient_markers_arena,
|
||||||
V.timeline.persistent_markers_arena,
|
V.persistent_markers_arena,
|
||||||
};
|
};
|
||||||
for (u64 marker_arena_idx = 0; marker_arena_idx < countof(marker_arenas); ++marker_arena_idx)
|
for (u64 marker_arena_idx = 0; marker_arena_idx < countof(marker_arenas); ++marker_arena_idx)
|
||||||
{
|
{
|
||||||
Arena *marker_arena = marker_arenas[marker_arena_idx];
|
Arena *marker_arena = marker_arenas[marker_arena_idx];
|
||||||
u64 markers_count = ArenaCount(marker_arena, V_TimelineMarker);
|
u64 markers_count = ArenaCount(marker_arena, V_TimelineMarker);
|
||||||
b32 is_transient = marker_arena == V.timeline.transient_markers_arena;
|
b32 is_transient = marker_arena == V.transient_markers_arena;
|
||||||
V_TimelineMarker *markers = ArenaFirst(marker_arena, V_TimelineMarker);
|
V_TimelineMarker *markers = ArenaFirst(marker_arena, V_TimelineMarker);
|
||||||
for (u64 marker_idx = 0; marker_idx < markers_count; ++marker_idx)
|
for (u64 marker_idx = 0; marker_idx < markers_count; ++marker_idx)
|
||||||
{
|
{
|
||||||
@ -4768,35 +5106,30 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
UI_PopCP(UI_TopCP());
|
UI_PopCP(UI_TopCP());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i64 reset_span_ns = timeline_span_ns * 0.5;
|
||||||
i64 reset_span_ns = timeline_span_ns;
|
b32 is_first_ack = prev_frame_ack == 0 && ack != 0;
|
||||||
if (locked)
|
b32 should_reset = (
|
||||||
{
|
!paused && (
|
||||||
reset_span_ns = timeline_span_ns * 0.5;
|
(frame->time_ns - last_timeline_reset_ns > reset_span_ns) ||
|
||||||
}
|
locked != was_locked ||
|
||||||
|
paused != was_paused ||
|
||||||
// reset_span_ns = NsFromSeconds(10);
|
showing != was_showing ||
|
||||||
|
is_first_ack
|
||||||
b32 should_reset = 0;
|
)
|
||||||
if (!paused)
|
);
|
||||||
{
|
if (!locked && should_reset || is_first_ack || showing != was_showing)
|
||||||
b32 is_first_ack = prev_frame_ack == 0 && ack != 0;
|
|
||||||
should_reset = (frame->time_ns - last_timeline_reset_ns > reset_span_ns) || is_first_ack || (locked != was_locked);
|
|
||||||
}
|
|
||||||
if (!locked && should_reset)
|
|
||||||
{
|
{
|
||||||
last_timeline_matchup_ns = frame->time_ns;
|
last_timeline_matchup_ns = frame->time_ns;
|
||||||
timeline_start_ns = ack_frame->time_ns;
|
timeline_start_ns = frame->predict_tick_accum * SIM_TICK_INTERVAL_NS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (should_reset)
|
if (should_reset)
|
||||||
{
|
{
|
||||||
last_timeline_reset_ns = frame->time_ns;
|
last_timeline_reset_ns = frame->time_ns;
|
||||||
ResetArena(V.timeline.persistent_markers_arena);
|
ResetArena(V.persistent_markers_arena);
|
||||||
}
|
}
|
||||||
if (!paused)
|
if (!paused)
|
||||||
{
|
{
|
||||||
ResetArena(V.timeline.transient_markers_arena);
|
ResetArena(V.transient_markers_arena);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5203,14 +5536,22 @@ void V_TickForever(WaveLaneCtx *lane)
|
|||||||
|
|
||||||
case V_CmdKind_toggle_console:
|
case V_CmdKind_toggle_console:
|
||||||
{
|
{
|
||||||
b32 new = !frame->show_console;
|
frame->show_console = !frame->show_console;
|
||||||
frame->show_console = new;
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case V_CmdKind_toggle_timeline:
|
case V_CmdKind_toggle_timeline:
|
||||||
{
|
{
|
||||||
b32 new = !V.timeline.show;
|
frame->timeline.show = !frame->timeline.show;
|
||||||
V.timeline.show = new;
|
} break;
|
||||||
|
|
||||||
|
case V_CmdKind_pause_timeline:
|
||||||
|
{
|
||||||
|
frame->timeline.paused = !frame->timeline.paused;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case V_CmdKind_lock_timeline:
|
||||||
|
{
|
||||||
|
frame->timeline.locked = !frame->timeline.locked;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case V_CmdKind_toggle_fullscreen:
|
case V_CmdKind_toggle_fullscreen:
|
||||||
|
|||||||
@ -12,6 +12,8 @@
|
|||||||
X(toggle_ui_debug, Toggle UI Debug, V_CmdDescFlag_None, V_HOTKEY( Button_F5 ), ) \
|
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_console, Toggle Developer Console, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent ), ) \
|
||||||
X(toggle_timeline, Toggle Debug Timeline, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent, .alt = 1 ), ) \
|
X(toggle_timeline, Toggle Debug Timeline, V_CmdDescFlag_None, V_HOTKEY( Button_GraveAccent, .alt = 1 ), ) \
|
||||||
|
X(pause_timeline, Pause Debug Timeline, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_E ), ) \
|
||||||
|
X(lock_timeline, Lock Debug Timeline, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_R ), ) \
|
||||||
X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \
|
X(toggle_fullscreen, Toggle Fullscreen Mode, V_CmdDescFlag_None, V_HOTKEY( Button_Enter, .alt = 1 ) ) \
|
||||||
X(toggle_window_topmost, Toggle Window Topmost, V_CmdDescFlag_None, V_HOTKEY( Button_F4 ), ) \
|
X(toggle_window_topmost, Toggle Window Topmost, V_CmdDescFlag_None, V_HOTKEY( Button_F4 ), ) \
|
||||||
X(tp_player, Teleport Player, V_CmdDescFlag_None, V_HOTKEY( Button_Q ), ) \
|
X(tp_player, Teleport Player, V_CmdDescFlag_None, V_HOTKEY( Button_Q ), ) \
|
||||||
@ -245,7 +247,9 @@ Struct(V_Frame)
|
|||||||
|
|
||||||
NET_Key sim_key;
|
NET_Key sim_key;
|
||||||
NET_Key desired_sim_key;
|
NET_Key desired_sim_key;
|
||||||
|
f64 target_predict_tick_accum;
|
||||||
f64 predict_tick_accum;
|
f64 predict_tick_accum;
|
||||||
|
f64 blend_tick;
|
||||||
|
|
||||||
i64 blend_from_tick;
|
i64 blend_from_tick;
|
||||||
i64 blend_to_tick;
|
i64 blend_to_tick;
|
||||||
@ -270,14 +274,8 @@ Struct(V_Ctx)
|
|||||||
P_EntKey player_key;
|
P_EntKey player_key;
|
||||||
P_EntKey follow_key;
|
P_EntKey follow_key;
|
||||||
|
|
||||||
struct
|
Arena *transient_markers_arena;
|
||||||
{
|
Arena *persistent_markers_arena;
|
||||||
b32 show;
|
|
||||||
b32 paused;
|
|
||||||
b32 locked;
|
|
||||||
Arena *transient_markers_arena;
|
|
||||||
Arena *persistent_markers_arena;
|
|
||||||
} timeline;
|
|
||||||
|
|
||||||
i64 panels_count;
|
i64 panels_count;
|
||||||
i64 windows_count;
|
i64 windows_count;
|
||||||
@ -286,9 +284,6 @@ Struct(V_Ctx)
|
|||||||
|
|
||||||
i64 connect_try_ns;
|
i64 connect_try_ns;
|
||||||
|
|
||||||
i64 target_blend_time_ns;
|
|
||||||
i64 blend_time_ns;
|
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
V_Notif *first_notif;
|
V_Notif *first_notif;
|
||||||
V_Notif *last_notif;
|
V_Notif *last_notif;
|
||||||
|
|||||||
@ -233,6 +233,13 @@ Enum(V_EditMode)
|
|||||||
V_EditMode_Tile,
|
V_EditMode_Tile,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(V_Timeline)
|
||||||
|
{
|
||||||
|
b32 show;
|
||||||
|
b32 paused;
|
||||||
|
b32 locked;
|
||||||
|
};
|
||||||
|
|
||||||
Struct(V_Affines)
|
Struct(V_Affines)
|
||||||
{
|
{
|
||||||
// World <-> screen (raw)
|
// World <-> screen (raw)
|
||||||
@ -288,6 +295,11 @@ Struct(V_SharedFrame)
|
|||||||
b32 has_mouse_focus;
|
b32 has_mouse_focus;
|
||||||
b32 has_keyboard_focus;
|
b32 has_keyboard_focus;
|
||||||
|
|
||||||
|
//- Timeline
|
||||||
|
|
||||||
|
V_Timeline prev_timeline;
|
||||||
|
V_Timeline timeline;
|
||||||
|
|
||||||
//- Editor state
|
//- Editor state
|
||||||
|
|
||||||
V_EditMode edit_mode;
|
V_EditMode edit_mode;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user