use strafesnet_common::instruction::TimedInstruction; use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner}; use strafesnet_common::physics::{OtherInstruction,OtherOtherInstruction,SetControlInstruction}; use crate::physics_worker::Instruction as PhysicsWorkerInstruction; use crate::session::SessionInputInstruction; pub enum Instruction{ Resize(winit::dpi::PhysicalSize), WindowEvent(winit::event::WindowEvent), DeviceEvent(winit::event::DeviceEvent), RequestRedraw, Render, } //holds thread handles to dispatch to struct WindowContext<'a>{ manual_mouse_lock:bool, mouse_pos:glam::DVec2, screen_size:glam::UVec2, window:&'a winit::window::Window, physics_thread:crate::compat_worker::QNWorker<'a,TimedInstruction>, } impl WindowContext<'_>{ fn get_middle_of_screen(&self)->winit::dpi::PhysicalPosition{ winit::dpi::PhysicalPosition::new(self.screen_size.x/2,self.screen_size.y/2) } fn window_event(&mut self,time:SessionTime,event:winit::event::WindowEvent){ match event{ winit::event::WindowEvent::DroppedFile(path)=>{ match crate::file::load(path.as_path()){ Ok(map)=>self.physics_thread.send(TimedInstruction{time,instruction:PhysicsWorkerInstruction::ChangeMap(map)}).unwrap(), Err(e)=>println!("Failed to load map: {e}"), } }, winit::event::WindowEvent::Focused(state)=>{ //pause unpause self.physics_thread.send(TimedInstruction{ time, instruction:PhysicsWorkerInstruction::SetPaused(!state), }).unwrap(); //recalculate pressed keys on focus }, winit::event::WindowEvent::KeyboardInput{ event:winit::event::KeyEvent{state,logical_key,repeat:false,..}, .. }=>{ 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) }, } } } self.window.set_cursor_visible(state.is_pressed()); }, (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))); } }, (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), } self.window.set_cursor_visible(true); }, (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))), 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))), "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) }), "F"|"f"=>s.then_some(SessionInputInstruction::Other(OtherOtherInstruction::PracticeFly)), _=>None, }, _=>None, }{ self.physics_thread.send(TimedInstruction{ time, instruction:PhysicsWorkerInstruction::Input(session_input_instruction), }).unwrap(); } }, } }, _=>(), } } fn device_event(&mut self,time:SessionTime,event: winit::event::DeviceEvent){ match event{ winit::event::DeviceEvent::MouseMotion{ delta, }=>{ 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), } } 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())), }).unwrap(); }, winit::event::DeviceEvent::MouseWheel { delta, }=>{ println!("mousewheel {:?}",delta); 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 }).unwrap(); } }, _=>(), } } } pub fn worker<'a>( window:&'a winit::window::Window, setup_context:crate::setup::SetupContext<'a>, )->crate::compat_worker::QNWorker<'a,TimedInstruction>{ // WindowContextSetup::new let user_settings=crate::settings::read_user_settings(); let mut graphics=crate::graphics::GraphicsState::new(&setup_context.device,&setup_context.queue,&setup_context.config); graphics.load_user_settings(&user_settings); //WindowContextSetup::into_context 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, mouse_pos:glam::DVec2::ZERO, //make sure to update this!!!!! screen_size, window, physics_thread:crate::physics_worker::new( graphics_thread, user_settings, ), }; //WindowContextSetup::into_worker crate::compat_worker::QNWorker::new(move |ins:TimedInstruction|{ match ins.instruction{ Instruction::RequestRedraw=>{ window_context.window.request_redraw(); } Instruction::WindowEvent(window_event)=>{ window_context.window_event(ins.time,window_event); }, Instruction::DeviceEvent(device_event)=>{ window_context.device_event(ins.time,device_event); }, Instruction::Resize(size)=>{ window_context.physics_thread.send( TimedInstruction{ time:ins.time, instruction:PhysicsWorkerInstruction::Resize(size) } ).unwrap(); } Instruction::Render=>{ window_context.physics_thread.send( TimedInstruction{ time:ins.time, instruction:PhysicsWorkerInstruction::Render } ).unwrap(); } } }) }