From 15a9136fc44cfc8528718d356c85cb4b4318539a Mon Sep 17 00:00:00 2001 From: Quaternions Date: Wed, 15 Jan 2025 22:59:59 -0800 Subject: [PATCH] session instruction changes for control and playback --- strafe-client/src/physics_worker.rs | 19 ++++--- strafe-client/src/session.rs | 31 ++++++++++-- strafe-client/src/window.rs | 77 +++++++++++++++++++++++------ 3 files changed, 101 insertions(+), 26 deletions(-) diff --git a/strafe-client/src/physics_worker.rs b/strafe-client/src/physics_worker.rs index 092d518..084d164 100644 --- a/strafe-client/src/physics_worker.rs +++ b/strafe-client/src/physics_worker.rs @@ -1,13 +1,17 @@ use crate::graphics_worker::Instruction as GraphicsInstruction; -use crate::session::{SessionInputInstruction,Instruction as SessionInstruction,Session,Simulation}; +use crate::session::{ + Session,Simulation,SessionInputInstruction,SessionControlInstruction,SessionPlaybackInstruction, + Instruction as SessionInstruction, +}; use strafesnet_common::instruction::{TimedInstruction,InstructionConsumer}; use strafesnet_common::physics::Time as PhysicsTime; use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; use strafesnet_common::timer::Timer; pub enum Instruction{ - Input(SessionInputInstruction), - SetPaused(bool), + SessionInput(SessionInputInstruction), + SessionControl(SessionControlInstruction), + SessionPlayback(SessionPlaybackInstruction), Render, Resize(winit::dpi::PhysicalSize), ChangeMap(strafesnet_common::map::CompleteMap), @@ -42,11 +46,14 @@ pub fn new<'a>( }; } match ins.instruction{ - Instruction::Input(unbuffered_instruction)=>{ + Instruction::SessionInput(unbuffered_instruction)=>{ run_session_instruction!(ins.time,SessionInstruction::Input(unbuffered_instruction)); }, - Instruction::SetPaused(paused)=>{ - run_session_instruction!(ins.time,SessionInstruction::SetPaused(paused)); + Instruction::SessionControl(unbuffered_instruction)=>{ + run_session_instruction!(ins.time,SessionInstruction::Control(unbuffered_instruction)); + }, + Instruction::SessionPlayback(unbuffered_instruction)=>{ + run_session_instruction!(ins.time,SessionInstruction::Playback(unbuffered_instruction)); }, Instruction::Render=>{ run_session_instruction!(ins.time,SESSION_INSTRUCTION_IDLE); diff --git a/strafe-client/src/session.rs b/strafe-client/src/session.rs index 1a913d5..dc0b17a 100644 --- a/strafe-client/src/session.rs +++ b/strafe-client/src/session.rs @@ -16,9 +16,9 @@ use crate::settings::UserSettings; pub enum Instruction<'a>{ Input(SessionInputInstruction), - SetPaused(bool), + Control(SessionControlInstruction), + Playback(SessionPlaybackInstruction), ChangeMap(&'a strafesnet_common::map::CompleteMap), - //Graphics(crate::graphics_worker::Instruction), } pub enum SessionInputInstruction{ @@ -35,6 +35,20 @@ pub enum ImplicitModeInstruction{ ResetAndSpawn(strafesnet_common::gameplay_modes::ModeId,strafesnet_common::gameplay_modes::StageId), } +pub enum SessionControlInstruction{ + SetPaused(bool), + // copy the current session simulation recording into a replay and view it + CopyRecordingIntoReplayAndSpectate, + StopSpectate, +} +pub enum SessionPlaybackInstruction{ + SkipForward, + SkipBack, + TogglePaused, + DecreaseTimescale, + IncreaseTimescale, +} + pub struct FrameState{ pub body:crate::physics::Body, pub camera:crate::physics::PhysicsCamera, @@ -176,12 +190,21 @@ impl InstructionConsumer> for Session{ Instruction::Input(SessionInputInstruction::Misc(other_other_instruction))=>{ run_mouse_interpolator_instruction!(MouseInterpolatorInstruction::Misc(other_other_instruction)); }, - Instruction::SetPaused(paused)=>{ + Instruction::Control(SessionControlInstruction::SetPaused(paused))=>{ // don't flush the buffered instructions in the mouse interpolator // until the mouse is confirmed to be not moving at a later time // what if they pause for 5ms lmao _=self.simulation.timer.set_paused(ins.time,paused); - } + }, + Instruction::Control(SessionControlInstruction::CopyRecordingIntoReplayAndSpectate)=>{ + todo!(); + }, + Instruction::Control(SessionControlInstruction::StopSpectate)=>{ + todo!(); + }, + Instruction::Playback(_)=>{ + todo!(); + }, Instruction::ChangeMap(complete_map)=>{ self.clear_recording(); self.change_map(complete_map); diff --git a/strafe-client/src/window.rs b/strafe-client/src/window.rs index 441d3d3..00f52a2 100644 --- a/strafe-client/src/window.rs +++ b/strafe-client/src/window.rs @@ -2,7 +2,7 @@ use strafesnet_common::instruction::TimedInstruction; use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; use strafesnet_common::physics::{MiscInstruction,SetControlInstruction}; use crate::physics_worker::Instruction as PhysicsWorkerInstruction; -use crate::session::SessionInputInstruction; +use crate::session::{SessionInputInstruction,SessionControlInstruction,SessionPlaybackInstruction}; pub enum Instruction{ Resize(winit::dpi::PhysicalSize), @@ -37,7 +37,7 @@ impl WindowContext<'_>{ //pause unpause self.physics_thread.send(TimedInstruction{ time, - instruction:PhysicsWorkerInstruction::SetPaused(!state), + instruction:PhysicsWorkerInstruction::SessionControl(SessionControlInstruction::SetPaused(!state)), }).unwrap(); //recalculate pressed keys on focus }, @@ -92,29 +92,74 @@ impl WindowContext<'_>{ }, (keycode,state)=>{ let s=state.is_pressed(); - if let Some(session_input_instruction)=match keycode{ - winit::keyboard::Key::Named(winit::keyboard::NamedKey::Space)=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetJump(s))), + + // internal variants for this scope + enum SessionInstructionSubset{ + Input(SessionInputInstruction), + Control(SessionControlInstruction), + Playback(SessionPlaybackInstruction), + } + macro_rules! input_ctrl{ + ($variant:ident,$state:expr)=>{ + Some(SessionInstructionSubset::Input(SessionInputInstruction::SetControl(SetControlInstruction::$variant($state)))) + }; + } + macro_rules! input_misc{ + ($variant:ident,$state:expr)=>{ + s.then_some(SessionInstructionSubset::Input(SessionInputInstruction::Misc(MiscInstruction::$variant))) + }; + } + macro_rules! session_ctrl{ + ($variant:ident,$state:expr)=>{ + s.then_some(SessionInstructionSubset::Control(SessionControlInstruction::$variant)) + }; + } + macro_rules! session_playback{ + ($variant:ident,$state:expr)=>{ + s.then_some(SessionInstructionSubset::Playback(SessionPlaybackInstruction::$variant)) + }; + } + impl From for PhysicsWorkerInstruction{ + fn from(value:SessionInstructionSubset)->Self{ + match value{ + SessionInstructionSubset::Input(session_input_instruction)=>PhysicsWorkerInstruction::SessionInput(session_input_instruction), + SessionInstructionSubset::Control(session_control_instruction)=>PhysicsWorkerInstruction::SessionControl(session_control_instruction), + SessionInstructionSubset::Playback(session_playback_instruction)=>PhysicsWorkerInstruction::SessionPlayback(session_playback_instruction), + } + } + } + + if let Some(session_instruction)=match keycode{ + winit::keyboard::Key::Named(winit::keyboard::NamedKey::Space)=>input_ctrl!(SetJump,s), + // TODO: bind system so playback pausing can use spacebar + winit::keyboard::Key::Named(winit::keyboard::NamedKey::Enter)=>session_playback!(TogglePaused,s), + winit::keyboard::Key::Named(winit::keyboard::NamedKey::ArrowUp)=>session_playback!(IncreaseTimescale,s), + winit::keyboard::Key::Named(winit::keyboard::NamedKey::ArrowDown)=>session_playback!(DecreaseTimescale,s), + winit::keyboard::Key::Named(winit::keyboard::NamedKey::ArrowLeft)=>session_playback!(SkipBack,s), + winit::keyboard::Key::Named(winit::keyboard::NamedKey::ArrowRight)=>session_playback!(SkipForward,s), winit::keyboard::Key::Character(key)=>match key.as_str(){ - "W"|"w"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveForward(s))), - "A"|"a"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveLeft(s))), - "S"|"s"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveBack(s))), - "D"|"d"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveRight(s))), - "E"|"e"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveUp(s))), - "Q"|"q"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetMoveDown(s))), - "Z"|"z"=>Some(SessionInputInstruction::SetControl(SetControlInstruction::SetZoom(s))), + "W"|"w"=>input_ctrl!(SetMoveForward,s), + "A"|"a"=>input_ctrl!(SetMoveLeft,s), + "S"|"s"=>input_ctrl!(SetMoveBack,s), + "D"|"d"=>input_ctrl!(SetMoveRight,s), + "E"|"e"=>input_ctrl!(SetMoveUp,s), + "Q"|"q"=>input_ctrl!(SetMoveDown,s), + "Z"|"z"=>input_ctrl!(SetZoom,s), "R"|"r"=>s.then(||{ //mouse needs to be reset since the position is absolute self.mouse_pos=glam::DVec2::ZERO; - SessionInputInstruction::Mode(crate::session::ImplicitModeInstruction::ResetAndRestart) + SessionInstructionSubset::Input(SessionInputInstruction::Mode(crate::session::ImplicitModeInstruction::ResetAndRestart)) }), - "F"|"f"=>s.then_some(SessionInputInstruction::Misc(MiscInstruction::PracticeFly)), + "F"|"f"=>input_misc!(PracticeFly,s), + "B"|"b"=>session_ctrl!(CopyRecordingIntoReplayAndSpectate,s), + "X"|"x"=>session_ctrl!(StopSpectate,s), _=>None, }, _=>None, }{ self.physics_thread.send(TimedInstruction{ time, - instruction:PhysicsWorkerInstruction::Input(session_input_instruction), + instruction:session_instruction.into(), }).unwrap(); } }, @@ -138,7 +183,7 @@ impl WindowContext<'_>{ self.mouse_pos+=glam::dvec2(delta.0,delta.1); self.physics_thread.send(TimedInstruction{ time, - instruction:PhysicsWorkerInstruction::Input(SessionInputInstruction::Mouse(self.mouse_pos.as_ivec2())), + instruction:PhysicsWorkerInstruction::SessionInput(SessionInputInstruction::Mouse(self.mouse_pos.as_ivec2())), }).unwrap(); }, winit::event::DeviceEvent::MouseWheel { @@ -148,7 +193,7 @@ impl WindowContext<'_>{ if false{//self.physics.style.use_scroll{ self.physics_thread.send(TimedInstruction{ time, - instruction:PhysicsWorkerInstruction::Input(SessionInputInstruction::SetControl(SetControlInstruction::SetJump(true))),//activates the immediate jump path, but the style modifier prevents controls&CONTROL_JUMP bit from being set to auto jump + instruction:PhysicsWorkerInstruction::SessionInput(SessionInputInstruction::SetControl(SetControlInstruction::SetJump(true))),//activates the immediate jump path, but the style modifier prevents controls&CONTROL_JUMP bit from being set to auto jump }).unwrap(); } },