Before I'm asking, I know I can iterate through register.view<Comp>(), but just making sure, is there any proper method for doing it?
Not sure I get what you mean. Do you want to get the entity associated with a given instance of a component of type T?
In this case, you can calculate the offset of the component using the component raw pointer (as in registry::raw<T>), then get its entity by adding the same offset to the entity raw pointer (as in registry::data<T>).
Remember that all components and entities are tightly packed and ordered the same in a given pool.
Okay, got it! thanks anyway!
Hi @skypjack . Thanks for the awesome library first of all! Secondly, I was trying to do exactly what you talked about in the comment above, "get the entity associated with a given instance of a component of type T". So, I created this helper function in my scene class:
template<typename T>
std::pair<entt::registry&, entt::entity> GetEntity(const T& component)
{
size_t offset = &component - m_Registry.raw<T>();
Log::Assert(offset < m_Registry.size(), "Tried to get nonexistent entity.");
return { m_Registry, *(m_Registry.data() + offset) };
}
And this was works fine _almost_ all of the time. However, if I create an entity and assign it component A, then I create two more entities and assign them components A, B, and C. If I iterate through components A, B, C as a group, I end up getting an off by one error when using my GetEntity function, for example, if I am iterating over entity 100, I end up calculating entity 99 using the function. Specifically I have some code that looks like this:
for (auto entity : group)
{
auto& aabb = group.get<AABB>(entity);
auto& transform = group.get<Transform>(entity);
Log::Info("Concrete iter: %d", entt::to_integral(entity));
Log::Info("Calculated iter: %d", entt::to_integral(Application::Get()->GetScene()->GetEntity(aabb).second));
}
And the problem mentioned above happens where the first log will report 100, but the second log reports 99. Is this a design flaw on my part by assuming that the offset will always remain the same? Or am I perhaps missing another calculation? Once again thank you for the amazing library :)
@ambrosiogabe This doesn't answer your question but I noticed std::pair<entt::registry&, entt::entity>and wanted to let you know that there's a fancy version of that coming soon to an EnTT near you. See here.
Thanks @Kerndog73 I like the looks of this new feature, and I'm still pretty early on in the integration of entt into my project so I should be able to get rid of those cumbersome std::pair's 馃憤
Solved my own problem, there was a problem with this line:
return { m_Registry, *(m_Registry.data() + offset) };
I looked closer at the docs and it looks like that returns the raw pointer for _all_ entities (which makes sense), so changing the line to:
return { m_Registry, *(m_Registry.data<T>() + offset) };
Ensures I'm getting the raw pointer for the first entity that has a component of type T. For anyone else who may need this function in the future, here is the full corrected version :)
template<typename T>
std::pair<entt::registry&, entt::entity> GetEntity(const T& component)
{
size_t offset = &component - m_Registry.raw<T>();
return { m_Registry, *(m_Registry.data<T>() + offset) };
}
@ambrosiogabe Sorry, I'm late to the party.
Thanks for using EnTT and I'm glad you solved your problem. :+1:
Ofc data without a type returns the list of all the entities, an array that contains also the deleted ones. It's mainly meant for serialization purposes since you can also restore a registry at once from that array later.
All in all, we can easily add a free function to the set of helpers. Something along this line:
const auto entity = entt::to_entity(registry, position);
It would work with all components, all registries and all entity types.
@skypjack No worries about the lateness, and that function would be great if you guys have had question like this before! In my case I'm not struggling with performance as of now, but it's always nice to have the helper if needed :+1:
Yup. I'm pushing it upstream soon. Gimme the time to write a test and update the doc. :wink:
Most helpful comment
Solved my own problem, there was a problem with this line:
I looked closer at the docs and it looks like that returns the raw pointer for _all_ entities (which makes sense), so changing the line to:
Ensures I'm getting the raw pointer for the first entity that has a component of type
T. For anyone else who may need this function in the future, here is the full corrected version :)