1 module unecht.core.entity; 2 3 import derelict.util.system; 4 5 import unecht.core.components.sceneNode; 6 import unecht.core.object; 7 import unecht.core.serialization.serializer; 8 import unecht.core.stdex; 9 import unecht.ue; 10 import unecht.core.events; 11 12 /// 13 enum UELayer : uint 14 { 15 all=0, 16 editor, 17 } 18 19 /// 20 static immutable uint UECameraDefaultLayers = 0xffffffff ^ (1<<UELayer.editor); 21 22 static assert(false == testBit(UECameraDefaultLayers,UELayer.editor)); 23 static assert(true == testBit(UECameraDefaultLayers,UELayer.all)); 24 25 /// 26 final class UEEntity : UEObject 27 { 28 import unecht.core.component:UERegisterObject,UEComponent; 29 import unecht.core.serialization.mixins:generateObjectSerializeFunc; 30 mixin(UERegisterObject!()); 31 32 @nogc @property{ 33 /// 34 UESceneNode sceneNode() nothrow { return _sceneNode; } 35 /// 36 const(UESceneNode) sceneNode() const nothrow { return _sceneNode; } 37 /// 38 bool destroyed() nothrow { return _destroyed; } 39 /// 40 string name() const { return _name; } 41 /// 42 void name(string v) { _name = v; } 43 /// 44 UELayer layer() const { return _layer; } 45 /// 46 void layer(UELayer layer) { _layer = layer; } 47 /// 48 UEComponent[] components() { return _components; } 49 } 50 51 /// 52 void broadcast(string _method,ARG)(ARG _arg) 53 { 54 import std..string:format; 55 foreach(component; _components) 56 { 57 enum mix = format("component.%s(_arg);",_method); 58 mixin(mix); 59 } 60 } 61 62 /// 63 void broadcast(string _method)() 64 { 65 import std..string:format; 66 foreach(component; _components) 67 { 68 enum mix = format("component.%s();",_method); 69 70 mixin(mix); 71 } 72 } 73 74 //TODO: optimize ? 75 /// find first component of type T 76 @nogc auto getComponent(T : UEComponent)() nothrow 77 { 78 foreach(c; _components) 79 { 80 auto c2t = cast(T)c; 81 if(c2t) 82 return c2t; 83 } 84 85 return null; 86 } 87 88 /// 89 @nogc bool hasComponent(T : UEComponent)() nothrow 90 { 91 return getComponent!T !is null; 92 } 93 94 /// 95 auto addComponent(T : UEComponent)() 96 { 97 auto newT = new T(); 98 auto newcomp = cast(UEComponent)newT; 99 100 addComponent(newcomp); 101 102 return newT; 103 } 104 105 /// 106 UEComponent addComponent(string _type) 107 { 108 auto newcomp = cast(UEComponent)Object.factory(_type); 109 assert(newcomp); 110 111 addComponent(newcomp); 112 113 return newcomp; 114 } 115 116 /// 117 void removeComponent(UEComponent c) 118 { 119 import std.algorithm:countUntil,remove; 120 121 auto idx = _components.countUntil(c); 122 if(idx > -1) 123 { 124 c.onDestroy(); 125 ue.events.removeComponent(c); 126 .destroy(c); 127 128 _components = _components.remove(idx); 129 } 130 } 131 132 /// factory method 133 static auto create(string _name = null, UESceneNode _parent = null) 134 { 135 return new UEEntity(_parent ? _parent : ue.scene.root, _name); 136 } 137 138 /// 139 static auto createForDeserialize() 140 { 141 return new UEEntity(); 142 } 143 144 /// 145 static void destroy(UEEntity entity) 146 { 147 assert(entity); 148 assert(entity._sceneNode.parent); 149 entity._destroyed = true; 150 } 151 152 /// 153 static void destroyImmediate(UEEntity entity) 154 { 155 assert(entity); 156 entity.doDestroy(); 157 } 158 159 /// can go once ue is removed and we have DI 160 @property UEEvents events(){ return ue.events; } 161 162 private: 163 164 /// used for default construction in the deserializer 165 this() 166 {} 167 168 this(UESceneNode _parent, string _name) 169 { 170 if(_name) 171 this._name = _name; 172 173 this._sceneNode = new UESceneNode(); 174 addComponent(this._sceneNode); 175 176 this._sceneNode.parent = _parent; 177 } 178 179 void addComponent(UEComponent _comp) 180 { 181 _comp.setEntity(this); 182 183 _components ~= _comp; 184 185 _comp.onCreate(); 186 } 187 188 void doDestroy() 189 { 190 while(_sceneNode.children.length > 0) 191 { 192 auto child = _sceneNode.children[0]; 193 194 assert(child.entity); 195 child.entity.doDestroy(); 196 } 197 198 //unparenting of local components 199 broadcast!("onDestroy")(); 200 201 _destroyed = true; 202 _sceneNode = null; 203 _name = null; 204 205 foreach(component; _components) 206 { 207 component.setEntity(null); 208 ue.events.removeComponent(component); 209 .destroy(component); 210 } 211 _components.length = 0; 212 } 213 214 private: 215 //TODO: non public as soon as @Serialize works 216 @Serialize 217 string _name = "entity"; 218 219 bool _destroyed = false; 220 221 //TODO: non public as soon as @Serialize works 222 @Serialize 223 UELayer _layer = UELayer.all; 224 225 @Serialize 226 UESceneNode _sceneNode; 227 228 //TODO: non public as soon as @Serialize works 229 @Serialize 230 UEComponent[] _components; 231 }