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 📚
Entitiesfor info on creating and deletingEntitysComponentsfor info on creating, updating and deleting componentsEntryfor info on tracking changes to individual componentsQueryfor info on querying bundles of componentsFacadefor info on interacting with theWorldfrom a future operations together into an easy-to-integrate package
Implementations§
Source§impl World
impl World
Sourcepub fn facade_count(&self) -> usize
pub fn facade_count(&self) -> usize
Returns the total number of Facades.
pub fn add_subgraph(&mut self, graph: Graph) -> &mut Self
pub fn remove_node(&mut self, name: impl AsRef<str>)
pub fn remove_nodes<T: AsRef<str>>( &mut self, names: impl IntoIterator<Item = T>, )
pub fn interleave_subgraph(&mut self, graph: Graph) -> &mut Self
pub fn contains_resource<T: Any + Send + Sync>(&self) -> bool
pub fn add_resource<T: Any + Send + Sync>(&mut self, t: T) -> &mut Self
pub fn get_resource<T: Any + Send + Sync>(&self) -> Option<&T>
pub fn get_resource_mut<T: Any + Send + Sync>(&mut self) -> Option<&mut T>
Sourcepub fn visit<T: Edges, S>(
&mut self,
f: impl FnOnce(T) -> S,
) -> Result<S, GraphError>
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>());pub fn with_parallelism(&mut self, parallelism: Parallelism) -> &mut Self
Sourcepub fn tick(&mut self) -> Result<(), GraphError>
pub fn tick(&mut self) -> Result<(), GraphError>
Conduct a world tick.
Sourcepub fn has_facade_requests(&self) -> bool
pub fn has_facade_requests(&self) -> bool
Return whether or not there are any requests for world resources from one
or more Facades.
Sourcepub fn get_facade_schedule(&mut self) -> Result<FacadeSchedule<'_>, GraphError>
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.
Sourcepub fn run(&mut self) -> Result<&mut Self, GraphError>
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();Sourcepub fn get_components(&self) -> &Components
pub fn get_components(&self) -> &Components
Return a reference to Components.
Sourcepub fn get_components_mut(&mut self) -> &mut Components
pub fn get_components_mut(&mut self) -> &mut Components
Return a mutable reference to Components.
Sourcepub fn get_entities(&self) -> &Entities
pub fn get_entities(&self) -> &Entities
Return a reference to Entities.
Sourcepub fn get_entities_mut(&mut self) -> &mut Entities
pub fn get_entities_mut(&mut self) -> &mut Entities
Return a mutable reference to Entities.
Sourcepub fn get_schedule_names(&mut self) -> Vec<Vec<&str>>
pub fn get_schedule_names(&mut self) -> Vec<Vec<&str>>
Returns the scheduled systems’ names, collated by batch.
Trait Implementations§
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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