Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
64e1e762a1 | |||
ad862ae8c9 | |||
0ee17ac3d9 | |||
e2af6fc4ed | |||
bdc0dd1b3b |
174
Cargo.lock
generated
174
Cargo.lock
generated
@ -86,21 +86,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278"
|
||||
dependencies = [
|
||||
"num-traits 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "array-init"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc"
|
||||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.7"
|
||||
@ -178,30 +163,6 @@ version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
|
||||
|
||||
[[package]]
|
||||
name = "binrw"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f846d8732b2a55b569b885852ecc925a2b1f24568f4707f8b1ccd5dc6805ea9b"
|
||||
dependencies = [
|
||||
"array-init",
|
||||
"binrw_derive",
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binrw_derive"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c2aa66a5e35daf7f91ed44c945886597ef4c327f34f68b6bbf22951a250ceeb"
|
||||
dependencies = [
|
||||
"either",
|
||||
"owo-colors",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
@ -277,27 +238,12 @@ dependencies = [
|
||||
"objc2-encode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "build_const"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
|
||||
|
||||
[[package]]
|
||||
name = "bv"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340"
|
||||
dependencies = [
|
||||
"feature-probe",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.13.1"
|
||||
@ -318,12 +264,6 @@ dependencies = [
|
||||
"syn 2.0.29",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
@ -366,16 +306,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "cgmath"
|
||||
version = "0.18.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-traits 0.2.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
@ -453,15 +383,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb"
|
||||
dependencies = [
|
||||
"build_const",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
@ -508,7 +429,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "594ecd967c2f40db5dde8da4c356975fc1fe030e951c7c3962f6dc2e80042e87"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"byteorder 1.4.3",
|
||||
"byteorder",
|
||||
"enum_primitive",
|
||||
]
|
||||
|
||||
@ -544,12 +465,6 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "enum_primitive"
|
||||
version = "0.1.1"
|
||||
@ -623,12 +538,6 @@ dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "feature-probe"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.27"
|
||||
@ -1028,25 +937,6 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "782ba3f542e8bc1349386c15e9dc3119ae6da96479f96b3863cc7a88bbdfd4e4"
|
||||
dependencies = [
|
||||
"byteorder 0.5.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lzma-rs"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aba8ecb0450dfabce4ad72085eed0a75dffe8f21f7ada05638564ea9db2d7fb1"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3",
|
||||
"crc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
@ -1351,12 +1241,6 @@ dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
version = "3.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.1.0"
|
||||
@ -1651,7 +1535,7 @@ version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3",
|
||||
"byteorder",
|
||||
"num-traits 0.2.16",
|
||||
"paste",
|
||||
]
|
||||
@ -1662,7 +1546,7 @@ version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3",
|
||||
"byteorder",
|
||||
"rmp",
|
||||
"serde",
|
||||
]
|
||||
@ -1821,7 +1705,6 @@ dependencies = [
|
||||
"rbx_dom_weak",
|
||||
"rbx_reflection_database",
|
||||
"rbx_xml",
|
||||
"vbsp",
|
||||
"wgpu",
|
||||
"winit",
|
||||
]
|
||||
@ -1860,17 +1743,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn_util"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6754c4559b79657554e9d8a0d56e65e490c76d382b9c23108364ec4125dea23c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.2.0"
|
||||
@ -1972,35 +1844,6 @@ version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
|
||||
|
||||
[[package]]
|
||||
name = "vbsp"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/icewind1991/vbsp?rev=0850bb8dbd695a770d39a06f2cc880aa9d626bf7#0850bb8dbd695a770d39a06f2cc880aa9d626bf7"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"binrw",
|
||||
"bitflags 1.3.2",
|
||||
"bv",
|
||||
"cgmath",
|
||||
"lzma-rs",
|
||||
"num_enum 0.5.11",
|
||||
"static_assertions",
|
||||
"thiserror",
|
||||
"vbsp-derive",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vbsp-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/icewind1991/vbsp?rev=0850bb8dbd695a770d39a06f2cc880aa9d626bf7#0850bb8dbd695a770d39a06f2cc880aa9d626bf7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"syn_util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
@ -2520,14 +2363,3 @@ name = "xml-rs"
|
||||
version = "0.8.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1"
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.3"
|
||||
source = "git+https://github.com/icewind1991/zip?branch=lzma-decompression#67239e847f4fbe3a5b847707ee3228ac370388f5"
|
||||
dependencies = [
|
||||
"byteorder 1.4.3",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"lzma",
|
||||
]
|
||||
|
@ -21,7 +21,6 @@ rbx_binary = "0.7.1"
|
||||
rbx_dom_weak = "2.5.0"
|
||||
rbx_reflection_database = "0.2.7"
|
||||
rbx_xml = "0.13.1"
|
||||
vbsp = { git="https://github.com/icewind1991/vbsp", rev = "0850bb8dbd695a770d39a06f2cc880aa9d626bf7" }
|
||||
wgpu = "0.17.0"
|
||||
winit = "0.28.6"
|
||||
|
||||
|
@ -1,24 +0,0 @@
|
||||
pub fn generate_indexed_models<R:std::io::Read+std::io::Seek>(input:&mut R) -> crate::model::IndexedModelInstances{
|
||||
let mut spawn_point=glam::Vec3::ZERO;
|
||||
|
||||
let mut indexed_models=Vec::new();
|
||||
|
||||
let mut s=Vec::new();
|
||||
|
||||
match input.read_to_end(&mut s){
|
||||
Ok(guac)=>println!("readed to string {:?}", guac),
|
||||
Err(e)=>println!("faile {:?}",e),
|
||||
}
|
||||
|
||||
match vbsp::Bsp::read(s.as_slice()){
|
||||
Ok(guac)=>println!("we got the guac {:?}", guac),
|
||||
Err(e)=>println!("rotten {:?}",e),
|
||||
}
|
||||
|
||||
crate::model::IndexedModelInstances{
|
||||
textures:Vec::new(),
|
||||
models:indexed_models,
|
||||
spawn_point,
|
||||
modes:Vec::new(),
|
||||
}
|
||||
}
|
110
src/main.rs
110
src/main.rs
@ -7,6 +7,7 @@ use instruction::{TimedInstruction, InstructionConsumer};
|
||||
mod bvh;
|
||||
mod aabb;
|
||||
mod model;
|
||||
mod timers;
|
||||
mod zeroes;
|
||||
mod worker;
|
||||
mod physics;
|
||||
@ -14,7 +15,6 @@ mod settings;
|
||||
mod framework;
|
||||
mod primitives;
|
||||
mod instruction;
|
||||
mod load_bsp;
|
||||
mod load_roblox;
|
||||
|
||||
struct Entity {
|
||||
@ -879,7 +879,7 @@ impl framework::Example for GlobalState {
|
||||
},
|
||||
}
|
||||
},
|
||||
b"VBSP"=>Some(load_bsp::generate_indexed_models(&mut input)),
|
||||
//b"VBSP"=>Some(load_bsp::generate_indexed_models(input)),
|
||||
//b"SNFM"=>Some(sniffer::generate_indexed_models(input)),
|
||||
//b"SNFB"=>Some(sniffer::load_bot(input)),
|
||||
other=>{
|
||||
@ -919,61 +919,23 @@ impl framework::Example for GlobalState {
|
||||
|
||||
#[allow(clippy::single_match)]
|
||||
fn update(&mut self, window: &winit::window::Window, device: &wgpu::Device, queue: &wgpu::Queue, event: winit::event::WindowEvent) {
|
||||
let time=self.start_time.elapsed().as_nanos() as i64;
|
||||
match event {
|
||||
winit::event::WindowEvent::DroppedFile(path) => self.load_file(path,device,queue),
|
||||
winit::event::WindowEvent::Focused(state)=>{
|
||||
//pause unpause
|
||||
//recalculate pressed keys on focus
|
||||
}
|
||||
_=>(),
|
||||
}
|
||||
}
|
||||
|
||||
fn device_event(&mut self, window: &winit::window::Window, event: winit::event::DeviceEvent) {
|
||||
//there's no way this is the best way get a timestamp.
|
||||
let time=self.start_time.elapsed().as_nanos() as i64;
|
||||
match event {
|
||||
winit::event::DeviceEvent::Key(winit::event::KeyboardInput {
|
||||
state,
|
||||
scancode: keycode,
|
||||
},
|
||||
winit::event::WindowEvent::KeyboardInput {
|
||||
input:winit::event::KeyboardInput{state, virtual_keycode,..},
|
||||
..
|
||||
}) => {
|
||||
}=>{
|
||||
let s=match state {
|
||||
winit::event::ElementState::Pressed => true,
|
||||
winit::event::ElementState::Released => false,
|
||||
};
|
||||
if let Some(input_instruction)=match keycode {
|
||||
17=>Some(InputInstruction::MoveForward(s)),//W
|
||||
30=>Some(InputInstruction::MoveLeft(s)),//A
|
||||
31=>Some(InputInstruction::MoveBack(s)),//S
|
||||
32=>Some(InputInstruction::MoveRight(s)),//D
|
||||
18=>Some(InputInstruction::MoveUp(s)),//E
|
||||
16=>Some(InputInstruction::MoveDown(s)),//Q
|
||||
57=>Some(InputInstruction::Jump(s)),//Space
|
||||
44=>Some(InputInstruction::Zoom(s)),//Z
|
||||
19=>if s{Some(InputInstruction::Reset)}else{None},//R
|
||||
87=>{//F11
|
||||
if s{
|
||||
if window.fullscreen().is_some(){
|
||||
window.set_fullscreen(None);
|
||||
}else{
|
||||
window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(None)));
|
||||
}
|
||||
}
|
||||
None
|
||||
},
|
||||
01=>{//Esc
|
||||
if s{
|
||||
self.manual_mouse_lock=false;
|
||||
match window.set_cursor_grab(winit::window::CursorGrabMode::None){
|
||||
Ok(())=>(),
|
||||
Err(e)=>println!("Could not release cursor: {:?}",e),
|
||||
}
|
||||
window.set_cursor_visible(true);
|
||||
}
|
||||
None
|
||||
},
|
||||
15=>{//Tab
|
||||
match virtual_keycode{
|
||||
Some(winit::event::VirtualKeyCode::Tab)=>{
|
||||
if s{
|
||||
self.manual_mouse_lock=false;
|
||||
match window.set_cursor_position(winit::dpi::PhysicalPosition::new(self.graphics.camera.screen_size.x as f32/2.0, self.graphics.camera.screen_size.y as f32/2.0)){
|
||||
@ -1001,16 +963,56 @@ impl framework::Example for GlobalState {
|
||||
}
|
||||
}
|
||||
window.set_cursor_visible(s);
|
||||
None
|
||||
},
|
||||
_ => {println!("scancode {}",keycode);None},
|
||||
}{
|
||||
self.physics_thread.send(TimedInstruction{
|
||||
time,
|
||||
instruction:input_instruction,
|
||||
}).unwrap();
|
||||
Some(winit::event::VirtualKeyCode::F11)=>{
|
||||
if s{
|
||||
if window.fullscreen().is_some(){
|
||||
window.set_fullscreen(None);
|
||||
}else{
|
||||
window.set_fullscreen(Some(winit::window::Fullscreen::Borderless(None)));
|
||||
}
|
||||
}
|
||||
},
|
||||
Some(winit::event::VirtualKeyCode::Escape)=>{
|
||||
if s{
|
||||
self.manual_mouse_lock=false;
|
||||
match window.set_cursor_grab(winit::window::CursorGrabMode::None){
|
||||
Ok(())=>(),
|
||||
Err(e)=>println!("Could not release cursor: {:?}",e),
|
||||
}
|
||||
window.set_cursor_visible(true);
|
||||
}
|
||||
},
|
||||
Some(keycode)=>{
|
||||
if let Some(input_instruction)=match keycode {
|
||||
winit::event::VirtualKeyCode::W => Some(InputInstruction::MoveForward(s)),
|
||||
winit::event::VirtualKeyCode::A => Some(InputInstruction::MoveLeft(s)),
|
||||
winit::event::VirtualKeyCode::S => Some(InputInstruction::MoveBack(s)),
|
||||
winit::event::VirtualKeyCode::D => Some(InputInstruction::MoveRight(s)),
|
||||
winit::event::VirtualKeyCode::E => Some(InputInstruction::MoveUp(s)),
|
||||
winit::event::VirtualKeyCode::Q => Some(InputInstruction::MoveDown(s)),
|
||||
winit::event::VirtualKeyCode::Space => Some(InputInstruction::Jump(s)),
|
||||
winit::event::VirtualKeyCode::Z => Some(InputInstruction::Zoom(s)),
|
||||
winit::event::VirtualKeyCode::R => if s{Some(InputInstruction::Reset)}else{None},
|
||||
_ => None,
|
||||
}{
|
||||
self.physics_thread.send(TimedInstruction{
|
||||
time,
|
||||
instruction:input_instruction,
|
||||
}).unwrap();
|
||||
}
|
||||
},
|
||||
_=>(),
|
||||
}
|
||||
},
|
||||
_=>(),
|
||||
}
|
||||
}
|
||||
|
||||
fn device_event(&mut self, window: &winit::window::Window, event: winit::event::DeviceEvent) {
|
||||
//there's no way this is the best way get a timestamp.
|
||||
let time=self.start_time.elapsed().as_nanos() as i64;
|
||||
match event {
|
||||
winit::event::DeviceEvent::MouseMotion {
|
||||
delta,//these (f64,f64) are integers on my machine
|
||||
} => {
|
||||
|
@ -19,12 +19,12 @@ pub enum PhysicsInstruction {
|
||||
pub enum PhysicsInputInstruction {
|
||||
ReplaceMouse(MouseState,MouseState),
|
||||
SetNextMouse(MouseState),
|
||||
SetMoveForward(bool),
|
||||
SetMoveLeft(bool),
|
||||
SetMoveBack(bool),
|
||||
SetMoveRight(bool),
|
||||
SetMoveUp(bool),
|
||||
SetMoveBack(bool),
|
||||
SetMoveLeft(bool),
|
||||
SetMoveDown(bool),
|
||||
SetMoveForward(bool),
|
||||
SetJump(bool),
|
||||
SetZoom(bool),
|
||||
Reset,
|
||||
@ -33,21 +33,22 @@ pub enum PhysicsInputInstruction {
|
||||
#[derive(Debug)]
|
||||
pub enum InputInstruction {
|
||||
MoveMouse(glam::IVec2),
|
||||
MoveForward(bool),
|
||||
MoveLeft(bool),
|
||||
MoveBack(bool),
|
||||
MoveRight(bool),
|
||||
MoveUp(bool),
|
||||
MoveBack(bool),
|
||||
MoveLeft(bool),
|
||||
MoveDown(bool),
|
||||
MoveForward(bool),
|
||||
Jump(bool),
|
||||
Zoom(bool),
|
||||
Reset,
|
||||
SetPaused(bool),
|
||||
Idle,
|
||||
//Idle: there were no input events, but the simulation is safe to advance to this timestep
|
||||
//for interpolation / networking / playback reasons, most playback heads will always want
|
||||
//to be 1 instruction ahead to generate the next state for interpolation.
|
||||
}
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone,Debug)]
|
||||
pub struct Body {
|
||||
position: glam::Vec3,//I64 where 2^32 = 1 u
|
||||
velocity: glam::Vec3,//I64 where 2^32 = 1 u/s
|
||||
@ -453,6 +454,7 @@ impl PhysicsState {
|
||||
pub fn into_worker(mut self)->crate::worker::CompatWorker<TimedInstruction<InputInstruction>,PhysicsOutputState,Box<dyn FnMut(TimedInstruction<InputInstruction>)->PhysicsOutputState>>{
|
||||
let mut mouse_blocking=true;
|
||||
let mut last_mouse_time=self.next_mouse.time;
|
||||
let mut simulation_timer=crate::timers::UnscaledTimer::unpaused();
|
||||
let mut timeline=std::collections::VecDeque::new();
|
||||
crate::worker::CompatWorker::new(self.output(),Box::new(move |ins:TimedInstruction<InputInstruction>|{
|
||||
if if let Some(phys_input)=match ins.instruction{
|
||||
@ -460,17 +462,17 @@ impl PhysicsState {
|
||||
if mouse_blocking{
|
||||
//tell the game state which is living in the past about its future
|
||||
timeline.push_front(TimedInstruction{
|
||||
time:last_mouse_time,
|
||||
time:simulation_timer.time(last_mouse_time),
|
||||
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:m}),
|
||||
});
|
||||
}else{
|
||||
//mouse has just started moving again after being still for longer than 10ms.
|
||||
//replace the entire mouse interpolation state to avoid an intermediate state with identical m0.t m1.t timestamps which will divide by zero
|
||||
timeline.push_front(TimedInstruction{
|
||||
time:last_mouse_time,
|
||||
time:simulation_timer.time(last_mouse_time),
|
||||
instruction:PhysicsInputInstruction::ReplaceMouse(
|
||||
MouseState{time:last_mouse_time,pos:self.next_mouse.pos},
|
||||
MouseState{time:ins.time,pos:m}
|
||||
MouseState{time:simulation_timer.time(last_mouse_time),pos:self.next_mouse.pos},
|
||||
MouseState{time:simulation_timer.time(ins.time),pos:m}
|
||||
),
|
||||
});
|
||||
//delay physics execution until we have an interpolation target
|
||||
@ -479,6 +481,14 @@ impl PhysicsState {
|
||||
last_mouse_time=ins.time;
|
||||
None
|
||||
},
|
||||
InputInstruction::SetPaused(s)=>{
|
||||
if s{
|
||||
simulation_timer.pause(ins.time);
|
||||
}else{
|
||||
simulation_timer.unpause(ins.time);
|
||||
}
|
||||
Some(PhysicsInputInstruction::Idle)
|
||||
}
|
||||
InputInstruction::MoveForward(s)=>Some(PhysicsInputInstruction::SetMoveForward(s)),
|
||||
InputInstruction::MoveLeft(s)=>Some(PhysicsInputInstruction::SetMoveLeft(s)),
|
||||
InputInstruction::MoveBack(s)=>Some(PhysicsInputInstruction::SetMoveBack(s)),
|
||||
@ -492,7 +502,7 @@ impl PhysicsState {
|
||||
}{
|
||||
//non-mouse event
|
||||
timeline.push_back(TimedInstruction{
|
||||
time:ins.time,
|
||||
time:simulation_timer.time(ins.time),
|
||||
instruction:phys_input,
|
||||
});
|
||||
|
||||
@ -504,7 +514,7 @@ impl PhysicsState {
|
||||
if 10_000_000<ins.time-self.next_mouse.time{
|
||||
//push an event to extrapolate no movement from
|
||||
timeline.push_front(TimedInstruction{
|
||||
time:last_mouse_time,
|
||||
time:simulation_timer.time(last_mouse_time),
|
||||
instruction:PhysicsInputInstruction::SetNextMouse(MouseState{time:ins.time,pos:self.next_mouse.pos}),
|
||||
});
|
||||
last_mouse_time=ins.time;
|
||||
@ -526,9 +536,10 @@ impl PhysicsState {
|
||||
}{
|
||||
//empty queue
|
||||
while let Some(instruction)=timeline.pop_front(){
|
||||
self.run(instruction.time);
|
||||
let simulation_time=simulation_timer.time(instruction.time);
|
||||
self.run(simulation_time);
|
||||
self.process_instruction(TimedInstruction{
|
||||
time:instruction.time,
|
||||
time:simulation_time,
|
||||
instruction:PhysicsInstruction::Input(instruction.instruction),
|
||||
});
|
||||
}
|
||||
|
237
src/timers.rs
Normal file
237
src/timers.rs
Normal file
@ -0,0 +1,237 @@
|
||||
type TIME=crate::physics::TIME;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Timescale{
|
||||
num:i64,
|
||||
den:std::num::NonZeroU64,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Paused{}
|
||||
#[derive(Clone)]
|
||||
pub struct Unpaused{}
|
||||
#[derive(Clone)]
|
||||
pub struct PausedScaled{scale:Timescale}
|
||||
#[derive(Clone)]
|
||||
pub struct UnpausedScaled{scale:Timescale}
|
||||
|
||||
pub trait TimerState{}
|
||||
impl TimerState for Paused{}
|
||||
impl TimerState for Unpaused{}
|
||||
impl TimerState for PausedScaled{}
|
||||
impl TimerState for UnpausedScaled{}
|
||||
|
||||
pub trait IsPaused{}
|
||||
impl IsPaused for Paused{}
|
||||
impl IsPaused for PausedScaled{}
|
||||
|
||||
pub trait IsUnpaused{}
|
||||
impl IsUnpaused for Unpaused{}
|
||||
impl IsUnpaused for UnpausedScaled{}
|
||||
|
||||
pub trait IsScaled{}
|
||||
impl IsScaled for PausedScaled{}
|
||||
impl IsScaled for UnpausedScaled{}
|
||||
|
||||
pub trait IsUnscaled{}
|
||||
impl IsUnscaled for Paused{}
|
||||
impl IsUnscaled for Unpaused{}
|
||||
|
||||
//scaled timer wrapper
|
||||
enum Scaled{
|
||||
Paused(Timer<PausedScaled>),
|
||||
Unpaused(Timer<UnpausedScaled>),
|
||||
}
|
||||
pub struct ScaledTimer{
|
||||
timer:Scaled,
|
||||
}
|
||||
impl ScaledTimer{
|
||||
pub fn unpaused()->Self{
|
||||
Self{
|
||||
timer:Scaled::Unpaused(unpaused_scaled(Timescale{num:1,den:std::num::NonZeroU64::new(1).unwrap()}))
|
||||
}
|
||||
}
|
||||
pub fn time(&self,time:TIME)->TIME{
|
||||
match &self.timer{
|
||||
Scaled::Paused(timer)=>timer.time(),
|
||||
Scaled::Unpaused(timer)=>timer.time(time),
|
||||
}
|
||||
}
|
||||
pub fn pause(&mut self,time:TIME){
|
||||
match &self.timer{
|
||||
Scaled::Paused(_)=>(),
|
||||
Scaled::Unpaused(timer)=>self.timer=Scaled::Paused(timer.clone().pause(time)),
|
||||
};
|
||||
}
|
||||
pub fn unpause(&mut self,time:TIME){
|
||||
match &self.timer{
|
||||
Scaled::Paused(timer)=>self.timer=Scaled::Unpaused(timer.clone().unpause(time)),
|
||||
Scaled::Unpaused(_)=>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//unscaled timer wrapper
|
||||
enum Unscaled{
|
||||
Paused(Timer<Paused>),
|
||||
Unpaused(Timer<Unpaused>),
|
||||
}
|
||||
pub struct UnscaledTimer{
|
||||
timer:Unscaled,
|
||||
}
|
||||
|
||||
impl UnscaledTimer{
|
||||
pub fn unpaused()->Self{
|
||||
Self{
|
||||
timer:Unscaled::Unpaused(unpaused())
|
||||
}
|
||||
}
|
||||
pub fn time(&self,time:TIME)->TIME{
|
||||
match &self.timer{
|
||||
Unscaled::Paused(timer)=>timer.time(),
|
||||
Unscaled::Unpaused(timer)=>timer.time(time),
|
||||
}
|
||||
}
|
||||
pub fn pause(&mut self,time:TIME){
|
||||
match &self.timer{
|
||||
Unscaled::Paused(_)=>(),
|
||||
Unscaled::Unpaused(timer)=>self.timer=Unscaled::Paused(timer.clone().pause(time)),
|
||||
};
|
||||
}
|
||||
pub fn unpause(&mut self,time:TIME){
|
||||
match &self.timer{
|
||||
Unscaled::Paused(timer)=>self.timer=Unscaled::Unpaused(timer.clone().unpause(time)),
|
||||
Unscaled::Unpaused(_)=>(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Timer<State:TimerState>{
|
||||
offset:crate::physics::TIME,
|
||||
state:State,
|
||||
}
|
||||
|
||||
fn get_offset(time:TIME,write_time:TIME)->TIME{
|
||||
write_time-time
|
||||
}
|
||||
fn get_offset_scaled(time:TIME,write_time:TIME,scale:&Timescale)->TIME{
|
||||
write_time-time*scale.num/scale.den.get() as i64
|
||||
}
|
||||
|
||||
fn paused()->Timer<Paused>{
|
||||
Timer{
|
||||
offset:0,
|
||||
state:Paused{},
|
||||
}
|
||||
}
|
||||
fn unpaused()->Timer<Unpaused>{
|
||||
Timer{
|
||||
offset:0,
|
||||
state:Unpaused{},
|
||||
}
|
||||
}
|
||||
fn paused_scaled(scale:Timescale)->Timer<PausedScaled>{
|
||||
Timer{
|
||||
offset:0,
|
||||
state:PausedScaled{scale},
|
||||
}
|
||||
}
|
||||
fn unpaused_scaled(scale:Timescale)->Timer<UnpausedScaled>{
|
||||
Timer{
|
||||
offset:0,
|
||||
state:UnpausedScaled{scale},
|
||||
}
|
||||
}
|
||||
impl Timer<Paused>{
|
||||
pub fn time(&self)->TIME{
|
||||
self.offset
|
||||
}
|
||||
pub fn unpause(self,time:TIME)->Timer<Unpaused>{
|
||||
Timer{
|
||||
offset:get_offset(time,self.time()),
|
||||
state:Unpaused{},
|
||||
}
|
||||
}
|
||||
pub fn set_time(&mut self,time:TIME,write_time:TIME){
|
||||
self.offset=get_offset(time,write_time);
|
||||
}
|
||||
pub fn set_scale(self,time:TIME,scale:Timescale)->Timer<PausedScaled>{
|
||||
Timer{
|
||||
offset:get_offset_scaled(time,self.time(),&scale),
|
||||
state:PausedScaled{scale},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Timer<Unpaused>{
|
||||
pub fn time(&self,time:TIME)->TIME{
|
||||
self.offset+time
|
||||
}
|
||||
pub fn pause(self,time:TIME)->Timer<Paused>{
|
||||
Timer{
|
||||
offset:self.time(time),
|
||||
state:Paused{},
|
||||
}
|
||||
}
|
||||
pub fn set_time(&mut self,time:TIME,write_time:TIME){
|
||||
self.offset=get_offset(time,write_time);
|
||||
}
|
||||
pub fn set_scale(self,time:TIME,scale:Timescale)->Timer<UnpausedScaled>{
|
||||
Timer{
|
||||
offset:get_offset_scaled(time,self.time(time),&scale),
|
||||
state:UnpausedScaled{scale},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Timer<PausedScaled>{
|
||||
pub fn time(&self)->TIME{
|
||||
self.offset
|
||||
}
|
||||
pub fn unpause(self,time:TIME)->Timer<UnpausedScaled>{
|
||||
Timer{
|
||||
offset:get_offset_scaled(time,self.time(),&self.state.scale),
|
||||
state:UnpausedScaled{scale:self.state.scale},
|
||||
}
|
||||
}
|
||||
pub fn set_time(&mut self,time:TIME,write_time:TIME){
|
||||
self.offset=get_offset_scaled(time,write_time,&self.state.scale);
|
||||
}
|
||||
pub fn set_scale(self,time:TIME,scale:Timescale)->Timer<PausedScaled>{
|
||||
Timer{
|
||||
offset:get_offset_scaled(time,self.time(),&scale),
|
||||
state:PausedScaled{scale},
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Timer<UnpausedScaled>{
|
||||
pub fn time(&self,time:TIME)->TIME{
|
||||
self.offset+time*self.state.scale.num/self.state.scale.den.get() as i64
|
||||
}
|
||||
pub fn pause(self,time:TIME)->Timer<PausedScaled>{
|
||||
Timer{
|
||||
offset:self.time(time),
|
||||
state:PausedScaled{scale:self.state.scale},
|
||||
}
|
||||
}
|
||||
pub fn set_time(&mut self,time:TIME,write_time:TIME){
|
||||
self.offset=get_offset_scaled(time,write_time,&self.state.scale);
|
||||
}
|
||||
pub fn set_scale(self,time:TIME,scale:Timescale)->Timer<UnpausedScaled>{
|
||||
Timer{
|
||||
offset:get_offset_scaled(time,self.time(time),&scale),
|
||||
//self.offset+time*self.state.scale.num/self.state.scale.den.get() as i64-time*scale.num/scale.den.get() as i64
|
||||
state:UnpausedScaled{scale},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_timer_unscaled(){
|
||||
const ONE_SECOND:TIME=1_000_000_000;
|
||||
let run_prepare=paused();
|
||||
|
||||
let run_start=run_prepare.unpause(ONE_SECOND);
|
||||
let run_finish=run_start.pause(11*ONE_SECOND);
|
||||
|
||||
assert_eq!(run_finish.time(),10*ONE_SECOND);
|
||||
}
|
Reference in New Issue
Block a user