Skip to content

Added create and destroy from core changes in the runtime #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"request": "launch",
"program": "${workspaceFolder}/bazel-bin/runtime/test/test",
"cwd": "${workspaceFolder}",
"args": [],
"args": [
"--gtest_break_on_failure"
],
"type": "cppdbg",
"windows": {
"type": "cppvsdbg",
Expand Down
14 changes: 7 additions & 7 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ http_archive(
url = "https://github.com/ecsact-dev/ecsact_lang_cpp/archive/b1fa28b445b98d5ba62ede19cd6a5bdfa51141be.zip",
)

http_archive(
name = "ecsact_runtime",
sha256 = "ab8270dfbe7fb6360e3b395fb3ad141a99d18b43bb0f3a897cf04e8a736036b8",
strip_prefix = "ecsact_runtime-94b3c740e69b1bc1d35ec3dd8218e80d6bf8fa00",
url = "https://github.com/ecsact-dev/ecsact_runtime/archive/94b3c740e69b1bc1d35ec3dd8218e80d6bf8fa00.zip",
)

load("@rules_ecsact//ecsact:repositories.bzl", "ecsact_register_toolchains", "rules_ecsact_dependencies")

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

boost_http_archives()

http_archive(
name = "ecsact_runtime",
sha256 = "80b722a8790447627b621877c171a96d5e7d09005bfbed7d8b388cb37cefa7b6",
strip_prefix = "ecsact_runtime-f7ee18fe96c4400672caccf5475835d54281582c",
url = "https://github.com/ecsact-dev/ecsact_runtime/archive/f7ee18fe96c4400672caccf5475835d54281582c.zip",
)

http_archive(
name = "hedron_compile_commands",
sha256 = "4b251a482a85de6c5cb0dc34c5671e73190b9ff348e9979fa2c033d81de0f928",
Expand Down
24 changes: 24 additions & 0 deletions ecsact/entt/detail/execution_events_collector.hh
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ struct execution_events_collector {
return target->remove_callback != nullptr;
}

inline bool has_entity_created_callback() const {
return target->entity_created_callback != nullptr;
}

inline bool has_entity_destroyed_callback() const {
return target->entity_destroyed_callback != nullptr;
}

template<typename C>
requires(!std::is_empty_v<C>)
void invoke_init_callback(ecsact_entity_id entity, const C& component) {
Expand Down Expand Up @@ -91,6 +99,22 @@ struct execution_events_collector {
target->remove_callback_user_data
);
}

void invoke_entity_created_callback(ecsact_entity_id entity) {
target->entity_created_callback(
ECSACT_EVENT_CREATE_ENTITY,
static_cast<ecsact_entity_id>(entity),
target->entity_created_callback_user_data
);
}

void invoke_entity_destroyed_callback(ecsact_entity_id entity) {
target->entity_destroyed_callback(
ECSACT_EVENT_DESTROY_ENTITY,
static_cast<ecsact_entity_id>(entity),
target->entity_destroyed_callback_user_data
);
}
};

} // namespace ecsact_entt_rt
4 changes: 4 additions & 0 deletions ecsact/entt/detail/internal_markers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ struct pending_add<C> {
template<typename C>
struct pending_remove {};

struct created_entity {};

struct destroyed_entity {};

} // namespace ecsact::entt::detail
7 changes: 7 additions & 0 deletions ecsact/entt/detail/registry_info.hh
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,13 @@ struct registry_info {
return _create_entity();
}

inline void destroy_entity(ecsact_entity_id entity_id) {
auto entt_entity_id = entities_map.at(entity_id);

registry.destroy(entt_entity_id);
entities_map.erase(entity_id);
}

