diff --git a/BUILD.bazel b/BUILD.bazel index 4164dbd..f6af25d 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -26,7 +26,10 @@ filegroup( cc_library( name = "common", - hdrs = ["ecsact/runtime/common.h"], + hdrs = [ + "ecsact/runtime/common.h", + "ecsact/runtime/common.hh", + ], copts = copts, ) diff --git a/ecsact/runtime/common.hh b/ecsact/runtime/common.hh new file mode 100644 index 0000000..d139142 --- /dev/null +++ b/ecsact/runtime/common.hh @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include "ecsact/runtime/common.h" + +namespace ecsact { + +template +concept component_like = requires(T) { + { + ecsact_id_cast(T::id) + } -> std::convertible_to; +}; + +template +concept component = requires(T) { + { T::id } -> std::convertible_to; +}; + +template +concept tag_component = component && std::is_empty_v; + +template +concept tag_component_like = component_like && std::is_empty_v; + +template +concept non_tag_component = component && !std::is_empty_v; + +template +concept non_tag_component_like = component_like && !std::is_empty_v; + +template +concept non_tag_component_with_indexed_fields = + non_tag_component && !std::is_empty_v; + +template +concept non_tag_component_without_indexed_fields = + non_tag_component && std::is_empty_v; + +template +concept component_without_indexed_fields = + component && std::is_empty_v; + +template +concept component_with_indexed_fields = + component && std::is_empty_v; + +} // namespace ecsact diff --git a/ecsact/runtime/core.hh b/ecsact/runtime/core.hh index 34f062f..d0bd119 100644 --- a/ecsact/runtime/core.hh +++ b/ecsact/runtime/core.hh @@ -6,6 +6,7 @@ #include #include #include +#include "ecsact/runtime/common.hh" #include "ecsact/runtime/core.h" namespace ecsact::core { @@ -14,7 +15,7 @@ class builder_entity { friend class execution_options; public: - template + template ECSACT_ALWAYS_INLINE auto add_component(C* component) -> builder_entity& { components.push_back(ecsact_component{ .component_id = C::id, @@ -38,7 +39,7 @@ public: * The lifetime of @p `component` must be maintained until the * `ecsact::core::execution_options` destructor occurs or `clear()` occurs. */ - template + template void add_component(ecsact_entity_id entity, C* component) { add_components_container.push_back( ecsact_component{.component_id = C::id, .component_data = component} @@ -50,7 +51,7 @@ public: * The lifetime of @p `component` must be maintained until the * `ecsact::core::execution_options` destructor occurs or `clear()` occurs. */ - template + template void update_component(ecsact_entity_id entity, C* component) { update_components_container.push_back( ecsact_component{.component_id = C::id, .component_data = component} @@ -58,7 +59,7 @@ public: update_entities_container.push_back(entity); } - template + template ECSACT_ALWAYS_INLINE void remove_component(ecsact_entity_id entity_id) { remove_component_ids_container.push_back(C::id); remove_entities_container.push_back(entity_id); @@ -186,12 +187,12 @@ public: inline any_component_view(const any_component_view&) = default; inline ~any_component_view() = default; - template + template auto is() const -> bool { return _component_id == C::id; } - template + template auto as() const -> const C& { assert(is()); return *static_cast(_component_data); @@ -226,7 +227,7 @@ public: * Set the init callback for component @tp C. Overwrite existing callback * for @tp C if one exists. */ - template + template auto set_init_callback( // init_component_callback_t callback ) -> execution_events_collector& { @@ -244,7 +245,7 @@ public: * Set the update callback for component @tp C. Overwrite existing callback * for @tp C if one exists. */ - template + template auto set_update_callback( // update_component_callback_t callback ) -> execution_events_collector& { @@ -263,7 +264,7 @@ public: * Set the remove callback for component @tp C. Overwrite existing callback * for @tp C if one exists. */ - template + template auto set_remove_callback( // remove_component_callback_t callback ) -> execution_events_collector& { @@ -646,140 +647,91 @@ public: return ecsact_hash_registry(_id); } - template - requires(!std::is_empty_v) + template ECSACT_ALWAYS_INLINE auto get_component( // - ecsact_entity_id entity_id, - AssocFields&&... assoc_fields - ) -> const Component& { - if constexpr(Component::has_assoc_fields) { - static_assert( - sizeof...(AssocFields) > 0, - "must be called with assoc fields" - ); - } - - if constexpr(sizeof...(AssocFields) > 0) { - const void* assoc_field_values[sizeof...(AssocFields)] = { - &assoc_fields..., - }; + ecsact_entity_id entity_id + ) -> const C& { + return *reinterpret_cast( + ecsact_get_component(_id, entity_id, C::id, nullptr) + ); + } - return *reinterpret_cast( - ecsact_get_component(_id, entity_id, Component::id, assoc_field_values) - ); - } else { - return *reinterpret_cast( - ecsact_get_component(_id, entity_id, Component::id, nullptr) - ); - } + template + ECSACT_ALWAYS_INLINE auto get_component( // + ecsact_entity_id entity_id, + const C::IndexedFields& indexed_fields + ) -> const C& { + return *reinterpret_cast( + ecsact_get_component(_id, entity_id, C::id, &indexed_fields) + ); } - template - ECSACT_ALWAYS_INLINE bool has_component( - ecsact_entity_id entity_id, - AssocFields&&... assoc_fields - ) { - if constexpr(Component::has_assoc_fields) { - static_assert( - sizeof...(AssocFields) > 0, - "must be called with assoc fields" - ); - } + template + ECSACT_ALWAYS_INLINE auto has_component(ecsact_entity_id entity_id) -> bool { + return ecsact_has_component(_id, entity_id, C::id, nullptr); + } - if constexpr(sizeof...(AssocFields) > 0) { - const void* assoc_field_values[sizeof...(AssocFields)] = { - &assoc_fields..., - }; - return ecsact_has_component( - _id, - entity_id, - Component::id, - assoc_field_values - ); - } else { - return ecsact_has_component(_id, entity_id, Component::id, nullptr); - } + template + ECSACT_ALWAYS_INLINE auto has_component( + ecsact_entity_id entity_id, + const C::IndexedFields& indexed_fields + ) -> bool { + return ecsact_has_component(_id, entity_id, C::id, &indexed_fields); } - template - requires(std::is_empty_v) + template ECSACT_ALWAYS_INLINE auto add_component(ecsact_entity_id entity_id) { return ecsact_add_component(_id, entity_id, Component::id, nullptr); } - template + template ECSACT_ALWAYS_INLINE auto add_component( ecsact_entity_id entity_id, - const Component& component + const C& component ) { - if constexpr(std::is_empty_v) { - return ecsact_add_component(_id, entity_id, Component::id, nullptr); + if constexpr(ecsact::tag_component) { + return ecsact_add_component(_id, entity_id, C::id, nullptr); } else { - return ecsact_add_component(_id, entity_id, Component::id, &component); + return ecsact_add_component(_id, entity_id, C::id, &component); } } - template + template ECSACT_ALWAYS_INLINE auto update_component( ecsact_entity_id entity_id, - const Component& component, - AssocFields&&... assoc_fields + const C& component ) { - if constexpr(Component::has_assoc_fields) { - static_assert( - sizeof...(AssocFields) > 0, - "must be called with assoc fields" - ); - } + return ecsact_update_component(_id, entity_id, C::id, &component, nullptr); + } - if constexpr(sizeof...(AssocFields) > 0) { - const void* assoc_field_values[sizeof...(AssocFields)] = { - &assoc_fields..., - }; - return ecsact_update_component( - _id, - entity_id, - Component::id, - &component, - assoc_field_values - ); - } else { - return ecsact_update_component( - _id, - entity_id, - Component::id, - &component, - nullptr - ); - } + template + ECSACT_ALWAYS_INLINE auto update_component( + ecsact_entity_id entity_id, + const C& component, + const C::IndexedFields& indexed_fields + ) { + return ecsact_update_component( + _id, + entity_id, + C::id, + &component, + &indexed_fields + ); } - template - ECSACT_ALWAYS_INLINE auto remove_component( - ecsact_entity_id entity_id, - AssocFields&&... assoc_fields + template + ECSACT_ALWAYS_INLINE auto remove_component( // + ecsact_entity_id entity_id ) -> void { - if constexpr(Component::has_assoc_fields) { - static_assert( - sizeof...(AssocFields) > 0, - "must be called with assoc fields" - ); - } - - if constexpr(sizeof...(AssocFields) > 0) { - const void* assoc_field_values[sizeof...(AssocFields)] = { - &assoc_fields..., - }; + return ecsact_remove_component(_id, entity_id, C::id, nullptr); + } - return ecsact_remove_component( - _id, - entity_id, - Component::id, - assoc_field_values - ); - } else { - return ecsact_remove_component(_id, entity_id, Component::id, nullptr); - } + template + ECSACT_ALWAYS_INLINE auto remove_component( // + ecsact_entity_id entity_id, + const C::IndexedFields& indexed_fields + ) -> void { + return ecsact_remove_component(_id, entity_id, C::id, &indexed_fields); } ECSACT_ALWAYS_INLINE auto count_entities() const -> int32_t {