Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

86 application window #88

Merged
merged 9 commits into from
Apr 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .idea/recs.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/runConfigurations/Run_rendered_app.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions .idea/runConfigurations/Run_rendered_ecs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

95 changes: 59 additions & 36 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions crates/ecs/examples/simple.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use color_eyre::Report;
use crossbeam::channel::unbounded;
use ecs::logging::Loggable;
use ecs::systems::{Read, Write};
use ecs::{Application, Sequential, Unordered};
use ecs::{Application, BasicApplication, Sequential, Unordered};
use std::thread;
use std::time::Duration;
use tracing::{error, info, instrument, trace, warn};

// a simple example of how to use the crate `ecs`
#[instrument]
fn main() -> Result<(), Report> {
let mut app = Application::default()
let mut app = BasicApplication::default()
.with_tracing()?
.add_system(basic_system)
.add_system(read_a_system)
Expand Down
76 changes: 52 additions & 24 deletions crates/ecs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use crate::systems::SystemError::CannotRunSequentially;
use crate::systems::{
ComponentIndex, IntoSystem, System, SystemError, SystemParameters, SystemResult,
};
use crate::ApplicationError::ScheduleGeneration;
use crate::BasicApplicationError::ScheduleGeneration;
use core::panic;
use crossbeam::channel::{bounded, Receiver, Sender, TryRecvError};
use std::any;
Expand All @@ -50,7 +50,7 @@ use thiserror::Error;

/// An error in the application.
#[derive(Error, Debug)]
pub enum ApplicationError {
pub enum BasicApplicationError {
/// Failed to generate schedule for given systems.
#[error("failed to generate schedule for given systems")]
ScheduleGeneration(#[source] ScheduleError),
Expand All @@ -63,27 +63,62 @@ pub enum ApplicationError {
}

/// Whether an operation on the application succeeded.
pub type AppResult<T, E = ApplicationError> = Result<T, E>;
pub type BasicAppResult<T, E = BasicApplicationError> = Result<T, E>;

/// The entry-point of the entire program, containing all of the entities, components and systems.
/// A basic type of [`Application`], with not much extra functionality.
#[derive(Default, Debug)]
pub struct Application {
pub struct BasicApplication {
world: World,
systems: Vec<Box<dyn System>>,
}

impl Application {
/// The entry-point of the entire program, containing all of the entities, components and systems.
pub trait Application {
/// The type of errors returned by application methods.
type Error: std::error::Error + Send + Sync + 'static;

/// Spawns a new entity in the world.
pub fn create_entity(&mut self) -> AppResult<Entity> {
fn create_entity(&mut self) -> Result<Entity, Self::Error>;

/// Registers a new system to run in the world.
fn add_system<System, Parameters>(self, system: System) -> Self
where
System: IntoSystem<Parameters>,
Parameters: SystemParameters;

/// Registers multiple new systems to run in the world.
fn add_systems<System, Parameters>(self, systems: impl IntoIterator<Item = System>) -> Self
where
System: IntoSystem<Parameters>,
Parameters: SystemParameters;

/// Adds a new component to a given entity.
fn add_component<ComponentType: Debug + Send + Sync + 'static>(
&mut self,
entity: Entity,
component: ComponentType,
) -> Result<(), Self::Error>;

/// Starts the application. This function does not return until the shutdown command has
/// been received.
fn run<'systems, E: Executor<'systems>, S: Schedule<'systems>>(
&'systems mut self,
shutdown_receiver: Receiver<()>,
) -> Result<(), Self::Error>;
}

impl Application for BasicApplication {
type Error = BasicApplicationError;

fn create_entity(&mut self) -> Result<Entity, Self::Error> {
let entity = self.world.create_new_entity();
self.world
.store_entity_in_archetype(entity, 0)
.map_err(ApplicationError::World)?; // todo(#72): Change so that all entities are not stored in the same big archetype, that is change index 0 to be something else.
.map_err(BasicApplicationError::World)?; // todo(#72): Change so that all entities are not stored in the same big archetype, that is change index 0 to be something else.
Ok(entity)
}

/// Registers a new system to run in the world.
pub fn add_system<System, Parameters>(mut self, system: System) -> Self
fn add_system<System, Parameters>(mut self, system: System) -> Self
where
System: IntoSystem<Parameters>,
Parameters: SystemParameters,
Expand All @@ -92,11 +127,7 @@ impl Application {
self
}

/// Registers multiple new systems to run in the world.
pub fn add_systems<System, Parameters>(
mut self,
systems: impl IntoIterator<Item = System>,
) -> Self
fn add_systems<System, Parameters>(mut self, systems: impl IntoIterator<Item = System>) -> Self
where
System: IntoSystem<Parameters>,
Parameters: SystemParameters,
Expand All @@ -107,28 +138,25 @@ impl Application {
self
}

/// Adds a new component to a given entity.
pub fn add_component<ComponentType: Debug + Send + Sync + 'static>(
fn add_component<ComponentType: Debug + Send + Sync + 'static>(
&mut self,
entity: Entity,
component: ComponentType,
) -> AppResult<()> {
) -> Result<(), Self::Error> {
self.world
.create_component_vec_and_add(entity, component)
.map_err(ApplicationError::World)
.map_err(BasicApplicationError::World)
}

/// Starts the application. This function does not return until the shutdown command has
/// been received.
pub fn run<'systems, E: Executor<'systems>, S: Schedule<'systems>>(
fn run<'systems, E: Executor<'systems>, S: Schedule<'systems>>(
&'systems mut self,
shutdown_receiver: Receiver<()>,
) -> AppResult<()> {
) -> Result<(), Self::Error> {
let schedule = S::generate(&self.systems).map_err(ScheduleGeneration)?;
let mut executor = E::default();
executor
.execute(schedule, &self.world, shutdown_receiver)
.map_err(ApplicationError::Execution)
.map_err(BasicApplicationError::Execution)
}
}

Expand Down
9 changes: 7 additions & 2 deletions crates/ecs/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,14 @@ pub enum LoggingError {
/// Whether a logging operation succeeded.
pub type LoggingResult<T, E = LoggingError> = Result<T, E>;

impl Application {
/// Represents an [`Application`] which can log messages.
pub trait Loggable: Sized {
/// Attaches and initializes tracing infrastructure.
pub fn with_tracing(self) -> LoggingResult<Self> {
fn with_tracing(self) -> LoggingResult<Self>;
}

impl<App: Application> Loggable for App {
fn with_tracing(self) -> LoggingResult<Self> {
install_tracing()?;
color_eyre::install().map_err(ColorInitialization)?;
Ok(self)
Expand Down
9 changes: 7 additions & 2 deletions crates/ecs/src/profiling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ pub enum ProfilingError {
/// Whether a profiling operation succeeded.
pub type ProfilingResult<T, E = ProfilingError> = Result<T, E>;

impl Application {
/// Represents an [`Application`] which can be profiled.
pub trait Profileable: Sized {
/// Enables profiling connection to Tracy.
fn with_profiling(self) -> ProfilingResult<Self>;
martinjonsson01 marked this conversation as resolved.
Show resolved Hide resolved
}

impl<App: Application> Profileable for App {
#[allow(clippy::print_stdout)] // Because we can't print to console using tracing when it's disabled
pub fn with_profiling(self) -> ProfilingResult<Self> {
fn with_profiling(self) -> ProfilingResult<Self> {
tracing_subscriber::registry()
.with(tracing_tracy::TracyLayer::new().with_filter(LevelFilter::TRACE))
.try_init()
Expand Down
8 changes: 4 additions & 4 deletions crates/ecs/tests/application_tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crossbeam::channel::unbounded;
use ecs::systems::{Read, Write};
use ecs::{Application, Sequential, Unordered};
use ecs::{Application, BasicApplication, Sequential, Unordered};
use ntest::timeout;
use std::sync::atomic::AtomicU8;
use std::sync::atomic::Ordering::SeqCst;
Expand Down Expand Up @@ -34,7 +34,7 @@ fn system_is_passed_component_values_for_each_entity() {
}
};

let mut app = Application::default().add_system(system);
let mut app = BasicApplication::default().add_system(system);

let entity = app.create_entity().unwrap();
app.add_component(entity, A).unwrap();
Expand Down Expand Up @@ -70,7 +70,7 @@ fn system_mutates_component_values() {
}
};

let mut app = Application::default()
let mut app = BasicApplication::default()
.add_system(write_system)
.add_system(read_system);

Expand Down Expand Up @@ -117,7 +117,7 @@ fn multiparameter_systems_run_with_component_values_queried() {
one_parameter_count.fetch_add(1, SeqCst);
};

let mut app = Application::default()
let mut app = BasicApplication::default()
.add_system(three_parameter_system)
.add_system(two_parameter_system)
.add_system(one_parameter_system);
Expand Down
Loading