Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to debug the composition of an Entity #1052

Open
samaursa opened this issue Aug 7, 2023 · 10 comments
Open

Ability to debug the composition of an Entity #1052

samaursa opened this issue Aug 7, 2023 · 10 comments
Assignees
Labels
discussion it sounds interesting, let's discuss it help wanted I don't have the knowledge/resources to do that

Comments

@samaursa
Copy link

samaursa commented Aug 7, 2023

More details here: #60 (comment)

It would be great to be able to debug an entity and all of it's components inside the debugger. In Visual Studio, with natvis support, the entity should be expandable in the watch window to show all the components that it has. Ideally, one would be able to expand the components as well to inspect their values.

@skypjack skypjack self-assigned this Aug 8, 2023
@skypjack skypjack added the enhancement accepted requests, sooner or later I'll do it label Aug 8, 2023
@samaursa
Copy link
Author

@skypjack is there any update on the trampoline class? I could help you out with the implementation (and natvis) if you get me started on what you have in mind with that class.

@skypjack
Copy link
Owner

Not yet, sorry. I'm back from vacation but also need to keep up with all other things before starting something new and tricky with natvis. 🙂
I'll ping you soon on this one though. During the last days, I tried to put a few ideas together for the pending issues. 👍

@skypjack
Copy link
Owner

skypjack commented Mar 1, 2024

I've spent some time on this during the last week and 🤷‍♂️ CustomListItems doesn't support a tree-like representation. I didn't expect it. 😞
Because of that, the only way to have something meaningful is to pass all types to the registry as in registry<T1, T2, ..., TN> or have a similar viewer with the type list as template arguments. This gets rid of a loop within natvis and makes it possible to use its container-like views to show the data for the entities.
The other way around is to implement an imgui plugin and forget about natvis I guess... 😅

Unless you have some smart idea to do it, I think I'll close the issue since it's not implementable as I initially thought and I don't know how to solve it if they don't improve natvis itself a little. I'm sorry.

@skypjack skypjack added help wanted I don't have the knowledge/resources to do that wontfix I won't fix it any time soon, I'm sorry and removed enhancement accepted requests, sooner or later I'll do it labels Mar 1, 2024
@samaursa
Copy link
Author

samaursa commented Mar 4, 2024

@skypjack I do have an implementation for our internal purposes. It is not exactly fast (we can toggle it on/off at runtime) but it's not that slow either. It does the job and has been indispensable in debugging the entities.

The gist of it is:

  • we have a component called the Mapper which stores a pointer to all the components in an array
  • each time we add we also add the component pointer to the mapper
  • each time we remove we also remove the component pointer from the mapper
  • (not-so-great) we have a debug-only macro that we add to all our components to ensure pointer stability so that none of the components gets swapped out on us
  • the Mapper has a custom natvis definition that is able to display all the components of an Entity. We can even inspect the values of the component (and nested Entities in those components, if we have any).

I'm sure there are points of contention in the above such that it's not suitable to add to entt directly, especially if performance is sacrificed. However, I think it would be worth sacrificing performance (opt-in only) if a similar or better approach is provided by entt officially where entt has an optional (ideally switchable at runtime) 'debugging' mode which, while slower, provides the invaluable debugging capabilities that we are currently lacking in entt.

@skypjack
Copy link
Owner

skypjack commented Mar 4, 2024

In a project I work on, we used a slightly different approach (that could work in EnTT out of the box maybe).

First of all, note that natvis has an annoying idiosyncrasy.
Usually, it shows the content of a derived class when there is a vtable. However, it gets crazy with primitive types and enums. In particular, a storage is shown from a pointer to a sparse set only if the entity type is a class rather than an enum.
Don't ask me why, no one knows 😅 I can only imagine what the code is that runs behind natvis to get lost in such a thing.
Anyway, this would be easily solved with an opt-in macro to use a class and would be completely transparent to the end user.

Once this is done, in the project I work on there is an entity object that also contains a pointer to a registry.
This wouldn't be necessary in EnTT actually. A mixin or a debug only macro would be enough for the storage entity so that it can only use such an object internally.
At this point, we would have a type T that contains an entity and a pointer to a registry (or sort of). There are no longer two loops, this type can have its own natvis view.

However, how would this work? The registry has pointers to sparse sets. Using a non-enum entity type would display the content of the derived class, however it would still not be accessible from natvis.
Well, what we do in this project is this. For each entity (when expanded) the storages are iterated and those in which the entity isn't available are discarded. For the others, an item is added whose key is the position of the entity within the storage (which shows all its elements in order in the debugger, as if it were a vector).
Therefore, the expansion doesn't directly show the component but a list where we know where to look. On the other hand, there is no need to enable any sort of risky tracking or to turn on pointer stability even where not required. Also, performance aren't affected in any case here.

I must say that I like it as a compromise and I find it easy to use at the end of the day. It gets the job done for sure.
The next step to this I think is a plugin for VS or a gui imgui, the only two things I would use and therefore I would gladly mnaintain probably. 🙂

@samaursa
Copy link
Author

samaursa commented Mar 5, 2024

That sounds great!

For each entity (when expanded) the storages are iterated and those in which the entity isn't available are discarded. For the others, an item is added whose key is the position of the entity within the storage (which shows all its elements in order in the debugger, as if it were a vector).

I am not a natvis wizard and I'm not sure how to iterate over the storages and sprinkle in some logic in the natvis (what is this now, a natvis script?) file. If you have any resource I can check out for this, I would appreciate it.

The next step to this I think is a plugin for VS or a gui imgui

How would the imgui gui debugger work without knowing the types at compile time? I assume some extra work would be required by the user [1]?

[1] this is one of the reasons we really liked our natvis approach, no extra work is required by the user to 'expose' the type in any way. It just works with the debugger.

@skypjack
Copy link
Owner

skypjack commented Mar 6, 2024

I am not a natvis wizard and I'm not sure how to iterate over the storages and sprinkle in some logic in the natvis (what is this now, a natvis script?) file. If you have any resource I can check out for this, I would appreciate it.

I think the best way to proceed is to implement what I've in mind for the handle class. It already owns a single entity and a reference to a registry after all. If it works and is a good compromise, we can then try to apply the same to the registry itself with the trick above.

How would the imgui gui debugger work without knowing the types at compile time? I assume some extra work would be required by the user [1]?

Oh, yeah, it would use meta or the like for sure. Right. I do something similar in a project of mine already, with a small macro to export component types for the imgui windows.

@samaursa
Copy link
Author

samaursa commented Mar 8, 2024

@skypjack that sounds good

If this is to become a feature, I would request some modularity with the type information i.e. on the one hand one can use the macro you mentioned without any additional work. On the other hand, with minimal code, one should be able to leverage other reflection systems e.g. Unreal's type reflection, with the entt debugger.

skypjack added a commit that referenced this issue Apr 2, 2024
@skypjack
Copy link
Owner

skypjack commented Apr 2, 2024

Ok, I added a view for the handle class to give you a grasp of what I mean and also have a starting point.
Let me know if it makes sense to you or if it has obscure parts that I can improve/explain. Thanks. 👍

@samaursa
Copy link
Author

samaursa commented Apr 5, 2024

Thanks @skypjack. I'll try it out asap.

@skypjack skypjack added discussion it sounds interesting, let's discuss it and removed wontfix I won't fix it any time soon, I'm sorry labels Apr 5, 2024
skypjack added a commit that referenced this issue Apr 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion it sounds interesting, let's discuss it help wanted I don't have the knowledge/resources to do that
Projects
None yet
Development

No branches or pull requests

2 participants