578 m_last_time(std::chrono::high_resolution_clock::now()),
579 m_commands(std::make_unique<Commands>(*
this)) {
594 m_resources[
typeid(T)] = std::make_unique<
Resource<T>>(resource);
609 auto it = m_resources.find(
typeid(T));
611 assert(it != m_resources.end() &&
"Requested resource not found");
613 return *
static_cast<Resource<T>*
>(it->second.get());
631 template<
typename Func>
633 get_systems(label).emplace_back(
634 std::make_unique<System<std::decay_t<Func>>>(
635 std::forward<Func>(func),
656 template<
typename Func>
658 add_system(ScheduleLabel::Update, std::forward<Func>(func));
665 auto current_time = std::chrono::high_resolution_clock::now();
666 std::chrono::duration<float> delta = current_time - m_last_time;
667 m_time.delta = delta.count();
668 m_last_time = current_time;
678 m_time.delta = delta_time;
685 template<
typename... Components>
686 inline Query<Components...> query() {
687 return Query<Components...>(
this);
690 template<
typename... Components>
691 Observer<Components...>& observe() {
692 auto observer = std::make_unique<Observer<Components...>>();
693 auto new_observer = observer.
get();
694 m_observers.push_back(std::move(observer));
695 return *new_observer;
698 inline Commands& commands();
700 void despawn(Entity entity) {
701 auto entity_it = m_entity_archetype_map.find(entity);
702 if (entity_it == m_entity_archetype_map.end()) {
707 Archetype* archetype = entity_it->second;
708 archetype->remove_entity(entity);
709 m_entity_archetype_map.erase(entity_it);
710 notify_remove(archetype->m_mask, entity);
711 m_free_list.push_back(entity);
715 void log_archetypes() {
716 printf(
"--- Logging Archetypes ---\n");
717 for (
const auto& archetype : m_archetypes) {
719 "Archetype with mask: %s\n",
720 archetype->m_mask.to_string().c_str()
723 if (archetype->m_entity_to_index.empty()) {
724 printf(
"No entities in this archetype (empty)\n");
726 printf(
"Entities in this archetype: ");
727 for (
const auto& entity : archetype->m_entity_to_index) {
728 printf(
"Entity(%zu) ", entity.first);
730 printf(
"(total = %zu)\n", archetype->m_entity_to_index.size());
733 printf(
"--- End of Archetypes Log ---\n");
737 template<
typename... Components>
739 friend class EntityBuilder;
740 friend class EntityCommands;
743 struct TypeErasedSystem {
744 virtual ~TypeErasedSystem() =
default;
745 virtual void execute(World& world) = 0;
748 template<
typename Func>
749 struct System: TypeErasedSystem {
752 System(Func&& f, World& world) :
753 params(get_system_params<
754 typename _traits::function_traits<Func>::args_tuple>(world)),
755 func(std::forward<Func>(f)) {}
757 void execute(World& world)
override {
758 std::apply(func, params);
763 decltype(get_system_params<
764 typename _traits::function_traits<Func>::args_tuple>(
765 std::declval<World&>()
773 template<
typename... Components>
776 friend class EntityBuilder;
779 T* get_component(Entity entity) {
780 auto it = m_entity_to_index.find(entity);
781 if (it == m_entity_to_index.end()) {
784 return get_row<T>(it->second);
788 T* get_row(
size_t row) {
789 static const ComponentId
id = TypeIDGenerator::get_type_id<T>();
790 auto it = m_type_to_column.find(
id);
791 if (it == m_type_to_column.end()) {
797 static_cast<ComponentColumn<T>*
>(m_columns[it->second].get());
798 if (row >= column->data.size()) {
803 return &column->data[row];
806 template<
typename Component>
808 get_component_or_entity(Archetype* archetype,
const Entity& entity) {
809 if constexpr (std::is_same_v<Component, Entity>) {
811 }
else if constexpr (_traits::is_optional<Component>()) {
812 using UnderlyingType =
typename Component::value_type;
813 return Optional<UnderlyingType>(
814 archetype->template get_component<UnderlyingType>(entity)
817 return archetype->template get_component<Component>(entity);
821 template<
typename... Components>
823 make_component_tuple(Archetype* archetype,
const Entity& entity) {
824 return std::make_tuple(
825 get_component_or_entity<Components>(archetype, entity)...
829 Archetype(
const ComponentMask& mask) : m_mask(mask) {}
831 template<
typename... Components>
832 static std::unique_ptr<Archetype> from_columns() {
833 ComponentMask mask = compute_mask<Components...>();
834 auto archetype = std::make_unique<Archetype>(Archetype(mask));
835 (archetype->add_column<Components>(), ...);
836 return std::move(archetype);
839 template<
typename... NewComponents>
840 static std::unique_ptr<Archetype>
841 from_archetype(
const Archetype& old_archetype) {
842 ComponentMask new_components_mask =
843 compute_mask<NewComponents...>();
844 ComponentMask combined_mask =
845 old_archetype.m_mask | new_components_mask;
848 std::make_unique<Archetype>(Archetype(combined_mask));
850 for (
const auto& [component_id, column_index] :
851 old_archetype.m_type_to_column) {
852 auto& component = old_archetype.m_columns[column_index];
853 new_archetype->m_columns.emplace_back(component->clone_empty());
854 new_archetype->m_type_to_column[component_id] =
855 new_archetype->m_columns.size() - 1;
858 (new_archetype->add_column<NewComponents>(), ...);
860 return new_archetype;
865 ComponentId
id = TypeIDGenerator::get_type_id<T>();
866 m_columns.push_back(std::make_unique<ComponentColumn<T>>());
867 m_type_to_column[id] = m_columns.size() - 1;
871 void add_row(
size_t row, T&& component) {
872 static const ComponentId
id = TypeIDGenerator::get_type_id<T>();
874 auto it = m_type_to_column.find(
id);
875 if (it == m_type_to_column.end()) {
876 printf(
"Error: column does not exist in archetype\n");
880 auto* column =
static_cast<ComponentColumn<T>*
>(
881 m_columns[m_type_to_column[id]].get()
884 if (column->data.size() <= row) {
885 column->data.resize(row + 1);
888 column->data[row] = std::forward<T>(component);
891 template<
typename... Components>
892 void update_components(Entity entity, Components&&... components) {
893 (update_row<Components>(entity, components), ...);
897 void update_row(Entity entity, T&& component) {
898 static const ComponentId
id = TypeIDGenerator::get_type_id<T>();
900 auto it = m_type_to_column.find(
id);
901 if (it == m_type_to_column.end()) {
902 printf(
"error: coulmn does not exist in archetype\n");
906 auto* column =
static_cast<ComponentColumn<T>*
>(
907 m_columns[m_type_to_column[id]].get()
910 auto row_it = m_entity_to_index.find(entity);
912 if (row_it == m_entity_to_index.end()) {
913 printf(
"error: row does not exist in archetype\n");
917 column->data[row_it->second] = std::forward<T>(component);
920 template<
typename... Components>
921 bool has_components()
const {
922 auto mask = compute_mask<Components...>();
923 return has_components(mask);
926 bool has_components(ComponentMask mask)
const {
928 return m_mask.contains(mask);
931 template<
typename... Components>
932 void add_entity(Entity entity, Components&&... components) {
933 size_t row = m_next_available_row;
934 m_entity_to_index[entity] = row;
935 (add_row<Components>(row, std::forward<Components>(components)),
937 ++m_next_available_row;
940 void remove_entity(Entity entity) {
941 auto it = m_entity_to_index.find(entity);
942 if (it == m_entity_to_index.end()) {
945 size_t row = it->second;
946 size_t last_row = m_next_available_row - 1;
947 if (row != last_row) {
948 for (
auto& column : m_columns) {
949 column->swap(row, last_row);
951 for (
auto& pair : m_entity_to_index) {
952 if (pair.second == last_row) {
959 --m_next_available_row;
961 for (
auto& column : m_columns) {
965 m_entity_to_index.erase(it);
968 struct TypeErasedComponentColumn {
969 virtual ~TypeErasedComponentColumn() =
default;
970 virtual std::unique_ptr<TypeErasedComponentColumn>
971 clone_empty()
const = 0;
972 virtual void copy_component_to(
973 TypeErasedComponentColumn* target_column,
977 virtual void swap(
size_t index1,
size_t index2) = 0;
978 virtual void pop_back() = 0;
982 struct ComponentColumn: TypeErasedComponentColumn {
983 using StorageType =
typename std::decay<T>::type;
985 std::vector<StorageType> data;
987 std::unique_ptr<TypeErasedComponentColumn>
988 clone_empty()
const override {
989 return std::make_unique<ComponentColumn<T>>();
992 void copy_component_to(
993 TypeErasedComponentColumn* target_column,
997 auto* target =
static_cast<ComponentColumn<T>*
>(target_column);
998 if (target->data.size() <= to_index) {
999 target->data.resize(to_index + 1);
1001 target->data[to_index] = this->data[from_index];
1004 void swap(
size_t index1,
size_t index2)
override {
1005 std::swap(data[index1], data[index2]);
1008 void pop_back()
override {
1013 template<
typename... NewComponents>
1015 Archetype* target_archetype,
1017 NewComponents&&... new_components
1019 auto it = m_entity_to_index.find(entity);
1020 if (it == m_entity_to_index.end()) {
1021 printf(
"Error: Entity not found in archetype during move.\n");
1024 size_t source_row = it->second;
1025 size_t target_row = target_archetype->m_next_available_row;
1026 target_archetype->m_entity_to_index[entity] = target_row;
1028 for (
const auto& [component_id, column_index] : m_type_to_column) {
1029 auto& src_column = m_columns[column_index];
1031 target_archetype->m_type_to_column.find(component_id);
1032 if (target_it != target_archetype->m_type_to_column.end()) {
1033 size_t target_column_index = target_it->second;
1034 auto& target_column =
1035 target_archetype->m_columns[target_column_index];
1038 src_column->copy_component_to(
1039 target_column.get(),
1047 (target_archetype->add_row<NewComponents>(
1049 std::forward<NewComponents>(new_components)
1054 ++target_archetype->m_next_available_row;
1057 ComponentMask m_mask;
1059 size_t m_next_available_row {0};
1060 storage::dense_map<ComponentId, size_t> m_type_to_column;
1061 storage::dense_map<Entity, size_t> m_entity_to_index;
1062 std::vector<std::unique_ptr<TypeErasedComponentColumn>> m_columns;
1065 void notify_add(
const ComponentMask& mask, Entity entity) {
1066 for (
const auto& observer : m_observers) {
1067 if (mask.contains(observer->mask())) {
1068 observer->add(entity);
1073 void notify_insert(
const ComponentMask& mask, Entity entity) {
1074 for (
const auto& observer : m_observers) {
1075 if (mask.contains(observer->mask())) {
1076 observer->insert(entity);
1081 void notify_remove(
const ComponentMask& mask, Entity entity) {
1082 for (
const auto& observer : m_observers) {
1083 if (mask.contains(observer->mask())) {
1084 observer->remove(entity);
1089 enum class AddFlags { None = 0, Add = 1 << 0, Insert = 1 << 1 };
1091 friend inline AddFlags operator|(AddFlags a, AddFlags b) {
1092 return static_cast<AddFlags
>(
static_cast<int>(a) |
static_cast<int>(b));
1095 friend inline AddFlags operator&(AddFlags a, AddFlags b) {
1096 return static_cast<AddFlags
>(
static_cast<int>(a) &
static_cast<int>(b));
1099 template<
typename... Components>
1100 AddFlags add_components(Entity entity, Components&&... components) {
1101 auto new_components_mask = compute_mask<Components...>();
1102 ComponentMask combined_mask = new_components_mask;
1104 AddFlags flags = AddFlags::None;
1106 Archetype* current_archetype =
nullptr;
1107 auto entity_it = m_entity_archetype_map.find(entity);
1108 if (entity_it != m_entity_archetype_map.end()) {
1109 current_archetype = entity_it->second;
1110 combined_mask = current_archetype->m_mask | new_components_mask;
1113 if (current_archetype->m_mask.contains(new_components_mask)) {
1114 current_archetype->update_components(entity, components...);
1115 notify_insert(combined_mask, entity);
1116 return AddFlags::Insert;
1121 Archetype* target_archetype =
nullptr;
1122 auto archetype_it = m_archetype_map.find(combined_mask);
1123 if (archetype_it != m_archetype_map.end()) {
1125 target_archetype = archetype_it->second;
1128 if (current_archetype ==
nullptr) {
1129 auto new_archetype = Archetype::from_columns<Components...>();
1130 target_archetype = new_archetype.get();
1131 m_archetypes.push_back(std::move(new_archetype));
1132 m_archetype_map[combined_mask] = target_archetype;
1134 auto new_archetype =
1135 Archetype::from_archetype<Components...>(*current_archetype
1137 target_archetype = new_archetype.get();
1138 m_archetypes.push_back(std::move(new_archetype));
1139 m_archetype_map[combined_mask] = target_archetype;
1143 if (current_archetype !=
nullptr) {
1144 current_archetype->move_entity(
1147 std::forward<Components>(components)...
1149 notify_add(combined_mask, entity);
1150 notify_insert(combined_mask, entity);
1151 flags = AddFlags::Add | AddFlags::Insert;
1153 current_archetype->remove_entity(entity);
1155 target_archetype->add_entity(
1157 std::forward<Components>(components)...
1159 notify_add(combined_mask, entity);
1160 notify_insert(combined_mask, entity);
1162 flags = AddFlags::Add | AddFlags::Insert;
1164 m_entity_archetype_map[entity] = target_archetype;
1170 template<
typename Component>
1171 void remove_component(Entity entity) {
1172 auto entity_it = m_entity_archetype_map.find(entity);
1173 if (entity_it == m_entity_archetype_map.end()) {
1177 Archetype* current_archetype = entity_it->second;
1179 ComponentMask new_mask = current_archetype->m_mask;
1180 ComponentId component_id = TypeIDGenerator::get_type_id<Component>();
1182 if (!new_mask.test(component_id)) {
1186 new_mask.reset(component_id);
1189 Archetype* target_archetype =
nullptr;
1190 auto archetype_it = m_archetype_map.find(new_mask);
1191 if (archetype_it != m_archetype_map.end()) {
1192 target_archetype = archetype_it->second;
1195 target_archetype =
new Archetype(new_mask);
1198 for (
const auto& [type_id, column_idx] :
1199 current_archetype->m_type_to_column) {
1200 if (type_id != component_id) {
1201 size_t new_idx = target_archetype->m_columns.size();
1202 target_archetype->m_columns.push_back(
1203 current_archetype->m_columns[column_idx]->clone_empty()
1205 target_archetype->m_type_to_column[type_id] = new_idx;
1208 m_archetypes.push_back(std::unique_ptr<Archetype>(target_archetype)
1210 m_archetype_map[new_mask] = target_archetype;
1214 size_t entity_index = current_archetype->m_entity_to_index[entity];
1215 size_t target_index = target_archetype->m_entity_to_index.size();
1218 for (
const auto& [type_id, src_column_idx] :
1219 current_archetype->m_type_to_column) {
1220 if (type_id != component_id) {
1221 auto target_column_idx =
1222 target_archetype->m_type_to_column[type_id];
1223 current_archetype->m_columns[src_column_idx]->copy_component_to(
1224 target_archetype->m_columns[target_column_idx].get(),
1231 notify_remove(current_archetype->m_mask, entity);
1233 target_archetype->m_entity_to_index[entity] = target_index;
1234 current_archetype->remove_entity(entity);
1235 m_entity_archetype_map[entity] = target_archetype;
1239 inline void execute_schedule(ScheduleLabel label) {
1240 for (
const auto& system : get_systems(label)) {
1241 system->execute(*
this);
1245 inline void execute_commands();
1247 inline void execute_progress() {
1248 execute_schedule(ScheduleLabel::Startup);
1249 execute_schedule(ScheduleLabel::PreUpdate);
1250 execute_schedule(ScheduleLabel::Update);
1251 execute_schedule(ScheduleLabel::Validate);
1252 execute_schedule(ScheduleLabel::PostUpdate);
1253 execute_schedule(ScheduleLabel::PreStore);
1254 execute_schedule(ScheduleLabel::Store);
1256 for (
const auto& observer : m_observers) {
1262 get_systems(ScheduleLabel::Startup).clear();
1266 std::chrono::high_resolution_clock::time_point m_last_time;
1268 inline std::vector<std::unique_ptr<TypeErasedSystem>>&
1269 get_systems(ScheduleLabel label) {
1270 return m_systems[
static_cast<std::underlying_type_t<ScheduleLabel>
>(
1276 std::underlying_type_t<ScheduleLabel>,
1277 std::vector<std::unique_ptr<TypeErasedSystem>>>
1285 std::unordered_map<std::type_index, std::unique_ptr<TypeErasedResource>>
1288 Entity m_current_entity_id {0};
1289 unsigned int m_query_version {0};
1290 std::vector<std::unique_ptr<Archetype>> m_archetypes;
1291 std::unordered_map<ComponentMask, Archetype*> m_archetype_map;
1292 storage::dense_map<Entity, Archetype*> m_entity_archetype_map;
1293 std::vector<std::unique_ptr<TypeErasedObserver>> m_observers;
1294 std::unique_ptr<Commands> m_commands;
1295 std::vector<Entity> m_free_list;