2023-10-19 00:17:21 +00:00
use crate ::physics_worker ::InputInstruction ;
2024-01-30 00:19:41 +00:00
use strafesnet_common ::integer ;
use strafesnet_common ::instruction ::TimedInstruction ;
2024-01-30 06:37:05 +00:00
use strafesnet_texture_loader ::texture_loader ::TextureLoaderTrait ;
2023-10-19 00:17:21 +00:00
pub enum WindowInstruction {
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 ,
mouse :crate ::physics ::MouseState , //std::sync::Arc<std::sync::Mutex<>>
screen_size :glam ::UVec2 ,
user_settings :crate ::settings ::UserSettings ,
2024-01-18 22:26:08 +00:00
window :& ' a winit ::window ::Window ,
2023-10-19 00:17:21 +00:00
physics_thread :crate ::compat_worker ::QNWorker < ' a , TimedInstruction < crate ::physics_worker ::Instruction > > ,
}
impl WindowContext < '_ > {
fn get_middle_of_screen ( & self ) ->winit ::dpi ::PhysicalPosition < f32 > {
2023-10-25 22:56:36 +00:00
winit ::dpi ::PhysicalPosition ::new ( self . screen_size . x as f32 / 2.0 , self . screen_size . y as f32 / 2.0 )
2023-10-19 00:17:21 +00:00
}
2024-01-30 00:19:41 +00:00
fn window_event ( & mut self , time :integer ::Time , event : winit ::event ::WindowEvent ) {
2023-10-19 00:17:21 +00:00
match event {
winit ::event ::WindowEvent ::DroppedFile ( path ) = > {
2024-01-30 06:37:05 +00:00
let path = path . as_path ( ) ;
2023-10-19 00:17:21 +00:00
//blocking because it's simpler...
2024-01-30 06:37:05 +00:00
if let Ok ( file ) = std ::fs ::File ::open ( path ) {
// match strafesnet_snf::read_snf(std::io::BufReader::new(file)){
// Ok(strafesnet_snf::SNF::Map(streamable_map))=>{
// if let Ok(indexed_model_instances)=streamable_map.load_all(){
// self.physics_thread.send(TimedInstruction{time,instruction:crate::physics_worker::Instruction::ClearModels}).unwrap();
// self.physics_thread.send(TimedInstruction{time,instruction:crate::physics_worker::Instruction::GenerateModels(indexed_model_instances)}).unwrap();
// }
// },
// Ok(strafesnet_snf::SNF::Bot(streamable_map))=>println!("File type not yet supported"),
// Ok(strafesnet_snf::SNF::Demo(streamable_map))=>println!("File type not yet supported"),
// Err(e)=>println!("Error reading file: {e:?}"),
// }
let mut texture_loader = strafesnet_texture_loader ::legacy ( ) ;
match ( strafesnet_rbx_loader ::read ( file , | name | {
match texture_loader . acquire_id ( name ) {
Ok ( texture_id ) = > Some ( texture_id ) ,
Err ( e ) = > {
println! ( " there was error: {e} " ) ;
None
} ,
}
} ) , texture_loader . load ( ) ) {
( Ok ( map ) , Ok ( textures ) ) = > {
self . physics_thread . send ( TimedInstruction { time , instruction :crate ::physics_worker ::Instruction ::ClearModels } ) . unwrap ( ) ;
self . physics_thread . send ( TimedInstruction { time , instruction :crate ::physics_worker ::Instruction ::GenerateModels ( map , textures ) } ) . unwrap ( ) ;
} ,
( Err ( e ) , _ ) = > println! ( " Error reading file: {e:?} " ) ,
( _ , Err ( e ) ) = > println! ( " Error loading textures: {e:?} " ) ,
}
} else {
println! ( " Failed to open file {path:?} " ) ;
2023-10-19 00:17:21 +00:00
}
} ,
2023-10-25 23:07:12 +00:00
winit ::event ::WindowEvent ::Focused ( _state ) = > {
2023-10-19 00:17:21 +00:00
//pause unpause
//recalculate pressed keys on focus
} ,
winit ::event ::WindowEvent ::KeyboardInput {
event :winit ::event ::KeyEvent { state , logical_key , repeat :false , .. } ,
..
} = > {
let s = match state {
winit ::event ::ElementState ::Pressed = > true ,
winit ::event ::ElementState ::Released = > false ,
} ;
match logical_key {
winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Tab ) = > {
if s {
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 ) ,
}
} else {
//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 )
} ,
}
}
}
}
self . window . set_cursor_visible ( s ) ;
} ,
winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::F11 ) = > {
if s {
if self . window . fullscreen ( ) . is_some ( ) {
self . window . set_fullscreen ( None ) ;
} else {
self . window . set_fullscreen ( Some ( winit ::window ::Fullscreen ::Borderless ( None ) ) ) ;
}
}
} ,
winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Escape ) = > {
if s {
self . manual_mouse_lock = false ;
match self . window . set_cursor_grab ( winit ::window ::CursorGrabMode ::None ) {
Ok ( ( ) ) = > ( ) ,
Err ( e ) = > println! ( " Could not release cursor: {:?} " , e ) ,
}
self . window . set_cursor_visible ( true ) ;
}
} ,
keycode = > {
if let Some ( input_instruction ) = match keycode {
winit ::keyboard ::Key ::Named ( winit ::keyboard ::NamedKey ::Space ) = > Some ( InputInstruction ::Jump ( s ) ) ,
winit ::keyboard ::Key ::Character ( key ) = > match key . as_str ( ) {
" w " = > Some ( InputInstruction ::MoveForward ( s ) ) ,
" a " = > Some ( InputInstruction ::MoveLeft ( s ) ) ,
" s " = > Some ( InputInstruction ::MoveBack ( s ) ) ,
" d " = > Some ( InputInstruction ::MoveRight ( s ) ) ,
" e " = > Some ( InputInstruction ::MoveUp ( s ) ) ,
" q " = > Some ( InputInstruction ::MoveDown ( s ) ) ,
" z " = > Some ( InputInstruction ::Zoom ( s ) ) ,
" r " = > if s { Some ( InputInstruction ::Reset ) } else { None } ,
_ = > None ,
} ,
_ = > None ,
} {
self . physics_thread . send ( TimedInstruction {
time ,
instruction :crate ::physics_worker ::Instruction ::Input ( input_instruction ) ,
} ) . unwrap ( ) ;
}
} ,
}
} ,
_ = > ( ) ,
}
}
2024-01-30 00:19:41 +00:00
fn device_event ( & mut self , time :integer ::Time , event : winit ::event ::DeviceEvent ) {
2023-10-19 00:17:21 +00:00
match event {
winit ::event ::DeviceEvent ::MouseMotion {
delta , //these (f64,f64) are integers on my machine
} = > {
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 ) ,
}
}
//do not step the physics because the mouse polling rate is higher than the physics can run.
//essentially the previous input will be overwritten until a true step runs
//which is fine because they run all the time.
let delta = glam ::ivec2 ( delta . 0 as i32 , delta . 1 as i32 ) ;
self . mouse . pos + = delta ;
self . physics_thread . send ( TimedInstruction {
time ,
instruction :crate ::physics_worker ::Instruction ::Input ( InputInstruction ::MoveMouse ( self . mouse . pos ) ) ,
} ) . unwrap ( ) ;
} ,
winit ::event ::DeviceEvent ::MouseWheel {
delta ,
} = > {
println! ( " mousewheel {:?} " , delta ) ;
if false { //self.physics.style.use_scroll{
self . physics_thread . send ( TimedInstruction {
time ,
instruction :crate ::physics_worker ::Instruction ::Input ( InputInstruction ::Jump ( true ) ) , //activates the immediate jump path, but the style modifier prevents controls&CONTROL_JUMP bit from being set to auto jump
} ) . unwrap ( ) ;
}
}
_ = > ( ) ,
}
}
}
2024-01-18 22:26:08 +00:00
pub struct WindowContextSetup < ' a > {
2023-10-19 00:17:21 +00:00
user_settings :crate ::settings ::UserSettings ,
2024-01-18 22:26:08 +00:00
window :& ' a winit ::window ::Window ,
2024-01-30 06:37:05 +00:00
physics :crate ::physics ::PhysicsContext ,
2023-10-19 00:17:21 +00:00
graphics :crate ::graphics ::GraphicsState ,
}
2024-01-18 22:26:08 +00:00
impl < ' a > WindowContextSetup < ' a > {
pub fn new ( context :& crate ::setup ::SetupContext , window :& ' a winit ::window ::Window ) ->Self {
2023-10-19 00:17:21 +00:00
let user_settings = crate ::settings ::read_user_settings ( ) ;
2024-01-30 06:37:05 +00:00
let mut physics = crate ::physics ::PhysicsContext ::default ( ) ;
physics . state . load_user_settings ( & user_settings ) ;
2023-10-19 00:17:21 +00:00
let mut graphics = crate ::graphics ::GraphicsState ::new ( & context . device , & context . queue , & context . config ) ;
graphics . load_user_settings ( & user_settings ) ;
Self {
user_settings ,
window ,
graphics ,
physics ,
}
}
2024-01-18 22:26:08 +00:00
fn into_context ( self , setup_context :crate ::setup ::SetupContext < ' a > ) ->WindowContext < ' a > {
2023-10-19 00:17:21 +00:00
let screen_size = glam ::uvec2 ( setup_context . config . width , setup_context . config . height ) ;
let graphics_thread = crate ::graphics_worker ::new ( self . graphics , setup_context . config , setup_context . surface , setup_context . device , setup_context . queue ) ;
WindowContext {
manual_mouse_lock :false ,
mouse :crate ::physics ::MouseState ::default ( ) ,
//make sure to update this!!!!!
screen_size ,
user_settings :self . user_settings ,
window :self . window ,
physics_thread :crate ::physics_worker ::new ( self . physics , graphics_thread ) ,
}
}
2024-01-18 22:26:08 +00:00
pub fn into_worker ( self , setup_context :crate ::setup ::SetupContext < ' a > ) ->crate ::compat_worker ::QNWorker < ' a , TimedInstruction < WindowInstruction > > {
2023-10-19 00:17:21 +00:00
let mut window_context = self . into_context ( setup_context ) ;
crate ::compat_worker ::QNWorker ::new ( move | ins :TimedInstruction < WindowInstruction > | {
match ins . instruction {
WindowInstruction ::RequestRedraw = > {
window_context . window . request_redraw ( ) ;
}
WindowInstruction ::WindowEvent ( window_event ) = > {
window_context . window_event ( ins . time , window_event ) ;
} ,
WindowInstruction ::DeviceEvent ( device_event ) = > {
window_context . device_event ( ins . time , device_event ) ;
} ,
WindowInstruction ::Resize ( size ) = > {
window_context . physics_thread . send (
TimedInstruction {
time :ins . time ,
instruction :crate ::physics_worker ::Instruction ::Resize ( size , window_context . user_settings . clone ( ) )
}
) . unwrap ( ) ;
}
WindowInstruction ::Render = > {
window_context . physics_thread . send (
TimedInstruction {
time :ins . time ,
instruction :crate ::physics_worker ::Instruction ::Render
}
) . unwrap ( ) ;
}
}
} )
}
}