diff --git a/ecsact/entt/detail/id_map.hh b/ecsact/entt/detail/id_map.hh new file mode 100644 index 0000000..b518c4f --- /dev/null +++ b/ecsact/entt/detail/id_map.hh @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include + +namespace ecsact::entt::detail { + +/** + * + */ +template +class id_map { +public: + using key_type = KeyT; + using value_type = ValueT; + using underlying_key_type = std::underlying_type_t; + + static constexpr auto min_key_value() -> underlying_key_type { + return static_cast(MinKeyValue); + } + + static constexpr auto max_key_value() -> underlying_key_type { + return static_cast(MaxKeyValue); + } + + static_assert( + max_key_value() > min_key_value(), + "id_map MaxKeyValue must be > MinKeyValue" + ); + + std::array _data; + + constexpr auto key_index(const key_type& key) const -> size_t { + auto index = static_cast(key); + index -= static_cast(min_key_value()); + return index; + } + + constexpr auto operator[](const key_type& key) -> value_type& { + return _data[key_index(key)]; + } + + constexpr auto operator[](const key_type& key) const -> const value_type& { + return _data[key_index(key)]; + } +}; +} // namespace ecsact::entt::detail diff --git a/rt_entt_codegen/core/execution_options.cc b/rt_entt_codegen/core/execution_options.cc index 5a16d1c..c6bb1ca 100644 --- a/rt_entt_codegen/core/execution_options.cc +++ b/rt_entt_codegen/core/execution_options.cc @@ -37,7 +37,7 @@ inline auto print_static_maps( block( ctx, - "static const auto execution_update_fns=" + "static const auto execution_update_fns =" "std::unordered_map\n", [&] { diff --git a/rt_entt_codegen/core/system_provider/system_ctx_functions.cc b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc index 8715a25..1d91f18 100644 --- a/rt_entt_codegen/core/system_provider/system_ctx_functions.cc +++ b/rt_entt_codegen/core/system_provider/system_ctx_functions.cc @@ -9,6 +9,7 @@ using ecsact::cc_lang_support::cpp_identifier; using ecsact::cpp_codegen_plugin_util::block; using ecsact::meta::decl_full_name; using ecsact::rt_entt_codegen::util::is_transient_component; +using ecsact::rt_entt_codegen::util::make_id_map_type; auto ecsact::rt_entt_codegen::core::provider::context_action_impl( ecsact::codegen_plugin_context& ctx, @@ -225,9 +226,9 @@ auto ecsact::rt_entt_codegen::core::provider::context_get_impl( ctx.write("static const auto get_fns = []()\n"); block(ctx, "", [&] { - ctx.write( - "auto result = std::unordered_map{};\n" + ctx.writef( + "auto result = {}{{}};\n", + make_id_map_type("get_fn_t") ); for(const auto comp_id : details.readable_comps) { auto type_name = cpp_identifier(decl_full_name(comp_id)); @@ -245,8 +246,8 @@ auto ecsact::rt_entt_codegen::core::provider::context_get_impl( ctx.write("();\n"); ctx.write( - "get_fns.at(" - "component_id)(this, component_id, out_component_data, nullptr, *view" + "get_fns[component_id]" + "(this, component_id, out_component_data, nullptr, *view" ");\n" ); } @@ -295,9 +296,9 @@ auto ecsact::rt_entt_codegen::core::provider::context_update_impl( ctx.write("static const auto update_fns = []()\n"); block(ctx, "", [&] { - ctx.write( - "auto result = std::unordered_map{};\n" + ctx.writef( + "auto result = {}{{}};\n", + make_id_map_type("update_fn_t") ); for(const auto comp_id : details.writable_comps) { auto type_name = cpp_identifier(decl_full_name(comp_id)); @@ -315,8 +316,8 @@ auto ecsact::rt_entt_codegen::core::provider::context_update_impl( ctx.write("();\n"); ctx.write( - "update_fns.at(component_id)(this, component_id, component_data, nullptr, " - "*view);\n" + "update_fns[component_id]" + "(this, component_id, component_data, nullptr, *view);\n" ); } diff --git a/rt_entt_codegen/rt_entt_codegen.cc b/rt_entt_codegen/rt_entt_codegen.cc index fd677de..7bdb1c1 100644 --- a/rt_entt_codegen/rt_entt_codegen.cc +++ b/rt_entt_codegen/rt_entt_codegen.cc @@ -138,6 +138,7 @@ void ecsact_codegen_plugin( inc_header(ctx, "ecsact/entt/wrapper/core.hh"); inc_header(ctx, "ecsact/entt/wrapper/dynamic.hh"); inc_header(ctx, "ecsact/entt/error_check.hh"); + inc_header(ctx, "ecsact/entt/detail/id_map.hh"); inc_header(ctx, "xxhash.h"); ctx.write("#include \n"); diff --git a/rt_entt_codegen/shared/BUILD.bazel b/rt_entt_codegen/shared/BUILD.bazel index 0147e6b..52b0481 100644 --- a/rt_entt_codegen/shared/BUILD.bazel +++ b/rt_entt_codegen/shared/BUILD.bazel @@ -31,6 +31,7 @@ cc_library( cc_library( name = "util", + srcs = ["util.cc"], hdrs = ["util.hh"], copts = copts, defines = ["ECSACT_META_API_LOAD_AT_RUNTIME"], diff --git a/rt_entt_codegen/shared/util.cc b/rt_entt_codegen/shared/util.cc new file mode 100644 index 0000000..c5c7435 --- /dev/null +++ b/rt_entt_codegen/shared/util.cc @@ -0,0 +1,107 @@ +#include "rt_entt_codegen/shared/util.hh" + +#include +#include +#include "ecsact/runtime/meta.hh" + +static auto collect_pkg_deps( + ecsact_package_id pkg_id, + std::unordered_set& out_set +) -> void { + auto deps = ecsact::meta::get_dependencies(pkg_id); + for(auto dep : deps) { + if(out_set.contains(dep)) { + continue; + } + out_set.insert(dep); + collect_pkg_deps(dep, out_set); + } +} + +static auto all_pkg_ids() -> std::unordered_set { + auto ids = std::unordered_set{}; + auto main_pkg_id = ecsact::meta::main_package(); + ids.insert(*main_pkg_id); + collect_pkg_deps(*main_pkg_id, ids); + return ids; +} + +template +constexpr auto default_id_min() -> ID { + return static_cast(std::numeric_limits>::max() + ); +} + +template +constexpr auto default_id_max() -> ID { + return static_cast(std::numeric_limits>::min() + ); +} + +template<> +auto ecsact::rt_entt_codegen::util::ecsact_id_min_max() + -> std::tuple { + auto min = default_id_min(); + auto max = default_id_max(); + for(auto pkg_id : all_pkg_ids()) { + auto comp_ids = ecsact::meta::get_component_ids(pkg_id); + for(auto comp_id : comp_ids) { + if(static_cast(comp_id) < static_cast(min)) { + min = comp_id; + } + + if(static_cast(comp_id) > static_cast(max)) { + max = comp_id; + } + } + } + + if(min == default_id_min()) { + return {}; + } + + return {min, max}; +} + +template<> +auto ecsact::rt_entt_codegen::util::ecsact_id_min_max() + -> std::tuple { + auto min = default_id_min(); + auto max = default_id_max(); + for(auto pkg_id : all_pkg_ids()) { + auto trans_ids = ecsact::meta::get_transient_ids(pkg_id); + for(auto trans_id : trans_ids) { + if(static_cast(trans_id) < static_cast(min)) { + min = trans_id; + } + + if(static_cast(trans_id) > static_cast(max)) { + max = trans_id; + } + } + } + + if(min == default_id_min()) { + return {}; + } + + return {min, max}; +} + +template<> +auto ecsact::rt_entt_codegen::util::ecsact_id_min_max( +) -> std::tuple { + auto [transient_min, transient_max] = + ecsact_id_min_max(); + auto [component_min, component_max] = + ecsact_id_min_max(); + + return { + static_cast( + std::min(static_cast(transient_min), static_cast(component_min)) + ), + static_cast( + std::max(static_cast(transient_max), static_cast(component_max)) + ) + }; +} diff --git a/rt_entt_codegen/shared/util.hh b/rt_entt_codegen/shared/util.hh index 02f22fe..bc5b80d 100644 --- a/rt_entt_codegen/shared/util.hh +++ b/rt_entt_codegen/shared/util.hh @@ -326,4 +326,49 @@ auto make_view( // ctx.write(");\n"); } +template +constexpr auto ecsact_id_type_to_string() -> std::string_view; + +template<> +constexpr auto ecsact_id_type_to_string() + -> std::string_view { + return "ecsact_component_like_id"; +} + +/** + * Get the smallest and largest ID by number. + * Used when creating and id_map + */ +template +auto ecsact_id_min_max() -> std::tuple; + +template<> +auto ecsact_id_min_max() + -> std::tuple; + +template<> +auto ecsact_id_min_max() + -> std::tuple; + +template<> +auto ecsact_id_min_max() + -> std::tuple; + +/** + * Helper function for printing an ecsact::entt::detail::id_map in codegen + */ +template +auto make_id_map_type(std::string value_type) -> std::string { + auto id_type_str = ecsact_id_type_to_string(); + auto [min, max] = ecsact_id_min_max(); + return std::format( + "::ecsact::entt::detail::id_map<{0}, {1}, " + "static_cast<{0}>({2}), " + "static_cast<{0}>({3})>", + id_type_str, + value_type, + static_cast(min), + static_cast(max) + ); +} } // namespace ecsact::rt_entt_codegen::util