World

Struct World 

Source
pub struct World { /* private fields */ }
Expand description

A collection of resources and systems.

The World holds all resources, entities, components and systems.

Most applications will create and configure a World in their main function and call World::run or World::tick or World::tock to run all systems.

How to run async futures is up to you, but those futures can interact with with the World through a Facade.

use apecs::*;

struct Channel<T> {
    tx: async_broadcast::Sender<T>,
    rx: async_broadcast::Receiver<T>,
}

impl<T> Default for Channel<T> {
    fn default() -> Self {
        let (tx, rx) = async_broadcast::broadcast(3);
        Channel { tx, rx }
    }
}

/// Anything that derives `Edges` can be used as system parameters
/// and visited by a `Facade`.
///
/// Its fields will be stored in the `World` as individual resources.
#[derive(Edges)]
struct MyAppData {
    channel: View<Channel<String>>,
    count: ViewMut<usize>,
}

/// `compute_hello` is a system that visits `MyAppData`, accumlates a count and
/// sends a message into a channel the third time it is run.
fn compute_hello(mut data: MyAppData) -> Result<(), GraphError> {
    if *data.count >= 3 {
        data.channel
            .tx
            .try_broadcast("hello world".to_string())
            .unwrap();
        end()
    } else {
        *data.count += 1;
        ok()
    }
}

let mut world = World::default();
world.add_subgraph(graph!(compute_hello));
// Create a facade to move into an async future that awaits a message from the
// `compute_hello` system.
let mut facade = world.facade();
let task = smol::spawn(async move {
    // Visit the world's `MyAppData` to get the receiver.
    let mut rx = facade
        .visit(|data: MyAppData| data.channel.rx.clone())
        .await
        .unwrap();
    if let Ok(msg) = rx.recv().await {
        println!("got message: {}", msg);
    }
});

while !task.is_finished() {
    // `tick` progresses the world by one frame
    world.tick().unwrap();
    // send out any requests the facade may have made from a future running in our
    // executor
    let mut facade_schedule = world.get_facade_schedule().unwrap();
    facade_schedule.run().unwrap();
}

World is the outermost object of apecs, as it contains all systems and resources. It contains Entities and Components as default resources. You can create entities, attach components and query them from outside the world if desired:

use apecs::*;
let mut world = World::default();
// Create entities to hold heterogenous components
let a = world.get_entities_mut().create();
let b = world.get_entities_mut().create();
// Nearly any type can be used as a component with zero boilerplate.
// Here we add three components as a "bundle" to entity "a".
world
    .get_components_mut()
    .insert_bundle(*a, (123i32, true, "abc"));
assert!(world
    .get_components()
    .get_component::<i32>(a.id())
    .is_some());
// Add two components as a "bundle" to entity "b".
world.get_components_mut().insert_bundle(*b, (42i32, false));
// Query the world for all matching bundles
let mut query = world.get_components_mut().query::<(&mut i32, &bool)>();
for (number, flag) in query.iter_mut() {
    println!("id: {}", number.id());
    if **flag {
        **number *= 2;
    }
}
// Perform random access within the same query by using the entity.
let b_i32 = **query.find_one(b.id()).unwrap().0;
assert_eq!(b_i32, 42);
// Track changes to individual components
let a_entry: &Entry<i32> = query.find_one(a.id()).unwrap().0;
assert_eq!(apecs::current_iteration(), a_entry.last_changed());
assert_eq!(**a_entry, 246);

§Where to look next 📚

  • Entities for info on creating and deleting Entitys
  • Components for info on creating, updating and deleting components
  • Entry for info on tracking changes to individual components
  • Query for info on querying bundles of components
  • Facade for info on interacting with the World from a future operations together into an easy-to-integrate package

Implementations§

Source§

impl World

Source

pub fn facade(&self) -> Facade

Create a new facade

Source

pub fn facade_count(&self) -> usize

Returns the total number of Facades.

Source

pub fn add_subgraph(&mut self, graph: Graph) -> &mut Self

Source

pub fn remove_node(&mut self, name: impl AsRef<str>)

Source

pub fn remove_nodes<T: AsRef<str>>( &mut self, names: impl IntoIterator<Item = T>, )

Source

pub fn interleave_subgraph(&mut self, graph: Graph) -> &mut Self

Source

