legion/
lib.rs

1#![deny(missing_docs)]
2
3//! Legion aims to be a feature rich high performance ECS library for Rust game projects with minimal boilerplate.
4//!
5//! # Getting Started
6//!
7//! ## Worlds
8//!
9//! [Worlds](World) are collections of [entities](Entity), where each entity can have an arbitrary collection of
10//! [components](storage::Component) attached.
11//!
12//! ```
13//! use legion::*;
14//! let world = World::default();
15//! ```
16//!
17//! Entities can be inserted via either [`World::push`] (for a single entity) or [`World::extend`] (for a collection
18//! of entities with the same component types). The world will create a unique ID for each entity upon insertion
19//! that you can use to refer to that entity later.
20//!
21//! ```
22//! # use legion::*;
23//! # let mut world = World::default();
24//! // a component is any type that is 'static, sized, send and sync
25//! #[derive(Clone, Copy, Debug, PartialEq)]
26//! struct Position {
27//!     x: f32,
28//!     y: f32,
29//! }
30//!
31//! #[derive(Clone, Copy, Debug, PartialEq)]
32//! struct Velocity {
33//!     dx: f32,
34//!     dy: f32,
35//! }
36//!
37//! // push a component tuple into the world to create an entity
38//! let entity: Entity = world.push((Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }));
39//!
40//! // or extend via an IntoIterator of tuples to add many at once (this is faster)
41//! let entities: &[Entity] = world.extend(vec![
42//!     (Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }),
43//!     (Position { x: 1.0, y: 1.0 }, Velocity { dx: 0.0, dy: 0.0 }),
44//!     (Position { x: 2.0, y: 2.0 }, Velocity { dx: 0.0, dy: 0.0 }),
45//! ]);
46//! ```
47//!
48//! You can access entities via [entries](world::Entry). Entries allow you to query an entity to find out what
49//! types of components are attached to it, to get component references, or to add and remove components.
50//!
51//! ```
52//! # use legion::*;
53//! # let mut world = World::default();
54//! # let entity = world.push((false,));
55//! // entries return `None` if the entity does not exist
56//! if let Some(mut entry) = world.entry(entity) {
57//!     // access information about the entity's archetype
58//!     println!(
59//!         "{:?} has {:?}",
60//!         entity,
61//!         entry.archetype().layout().component_types()
62//!     );
63//!
64//!     // add an extra component
65//!     entry.add_component(12f32);
66//!
67//!     // access the entity's components, returns `None` if the entity does not have the component
68//!     assert_eq!(entry.get_component::<f32>().unwrap(), &12f32);
69//! }
70//! ```
71//!
72//! See the [`world`] module for more information.
73//!
74//! ## Queries
75//!
76//! Entries are not the most convenient or performant way to search or bulk-access a world. [Queries](query)
77//! allow for high performance and expressive iteration through the entities in a world.
78//!
79//! ```
80//! # use legion::*;
81//! # let world = World::default();
82//! # #[derive(Debug)]
83//! # struct Position;
84//! // you define a query be declaring what components you want to find, and how you will access them
85//! let mut query = Read::<Position>::query();
86//!
87//! // you can then iterate through the components found in the world
88//! for position in query.iter(&world) {
89//!     println!("{:?}", position);
90//! }
91//! ```
92//!
93//! You can search for entities which have all of a set of components.
94//!
95//! ```
96//! # use legion::*;
97//! # let mut world = World::default();
98//! # struct Position { x: f32, y: f32 }
99//! # struct Velocity { x: f32, y: f32 }
100//! // construct a query from a "view tuple"
101//! let mut query = <(&Velocity, &mut Position)>::query();
102//!
103//! // this time we have &Velocity and &mut Position
104//! for (velocity, position) in query.iter_mut(&mut world) {
105//!     position.x += velocity.x;
106//!     position.y += velocity.y;
107//! }
108//! ```
109//!
110//! You can augment a basic query with additional filters. For example, you can choose to exclude
111//! entities which also have a certain component, or only include entities for which a certain
112//! component has changed since the last time the query ran (this filtering is conservative and coarse-grained)
113//!
114//! ```
115//! # use legion::*;
116//! # let mut world = World::default();
117//! # struct Position { x: f32, y: f32 }
118//! # struct Velocity { dx: f32, dy: f32 }
119//! # struct Ignore;
120//! // you can use boolean expressions when adding filters
121//! let mut query = <(&Velocity, &mut Position)>::query()
122//!     .filter(!component::<Ignore>() & maybe_changed::<Position>());
123//!
124//! for (velocity, position) in query.iter_mut(&mut world) {
125//!     position.x += velocity.dx;
126//!     position.y += velocity.dy;
127//! }
128//! ```
129//!
130//! There is much more than can be done with queries. See the [module document](query) for more information.
131//!
132//! ## Systems
133//!
134//! You may have noticed that when we wanted to write to a component, we needed to use `iter_mut` to iterate through our query.
135//! But perhaps your application wants to be able to process different components on different entities, perhaps even at the same
136//! time in parallel? While it is possible to do this manually (see [`World::split`]), this is very difficult to do when the
137//! different pieces of the application don't know what components each other need, or might or might not even have conflicting
138//! access requirements.
139//!
140//! Systems and the [`Schedule`] automates this process, and can even schedule work at a more granular level than
141//! you can otherwise do manually.
142//!
143//! A system is a unit of work. Each system is defined as a function which is provided access to queries and shared
144//! [`Resources`]. These systems can then be appended to a schedule, which is a linear sequence of systems,
145//! ordered by when side effects (such as writes to components) should be observed.
146//!
147//! The schedule will automatically parallelize the execution of all systems whilst maintaining the apparent order of execution from
148//! the perspective of each system.
149//!
150//! ```
151//! # #[cfg(feature = "codegen")] {
152//! # use legion::*;
153//! # struct Position { x: f32, y: f32 }
154//! # struct Velocity { dx: f32, dy: f32 }
155//! # struct Time { elapsed_seconds: f32 }
156//! # let mut world = World::default();
157//! # let mut resources = Resources::default();
158//! # resources.insert(Time { elapsed_seconds: 0.0 });
159//! // a system fn which loops through Position and Velocity components, and reads
160//! // the Time shared resource.
161//! #[system(for_each)]
162//! fn update_positions(pos: &mut Position, vel: &Velocity, #[resource] time: &Time) {
163//!     pos.x += vel.dx * time.elapsed_seconds;
164//!     pos.y += vel.dy * time.elapsed_seconds;
165//! }
166//!
167//! // construct a schedule (you should do this on init)
168//! let mut schedule = Schedule::builder()
169//!     .add_system(update_positions_system())
170//!     .build();
171//!
172//! // run our schedule (you should do this each update)
173//! schedule.execute(&mut world, &mut resources);
174//! # }
175//! ```
176//!
177//! See the [`systems`] module and the [`system`] proc macro for more information.
178//!
179//! # Feature Flags
180//!
181//! Legion provides a few feature flags:  
182//! * `parallel` - Enables parallel iterators and parallel schedule execution via the rayon library. Enabled by default.
183//! * `extended-tuple-impls` - Extends the maximum size of view and component tuples from 8 to 24, at the cost of increased compile times. Off by default.
184//! * `serialize` - Enables the serde serialization module and associated functionality. Enabled by default.
185//! * `crossbeam-events` - Implements the `EventSender` trait for crossbeam `Sender` channels, allowing them to be used for event subscriptions. Enabled by default.
186//! * `codegen` - Enables the `#[system]` procedural macro. Enabled by default.
187
188// implementation modules
189mod internals;
190
191// public API organized into logical modules
192pub mod query;
193pub mod storage;
194pub mod systems;
195pub mod world;
196
197#[cfg(feature = "serialize")]
198pub mod serialize;
199
200// re-export most common types into the root
201#[cfg(feature = "codegen")]
202pub use legion_codegen::system;
203
204#[cfg(feature = "serialize")]
205pub use crate::serialize::Registry;
206pub use crate::{
207    query::{
208        any, component, maybe_changed, passthrough, Fetch, IntoQuery, Query, Read, TryRead,
209        TryWrite, Write,
210    },
211    storage::{GroupSource, IntoSoa},
212    systems::{Resources, Schedule, SystemBuilder},
213    world::{Entity, EntityStore, World, WorldOptions},
214};