1 module artemisd.world;
2 
3 import artemisd.utils.bag;
4 import artemisd.entitymanager;
5 import artemisd.entity;
6 import artemisd.entitytemplate;
7 import artemisd.componentmanager;
8 import artemisd.entitysystem;
9 import artemisd.manager;
10 import artemisd.entityobserver;
11 
12 class World 
13 {
14     private EntityManager em;
15     private ComponentManager cm;
16 
17     public float delta;
18     private Bag!Entity added;
19     private Bag!Entity changed;
20     private Bag!Entity deleted;
21     private Bag!Entity enabled;
22     private Bag!Entity disabled;
23 
24     private Manager[] managers;
25     
26     private EntitySystem[] systems;
27     
28     this() 
29     {
30         managers.length = 1;
31         systems.length = 1;
32 
33         added = new Bag!Entity();
34         changed = new Bag!Entity();
35         deleted = new Bag!Entity();
36         enabled = new Bag!Entity();
37         disabled = new Bag!Entity();
38 
39         cm = new ComponentManager();
40         setManager(cm);
41         
42         em = new EntityManager();
43         setManager(em);
44     }
45 
46     void initialize() 
47     {
48         foreach(m; managers)
49         {
50             if(m) m.initialize();
51         }
52 
53         foreach(s;systems)
54         {
55             if(s) s.initialize();
56         }
57     }
58     
59     EntityManager getEntityManager() 
60     {
61         return em;
62     }
63     
64     ComponentManager getComponentManager() 
65     {
66         return cm;
67     }
68 
69     T setManager(T)(T manager) 
70         if( is(T:Manager) )
71     {
72         import std.stdio;
73         if(managers.length <= T.TypeId)
74             managers.length = T.TypeId + 1;
75         managers[T.TypeId] = manager;
76         manager.setWorld(this);
77 
78         debug
79         {
80             import std.stdio;
81             writeln(typeid(manager), "(", T.TypeId, ")", " added");
82         }
83         return manager;
84     }
85 
86     T getManager(T)() 
87         if( is(T:Manager) )
88     {
89         return cast(T)managers[T.TypeId];
90     }
91     
92     void deleteManager(M)()
93         if( is(M:Manager))
94     {
95         managers[M.TypeId] = null;
96     }
97     
98     float getDelta() 
99     {
100         return delta;
101     }
102 
103     void setDelta(float delta) 
104     {
105         this.delta = delta;
106     }
107     
108     void addEntity(Entity e) 
109     {
110         added.add(e);
111     }
112     
113     void changedEntity(Entity e) 
114     {
115         changed.add(e);
116     }
117     
118     void deleteEntity(Entity e) 
119     {
120         if (!deleted.contains(e)) 
121         {
122             deleted.add(e);
123         }
124     }
125 
126     void enable(Entity e) 
127     {
128         enabled.add(e);
129     }
130 
131     void disable(Entity e) 
132     {
133         disabled.add(e);
134     }
135 
136     Entity createEntity() 
137     {
138         return em.createEntityInstance();
139     }
140 
141     Entity createEntityFromTemplate(T : EntityTemplate, Args...)(Args args) {
142         Entity entity = em.createEntityInstance();
143         T.buildEntity(entity, this, args);
144         return entity;
145     }
146 
147     Entity getEntity(int entityId) 
148     {
149         return em.getEntity(entityId);
150     }
151 
152     EntitySystem[] getSystems() 
153     {
154         return systems;
155     }
156 
157     T setSystem(T)(T system) 
158         if( is(T:EntitySystem) )
159     {
160         return setSystem!T(system, false);
161     }
162 
163     T setSystem(T)(T system, bool passive) 
164     {
165         system.setWorld(this);
166         system.setPassive(passive);
167         
168         if( systems.length <= T.TypeId )
169             systems.length = T.TypeId + 1;
170         systems[T.TypeId] = system;
171 
172         debug
173         {
174             import std.stdio;
175             writeln(typeid(system), "(", T.TypeId, ")", " added");
176         }   
177 
178         return system;
179     }
180     
181     void deleteSystem(E)()
182         if( is(E:EntitySystem) )
183     {
184         systems[E.TypeId] = null;
185     }
186     
187     private void notifySystems(Performer performer, Entity e) 
188     {
189         foreach(s;systems)
190         {
191             if(s) performer.perform(s,e);
192         }
193     }
194 
195     private void notifyManagers(Performer performer, Entity e) 
196     {
197         foreach(m;managers)
198         {
199             if(m) performer.perform(m,e);
200         }
201     }
202     
203     T getSystem(T)()
204         if( is(T:EntitySystem) )
205     {
206         return systems[T.TypeId];
207     }
208 
209     private void check(Bag!Entity entities, Performer performer) 
210     {
211         if (!entities.isEmpty()) 
212         {
213             for (int i = 0; entities.size() > i; i++) 
214             {
215                 Entity e = entities.get(i);
216                 notifyManagers(performer, e);
217                 notifySystems(performer, e);
218             }
219             entities.clear();
220         }
221     }
222 
223     void process() 
224     {
225         check(added, new class Performer {
226             public void perform(EntityObserver observer, Entity e) {
227                 observer.added(e);
228             }
229         });
230         
231         check(changed, new class Performer {
232             public void perform(EntityObserver observer, Entity e) {
233                 observer.changed(e);
234             }
235         });
236         
237         check(disabled, new class Performer {
238             public void perform(EntityObserver observer, Entity e) {
239                 observer.disabled(e);
240             }
241         });
242         
243         check(enabled, new class Performer {
244             public void perform(EntityObserver observer, Entity e) {
245                 observer.enabled(e);
246             }
247         });
248         
249         check(deleted, new class Performer {
250             public void perform(EntityObserver observer, Entity e) {
251                 observer.deleted(e);
252             }
253         });
254         
255         cm.clean();
256         
257         foreach(s;systems)
258         {
259             if( s && !s.isPassive() )
260                 s.process();
261         }
262     }
263     
264     private interface Performer 
265     {
266         void perform(EntityObserver observer, Entity e);
267     }
268 }