1 module re.ecs.entity;
2 
3 import std.array;
4 import std.conv;
5 import std.algorithm.iteration;
6 import std.algorithm.searching;
7 import re.ng.scene;
8 import re.ecs.manager;
9 import re.ecs.component;
10 import re.ecs.storage;
11 import re.math;
12 
13 /// a container for components
14 class Entity {
15     /// the unique id of this entity
16     public size_t id;
17     /// whether this entity is alive
18     public bool alive;
19     /// the scene that this entity is part of
20     public Scene scene;
21     /// world transform of entity
22     public Transform transform;
23     /// friendly name
24     public string name;
25     /// ecs manager
26     public EntityManager manager;
27     /// list of component references
28     public ComponentId[] components;
29 
30     /// create entity given the ecs
31     this(EntityManager manager) {
32         this.manager = manager;
33     }
34 
35     /// prepare the instance as a fresh entity
36     public void initialize() {
37         alive = true;
38         transform = Transform();
39         name = string.init;
40         components = [];
41     }
42 
43     /// release all resources and deinitialize
44     public void destroy() {
45         alive = false;
46         manager.storage.destroy_all(this); // destroy all components
47         name = string.init;
48     }
49 
50     /// add an instance of a component given the type
51     public T add_component(T)() {
52         return add_component(new T());
53     }
54 
55     /// add a component
56     public T add_component(T)(T component) {
57         auto id = manager.storage.insert(this, component);
58         components ~= id;
59         component.entity = this;
60         component.setup();
61         return component;
62     }
63 
64     /// remove a matching component given a type
65     public void remove_component(T)() {
66         auto component = get_component!T();
67         remove_component(component);
68     }
69 
70     /// remove a specific component
71     public void remove_component(T)(T component) {
72         manager.storage.remove(this, component);
73     }
74 
75     /// checks whether this entity contains a matching component
76     public bool has_component(T)() {
77         return manager.storage.has_component!T(this);
78     }
79 
80     /// gets a matching component given a type
81     public T get_component(T)() {
82         return cast(T) manager.storage.get!T(this);
83 
84     }
85 
86     /// gets all matching components given a type
87     public T[] get_components(T)() {
88         return manager.storage.get_all!T(this);
89     }
90 
91     /// gets all components attached to this entity
92     public Component[] get_all_components() {
93         return manager.storage.get_all(this);
94     }
95 
96     // - transform
97 
98     /// forwards to transform
99     @property Vector2 position2() {
100         return transform.position2;
101     }
102 
103     /// forwards to transform
104     @property Vector2 position2(Vector2 value) {
105         return transform.position2 = value;
106     }
107 
108     /// forwards to transform
109     @property ref Vector3 position() {
110         return transform.position;
111     }
112 
113     /// forwards to transform
114     @property Vector3 position(Vector3 value) {
115         return transform.position = value;
116     }
117 
118     public override string toString() const {
119         import std.string : format;
120 
121         return format("Entity[%d, %s]", id, name);
122     }
123 }