1 /*
2                                     __
3                                    / _|
4   __ _ _   _ _ __ ___  _ __ __ _  | |_ ___  ___ ___
5  / _` | | | | '__/ _ \| '__/ _` | |  _/ _ \/ __/ __|
6 | (_| | |_| | | | (_) | | | (_| | | || (_) \__ \__ \
7  \__,_|\__,_|_|  \___/|_|  \__,_| |_| \___/|___/___/
8 
9 Copyright (C) 2019-2020 Aurora Free Open Source Software.
10 Copyright (C) 2019 João Lourenço <joao@aurorafoss.org>
11 
12 This file is part of the Aurora Free Open Source Software. This
13 organization promote free and open source software that you can
14 redistribute and/or modify under the terms of the GNU Lesser General
15 Public License Version 3 as published by the Free Software Foundation or
16 (at your option) any later version approved by the Aurora Free Open Source
17 Software Organization. The license is available in the package root path
18 as 'LICENSE' file. Please review the following information to ensure the
19 GNU Lesser General Public License version 3 requirements will be met:
20 https://www.gnu.org/licenses/lgpl.html .
21 
22 Alternatively, this file may be used under the terms of the GNU General
23 Public License version 3 or later as published by the Free Software
24 Foundation. Please review the following information to ensure the GNU
25 General Public License requirements will be met:
26 https://www.gnu.org/licenses/gpl-3.0.html.
27 
28 NOTE: All products, services or anything associated to trademarks and
29 service marks used or referenced on this file are the property of their
30 respective companies/owners or its subsidiaries. Other names and brands
31 may be claimed as the property of others.
32 
33 For more info about intellectual property visit: aurorafoss.org or
34 directly send an email to: contact (at) aurorafoss.org .
35 */
36 
37 module aurorafw.entity.world;
38 
39 import aurorafw.entity.entity;
40 import aurorafw.entity.entitymanager;
41 import aurorafw.entity.icomponent;
42 import aurorafw.entity.componentmanager;
43 import aurorafw.entity.systemmanager;
44 import aurorafw.entity.system;
45 
46 version (unittest) import aurorafw.unit.assertion;
47 
48 final class World
49 {
50 	@safe pure
51 	public this()
52 	{
53 		_component = new ComponentManager();
54 		_entity = new EntityManager();
55 		_system = new SystemManager(_entity);
56 	}
57 
58 	/**
59 	 * Entity
60 	 *
61 	 * Returns the Entity Manager
62 	 *
63 	 * Examples:
64 	 * --------------------
65 	 * EntityManger manager = world.entity;
66 	 * --------------------
67 	 */
68 	@safe pure
69 	public EntityManager entity()
70 	{
71 		return _entity;
72 	}
73 
74 	/**
75 	 * Component
76 	 *
77 	 * Returns the Component Manager
78 	 *
79 	 * Examples:
80 	 * --------------------
81 	 * ComponentManager maneger = world.component;
82 	 * --------------------
83 	 */
84 	@property @safe pure
85 	public ComponentManager component()
86 	{
87 		return _component;
88 	}
89 
90 	/**
91 	 * System
92 	 *
93 	 * Returns the System Manager
94 	 *
95 	 * Examples:
96 	 * --------------------
97 	 * SystemManager manager = world.system;
98 	 * --------------------
99 	 */
100 	@property @safe pure
101 	public SystemManager system()
102 	{
103 		return _system;
104 	}
105 
106 	/**
107 	 * Update
108 	 *
109 	 * Updates every system with the UpdatePolicy set to Automatic
110 	 *
111 	 * Examples:
112 	 * --------------------
113 	 * world.update();
114 	 * --------------------
115 	 */
116 	@property public void update()
117 	{
118 		_system.update;
119 	}
120 
121 	/**
122 	 * Update
123 	 *
124 	 * Updates a single system passed by the user
125 	 *
126 	 * Examples:
127 	 * --------------------
128 	 * world.update!fooSystem;
129 	 * --------------------
130 	 */
131 	public void update(S : System)()
132 	{
133 		_system.update!S;
134 	}
135 
136 	private EntityManager _entity;
137 	private ComponentManager _component;
138 	private SystemManager _system;
139 }
140 
141 version (unittest)
142 {
143 	private class unittest_FooSystem : System
144 	{
145 		override public void update()
146 		{
147 			this.updatePolicy = UpdatePolicy.Manual;
148 		}
149 	}
150 
151 	private class unittest_BarSystem : System
152 	{
153 		@safe pure
154 		public this()
155 		{
156 			super(UpdatePolicy.Manual);
157 		}
158 
159 		override public void update()
160 		{
161 			this.updatePolicy = UpdatePolicy.Automatic;
162 		}
163 	}
164 
165 	private class unittest_FooComponent : IComponent
166 	{
167 		int a;
168 	}
169 
170 	private class unittest_FooBarSystem : System
171 	{
172 		override public void update()
173 		{
174 			Entity[] arr = this.manager.entity.getAllWith!(unittest_FooComponent);
175 
176 			foreach (Entity e; arr)
177 			{
178 				e.modify!unittest_FooComponent(5);
179 			}
180 		}
181 	}
182 }
183 
184 ///
185 @("World: System update")
186 unittest
187 {
188 	World world = new World();
189 
190 	unittest_FooSystem fooSys = new unittest_FooSystem();
191 	unittest_BarSystem barSys = new unittest_BarSystem();
192 	world.system.create(fooSys);
193 	world.system.create(barSys);
194 
195 	world.update(); // Only updates systems with Automatic Update Policy
196 
197 	assertEquals(fooSys.updatePolicy, fooSys.UpdatePolicy.Manual); // Got updated
198 	assertEquals(barSys.updatePolicy, barSys.UpdatePolicy.Manual); // Didn't get updated
199 
200 	world.system.update!unittest_BarSystem; // Every system can be updated manualy
201 
202 	assertEquals(barSys.updatePolicy, barSys.UpdatePolicy.Automatic); // Got updated
203 }
204 
205 ///
206 @("World: Main loop")
207 unittest
208 {
209 	World world = new World();
210 
211 	world.system.create(new unittest_FooBarSystem);
212 	Entity e = world.entity.create();
213 	e.add!unittest_FooComponent;
214 
215 	world.update();
216 
217 	assertEquals(5, e.get!unittest_FooComponent.a); // Component variable modified in the update method
218 }
219 
220 ///
221 @safe pure
222 @("World: Component Manager getter")
223 unittest
224 {
225 	World world = new World();
226 
227 	assertTrue(world._component is world.component);
228 }