From 6138d70a6faa928034b07a648ca57f96d37144e9 Mon Sep 17 00:00:00 2001 From: Quaternions <krakow20@gmail.com> Date: Tue, 14 Jan 2025 23:23:41 -0800 Subject: [PATCH] =?UTF-8?q?unify=20timeout=20=F0=9F=98=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- strafe-client/src/mouse_interpolator.rs | 114 +++++++++--------------- 1 file changed, 44 insertions(+), 70 deletions(-) diff --git a/strafe-client/src/mouse_interpolator.rs b/strafe-client/src/mouse_interpolator.rs index 0c61089..d225bae 100644 --- a/strafe-client/src/mouse_interpolator.rs +++ b/strafe-client/src/mouse_interpolator.rs @@ -75,6 +75,37 @@ impl MouseInterpolator{ self.output.append(&mut self.buffer); } } + fn get_timedout_at(&self,time_limit:SessionTime)->Option<SessionTime>{ + match &self.buffer_state{ + BufferState::Unbuffered=>None, + BufferState::Initializing(time,_mouse_state) + |BufferState::Buffered(time,_mouse_state)=>{ + let timeout=*time+MOUSE_TIMEOUT; + (timeout<time_limit).then_some(timeout) + } + } + } + fn timeout(&mut self){ + let buffer_state=core::mem::replace(&mut self.buffer_state,BufferState::Unbuffered); + match buffer_state{ + BufferState::Unbuffered=>(), + BufferState::Initializing(_time,mouse_state) + |BufferState::Buffered(_time,mouse_state)=>{ + // convert to BufferState::Unbuffered + // use the first instruction which should be a mouse instruction + // to push a ReplaceMouse instruction + // duplicate the current mouse + self.push_mouse(TimedInstruction{ + // This should be simulation_timer.time(timeout) + // but the timer is not accessible from this scope + // and it's just here to say that the mouse isn't moving anyways. + // I think this is a divide by zero bug, two identical mouse_states will occupy the interpolation state + time:mouse_state.time, + instruction:MouseInstruction::SetNextMouse(mouse_state), + }); + }, + } + } pub fn push_unbuffered_input(&mut self,ins:DoubleTimedUnbufferedInstruction){ // new input // if there is zero instruction buffered, it means the mouse is not moving @@ -86,6 +117,11 @@ impl MouseInterpolator{ // a mouse event is buffered, and exists within the last 10ms // case 3: stop // a mouse event is buffered, but no mouse events have transpired within 10ms + + // push buffered mouse instruction and flush buffer to output + if self.get_timedout_at(ins.time).is_some(){ + self.timeout(); + } // replace_with allows the enum variant to safely be replaced from behind a mutable reference let (ins_mouse,ins_other)=replace_with::replace_with_or_abort_and_return(&mut self.buffer_state,|buffer_state|{ let next_state=match buffer_state{ @@ -96,18 +132,6 @@ impl MouseInterpolator{ BufferState::Unbuffered }, BufferState::Initializing(time,mouse_state)=>{ - let timeout=time+MOUSE_TIMEOUT; - if timeout<ins.time{ - // duplicate the current mouse - let ins_mouse=TimedInstruction{ - // This should be simulation_timer.time(time) - // but the timer is not accessible from this scope - // and it's just here to say that the mouse isn't moving anyways. - time:ins.instruction.time, - instruction:MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}), - }; - return ((Some(ins_mouse),None),BufferState::Unbuffered); - } if let Instruction::MoveMouse(pos)=ins.instruction.instruction{ let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let ins_mouse=TimedInstruction{ @@ -122,19 +146,6 @@ impl MouseInterpolator{ BufferState::Initializing(time,mouse_state) }, BufferState::Buffered(time,mouse_state)=>{ - // TODO: deduplicate code with above case - let timeout=time+MOUSE_TIMEOUT; - if timeout<ins.time{ - // duplicate the current mouse - let ins_mouse=TimedInstruction{ - // This should be simulation_timer.time(timeout) - // but the timer is not accessible from this scope - // and it's just here to say that the mouse isn't moving anyways. - time:ins.instruction.time, - instruction:MouseInstruction::SetNextMouse(MouseState{pos:mouse_state.pos,time:ins.instruction.time}), - }; - return ((Some(ins_mouse),None),BufferState::Unbuffered); - } if let Instruction::MoveMouse(pos)=ins.instruction.instruction{ let next_mouse_state=MouseState{pos,time:ins.instruction.time}; let ins_mouse=TimedInstruction{ @@ -174,60 +185,23 @@ impl MouseInterpolator{ self.output.len()!=0 } pub fn buffered_instruction_with_timeout(&self,time_limit:SessionTime)->Option<TimedInstruction<StepInstruction,SessionTimeInner>>{ - match &self.buffer_state{ - BufferState::Unbuffered=>self.has_output().then_some(TimedInstruction{ + match self.get_timedout_at(time_limit){ + Some(timeout)=>Some(TimedInstruction{ + time:timeout, + instruction:StepInstruction::Timeout, + }), + None=>self.has_output().then_some(TimedInstruction{ + // this timestamp should not matter time:time_limit, instruction:StepInstruction::Pop, }), - BufferState::Initializing(time,_mouse_state) - |BufferState::Buffered(time,_mouse_state)=>{ - let timeout=*time+MOUSE_TIMEOUT; - if timeout<time_limit{ - // if the mouse has stopped moving for over 10ms, emit DoStepReplaceMouse at that exact timestamp - Some(TimedInstruction{ - time:timeout, - instruction:StepInstruction::Timeout, - }) - }else if self.has_output(){ - // emit Step - Some(TimedInstruction{ - // this timestamp should not matter - // verify this and potentially emit a different type using the enum only - time:time_limit, - instruction:StepInstruction::Pop, - }) - }else{ - None - } - }, } } // include timestamp and implement InstructionConsumer? pub fn pop_buffered_instruction(&mut self,ins:StepInstruction)->Option<TimedInstruction<PhysicsInputInstruction,PhysicsTimeInner>>{ match ins{ - // could check if self.is_first_ready() StepInstruction::Pop=>(), - StepInstruction::Timeout=>{ - let buffer_state=core::mem::replace(&mut self.buffer_state,BufferState::Unbuffered); - match buffer_state{ - BufferState::Unbuffered=>(), - BufferState::Initializing(_time,mouse_state) - |BufferState::Buffered(_time,mouse_state)=>{ - // convert to BufferState::Unbuffered - // use the first instruction which should be a mouse instruction - // to push a ReplaceMouse instruction - // duplicate the current mouse - self.push_mouse(TimedInstruction{ - // This should be simulation_timer.time(timeout) - // but the timer is not accessible from this scope - // and it's just here to say that the mouse isn't moving anyways. - // I think this is a divide by zero bug, two identical mouse_states will occupy the interpolation state - time:mouse_state.time, - instruction:MouseInstruction::SetNextMouse(mouse_state), - }); - }, - } - }, + StepInstruction::Timeout=>self.timeout(), } self.output.pop_front() }