entt::entity get_entt_entity_id(ecsact_entity_id ecsact_entity_id) const {
return entities_map.at(ecsact_entity_id);
}
Expand Down
2 changes: 2 additions & 0 deletions ecsact/entt/detail/system_execution_context.hh
Original file line number Diff line number Diff line change
Expand Up @@ -341,9 +341,11 @@ struct system_execution_context : system_execution_context_base {
) {
using boost::mp11::mp_for_each;
using ecsact::entt::component_added;
using ecsact::entt::detail::created_entity;
using ecsact::entt::detail::pending_add;

auto new_entity = info.create_entity().entt_entity_id;
info.registry.template emplace<created_entity>(new_entity);
for(int i = 0; component_count > i; ++i) {
auto component_id = component_ids[i];
auto component_data = components_data[i];
Expand Down
112 changes: 108 additions & 4 deletions ecsact/entt/runtime.hh
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,13 @@ public:
using boost::mp11::mp_for_each;

auto& info = _registries.at(reg_id);
auto entt_entity_id = info.entities_map.at(entity_id);

info.registry.destroy(entt_entity_id);
info.entities_map.erase(entity_id);
info.destroy_entity(entity_id);
}

int count_entities(ecsact_registry_id reg_id) {
auto& info = _registries.at(reg_id);
return static_cast<int>(info.registry.size());
return static_cast<int>(info.registry.alive());
}

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

if(!events_collector.has_update_callback()) {
return;
}

mp_for_each<typename package::components>([&]<typename C>(C) {
if constexpr(!C::transient && !std::is_empty_v<C>) {
::entt::basic_view changed_view{
Expand Down Expand Up @@ -886,6 +888,10 @@ private:
) {
using boost::mp11::mp_for_each;

if(!events_collector.has_remove_callback()) {
return;
}

mp_for_each<typename package::components>([&]<typename C>(C) {
if constexpr(C::transient) {
return;
Expand Down Expand Up @@ -918,6 +924,50 @@ private:
});
}

void _trigger_create_entity_event(
registry_info& info,
execution_events_collector& events_collector
) {
using boost::mp11::mp_for_each;
using ecsact::entt::detail::created_entity;

if(!events_collector.has_entity_created_callback()) {
return;
}

::entt::basic_view created_view{
info.registry.template storage<created_entity>(),
};

for(entt_entity_type entity : created_view) {
events_collector.invoke_entity_created_callback(
info.get_ecsact_entity_id(entity)
);
}
}

void _trigger_destroy_entity_event(
registry_info& info,
execution_events_collector& events_collector
) {
using boost::mp11::mp_for_each;
using ecsact::entt::detail::destroyed_entity;

if(!events_collector.has_entity_destroyed_callback()) {
return;
}

::entt::basic_view destroy_view{
info.registry.template storage<destroyed_entity>(),
};

for(entt_entity_type entity : destroy_view) {
events_collector.invoke_entity_destroyed_callback(
info.get_ecsact_entity_id(entity)
);
}
}

void _execute_systems(registry_info& info, actions_span_t& actions) {
using boost::mp11::mp_for_each;

Expand Down Expand Up @@ -1045,6 +1095,35 @@ private:
registry_info& info
) {
using boost::mp11::mp_for_each;
using ecsact::entt::detail::created_entity;
using ecsact::entt::detail::destroyed_entity;

for(int i = 0; options.create_entities_length > i; i++) {
auto entity = info.create_entity().entt_entity_id;
info.registry.template emplace<created_entity>(entity);

for(int j = 0; options.create_entities_components_length[i] > j; j++) {
const ecsact_component& comp = options.create_entities_components[i][j];

mp_for_each<typename package::components>([&]<typename C>(C) {
if constexpr(C::transient) {
return;
}

if(comp.component_id == static_cast<ecsact_component_id>(C::id)) {
if constexpr(std::is_empty_v<C>) {
_pre_exec_add_component<C>(info, entity);
} else {
_pre_exec_add_component<C>(
info,
entity,
*static_cast<const C*>(comp.component_data)
);
}
}
});
}
}

for(int i = 0; options.add_components_length > i; ++i) {
const ecsact_entity_id& entity = options.add_components_entities[i];
Expand Down Expand Up @@ -1112,10 +1191,30 @@ private:
}
});
}

for(int i = 0; options.destroy_entities_length > i; ++i) {
const ecsact_entity_id& entity = options.destroy_entities[i];
mp_for_each<typename package::components>([&]<typename C>(C) {
if constexpr(C::transient) {
return;
}
if(info.registry.template all_of<C>(info.get_entt_entity_id(entity))) {
_pre_exec_remove_component<C>(
info,
info.entities_map.at(static_cast<ecsact_entity_id>(entity))
);
}
});
auto entt_id = info.get_entt_entity_id(entity);
info.registry.template emplace<destroyed_entity>(entt_id);
info.destroy_entity(entity);
}
}

void _clear_event_markers(registry_info& info) {
using boost::mp11::mp_for_each;
using ecsact::entt::detail::created_entity;
using ecsact::entt::detail::destroyed_entity;

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

info.registry.template clear<component_removed<C>>();
});

info.registry.template clear<created_entity>();
info.registry.template clear<destroyed_entity>();
}

