1 /************************************************************************************************************************ 2 System module. 3 4 Copyright: Copyright © 2018-2023, Dawid Masiukiewicz, Michał Masiukiewicz 5 License: BSD 3-clause, see LICENSE file in project root folder. 6 */ 7 module bubel.ecs.system; 8 9 import bubel.ecs.entity; 10 import bubel.ecs.manager; 11 12 /************************************************************************************************************************ 13 System contain data required to proper glue EntityManager with Systems. 14 System callbacks: 15 $(LIST 16 * void onUpdate(EntitesData); 17 * void onEnable() - called inside system.enable() function 18 * void onDisable() - called inside system.disable() function 19 * bool onBegin() - called inside manager.begin() 20 * void onEnd() - called inside manager.end() 21 * void onCreate() - called after registration inside registerSystem function 22 * void onDestroy() - called during re-registration and inside manager destructor 23 * void onAddEntity(EntitesData) - called for every entity which are assigned to system (by adding new entity or changing its components) 24 * void onRemoveEntity(EntitiesData) - called for every entity removed from system update process 25 * void onChangeEntity(EntitiesData) - called for every entity which components are changed but it was previously assigned to system 26 * void handleEvent(Entity*, Event) - called for every event supported by system 27 ) 28 */ 29 struct System 30 { 31 32 /************************************************************************************************************************ 33 Check if system is enabled. 34 */ 35 export bool enabled() nothrow @nogc 36 { 37 return m_enabled; 38 } 39 40 /************************************************************************************************************************ 41 Enable system. If actually it is enabled function do nothing. 42 */ 43 export void enable() nothrow @nogc 44 { 45 if (!m_enabled && m_enable) 46 (cast(void function(void*) nothrow @nogc) m_enable)(m_system_pointer); 47 m_enabled = true; 48 } 49 50 /************************************************************************************************************************ 51 Disable system. If actually it is disabled function do nothing. 52 */ 53 export void disable() nothrow @nogc 54 { 55 if (m_enabled && m_disable) 56 (cast(void function(void*) nothrow @nogc) m_disable)(m_system_pointer); 57 m_enabled = false; 58 } 59 60 /************************************************************************************************************************ 61 Get system priority. 62 */ 63 export int priority() nothrow @nogc 64 { 65 return m_priority; 66 } 67 68 /************************************************************************************************************************ 69 Get if system will be executed during current frame. Should be checked after manager.begin(). Its value is setted as result of manager.onBegin() callback. 70 */ 71 export bool willExecute() nothrow @nogc 72 { 73 return m_execute; 74 } 75 76 /************************************************************************************************************************ 77 Get system id. 78 */ 79 export ushort id() nothrow @nogc 80 { 81 return m_id; 82 } 83 84 /************************************************************************************************************************ 85 Get system name. 86 */ 87 export const(char)[] name() nothrow @nogc 88 { 89 return cast(const(char)[]) m_name; 90 } 91 92 /************************************************************************************************************************ 93 Return false if system was unregistered, true otherwise. 94 */ 95 export bool isAlive() nothrow @nogc 96 { 97 return m_system_pointer != null; 98 } 99 100 package: 101 102 void destroy() 103 { 104 import bubel.ecs.std : Mallocator; 105 disable(); 106 if (m_destroy) 107 (cast(void function(void*)) m_destroy)(m_system_pointer); 108 109 if (m_name) 110 Mallocator.dispose(m_name); 111 if (m_components) 112 Mallocator.dispose(m_components); 113 if (m_excluded_components) 114 Mallocator.dispose(m_excluded_components); 115 if (m_optional_components) 116 Mallocator.dispose(m_optional_components); 117 if (jobs) 118 Mallocator.dispose(jobs); 119 if (m_read_only_components) 120 Mallocator.dispose(m_read_only_components); 121 if (m_writable_components) 122 Mallocator.dispose(m_writable_components); 123 if (m_readonly_dependencies) 124 Mallocator.dispose(m_readonly_dependencies); 125 if (m_writable_dependencies) 126 Mallocator.dispose(m_writable_dependencies); 127 if (m_event_callers) 128 Mallocator.dispose(m_event_callers); 129 130 if (m_system_pointer) 131 Mallocator.dispose(m_system_pointer); 132 } 133 134 struct EventCaller 135 { 136 ushort id; 137 void* callback; 138 } 139 140 ///should system be executed in current update? 141 bool m_execute = true; 142 ///system id 143 ushort m_id; 144 ///is system empty? Empty systems don't update entities, and is called once per update 145 bool m_empty = false; 146 147 ///should system update and catch events? 148 bool m_enabled = false; 149 ///system priority 150 int m_priority; 151 ///pointer to system implementation 152 void* m_system_pointer; 153 ///system pass index 154 int m_pass; 155 156 ///system name 157 char[] m_name; 158 159 ///required components 160 ushort[] m_components; 161 ///excluded components 162 ushort[] m_excluded_components; 163 ///optional components 164 ushort[] m_optional_components; 165 166 EntityManager.Job[] jobs; 167 168 //System*[] m_dependencies; 169 ushort[] m_read_only_components; 170 ushort[] m_writable_components; 171 172 ushort[] m_readonly_dependencies; 173 ushort[] m_writable_dependencies; 174 175 EntityManager.SystemCaller* m_any_system_caller; 176 177 EventCaller[] m_event_callers; 178 179 //void function(ref EntityManager.CallData data) m_update; 180 void* m_update; ///workaroud for DMD bug with upper line 181 void delegate() m_update_delegate; 182 183 //void function(void* system_pointer) m_enable; 184 //void function(void* system_pointer) m_disable; 185 186 //void function(void* system_pointer) m_create; 187 //void function(void* system_pointer) m_destroy; 188 189 //void function(void* system_pointer) m_begin; 190 //void function(void* system_pointer) m_end; 191 192 void* m_enable; 193 void* m_disable; 194 195 void* m_create; 196 void* m_destroy; 197 198 void* m_begin; 199 void* m_end; 200 201 void* m_add_entity; 202 void* m_remove_entity; 203 void* m_change_entity; 204 205 void* m_filter_entity; 206 207 //void function(ref EntityManager.CallData data) m_initialize; 208 //void function(ref EntityManager.CallData data) m_deinitilize; 209 void* m_initialize; 210 void* m_deinitilize; 211 }