1 module unecht.core.component; 2 3 import derelict.util.system; 4 5 public import unecht.core.serialization.serializer; 6 public import unecht.core.serialization.mixins; 7 import unecht.core.events:UEEventType; 8 import unecht.core.entity; 9 import unecht.core.components.sceneNode; 10 import unecht.core.object; 11 12 /// 13 template UEObjectCreateMenuItem() 14 { 15 enum UEObjectCreateMenuItem = q{ 16 static if(!is(typeof(this) == UEComponent) && is(typeof(this) : UEComponent)) 17 { 18 version(UEIncludeEditor)import unecht.core.components.editor.menus; 19 version(UEIncludeEditor)import unecht.meta.uda; 20 21 version(UEIncludeEditor)override void getMenuItems(ref EditorMenuItem[] items) 22 { 23 super.getMenuItems(items); 24 25 alias T = typeof(this); 26 27 foreach(m; __traits(derivedMembers, T)) 28 { 29 static if(__traits(isStaticFunction, __traits(getMember, T, m))) 30 { 31 static if(hasUDA!(__traits(getMember, T, m), MenuItem)) 32 { 33 alias MemberType = typeof(&__traits(getMember, T, m)); 34 35 static if(is(MemberType : MenuItemFunc)) 36 { 37 alias uda = getUDA!(__traits(getMember, T, m), MenuItem); 38 39 items ~= EditorMenuItem(uda.name, &__traits(getMember, T, m), uda.validate); 40 } 41 else 42 { 43 static assert(false, format("%s.%s is annotated as MenuItem but has type: '%s' expected '%s'", 44 T.stringof,m,MemberType.stringof,MenuItemFunc.stringof)); 45 } 46 } 47 } 48 } 49 } 50 } 51 }; 52 } 53 54 /// 55 template UEObjectSerialization() 56 { 57 enum UEObjectSerialization = q{ 58 59 private{ 60 mixin generateObjectSerializeFunc!(serializeMember, UESerializer, "serialize"); 61 mixin generateObjectSerializeFunc!(deserializeMember, UEDeserializer, "deserialize"); 62 63 void serializeMember(T,M)(string m,ref M member, ref UESerializer serializer, UECustomFuncSerialize!M customFunc=null) 64 { 65 serializer.serializeObjectMember!(T,M)(this, m, member, customFunc); 66 } 67 68 void deserializeMember(T,M)(string m, ref M member, ref UEDeserializer serializer, UECustomFuncDeserialize!M customFunc=null) 69 { 70 serializer.deserializeObjectMember!(T,M)(this, this.instanceId.toString(), m, member, customFunc); 71 } 72 } 73 74 override void serialize(ref UESerializer serializer) 75 { 76 import unecht.core.hideFlags; 77 if(hideFlags.isSet(HideFlags.dontSaveInScene)) 78 return; 79 80 alias T = typeof(this); 81 82 iterateAllSerializables!(T)(this, serializer); 83 84 super.serialize(serializer); 85 } 86 87 override void deserialize(ref UEDeserializer serializer, string uid=null) 88 { 89 super.deserialize(serializer,uid); 90 91 alias T = typeof(this); 92 93 iterateAllSerializables!(T)(this, serializer); 94 } 95 }; 96 } 97 98 /// 99 template UEObjectCreateEditor() 100 { 101 enum UEObjectCreateEditor = q{ 102 103 version(UEIncludeEditor)import unecht.core.componentManager:IComponentEditor; 104 105 version(UEIncludeEditor) 106 override IComponentEditor createEditor() 107 { 108 import unecht.core.defaultInspector; 109 110 alias T = typeof(this); 111 112 static UEDefaultInspector!T editor; 113 114 if(editor is null) 115 editor = new UEDefaultInspector!T(); 116 117 return editor; 118 } 119 }; 120 } 121 122 /// 123 template UERegisterObject() 124 { 125 enum UERegisterObject = 126 UEObjectSerialization!() 127 ~ UEObjectCreateMenuItem!() 128 ~ UEObjectCreateEditor!() 129 ~ q{version(UEIncludeEditor)override @property string typename() { return typeof(this).stringof; }}; 130 } 131 132 /// binding component between an GameEntity and a SceneNode 133 abstract class UEComponent : UEObject 134 { 135 import unecht.core.events:UEEventCallback,UEEventReceiver; 136 137 mixin(UERegisterObject!()); 138 139 //void OnEnable() {} 140 /// 141 void onUpdate() {} 142 //void OnDisable() {} 143 144 /// 145 void onCreate() {} 146 /// 147 void onDestroy() {} 148 /// 149 void onCollision(UEComponent /+_collider+/) {} 150 151 @nogc final nothrow { 152 /// 153 @property bool enabled() const { return _enabled; } 154 /// 155 @property void enabled(bool _value) { _enabled = _value; } 156 /// 157 @property UEEntity entity() { return _entity; } 158 /// 159 @property UESceneNode sceneNode() { return _entity.sceneNode; } 160 } 161 162 /// helper 163 final void registerEvent(UEEventType _type, UEEventCallback _callback) 164 { 165 _entity.events.register(UEEventReceiver(this,_type,_callback)); 166 } 167 168 version(UEIncludeEditor){ 169 import unecht.core.components.editor.menus:EditorMenuItem; 170 /// 171 void getMenuItems(ref EditorMenuItem[] items){} 172 } 173 174 package: 175 /// 176 final void setEntity(UEEntity _entity) { this._entity = _entity; } 177 178 private: 179 @Serialize 180 UEEntity _entity; 181 182 //TODO: disabled by default 183 @Serialize 184 bool _enabled = true; 185 }