auto _validate_action(ecsact_registry_id registry_id, ecsact_action& action)
Expand Down Expand Up @@ -1223,9 +1325,11 @@ public:
_clear_transients(info);
}
if(events_collector) {
_trigger_create_entity_event(info, *events_collector);
_trigger_init_component_events(info, *events_collector);
_trigger_update_component_events(info, *events_collector);
_trigger_remove_component_events(info, *events_collector);
_trigger_destroy_entity_event(info, *events_collector);
}
_clear_event_markers(info);

Expand Down
68 changes: 68 additions & 0 deletions runtime/test/runtime_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,74 @@ TEST(Core, DynamicSystemImpl) {
EXPECT_EQ(comp_get.a, comp.a);
}

TEST(Core, CreateAndDestroyEntity) {
auto reg = ecsact::core::registry("CreateAndDestroyEntity");

runtime_test::EntityTesting component_a{.a = 6};

ecsact_component my_component_a{
.component_id = runtime_test::EntityTesting::id,
.component_data = &component_a,
};

auto options = ecsact_execution_options{};

std::array<ecsact_component, 1> entity_component = {my_component_a};

std::array<int, 1> entity_component_length = {entity_component.size()};

std::vector<ecsact_component*> pointer_vector{};

pointer_vector.push_back(entity_component.data());

options.create_entities_components = pointer_vector.data();
options.create_entities_components_length = entity_component_length.data();
options.create_entities_length = entity_component_length.size();

auto evc = ecsact_execution_events_collector{};

struct callback_info {
ecsact_entity_id entity_id;
bool entity_created = false;
};

auto info = callback_info{};

evc.entity_created_callback_user_data = &info;

auto entity_created_callback = //
[](
ecsact_event event,
ecsact_entity_id entity_id,
void* callback_user_data
) {
auto& info = *static_cast<callback_info*>(callback_user_data);
info.entity_created = true;
info.entity_id = entity_id;
};

evc.entity_created_callback = entity_created_callback;

ecsact_execute_systems(reg.id(), 1, &options, &evc);

ASSERT_EQ(ecsact_count_entities(reg.id()), 1);

auto comp = reg.get_component<runtime_test::EntityTesting>(info.entity_id);

ASSERT_EQ(comp.a, 6);

ecsact_execution_options delete_options{};

auto entity_vector = std::vector<ecsact_entity_id>{info.entity_id};

delete_options.destroy_entities = entity_vector.data();
delete_options.destroy_entities_length = entity_vector.size();

ecsact_execute_systems(reg.id(), 1, &delete_options, nullptr);

ASSERT_EQ(ecsact_count_entities(reg.id()), 0);
}

#ifdef ECSACT_ENTT_TEST_STATIC_SYSTEM_IMPL
TEST(Core, StaticSystemImpl) {
auto reg_id = ecsact_create_registry("StaticSystemImpl");
Expand Down
4 changes: 4 additions & 0 deletions runtime/test/runtime_test.ecsact
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,7 @@ system AttackDamageWeakened {
readonly Weakened;
}
}

component EntityTesting {
i32 a;
}