1 module Engine.Component; 2 3 4 import t = Engine.Transform; 5 import std.traits; 6 import e = Engine.Entity; 7 import std.traits; 8 import std.typetuple; 9 10 abstract class Component 11 { 12 package e.Entity _entity; 13 14 final @property public e.Entity entity() { 15 return _entity; 16 }; 17 18 final @property public t.Transform transform() { 19 return _entity.transform; 20 }; 21 22 this() 23 { 24 25 } 26 27 final package void bind(e.Entity entity) { 28 this._entity = entity; 29 }; 30 31 public T Cast(T)() if (is(T == class)) { 32 auto tptr = cast(T)CastType(typeid(T)); 33 if (tptr) 34 return tptr; 35 return cast(T)this; 36 } 37 38 public void* CastType(TypeInfo targetType) { 39 return null; 40 } 41 42 public auto Cast(T)() if (is(T == struct)) { 43 auto cit = cast(ComponentImpl!T)this; 44 if (cit) 45 return cit.Cast!T(); 46 return null; 47 } 48 49 public auto Cast(T : T*)() if (is(T == struct)) { 50 auto cit = cast(ComponentImpl!T)this; 51 if (cit) 52 return cit.Cast!T(); 53 return null; 54 } 55 56 57 public void OnComponentAdd() {}; 58 public void Awake() {}; 59 public void Start() {}; 60 public void Update() {}; 61 public void LateUpdate() {}; 62 63 public void OnMessage(string op, void* arg) { 64 65 } 66 67 final @property public bool hasUpdate() { 68 return ((&Update).funcptr != (&Component.Update).funcptr); 69 }; 70 71 final @property public bool hasStart() { 72 return ((&Start).funcptr != (&Component.Start).funcptr); 73 }; 74 75 final @property public bool hasLateUpdate() { 76 return ((&LateUpdate).funcptr != (&Component.LateUpdate).funcptr); 77 }; 78 } 79 80 81 template ComponentBase() 82 { 83 84 e.Entity _entity; 85 86 final @property public e.Entity entity() { 87 return _entity; 88 }; 89 90 final @property public t.Transform transform() { 91 return entity.transform; 92 }; 93 } 94 95 public class ComponentImpl(T) : Component { 96 97 static if (is(T == class)) { 98 private byte[__traits(classInstanceSize, T)] raw; 99 } 100 T component; 101 102 this()() { 103 static if (is(T == class)) { 104 component = cast(T)&raw; 105 auto l = raw.length; 106 raw[0..l] = T.classinfo.init[0..l]; 107 static if (__traits(compiles, component.__ctor())) { 108 component.__ctor(); 109 } 110 } 111 } 112 113 this(Args...)(Args args) if (args.length > 0) { 114 static if (is(T == class)) { 115 component = cast(T)&raw; 116 auto l = raw.length; 117 raw[0..l] = T.classinfo.init[0..l]; 118 component.__ctor(args); 119 } else { 120 component = T(args); 121 } 122 } 123 124 pure T Cast(T)() if (is(T == class)) { 125 return cast(T)component; 126 } 127 128 public auto Cast(T)() if (is(T == struct)) { 129 static if (__traits(compiles, cast(T)&component)) 130 return cast(T)&component; 131 else 132 return cast(T*)&component; 133 } 134 135 static if(hasMember!(T, "OnMessage")) 136 public override void OnMessage(string op, void* arg) { 137 component.OnMessage(op,arg); 138 } 139 140 static if(hasMember!(T, "Awake")) 141 public override void Awake() { 142 component.Awake(); 143 } 144 145 static if(hasMember!(T, "Update")) 146 public override void Update() { 147 component.Update(); 148 } 149 150 static if(hasMember!(T, "OnComponentAdd")) 151 public override void OnComponentAdd() { 152 component.OnComponentAdd(); 153 } 154 155 final package void bind(e.Entity entity) { 156 super.bind(entity); 157 (cast(e.Entity)component._entity) = entity; 158 } 159 160 static if(is(T == class)) 161 public override void* CastType(TypeInfo targetType) 162 { 163 alias TypeTuple!(T, ImplicitConversionTargets!T) AllTypes; 164 foreach (F ; AllTypes) 165 { 166 if (targetType != typeid(F) && 167 targetType != typeid(const(F))) 168 { 169 static if (isImplicitlyConvertible!(F, immutable(F))) 170 { 171 if (targetType != typeid(immutable(F))) 172 { 173 continue; 174 } 175 } 176 else 177 { 178 continue; 179 } 180 } 181 return cast(void*)cast(F)component; 182 } 183 return null; 184 } 185 }