1#ifndef ENTT_TOOLS_DAVEY_HPP
2#define ENTT_TOOLS_DAVEY_HPP
4#include "../config/config.h"
5#include "../entity/mixin.hpp"
6#include "../entity/registry.hpp"
7#include "../entity/sparse_set.hpp"
8#include "../entity/storage.hpp"
9#include "../locator/locator.hpp"
10#include "../meta/container.hpp"
11#include "../meta/context.hpp"
12#include "../meta/meta.hpp"
13#include "../meta/pointer.hpp"
14#include "../meta/resolve.hpp"
15#include "../stl/cstdint.hpp"
16#include "../stl/ios.hpp"
17#include "../stl/sstream.hpp"
18#include "../stl/string.hpp"
20#if __has_include(<imgui.h>)
29template<
typename Entity,
typename OnEntity>
30static void present_element(
const meta_any &obj, OnEntity on_entity) {
31 for([[maybe_unused]]
const auto [
id, data]: obj.type().data()) {
32 const auto elem = data.get(obj);
33 const stl::string name = data.name().empty() ? stl::string{data.type().info().name()} : stl::string{data.name()};
34 const char *
const label = name.c_str();
36 if(
auto type = data.type(); type.info() == type_id<const char *>()) {
37 ImGui::Text(
"%s: %s", label, elem.template cast<const char *>());
38 }
else if(type.info() == type_id<stl::string>()) {
39 ImGui::Text(
"%s: %s", label, elem.template cast<const stl::string &>().data());
40 }
else if(type.info() == type_id<Entity>()) {
41 if(
const auto entt = elem.template cast<Entity>(); entt == null) {
42 ImGui::Text(
"%s: %s", label,
"null");
44 on_entity(label, entt);
46 }
else if(type.is_enum()) {
47 const char *as_string =
nullptr;
49 for(
auto [
id, curr]: type.data()) {
50 if(curr.get({}) == elem) {
51 as_string = curr.name().data();
57 ImGui::Text(
"%s: %s", label, as_string);
59 ImGui::Text(
"%s: %zu", label, elem.template allow_cast<stl::uint64_t>().template cast<stl::uint64_t>());
61 }
else if(type.is_arithmetic()) {
62 if(type.info() == type_id<bool>()) {
63 stl::stringstream buffer{};
64 buffer << stl::boolalpha << elem.template cast<bool>();
65 ImGui::Text(
"%s: %s", label, buffer.str().data());
66 }
else if(type.info() == type_id<char>()) {
67 ImGui::Text(
"%s: %c", label, elem.template cast<char>());
68 }
else if(type.is_integral()) {
69 ImGui::Text(
"%s: %zu", label, elem.template allow_cast<stl::uint64_t>().template cast<stl::uint64_t>());
71 ImGui::Text(
"%s: %f", label, elem.template allow_cast<double>().template cast<double>());
73 }
else if(type.is_pointer_like()) {
74 if(
auto deref = *obj; deref) {
75 if(ImGui::TreeNode(label)) {
76 present_element<Entity>(*obj, on_entity);
80 ImGui::Text(
"%s: %s", label,
"null");
82 }
else if(type.is_sequence_container()) {
83 if(ImGui::TreeNode(label)) {
84 meta_sequence_container
view = elem.as_sequence_container();
86 for(stl::size_t pos{}, last =
view.size(); pos < last; ++pos) {
87 ImGui::PushID(
static_cast<int>(pos));
89 if(ImGui::TreeNode(label,
"%zu", pos)) {
90 present_element<Entity>(view[pos], on_entity);
99 }
else if(type.is_associative_container()) {
100 if(ImGui::TreeNode(label)) {
101 meta_associative_container
view = elem.as_associative_container();
102 auto it =
view.begin();
104 for(stl::size_t pos{}, last =
view.size(); pos < last; ++pos, ++it) {
105 ImGui::PushID(
static_cast<int>(pos));
107 if(ImGui::TreeNode(label,
"%zu", pos)) {
108 const auto [key, value] = *it;
110 if(ImGui::TreeNode(
"key")) {
111 present_element<Entity>(key, on_entity);
115 if(ImGui::TreeNode(
"value")) {
116 present_element<Entity>(value, on_entity);
128 }
else if(type.is_class()) {
129 if(ImGui::TreeNode(label)) {
130 present_element<Entity>(elem, on_entity);
134 const stl::string underlying_type{data.type().info().name()};
135 ImGui::Text(
"%s: %s", label, underlying_type.data());
139 for([[maybe_unused]]
const auto [
id, base]: obj.type().base()) {
140 present_element<Entity>(obj.allow_cast(base.type()), on_entity);
144template<
typename Entity,
typename Allocator>
145static void present_storage(
const meta_ctx &ctx,
const basic_sparse_set<Entity, Allocator> &storage) {
147 for(
auto entt: storage) {
148 ImGui::PushID(
static_cast<int>(
to_entity(entt)));
151 if(
const auto obj = type.from_void(
storage.
value(entt)); obj) {
152 present_element<
typename stl::decay_t<
decltype(
storage)>::entity_type>(obj, [](
const char *name,
const Entity entt) {
163 for(
auto entt: storage) {
169template<
typename Entity,
typename It>
170static void present_entity(
const meta_ctx &ctx,
const Entity entt,
const It from,
const It to) {
171 for(
auto it = from; it != to; ++it) {
174 const stl::string name = type.name().empty() ? stl::string{
storage.
info().
name()} : stl::string{type.name()};
175 const char *
const label = name.c_str();
177 if(ImGui::TreeNode(&
storage.
info(),
"%s", label)) {
178 if(
const auto obj = type.from_void(
storage.
value(entt)); obj) {
179 present_element<Entity>(obj, [&ctx, from, to](
const char *name,
const Entity other) {
181 present_entity<Entity>(ctx, other, from, to);
191 ImGui::Text(
"%s", name.data());
197template<
typename... Get,
typename... Exclude, stl::size_t... Index>
198static void present_view(
const meta_ctx &ctx,
const basic_view<get_t<Get...>, exclude_t<Exclude...>> &view, stl::index_sequence<Index...>) {
199 using view_type =
basic_view<get_t<Get...>, exclude_t<Exclude...>>;
200 const stl::array<
const typename view_type::common_type *,
sizeof...(Index)> range{
view.template storage<Index>()...};
202 for(
auto tup:
view.each()) {
203 const auto entt = stl::get<0>(tup);
204 ImGui::PushID(
static_cast<int>(
to_entity(entt)));
207 for(
const auto *storage: range) {
209 const stl::string name = type.name().empty() ? stl::string{
storage->
info().
name()} : stl::string{type.name()};
210 const char *
const label = name.c_str();
212 if(ImGui::TreeNode(&
storage->
info(),
"%s", label)) {
213 if(
const auto obj = type.from_void(
storage->
value(entt)); obj) {
214 present_element<typename view_type::entity_type>(obj, [](
const char *name,
const view_type::entity_type entt) {
223 ImGui::Text(
"%s", name.data());
245template<
typename Type,
typename Entity,
typename Allocator>
247 internal::present_storage(ctx,
storage);
257template<
typename Type,
typename Entity,
typename Allocator>
269template<
typename... Get,
typename... Exclude>
271 internal::present_view(ctx,
view, stl::index_sequence_for<Get...>{});
280template<
typename... Get,
typename... Exclude>
292template<
typename Entity,
typename Allocator>
294 ImGui::BeginTabBar(
"#tabs");
296 if(ImGui::BeginTabItem(
"Entity")) {
301 const auto range =
registry.storage();
302 internal::present_entity(ctx,
entt, range.begin(), range.end());
312 if(ImGui::BeginTabItem(
"Storage")) {
315 const stl::string name =
type.name().empty() ? stl::string{
storage.info().name()} : stl::string{
type.name()};
316 const char *
const label = name.c_str();
318 if(ImGui::TreeNode(&
storage.info(),
"%s (%zu)", label,
storage.size())) {
319 internal::present_storage(ctx,
storage);
336template<
typename Entity,
typename Allocator>
Fast and reliable entity-component system.
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.
static Service & value_or(Args &&...args)
Returns a service if available or sets it from a fallback type.
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.
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.
constexpr entt_traits< Entity >::version_type to_version(const Entity value) noexcept
Returns the version part once converted to the underlying type.
void davey(const meta_ctx &ctx, const basic_storage< Type, Entity, Allocator > &storage)
ImGui-based introspection tool for storage types.
meta_type resolve() noexcept
Returns the meta type associated with a given type.
basic_registry<> registry
Alias declaration for the most common use case.
constexpr entt_traits< Entity >::entity_type to_integral(const Entity value) noexcept
Converts an entity to its underlying type.
meta_type resolve(const meta_ctx &ctx) noexcept
Returns the meta type associated with a given type.
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.
Alias for exclusion lists.
Alias for lists of observed elements.
constexpr stl::string_view name() const noexcept
Type name.