1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#![deny(missing_docs)]

//! Legion aims to be a feature rich high performance ECS library for Rust game projects with minimal boilerplate.
//!
//! # Getting Started
//!
//! ## Worlds
//!
//! [Worlds](World) are collections of [entities](Entity), where each entity can have an arbitrary collection of
//! [components](storage::Component) attached.
//!
//! ```
//! use legion::*;
//! let world = World::default();
//! ```
//!
//! Entities can be inserted via either [`World::push`] (for a single entity) or [`World::extend`] (for a collection
//! of entities with the same component types). The world will create a unique ID for each entity upon insertion
//! that you can use to refer to that entity later.
//!
//! ```
//! # use legion::*;
//! # let mut world = World::default();
//! // a component is any type that is 'static, sized, send and sync
//! #[derive(Clone, Copy, Debug, PartialEq)]
//! struct Position {
//!     x: f32,
//!     y: f32,
//! }
//!
//! #[derive(Clone, Copy, Debug, PartialEq)]
//! struct Velocity {
//!     dx: f32,
//!     dy: f32,
//! }
//!
//! // push a component tuple into the world to create an entity
//! let entity: Entity = world.push((Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }));
//!
//! // or extend via an IntoIterator of tuples to add many at once (this is faster)
//! let entities: &[Entity] = world.extend(vec![
//!     (Position { x: 0.0, y: 0.0 }, Velocity { dx: 0.0, dy: 0.0 }),
//!     (Position { x: 1.0, y: 1.0 }, Velocity { dx: 0.0, dy: 0.0 }),
//!     (Position { x: 2.0, y: 2.0 }, Velocity { dx: 0.0, dy: 0.0 }),
//! ]);
//! ```
//!
//! You can access entities via [entries](world::Entry). Entries allow you to query an entity to find out what
//! types of components are attached to it, to get component references, or to add and remove components.
//!
//! ```
//! # use legion::*;
//! # let mut world = World::default();
//! # let entity = world.push((false,));
//! // entries return `None` if the entity does not exist
//! if let Some(mut entry) = world.entry(entity) {
//!     // access information about the entity's archetype
//!     println!(
//!         "{:?} has {:?}",
//!         entity,
//!         entry.archetype().layout().component_types()
//!     );
//!
//!     // add an extra component
//!     entry.add_component(12f32);
//!
//!     // access the entity's components, returns `None` if the entity does not have the component
//!     assert_eq!(entry.get_component::<f32>().unwrap(), &12f32);
//! }
//! ```
//!
//! See the [`world`] module for more information.
//!
//! ## Queries
//!
//! Entries are not the most convenient or performant way to search or bulk-access a world. [Queries](query)
//! allow for high performance and expressive iteration through the entities in a world.
//!
//! ```
//! # use legion::*;
//! # let world = World::default();
//! # #[derive(Debug)]
//! # struct Position;
//! // you define a query be declaring what components you want to find, and how you will access them
//! let mut query = Read::<Position>::query();
//!
//! // you can then iterate through the components found in the world
//! for position in query.iter(&world) {
//!     println!("{:?}", position);
//! }
//! ```
//!
//! You can search for entities which have all of a set of components.
//!
//! ```
//! # use legion::*;
//! # let mut world = World::default();
//! # struct Position { x: f32, y: f32 }
//! # struct Velocity { x: f32, y: f32 }
//! // construct a query from a "view tuple"
//! let mut query = <(&Velocity, &mut Position)>::query();
//!
//! // this time we have &Velocity and &mut Position
//! for (velocity, position) in query.iter_mut(&mut world) {
//!     position.x += velocity.x;
//!     position.y += velocity.y;
//! }
//! ```
//!
//! You can augment a basic query with additional filters. For example, you can choose to exclude
//! entities which also have a certain component, or only include entities for which a certain
//! component has changed since the last time the query ran (this filtering is conservative and coarse-grained)
//!
//! ```
//! # use legion::*;
//! # let mut world = World::default();
//! # struct Position { x: f32, y: f32 }
//! # struct Velocity { dx: f32, dy: f32 }
//! # struct Ignore;
//! // you can use boolean expressions when adding filters
//! let mut query = <(&Velocity, &mut Position)>::query()
//!     .filter(!component::<Ignore>() & maybe_changed::<Position>());
//!
//! for (velocity, position) in query.iter_mut(&mut world) {
//!     position.x += velocity.dx;
//!     position.y += velocity.dy;
//! }
//! ```
//!
//! There is much more than can be done with queries. See the [module document](query) for more information.
//!
//! ## Systems
//!
//! You may have noticed that when we wanted to write to a component, we needed to use `iter_mut` to iterate through our query.
//! But perhaps your application wants to be able to process different components on different entities, perhaps even at the same
//! time in parallel? While it is possible to do this manually (see [`World::split`]), this is very difficult to do when the
//! different pieces of the application don't know what components each other need, or might or might not even have conflicting
//! access requirements.
//!
//! Systems and the [`Schedule`] automates this process, and can even schedule work at a more granular level than
//! you can otherwise do manually.
//!
//! A system is a unit of work. Each system is defined as a function which is provided access to queries and shared
//! [`Resources`]. These systems can then be appended to a schedule, which is a linear sequence of systems,
//! ordered by when side effects (such as writes to components) should be observed.
//!
//! The schedule will automatically parallelize the execution of all systems whilst maintaining the apparent order of execution from
//! the perspective of each system.
//!
//! ```
//! # #[cfg(feature = "codegen")] {
//! # use legion::*;
//! # struct Position { x: f32, y: f32 }
//! # struct Velocity { dx: f32, dy: f32 }
//! # struct Time { elapsed_seconds: f32 }
//! # let mut world = World::default();
//! # let mut resources = Resources::default();
//! # resources.insert(Time { elapsed_seconds: 0.0 });
//! // a system fn which loops through Position and Velocity components, and reads
//! // the Time shared resource.
//! #[system(for_each)]
//! fn update_positions(pos: &mut Position, vel: &Velocity, #[resource] time: &Time) {
//!     pos.x += vel.dx * time.elapsed_seconds;
//!     pos.y += vel.dy * time.elapsed_seconds;
//! }
//!
//! // construct a schedule (you should do this on init)
//! let mut schedule = Schedule::builder()
//!     .add_system(update_positions_system())
//!     .build();
//!
//! // run our schedule (you should do this each update)
//! schedule.execute(&mut world, &mut resources);
//! # }
//! ```
//!
//! See the [`systems`] module and the [`system`] proc macro for more information.
//!
//! # Feature Flags
//!
//! Legion provides a few feature flags:  
//! * `parallel` - Enables parallel iterators and parallel schedule execution via the rayon library. Enabled by default.
//! * `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.
//! * `serialize` - Enables the serde serialization module and associated functionality. Enabled by default.
//! * `crossbeam-events` - Implements the `EventSender` trait for crossbeam `Sender` channels, allowing them to be used for event subscriptions. Enabled by default.
//! * `codegen` - Enables the `#[system]` procedural macro. Enabled by default.

// implementation modules
mod internals;

// public API organized into logical modules
pub mod query;
pub mod storage;
pub mod systems;
pub mod world;

#[cfg(feature = "serialize")]
pub mod serialize;

// re-export most common types into the root
#[cfg(feature = "codegen")]
pub use legion_codegen::system;

#[cfg(feature = "serialize")]
pub use crate::serialize::Registry;
pub use crate::{
    query::{
        any, component, maybe_changed, passthrough, Fetch, IntoQuery, Query, Read, TryRead,
        TryWrite, Write,
    },
    storage::{GroupSource, IntoSoa},
    systems::{Resources, Schedule, SystemBuilder},
    world::{Entity, EntityStore, World, WorldOptions},
};