Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
64e1e762a1 | |||
ad862ae8c9 | |||
0ee17ac3d9 |
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -538,12 +538,6 @@ dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fixedbitset"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.27"
|
||||
@ -623,15 +617,6 @@ dependencies = [
|
||||
"waker-fn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fxhash"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@ -777,16 +762,6 @@ version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "include_wgsl"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "57ac28436974a64aef47cbf8453e8f1a558b779177fe50b7e3c3774e2cb9ba47"
|
||||
dependencies = [
|
||||
"naga 0.7.3",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
@ -1038,24 +1013,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "806f448a7ce662ca79ef5484ef8f451a9b7c51b8166c95f5a667228b3825a6ca"
|
||||
dependencies = [
|
||||
"bit-set",
|
||||
"bitflags 1.3.2",
|
||||
"codespan-reporting",
|
||||
"fxhash",
|
||||
"hexf-parse",
|
||||
"indexmap 1.9.3",
|
||||
"log",
|
||||
"num-traits 0.2.16",
|
||||
"spirv",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.13.0"
|
||||
@ -1069,7 +1026,6 @@ dependencies = [
|
||||
"indexmap 1.9.3",
|
||||
"log",
|
||||
"num-traits 0.2.16",
|
||||
"petgraph",
|
||||
"rustc-hash",
|
||||
"spirv",
|
||||
"termcolor",
|
||||
@ -1326,16 +1282,6 @@ version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||
|
||||
[[package]]
|
||||
name = "petgraph"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9"
|
||||
dependencies = [
|
||||
"fixedbitset",
|
||||
"indexmap 2.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.13"
|
||||
@ -1750,7 +1696,6 @@ dependencies = [
|
||||
"ddsfile",
|
||||
"env_logger",
|
||||
"glam",
|
||||
"include_wgsl",
|
||||
"lazy-regex",
|
||||
"log",
|
||||
"obj",
|
||||
@ -2082,7 +2027,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"log",
|
||||
"naga 0.13.0",
|
||||
"naga",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
@ -2107,7 +2052,7 @@ dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"codespan-reporting",
|
||||
"log",
|
||||
"naga 0.13.0",
|
||||
"naga",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle",
|
||||
@ -2144,7 +2089,7 @@ dependencies = [
|
||||
"libloading 0.8.0",
|
||||
"log",
|
||||
"metal",
|
||||
"naga 0.13.0",
|
||||
"naga",
|
||||
"objc",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
|
@ -12,7 +12,6 @@ configparser = "3.0.2"
|
||||
ddsfile = "0.5.1"
|
||||
env_logger = "0.10.0"
|
||||
glam = "0.24.1"
|
||||
include_wgsl = { version = "1.1.1", features = ["spv-out"] }
|
||||
lazy-regex = "3.0.2"
|
||||
log = "0.4.20"
|
||||
obj = "0.10.2"
|
||||
@ -22,7 +21,7 @@ rbx_binary = "0.7.1"
|
||||
rbx_dom_weak = "2.5.0"
|
||||
rbx_reflection_database = "0.2.7"
|
||||
rbx_xml = "0.13.1"
|
||||
wgpu = { version = "0.17.0", features = ["spirv"] }
|
||||
wgpu = "0.17.0"
|
||||
winit = "0.28.6"
|
||||
|
||||
#[profile.release]
|
||||
|
@ -7,6 +7,7 @@ use instruction::{TimedInstruction, InstructionConsumer};
|
||||
mod bvh;
|
||||
mod aabb;
|
||||
mod model;
|
||||
mod timers;
|
||||
mod zeroes;
|
||||
mod worker;
|
||||
mod physics;
|
||||
@ -556,7 +557,7 @@ impl framework::Example for GlobalState {
|
||||
// Create the render pipeline
|
||||
let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor {
|
||||
label: None,
|
||||
source: wgpu::ShaderSource::SpirV(Cow::Borrowed(include_wgsl_to_spv!("shader.wgsl"))),
|
||||
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
|
||||
});
|
||||
|
||||
//load textures
|
||||
|
@ -42,12 +42,13 @@ pub enum InputInstruction {
|
||||
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),
|
||||
});
|
||||
}
|
||||
@ -913,7 +924,7 @@ impl PhysicsState {
|
||||
fn predict_collision_start(&self,time:TIME,time_limit:TIME,model_id:u32) -> Option<TimedInstruction<PhysicsInstruction>> {
|
||||
let mesh0=self.mesh();
|
||||
let mesh1=self.models.get(model_id as usize).unwrap().mesh();
|
||||
let (p,v,a,body_time)=(self.body.position,self.body.velocity,self.body.acceleration,self.body.time);
|
||||
let (p,v,a,time)=(self.body.position,self.body.velocity,self.body.acceleration,self.body.time);
|
||||
//find best t
|
||||
let mut best_time=time_limit;
|
||||
let mut best_face:Option<TreyMeshFace>=None;
|
||||
@ -922,7 +933,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&0f32<v.x+a.x*t{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
@ -938,7 +949,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&v.x+a.x*t<0f32{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
@ -955,7 +966,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&0f32<v.y+a.y*t{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
@ -971,7 +982,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&v.y+a.y*t<0f32{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
@ -988,7 +999,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&0f32<v.z+a.z*t{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
@ -1004,7 +1015,7 @@ impl PhysicsState {
|
||||
//must collide now or in the future
|
||||
//must beat the current soonest collision time
|
||||
//must be moving towards surface
|
||||
let t_time=body_time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
let t_time=time+((t as f64)*1_000_000_000f64) as TIME;
|
||||
if time<=t_time&&t_time<best_time&&v.z+a.z*t<0f32{
|
||||
let dp=self.body.extrapolated_position(t_time)-p;
|
||||
//faces must be overlapping
|
||||
|
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);
|
||||
}
|
@ -79,7 +79,7 @@ fn test_worker() {
|
||||
);
|
||||
|
||||
// Send tasks to the worker
|
||||
for _ in 0..5 {
|
||||
for i in 0..5 {
|
||||
let task = crate::instruction::TimedInstruction{
|
||||
time:0,
|
||||
instruction:crate::physics::PhysicsInstruction::StrafeTick,
|
||||
|
Reference in New Issue
Block a user