This series is a response to the request of many people and is thought on the one hand to explain the design and ideas behind many choices in EnTT, on the other to show how this library can be used to develop something from scratch.
In no case is the aim to teach programming a game (since I’m not the right person to do it) but I’ll try to show how the various EnTT modules can be combined to achieve something that works in this sense. I’ll probably focus on something simple because I’m not that skilled overall and the goal is to explore the various features of the library, not to make the game of the year one step at a time. Afterwards, nothing excludes that the series takes a turn towards more complex applications, just for the sake of continuing to write it. :)

A library of libraries

Let’s start with the basics: what EnTT is and how I recommend using it.
Unfortunately, I’ve read or been told several times that EnTT is very big. I’d like to debunk a myth: it is not. EnTT is a library of libraries, mainly completely unrelated to each other and usable independently.

So, why didn’t you create many different projects instead? Good question.
My goal has never been to have one or many high-rated projects on GitHub. My aim was and is to have something that I can clone and that offers me all together those tools that I’ve developed and continue to develop over the years.
The alternative was to make EnTT a project full of submodules. However, I’m not a supporter of submodules. Honestly, it had to be comfortable for me first of all and I find this form much much easier to use and to work with.

This doesn’t prevent users from cloning the repository and using only a small part of it.
I’ve seen many projects that rely only on the ECS part or only on its runtime reflection system, even someone who clones it and then uses only the delegate and little else.
This is… just… fine? Using a class from EnTT won’t tie a project to all the other parts of the library.

So there are no dependencies between modules?

It depends on the definition of dependencies actually.
Literally all files refer to the core directory for definitions such as ENTT_ASSERT or ENTT_NOEXCEPT. That is to say, a single configuration file (or kind of) to rule them all.
If this type of dependencies is a problem and not acceptable, then yes, this library is not for you. If this is fine instead, the other dependencies are likely irrelevant to you anyway. They are most of the times things that are convenient but configurable and can be by-passed.

For example, the default pool in the registry offers signal for when a component is created or destroyed. To do that, it uses the signal class from the signal directory.
Is this an inevitable dependency? Definitely no. The default pool type is fully customizable. Signal support can be removed or replaced with your own class, thus removing the dependency on the built-in signal class.

Then there are modules that are completely unrelated to the rest of the library. An example of this are many of the classes in the signal folder.
On the other hand, some types make use of features offered by other modules and therefore depend on them. For example, the registry class makes use of the internal RTTI system (core/type_info) and would not work without it. In these cases, although the dependencies are minimal, these are things that would have been replicated had I chosen to create separate repositories.

So, at the end of the day, the answer is that yes, there are some dependencies. A very few ones though, mainly due to things closely related to the module in use and such that you would have wanted to have anyway.

If there are few dependencies, why do I import everything every time anyway?

Most likely because you’ve decided to use the single include file or to include entt.hpp from inside src. Well, don’t and life will smile at you.
These files are intended for small tests or for online use. For example, the single include file was a convenience for testing and reproducing errors on godbolt. And I say was because thankfully godbolt now includes EnTT as a library and it’s possible to use the files inside src directly, making it much easier to work with.

The only reason I personally see for using the single include file or entt.hpp directly is to increase parsing and compile times, without any real benefit.
EnTT is designed as a library of libraries and I constantly try to insert in each file the minimum necessary for the functionality that belongs to it.

Even including only registry.hpp in my headers doesn’t help either

Likely, in fact you shouldn’t most of the time.
A long time ago now, a very smart guy suggested filling EnTT with what I would call forward files and I’ve been keeping them up-to-date ever since.

For example, if your header only refers to a generic reference to a registry (such as const entt::registry &), why include registry.hpp at all, risking that every change will propagate to who knows how many cpp files?
Try including entt/entity/fwd.hpp instead next time. Do it for all your headers, do it wherever you need it, do it for every EnTT class you find yourself using.

EnTT is a header-only library and I personally have no problem using a super optimized, tested and well known std::vector rather than reinventing the wheel by offering something worse and with a dubious interface, just because the gamedev world often wants it.
Of course, this doesn’t mean that we should be crazy or deny one of the most critical aspects of C++, that is, compilation time. However, we can do a lot to mitigate the problem as long as we know the right means.
Believe me, I don’t like to heat my room with my laptop and that’s why I’m in a constant process to reduce inclusions, instantiations and so on. Though, the first step is to start using the right tools that already exist!

Oh, and anyway EnTT is too modern C++, it doesn’t work on consoles

Really? I thought Bedrock ran on consoles. :)
Why do we keep talking about this point all the time? It works, that’s it, C++17 is widely accepted nowadays, you don’t have to worry about it anymore.

Okay, you convinced me, where do I start?

From the next posts (which I’ll try to keep short for the whole series, trying to publish frequently).
Next time I’ll try to give you an idea of what’s really in this library. Module by module, just a quick look. Then we’ll delve into one module at a time, one class at a time, one design choice at a time and one example at a time, with some explanations on lesser known C++ techniques used here and there.

This is just the beginning of this journey. I’ve waited a long time, many have asked me about this, finally it’s time to start it.

Let me know that it helped

I hope you enjoyed what you’ve read so far.

If you liked this post and want to say thanks, consider to star the GitHub project that hosts this blog. It’s the only way you have to let me know that you appreciate my work.