pub fn contains_resource<T: Any + Send + Sync>(&self) -> bool

Source

pub fn add_resource<T: Any + Send + Sync>(&mut self, t: T) -> &mut Self

Source

pub fn get_resource<T: Any + Send + Sync>(&self) -> Option<&T>

Source

pub fn get_resource_mut<T: Any + Send + Sync>(&mut self) -> Option<&mut T>

Source

pub fn visit<T: Edges, S>( &mut self, f: impl FnOnce(T) -> S, ) -> Result<S, GraphError>

Visit world resources with a closure.

This is like running a one-off system, but S does not get packed into the world as a result resource, instead it is given back to the callsite.

§!Send and !Sync

Using World::visit you can run !Send and !Sync “systems”. The visiting closure can reference any !Send or !Sync resources that are in scope. Unfortunately these !Send or !Sync resources must be stored outside of the World.

§Note

By design, visiting the world with a type that uses Move in one of its fields will result in the wrapped type of that field being moved out of the world. The resource will no longer be available within the world.

use apecs::*;
use snafu::prelude::*;

#[derive(Debug, Snafu)]
enum TestError {}

#[derive(Edges)]
struct Input {
    num_usize: View<usize>,
    num_f32: ViewMut<f32>,
    num_f64: Move<f64>,
}

// pack the graph with resources
let mut graph = Graph::default()
    .with_resource(0usize)
    .with_resource(0.0f32)
    .with_resource(0.0f64);

// visit the graph, reading, modifying and _moving_!
let num_usize = graph.visit(|mut input: Input| {
    *input.num_f32 = 666.0;
    *input.num_f64 += 10.0;
    *input.num_usize
}).unwrap();

// observe we read usize
assert_eq!(0, num_usize);
assert_eq!(0, *graph.get_resource::<usize>().unwrap().unwrap());

// observe we modified f32
assert_eq!(666.0, *graph.get_resource::<f32>().unwrap().unwrap());

// observe we moved f64 out of the graph and it is no longer present
assert!(!graph.contains_resource::<f64>());
Source

pub fn with_parallelism(&mut self, parallelism: Parallelism) -> &mut Self

Source

pub fn tick(&mut self) -> Result<(), GraphError>

Conduct a world tick.

Source

pub fn tock(&mut self)

Conduct a world tick, but panic if the result is not Ok.

§Panics

Panics if the result is not Ok

Source

pub fn has_facade_requests(&self) -> bool

Return whether or not there are any requests for world resources from one or more Facades.

Source

pub fn get_facade_schedule(&mut self) -> Result<FacadeSchedule<'_>, GraphError>

Build the schedule of resource requests from the World’s Facades.

This schedule can be run with FacadeSchedule::run or ticked with FacadeSchedule::tick, which delivers those resources to each Facade in parallel batches, if possible.

Source

pub fn run(&mut self) -> Result<&mut Self, GraphError>

Run all systems until one of the following conditions have been met:

  • All systems have finished successfully
  • One system has erred
  • One or more requests have been received from a Facade
§Note

This does not send out resources to the Facade. For async support it is recommended you use World::run to progress the world’s systems, followed by World::get_facade_schedule and FacadeSchedule::tick.

use apecs::{World, FacadeSchedule};

let mut world = World::default();
//...populate the world

// run systems until the facade makes a request for resources
world.run().unwrap();

// answer requests for world resources from external futures
// until all requests are met
let mut facade_schedule = world.get_facade_schedule().unwrap();
facade_schedule.run().unwrap();
Source

pub fn get_components(&self) -> &Components

Return a reference to Components.

Source

pub fn get_components_mut(&mut self) -> &mut Components

Return a mutable reference to Components.

Source

pub fn get_entities(&self) -> &Entities

Return a reference to Entities.

Source

pub fn get_entities_mut(&mut self) -> &mut Entities

Return a mutable reference to Entities.

Source

pub fn get_schedule_names(&mut self) -> Vec<Vec<&str>>

Returns the scheduled systems’ names, collated by batch.

Trait Implementations§

Source§

impl Default for World

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl Freeze for World

§

impl !RefUnwindSafe for World

§

impl !Send for World

§

impl !Sync for World

§

impl Unpin for World

§

impl !UnwindSafe for World

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> SatisfyTraits<dyn None> for T