forked from StrafesNET/strafe-project
264 lines
10 KiB
Rust
264 lines
10 KiB
Rust
use strafesnet_common::instruction::TimedInstruction;
|
|
use strafesnet_common::session::{Time as SessionTime,TimeInner as SessionTimeInner};
|
|
use strafesnet_common::physics::{MiscInstruction,SetControlInstruction};
|
|
use crate::file::Format2;
|
|
use crate::physics_worker::Instruction as PhysicsWorkerInstruction;
|
|
use crate::session::{SessionInputInstruction,SessionControlInstruction,SessionPlaybackInstruction};
|
|
|
|
pub enum Instruction{
|
|
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_pos:glam::DVec2,
|
|
screen_size:glam::UVec2,
|
|
window:&'a winit::window::Window,
|
|
physics_thread:crate::compat_worker::QNWorker<'a,TimedInstruction<PhysicsWorkerInstruction,SessionTimeInner>>,
|
|
}
|
|
|
|
impl WindowContext<'_>{
|
|
fn get_middle_of_screen(&self)->winit::dpi::PhysicalPosition<u32>{
|
|
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(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}"),
|
|
}
|
|
},
|
|
winit::event::WindowEvent::Focused(state)=>{
|
|
//pause unpause
|
|
self.physics_thread.send(TimedInstruction{
|
|
time,
|
|
instruction:PhysicsWorkerInstruction::SessionControl(SessionControlInstruction::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();
|
|
|
|
// 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),
|
|
winit::keyboard::Key::Character(key)=>match key.as_str(){
|
|
"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;
|
|
SessionInstructionSubset::Input(SessionInputInstruction::Mode(crate::session::ImplicitModeInstruction::ResetAndRestart))
|
|
}),
|
|
"F"|"f"=>input_misc!(PracticeFly,s),
|
|
"B"|"b"=>session_ctrl!(CopyRecordingIntoReplayAndSpectate,s),
|
|
"X"|"x"=>session_ctrl!(StopSpectate,s),
|
|
"N"|"n"=>session_ctrl!(SaveReplay,s),
|
|
"J"|"j"=>session_ctrl!(LoadIntoReplayState,s),
|
|
_=>None,
|
|
},
|
|
_=>None,
|
|
}{
|
|
self.physics_thread.send(TimedInstruction{
|
|
time,
|
|
instruction:session_instruction.into(),
|
|
}).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::SessionInput(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::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();
|
|
}
|
|
},
|
|
_=>(),
|
|
}
|
|
}
|
|
}
|
|
pub fn worker<'a>(
|
|
window:&'a winit::window::Window,
|
|
setup_context:crate::setup::SetupContext<'a>,
|
|
)->crate::compat_worker::QNWorker<'a,TimedInstruction<Instruction,SessionTimeInner>>{
|
|
// 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<Instruction,SessionTimeInner>|{
|
|
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();
|
|
}
|
|
}
|
|
})
|
|
}
|