Sfoglia il codice sorgente

Refactored Resources and Systems

raster
Bergmann89 3 anni fa
parent
commit
1323faefc9
24 ha cambiato i file con 370 aggiunte e 246 eliminazioni
  1. +13
    -0
      Cargo.lock
  2. +1
    -0
      space-crush/Cargo.toml
  3. +0
    -69
      space-crush/src/app/misc/frame_counter.rs
  4. +9
    -41
      space-crush/src/app/misc/mod.rs
  5. +57
    -10
      space-crush/src/app/misc/text.rs
  6. +86
    -0
      space-crush/src/app/misc/world.rs
  7. +11
    -7
      space-crush/src/app/mod.rs
  8. +51
    -19
      space-crush/src/app/render/debug.rs
  9. +18
    -52
      space-crush/src/app/render/init.rs
  10. +1
    -1
      space-crush/src/app/render/mod.rs
  11. +16
    -20
      space-crush/src/app/render/test.rs
  12. +0
    -0
      space-crush/src/app/resources/camera.rs
  13. +0
    -0
      space-crush/src/app/resources/geometry.rs
  14. +9
    -0
      space-crush/src/app/resources/mod.rs
  15. +6
    -0
      space-crush/src/app/resources/state.rs
  16. +0
    -0
      space-crush/src/app/resources/vfs.rs
  17. +2
    -2
      space-crush/src/app/systems/mod.rs
  18. +9
    -19
      space-crush/src/app/systems/state_update.rs
  19. +3
    -0
      space-crush/src/error.rs
  20. +19
    -6
      space-crush/src/server/mod.rs
  21. +5
    -0
      space-crush/src/server/resources/global.rs
  22. +3
    -0
      space-crush/src/server/resources/mod.rs
  23. +3
    -0
      space-crush/src/server/systems/mod.rs
  24. +48
    -0
      space-crush/src/server/systems/process.rs

+ 13
- 0
Cargo.lock Vedi File

@@ -1483,10 +1483,22 @@ dependencies = [
"hashbrown",
"mopa",
"rayon",
"shred-derive",
"smallvec",
"tynm",
]

[[package]]
name = "shred-derive"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1f37080f2751fbf091dbdebaa95bd6cf9dbf74ad1d50396b1908518a1747fdf"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

