2024-01-29 16:19:41 -08:00
use strafesnet_common ::instruction ::TimedInstruction ;
2025-01-07 22:54:58 -08:00
use strafesnet_common ::session ::{ Time as SessionTime , TimeInner as SessionTimeInner } ;
2025-01-15 20:19:20 -08:00
use strafesnet_common ::physics ::{ MiscInstruction , SetControlInstruction } ;
2025-01-18 00:12:09 -08:00
use crate ::file ::Format2 ;
2025-01-15 01:01:24 -08:00
use crate ::physics_worker ::Instruction as PhysicsWorkerInstruction ;
2025-01-15 22:59:59 -08:00
use crate ::session ::{ SessionInputInstruction , SessionControlInstruction , SessionPlaybackInstruction } ;
2023-10-18 17:17:21 -07:00
2025-01-15 01:01:24 -08:00
pub enum Instruction {
2023-10-18 17:17:21 -07:00
Resize ( winit ::dpi ::PhysicalSize < u32 > ) ,
WindowEvent ( winit ::event ::WindowEvent ) ,
DeviceEvent ( winit ::event ::DeviceEvent ) ,
RequestRedraw ,
Render ,
}
//holds thread handles to dispatch to
struct WindowContext < ' a > {
manual_mouse_lock :bool ,
2025-01-15 01:01:24 -08:00
mouse_pos :glam ::DVec2 ,
2023-10-18 17:17:21 -07:00
screen_size :glam ::UVec2 ,
2024-01-18 14:26:08 -08:00
window :& ' a winit ::window ::Window ,
2025-01-15 01:01:24 -08:00
physics_thread :crate ::compat_worker ::QNWorker < ' a , TimedInstruction < PhysicsWorkerInstruction , SessionTimeInner > > ,
2023-10-18 17:17:21 -07:00
}
impl WindowContext < '_ > {
2025-01-03 02:30:11 -08:00
fn get_middle_of_screen ( & self ) ->winit ::dpi ::PhysicalPosition < u32 > {
winit ::dpi ::PhysicalPosition ::new ( self . screen_size . x / 2 , self . screen_size . y / 2 )
2023-10-18 17:17:21 -07:00
}
2025-01-07 22:54:58 -08:00
fn window_event ( & mut self , time :SessionTime , event :winit ::event ::WindowEvent ) {
2025-01-03 02:31:43 -08:00
match event {
2023-10-18 17:17:21 -07:00
winit ::event ::WindowEvent ::DroppedFile ( path ) = > {
2024-02-13 21:56:11 -08:00
match crate ::file ::load ( path . as_path ( ) ) {
2025-01-18 00:12:09 -08:00
Ok ( Format2 ::Map ( map ) ) = > self . physics_thread . send ( TimedInstruction { time , instruction :PhysicsWorkerInstruction ::ChangeMap ( map ) } ) . unwrap ( ) ,
Ok ( Format2 ::Bot ( bot ) ) = > self . physics_thread . send ( TimedInstruction { time , instruction :PhysicsWorkerInstruction ::LoadReplay ( bot ) } ) . unwrap ( ) ,
Err ( e ) = > println! ( " Failed to load file: {e} " ) ,
2023-10-18 17:17:21 -07:00
}
} ,
2024-08-02 10:41:42 -07:00
winit ::event ::WindowEvent ::Focused ( state ) = > {
2023-10-18 17:17:21 -07:00
//pause unpause
2024-08-02 10:41:42 -07:00
self . physics_thread . send ( TimedInstruction {
time ,
2025-01-15 22:59:59 -08:00
instruction :PhysicsWorkerInstruction ::SessionControl ( SessionControlInstruction ::SetPaused ( ! state ) ) ,
2024-08-02 10:41:42 -07:00
} ) . unwrap ( ) ;
2023-10-18 17:17:21 -07:00
//recalculate pressed keys on focus
} ,
winit ::event ::WindowEvent ::KeyboardInput {
event :winit ::event ::KeyEvent { state , logical_key , repeat :false , .. } ,
..
} = > {
2025-01-03 02:20:09 -08:00
match ( logical_key , state ) {
( winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Tab ) , winit ::event ::ElementState ::Pressed ) = > {
self . manual_mouse_lock = false ;
match self . window . set_cursor_position ( self . get_middle_of_screen ( ) ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > println! ( " Could not set cursor position: {:?} " , e ) ,
}
match self . window . set_cursor_grab ( winit ::window ::CursorGrabMode ::None ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > println! ( " Could not release cursor: {:?} " , e ) ,
}
self . window . set_cursor_visible ( state . is_pressed ( ) ) ;
} ,
( winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Tab ) , winit ::event ::ElementState ::Released ) = > {
//if cursor is outside window don't lock but apparently there's no get pos function
//let pos=window.get_cursor_pos();
match self . window . set_cursor_grab ( winit ::window ::CursorGrabMode ::Locked ) {
Ok ( ( ) ) = > ( ) ,
Err ( _ ) = > {
match self . window . set_cursor_grab ( winit ::window ::CursorGrabMode ::Confined ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > {
self . manual_mouse_lock = true ;
println! ( " Could not confine cursor: {:?} " , e )
} ,
2023-10-18 17:17:21 -07:00
}
}
}
2025-01-03 02:20:09 -08:00
self . window . set_cursor_visible ( state . is_pressed ( ) ) ;
2023-10-18 17:17:21 -07:00
} ,
2025-01-03 02:20:09 -08:00
( winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::F11 ) , winit ::event ::ElementState ::Pressed ) = > {
if self . window . fullscreen ( ) . is_some ( ) {
self . window . set_fullscreen ( None ) ;
} else {
self . window . set_fullscreen ( Some ( winit ::window ::Fullscreen ::Borderless ( None ) ) ) ;
2023-10-18 17:17:21 -07:00
}
} ,
2025-01-03 02:20:09 -08:00
( winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Escape ) , winit ::event ::ElementState ::Pressed ) = > {
self . manual_mouse_lock = false ;
match self . window . set_cursor_grab ( winit ::window ::CursorGrabMode ::None ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > println! ( " Could not release cursor: {:?} " , e ) ,
2023-10-18 17:17:21 -07:00
}
2025-01-03 02:20:09 -08:00
self . window . set_cursor_visible ( true ) ;
2023-10-18 17:17:21 -07:00
} ,
2025-01-03 02:20:09 -08:00
( keycode , state ) = > {
let s = state . is_pressed ( ) ;
2025-01-15 22:59:59 -08:00
// 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 < SessionInstructionSubset > 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 ) ,
2023-10-18 17:17:21 -07:00
winit ::keyboard ::Key ::Character ( key ) = > match key . as_str ( ) {
2025-01-15 22:59:59 -08:00
" 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 ) ,
2025-01-15 01:01:24 -08:00
" R " | " r " = > s . then ( | | {
2024-08-01 12:57:58 -07:00
//mouse needs to be reset since the position is absolute
2025-01-15 01:01:24 -08:00
self . mouse_pos = glam ::DVec2 ::ZERO ;
2025-01-15 22:59:59 -08:00
SessionInstructionSubset ::Input ( SessionInputInstruction ::Mode ( crate ::session ::ImplicitModeInstruction ::ResetAndRestart ) )
2025-01-15 01:01:24 -08:00
} ) ,
2025-01-15 22:59:59 -08:00
" F " | " f " = > input_misc! ( PracticeFly , s ) ,
" B " | " b " = > session_ctrl! ( CopyRecordingIntoReplayAndSpectate , s ) ,
" X " | " x " = > session_ctrl! ( StopSpectate , s ) ,
2025-01-18 00:12:09 -08:00
" N " | " n " = > session_ctrl! ( SaveReplay , s ) ,
2025-01-18 01:32:45 -08:00
" J " | " j " = > session_ctrl! ( LoadIntoReplayState , s ) ,
2023-10-18 17:17:21 -07:00
_ = > None ,
} ,
_ = > None ,
} {
self . physics_thread . send ( TimedInstruction {
time ,
2025-01-15 22:59:59 -08:00
instruction :session_instruction . into ( ) ,
2023-10-18 17:17:21 -07:00
} ) . unwrap ( ) ;
}
} ,
}
} ,
_ = > ( ) ,
}
}
2025-01-07 22:54:58 -08:00
fn device_event ( & mut self , time :SessionTime , event : winit ::event ::DeviceEvent ) {
2025-01-03 02:31:43 -08:00
match event {
winit ::event ::DeviceEvent ::MouseMotion {
2025-01-15 01:01:24 -08:00
delta ,
2025-01-03 02:31:43 -08:00
} = > {
2023-10-18 17:17:21 -07:00
if self . manual_mouse_lock {
match self . window . set_cursor_position ( self . get_middle_of_screen ( ) ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > println! ( " Could not set cursor position: {:?} " , e ) ,
}
}
2025-01-15 01:01:24 -08:00
self . mouse_pos + = glam ::dvec2 ( delta . 0 , delta . 1 ) ;
2023-10-18 17:17:21 -07:00
self . physics_thread . send ( TimedInstruction {
time ,
2025-01-15 22:59:59 -08:00
instruction :PhysicsWorkerInstruction ::SessionInput ( SessionInputInstruction ::Mouse ( self . mouse_pos . as_ivec2 ( ) ) ) ,
2023-10-18 17:17:21 -07:00
} ) . unwrap ( ) ;
} ,
winit ::event ::DeviceEvent ::MouseWheel {
delta ,
2025-01-03 02:31:43 -08:00
} = > {
2023-10-18 17:17:21 -07:00
println! ( " mousewheel {:?} " , delta ) ;
if false { //self.physics.style.use_scroll{
self . physics_thread . send ( TimedInstruction {
time ,
2025-01-15 22:59:59 -08:00
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
2023-10-18 17:17:21 -07:00
} ) . unwrap ( ) ;
}
2025-01-03 02:31:43 -08:00
} ,
2023-10-18 17:17:21 -07:00
_ = > ( ) ,
}
}
}
2024-08-06 11:26:27 -07:00
pub fn worker < ' a > (
2024-01-18 14:26:08 -08:00
window :& ' a winit ::window ::Window ,
2024-08-06 11:26:27 -07:00
setup_context :crate ::setup ::SetupContext < ' a > ,
2025-01-15 01:01:24 -08:00
) ->crate ::compat_worker ::QNWorker < ' a , TimedInstruction < Instruction , SessionTimeInner > > {
2024-08-06 11:26:27 -07:00
// WindowContextSetup::new
2025-01-03 02:31:43 -08:00
let user_settings = crate ::settings ::read_user_settings ( ) ;
2023-10-18 17:17:21 -07:00
2025-01-03 02:31:43 -08:00
let mut graphics = crate ::graphics ::GraphicsState ::new ( & setup_context . device , & setup_context . queue , & setup_context . config ) ;
graphics . load_user_settings ( & user_settings ) ;
2023-10-18 17:17:21 -07:00
2024-08-06 11:26:27 -07:00
//WindowContextSetup::into_context
2025-01-03 02:31:43 -08:00
let screen_size = glam ::uvec2 ( setup_context . config . width , setup_context . config . height ) ;
let graphics_thread = crate ::graphics_worker ::new ( graphics , setup_context . config , setup_context . surface , setup_context . device , setup_context . queue ) ;
let mut window_context = WindowContext {
manual_mouse_lock :false ,
2025-01-15 01:01:24 -08:00
mouse_pos :glam ::DVec2 ::ZERO ,
2025-01-03 02:31:43 -08:00
//make sure to update this!!!!!
screen_size ,
window ,
physics_thread :crate ::physics_worker ::new (
graphics_thread ,
user_settings ,
) ,
} ;
2023-10-18 17:17:21 -07:00
2024-08-06 11:26:27 -07:00
//WindowContextSetup::into_worker
2025-01-15 01:01:24 -08:00
crate ::compat_worker ::QNWorker ::new ( move | ins :TimedInstruction < Instruction , SessionTimeInner > | {
2025-01-03 02:31:43 -08:00
match ins . instruction {
2025-01-15 01:01:24 -08:00
Instruction ::RequestRedraw = > {
2025-01-03 02:31:43 -08:00
window_context . window . request_redraw ( ) ;
}
2025-01-15 01:01:24 -08:00
Instruction ::WindowEvent ( window_event ) = > {
2025-01-03 02:31:43 -08:00
window_context . window_event ( ins . time , window_event ) ;
} ,
2025-01-15 01:01:24 -08:00
Instruction ::DeviceEvent ( device_event ) = > {
2025-01-03 02:31:43 -08:00
window_context . device_event ( ins . time , device_event ) ;
} ,
2025-01-15 01:01:24 -08:00
Instruction ::Resize ( size ) = > {
2025-01-03 02:31:43 -08:00
window_context . physics_thread . send (
TimedInstruction {
time :ins . time ,
2025-01-15 01:01:24 -08:00
instruction :PhysicsWorkerInstruction ::Resize ( size )
2025-01-03 02:31:43 -08:00
}
) . unwrap ( ) ;
}
2025-01-15 01:01:24 -08:00
Instruction ::Render = > {
2025-01-03 02:31:43 -08:00
window_context . physics_thread . send (
TimedInstruction {
time :ins . time ,
2025-01-15 01:01:24 -08:00
instruction :PhysicsWorkerInstruction ::Render
2025-01-03 02:31:43 -08:00
}
) . unwrap ( ) ;
2023-10-18 17:17:21 -07:00
}
2025-01-03 02:31:43 -08:00
}
} )
2024-08-01 12:57:58 -07:00
}