1#ifndef ENTT_ENTITY_ORGANIZER_HPP
2#define ENTT_ENTITY_ORGANIZER_HPP
8#include "../core/type_info.hpp"
9#include "../core/type_traits.hpp"
10#include "../core/utility.hpp"
11#include "../graph/adjacency_matrix.hpp"
12#include "../graph/flow.hpp"
22struct is_view: std::false_type {};
24template<
typename... Args>
25struct is_view<
basic_view<Args...>>: std::true_type {};
27template<
typename Type>
28inline constexpr bool is_view_v = is_view<Type>::value;
31struct is_group: std::false_type {};
33template<
typename... Args>
34struct is_group<basic_group<Args...>>: std::true_type {};
36template<
typename Type>
37inline constexpr bool is_group_v = is_group<Type>::value;
39template<
typename Type,
typename Overr
ide>
41 using ro = std::conditional_t<
42 type_list_contains_v<Override, const Type> || (std::is_const_v<Type> && !type_list_contains_v<Override, std::remove_const_t<Type>>),
43 type_list<std::remove_const_t<Type>>,
46 using rw = std::conditional_t<
47 type_list_contains_v<Override, std::remove_const_t<Type>> || (!std::is_const_v<Type> && !type_list_contains_v<Override, const Type>),
52template<
typename... Args,
typename... Override>
53struct unpack_type<basic_registry<Args...>, type_list<Override...>> {
54 using ro = type_list<>;
55 using rw = type_list<>;
58template<
typename... Args,
typename... Override>
59struct unpack_type<const basic_registry<Args...>, type_list<Override...>>
60 : unpack_type<basic_registry<Args...>, type_list<Override...>> {};
62template<
typename... Get,
typename... Exclude,
typename... Override>
63struct unpack_type<
basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
64 using ro =
type_list_cat_t<type_list<
typename Exclude::element_type...>,
typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro...>;
65 using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw...>;
68template<
typename... Get,
typename... Exclude,
typename... Override>
69struct unpack_type<const
basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>>
70 : unpack_type<basic_view<get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {};
72template<
typename... Owned,
typename... Get,
typename... Exclude,
typename... Override>
73struct unpack_type<basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {
74 using ro =
type_list_cat_t<type_list<
typename Exclude::element_type...>,
typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::ro...,
typename unpack_type<constness_as_t<typename Owned::element_type, Owned>, type_list<Override...>>::ro...>;
75 using rw = type_list_cat_t<typename unpack_type<constness_as_t<typename Get::element_type, Get>, type_list<Override...>>::rw...,
typename unpack_type<constness_as_t<typename Owned::element_type, Owned>, type_list<Override...>>::rw...>;
78template<
typename... Owned,
typename... Get,
typename... Exclude,
typename... Override>
79struct unpack_type<const basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>>
80 : unpack_type<basic_group<owned_t<Owned...>, get_t<Get...>, exclude_t<Exclude...>>, type_list<Override...>> {};
82template<
typename,
typename>
83struct resource_traits;
85template<
typename... Args,
typename... Req>
86struct resource_traits<type_list<Args...>, type_list<Req...>> {
87 using args = type_list<std::remove_const_t<Args>...>;
88 using ro =
type_list_cat_t<
typename unpack_type<Args, type_list<Req...>>::ro...,
typename unpack_type<Req, type_list<>>::ro...>;
89 using rw =
type_list_cat_t<
typename unpack_type<Args, type_list<Req...>>::rw...,
typename unpack_type<Req, type_list<>>::rw...>;
92template<
typename... Req,
typename Ret,
typename... Args>
93resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> free_function_to_resource_traits(Ret (*)(Args...));
95template<
typename... Req,
typename Ret,
typename Type,
typename... Args>
96resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (*)(Type &, Args...));
98template<
typename... Req,
typename Ret,
typename Class,
typename... Args>
99resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...));
101template<
typename... Req,
typename Ret,
typename Class,
typename... Args>
102resource_traits<type_list<std::remove_reference_t<Args>...>, type_list<Req...>> constrained_function_to_resource_traits(Ret (Class::*)(Args...)
const);
118template<
typename Registry>
120 using callback_type = void(
const void *, Registry &);
121 using prepare_type = void(Registry &);
122 using dependency_type = std::size_t(
const bool,
const type_info **,
const std::size_t);
124 struct vertex_data final {
125 std::size_t ro_count{};
126 std::size_t rw_count{};
128 const void *payload{};
129 callback_type *callback{};
130 dependency_type *dependency{};
131 prepare_type *prepare{};
135 template<
typename Type>
136 [[nodiscard]]
static decltype(
auto) extract(Registry ®) {
137 if constexpr(std::is_same_v<Type, Registry>) {
139 }
else if constexpr(internal::is_view_v<Type>) {
140 return static_cast<Type
>(
as_view{reg});
141 }
else if constexpr(internal::is_group_v<Type>) {
142 return static_cast<Type
>(
as_group{reg});
148 template<
typename... Args>
150 return std::tuple<decltype(extract<Args>(reg))...>(extract<Args>(reg)...);
153 template<
typename... Type>
154 [[nodiscard]]
static std::size_t fill_dependencies(
type_list<Type...>, [[maybe_unused]]
const type_info **buffer, [[maybe_unused]]
const std::size_t count) {
155 if constexpr(
sizeof...(Type) == 0u) {
160 const auto length = count <
sizeof...(Type) ? count :
sizeof...(Type);
162 for(std::size_t pos{}; pos < length; ++pos) {
164 buffer[pos] = info[pos];
171 template<
typename... RO,
typename... RW>
173 builder.bind(
static_cast<id_type>(index));
197 vertex(vertex_data
data, std::vector<std::size_t> from, std::vector<std::size_t> to)
198 : node{std::move(
data)},
200 out{std::move(to)} {}
210 return node.dependency(
false, buffer, length);
221 return node.dependency(
true, buffer, length);
229 return node.ro_count;
237 return node.rw_count;
260 [[nodiscard]]
const char *
name() const noexcept {
269 return node.callback;
276 [[nodiscard]]
const void *
data() const noexcept {
284 [[nodiscard]]
const std::vector<std::size_t> &
in_edges() const noexcept {
292 [[nodiscard]]
const std::vector<std::size_t> &
out_edges() const noexcept {
302 node.prepare ? node.prepare(reg) : void();
307 std::vector<std::size_t> in;
308 std::vector<std::size_t> out;
317 template<
auto Candidate,
typename... Req>
319 using resource_type =
decltype(internal::free_function_to_resource_traits<Req...>(Candidate));
322 callback_type *callback = +[](
const void *,
registry_type ®) {
323 std::apply(Candidate, to_args(reg,
typename resource_type::args{}));
327 resource_type::ro::size,
328 resource_type::rw::size,
332 +[](
const bool rw,
const type_info **buffer,
const std::size_t length) {
return rw ? fill_dependencies(
typename resource_type::rw{}, buffer, length) : fill_dependencies(
typename resource_type::ro{}, buffer, length); },
333 +[](
registry_type ®) { void(to_args(reg,
typename resource_type::args{})); },
334 &
type_id<std::integral_constant<
decltype(Candidate), Candidate>>()};
336 track_dependencies(vertices.size(), requires_registry,
typename resource_type::ro{},
typename resource_type::rw{});
337 vertices.push_back(std::move(vdata));
349 template<
auto Candidate,
typename... Req,
typename Type>
350 void emplace(Type &value_or_instance,
const char *name =
nullptr) {
351 using resource_type =
decltype(internal::constrained_function_to_resource_traits<Req...>(Candidate));
354 callback_type *callback = +[](
const void *payload,
registry_type ®) {
356 std::apply(Candidate, std::tuple_cat(std::forward_as_tuple(*curr), to_args(reg,
typename resource_type::args{})));
360 resource_type::ro::size,
361 resource_type::rw::size,
365 +[](
const bool rw,
const type_info **buffer,
const std::size_t length) {
return rw ? fill_dependencies(
typename resource_type::rw{}, buffer, length) : fill_dependencies(
typename resource_type::ro{}, buffer, length); },
366 +[](
registry_type ®) { void(to_args(reg,
typename resource_type::args{})); },
367 &
type_id<std::integral_constant<
decltype(Candidate), Candidate>>()};
369 track_dependencies(vertices.size(), requires_registry,
typename resource_type::ro{},
typename resource_type::rw{});
370 vertices.push_back(std::move(vdata));
381 template<
typename... Req>
383 using resource_type = internal::resource_traits<type_list<>,
type_list<Req...>>;
384 track_dependencies(vertices.size(),
true,
typename resource_type::ro{},
typename resource_type::rw{});
387 resource_type::ro::size,
388 resource_type::rw::size,
392 +[](
const bool rw,
const type_info **buffer,
const std::size_t length) {
return rw ? fill_dependencies(
typename resource_type::rw{}, buffer, length) : fill_dependencies(
typename resource_type::ro{}, buffer, length); },
396 vertices.push_back(std::move(vdata));
403 [[nodiscard]] std::vector<vertex>
graph() {
404 std::vector<vertex> adjacency_list{};
405 adjacency_list.reserve(vertices.size());
409 std::vector<std::size_t> in{};
410 std::vector<std::size_t> out{};
413 in.push_back(edge.first);
417 out.push_back(edge.second);
420 adjacency_list.emplace_back(vertices[curr], std::move(in), std::move(out));
423 return adjacency_list;
433 std::vector<vertex_data> vertices;
Basic implementation of a directed adjacency matrix.
iterable_adaptor< out_edge_iterator > out_edges(const vertex_type vertex) const noexcept
Returns an iterable object to visit all out-edges of a vertex.
iterable_adaptor< in_edge_iterator > in_edges(const vertex_type vertex) const noexcept
Returns an iterable object to visit all in-edges of a vertex.
iterable_adaptor< vertex_iterator > vertices() const noexcept
Returns an iterable object to visit all vertices of a matrix.
Converts a registry to a group.
Converts a registry to a view.
Utility class for creating a static task graph.
std::vector< vertex > graph()
Generates a task graph for the current content.
void clear()
Erases all elements from a container.
void emplace(const char *name=nullptr)
Adds a free function to the task list.
callback_type function_type
void emplace(function_type *func, const void *payload=nullptr, const char *name=nullptr)
Adds an user defined function with optional payload to the task list.
void emplace(Type &value_or_instance, const char *name=nullptr)
Adds a free function with payload or a member function with an instance to the task list.
typename registry_type::entity_type entity_type
typename traits_type::value_type entity_type
basic_view(Type &...storage) -> basic_view< get_t< Type... >, exclude_t<> >
Deduction guide.
typename constness_as< To, From >::type constness_as_t
Alias template to facilitate the transcription of the constness.
typename type_list_cat< List... >::type type_list_cat_t
Helper type.
std::uint32_t id_type
Alias declaration for type identifiers.
basic_flow<> flow
Alias declaration for the most common use case.
constexpr bool type_list_contains_v
Helper variable template.
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
size_type ro_dependency(const type_info **buffer, const std::size_t length) const noexcept
Fills a buffer with the type info objects for the writable resources of a vertex.
size_type ro_count() const noexcept
Returns the number of read-only resources of a vertex.
const type_info & info() const noexcept
Returns a type info object associated with a vertex.
function_type * callback() const noexcept
Returns the function associated with a vertex.
const std::vector< std::size_t > & in_edges() const noexcept
Returns the list of in-edges of a vertex.
const std::vector< std::size_t > & out_edges() const noexcept
Returns the list of out-edges of a vertex.
void prepare(registry_type ®) const
Prepares a registry and assures that all required resources are properly instantiated before using th...
size_type rw_dependency(const type_info **buffer, const std::size_t length) const noexcept
Fills a buffer with the type info objects for the read-only resources of a vertex.
const char * name() const noexcept
Returns a user defined name associated with a vertex, if any.
const void * data() const noexcept
Returns the payload associated with a vertex, if any.
vertex(vertex_data data, std::vector< std::size_t > from, std::vector< std::size_t > to)
Constructs a vertex of the task graph.
size_type rw_count() const noexcept
Returns the number of writable resources of a vertex.
bool top_level() const noexcept
Checks if a vertex is also a top-level one.
static constexpr id_type value() noexcept
Returns the numeric representation of a given type.
Implementation specific information about a type.
A class to use to push around lists of types, nothing more.