Skip to content

Commit b40eab7

Browse files
authored
Added create and destroy from core changes in the runtime (#35)
1 parent 3cd9516 commit b40eab7

File tree

9 files changed

+227
-12
lines changed

9 files changed

+227
-12
lines changed

.vscode/launch.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"request": "launch",
77
"program": "${workspaceFolder}/bazel-bin/runtime/test/test",
88
"cwd": "${workspaceFolder}",
9-
"args": [],
9+
"args": [
10+
"--gtest_break_on_failure"
11+
],
1012
"type": "cppdbg",
1113
"windows": {
1214
"type": "cppvsdbg",

WORKSPACE.bazel

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ http_archive(
2323
url = "https://github.com/ecsact-dev/ecsact_lang_cpp/archive/b1fa28b445b98d5ba62ede19cd6a5bdfa51141be.zip",
2424
)
2525

26+
http_archive(
27+
name = "ecsact_runtime",
28+
sha256 = "ab8270dfbe7fb6360e3b395fb3ad141a99d18b43bb0f3a897cf04e8a736036b8",
29+
strip_prefix = "ecsact_runtime-94b3c740e69b1bc1d35ec3dd8218e80d6bf8fa00",
30+
url = "https://github.com/ecsact-dev/ecsact_runtime/archive/94b3c740e69b1bc1d35ec3dd8218e80d6bf8fa00.zip",
31+
)
32+
2633
load("@rules_ecsact//ecsact:repositories.bzl", "ecsact_register_toolchains", "rules_ecsact_dependencies")
2734

2835
rules_ecsact_dependencies()
@@ -47,13 +54,6 @@ load("@boost//:index.bzl", "boost_http_archives")
4754

4855
boost_http_archives()
4956

50-
http_archive(
51-
name = "ecsact_runtime",
52-
sha256 = "80b722a8790447627b621877c171a96d5e7d09005bfbed7d8b388cb37cefa7b6",
53-
strip_prefix = "ecsact_runtime-f7ee18fe96c4400672caccf5475835d54281582c",
54-
url = "https://github.com/ecsact-dev/ecsact_runtime/archive/f7ee18fe96c4400672caccf5475835d54281582c.zip",
55-
)
56-
5757
http_archive(
5858
name = "hedron_compile_commands",
5959
sha256 = "4b251a482a85de6c5cb0dc34c5671e73190b9ff348e9979fa2c033d81de0f928",

ecsact/entt/detail/execution_events_collector.hh

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ struct execution_events_collector {
2020
return target->remove_callback != nullptr;
2121
}
2222

23+
inline bool has_entity_created_callback() const {
24+
return target->entity_created_callback != nullptr;
25+
}
26+
27+
inline bool has_entity_destroyed_callback() const {
28+
return target->entity_destroyed_callback != nullptr;
29+
}
30+
2331
template<typename C>
2432
requires(!std::is_empty_v<C>)
2533
void invoke_init_callback(ecsact_entity_id entity, const C& component) {
@@ -91,6 +99,22 @@ struct execution_events_collector {
9199
target->remove_callback_user_data
92100
);
93101
}
102+
103+
void invoke_entity_created_callback(ecsact_entity_id entity) {
104+
target->entity_created_callback(
105+
ECSACT_EVENT_CREATE_ENTITY,
106+
static_cast<ecsact_entity_id>(entity),
107+
target->entity_created_callback_user_data
108+
);
109+
}
110+
111+
void invoke_entity_destroyed_callback(ecsact_entity_id entity) {
112+
target->entity_destroyed_callback(
113+
ECSACT_EVENT_DESTROY_ENTITY,
114+
static_cast<ecsact_entity_id>(entity),
115+
target->entity_destroyed_callback_user_data
116+
);
117+
}
94118
};
95119

96120
} // namespace ecsact_entt_rt

ecsact/entt/detail/internal_markers.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,8 @@ struct pending_add<C> {
5656
template<typename C>
5757
struct pending_remove {};
5858

59+
struct created_entity {};
60+
61+
struct destroyed_entity {};
62+
5963
} // namespace ecsact::entt::detail

ecsact/entt/detail/registry_info.hh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,13 @@ struct registry_info {
199199
return _create_entity();
200200
}
201201

202+
inline void destroy_entity(ecsact_entity_id entity_id) {
203+
auto entt_entity_id = entities_map.at(entity_id);
204+
205+
registry.destroy(entt_entity_id);
206+
entities_map.erase(entity_id);
207+
}
208+
202209
entt::entity get_entt_entity_id(ecsact_entity_id ecsact_entity_id) const {
203210
return entities_map.at(ecsact_entity_id);
204211
}

ecsact/entt/detail/system_execution_context.hh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,9 +341,11 @@ struct system_execution_context : system_execution_context_base {
341341
) {
342342
using boost::mp11::mp_for_each;
343343
using ecsact::entt::component_added;
344+
using ecsact::entt::detail::created_entity;
344345
using ecsact::entt::detail::pending_add;
345346

346347
auto new_entity = info.create_entity().entt_entity_id;
348+
info.registry.template emplace<created_entity>(new_entity);
347349
for(int i = 0; component_count > i; ++i) {
348350
auto component_id = component_ids[i];
349351
auto component_data = components_data[i];

ecsact/entt/runtime.hh

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,13 @@ public:
138138
using boost::mp11::mp_for_each;
139139

140140
auto& info = _registries.at(reg_id);
141-
auto entt_entity_id = info.entities_map.at(entity_id);
142141

143-
info.registry.destroy(entt_entity_id);
144-
info.entities_map.erase(entity_id);
142+
info.destroy_entity(entity_id);
145143
}
146144

147145
int count_entities(ecsact_registry_id reg_id) {
148146
auto& info = _registries.at(reg_id);
149-
return static_cast<int>(info.registry.size());
147+
return static_cast<int>(info.registry.alive());
150148
}
151149

152150
std::vector<ecsact_entity_id> get_entities(ecsact_registry_id reg_id) {
@@ -855,6 +853,10 @@ private:
855853
using boost::mp11::mp_for_each;
856854
using detail::beforechange_storage;
857855

856+
if(!events_collector.has_update_callback()) {
857+
return;
858+
}
859+
858860
mp_for_each<typename package::components>([&]<typename C>(C) {
859861
if constexpr(!C::transient && !std::is_empty_v<C>) {
860862
::entt::basic_view changed_view{
@@ -886,6 +888,10 @@ private:
886888
) {
887889
using boost::mp11::mp_for_each;
888890

891+
if(!events_collector.has_remove_callback()) {
892+
return;
893+
}
894+
889895
mp_for_each<typename package::components>([&]<typename C>(C) {
890896
if constexpr(C::transient) {
891897
return;
@@ -918,6 +924,50 @@ private:
918924
});
919925
}
920926

927+
void _trigger_create_entity_event(
928+
registry_info& info,
929+
execution_events_collector& events_collector
930+
) {
931+
using boost::mp11::mp_for_each;
932+
using ecsact::entt::detail::created_entity;
933+
934+
if(!events_collector.has_entity_created_callback()) {
935+
return;
936+
}
937+
938+
::entt::basic_view created_view{
939+
info.registry.template storage<created_entity>(),
940+
};
941+
942+
for(entt_entity_type entity : created_view) {
943+
events_collector.invoke_entity_created_callback(
944+
info.get_ecsact_entity_id(entity)
945+
);
946+
}
947+
}
948+
949+
void _trigger_destroy_entity_event(
950+
registry_info& info,
951+
execution_events_collector& events_collector
952+
) {
953+
using boost::mp11::mp_for_each;
954+
using ecsact::entt::detail::destroyed_entity;
955+
956+
if(!events_collector.has_entity_destroyed_callback()) {
957+
return;
958+
}
959+
960+
::entt::basic_view destroy_view{
961+
info.registry.template storage<destroyed_entity>(),
962+
};
963+
964+
for(entt_entity_type entity : destroy_view) {
965+
events_collector.invoke_entity_destroyed_callback(
966+
info.get_ecsact_entity_id(entity)
967+
);
968+
}
969+
}
970+
921971
void _execute_systems(registry_info& info, actions_span_t& actions) {
922972
using boost::mp11::mp_for_each;
923973

@@ -1045,6 +1095,35 @@ private:
10451095
registry_info& info
10461096
) {
10471097
using boost::mp11::mp_for_each;
1098+
using ecsact::entt::detail::created_entity;
1099+
using ecsact::entt::detail::destroyed_entity;
1100+
1101+
for(int i = 0; options.create_entities_length > i; i++) {
1102+
auto entity = info.create_entity().entt_entity_id;
1103+
info.registry.template emplace<created_entity>(entity);
1104+
1105+
for(int j = 0; options.create_entities_components_length[i] > j; j++) {
1106+
const ecsact_component& comp = options.create_entities_components[i][j];
1107+
1108+
mp_for_each<typename package::components>([&]<typename C>(C) {
1109+
if constexpr(C::transient) {
1110+
return;
1111+
}
1112+
1113+
if(comp.component_id == static_cast<ecsact_component_id>(C::id)) {
1114+
if constexpr(std::is_empty_v<C>) {
1115+
_pre_exec_add_component<C>(info, entity);
1116+
} else {
1117+
_pre_exec_add_component<C>(
1118+
info,
1119+
entity,
1120+
*static_cast<const C*>(comp.component_data)
1121+
);
1122+
}
1123+
}
1124+
});
1125+
}
1126+
}
10481127

10491128
for(int i = 0; options.add_components_length > i; ++i) {
10501129
const ecsact_entity_id& entity = options.add_components_entities[i];
@@ -1112,10 +1191,30 @@ private:
11121191
}
11131192
});
11141193
}
1194+
1195+
for(int i = 0; options.destroy_entities_length > i; ++i) {
1196+
const ecsact_entity_id& entity = options.destroy_entities[i];
1197+
mp_for_each<typename package::components>([&]<typename C>(C) {
1198+
if constexpr(C::transient) {
1199+
return;
1200+
}
1201+
if(info.registry.template all_of<C>(info.get_entt_entity_id(entity))) {
1202+
_pre_exec_remove_component<C>(
1203+
info,
1204+
info.entities_map.at(static_cast<ecsact_entity_id>(entity))
1205+
);
1206+
}
1207+
});
1208+
auto entt_id = info.get_entt_entity_id(entity);
1209+
info.registry.template emplace<destroyed_entity>(entt_id);
1210+
info.destroy_entity(entity);
1211+
}
11151212
}
11161213

11171214
void _clear_event_markers(registry_info& info) {
11181215
using boost::mp11::mp_for_each;
1216+
using ecsact::entt::detail::created_entity;
1217+
using ecsact::entt::detail::destroyed_entity;
11191218

11201219
mp_for_each<typename package::components>([&]<typename C>(C) {
11211220
if constexpr(C::transient) {
@@ -1140,6 +1239,9 @@ private:
11401239

11411240
info.registry.template clear<component_removed<C>>();
11421241
});
1242+
1243+
info.registry.template clear<created_entity>();
1244+
info.registry.template clear<destroyed_entity>();
11431245
}
11441246

11451247
auto _validate_action(ecsact_registry_id registry_id, ecsact_action& action)
@@ -1223,9 +1325,11 @@ public:
12231325
_clear_transients(info);
12241326
}
12251327
if(events_collector) {
1328+
_trigger_create_entity_event(info, *events_collector);
12261329
_trigger_init_component_events(info, *events_collector);
12271330
_trigger_update_component_events(info, *events_collector);
12281331
_trigger_remove_component_events(info, *events_collector);
1332+
_trigger_destroy_entity_event(info, *events_collector);
12291333
}
12301334
_clear_event_markers(info);
12311335

runtime/test/runtime_test.cc

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,74 @@ TEST(Core, DynamicSystemImpl) {
717717
EXPECT_EQ(comp_get.a, comp.a);
718718
}
719719

720+
TEST(Core, CreateAndDestroyEntity) {
721+
auto reg = ecsact::core::registry("CreateAndDestroyEntity");
722+
723+
runtime_test::EntityTesting component_a{.a = 6};
724+
725+
ecsact_component my_component_a{
726+
.component_id = runtime_test::EntityTesting::id,
727+
.component_data = &component_a,
728+
};
729+
730+
auto options = ecsact_execution_options{};
731+
732+
std::array<ecsact_component, 1> entity_component = {my_component_a};
733+
734+
std::array<int, 1> entity_component_length = {entity_component.size()};
735+
736+
std::vector<ecsact_component*> pointer_vector{};
737+
738+
pointer_vector.push_back(entity_component.data());
739+
740+
options.create_entities_components = pointer_vector.data();
741+
options.create_entities_components_length = entity_component_length.data();
742+
options.create_entities_length = entity_component_length.size();
743+
744+
auto evc = ecsact_execution_events_collector{};
745+
746+
struct callback_info {
747+
ecsact_entity_id entity_id;
748+
bool entity_created = false;
749+
};
750+
751+
auto info = callback_info{};
752+
753+
evc.entity_created_callback_user_data = &info;
754+
755+
auto entity_created_callback = //
756+
[](
757+
ecsact_event event,
758+
ecsact_entity_id entity_id,
759+
void* callback_user_data
760+
) {
761+
auto& info = *static_cast<callback_info*>(callback_user_data);
762+
info.entity_created = true;
763+
info.entity_id = entity_id;
764+
};
765+
766+
evc.entity_created_callback = entity_created_callback;
767+
768+
ecsact_execute_systems(reg.id(), 1, &options, &evc);
769+
770+
ASSERT_EQ(ecsact_count_entities(reg.id()), 1);
771+
772+
auto comp = reg.get_component<runtime_test::EntityTesting>(info.entity_id);
773+
774+
ASSERT_EQ(comp.a, 6);
775+
776+
ecsact_execution_options delete_options{};
777+
778+
auto entity_vector = std::vector<ecsact_entity_id>{info.entity_id};
779+
780+
delete_options.destroy_entities = entity_vector.data();
781+
delete_options.destroy_entities_length = entity_vector.size();
782+
783+
ecsact_execute_systems(reg.id(), 1, &delete_options, nullptr);
784+
785+
ASSERT_EQ(ecsact_count_entities(reg.id()), 0);
786+
}
787+
720788
#ifdef ECSACT_ENTT_TEST_STATIC_SYSTEM_IMPL
721789
TEST(Core, StaticSystemImpl) {
722790
auto reg_id = ecsact_create_registry("StaticSystemImpl");

runtime/test/runtime_test.ecsact

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,7 @@ system AttackDamageWeakened {
100100
readonly Weakened;
101101
}
102102
}
103+
104+
component EntityTesting {
105+
i32 a;
106+
}

0 commit comments

Comments
 (0)