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
use *;
use TokenStream;
use quote;
use ;
/// Generates an ECS (World) and a component enum containing all components.
///
/// Takes as input a struct with named fields.
/// The names of the fields will correspond to the names of the storage types in the generated World.
/// The storage type used can be specified with `#[component(vec)]` for `VecStorage<T>` (the default)
/// or `#[component(map)]` for `MapStorage<T>`.
///
/// The name of the generated ECS is passed to the `#[world]` macro directly, together with the name of
/// the component enum. The component enum is a generated enum with one variant per component type that
/// can be used to register any of the component types on the generated World as an alternative to
/// directly calling `.set()` on the corresponding storage field.
///
/// The generated ECS has a shared set of `Entities` that is also used by each storage to check if
/// an entity exists; it is available via the `.entities` field. To avoid concurrency hazards,
/// it is stored in an `Arc<RwLock<Entities>>`. The generated `World` has some utility methods for
/// spawning new entities; these are handy shortcuts to accessing the underlying `entities` directly.
/// When spawning entities in a batch, direct access is recommended to avoid re-acquiring the write
/// lock over and over.
///
/// In addition to the component enum, this macro generates a "template" for an entity;
/// this template has one public field of type `Option<T>` for every component and can be used
/// to set the corresponding components on an entity. The name of these fields defaults to the name of the
/// field in the World definition and can be customized via `#[template_name(name)]`.
///
/// Attribute macros like `#[derive(Debug)]` are applied to both the component enum and the
/// template struct. This can be very useful for debugging and provides a quick and simple way
/// to define entities in data files and using e.g. serde to deserialize them into the generated
/// Template struct.
///
/// # Example
/// ```ignore
/// #[derive(Clone, Debug, Eq, PartialEq)]
/// pub struct Position {
/// pub position: (u32, u32),
/// }
///
/// #[derive(Clone, Debug, Eq, PartialEq)]
/// pub struct NameComponent {
/// pub name: String,
/// }
///
/// #[derive(Clone, Debug, Eq, PartialEq)]
/// pub struct RareComponent {
/// pub data: u32,
/// }
///
/// #[world(MyComponent, Template)]
/// #[derive(Clone, Debug, Eq, PartialEq)]
/// pub struct World {
/// #[component(vec)] //default, optional
/// positions: Position,
/// names: NameComponent,
/// #[component(map)]
/// rare_data: RareComponent,
/// }
/// ```