EnTT 3.16.0
Loading...
Searching...
No Matches
davey.hpp
1#ifndef ENTT_TOOLS_DAVEY_HPP
2#define ENTT_TOOLS_DAVEY_HPP
3
4#include <cstdint>
5#include <ios>
6#include <sstream>
7#include <string>
8#include <imgui.h>
9#include "../entity/mixin.hpp"
10#include "../entity/registry.hpp"
11#include "../entity/sparse_set.hpp"
12#include "../entity/storage.hpp"
13#include "../locator/locator.hpp"
14#include "../meta/container.hpp"
15#include "../meta/context.hpp"
16#include "../meta/meta.hpp"
17#include "../meta/pointer.hpp"
18#include "../meta/resolve.hpp"
19
20namespace entt {
21
23namespace internal {
24
25template<typename Entity, typename OnEntity>
26static void present_element(const meta_any &obj, OnEntity on_entity) {
27 for([[maybe_unused]] const auto [id, data]: obj.type().data()) {
28 const auto elem = data.get(obj);
29 const char *label = data.name() ? data.name() : std::string{data.type().info().name()}.data();
30
31 if(auto type = data.type(); type.info() == type_id<const char *>()) {
32 ImGui::Text("%s: %s", label, elem.template cast<const char *>());
33 } else if(type.info() == type_id<std::string>()) {
34 ImGui::Text("%s: %s", label, elem.template cast<const std::string &>().data());
35 } else if(type.info() == type_id<Entity>()) {
36 if(const auto entt = elem.template cast<Entity>(); entt == null) {
37 ImGui::Text("%s: %s", label, "null");
38 } else {
39 on_entity(label, entt);
40 }
41 } else if(type.is_enum()) {
42 const char *as_string = nullptr;
43
44 for(auto [id, curr]: type.data()) {
45 if(curr.get({}) == elem) {
46 as_string = curr.name();
47 break;
48 }
49 }
50
51 if(as_string) {
52 ImGui::Text("%s: %s", label, as_string);
53 } else {
54 ImGui::Text("%s: %zu", label, elem.template allow_cast<std::uint64_t>().template cast<std::uint64_t>());
55 }
56 } else if(type.is_arithmetic()) {
57 if(type.info() == type_id<bool>()) {
58 std::stringstream buffer{};
59 buffer << std::boolalpha << elem.template cast<bool>();
60 ImGui::Text("%s: %s", label, buffer.str().data());
61 } else if(type.info() == type_id<char>()) {
62 ImGui::Text("%s: %c", label, elem.template cast<char>());
63 } else if(type.is_integral()) {
64 ImGui::Text("%s: %zu", label, elem.template allow_cast<std::uint64_t>().template cast<std::uint64_t>());
65 } else {
66 ImGui::Text("%s: %f", label, elem.template allow_cast<double>().template cast<double>());
67 }
68 } else if(type.is_pointer_like()) {
69 if(auto deref = *obj; deref) {
70 if(ImGui::TreeNode(label)) {
71 present_element<Entity>(*obj, on_entity);
72 ImGui::TreePop();
73 }
74 } else {
75 ImGui::Text("%s: %s", label, "null");
76 }
77 } else if(type.is_sequence_container()) {
78 if(ImGui::TreeNode(label)) {
79 meta_sequence_container view = elem.as_sequence_container();
80
81 for(std::size_t pos{}, last = view.size(); pos < last; ++pos) {
82 ImGui::PushID(static_cast<int>(pos));
83
84 if(ImGui::TreeNode(label, "%zu", pos)) {
85 present_element<Entity>(view[pos], on_entity);
86 ImGui::TreePop();
87 }
88
89 ImGui::PopID();
90 }
91
92 ImGui::TreePop();
93 }
94 } else if(type.is_associative_container()) {
95 if(ImGui::TreeNode(label)) {
96 meta_associative_container view = elem.as_associative_container();
97 auto it = view.begin();
98
99 for(std::size_t pos{}, last = view.size(); pos < last; ++pos, ++it) {
100 ImGui::PushID(static_cast<int>(pos));
101
102 if(ImGui::TreeNode(label, "%zu", pos)) {
103 const auto [key, value] = *it;
104
105 if(ImGui::TreeNode("key")) {
106 present_element<Entity>(key, on_entity);
107 ImGui::TreePop();
108 }
109
110 if(ImGui::TreeNode("value")) {
111 present_element<Entity>(value, on_entity);
112 ImGui::TreePop();
113 }
114
115 ImGui::TreePop();
116 }
117
118 ImGui::PopID();
119 }
120
121 ImGui::TreePop();
122 }
123 } else if(type.is_class()) {
124 if(ImGui::TreeNode(label)) {
125 present_element<Entity>(elem, on_entity);
126 ImGui::TreePop();
127 }
128 } else {
129 const std::string underlying_type{data.type().info().name()};
130 ImGui::Text("%s: %s", label, underlying_type.data());
131 }
132 }
133}
134
135template<typename Entity, typename Allocator>
136static void present_storage(const meta_ctx &ctx, const basic_sparse_set<Entity, Allocator> &storage) {
137 if(auto type = resolve(ctx, storage.info()); type) {
138 for(auto entt: storage) {
139 ImGui::PushID(static_cast<int>(to_entity(entt)));
140
141 if(ImGui::TreeNode(&storage.info(), "%d [%d/%d]", to_integral(entt), to_entity(entt), to_version(entt))) {
142 if(const auto obj = type.from_void(storage.value(entt)); obj) {
143 present_element<typename std::decay_t<decltype(storage)>::entity_type>(obj, [](const char *name, const Entity entt) {
144 ImGui::Text("%s: %d [%d/%d]", name, to_integral(entt), to_entity(entt), to_version(entt));
145 });
146 }
147
148 ImGui::TreePop();
149 }
150
151 ImGui::PopID();
152 }
153 } else {
154 for(auto entt: storage) {
155 ImGui::Text("%d [%d/%d]", to_integral(entt), to_entity(entt), to_version(entt));
156 }
157 }
158}
159
160template<typename Entity, typename It>
161static void present_entity(const meta_ctx &ctx, const Entity entt, const It from, const It to) {
162 for(auto it = from; it != to; ++it) {
163 if(const auto &storage = it->second; storage.contains(entt)) {
164 if(auto type = resolve(ctx, storage.info()); type) {
165 const char *label = type.name() ? type.name() : std::string{storage.info().name()}.data();
166
167 if(ImGui::TreeNode(&storage.info(), "%s", label)) {
168 if(const auto obj = type.from_void(storage.value(entt)); obj) {
169 present_element<Entity>(obj, [&ctx, from, to](const char *name, const Entity other) {
170 if(ImGui::TreeNode(name, "%s: %d [%d/%d]", name, to_integral(other), to_entity(other), to_version(other))) {
171 present_entity<Entity>(ctx, other, from, to);
172 ImGui::TreePop();
173 }
174 });
175 }
176
177 ImGui::TreePop();
178 }
179 } else {
180 const std::string name{storage.info().name()};
181 ImGui::Text("%s", name.data());
182 }
183 }
184 }
185}
186
187template<typename... Get, typename... Exclude, std::size_t... Index>
188static void present_view(const meta_ctx &ctx, const basic_view<get_t<Get...>, exclude_t<Exclude...>> &view, std::index_sequence<Index...>) {
189 using view_type = basic_view<get_t<Get...>, exclude_t<Exclude...>>;
190 const std::array<const typename view_type::common_type *, sizeof...(Index)> range{view.template storage<Index>()...};
191
192 for(auto tup: view.each()) {
193 const auto entt = std::get<0>(tup);
194 ImGui::PushID(static_cast<int>(to_entity(entt)));
195
196 if(ImGui::TreeNode(&type_id<typename view_type::entity_type>(), "%d [%d/%d]", to_integral(entt), to_entity(entt), to_version(entt))) {
197 for(const auto *storage: range) {
198 if(auto type = resolve(ctx, storage->info()); type) {
199 const char *label = type.name() ? type.name() : std::string{storage->info().name()}.data();
200
201 if(ImGui::TreeNode(&storage->info(), "%s", label)) {
202 if(const auto obj = type.from_void(storage->value(entt)); obj) {
203 present_element<typename view_type::entity_type>(obj, [](const char *name, const typename view_type::entity_type entt) {
204 ImGui::Text("%s: %d [%d/%d]", name, to_integral(entt), to_entity(entt), to_version(entt));
205 });
206 }
207
208 ImGui::TreePop();
209 }
210 } else {
211 const std::string name{storage->info().name()};
212 ImGui::Text("%s", name.data());
213 }
214 }
215
216 ImGui::TreePop();
217 }
218
219 ImGui::PopID();
220 }
221}
222
223} // namespace internal
225
234template<typename Type, typename Entity, typename Allocator>
236 internal::present_storage(ctx, storage);
237}
238
246template<typename Type, typename Entity, typename Allocator>
250
258template<typename... Get, typename... Exclude>
260 internal::present_view(ctx, view, std::index_sequence_for<Get...>{});
261}
262
269template<typename... Get, typename... Exclude>
273
281template<typename Entity, typename Allocator>
283 ImGui::BeginTabBar("#tabs");
284
285 if(ImGui::BeginTabItem("Entity")) {
286 for(const auto [entt]: registry.template storage<Entity>()->each()) {
287 ImGui::PushID(static_cast<int>(to_entity(entt)));
288
289 if(ImGui::TreeNode(&type_id<Entity>(), "%d [%d/%d]", to_integral(entt), to_entity(entt), to_version(entt))) {
290 const auto range = registry.storage();
291 internal::present_entity(ctx, entt, range.begin(), range.end());
292 ImGui::TreePop();
293 }
294
295 ImGui::PopID();
296 }
297
298 ImGui::EndTabItem();
299 }
300
301 if(ImGui::BeginTabItem("Storage")) {
302 for([[maybe_unused]] auto [id, storage]: registry.storage()) {
303 const auto type = resolve(ctx, storage.info());
304 const char *label = type.name() ? type.name() : std::string{storage.info().name()}.data();
305
306 if(ImGui::TreeNode(&storage.info(), "%s (%zu)", label, storage.size())) {
307 internal::present_storage(ctx, storage);
308 ImGui::TreePop();
309 }
310 }
311
312 ImGui::EndTabItem();
313 }
314
315 ImGui::EndTabBar();
316}
317
324template<typename Entity, typename Allocator>
328
329} // namespace entt
330
331#endif
Fast and reliable entity-component system.
Definition registry.hpp:238
bool contains(const entity_type entt) const noexcept
Checks if a sparse set contains an entity.
const void * value(const entity_type entt) const noexcept
Returns the element assigned to an entity, if any.
const type_info & info() const noexcept
Returns a type info object for the value type, if any.
Storage implementation.
Definition storage.hpp:229
View implementation.
Definition fwd.hpp:47
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
Definition locator.hpp:88
Opaque meta context type.
Definition context.hpp:34
EnTT default namespace.
Definition dense_map.hpp:22
basic_view(Type &...storage) -> basic_view< get_t< Type... >, exclude_t<> >
Deduction guide.
constexpr entt_traits< Entity >::entity_type to_entity(const Entity value) noexcept
Returns the entity part once converted to the underlying type.
Definition entity.hpp:188
basic_view< type_list_transform_t< Get, storage_for >, type_list_transform_t< Exclude, storage_for > > view
Alias declaration for the most common use case.
Definition fwd.hpp:277
constexpr entt_traits< Entity >::version_type to_version(const Entity value) noexcept
Returns the version part once converted to the underlying type.
Definition entity.hpp:199
void davey(const meta_ctx &ctx, const basic_storage< Type, Entity, Allocator > &storage)
ImGui-based introspection tool for storage types.
Definition davey.hpp:235
meta_type resolve() noexcept
Returns the meta type associated with a given type.
Definition resolve.hpp:32
basic_registry<> registry
Alias declaration for the most common use case.
Definition fwd.hpp:95
constexpr entt_traits< Entity >::entity_type to_integral(const Entity value) noexcept
Converts an entity to its underlying type.
Definition entity.hpp:177
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
Definition resolve.hpp:21
const type_info & type_id() noexcept
Returns the type info object associated to a given type.
basic_storage< Type > storage
Alias declaration for the most common use case.
Definition fwd.hpp:78
Alias for exclusion lists.
Definition fwd.hpp:140
Alias for lists of observed elements.
Definition fwd.hpp:157
constexpr std::string_view name() const noexcept
Type name.