Skip to content

Commit

Permalink
feat: Pausable legion systems base on GameState
Browse files Browse the repository at this point in the history
Fixes #50
  • Loading branch information
suspistew committed Mar 22, 2021
1 parent 9f00167 commit feba786
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "scion"
version = "0.1.0"
version = "0.2.0-alpha"
authors = ["grzi <jeremy.thulliez@gmail.com>"]
edition = "2018"
description = "Game making library on top of wgpu, winit, legion"
Expand Down
13 changes: 13 additions & 0 deletions examples/tetris/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use scion::Scion;
use scion::legion::system;

#[system]
fn test(){
log::info!("Hello all");
}

fn main() {
Scion::app()
.with_pausable_system(test_system(), |state| state.test())
.run();
}
21 changes: 21 additions & 0 deletions src/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ use crate::{
rendering::{renderer_state::RendererState, RendererType},
utils::{time::Time, window::WindowDimensions},
};
use crate::state::GameState;
use crate::utils::legion_ext::PausableSystem;
use legion::systems::ResourceTypeId;

/// `Scion` is the entry point of any application made with Scion's lib.
pub struct Scion {
Expand Down Expand Up @@ -62,6 +65,7 @@ impl Scion {

self.resources.insert(Time::default());
self.resources.insert(Inputs::default());
self.resources.insert(GameState::default());
self.apply_layers_action(LayerAction::Start);
}

Expand Down Expand Up @@ -243,6 +247,23 @@ impl ScionBuilder {
self
}

pub fn with_pausable_system<S: ParallelRunnable + 'static>(mut self, system: S, condition: fn(GameState) -> bool) -> Self {
let (resource_reads, _) = system.reads();
let resource_reads = resource_reads
.iter()
.copied()
.chain(std::iter::once(ResourceTypeId::of::<GameState>()))
.collect::<Vec<_>>();
let boxed_condition = Box::new(condition);
let pausable_system = PausableSystem{
system,
decider: boxed_condition,
resource_reads
};
self.schedule_builder.add_system(pausable_system);
self
}

/// Specify which render type you want to use. Note that by default if not set, `Scion` will use [`crate::rendering::RendererType::Scion2D`].
pub fn with_renderer(mut self, renderer_type: RendererType) -> Self {
self.renderer = renderer_type;
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//!
//! #[system]
//! fn hello() {
//! println!("Heullo world from a system");
//! println!("Hello world from a system");
//! }
//!
//! fn main() {
Expand All @@ -35,3 +35,4 @@ pub mod game_layer;
pub mod inputs;
pub mod rendering;
pub mod utils;
pub mod state;
11 changes: 11 additions & 0 deletions src/state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// `GameState` is a convenience Resource created to keep track of
/// diverse thing internally. It's also the resource used to create
/// pausable systems.
#[derive(Debug, Copy, Clone, Default)]
pub struct GameState {}

impl GameState{
pub fn test(&self)-> bool{
true
}
}
52 changes: 52 additions & 0 deletions src/utils/legion_ext.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use legion::systems::{Runnable, ResourceTypeId, SystemId, UnsafeResources, ResourceSet, CommandBuffer};
use legion::storage::ComponentTypeId;
use legion::{World, Read};
use legion::world::{ArchetypeAccess, WorldId};
use crate::state::GameState;

pub(crate) struct PausableSystem<S> {
pub(crate) system: S,
pub(crate) decider: Box<fn(GameState) -> bool>,
pub(crate) resource_reads: Vec<ResourceTypeId>,
}

impl<S> Runnable for PausableSystem<S>
where
S: Runnable
{
fn name(&self) -> Option<&SystemId> {
self.system.name()
}

fn reads(&self) -> (&[ResourceTypeId], &[ComponentTypeId]) {
let (_, components) = self.system.reads();
(&self.resource_reads[..], components)
}

fn writes(&self) -> (&[ResourceTypeId], &[ComponentTypeId]) {
self.system.writes()
}

fn prepare(&mut self, world: &World) {
self.system.prepare(world)
}

fn accesses_archetypes(&self) -> &ArchetypeAccess {
self.system.accesses_archetypes()
}

unsafe fn run_unsafe(&mut self, world: &World, resources: &UnsafeResources) {
let resources_static = &*(resources as *const UnsafeResources);
let resource_to_check = Read::<GameState>::fetch_unchecked(resources_static);

if (self.decider)(*resource_to_check) {
return;
} else {}

self.system.run_unsafe(world, resources);
}

fn command_buffer_mut(&mut self, world: WorldId) -> Option<&mut CommandBuffer> {
self.system.command_buffer_mut(world)
}
}
1 change: 1 addition & 0 deletions src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ pub mod file;
pub mod logger;
pub mod time;
pub mod window;
pub(crate) mod legion_ext;

0 comments on commit feba786

Please # to comment.