[[package]]
name = "shrev"
version = "1.1.1"
@@ -1539,6 +1551,7 @@ dependencies = [
"num_cpus",
"ordered-float 2.0.0",
"rand",
"shred",
"shrev",
"specs",
"thiserror",


+ 1
- 0
space-crush/Cargo.toml Vedi File

@@ -15,6 +15,7 @@ log = { version = "0.4", features = [ "max_level_trace", "release_max_level_warn
num_cpus = "1.13"
ordered-float = "2.0"
rand = "0.7"
shred = "0.10"
shrev = "1.1"
specs = "0.16"
thiserror = "1.0"


+ 0
- 69
space-crush/src/app/misc/frame_counter.rs Vedi File

@@ -1,69 +0,0 @@
#![allow(dead_code)]

use std::mem::take;
use std::time::Instant;

pub struct FrameCounter {
last_frame: Instant,
time: f32,
count: usize,
fps: usize,
delta: f32,
updated: bool,
}

impl FrameCounter {
pub fn updated(&self) -> bool {
self.updated
}

#[inline]
pub fn fps(&self) -> usize {
self.fps
}

#[inline]
pub fn delta(&self) -> f32 {
self.delta
}

#[inline]
pub fn next(&mut self) -> bool {
let now = Instant::now();

self.delta = (now - self.last_frame).as_secs_f32();
self.last_frame = now;
self.time += self.delta;
self.count += 1;

self.updated = if self.time >= 2.0 {
self.time = 0.0;
self.fps = 0;
self.count = 0;

true
} else if self.time >= 1.0 {
self.time -= 1.0;
self.fps = take(&mut self.count);

true
} else {
false
};

self.updated
}
}

impl Default for FrameCounter {
fn default() -> Self {
Self {
last_frame: Instant::now(),
time: 0.0,
count: 0,
fps: 0,
delta: 0.0,
updated: false,
}
}
}

+ 9
- 41
space-crush/src/app/misc/mod.rs Vedi File

@@ -1,41 +1,9 @@
pub mod camera;
pub mod events;
pub mod frame_counter;
pub mod geometry;
pub mod text;
pub mod vfs;
pub mod window;

use std::iter::Iterator;
use std::ops::Deref;

use self::vfs::Vfs;
use glc::{
shader::{Program, Shader, Type},
texture::{Data, Target, Texture},
};

use crate::Error;

pub fn load_program<I>(vfs: &Vfs, iter: I) -> Result<Program, Error>
where
I: IntoIterator<Item = (Type, &'static str)>,
{
Program::from_shaders_result(iter.into_iter().map(|(t, p)| {
let mut file = vfs.deref().join(p)?.open_file()?;
let shader = Shader::from_reader(t, &mut file)?;

Ok(shader)
}))
}

pub fn load_texture(vfs: &Vfs, path: &str) -> Result<Texture, Error> {
let mut file = vfs.deref().join(path)?.open_file()?;
let mut data = Data::from_reader(&mut file)?;
data.convert_to(data.format().info().format_gl_support)?;

let mut texture = Texture::new(Target::Texture2D)?;
texture.upload(&data, true)?;

Ok(texture)
}
mod events;
mod text;
mod window;
mod world;

pub use events::{Events, WindowEvent};
pub use text::{Text, TextCache, TextManager};
pub use window::Window;
pub use world::WorldHelper;

+ 57
- 10
space-crush/src/app/misc/text.rs Vedi File

@@ -6,6 +6,7 @@ use std::collections::HashMap;
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::mem::size_of;
use std::ops::Deref;
use std::ptr::null;
use std::rc::{Rc, Weak};

@@ -25,10 +26,11 @@ use glyph_brush::{
};
use log::warn;
use ordered_float::OrderedFloat;
use specs::World;

use crate::Error;

use super::{load_program, vfs::Vfs};
use super::super::{misc::WorldHelper, resources::Vfs};

/* TextManager */

@@ -42,15 +44,12 @@ struct TextManagerInner {
}

impl TextManager {
pub fn new(vfs: &Vfs) -> Result<Self, Error> {
let vfs = vfs.clone();
let program = load_program(
&vfs,
vec![
(Type::Vertex, "resources/shader/text.vert"),
(Type::Fragment, "resources/shader/text.frag"),
],
)?;
pub fn new(world: &World) -> Result<Self, Error> {
let vfs = world.resource::<Vfs>()?.deref().clone();
let program = world.load_program(vec![
(Type::Vertex, "resources/shader/text.vert"),
(Type::Fragment, "resources/shader/text.frag"),
])?;
let program = Rc::new(program);

Ok(Self(Rc::new(RefCell::new(TextManagerInner {
@@ -109,8 +108,12 @@ pub struct TextCacheInner {
texts: HashMap<usize, Weak<RefCell<TextInner>>>,
text_ids: Vec<usize>,
next_text_id: usize,
update_counter: usize,
update_requested: bool,
}

pub struct UpdateGuard(TextCache);

impl TextCache {
fn new(manager: &TextManager) -> Result<Self, Error> {
let mut texture = Texture::new(TextureTarget::Texture2D)?;
@@ -125,6 +128,8 @@ impl TextCache {
texts: HashMap::new(),
text_ids: Vec::new(),
next_text_id: 0,
update_counter: 0,
update_requested: false,
}))))
}

@@ -132,6 +137,34 @@ impl TextCache {
TextBuilder::new(self)
}

pub fn begin_update(&self) -> UpdateGuard {
self.0.borrow_mut().update_counter += 1;

UpdateGuard(self.clone())
}

fn end_update(&self) {
let mut inner = self.0.borrow_mut();

if inner.update_counter > 0 {
inner.update_counter -= 1;
}

if inner.update_counter > 0 {
return;
}

let update_requested = inner.update_requested;

drop(inner);

if update_requested {
if let Err(err) = self.update() {
warn!("Unable to update text cache: {}", err);
}
}
}

fn font_by_name(&self, name: &str) -> Result<FontId, Error> {
let mut inner = self.0.borrow_mut();

@@ -186,6 +219,12 @@ impl TextCache {
let mut inner = self.0.borrow_mut();
let inner = &mut *inner;

if inner.update_counter > 0 {
inner.update_requested = true;

return Ok(());
}

/* remove droped texts */
let texts = &mut inner.texts;
let text_ids = &mut inner.text_ids;
@@ -251,6 +290,8 @@ impl TextCache {
}
}

inner.update_requested = false;

Ok(())
}
}
@@ -287,6 +328,12 @@ impl TextCacheInner {
}
}

impl Drop for UpdateGuard {
fn drop(&mut self) {
self.0.end_update()
}
}

fn resize_texture(new_size: (u32, u32), cur_size: Option<(u32, u32)>) -> Result<(u32, u32), Error> {
let mut max_size = 0;
gl::get_integer_v(gl::MAX_TEXTURE_SIZE, &mut max_size);


+ 86
- 0
space-crush/src/app/misc/world.rs Vedi File

@@ -0,0 +1,86 @@
use std::any::type_name;
use std::iter::Iterator;

use glc::{
shader::{Program, Shader, Type},
texture::{Data, Target, Texture},
};
use shred::{Fetch, FetchMut, Resource};
use shrev::{Event, EventChannel, ReaderId};
use specs::World;

use crate::Error;

use super::super::resources::Vfs;

pub trait WorldHelper {
fn resource<R>(&self) -> Result<Fetch<R>, Error>
where
R: Resource;

fn resource_mut<R>(&self) -> Result<FetchMut<R>, Error>
where
R: Resource;

fn register_event_reader<E>(&self) -> Result<ReaderId<E>, Error>
where
E: Event;

fn load_program<I>(&self, iter: I) -> Result<Program, Error>
where
I: IntoIterator<Item = (Type, &'static str)>;

fn load_texture(&self, path: &str) -> Result<Texture, Error>;
}

impl WorldHelper for World {
fn resource<R>(&self) -> Result<Fetch<R>, Error>
where
R: Resource,
{
self.try_fetch::<R>()
.ok_or_else(|| Error::ResourceNotRegistered(type_name::<R>()))
}

fn resource_mut<R>(&self) -> Result<FetchMut<R>, Error>
where
R: Resource,
{
self.try_fetch_mut::<R>()
.ok_or_else(|| Error::ResourceNotRegistered(type_name::<R>()))
}

fn register_event_reader<E>(&self) -> Result<ReaderId<E>, Error>
where
E: Event,
{
Ok(self.resource_mut::<EventChannel<E>>()?.register_reader())
}

fn load_program<I>(&self, iter: I) -> Result<Program, Error>
where
I: IntoIterator<Item = (Type, &'static str)>,
{
let vfs = self.fetch::<Vfs>();

Program::from_shaders_result(iter.into_iter().map(|(t, p)| {
let mut file = vfs.join(p)?.open_file()?;
let shader = Shader::from_reader(t, &mut file)?;

Ok(shader)
}))
}

fn load_texture(&self, path: &str) -> Result<Texture, Error> {
let vfs = self.fetch::<Vfs>();

let mut file = vfs.join(path)?.open_file()?;
let mut data = Data::from_reader(&mut file)?;
data.convert_to(data.format().info().format_gl_support)?;

let mut texture = Texture::new(Target::Texture2D)?;
texture.upload(&data, true)?;

Ok(texture)
}
}

+ 11
- 7
space-crush/src/app/mod.rs Vedi File

@@ -1,14 +1,16 @@
mod misc;
mod render;
mod resources;
mod systems;

use specs::{Dispatcher, DispatcherBuilder, World};

use crate::Error;

use misc::{events::Events, geometry::Geometry, text::TextManager, vfs::Vfs, window::Window};
use misc::{Events, TextManager, Window};
use render::{Debug, Init, Test};
use systems::{State, StateUpdate};
use resources::{Camera, Geometry, State, Vfs};
use systems::StateUpdate;

pub struct App<'a, 'b> {
is_running: bool,
@@ -19,19 +21,21 @@ pub struct App<'a, 'b> {

impl<'a, 'b> App<'a, 'b> {
pub fn new(world: &mut World) -> Result<Self, Error> {
let vfs = Vfs::new()?;
let events = Events::new(world);
let window = Window::new(events.handle())?;
let text_manager = TextManager::new(&vfs)?;

world.insert(vfs);
world.insert(Vfs::new()?);
world.insert(Camera::new()?);
world.insert(Geometry::new()?);
world.insert(State::default());

let text_manager = TextManager::new(world)?;

let mut dispatcher = DispatcherBuilder::new()
.with(StateUpdate::new(world), "state_update", &[])
.with(StateUpdate::new(world)?, "state_update", &[])
.with_thread_local(Init::new(world)?)
.with_thread_local(Test::new(world)?)
.with_thread_local(Debug::new(text_manager)?)
.with_thread_local(Debug::new(&text_manager)?)
.build();
dispatcher.setup(world);



+ 51
- 19
space-crush/src/app/render/debug.rs Vedi File

@@ -1,23 +1,28 @@
use std::string::ToString;

use log::warn;
use specs::{ReadExpect, System};

use crate::Error;
use crate::{server::resources::Global, Error};

use super::{
super::misc::text::{Text, TextManager},
Global,
use super::super::{
misc::{Text, TextCache, TextManager},
resources::State,
};

/* Debug */

pub struct Debug {
cache: TextCache,
text: Text,
fps: usize,
resolution: (u32, u32),
}

impl Debug {
pub fn new(manager: TextManager) -> Result<Self, Error> {
let text = manager
.create_cache()?
pub fn new(text_manager: &TextManager) -> Result<Self, Error> {
let cache = text_manager.create_cache()?;
let text = cache
.new_text()
.scale(12.0)
.font_name("DroidSansMono.ttf")
@@ -30,23 +35,50 @@ impl Debug {
.text("1280 x 720")
.build()?;

Ok(Self { text })
Ok(Self {
cache,
text,
fps: 0,
resolution: (0, 0),
})
}
}

impl<'a> System<'a> for Debug {
type SystemData = ReadExpect<'a, Global>;

fn run(&mut self, global: Self::SystemData) {
if global.frame_counter.updated() {
let ret = self
.text
.update(2, format!("{}", global.frame_counter.fps()));
if let Err(err) = ret {
warn!("Unable to update debug text: {}", err);
}
}
type SystemData = (ReadExpect<'a, Global>, ReadExpect<'a, State>);

fn run(&mut self, (global, state): Self::SystemData) {
let guard = self.cache.begin_update();
update_text(
&mut self.text,
2,
&mut self.fps,
&global.fps,
ToString::to_string,
);
update_text(
&mut self.text,
4,
&mut self.resolution,
&state.resolution,
|(w, h)| format!("{} x {}", w, h),
);
drop(guard);

self.text.render(true);
}
}

fn update_text<T, F>(text: &mut Text, pos: usize, old: &mut T, new: &T, update: F)
where
T: PartialEq + Copy,
F: FnOnce(&T) -> String,
{
if old != new {
*old = *new;
let s = update(old);
if let Err(err) = text.update(pos, s) {
warn!("Unable to update debug text: {}", err);
}
}
}

+ 18
- 52
space-crush/src/app/render/init.rs Vedi File

@@ -3,87 +3,53 @@ use glc::{
shader::{Program, Type},
};
use log::error;
use shrev::{EventChannel, ReaderId};
use specs::{ReadExpect, System, World, WriteExpect};

use crate::Error;

use super::super::misc::{
camera::Camera, events::WindowEvent, frame_counter::FrameCounter, geometry::Geometry,
load_program, vfs::Vfs,
use super::super::{
misc::WorldHelper,
resources::{Camera, Geometry, State},
};

/* Global */

pub struct Global {
pub camera: Camera,
pub frame_counter: FrameCounter,
}

impl Global {
pub fn new() -> Result<Self, Error> {
Ok(Self {
camera: Camera::new()?,
frame_counter: FrameCounter::default(),
})
}
}

/* Init */

pub struct Init {
program: Program,
window_events_id: ReaderId<WindowEvent>,
resolution: (u32, u32),
}

impl Init {
pub fn new(world: &mut World) -> Result<Self, Error> {
world.insert(Global::new()?);

let vfs = world.fetch::<Vfs>();
let program = load_program(
&vfs,
vec![
(Type::Vertex, "resources/shader/noise.vert"),
(Type::Fragment, "resources/shader/noise.frag"),
],
)?;
let window_events_id = world
.fetch_mut::<EventChannel<WindowEvent>>()
.register_reader();
let program = world.load_program(vec![
(Type::Vertex, "resources/shader/noise.vert"),
(Type::Fragment, "resources/shader/noise.frag"),
])?;

Ok(Self {
program,
window_events_id,
resolution: (0, 0),
})
}
}

impl<'a> System<'a> for Init {
type SystemData = (
WriteExpect<'a, Global>,
WriteExpect<'a, Camera>,
ReadExpect<'a, State>,
ReadExpect<'a, Geometry>,
ReadExpect<'a, EventChannel<WindowEvent>>,
);

fn run(&mut self, (mut global, geometry, window_events): Self::SystemData) {
let events = window_events.read(&mut self.window_events_id);
for event in events {
if let WindowEvent::Resize(w, h) = event {
gl::viewport(0, 0, *w as gl::GLsizei, *h as gl::GLsizei);
fn run(&mut self, (mut camera, state, geometry): Self::SystemData) {
if self.resolution != state.resolution {
self.resolution = state.resolution;

let w = *w as f32;
let h = *h as f32;
gl::viewport(0, 0, self.resolution.0 as _, self.resolution.1 as _);

if let Err(err) = global.camera.resize(w, h) {
error!("Error while updating camera: {}", err);
panic!("Error while updating camera: {}", err);
}
if let Err(err) = camera.resize(self.resolution.0 as _, self.resolution.1 as _) {
error!("Error while updating camera: {}", err);
panic!("Error while updating camera: {}", err);
}
}

global.frame_counter.next();

self.program.bind();
geometry.render_quad();
self.program.unbind();


+ 1
- 1
space-crush/src/app/render/mod.rs Vedi File

@@ -3,5 +3,5 @@ mod init;
mod test;

pub use debug::Debug;
pub use init::{Global, Init};
pub use init::Init;
pub use test::Test;

+ 16
- 20
space-crush/src/app/render/test.rs Vedi File

@@ -7,42 +7,38 @@ use glc::{
};
use specs::{ReadExpect, System, World};

use crate::Error;
use crate::{server::resources::Global, Error};

use super::{
super::misc::{geometry::Geometry, load_program, load_texture, vfs::Vfs},
init::Global,
use super::super::{
misc::WorldHelper,
resources::{Camera, Geometry},
};

pub struct Test {
model: Matrix4f,
program: Program,
texture: Texture,
model: Matrix4f,
}

impl Test {
pub fn new(world: &World) -> Result<Self, Error> {
let vfs = world.fetch::<Vfs>();
let program = load_program(
&vfs,
vec![
(Type::Vertex, "resources/shader/quad.vert"),
(Type::Fragment, "resources/shader/quad.frag"),
],
)?;

let mut texture = load_texture(&vfs, "resources/textures/test.png")?;
texture.set_filter(FilterMin::LinearMipmapLinear, FilterMag::Linear)?;
let model = Matrix4f::scale(Vector3f::new(500.0, 500.0, 500.0));

let global = world.fetch::<Global>();
let program = world.load_program(vec![
(Type::Vertex, "resources/shader/quad.vert"),
(Type::Fragment, "resources/shader/quad.frag"),
])?;
program.bind();
global.camera.bind(0)?;
world.resource::<Camera>()?.bind(0)?;
program.unbind();

let mut texture = world.load_texture("resources/textures/test.png")?;
texture.set_filter(FilterMin::LinearMipmapLinear, FilterMag::Linear)?;

Ok(Self {
model,
program,
texture,
model: Matrix4f::scale(Vector3f::new(500.0, 500.0, 500.0)),
})
}
}
@@ -54,7 +50,7 @@ impl<'a> System<'a> for Test {
self.model = self.model
* Matrix4f::rotate(
Vector3f::new(0.0, 0.0, 1.0),
Angle::Deg(10.0 * global.frame_counter.delta()),
Angle::Deg(10.0 * global.delta),
);

self.texture.bind();


space-crush/src/app/misc/camera.rs → space-crush/src/app/resources/camera.rs Vedi File


space-crush/src/app/misc/geometry.rs → space-crush/src/app/resources/geometry.rs Vedi File


+ 9
- 0
space-crush/src/app/resources/mod.rs Vedi File

@@ -0,0 +1,9 @@
mod camera;
mod geometry;
mod state;
mod vfs;

pub use self::vfs::Vfs;
pub use camera::Camera;
pub use geometry::Geometry;
pub use state::State;

+ 6
- 0
space-crush/src/app/resources/state.rs Vedi File

@@ -0,0 +1,6 @@
#[derive(Default)]
pub struct State {
pub resolution: (u32, u32),

pub close_requested: bool,
}

space-crush/src/app/misc/vfs.rs → space-crush/src/app/resources/vfs.rs Vedi File


+ 2
- 2
space-crush/src/app/systems/mod.rs Vedi File

@@ -1,3 +1,3 @@
mod state;
mod state_update;

pub use state::{State, StateUpdate};
pub use state_update::StateUpdate;

space-crush/src/app/systems/state.rs → space-crush/src/app/systems/state_update.rs Vedi File

@@ -1,31 +1,22 @@
use shrev::{EventChannel, ReaderId};
use specs::{ReadExpect, System, World, Write};

use super::super::misc::events::WindowEvent;
use crate::Error;

/* State */

#[derive(Default)]
pub struct State {
pub close_requested: bool,

pub window_width: u32,
pub window_height: u32,
}

/* StateUpdate*/
use super::super::{
misc::{WindowEvent, WorldHelper},
resources::State,
};

pub struct StateUpdate {
window_events_id: ReaderId<WindowEvent>,
}

impl StateUpdate {
pub fn new(world: &mut World) -> Self {
let window_events_id = world
.fetch_mut::<EventChannel<WindowEvent>>()
.register_reader();
pub fn new(world: &mut World) -> Result<Self, Error> {
let window_events_id = world.register_event_reader::<WindowEvent>()?;

Self { window_events_id }
Ok(Self { window_events_id })
}
}

@@ -37,8 +28,7 @@ impl<'a> System<'a> for StateUpdate {
for event in events {
match event {
WindowEvent::Resize(w, h) => {
state.window_width = *w;
state.window_height = *h;
state.resolution = (*w, *h);
}
WindowEvent::Close => {
state.close_requested = true;

+ 3
- 0
space-crush/src/error.rs Vedi File

@@ -30,6 +30,9 @@ pub enum Error {
#[error("Invalid Font: {0}")]
InvalidFont(InvalidFont),

#[error("Resource is not registered: {0}!")]
ResourceNotRegistered(&'static str),

#[error("Unable to create OpenGL context!")]
CreateContext,



+ 19
- 6
space-crush/src/server/mod.rs Vedi File

@@ -1,15 +1,28 @@
use specs::World;
pub mod resources;
pub mod systems;

pub struct Server {}
use specs::{Dispatcher, DispatcherBuilder, World};

impl Server {
use resources::Global;
use systems::Process;

pub struct Server<'a, 'b> {
dispatcher: Dispatcher<'a, 'b>,
}

impl<'a, 'b> Server<'a, 'b> {
pub fn new(world: &mut World) -> Self {
let _world = world;
world.insert(Global::default());

let mut dispatcher = DispatcherBuilder::new()
.with(Process::default(), "process", &[])
.build();
dispatcher.setup(world);

Self {}
Self { dispatcher }
}

pub fn process(&mut self, world: &World) {
let _world = world;
self.dispatcher.dispatch(world);
}
}

+ 5
- 0
space-crush/src/server/resources/global.rs Vedi File

@@ -0,0 +1,5 @@
#[derive(Default)]
pub struct Global {
pub fps: usize,
pub delta: f32,
}

+ 3
- 0
space-crush/src/server/resources/mod.rs Vedi File

@@ -0,0 +1,3 @@
mod global;

pub use global::Global;

+ 3
- 0
space-crush/src/server/systems/mod.rs Vedi File

@@ -0,0 +1,3 @@
mod process;

pub use process::Process;

+ 48
- 0
space-crush/src/server/systems/process.rs Vedi File

@@ -0,0 +1,48 @@
#![allow(dead_code)]

use std::mem::take;
use std::time::Instant;

use specs::{System, Write};

use super::super::resources::Global;

pub struct Process {
last_frame: Instant,
time: f32,
count: usize,
}

impl Default for Process {
fn default() -> Self {
Self {
last_frame: Instant::now(),
time: 0.0,
count: 0,
}
}
}

impl<'a> System<'a> for Process {
type SystemData = Write<'a, Global>;

fn run(&mut self, mut global: Self::SystemData) {
let now = Instant::now();

global.delta = (now - self.last_frame).as_secs_f32();
self.last_frame = now;
self.time += global.delta;
self.count += 1;

if self.time >= 2.0 {
self.time = 0.0;
self.count = 0;

global.fps = 0;
} else if self.time >= 1.0 {
self.time -= 1.0;

global.fps = take(&mut self.count);
}
}
}

Caricamento…
Annulla
Salva