Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

Overview

EnTT: Gaming meets modern C++

Build Status Coverage Try online Documentation Gitter chat Discord channel Donate

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++.
Among others, it's used in Minecraft by Mojang, the ArcGIS Runtime SDKs by Esri and the amazing Ragdoll.
If you don't see your project in the list, please open an issue, submit a PR or add the #entt tag to your topics! 👍


Do you want to keep up with changes or do you have a question that doesn't require you to open an issue?
Join the gitter channel and the discord server, meet other users like you. The more we are, the better for everyone.
Don't forget to check the FAQs and the wiki too. Your answers may already be there.

Do you want to support EnTT? Consider becoming a sponsor. Many thanks to these people and special thanks to:

mojang imgly

Table of Contents

Introduction

The entity-component-system (also known as ECS) is an architectural pattern used mostly in game development. For further details:

This project started off as a pure entity-component system. Over time the codebase has grown as more and more classes and functionalities were added.
Here is a brief, yet incomplete list of what it offers today:

  • Statically generated integer identifiers for types (assigned either at compile-time or at runtime).
  • A constexpr utility for human readable resource names.
  • A minimal configuration system built using the monostate pattern.
  • An incredibly fast entity-component system based on sparse sets, with its own pay for what you use policy to adjust performance and memory usage according to the users' requirements.
  • Views and groups to iterate entities and components and allow different access patterns, from perfect SoA to fully random.
  • A lot of facilities built on top of the entity-component system to help the users and avoid reinventing the wheel (dependencies, snapshot, handles, support for reactive systems and so on).
  • The smallest and most basic implementation of a service locator ever seen.
  • A built-in, non-intrusive and macro-free runtime reflection system.
  • Static polymorphism made simple and within everyone's reach.
  • A cooperative scheduler for processes of any type.
  • All that is needed for resource management (cache, loaders, handles).
  • Delegates, signal handlers (with built-in support for collectors) and a tiny event dispatcher for immediate and delayed events to integrate in loops.
  • A general purpose event emitter as a CRTP idiom based class template.
  • And much more! Check out the wiki.

Consider this list a work in progress as well as the project. The whole API is fully documented in-code for those who are brave enough to read it.

It is also known that EnTT is used in Minecraft.
Given that the game is available literally everywhere, I can confidently say that the library has been sufficiently tested on every platform that can come to mind.

Code Example

#include <entt/entt.hpp>

struct position {
    float x;
    float y;
};

struct velocity {
    float dx;
    float dy;
};

void update(entt::registry &registry) {
    auto view = registry.view<const position, velocity>();

    // use a callback
    view.each([](const auto &pos, auto &vel) { /* ... */ });

    // use an extended callback
    view.each([](const auto entity, const auto &pos, auto &vel) { /* ... */ });

    // use a range-for
    for(auto [entity, pos, vel]: view.each()) {
        // ...
    }

    // use forward iterators and get only the components of interest
    for(auto entity: view) {
        auto &vel = view.get<velocity>(entity);
        // ...
    }
}

int main() {
    entt::registry registry;

    for(auto i = 0u; i < 10u; ++i) {
        const auto entity = registry.create();
        registry.emplace<position>(entity, i * 1.f, i * 1.f);
        if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
    }

    update(registry);
}

Motivation

I started developing EnTT for the wrong reason: my goal was to design an entity-component system to beat another well known open source solution both in terms of performance and possibly memory usage.
In the end, I did it, but it wasn't very satisfying. Actually it wasn't satisfying at all. The fastest and nothing more, fairly little indeed. When I realized it, I tried hard to keep intact the great performance of EnTT and to add all the features I wanted to see in my own library at the same time.

Nowadays, EnTT is finally what I was looking for: still faster than its competitors, lower memory usage in the average case, a really good API and an amazing set of features. And even more, of course.

Performance

The proposed entity-component system is incredibly fast to iterate entities and components, this is a fact. Some compilers make a lot of optimizations because of how EnTT works, some others aren't that good. In general, if we consider real world cases, EnTT is somewhere between a bit and much faster than many of the other solutions around, although I couldn't check them all for obvious reasons.

If you are interested, you can compile the benchmark test in release mode (to enable compiler optimizations, otherwise it would make little sense) by setting the ENTT_BUILD_BENCHMARK option of CMake to ON, then evaluate yourself whether you're satisfied with the results or not.

Honestly I got tired of updating the README file whenever there is an improvement.
There are already a lot of projects out there that use EnTT as a basis for comparison (this should already tell you a lot). Many of these benchmarks are completely wrong, many others are simply incomplete, good at omitting some information and using the wrong function to compare a given feature. Certainly there are also good ones but they age quickly if nobody updates them, especially when the library they are dealing with is actively developed.

The choice to use EnTT should be based on its carefully designed API, its set of features and the general performance, not because some single benchmark shows it to be the fastest tool available.

In the future I'll likely try to get even better performance while still adding new features, mainly for fun.
If you want to contribute and/or have suggestions, feel free to make a PR or open an issue to discuss your idea.

Build Instructions

Requirements

To be able to use EnTT, users must provide a full-featured compiler that supports at least C++17.
The requirements below are mandatory to compile the tests and to extract the documentation:

  • CMake version 3.7 or later.
  • Doxygen version 1.8 or later.

Alternatively, Bazel is also supported as a build system (credits to zaucy who offered to maintain it).
In the documentation below I'll still refer to CMake, this being the official build system of the library.

If you are looking for a C++14 version of EnTT, check out the git tag cpp14.

Library

EnTT is a header-only library. This means that including the entt.hpp header is enough to include the library as a whole and use it. For those who are interested only in the entity-component system, consider to include the sole entity/registry.hpp header instead.
It's a matter of adding the following line to the top of a file:

#include <entt/entt.hpp>

Use the line below to include only the entity-component system instead:

#include <entt/entity/registry.hpp>

Then pass the proper -I argument to the compiler to add the src directory to the include paths.

Documentation

The documentation is based on doxygen. To build it:

$ cd build
$ cmake .. -DENTT_BUILD_DOCS=ON
$ make

The API reference will be created in HTML format within the directory build/docs/html. To navigate it with your favorite browser:

$ cd build
$ your_favorite_browser docs/html/index.html

The same version is also available online for the latest release, that is the last stable tag. If you are looking for something more pleasing to the eye, consider reading the nice-looking version available on docsforge: same documentation, much more pleasant to read.
Moreover, there exists a wiki dedicated to the project where users can find all related documentation pages.

Tests

To compile and run the tests, EnTT requires googletest.
cmake will download and compile the library before compiling anything else. In order to build the tests, set the CMake option ENTT_BUILD_TESTING to ON.

To build the most basic set of tests:

  • $ cd build
  • $ cmake -DENTT_BUILD_TESTING=ON ..
  • $ make
  • $ make test

Note that benchmarks are not part of this set.

Packaging Tools

EnTT is available for some of the most known packaging tools. In particular:

  • Conan, the C/C++ Package Manager for Developers.

  • vcpkg, Microsoft VC++ Packaging Tool.
    You can download and install EnTT in just a few simple steps:

    $ git clone https://github.com/Microsoft/vcpkg.git
    $ cd vcpkg
    $ ./bootstrap-vcpkg.sh
    $ ./vcpkg integrate install
    $ vcpkg install entt
    

    The EnTT port in vcpkg is kept up to date by Microsoft team members and community contributors.
    If the version is out of date, please create an issue or pull request on the vcpkg repository.

  • Homebrew, the missing package manager for macOS.
    Available as a homebrew formula. Just type the following to install it:

    brew install skypjack/entt/entt
    
  • build2, build toolchain for developing and packaging C and C++ code.
    In order to use the entt package in a build2 project, add the following line or a similar one to the manifest file:

    depends: entt ^3.0.0
    

    Also check that the configuration refers to a valid repository, so that the package can be found by build2:

    Both can be used with bpkg add-repo or added in a project repositories.manifest. See the official documentation for more details.

Consider this list a work in progress and help me to make it longer.

EnTT in Action

EnTT is widely used in private and commercial applications. I cannot even mention most of them because of some signatures I put on some documents time ago. Fortunately, there are also people who took the time to implement open source projects based on EnTT and did not hold back when it came to documenting them.

Here you can find an incomplete list of games, applications and articles that can be used as a reference.

If you know of other resources out there that are about EnTT, feel free to open an issue or a PR and I'll be glad to add them to the list.

Contributors

Requests for features, PRs, suggestions ad feedback are highly appreciated.

If you find you can help and want to contribute to the project with your experience or you do want to get part of the project for some other reason, feel free to contact me directly (you can find the mail in the profile).
I can't promise that each and every contribution will be accepted, but I can assure that I'll do my best to take them all as soon as possible.

If you decide to participate, please see the guidelines for contributing before to create issues or pull requests.
Take also a look at the contributors list to know who has participated so far.

License

Code and documentation Copyright (c) 2017-2021 Michele Caini.
Colorful logo Copyright (c) 2018-2021 Richard Caseres.

Code released under the MIT license.
Documentation released under CC BY 4.0.
All logos released under CC BY-SA 4.0.

Issues
  • Call for comments: signals on component creation/destruction

    Call for comments: signals on component creation/destruction

    Ok, people is asking this and I tried to figure out if it's possible. Probably, I found a nice way to add signalling stuff to the registry in a way that is in policy with the whole framework: pay only for what you use.. It means that there will be no performance hits for those components that aren't (let me say) observed. On the other side, it will be possible to be notified about creation and destruction of specific components if required.

    I've still to review the whole idea and try to implement it. However, I'd like to have feedbacks about it.

    Is it a feature in which you could be interested? Any suggestion, comment or request?

    As a side note, it would unlock other features like implicit blueprints (when component A is attached, attach also B and C silently) and so on.

    Let me know, feedbacks are appreciated!! I'll close the issue probably in a couple of days.

    Thank you.

    discussion 
    opened by skypjack 85
  • Member function for on_construct() without instance?

    Member function for on_construct() without instance?

    Would it be possible to add an overload for the on_construct()-family of methods on the sinks to allow for a member function of the underlying component type, without an instance of the member function's type?

    Here's a visual example:

    struct some_component {
        int i = 0;
    
        void init() {
            cout << "I've init'd: " << i << endl;
        }
    };
    
    registry.on_construct<some_component>().connect<&some_component::init>();
    

    In the above pseudo-code, we don't use a static function nor do we use a member function with a point/reference to a specific instance. Instead, we use a pointer to a member function of the component itself to call, with this being the pointer to the newly created component itself.

    This would greatly clean up some of the glue code in some parts of the engine, as right now I am either passing lambdas or creating stubs to do pretty much exactly this.

    For context, I could be using constructors and destructors, but given the inherently POD-like structures, default move constructors, et al, I'm writing my components in a way they can be re-used via init() and destroy() member methods (where a call to destroy() could, in theory, be followed by init() assuming all of the non-default POD properties have been set prior). I fully realize this isn't a design requirement by ENTT but it seems like a clean approach for my use-case.

    Would love to hear your thoughts, or why this might not be a good idea. :)

    enhancement 
    opened by Qix- 58
  • [POC] Annotated meta-data

    [POC] Annotated meta-data

    The purpose of annotated meta-data is to provide better runtime-introspection abilities with less code. Annotations are just properties created with reusable function or functional object.

    https://github.com/Innokentiy-Alaytsev/entt/tree/runtime-annotations

    I've implemented one of the functions I think is useful. I've renamed the concept from 'decoration' to 'annotation' - I think the new word better represents the purpose. I've only implemented the function for registering meta-data without setter and getter. If you say everything is fine, I'll add implementations for annotated meta-data with setter and getter, annotated meta-type (reflect_annotated), maybe annotated meta-function (func_annotated). Also, I'll try to find a way to minimise the amount of the required code - it's very straight forward, but it may be a support burden.

    feature request 
    opened by Innokentiy-Alaytsev 56
  • Save/Restore

    Save/Restore

    Hi @skypjack , I've been disconnected for a few weeks, and when today I got back, had a look at the code, well... wow! already version 2.4.1 and a lot of new features (and most of those I already had custom-implemented because of need, like the Actor class)!

    I have a side question and a possible feature request: how difficult would it be to implement a save/restore functionality in the ECS? In the simulation system we are implementing, one of the main features we need to implement is the possibility to take "snapshots" of the entire system state, save them and restore at a later time. More or less a classical replay system, but with multiple restore points.

    Is it possible to implement that functionality in the Registry, with the current implementation? In case you believe is a feature that is worth incorporating, please send me a PM and we can maybe have a quick call to discuss ways of helping/accelerating the development.

    enhancement discussion 
    opened by dbacchet 54
  • Implemented scoped unregistering of meta-types

    Implemented scoped unregistering of meta-types

    Added an overload for entt::meta function accepting an entt::meta_chain object reference for building a chain of locally registered types. The entt::meta_chain instance will store an implicit list of types registered with it and will call entt::meta::reset() for each of them upon its desctruction.

    triage 
    opened by Innokentiy-Alaytsev 48
  • discussion - empty components should not be part of the each callback

    discussion - empty components should not be part of the each callback

    skypjack was already refactoring the empty instance pools -> https://github.com/skypjack/entt/commit/e228cb66488fc6ae98365ce2f5f8db45834a92c3#diff-36792e38ee0671f0a02c94d88a91cfbb idk if that is gonna have any impact on this issue...

    but basically something like

    reg.group<Component, EmptyTag>().each([](auto id, auto comp) {});
    reg.group<Component, EmptyTag>().each([](auto comp) {});
    

    instead of

    reg.group<Component, EmptyTag>().each([](auto id, auto comp, auto tag) {});
    reg.group<Component, EmptyTag>().each([](auto comp, auto tag) {});
    

    since there's no point in having empty instance in the arguments.. This is a api breaking change though so it'd have to be part of a major release cause I'm sure everyone like me has just been including the tags in their each callbacks.

    feature request 
    opened by pgruenbacher 46
  • Some implementation Questions

    Some implementation Questions

    I have some questions about the best way to implement some things:

    1. Component Dependency: for example if i have a "Position" Component and a "Velocity" Componenet and i want to create a new Component called "Physics" to have more complex behaiviour how woud i make Position and Velocity a requirement for having a physics component. I could pass the Registry and the Entity into the Physics component constructor to add the Position and Velocity components if they dont exist but that doesnt seem to be a clean solution.

    2. Best way of implementing child entities: im kinda thinking about this too i would think that you create a "Parent" component that has a Entity handle to a child and thats it ? but what about passing information down the chain like if i change the position of the parent entity i want to inform the children that the parent moved and update their position accordingly. I would have to check in the "Position" component if it has a "Parent" component and then pass it down or is there a better way?.

    3. Getting the registry or the attached entity in the component: can you do that without having to pass it into the components that need it? im not sure about that but would it be possible to create a Component base class for those type of things and then have a specialization in the attach function but i dont know if that is possible in C++.

    4. What about baseclass Components: eg. if i have a Renderable Component and i want to subclass it to implement the draw function or something and add that to the entity and then get all of them with a view by searching all Renderables. is that possible, if not what would be a alternative?

    discussion faq 
    opened by SeeSoftware 46
  • Component polymorphism support feature & prototype

    Component polymorphism support feature & prototype

    Hello,

    I'd like to introduce my work on prototype feature, that adds component polymorphism support. Such thing might seem a little controversial, so I will immediately mention two things:

    • Despite not being a part of pure ECS concept, such feature can be very useful in many real world cases
    • It is enabled only for certain component types at compile time, so it will not affect performance of non-polymorphic components in any way (pay only for what you use)

    I already have working prototype in the experimental branch of my fork. Of course it requires some review and improvements, and some parts may not be made in a nicest way possible right now, but it is fully functional.

    Here is a basic example:

    struct Ticking : public entt::polymorphic {
        virtual void tick(const entt::entity) = 0;
    };
    
    class Physics : public entt::inherit<Ticking> {
        // ...
        void tick(const entt::entity e) override {
             // ...
        }
    };
    
    class AI : public entt::inherit<Ticking> {
        // ...
        void tick(const entt::entity e) override {
             // ...
        }
    };
    
    
    registry.emplace<Physics>(e); // emplace polymorphic component
    Ticking& ticking1 = registry.get<Ticking>(e); // will return Physics as Ticking
    registry.emplace<AI>(e); // emplace another polymorphic component
    Ticking& ticking2 = registry.get<Ticking>(e); // will return any of two components, because they are both inherit from Ticking, which component is returned is not defined
    
    // get iterable to iterate each component, that is inherited from Ticking, order of iteration is not defined
    for (Ticking& ticking : registry.view<entt::every<Ticking>>(e).each()) {
        // ...
    }
    
    // view can also get every component instead of one
    registry.view<entt::every<Ticking>>(e).each([](const entt::entity, entt::every<Ticking> every_ticking) {
        for(Ticking& ticking : every_ticking) // ...
    });
    
    // will remove EVERY component, that is inherited from Ticking
    registry.remove<Ticking>(e);
    

    You can try it yourself, it is already in the fork, along with some tests. I will appreciate any feedback about how to improve both the concept and the solution, and hope it will make it way into EnTT in the future.

    Now lets dive into some details:

    Problems, I try to address

    Maybe the main problem, this feature solves, is accessing components without knowing their exact type. It is sometimes can be very useful to access component as some interface/base type without knowing what exactly it is (so basically this is what polymorphism is about in general, and this feature is applying this concept to ECS).

    In the context of ECS it results in 2 main ideas: we should be able to access component by any of its base types and we also should be able to access all such components, attached to an entity, because there of course can be more than one. Example of this idea is already shown above, we create two component types, that implement Ticking interface and add both of them to an entity, and then we can just iterate all ticking components and do something with them (probably just call tick in this case).

    Additionally, to follow "pay only for what you use" rule, such polymorphic components must be treated separately and must not affect performance of other components.

    Some specs

    The basic idea is simple: component can be accessed not only by its own type, but by any of its parent types. From the example above we can see, that both Physics and AI components inherit from, and so can be accessed as reference to Ticking. Here I tried to come up with a bit more formal set of rules:

    1. We define polymorphic components separately from non-polymorphic, by inheriting from entt::polymorphic or entt::inherit<Parent1, Parent2, ...>. Polymorphic component can inherit only from other polymorphic components to keep them separate from non-polymorphic. With this requirement we can completely separate all logic at the compile time and preserve performance for non-polymorphic components.
    2. When polymorphic component is added to entity, it can then be accessed not only by its own type, but as any of its parent types. This applies both for getting it for one entity and for iterating with a view.
    3. Now for some parent type there can be several components of its child types attached to an entity. So we must be able to: 3.1. Still get one of this components, if we just need one. This operation ideally must be as fast, as getting one non-polymorphic component. Which component will be returned cannot be specified in this case, so we just return any of them. 3.2. Iterate over all components of this type, attached to an entity. Same as with one component, we must be able to use it both with get and with view. To achieve this, we pass entt::every<ParentType> instead of just ParentType to registry.get or registry.view, and get it back. Then we just iterate entt::every<ParentType> to get ParentType&. 3.3. Access with entt::every must work completely similar for one and for several components.
    4. Calling erase and remove must delete all components inherited from given type. This might seem a bit controversial, because in some cases we need to delete component of exactly this type, so maybe in the future separate method should be added to do such things.
    5. Actions insert, get_or_emplace are deleted for polymorphic components right now, and patch is also controversial one, as they deserve separate discussion. ... This list will be expanded as the discussion progresses

    Some implementation details

    Wrappers (or containers, don't know, which name is better)

    Main idea here is to store polymorphic components inside wrappers/containers (polymorphic_component_container<Component>). These wrappers are able to store component value of exactly given type and reference list to other components. They have storage for component value, list of references to other components and 2 bits for flags to store its state.

    Wrapper has methods for value construction/destruction, adding/removing references to other components from reference list and for getting reference to one component or entt::every to iterate all of them. When constructing a value, wrapper adds reference to this value into all wrappers for parent component types, when destructing - it will remove all this references. So it requires registry and entity to access those wrappers for parent types.

    Polymorphic components reference each other by pointer, so stable pointer is required, in_place_delete is true for all polymorphic types, and empty type optimization is also disabled, because wrappers are never empty.

    Changes in basic_storage

    Because polymorphic components are stored in wrappers and accessed in a slightly different way, separate basic_storage and iterator implementations are created for them. It changes implementation of get, emplace, erase and remove and also adds hidden methods for polymorphic_component_container like emplace_ref and erase_ref.

    I have also added get_as<T> (and similar) methods for all basic_storage implementations and similar as<T> methods for storage iterators. The purpose of those is resolving entt::every (and maybe some other type modifiers in the future). For non-polymorphic storage those methods are completely similar to get/operator*, they actually just call them with an extra static_assert, so no performance overhead here.

    And here comes an uglier part: emplace and erase now require registry for polymorphic storage, so right now they are just passed as an additional parameter, that is ignored for non-polymorphic component storages. Again, no performance overhead here, as the registry parameter is just optimized out, but the whole idea of such inverse dependence is pretty nasty. It is another open discussion on how to implement this in a more elegant way.

    Changes in basic_view

    Here things are simpler: I use get_as<T>/as<T> methods I have created in storage and storage iterators to just forward everything in a right way. Because all of these methods are basically same as get/operator* used before for non-polymorphic types, no overhead is expected for them.

    There is also some changes to get unwrap entt::every to get storages for required component, but these are fully resolved at compile time.

    Changes in basic_registry

    Only changes here are passing registry to emplace/erase/remove and unwrapping entt::every for views.

    Dive into polymorphic_component_container implementation

    As was said before, polymorphic_component_container aka polymorphic component wrapper can store both component value and reference list. In a very basic implementation it can be done like this (and also thinking of it in this way may help a lot):

    template<typename Component>
    struct polymorphic_component_container {
        std::optional<Component> value;
        std::vector<Component&> refs;
    };
    

    But when I came to thinking about erase implementation the following problem kicked in. When erasing component, we must also erase all components listed in refs (those are child types). When deleting component, it must delete all of its references from parent wrappers, so we must know exact types of components in refs to do it or come up with another way. My idea was to store pointer to 'deleter' function along with component reference, such deleter will be placed when reference is added and called, when it is required to erase component by its reference. So wrapper implementation should look like this:

    template<typename Component>
    struct polymorphic_component_container {
        struct component_ref {
            Component& ref;
            void* deleter;
        };
        std::optional<Component> value;
        std::vector<component_ref> refs;
    };
    

    Now lets move on to real implementation. It does not use std::vector nor std::optional. Instead it has data - buffer for component value or at least one pointer and uintptr_t pointer, which can store pointer to one reference or pointer to list, depending on wrapper state. And to store wrapper state I use a solution with some pointer hacks - I rely on memory alignment, so 2 bits of pointer are always zero and can be used to store the state (it is achieved by aligning entt::inherit by at least 4 bytes). This saves us one memory access when getting reference to the component and also sizeof(pointer) bytes of memory per wrapper, that would be otherwise added by padding. I thought it was worth it, so there is a lot of strange stuff going on inside wrapper, but if you consider this an overkill I of course will rethink it.

    Now lets look on the possible storage states: there are 2 bits, 2 flags that are mostly independent of each other, 1st flag - if wrapper has a value, 2nd flag - if wrapper has a reference list. Describing whole implementation here would take forever, I will try to do it separately, so here are some important notes:

    • There is always a value or a reference stored directly inside the wrapper, so one component reference can be always accessed without any indirection and looking into list. If nothing is stored, wrapper is deleted.
    • When wrapper has list, it stores all the references, owned by this wrapper, including reference to the value inside this wrapper (if in has one), so iterating the list does not require extra logic.
    • When wrapper contains only one reference or only value, it does not allocate a list (and also it deallocates a list, if only one reference/value remains)
    • Lists are allocated via component_ref_list_page_source to optimize many small memory allocations of the same size, required for them. Note: right now template of component_ref_list_page_source depends only on underlying allocator type, but maybe it should instead be instantiated per component type (the page size must be reduced greatly in this case).

    I am planning to clean up, and move some of this logic out of the wrapper class to abstract underlying memory layout a bit, right now the solution is messy.

    ...Implementation details are also to be expanded
    triage 
    opened by zheka2304 45
  • Non-owning entt::actor

    Non-owning entt::actor

    Here I have a draft for a non-owning version of entt::basic_actor called entt::basic_handle. I really had my heart set on the name "handle" but then I realised (well actually the compiler realised 😄) that there's already entt::handle. So the alias in the forwarding header is called handle_grr because grr naming things is hard! Anyway, we can figure out a name later.

    The handle is a reference type while actor is a value type. If actor was std::vector, then handle would be std::span. This has influenced a number of design decisions. Handles are lightweight types that can be copied and moved around freely. They are intended to be a drop-in replacement for an entity-registry pair. "having 3 parameters is better than having 6".

    Mutability

    entt::registry reg;
    entt::entity e = reg.create();
    
    entt::handle h1{e, reg};
    const entt::handle h2{e, reg};
    entt::const_handle h3{e, reg};
    const entt::const_handle h4{e, reg};
    
    h1.assign<int>(); // OK
    h2.assign<int>(); // OK
    h3.assign<int>(); // Not allowed
    h4.assign<int>(); // Not allowed
    

    Implicit conversions

    void add_components(entt::handle);
    void get_components(entt::const_handle);
    
    entt::registry reg;
    entt::actor actor{reg};
    entt::handle handle{actor};
    
    add_components(actor);
    get_components(actor);
    add_components(handle);
    get_components(handle);
    

    Deduction guides

    ENTT_OPAQUE_TYPE(my_entity, entt::id_type);
    
    entt::basic_registry<my_entity> reg;
    const auto &const_reg = reg;
    my_entity e = reg.create();
    
    entt::basic_actor a1{reg};           // basic_actor<my_entity>
    const auto &a2 = a1;
    entt::basic_handle h1{a1};           // basic_handle<my_entity>
    entt::basic_handle h2{e, reg};       // basic_handle<my_entity>
    entt::basic_handle h3{e, const_reg}; // basic_handle<const my_entity>
    entt::basic_handle h4{a2};           // basic_handle<const my_entity>
    

    I have not attempted to deal with the duplication between the three classes. I wanted to keep it simple and deal with that later. Better to have all this boilerplate in the library than in user code though, right? I was thinking that it might be useful to give these classes a fuller API. Instead of just assign and remove, there could be emplace_or_replace, remove_if_exists, patch, etc. That is, all (or most) of the registry member functions that operate on a single entity could be added. That will make the duplication much worse but is a separate discussion anyway.

    I also haven't added tests for this. I kind of wanted to find a name that doesn't clash (and perhaps discuss the design a bit too) before doing that. I just realised that the examples above are probably halfway towards a test suite.

    In a couple of the constructors, I commented Does this assertion really make sense?. Would it ever make sense to construct a handle from a valid registry but a null entity? If this class is to be a drop-in replacement for an entity-registry pair then perhaps that assertion should be removed. To be clear, I'm not suggesting that it is removed from actor, just from handle. Or maybe it could be changed to ENTT_ASSERT(ref.valid(entity) || entity == null)? Or even ENTT_ASSERT(reg.valid_or_null(entity))? I think I remember suggesting valid_or_null long ago. Once again, separate discussion!

    enhancement 
    opened by indianakernick 44
  • Basic logic operations for registry and filtering views.

    Basic logic operations for registry and filtering views.

    It just occurred to me that one could in principle enhance the registry.has<...>(...) and registry.any<...>(...) methods with all the basic logic operations. I admit XOR seems to me to be the most convenient, but in theory all apply.

    bool xorExistingComponents = registry.XOR<component1, component2, component3, ...>(entity);
    

    The holy grail would of course be able to generate views with more expressive logical conditions. But that might have other performance trade-offs.

    Also, build times may suffer...

    triage 
    opened by sunbubble 43
  • [Feature Request] Make the registry work across boundaries

    [Feature Request] Make the registry work across boundaries

    This is a follow up of #182 to discuss the problem in the title.
    To sum up: on Windows, inline variables aren't guaranteed to be unique between all the TUs and thus things could break when the registry is pushed across boundaries.

    There are several solutions that could make it work when a single library is used with a main executable. However, most of them will still break in case of multiple libraries used together at once. Therefore I won't even mention these solutions.

    So far, a widely accepted proposal (discussed on gitter) is based on named components. In other terms, components that will be pushed across boundaries must be assigned a compile-time name.
    This solution can be implemented in two different ways, each with its pros and cons:

    1. Components inherit from a dedicated class template:

      struct my_component: entt::shared<"my_name"_hs> { /* ... */ };
      // or even SHARED(my_component) { /* ... */ };
      // ...
      registry.do_something<my_component>(entity);
      

      A macro can be used to ease the definition, of course. In this case, whenever a shared component is detected, the registry searches it by name instead of by identifier. A secondary macro can be used to force the behavior only on libraries and rely on direct access through identifiers in the main executable.

    2. The other way around doesn't affect component definitions, but require users to explicitly specify when to use a components in shared mode, that is by name. Something along this line:

      struct my_component { /* ... */ };
      // ...
      registry.do_something<my_component>(entity); // direct access with numeric identifier
      registry.do_something<SHARED(my_component)>(entity); // work fine across boundaries
      

      This is a bit more verbose, but users have finer control and their components are theirs. Moreover, it's clear at the call site whether a component is used in shared mode or not.

    I'm open to comment, critiques and suggestions. I won't to get rid of this limitations, because it's getting annoying, so let's discuss it and solve the problem once and forever.


    EDIT

    I tried to implement a first draft. Another possible approach is to rely on 1. and split components between shared and non-shared ones. In other terms, to have two vectors of pools. The drawback is that there are two vectors ofc. :smile:
    It would affect to an extent only those components that are pushed across boundaries.
    On the other side, this is trickier, it requires much boilerplate and it will be most probably harder to maintain.

    A trivial approach instead, probably the easiest to implement and to maintain, is to have the whole registry as shared and non-shared.
    It means that internally the registry uses always a direct access or always a name based lookup. When users are dealing with dlls on Windows, it's enough to set up a macro and have components that inherit from shared_t to provide a name. In all the other cases, the lookup by name is disabled and everything works by direct access.
    Less granular, ofc, but it requires to change only one function at a first glance.

    Comments?


    EDIT

    @ArnCarveris came up with a good idea that is a compromise between what we discusses so far, gets rid of inheritance and is safe as well.
    This edit to keep track of it (names can change in the final version):

    template<typename>
    struct shared_traits;
    
    template<>
    struct shared_traits<my_component> {
        static constexpr auto value = "my_component"_hs;
    };
    

    A few macros will be provided to ease the definition of shared components. In particular:

    •  ENTT_SHARE(my_component);
      

      To use to turn an already existing type in a shared one.

    •  ENTT_SHARED_STRUCT(my_component) { /* ... */ };
       ENTT_SHARED_CLASS(my_component) { /* ... */ };
      

      To use to define directly a type as a shared class.

    Feedback are welcome.

    enhancement 
    opened by skypjack 43
  • Add a bounded each to observer

    Add a bounded each to observer

    An observer can now iterate its first N entities with each. In the mutable version, this will remove the first N entities from the observer. This allows an observer to be partially iterated when the amount of work is too high for the frame budget.

    triage 
    opened by cjhowedev 2
  • Allow entities and components of specific entities to be disabled/enabled

    Allow entities and components of specific entities to be disabled/enabled

    It would be super helpful to be able to disable either an entity or a specific component on an entity, both without actually deleting entity or component. The entity or component continues to exist, does not get overwritten by entt during creation (retains its id and version), and might be re-enabled later.

    What

    • get<T> and try_get<T> should not return component T if it has been disabled for the given entity.
    • get<T> and try_get<T> should not return an enabled component T if the given entity is disabled.
    • A view should skip a disabled entity.
    • A disabled entity or component should be able to be deleted.

    Imagine two entities exist with components:

    Entity A -TransformComponent -RenderComponent -CollisionComponent

    Entity B -TransformComponent -RenderComponent -CollisionComponent

    If I disable Entity A, it should not be returned if I create a view on CollisionComponent.

    If I disable CollisionComponent on Entity B, only Entity A should be returned if I create a view on CollisionComponent.

    (Why you would disable CollisionComponent I have no idea. This is just to demonstrate that disabling a component applies to a specific entity, not all components of that type.)

    Nice to Have

    • Something that could return all disabled but not deleted entities and components (by type) but at worst the user could just be maintaining a list of disabled entities.
    • An alternative version/overload of view that returns all entities, enabled or not.

    How

    I'm purposefully not suggesting how an entity or component might be enabled or disabled.

    Why

    Presumably entt's own check would be far faster/efficient than the method I employed to do this. All of my components derive from a Component class, which has an enabled member. All entities get a GeneralComponent on creation. Among other things GeneralComponent does, its enabled is treated specially: to determine if the entity itself is considered enabled.

    Background

    I was working on a pathing system that has three pieces: FollowComponent, WanderComponent, and PathingComponent (and the corresponding systems). The problem is simple: the first two components must stop all work for any entities involved in cutscene scripting (unless a script specifically turns them back on). I can't simply disable the systems because they should continue to process other entities not involved in the script. I need to disable FollowComponent and WanderComponent on the entities involved in the cutscene.

    Another practical usage scenario is undo/redo in a level editor. Deleting an entity could simply disable it, and then upon save all disabled entities are ignored. Undo'ing a delete would simply re-enable said entity (presumably the undo/redo list stores the entity). The major benefit of this approach is preserving the original state of the entity after the user requests an undo. Redo would simply disable the entity again.

    feature request 
    opened by Domiran 4
  • Sketch of a change to save binary size

    Sketch of a change to save binary size

    I was doing some explorations on improving binary size and found this potential change in ENTT. Basically, what's going on here is that the 'placeholder' function-level "magic static" is more expensive than it may appear to be at first.

    I analyzed a large game using ENTT, by using the SizeBench tool. Each 'placeholder' creates what is called an "atexit destructor" that ends up generating code that is unnecessary. When this magic static is first encountered, it gets constructed (thread-safe, too) which is a rad property of magic statics - but...who is responsible for destructing it? And when does that happen? That's what an atexit destructor does - it's code generated to run the destructor of the magic static (if it was ever constructed), and it runs when the module is unloaded or when exit() is used.

    Each of these 'placeholder' objects is returned as a const reference, so it's never mutated, but it still has to be destructed and that code has to be generated. If, instead, this returns nullptr in the case of not having a pool, the placeholder need not be constructer or destructed.

    There's not many callsites using assure that had to be updated to do -> instead of . for the reference-to-pointer switch, and tolerate a null return value.

    In a large game I found this to save ~200KB of binary size (almost all in the .text section, or code, a little bit in .pdata which has an entry per function in .text so it's usually correlated, and it saved some .bss in-memory read/write data pages.)

    I didn't actually run any tests after this change, and I only tested building and linking with MSVC, so consider this a sketch to see if you want to carry it forward and actually test it and ensure it's ok for all the compilers and platforms ENTT may support.

    triage 
    opened by Austin-Lamb 4
  • Component polymorphism support

    Component polymorphism support

    Adds extension, that allows to declare and work with polymorphic components. See discussion in the delated issue #859.

    Example usage (will be updated in case of changes):

    #include <entt/entity/polymorphic.hpp>
    
    struct ticking : public entt::inherit<> { // declare as polymorphic component without parents
        virtual void tick(const entt::entity) = 0;
    };
    
    class physics : public entt::inherit<ticking> { // inherit from ticking
        // ...
        void tick(const entt::entity e) override {
             // ...
        }
    };
    
    class ai : public entt::inherit<ticking> { // inherit from ticking
        // ...
        void tick(const entt::entity e) override {
             // ...
        }
    };
    
    // iterate all components, derived from ticking for given entity
    for (ticking& ticking : entt::algorithm::poly_get_all<ticking>(reg, e)) {
        ticking.tick(e);
    }
    
    // try get any component, derived from ticking for given entity
    if (ticking* ticking = entt::algorithm::poly_get_any<ticking>(reg, e); ticking != nullptr) {
        ticking->tick(e);
    }
    
    // iterate all components, derived from ticking in the registry
    entt::algorithm::poly_each<ticking>(reg, [] (entt::entity e, ticking& c) {
        ticking.tick(e);
    });
    
    // count components, derived from ticking 
    entt::algorithm::poly_count<ticking>(reg, e); // attached to entity
    entt::algorithm::poly_count<ticking>(reg); // in the registry
    
    // remove all components, derived from ticking, attached to entity
    entt::algorithm::poly_remove<ticking>(reg, e); 
    
    
    triage 
    opened by zheka2304 14
  • Question: Can I infer the size of the component type when visiting storage pools?

    Question: Can I infer the size of the component type when visiting storage pools?

    Hello!

    I am trying to generically (without upfront knowledge of the component types) read the byte contents of all existing pools.

    Is this possible?

    I assume the only way I can access the pools generically is by using visit:

    auto visitor = [](entt::sparse_set& pool) {
        // Can I get the pool element size?
    };
    entity_registry_.visit(visitor);
    

    (BTW, the documentation has this example but it seems to me this is no longer possible:

    // create a copy of an entity component by component
    for(auto &&curr: registry.storage()) {
        if(auto &storage = curr.second; storage.contains(src)) {
            storage.emplace(dst, storage.get(src));
        }
    }
    

    )

    question 
    opened by Ramito 33
Releases(v3.10.3)
  • v3.10.3(Aug 2, 2022)

    Changelog

    • entity:
      • Fix an issue that makes storage cross range-erase break when using built-in iterators.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.10.2(Aug 1, 2022)

    Changelog

    • entity:
      • Fix an issue that makes sparse set cross range-erase break when using built-in iterators.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.10.1(Apr 28, 2022)

    Changelog

    • config:

      • Decouple ENTT_NOEXCEPT and exceptions handling
    • entity:

      • Correctly handle overflow of version and max number of entities
    • meta:

      • Container traits don't really support plain arrays anymore (if they ever did)
      • Fixed an issue with insert/erase of meta sequence containers
      • Re-added meta_type::remove_pointer
    • signal:

      • Added more comparison operators for resource handles

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.10.0(Apr 15, 2022)

    Changelog

    • config:

      • Added the macro.h file with a couple of utilities
      • Export the ENTT_VERSION string
      • Detect version and configuration mismatches automatically on Windows
    • container:

      • Uses-allocator construction guaranteed for dense_set
      • Uses-allocator construction guaranteed for dense_map
      • dense_map iterators are in the input iterator category but model either a forward (local) or a random (default) iterator
      • dense_map::value_type is either pair<const T &, U &> or pair<const T &, const U &> (zip iterator type)
      • No more risky UBs due to type punning or destroy/construct within a vector for a dense_map
      • Strong exception guarantee for emplace and insert functions of the dense_map class
      • Strong exception guarantee for emplace and insert functions of the dense_set class
    • core:

      • Store size with hashed strings
      • Decouple begin/end iterator types of iterable_adaptor
      • Utility uses_allocator_construction_args (waiting for C++20)
      • Utility make_obj_using_allocator (waiting for C++20)
      • Utility uninitialized_construct_using_allocator (waiting for C++20)
      • Added utilities allocation_deleter and allocate_unique (with uses-allocator construction guaranteed)
      • compressed_pair correctly manages references with piecewise construction
      • ENTT_NOEXCEPT_IF (for future uses)
      • Added an overload of type_id to get a type_info from a variable
      • Allow to construct type_info objects directly (no static storage duration in this case)
    • entity:

      • Optimized runtime view iterators
      • Weak basic_registry<...>::storage for opaque operations across (eventually different) registries
      • basic_runtime_view<...>::iterate/exclude member functions to attach pools at runtime
      • basic_sparse_set<...>::emplace returns an iterator to the inserted element (or the end iterator in case of errors)
      • basic_sparse_set<...>::insert returns an iterator to the inserted elements (or the end iterator in case of errors)
      • sigh_storage_mixin always triggers an emplace request notification (in sync with unbalanced destroy)
      • Chained constructors support (ie parent-to-child propagation) for default storage classes
      • Arguments provided to storage classes are always discarded for empty types
      • Standalone registry context type returned by the .ctx() method, all context functionalities are part of its API now
      • Support to named context variables (through emplace_hint)
      • basic_registry<...>::storage<T> is no longer [[nodiscard]]
      • basic_registry<...>::storage<T> also supports const qualified types
      • Sparse set's iterators' ::index returns the right index (that is, offset - 1)
      • Internal hook basic_sparse_set<...>::try_emplace was changed to return an iterator to the inserted element (or end())
      • Internal hook basic_sparse_set<...>::try_emplace was changed to accept an additional boolean force_back parameter
      • basic_sparse_set<...>::insert always appends elements rather than trying to fill tombstones if any
      • basic_storage<...>::insert always appends elements rather than trying to fill tombstones if any
      • Internal hook basic_sparse_set<...>::swap_and_pop was changed to accept a couple of iterators
      • Internal hook basic_sparse_set<...>::in_place_pop was canged to accept a couple of iterators
      • basic_sparse_set<...>::clear no longer creates tombstones (it actually removes all of them)
      • Automatic traits deduction for the component class, drop basic_component_traits
      • Uses-allocator construction guaranteed for storage classes
      • All storage classes support entity and component types with custom swap functions
      • basic_sparse_set<...>::bump to force-refresh an entity version
      • Drop component_traits::::ignore_if_empty, use ::page_size 0 for empty types
      • Allow creating pool during a call to basic_registry<...>::destroy (ie from a listener)
      • Added a constructor to reserve enough memory for N pools on creation
    • locator:

      • Renamed service_locator to locator
      • Allocator support when creating new services (see allocate_emplace)
    • meta:

      • meta_type::invoke also searches into the base types for a candidate function
      • Added a compile-time check to prevent attaching a type as a meta base of itself
      • Meta sequence containers iterators belong to the input iterator category but model a forward iterator
      • Relaxed meta sequence containers requirements
      • Dereferencing a pointer-like object that converts to bool works in all cases (false implies empty meta_any)
    • process:

      • Allow attaching tasks to a scheduler from already running processes
    • resource:

      • Make resource handles equality comparable
      • Removed class resource_loader, made the loader a template parameter of the resource_cache
      • Full review of the resource_cache API and functionalities
      • Full review of the resource_handle (now resource) class
      • Added a transparent resource_loader for basic cases
    • signal:

      • Renamed delegate::instance to delegate::data
      • Added support for named queues to the basic_dispatcher class
      • Enable fetching the number of pending events from a basic_dispatcher
      • Allocator support for the basic_dispatcher class
    • Performance improvements:

      • Improved performance for basic_registry<...>::remove
      • Improved performance for basic_registry<...>::erase
      • Blazing fast basic_sparse_set<...>::clear
      • Blazing fast basic_sparse_set<...>::erase when using basic_sparse_set<...>::[const_]iterators
    • Build system:

      • Removed the in-source build check

    Natvis support

    • Added info about the sparse array of a sparse set (non-null elements only)
    • Updated representation for hashed strings (also include size)
    • Updated representation for the registry context
    • Updated representation for dense map and dense set
    • Updated representation for all classes in the resource module

    Breaking changes

    • container:

      • dense_hash_map was renamed to dense_map
      • dense_hash_set was renamed to dense_set
    • core:

      • Removed is_iterator_type[_v], no alternative provided
      • Removed ENTT_LAUNDER
    • entity:

      • basic_runtime_views do not have a vector-based constructor anymore, use ::iterate and ::exclude instead
      • basic_registry<...>::runtime_view no longer exists, use the default constructor, then ::iterate and ::exclude
      • Registry context functionalities have been moved to the standalone registry context class and are now part of its API
      • basic_sparse_set<...>::slot is no longer available, no alternative provided
      • basic_sparse_set<...> hooks were slightly changed for performance reasons
      • basic_component_traits doesn't exist anymore, all values should be specified explicitly
      • Renamed basic_registry<...>::sortable to basic_registry<...>::owned
      • component_traits::::ignore_if_empty isn't available anymore, set the page_size to 0 to avoid creating empty types
    • locator:

      • Renamed service_locator to locator
      • Full review of the locator's API (all functions are still there but they've likely a different name)
    • resource:

      • Removed class resource_loader, made the loader a template parameter of the resource_cache
      • Full review of the resource_cache API and functionalities
      • Full review of the resource_handle (now resource) class
    • signal:

      • delegate::instance doesn't exist anymore, use delegate::data instead

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I started a long term process to reduce the number of instantiations and also speed up the compilation. This release contains many changes and great improvements in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.9.0(Dec 21, 2021)

    Changelog

    • container:

      • Introduced a new dense_hash_map class that is mostly a drop-in replacement for std::unordered_map.
      • Introduced a new dense_hash_set class that is mostly a drop-in replacement for std::unordered_set.
    • core:

      • Added type_info constructor with in-place type (as in std::in_place_type_t<T>).
      • Added the new class compressed_pair for internal uses but also available to the final user (with support to structured binding).
      • Added is_ebco_eligible[_v] utility.
      • any_cast no longer forces by-copy construction for rvalues.
      • Added enum-as-bitmask support for enum classes.
      • Created a new memory.hpp header to support/offer general purpose functions generally missed in the standard library.
      • Added to_address to unwrap fancy pointers, waiting for C++20.
      • Added propagate_on_container_copy_assignment, propagate_on_container_move_assignment and propagate_on_container_swap.
      • Constexpr function is_power_of_two, it's mainly meant for internal uses but also generally available.
      • Constexpr function fast_mod, it's mainly meant for internal uses but also generally available.
      • Created a new tuple.hpp header to support/offer general purpose functions generally missed in the standard library.
      • Utility unwrap_tuple, it's mainly meant for internal uses but also generally available.
      • constexpr support for type_info.
      • basic_any<...>::type returns the object type if any, type_id<void>() (and not an empty type_info) otherwise.
      • Added optional const type_info & parameter (requested type) to basic_any<...>::data.
      • operator<, operator<=, operator> and operator>= for basic_hashed_string.
      • operator<, operator<=, operator> and operator>= for type_info.
      • type_id returns type_info objects with static storage duration.
      • Added basic_any<...>::assign to copy or move assign the wrapped value without replacing it.
      • Added to_entity and to_version aside to_integral, they forward the request to the right entt_traits<...> class.
      • New input_iterator_pointer utility class.
      • Constexpr function next_power_of_two, it's mainly meant for internal uses but also generally available.
      • Added is_transparent[_v] utility class.
      • An is_transparent type member is now part of the identity class.
      • iterable_adaptor utility to create a temporary iterable object from two iterators.
    • entity:

      • Added in_place_delete[_v] and ignore_as_empty[_v] utilities.
      • basic_sparse_set<...> is a non-copyable allocator-aware container (::get_allocator(), pocma/pocca/pocs support, and so on).
      • basic_storage<...> is a non-copyable allocator-aware container (::get_allocator(), pocma/pocca/pocs support, and so on).
      • Empty allocators are elided by exploiting EBCO.
      • All storage classes offer a get_as_tuple function.
      • Added owned_t besides get_t and exclude_t.
      • Included destroyed list head in the entity count when creating a snapshot.
      • entt_traits is now a first class citizen of the library and all entity related requests rely on it (see ::combine and so on).
      • basic_registry<...>::current returns a tombstone version for invalid entities and doesn't assert anymore.
      • Added basic_sparse_set<...>::current to return known version of identifiers in set.
      • Sparse arrays also contain updated entity versions, no more unused bits (out-of-sync support).
      • Sparse sets manage correctly foreign entities in all cases, the version is always taken in consideration now.
      • No tombstone checks for multi-type views, zero-cost pointer stability model.
      • Added empty ::get method to storage for empty types.
      • In-place delete always fills holes before appending new elements during an ::insert.
      • Generalized ::insert for all mixins.
      • Storage types are safe to use from the base class in all cases, no more risky corner cases.
      • Decoupled sparse set iterators from allocators to reduce instantiations.
      • Decoupled storage iterators from allocators to reduce instantiations.
      • Added basic_view<...>::operator[] overload to access (eventually unwrapped) components by entity.
      • operator-> for iterable objects iterators (iterable view, iterable group).
      • Added basic_view<...>::handle to return a const reference to the leading storage.
      • Non-const to const conversion guaranteed for storage iterators.
      • Include fwd.hpp from entity.hpp to make entity available in all cases.
      • Make basic_registry<...>::all_of, basic_registry<...>::any_of and a few other functions remove const qualifiers.
      • Make is_iterator[_v] also support void *and const void *.
      • Tuple-like type support for is_equality_comparable[_v].
      • Support for views with multiple components of the same type (i.e. view<E, T, T, T>).
      • Added basic_view<...>::use<integral value>() to set leading pool by index.
      • Added basic_view<...>::get<integral value>(e) to get components by index.
      • Make the basic_registry class work smoothly across boundaries.
      • Use a dense hash map to store context variables.
      • Removed the void * custom argument from basic_sparse_set::remove, ::erase, ::emplace, ::insert, ::clear.
      • Added a bind function to the basic_sparse_set to pass the outer context to mixins.
      • Fully removed the poly storage support.
      • Make a const basic_registry fully thread-safe (with placeholder pools).
      • swap is not longer virtual in the basic_sparse_set.
      • Allow emplacing opaque values (void *) from a basic_sparse_set.
      • Allow getting the value type of the derived class from a basic_sparse_set with ::type, if any.
      • Allow getting the value associated to an entity from a derived class as an opaque pointer (void *) with ::get, if any.
      • Removed basic_registry::prepare.
      • Added basic_registry::storage<T> to get or create pools at runtime and bind them to a custom name if needed.
      • Make to_entity also work with stable types.
      • Turned basic_component_traits::in_place_delete into a boolean value.
      • Turned basic_component_traits::ignore_if_empty into a boolean value.
      • Added basic_component_traits::page_size to allow customizing the packed page size on a per-type basis.
      • Removed in_place_delete_v.
      • Added basic_view::storage<T> to get pools at runtime if needed.
      • Added basic_group::storage<T> to get pools at runtime if needed.
      • Added entt_traits::page_size to allow customizing the sparse page size on a per-type basis.
      • Added basic_group<...>::handle to return a const reference to the leading storage.
      • Multi-type views' iterators are in the forward iterator category now.
      • Iterable views (.each()) do not offer reverse iterators anymore (cannot implement them correctly).
      • Iterable groups (.each()) do not offer reverse iterators anymore (cannot implement them correctly).
      • Added basic_sparse_set<...>::cbegin/::cend/crbegin/crend and the const_iterator and const_reverse_iterator type members.
      • basic_storage<...>::each function to iterate a storage as a set of entity/component tuples.
      • Views and groups iterators are also default constructible and a default constructed iterator always compares to end.
      • Added basic_registry<...>::storage() to return pools and their names as an iterable object.
    • meta:

      • meta_type::construct doesn't look for base constructors anymore.
      • Container support review (less instantiations, faster to compile).
      • Meta sequence containers ::insert returns now an iterator that is contextually convertible to bool (for validity checks).
      • Meta sequence containers ::erase returns now an iterator that is contextually convertible to bool (for validity checks).
      • meta_arg utility doesn't require an std::index_sequence anymore.
      • The list of types to meta_arg is now a type list template parameter instead of a function parameter.
      • meta_construct utility doesn't require an std::index_sequence anymore.
      • meta_invoke utility doesn't require an std::index_sequence anymore.
      • A public meta_dispatch utility is now available.
      • Removed meta_type::is_void.
      • Add fwd.hpp file for many types in meta.
      • Non-template version of meta_any::allow_cast that works with meta types.
      • Removed parent link from meta objects.
      • Lambda support for meta_invoke and meta_construct utilities.
      • Replaced meta_type::reset with the meta_reset free functions.
      • Added cbegin and cend to meta_range.
      • Added meta_type::is_arithmetic to replace is_integral and is_floating_point.
      • Automatic arithmetic conversion support to mimic what the language offers out of the box.
      • Automatic enum conversion support to/from underlying type.
      • Multi-setter support for meta_data (meta data members).
      • Added meta_any::assign to copy or move assign the wrapped value without replacing it.
      • operator-> for meta containers iterators.
      • operator-> for meta_range iterators.
      • Static functions that require the parent type as first argument are treated as (eventually const) member functions.
      • Non-const to const conversion guaranteed for meta_range iterators.
      • Extended support to base members when attached to meta types for derived classes.
      • Define meta_associative_container_traits for dense_hash_map.
      • Define meta_associative_container_traits for dense_hash_set.
      • Member functions can be used as meta destructors.
      • Policies also check function return types at compile-time.
      • Added meta_any::owner to know if a meta_any also owns the underlying object.
    • poly:

      • Single function vtable optimization to avoid indirections.
    • resource:

      • Added resource_handle::use_count to know how many handles are there for a single resource.
      • Added resource_handle::resource_type type member.
      • Review of the resource handle to make it a value type and improve the const correctness of the class.
      • Review of the resource cache to improve the const correctness of the class.
      • Added aliasing constructor to resource handle.
    • signal:

      • scoped_connection is now move assignable and move constructible.
      • Make the dispatcher class work smoothly across boundaries.
      • Make the emitter class work smoothly across boundaries.
      • Allocator support for the sigh class.
    • Performance improvements here and there (ie storage classes, any and any_cast, ...).

    • clang-format support. 🥳

    Build system

    • Added a pipeline to ensure that EnTT works as expected with all major compilers when using C++20.
    • ENTT_USE_LIBCPP default is OFF.
    • ENTT_INCLUDE_HEADERS option to add headers to the EnTT target (default: OFF).
    • ENTT_INCLUDE_NATVIS option to add natvis files to the EnTT target (default: OFF).

    EnTT across boundaries

    This is all you need to do right now for EnTT to work across boundaries:

    That is, absolutely nothing. Things like the registry class don't make use of static variables anymore and therefore they don't risk to break when used across boundaries. They should just work out of the box. Finally. 🙂

    Natvis files

    List of classes already covered by natvis files upstream (work in progress):

    • entt::basic_sparse_set (with tombstones detection)
    • entt::basic_storage (with tombstones detection)
    • entt::type_info
    • entt::basic_any
    • entt::compressed_pair
    • entt::dense_hash_map
    • entt::dense_hash_set
    • entt::meta_any
    • entt::meta_associative_container
    • entt::internal::meta_base_node
    • entt::internal::meta_conv_node
    • entt::internal::meta_ctor_node
    • entt::internal::meta_data_node
    • entt::meta_data
    • entt::internal::meta_func_node
    • entt::meta_func
    • entt::meta_handle
    • entt::internal::meta_prop_node
    • entt::meta_prop
    • entt::meta_sequence_container
    • entt::internal::meta_template_node
    • entt::internal::meta_type_node
    • entt::meta_type
    • entt::basic_hashed_string
    • entt::delegate
    • entt::sigh
    • entt::sink
    • entt::connection
    • entt::scoped_connection
    • entt::basic_view
    • entt::tombstone
    • entt::null
    • entt::basic_registry
    • entt::poly
    • entt::dispatcher
    • entt::basic_view

    Breaking changes

    • core:

      • Renamed type_seq to type_index.
      • Renamed type_info::seq to type_info::index.
      • type_info is no longer default nor user constructible, use type_id instead.
      • Renamed unpack_as_t to unpack_as_type and unpack_as_v to unpack_as_value.
    • entity:

      • Removed basic_storage<...>::sort, capture pool and use ::get if needed.
      • Removed basic_storage<...>::sort_n, capture pool and use ::get if needed.
      • Removed the free function get_as_tuple, use the functions offered by storage classes instead.
      • Changed view definition to basic_view<T, get_t<C...>, exclude_t<E...>> and therefore view<get_t<C...>, exclude_t<E...>> (second parameter is optional).
      • Changed group definition to basic_group<T, owned_t<O...>, get_t<G...>, exclude_t<E...>>.
      • basic_view<...>::use<T> doesn't modify the view in-place anymore, instead it returns a new view.
      • Removed null_t::operator|, use entt_traits<...>::combine instead.
      • Removed tombstone_t::operator|, use entt_traits<...>::combine instead.
      • Removed basic_registry<...>::version, use entt_traits instead.
      • Removed basic_registry<...>::entity, use entt_traits instead.
      • basic_sparse_set<...>::clear honors the set modality.
      • Renamed basic_sparse_set<...>::swap for entities to swap_elements to avoid conflicts.
      • Removed basic_sparse_set<...>::emplace_back, no alternative provided.
      • basic_sparse_set<...>::emplace doesn't return the position anymore.
      • entt_traits<...> doesn't offer anymore a difference_type alias.
      • Removed support for view.each<T>(F), use view.use<T>().each(F) instead.
      • Removed support for view.each<T>(), use view.use<T>().each() instead.
      • Removed basic_registry::prepare<T>, use storage<T> instead.
      • Removed in_place_delete_v<T>, use component_traits<T>::in_place_delete instead.
      • Removed basic_registry<...>::reserve<T>, use basic_registry<...>::storage<T>().reserve(N) instead.
      • Removed basic_registry<...>::capacity<T>, use basic_registry<...>::storage<T>().capacity() instead.
      • Removed basic_registry<...>::shrink_to_fit<T>, use basic_registry<...>::storage<T>().shrink_to_fit() instead.
      • Removed basic_registry<...>::size<T>, use basic_registry<...>::storage<T>().size() or a single type view instead.
      • Removed basic_registry<...>::empty<T>, use basic_registry<...>::storage<T>().empty() or a single type view instead.
      • Removed basic_view<...>::raw for single type views, use basic_view<...>::storage().raw() instead.
      • Removed basic_view<...>::data for single type views, use basic_view<...>::storage().data() instead.
      • Removed basic_group<...>::raw<T>, use basic_group<...>::storage<T>().raw() instead.
      • Removed basic_group<...>::data<T>, use basic_group<...>::handle().data() instead.
      • Removed basic_registry<...>::orphans, combine each and orphan instead.
      • Removed basic_registry<...>::visit(e, F), use the new iterable object to iterate pools instead.
      • Removed basic_registry<...>::visit, use basic_registry<...>::storage() instead.
    • meta:

      • Meta sequence containers ::insert no longer returns also a bool value but the iterator is contextually convertible to bool now.
      • Meta sequence containers ::erase no longer returns also a bool value but the iterator is contextually convertible to bool now.
      • meta_arg requires to pass the list of arguments as a type list template parameter instead of as a function argument.
      • Removed meta_type::is_void, use type == resolve<void>() instead.
      • Removed parent link from meta objects, no alternative provided.
      • Removed meta_type::reset, use the meta_reset functions instead.
      • Removed meta_type::rank, no alternative provided.
      • Removed meta_type::extent, no alternative provided.
      • Removed meta_type::remove_extent, no alternative provided.
      • Removed meta_type::remove_pointer, use ((*any).type()) instead.
      • Removed meta_type::is_function_pointer, no alternative provided.
      • Removed meta_type::is_union, no alternative provided.
      • Removed meta_type::is_integral, use meta_type::is_arithmetic instead.
      • Removed meta_type::is_floating_point, use meta_type::is_arithmetic instead.
      • Meta default constructors are no longer returned from a direct lookup nor during iterations.
      • Removed meta_type::is_member_object_pointer, no alternative provided.
      • Removed meta_type::is_member_function_pointer, no alternative provided.
      • Removed the possibility of invoking meta_factory<...>::prop multiple times, use ::props instead.
      • Removed annotation support for meta properties, no alternative provided.
      • Removed meta_ctor and all meta_type::ctor overloads, no alternatives provided.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I started a long term process to reduce the number of instantiations and also speed up the compilation. This release contains many changes and great improvements in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.8.1(Jul 28, 2021)

    Changelog

    • core:

      • Make is_equality_comparable[_v] work with iterators that have a non-comparable value_type.
    • entity:

      • Suppress warning for discarding a nodiscard value in the snapshot class.
      • Removed an inconsistent test that fails sporadically.
    • meta:

      • Avoid a risky fallthrough in the meta_any vtable.

    Bug fixes

    • Fixed an UB when id type is std::uint64_t.
    • Fixed a sparse set class issue with pages not always properly created during an emplace when in-place deletion policy is enabled.

    Build system

    Added everything needed to also run tests with id type std::uint64_t on the CI.

    Deprecated feature

    None.

    Breaking changes

    None.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.8.0(Jul 21, 2021)

    Changelog

    • config:

      • Added error messages to ENTT_ASSERT.
      • Added ENTT_LAUNDER to support older compilers that don't offer std::launder.
      • Replaced ENTT_PAGE_SIZE with ENTT_SPARSE_PAGE and ENTT_PACKED_PAGE.
      • Added ENTT_NOEXCEPTION to fully suppress support for exceptions.
      • ENTT_NO_EXCEPT is automatically defined.
      • Added ENTT_THROW, ENTT_TRY and ENTT_CATCH.
    • core:

      • Refined aggregate support in any to make it closer to its standard counterpart.
      • Added make_any and forward_as_any functions.
      • Drastically reduced the number of instantiations/size of vtables due to any.
      • Added basic_any<...>::owner to know if the wrapper also owns the contained object.
      • Added traits is_iterator[_v] and is_iterator_type[_v].
    • entity:

      • Storage is always in a valid state upon component removal (component destructors can RW access their own pools).
      • Updated ::raw member function for views and groups to make it opaque (support for fancy pointers from storage).
      • Updated basic_sparse_set<E>::remove to make it work also with entities that aren't part of the set.
      • Added basic_sparse_set<E>::erase that works only with entities that are already in the set.
      • basic_registry<E>::remove<T...> also accepts entities that don't have the given components (replaces ::remove_if_exists).
      • Added basic_registry<E>::erase<T...> that triggers an error if the entities don't have the given components (it was ::remove).
      • basic_handle<E>::remove<T...> also accepts types that aren't assigned to the entity (replaces ::remove_if_exists).
      • Added basic_handle<E>::erase<T...> that triggers an error if the entity doesn't have the given components (it was ::remove).
      • Allocator support for sparse sets and storage classes.
      • to_entity returns entt::null for invalid components.
      • Much faster registry::create for multiple entities (about twice the performance).
      • basic_registry<E>::insert and basic_storage<E, T>::insert with component array no longer require the end iterator.
      • Review of entt_traits design (added built-in functions ::to_entity, ::to_integral, ::to_version, and so on).
      • Entity type for class type identifiers is borrowed from entity_type member type (specializing entt_traits is no longer required).
      • Exception safety for all storage functions is either strong or basic.
      • Added the tombstone_t type and the entt::tombstone constexpr variable for tombstone versions.
      • Updated the registry to skip the tombstone version and overflow to 0 on entity deletion.
      • Added null_t::operator| to combine the null entity with any identifier (similar to tombstone_t::operator|).
      • Added component_traits (see component.hpp) to set the ETO policy (ignore_if_empty) and the deletion policy (in_place_delete).
      • Prevented groups from being mixed with tombstone.
      • Added support to compact one, more or all pools from the registry API.
      • Split views and view_iterators, drastically reduced the number of instantiations due to views.
      • Added stable/packed storage policy support to views (automatic detection of the deletion policy).
      • Added basic_sparse_set<E>::policy method for opaque runtime detection of the deletion policy.
      • Added support for storage policy (tombstones) to runtime views (automatic detection of the deletion policy).
      • Support for in-place deletion and pointer stability upon deletion on a per-type basis with automatic detection during iterations.
      • Support for pointer (and therefore reference) stability when assigning components to entities.
      • Registry const ::view/::group function also support non-const types.
      • Added ::release (aka force-destroy) overloads to the registry class.
      • Added ::released function to the registry class to replace ::destroyed.
      • Fast path on non-view iterators for range basic_registry<E>::destroy.
      • Improved performance on component destruction (it affects multiple functionalities like destroying entities and components).
      • Allow storage classes to inhibit component destruction for any reason.
      • Added the basic_sparse_set<E>::slot function to return the next slot available for insertion.
      • basic_sparse_set<E>::emplace returns now the slot used for insertion.
      • Added basic_sparse_set<E>::emplace_back function to force back insertion (and skip the tombstone chain check).
      • Allow non-const types in const overloads of registry context variable getters.
    • meta:

      • C-style arrays (eg T[N] or T[N][M]) aren't treated as pointer-like types.
      • Added make_meta and forward_as_meta functions.
      • Drastically reduced the number of instantiations/size of vtables due to meta_any.
    • resource:

      • Added a bunch of conversion functions to resource_handle.
    • Performance improvements here and there (ie registry ::create and ::destroy, component destruction/emplace/insert, ...).

    Bug fixes

    • core:
      • basic_any<...>::operator=(const basic_any<...> &other) can result in an invalid state when other isn't copyable.

    Deprecated feature

    • core:

      • Deprecated std::reference_wrapper support: use std::in_place_type<T &>, use make_any or ::emplace<T &> instead.
    • entity:

      • basic_registry<E>::remove_if_exists: use ::remove instead (it also supports iterators).
      • basic_handle<E>::remove_if_exists: use ::remove instead (it also supports iterators).
      • basic_registry<E>::remove_all: use ::destroy(e); ::create(e) instead.
      • basic_handle<E>::remove_all: no longer supported.
      • basic_registry<E>::reserve_pools: no longer supported.
      • basic_registry<E>::destroyed: use ::released instead.
    • meta:

      • Deprecated std::reference_wrapper support: use std::in_place_type<T &>, use make_meta or ::emplace<T &> instead.

    Breaking changes

    • config:

      • ENTT_ASSERT now receives two arguments (condition and error message).
      • Removed ENTT_PAGE_SIZE, use ENTT_SPARSE_PAGE and ENTT_PACKED_PAGE instead.
      • Defining ENTT_NO_EXCEPT triggers an error, use ENTT_NO_EXCEPTION to fully disable exceptions instead.
    • core:

      • Removed entt::is_empty[_v] and ENTT_IS_EMPTY, no longer required/supported.
    • entity

      • view::raw and group::raw return now a paged array of components (for pointer stability).
      • basic_registry<E>::insert and basic_storage<E, T>::insert no longer require the end iterator.
      • No longer required to specialize entt_traits. Otherwise, provide member function ::to_entity, ::to_version, and so on.
      • Removed about_to_pop virtual function from the sparse set class.
    • poly:

      • Removed std::reference_wrapper support (reference in-place construction still available).
    • process:

      • process::dead has been renamed to process::finished.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I started a long term process to reduce the number of instantiations and also speed up the compilation. This release contains many changes and great improvements in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.7.1(Apr 14, 2021)

    Changelog

    • core:

      • Extended support to both aggregates and non-aggregates type for any.
      • No more redundant copies in any when emplacing (as in .emplace<T>(args...)).
      • No more redundant copies in any when emplacing (as in = value).
      • No more redundant copies in any when resetting (as in .reset()).
    • entity:

      • Updated iterable views (view.each()) to make them work with <algorithm> in all cases.
      • Updated iterable groups (group.each()) to make them work with <algorithm> in all cases.
    • meta:

      • Extended support to both aggregates and non-aggregates type for meta_any.
      • No more redundant copies in meta_any when emplacing (as in .emplace<T>(args...)).
      • No more redundant copies in meta_any when emplacing (as in = value).
      • No more redundant copies in meta_any when resetting (as in .reset()).
      • Reduced instantiations due to meta_prop.

    Bug fixes

    None

    Breaking changes

    • core:
      • Removed trait is_std_hashable[_v].

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release contains some more changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.7.0(Apr 2, 2021)

    Changelog

    • core:
      • Added support for non-copyable types to any.
      • Standard containers friendly is_equality_comparable trait.
      • Added type_list_diff[_t] trait.
      • Added any::reset().
      • Copying an any always returns a copy of the contained object, even in case of references to external elements.
      • Added is_std_hashable[_v] trait.
      • type_id<T>() is a [[nodiscard]] function now.
      • any::as_ref is a member function rather than an in-class friend function exported in the global namespace.
      • basic_any supports configurable sbo size, any is an alias for basic_any<sizeof(double[2])>.
      • Added eventually constexpr conversion operator to underlying type to type_seq.
      • Added eventually constexpr conversion operator to underlying type to type_hash.
      • Added eventually constexpr conversion operator to underlying type to type_name.
      • basic_any takes now in consideration implicit alignment requirements for in_situ tests.
      • Added an extra parameter to basic_any to specify desired alignment requirements for the SBO storage.
    • entity:
      • Avoid UB with sparse_set::clear and component-less registry::clear.
      • Use entt::any to store context variables in a registry.
      • registry::storage returns actual references (eventually const) to the poly storage objects.
      • Added basic_sparse_set<E>::at to get entities at given positions.
      • Stable virtual remove for sparse sets.
      • Poly storage no longer has a remove member function by default.
      • Faster registry::clear that delegates to pools.
      • Added optional user data to basic_sparse_set<E>::remove and basic_sparse_set<E>::clear.
      • Simplified sigh_storage_mixin, less instantiations, less code, same functionalities.
      • Added unchecked basic_sparse_set<E>::operator[](pos).
      • Added support to aliased context variables (externally managed objects attached to a registry by reference).
      • Added an operator| to views for piping that creates a new view rather than a view pack.
      • Non-allocating non-const registry::try_get.
    • meta:
      • Implicitly generated default meta constructors for default constructible types.
      • Pointer-like to void support (dereference to invalid meta_any).
      • All overloads of meta_type::base return instances of meta_type now.
      • User defined getters are detected as are data members (is_invocable<F, [const] T &> instead of is_invocable<F, [const] T *>).
      • as_ref_t adapts to the constness of the underlying object/return type, as_cref_t always returns by const reference.
      • Added meta_any::reset().
      • Internal utilities (like meta_function_descriptor and meta_invoke) are now public for use as needed.
      • Support for std::vector<bool> and the like as meta containers.
      • Added support for self-pointers and proxy pointers to meta_any when used as pointer-like types.
      • Added explicit const meta_handle::operator bool().
      • Copying a meta_any always returns a copy of the contained object, even in case of references to external elements.
      • Added minimal customizable class template detection support to meta_type (see for example is_template_specialization).
      • meta_any::operator== is now consistent across boundaries.
      • meta_any::as_ref is a member function rather than an in-class friend function exported in the global namespace.
      • Re-registering meta objects is safe in all cases unless the meta objects has a name and the id is already used by a different element (hard user error).
      • A meta_prop key is now returned by const reference rather than by copy.
      • Removed has_meta_sequence_container_traits[_v] and has_meta_associative_container_traits[_v].
      • Meta destructors are no longer invoked for non-owning meta_any objects.
    • resource:
      • Removed the requirement for shared_ptr<T> from the loader/cache.
    • poly:
      • Added poly::reset().
      • Copying a poly always returns a copy of the contained object, even in case of references to external elements.
      • poly<T>::as_ref is a member function rather than an in-class friend function exported in the global namespace.
      • poly supports configurable sbo size with a default of sizeof(double[2]).
      • Added an extra parameter to poly to specify desired alignment requirements for the underlying storage.
    • signal:
      • Made dispatcher class work fine with std::is_copy_constructible.
    • Build system:
      • Updated Bazel configuration.
      • Added pkg-config support upon installation.
      • Use lcov for code coverage on the CI.

    Bug fixes

    • entity:
      • Fixed an issue with registry::clear. There are two ways to get around it in v3.6.x:
        • registry.each([&](auto entity) { registry.destroy(entity); }); if interested in signals.
        • registry = {}; if not interested in signals.

    Breaking changes

    • core:
      • In-place construction of references in any requires the argument to be an actual lvalue reference and not a pointer.
      • Copying an any always returns a copy of the contained object, even in case of references to external elements. Move the any object, pass it by reference or use as_ref to propagate elements without copying them.
      • Free function as_ref no longer exists for any, use any::as_ref() instead.
      • ENTT_PAGE_SIZE sets the number of elements of a page, not the size in bytes.
    • entity:
      • Removed registry::raw<T>(), use registry.view<T>().raw() instead.
      • Removed registry::data<T>(), use registry.view<T>().data() instead.
      • Updated precondition of registry::assign (all pools empty -> no entities still alive).
      • Renamed registry::has<T...> to registry::all_of<T...> and registry::any<T...> to registry::any_of<T...>.
      • Renamed handle::has<T...> to handle::all_of<T...> and handle::any<T...> to handle::any_of<T...>.
      • registry::storage returns poly storage objects by reference rather than by copy. Capture them by reference before using.
      • Poly storage no longer has a remove member function by default.
      • Const registry::view is no longer thread safe.
    • meta:
      • Removed meta_conv, it's used internally when needed (eg meta_any::allow_cast).
      • Removed meta_base, it's used internally when needed (eg meta_any::cast).
      • All overloads of meta_type::base return instances of meta_type now.
      • Meta iterators for associative containers return keys as const references and no longer by copy.
      • meta_handle::operator* isn't available anymore, no alternatives provided.
      • Copying a meta_any always returns a copy of the contained object, even in case of references to external elements. Move the meta_any object, pass it by reference or use as_ref to propagate elements without copying them.
      • Renamed meta_ctor::size and meta_func::size to meta_ctor::arity and meta_func::arity.
      • Deleted meta_handle copy constructor. No alternatives provided. Meta handles should never be copied.
      • Free function as_ref no longer exists for meta_any, use meta_any::as_ref() instead.
      • Removed has_meta_sequence_container_traits[_v] , use entt::is_complete_v<entt::meta_sequence_container_traits<T>> instead.
      • Removed has_meta_associative_container_traits[_v], use entt::is_complete_v<entt::meta_sequence_associative_traits<T>> instead.
    • poly:
      • Copying a poly always returns a copy of the contained object, even in case of references to external elements. Move the poly object, pass it by reference or use as_ref to propagate elements without copying them.
      • Free function as_ref no longer exists for poly<T>, use poly<T>::as_ref() instead.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the section EnTT in Action with more and more examples.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release contains some more changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.6.0(Jan 9, 2021)

    Changelog

    Short version (aka most wanted/relevant changes)

    • Stamp is back. 😄
    • Truly const and therefore const thread safe registry.
    • meta_any as well as the new any class support const references.
    • I've added the organizer class to create a minimal dependency graph for your systems.
    • The EnTT type system was improved and type_info is now an opaque type returnd by type_id<T>.
    • There is a new module called poly for automated static polymorphism.
    • Full support for custom pools is finally a (very important) thing.

    Long version (aka all you can find in v3.6.0)

    • config:

      • Reintroduced ENTT_DISABLE_ASSERT to fully disable asserts.
    • core:

      • Added sfinae-friendly class type_seq to provide sequential identifiers for types.
      • Added sfinae-friendly class type_hash to provide unique identifiers for types.
      • Added sfinae-friendly class type_name to provide demangled names for types.
      • Added untyped class type_info as a replacement for the template class type_info<T>.
      • Added type_id function template to generate untyped type_info objects from types:
        auto info = entt::type_id<a_type>();
        
      • Added utility type_list_contains[_v].
      • Added size_of_v, an extension for sizeof that doesn't complain when used with functions or incomplete types.
      • Added type_list<T...>::size to know the number of types of a type list.
      • Added operator+ for type lists (similar to type_list_cat[_t], but for variables rather than types):
        constexpr auto list = entt::type_list<int, char>{} + entt::type_list<double>{};
        
      • Added traits is_applicable[_v] and is_applicable_r[_v], a sort of std::is_invocable with tuples.
      • Added trait is_empty[_v] (mainly used for internal purposes) that is true only if ENTT_NO_ETO isn't defined.
      • Updated default page size (ENTT_PAGE_SIZE) to 4096.
      • hashed_string::value is now constexpr, suitable for uses with string views in constant expressions.
      • Added trait constness_as[_t] to transfer the constness between types.
      • User defined literals for hashed strings (_hs and _hws) have been moved to the namespace entt::literals.
      • Added trait is_complete[_v] to detect complete types.
      • Standalone, branchless implementation of entt::any with a default SBO size of sizeof(double[2]).
      • entt::any support for both const and non-const references (extended to meta and poly, see below).
      • Added entt::any_cast overloads similar to what the standard library offers.
      • Added as_ref to create aliases to unmanaged objects with any.
      • Added value_list and value_list_cat[_t] (similar to type_list and type_list_cast[_t], but for values rather than types).
      • Added type_identity[_t] trait (waiting for a C++20 version of EnTT).
      • Added type_list_element[_t] for type_lists, similar to std::tuple_element_t.
      • Added value_list_element[_v] for value_lists, similar to std::tuple_element_t.
    • entity:

      • Full support for custom storage/views (🥳). This is HUGE, even if at the moment it lacks proper documentation.
      • storage_adapter_mixin and sigh_pool_mixin are now independent from each other. It's also easy to set a signal-less default pool:
        template<typename Entity, typename Type>
        struct pool<Entity, Type> {
            using type = storage_adapter_mixin<basic_storage<Entity, Type>>;
        };
        
      • Added multi-type view ::size_hint member function.
      • registry::visit and registry::ctx return now a whole type_info object rather than the sole identifier.
      • It's now possible to create truly invalid instances of entt::handle.
      • Added the new class organizer to create a minimal dependency graph for your systems, see the documentation for further details.
      • storage::emplace returns now the newly created object.
      • Introduced the alias value_type as a replacement for object_type (storage, pool).
      • Added basic_group<...>::each() and basic_view<...>::each() as a replacement for ::proxy.
      • Reduced scope for candidate selection in views.
      • Extended get for views and groups:
        auto [pos, vel] = registry.view<position, velocity>().get(entity);
        
      • Added the view_pack class template to combine views and decide what type leads the iteration:
        for(auto entity: registry.view<position>() | registry.view<velocity>()) {
            // ...
        }
        

        The intended use for this tool is with custom storage/views, but it's also useful in everyday uses. The view pack is a view-like object, similar to a multi-type view. It's also iterable and it offers both each(func) and each() as well:

        for(auto [entity, pos, vel]: (registry.view<position>() | registry.view<velocity>()).each()) {
           // ...
        }
        

        A view pack converts to references to its views. See the documentation for further details.

      • Callbacks with entity are now the first choice for views and groups.
      • Iterable views and groups (each()) also offer reverse iterators.
      • registry::assign also requires the head of the list of destroyed entities now and is much (much!) faster.
      • Added registry::destroyed to get the head of the list of destroyed entities (to use with ::raw and ::assign).
      • Added view<...>::use<T> to multi-type views to force the pool to use a given storage (useful when using iterators).
      • Added the handle_view class, a more restricted version of handle which also specifies the types it operates on (conversion operators available).
      • Relaxed the requirement to expose a try_get member functions for (custom) storage classes.
      • Added the entt::get_as_tuple function to get the content of a storage given an entity as a (possibly empty) tuple.
      • Added the sfinae-friendly storage_traits class to provide information on storage classes.
      • Views constructors are public now, it's possible to create views from custom or externally managed storage.
      • Added runtime view ::size_hint member function.
      • Default constructible, invalid (pool-less) groups, views and runtime views.
      • Truly const and therefore const thread safe registry (currently based on pool-less views).
      • Support for destroying entities from a handle (namely basic_handle<Entity>::destroy).
      • Added poly_storage, fully customizable poly_storage_traits and const/non-const registry::storage for opaque proxies to pools (aka welcome back stamp, copy, ...). 🙂
      • Added registry::reserve_pools to reserve enough storage for pools when needed.
    • meta:

      • Added opaque meta_type::size_of to know the size of the underlying type.
      • Added meta_type::info as a replacement for meta_type::hash.
      • Extended resolve, it accepts now a type as a template parameter, or an unique identifier or type info object as an argument.
      • Meta functions and meta constructors finally support external functions:
        entt::meta<Type>().type("Type"_hs).func<&entt::registry::emplace_or_replace<Type>, entt::as_ref_t>("emplace"_hs);
        
      • Added meta function overload support.
      • Container traits are no longer an internal details only.
      • A meta_any that doesn't contain a pointer-like object can be safely dereferenced and will return an invalid instance.
      • meta_any uses entt::any internally rather than meta_storage.
      • Reduced instantiations due to meta_any using a single fake vtable function internally.
      • Added as_ref to create aliases to unmanaged objects with meta_any.
      • Support for const references when working with aliased objects.
      • Added the as_cref_t policy to receive data members and return values as const references.
      • Pointer-like types to const elements return wrapped const references rather than making a copy of the pointed object.
      • Meta containers support for const containers, their const iterators and const references to their elements.
      • Added meta_any::allow_cast as a better, more flexible alternative for meta_any::convert.
      • Added const and non-const overloads of meta_any::get and meta_any::invoke.
      • Direct alias constructor for meta_any:
        int value = 42;
        entt::meta_any any{std::in_place_type<int>, &value};
        
      • Added const and non-const overloads for operator*, as_sequence_container and as_associative_container to meta_any.
      • Support for pointer-like types with a custom dereference operator other than operator*.
    • poly:

      • Added a new module called poly for automated static polymorphism. See the official documentation for all the details and usage instructions.
    • signal:

      • Truly const and therefore const thread safe emitter.
    • The single include file also contains the version now.

    • Allow compilation for Windows with GNU-like compilers.

    • Performance improvements here and there (registry::create, registry::clear, storage remove and range-remove, ...).

    Breaking changes

    • config

      • ENTT_STANDALONE has been removed.
      • ENTT_HS_SUFFIX has been removed.
      • ENTT_HWS_SUFFIX has been removed.
    • core:

      • type_index has been removed, use type_seq instead.
      • has_type_index[_v] utility has been removed.
      • type_info is not longer a class template. See the untyped version of type_info, the type_id function template, other than type_seq, type_hash and type_name for further details.
      • Removed type_list_size[_v], use type_list<T...>::size instead.
      • is_eto_eligible[_v] is now is_empty[_v].
      • Importing entt::literals namespace is required in order to use user defined literals for hashed strings (_hs and _hws).
    • entity:

      • registry::visit and registry::ctx return now a whole type_info object rather than the sole identifier.
      • Removed multi-type view ::empty because it was misleading, use ::size_hint instead.
      • Removed multi-type view ::size because it was misleading, use ::size_hint instead.
      • Removed multi-type view ::size<T>, raw<T> and data<T> because they were misleading.
      • Removed the alias object_type, use value_type instead (storage, pool).
      • Removed basic_group<...>::proxy and basic_view<...>::proxy, use ::each() instead.
      • Single type views return an std::tuple<T> when the type isn't provided to the ::get member function (uniformity purpose for extended selection).
      • Callbacks with entity are now the first choice for views and groups.
      • registry::assign also requires the head of the list of destroyed entities (see ::destroyed).
      • Removed chunked iteration for multi-type views, there was no way to make it consistent across all views with custom storage.
      • pool_traits is replaced by storage_traits.
      • Removed member functions ::size<T>, ::empty<T..> and data<T> from groups, they provide misleading information.
      • Reduced the scope of the member function ::raw for groups, it provides misleading information.
      • Removed runtime view ::empty because it was misleading, use ::size_hint instead.
      • Removed runtime view ::size because it was misleading, use ::size_hint instead.
    • meta:

      • Removed meta_type::hash, use meta_type::info instead.
      • Removed resolve_id, use resolve instead.
      • Removed resolve_type, use resolve instead.
      • Removed meta_storage, replaced by entt::any.
      • Removed as_ref tag, no replacement available.
      • Removed meta_any::ref, use as_ref(any) instead.
      • Removed meta_any::convert, use meta_any::allow_cast instead.
    • EnTT across boundaries:

      • Standalone mode is now the default. To make EnTT work across boundaries, you've to provide support for contiguous identifiers. See the examples in the test directory for more details.

    Deprecated features

    All previously deprecated functions and classes have been removed. This release contains many breaking changes. There was no way to make a smooth transition because of the amount and nature of these changes. Because of that, I decided to not deprecate functions when possible and remove them directly instead. See the above section for a migration guide.

    Examples

    I'm adding some examples (see test/example) to answer the most frequently asked questions. Custom storage/views also deserve a fair number of examples. I'll add them time by time as possible.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    There are a couple of extra pages available in the documentation:

    • UE4 usage instructions.
    • poly module.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release contains some more changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.5.2(Sep 22, 2020)

    Changelog:

    • meta:
      • Implemented shortcuts for meta-functions and meta-data (see meta_any and meta_type).
      • meta_any support for pointer-like types to non-const, non-copyable types.

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the section EnTT in Action with more and more examples.

    Source code(tar.gz)
    Source code(zip)
  • v3.5.1(Sep 4, 2020)

    Changelog:

    • entity:

      • Fixed an issue in the observer class with exclusion lists.
      • Updated difference_type for 32b identifiers.
      • Removed support for 16b identifiers.
    • test:

      • Make all tests work despite the aggressive comdat folding on Windows in release mode.

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.5.0(Aug 31, 2020)

    Changelog

    • core:

      • Added type_info::name member function.
      • Added unpack_as_t and unpack_as_v utilities as type traits.
      • Added is_eto_eligible[_v] utility for internal purposes.
    • entity:

      • entt_traits: updated types for difference_type.
      • registry::remove_if_exists returns the number of elements actually removed.
      • Added an overload of registry::sortable for groups.
      • Relaxed requirements on types from at least copyable to at least movable for the snapshot class.
      • entt_traits as sfinae-friendly class template to allow user defined custom identifiers other than enum classes.
      • to_integral no longer depends on identifiers, it works instead for all types for which a specialization of entt_traits exists.
      • Added the non-owning entt::handle class to wrap a couple entity/registry and pass it as argument to functions.
      • Made entt::null_t publicly available.
      • Added view::proxy member function that returns an iterable object to visit entities and components at once.
      • Added group::proxy member function that returns an iterable object to visit entities and components at once.
      • entt::to_entity function that returns the entity associated with a given component.
      • Runtime views also support excluded components.
      • Added a sfinae-friendly utility for component-to-pool conversions.
      • Chunked iteration for multi-component views.
      • Added reverse iterators, rbegin and rend to sparse_sets.
      • Added reverse iterators, rbegin and rend to storages.
      • Added reverse iterators, rbegin and rend to groups.
      • Added reverse iterators, rbegin and rend to views.
      • views use only stable candidates and refresh them less frequently.
    • meta

      • Allowed null setters on meta data members (explicit read-only mode).
      • .data<&clazz::member> is now an alias of .data<&clazz::member, &clazz::member> and therefore supports non-const to const conversion for data members (literally .data<nullptr, &clazz::member>).
      • Defined a meta_range<T> iterable type to visit all meta objects of a given type.
      • Added an overload of meta_ctor::prop that returns an iterable object to visit all properties.
      • Added an overload of meta_data::prop that returns an iterable object to visit all properties.
      • Added an overload of meta_func::prop that returns an iterable object to visit all properties.
      • Added an overload of meta_type::base that returns an iterable object to visit all bases.
      • Added an overload of meta_type::conv that returns an iterable object to visit all conversion functions.
      • Added an overload of meta_type::ctor that returns an iterable object to visit all constructors.
      • Added an overload of meta_type::data that returns an iterable object to visit all data members.
      • Added an overload of meta_type::func that returns an iterable object to visit all member functions.
      • Added an overload of meta_type::prop that returns an iterable object to visit all properties.
      • resolve offers an overload that returns an iterable object to visit all meta types.
      • meta_type::rank returns the rank of an array when the meta type wraps a C-style array, 0 otherwise.
      • meta_type::extent accepts also the dimension (default to 0).
      • meta_handle is now copyable.
      • Built-in support for containers.
      • Built-in support for pointer-like types.
      • meta_any::operator* dereferences the wrapped element in case of pointer-like types and returns a wrapper for the pointed object.
      • Meta constructors and meta functions also accept a meta_any * + size pair.
      • Added meta_type::reset member function to reset meta types and remove them from the list of searchable types.
    • platform:

      • Added a support file to use EnTT on Android with the NDK r17.
    • signal:

      • delegate supports runtime parameters with optional payload.
      • delegate accepts non-capturing lambda functions as runtime parameters.
      • dispatcher::enqueue supports also aggregates.
      • Added opaque disconnect function to dispatcher.
      • The event passed to the listeners of a dispatcher isn't const by default anymore.
      • The event passed to the listeners of an emitter isn't const by default anymore.
    • type_index based lookup is now an opt-in alternative for standalone applications and no longer the default.

    • Added a new section in the wiki about the available definitions to be used to tune the library.

    • Added meaningful messages to static asserts.

    • [[nodiscard]] everywhere.

    • Performance improvements here and there (sparse set expansion, ...).

    Breaking changes

    • core:

      • ENTT_OPAQUE_TYPE is no longer available, define your own enum class or custom type instead.
    • entity:

      • group::sortable is no longer available, use registry::sortable.
    • meta:

      • meta_type::set and meta_type::get overloads to work with the i-th element of a C-style array are no longer available.
      • meta_any::operator* is not longer an alias for ref and dereferences pointer-like elements instead.
      • meta_ctor::prop with callback is no longer available, use the overload of meta_ctor::prop that returns an iterable object.
      • meta_data::prop with callback is no longer available, use the overload of meta_data::prop that returns an iterable object.
      • meta_func::prop with callback is no longer available, use the overload of meta_func::prop that returns an iterable object.
      • meta_type::base with callback is no longer available, use the overload of meta_type::base that returns an iterable object.
      • meta_type::conv with callback is no longer available, use the overload of meta_type::conv that returns an iterable object.
      • meta_type::ctor with callback is no longer available, use the overload of meta_type::ctor that returns an iterable object.
      • meta_type::data with callback is no longer available, use the overload of meta_type::data that returns an iterable object.
      • meta_type::func with callback is no longer available, use the overload of meta_type::func that returns an iterable object.
      • meta_type::prop with callback is no longer available, use the overload of meta_type::prop that returns an iterable object.
      • resolve with callback is no longer available, use the overload of resolve that returns an iterable object.
      • resolve_if is no longer available, use the overload of resolve that returns an iterable object.
      • meta_factory<...>::reset has been replaced by meta_type::reset.
    • resource:

      • cache has been renamed to resource_cache.
      • handle has been renamed to resource_handle.
      • loader has been renamed to resource_loader.
    • signal:

      • Renaming of exported functions: delegate::function_type becomes delegate::type.

    Deprecated features

    All previously deprecated functions and classes have been removed. This is the list of features deprecated with this release:

    • entity:
      • The actor class will be removed in a future release.

    Examples

    • Added an example of custom identifier that isn't an enum class and is initialized with entt::null by default.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release contains some more changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.4.0(May 9, 2020)

    Changelog

    • config:

      • Added ENTT_IS_EMPTY as an opaque way to recognize empty types (ENTT_DISABLE_ETO affects also this variable).
    • core:

      • Added entt::id_type as an user-friendly alternative for ENTT_ID_TYPE.
      • Added the entt::type_index class sfinae-friendly template to assign library wide sequential identifiers to types.
      • Added entt::has_type_index[_v] to know if a given type T has assigned a library wide sequential identifier.
      • Added entt::integral_constant as a shortcut for its standard counterpart.
    • entity:

      • Added registry::remove_all to orphan entities.
      • Added registry::patch<T> to replace an object in-place.
      • Added registry::on_update<T> to attach listeners to observe changes.
      • Added registry::emplace<T> to assign components to multiple entities at once.
      • Added registry::insert<T> to assign components to entities.
      • Added registry::get_or_emplace<T> get a component and construct it if it doesn't exist yet.
      • registry::replace from arguments is no longer deprecated and still available.
      • Added storage<T>::emplace to assign objects to entities.
      • Added storage<T>::insert to assign objects to multiple entities at once.
      • Added sparse_set::emplace to assign objects to entities.
      • Added sparse_set::insert to assign objects to multiple entities at once.
      • Added entt::invoke, a shortcut to invoke members on components from callbacks.
      • Added registry::destroy with suggested version.
    • meta:

      • Added meta_type::detach to make it possible to detach meta type from contexts (for example, during a visit).
      • Added a reviewed version of meta_factory::type that uses type_info<T>::id() as a default initializer.
      • Added meta_type::type_id to get the type id of the underlying (erased) type.
      • Added entt::resolve_if to lookup meta types using custom predicates.
      • Added entt::resolve_id to lookup meta types by identifier.
      • Added entt::resolve_type to lookup meta types by type id.
      • Added meta_any::ref to invoke aliasing constructor and get references to unmanaged objects.
    • Performance improvements here and there (more devirtualization, less branches, ...).

    Build system

    • homebrew-entt is automatically updated on tags.
    • Updated installation process.

    EnTT across boundaries

    It turned out that the latest version had a problem when multiple registries containing different component types were used concurrently from different threads (see #449 for further details). Because of this, the way used to make EnTT work across boundaries has changed and has been further refined. There exist now two paths within some of the data structure available in EnTT: the default one (also known as indexed access) based on the type_index class and its fallback based on the type_info class.

    In particular:

    • When EnTT is used standalone and its main classes (such as the registry) are not pushed across boundaries, there is nothing to worry about.

    • In case of linked libraries and when exporting the necessary symbols isn't a problem, use the ENTT_API_IMPORT and ENTT_API_EXPORT definitions as appropriate. This will make EnTT use the indexed access even across boundaries.

    • In all other cases, suppress the index generation to force EnTT to use a fallback:

      template<typename Type>
      struct entt::type_index<Type> {};
      

      It's recommended to use range operations as much as possible in this case.

    The lib directory contains many examples for who's interested in the topic. The meta system has not undergone any changes since its previous version.

    Breaking changes

    • Empty types are no longer returned nor are they available in any case.
      • The storage class for empty types doesn't offer anymore get, try_get and so on.
      • Views and groups no longer return empty types during a call to each and don't allow anymore to get an empty type for an entity.
      • ENTT_DISABLE_ETO is no longer considered, use ENTT_NO_ETO instead.
      • ENTT_ENABLE_ETO is no longer exported, use ENTT_IS_EMPTY instead.
    • iterator_type aliases have been renamed to iterator for better integration.
    • meta_type::id returns the type identifier rather than the type id.
    • basic_snapshot<T>::entities stores aside also destroyed entities, not only the ones still alive.
    • basic_snapshot_loader<T>::entities expects also destroyed entities, not only the ones still alive.
    • basic_continuous_loader<T>::entities expects also destroyed entities, not only the ones still alive.

    Deprecated functions

    All previously deprecated functions and classes have been removed. This is the list of features deprecated with this release:

    • registry::replace with callbacks, use registry::patch instead.
    • registry::on_replace, use registry::on_update instead.
    • registry::assign<T> for a single entity, use registry::emplace<T> instead.
    • registry::assign<T> for multiple entities, use registry::insert<T> instead.
    • registry::get_or_assign<T>, use registry::get_or_emplace<T> instead.
    • registry::snapshot, basic_snapshot<T> has now a constructor that accepts a reference to a registry.
    • registry::loader, basic_snapshot_loader<T> has now a constructor that accepts a reference to a registry.
    • storage<T>::construct for a single entity, use storage<T>::emplace instead.
    • storage<T>::construct for multiple entities, use storage<T>::insert instead.
    • storage<T>::destroy, use storage<T>::erase instead.
    • sparse_set::construct for a single entity, use sparse_set::emplace instead.
    • sparse_set::construct for multiple entities, use sparse_set::insert instead.
    • sparse_set::destroy, use sparse_set::erase instead.
    • sparse_set::has, use sparse_set::contains instead.
    • group::less, use group::each instead.
    • view::less, use view::each instead.
    • meta_factory::alias, use meta_factory::type instead.
    • meta_type::alias, use meta_type::id instead.
    • meta_data::alias, use meta_data::id instead.
    • meta_func::alias, use meta_func::id instead.
    • entt::as_alias_t and entt::as_alias, use entt::as_ref_t and entt::as_ref instead.
    • entt::resolve by identifier, use entt::resolve_id instead.
    • observer::replace, use observer::update instead.
    • basic_snapshot<T>::destroyed, use basic_snapshot<T>::entities instead.
    • basic_snapshot_loader<T>::destroyed, use basic_snapshot_loader<T>::entities instead.
    • basic_continuous_loader<T>::destroyed, use basic_continuous_loader<T>::entities instead.
    • basic_continuous_loader::has, use basic_continuous_loader::contains instead.

    Any other business

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release contains some more changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.3.2(Mar 7, 2020)

    Changelog:

    • sparse_set:
      • Removed copy ctor/assignment operator.
    • registry:
      • Fixed a bug that involved late group initialization.
    • Added an experimental workflow to automate the update of homebrew-entt (deploy.yml, --dry-run mode).
    • Updated build system (install process).

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the section EnTT in Action with more and more examples and links.

    The long term process to reduce the number of instantiations and therefore speed up the compilation continues. This release contains some changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.3.1(Feb 28, 2020)

    Changelog:

    • config
      • Updated requirements for ETO, types must also be default constructible.
    • registry
      • Suppressed some warnings with MSVC.
      • assign_or_replace works also with aggregates now.
    • Re-added bazel support (thanks to @zaucy for that).

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.3.0(Feb 22, 2020)

    Changelog:

    • config
      • Using atomics is no longer the default (ENTT_NO_ATOMIC became ENTT_USE_ATOMIC).
      • ENTT_DISABLE_ASSERT no longer exists, ENTT_ASSERT can be redefined now.
    • hashed_string
      • Static to_value renamed to value.
      • The helper function is no longer recursive (long names are now accepted).
    • delegate:
      • Support for unbound members (data and functions).
    • sigh/sink:
      • Support for unbound members (data and functions).
    • sparse_set:
      • Renamed reset to clear.
    • storage:
      • Renamed reset to clear.
      • Added range-construct.
    • registry
      • registry::create doesn't accept anymore a list of default constructible types to assign.
      • Added any to know if an entity has any component from a set.
      • Added range-assign by copy and range-assign from ranges.
      • Added create with hint.
      • Added range-remove
      • Added multi-component remove.
      • Added clear as a replacement for reset<T>() and reset().
      • Added remove_if_exists as a replacement for reset<T>(entity).
      • Added data to get the internal representation of entities (serialization purposes).
      • Added an overload to assign to assign entities to an empty registry (serialization purposes).
      • Added a visit overload to return the runtime identifiers for the components managed by a registry.
      • Added a visit overload to return the runtime identifiers for the components owned by an entity.
      • Added a ctx overload to return the runtime identifiers for the context variables stored in a registry.
      • Added in-place replace member function, deprecated old replace-with-arguments.
      • Added single component prepare functionality (suitable for custom pools).
      • Removed misplaced assert from clone and stomp functionalities.
      • Removed reset member functions (use remove and clear instead).
      • Removed range-stomp.
      • Renamed stomp to stamp.
      • Removed spawning create.
      • Pool access is no always O(1) after the warm-up (it was O(N) before in case of named types).
      • Updated assign to make it stable in case listeners mess with components.
      • Callbacks no longer receive components, use the registry and the entity to get them.
      • Callbacks receive the registry as the first parameter, then the entity.
      • Deprecated stamp and clone (see updated doc for more details).
    • view
      • All iterators are at least bidirectional.
      • Much faster contains.
      • Added front and back to get the first and the last entities.
    • group
      • All iterators are at least bidirectional.
      • Much faster contains.
      • Added front and back to get the first and the last entities.
    • meta
      • Added support for properties to opaque meta types.
      • Added support for non-copyable types to meta_any.
      • Added alias member function to factory and deprecated type.
      • Added alias member function to all meta objects and deprecated identifier.
      • Added meta_type::id to get the underlying type id (see type_info<T>::id for more details).
    • dispatcher
      • Renamed discard in clear for consistency.
    • type_traits
      • Added member_class and member_class_t to get the class from a pointer-to-member type.
    • attribute (new)
      • ENTT_EXPORT, ENTT_IMPORT, ENTT_API, ...
    • type_info (new)
      • Full featured, SFINAE-friendly type_info class template used to provide consistent identifiers and allow custom generators (id static member function).
      • Non-standard compile-time solution and standard runtime fallback that work in 99% of cases.
    • EnTT across boundaries
      • Named types are no longer available nor required.
      • EnTT works across boundaries transparently in many cases now and supports per-type and per-feature generators if required.
    • Renamed to_integer in to_integral (see ENTT_OPAQUE_TYPE for custom identifiers).
    • entt::component doesn't exist anymore (use entt::type_info<T>::id() instead).
    • Full noexcept-ness review.
    • Updated forward-.hpp files.
    • Removed support for Bazel (no longer maintained by community).
    • Removed mod example (there are now better ways to write a plugin system).
    • Performance improvements here and there (eg sparse_set and meta).
    • Reduced compilation time (work in progress).
    • Updated build system (more modern cmake, less warnings with very strict checks).

    Be aware that this release contains some non-backward compatible changes. The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    I started a long term process to reduce the number of instantiations and therefore speed up the compilation. This release already contains some changes in this regard. Still a work in progress though.

    Source code(tar.gz)
    Source code(zip)
  • v3.2.2(Dec 19, 2019)

    Changelog:

    • Workaround for a bug of MSVC (since version 19.24.28314.0).
    • Minor changes to the codebase for maintainability purposes.

    The documentation is up-to-date.

    Source code(tar.gz)
    Source code(zip)
  • v3.2.1(Nov 26, 2019)

    Changelog:

    • The family class no longer decays types implicitly.
    • It's now possible to attach the same meta properties to a meta type after a reset.
    • It's now possible to sort empty types by means of their entities.
    • Suppressed all shadow warnings.
    • Updated test suite.

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.2.0(Oct 29, 2019)

    Changelog:

    • Added EnTT to the GitHub Sponsors program (link in the README file).
    • Added the try online badge to the README file.
    • Moved CI to GH Actions.
    • Use codecov instead of coveralls.
    • Relaxed constraints on the order of types in the group definition.
    • The runtime reflection system finally works across boundaries.
    • In-depth review of the runtime reflection system, backward compatibility not guaranteed.
    • Key/Value pairs, key-only properties, tuples and annotations (invocable) are allowed as meta properties.
    • meta_any uses std::reference_wrapper instead of as_alias_t for aliasing.
    • Added meta_type::compare, meta_any no longer has to store aside comparison functions.
    • New meta_any constructor for unmanaged objects taken from a meta_handle.
    • meta_handle no longer exposes data/try_cast.
    • All meta functions take their arguments by alias and can edit objects in the outer context.
    • Introduced meta_type::remove_extent to get the meta type of the elements of an array.
    • A static assertion forbids using non-copyable types with meta_any.
    • Added dispatcher::discard to clear pools of events.
    • Invocation order guaranteed for signals (sigh, registry, dispatcher, ...).
    • Overloaded sink::before function to insert listeners at specific locations in the signal.
    • sink::disconnect and sink::before support also pointers as instances or payload.
    • delegate supports also pointers as instances or payload.
    • sparse_set::swap and storage::swap accept entities, no longer positions.
    • Sorting pools doesn't require to allocate anymore and is much faster.
    • stomp & spawn work also with const source registries now.
    • Make empty components eat arguments on construction.
    • Multi-component version of registry::reserve, registry::shrink_to_fit, registry::empty.
    • Added registry::prepare to force-create component pools within the registry.
    • Views support exclusion lists (eg registry.view<T>(exclude<U>)).
    • view::get for single component views accepts an optional template parameter for consistency.
    • Multi-component version of view::empty.
    • Multi-component version of group:empty.
    • Sorting groups doesn't require to allocate anymore and is much faster.
    • Nested groups: perfect SoA to the rescue.
    • Allow process to work with delta types other than fundamental ones.
    • Utilities: overloaded and y_combinator.
    • Added is_equality_comparable[_v] trait.
    • Added what is needed for the choice trick, see choice_t/choice from type_traits.hpp.
    • named_type_traits_v<Type> utility/shortcut for named_type_traits<Type>::value.
    • ENTT_DISABLE_ETO macro to disable empty type optimization for components.
    • Macros (for example ENTT_NAMED_TYPE) always require a trailing semicolon.
    • resource_handle, resource_loader and resource_cache are now handle, loader and cache.
    • cache exports both resource_type and id_type.
    • basic_continuous_loader support for map-like containers.
    • Fixed a bug on groups when dependencies between components were set.
    • Fixed a bug of collector::where when multiple rules were declared at once.
    • Marked cmake project explicitly as C++, language C is required only if BUILD_MOD is set to ON.
    • Added cmake support for clang users on Windows.
    • Added namespace qualifier in CMake.
    • Performance improvements here and there (eg groups lookup, stomp & spawn utilities).

    Be aware that this release contains some non-backward compatible changes. The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    Source code(tar.gz)
    Source code(zip)
  • v3.1.1(Sep 5, 2019)

    Changelog:

    • Small perf improvements here and there.
    • Fixed a major bug on the batch creation of entities.
    • Added a few more tests for the batch creation of entities.
    • The runtime reflection system compiles fine with VS2019 when C++20 is in use (latest).

    This release is mainly due to the resolution of the bug on the batch creation of entities. The documentation is up-to-date and the library is battle-tested with 100% coverage as usual.

    Source code(tar.gz)
    Source code(zip)
  • v3.1.0(Aug 29, 2019)

    Changelog:

    • Added radix_sort algorithm.
    • Resource handles are now mutable.
    • Small enhancement to the actor class.
    • entt::null no longer takes the version into account.
    • Updated the codebase so as to remove direct dependencies on hashed strings (eg runtime reflection system).
    • Added support for std::wstrings to hashed string (see the hashed_wstring class and the _hws literal).
    • Entity identifiers are enum classes, user defined types are allowed (see entt::entity and ENTT_OPAQUE_TYPE).
    • entt::registry::component_type has been replaced by the opaque identifier entt::component.
    • Batch creation returns iterators and no longer raw pointers.
    • Added two overloads of registry::create to spawn (literally clone) entities from a prototype.
    • Added registry::stomp to clone/overwrite entities locally or between different registries.
    • Added registry::ctx_or_set to get or create context variables at once (similar to registry::get_or_assign for components).
    • Easy set up for short circuits on the registry class and cross events between different registries.
    • The arguments of the signals emitted by the registry class are entity/registry/component and no longer registry/entity/component.
    • registry::clone accepts also an exclusion list to opt-out from the cloning functionality.
    • Added view::less and group::less. They work like each but they don't return empty types.
    • Added the possibility to sort free instances for owned types (see registry::sort).
    • It's now possible to sort non-owning groups using a custom comparison function.
    • Added excluded components to the list of template parameters of a group.
    • Full featured as_group helper, it supports also observed and excluded components.
    • Added cache::each to allow iteration of all resources in a cache.
    • A more flexible delegate class that accepts also functions with a list of parameters that is shorter than that of the delegate itself.
    • delegate works also with move only types and non-const references.
    • delegate::operator== and delegate::operator!= test the instance as a whole.
    • Removed collector from sigh type, turned sig::collect in a function template.
    • Reviewed sink::disconnect (and added another overload to remove all the listeners at once based on instances or payload).
    • Added connection and scoped_connection, the former is now the return value of sink::connect.
    • delegate and sink accept only references for instances and values, no longer naked pointers.
    • Curried functions return their values as references, no longer as naked pointers.
    • Introduced the observer class to ease the definition of reactive systems.
    • Greatly improved the runtime reflection system and reduced to a minimum the number of copies when meta_any is involved.
    • Added support for void to meta_any, it's treated as a normal type but it contains no values.
    • Added meta_any::try_cast (extended-if-friendly function), assignment operators, in-place constructors and so on.
    • meta_any can finally be used to work also with unmanaged objects.
    • Return values for meta_func are void-friendly and convert to false only in case of errors.
    • Setters and getters for meta_data receive instances as references, no longer as pointers.
    • Added the possibility to set free/member functions as conversion functions on meta_conv.
    • Introduced policies (as_is, as_void, as_alias) in the runtime reflection system.
    • Defined type_list_size and type_list_size_v to get the size of a type list.
    • Fixed a major bug in the clone functionality of the registry class.
    • Fixed a major bug in the range destroy of the registry class.
    • Fixed group::sort with components.
    • Bazel as an alternative build system.
    • Added Conan support in editable mode.
    • Added support for VS2019 through appveyor (CI).
    • Performance improvements here and there (eg construction/destruction of components).

    Classes and features that are no longer available starting from this version:

    • prototype: registry::stomp makes it easier to use a prototype-registry for the same purpose.
    • dependency (and therefore connect, disconnect): new signatures for callbacks allow for short circuits.
    • invoker and basic collectors (null and void ones): added an explicit collect function to sigh.
    • maybe_atomic_t: no longer required.

    The documentation is up-to-date and the library is battle-tested with 100% coverage as usual. I've also updated the FAQs and the section EnTT in Action with more and more examples.

    Source code(tar.gz)
    Source code(zip)
  • v3.0.0(May 16, 2019)

    A major release that represents an important improvement for EnTT, both in terms of performance and functionalities.

    To begin with, this is the first official release that requires and fully supports C++17.
    This is the root cause of some of the API changes that made it no longer backward compatible. However, the API itself has been greatly improved in some of its parts (such as the connect function of thedelegate class).
    Moreover, the library has been converted to snake case, leaving behind the misleading coding style of the previous version.

    Below there is a perhaps incomplete list of features and more or less important updates:

    • Added support for named types as an alternative to the family class.
      • As a consequence, EnTT can now work across boundaries (welcome DLLs).
    • Introduced a full featured runtime reflection system.
    • Introduced a few new utilities: as_view, as_group, label.
    • Removed persistent view, it's no longer available (see groups for further details).
    • Removed raw view, it's no longer available (single component view serves the same purpose now).
    • Support for context variables (sort of registry-wise singletons).
    • Removed support for single instance components.
    • Empty type optimization to reduce memory usage.
    • Improved the registry class in all its parts:
      • Added registry::try_get.
      • Added registry::get_or_assign.
      • Added registry::create overload to generate multiple entities at once.
      • Support for component lists to initialize entities when invoking registry::create.
      • Renamed registry::accommodate to registry::assign_or_replace for consistency.
      • Support for const and non-const types of components (eg registry.view<T>() vs registry.view<const T>()).
      • Support for const overload of registry::view.
      • Support for groups (see below).
      • Added registry::clone functionality.
      • Bulk operations are now available.
    • Extended the delegate class and therefore sigh and dispatcher as a consequence:
      • Support for invocable types that doesn't strictly respect the signature of the delegate.
      • Support for curried functions (available for free functions, they can now accept a payload).
    • Extended the view class:
      • Added view::find to search for specific entities.
      • view::each support lambdas that either accept or not the entity as a first argument (performance improvement).
    • Improved and extended hashed_string:
      • Added hashed_string::to_value static member function.
      • Added possibility to use either int32 or int64 for the value.
    • Slightly improved the resource part, in particular cache and handle classes.
    • Slightly improved the snapshot stuff in all its parts.
    • Slightly improved the monostate class.
    • Added Conan support.
    • Added fwd.hpp headers.
    • Introduced new grouping functionalities: the groups are an extremely powerful tool that allows up to perfect SoA during iterations. They support also exclusion lists. Please, refer to the official documentation for all the details.
    • Introduced pagination for the pools to reduce memory usage on sparse components.
    • Introduced ENTT_DISABLE_ASSERT/ENTT_ASSERT macros to speed up EnTT in debug (see the FAQ from the wiki for more details).
    • Added signal on replace, renamed and extended signals on construction/destruction.
    • Added default aliases for most common cases (eg entt::entity and entt::registry).

    The most important feature both in terms of functionalities and performance are the so-called groups. Let me go a little more in detail. They are divided into three parts and refer to different access patterns, being therefore indicated for different paths, from the most critical to the least relevant:

    • Full-owning groups: they allow what is called perfect SoA. Iterating this type of groups is reduced to iterating a bunch of packed arrays of the same size, all ordered in the same way. Probably we are close to the best that can be achieved in terms of performance.
    • Partial-owning groups: they allow what is called almost-perfect SoA. These groups go with perfect SoA on the types of components they manage to indecently increase performance during iterations and rely on indirection to access the other types of components.
    • Non-owning groups: they know in advance what are the entities that respect a given pattern and take advantage of this to iterate them quickly. However, they don't own any component and therefore rely on direction to retrieve their instances.

    In general, the more types a group owns, the faster it will be to iterate entities and components. Refer to the wiki for all the details.

    I didn't mention all the improvements made to further increase performance, but I want to let you know that there have been many.
    To sum up, EnTT is now faster than ever, more flexible and offers even more features.

    EnTT is still and as always battle-tested with 100% coverage. This doesn't mean that it's bug-free, but gives enough guarantees about its stability for use in production environments.
    The documentation has been updated, as well as the wiki and both reflect the latest version available.

    If I've forgotten anything, do not hesitate to contact me, so as to integrate this section.

    Source code(tar.gz)
    Source code(zip)
  • v2.7.3(Sep 2, 2018)

    Mainly due to some important bugs:

    • Fixed Snapshot::destroyed, it could lead to undefined behavior under certain circumstances (see #128)
    • Fixed Registry::accommodate, it didn't trigger events in any case (see #133)
    • break_t doesn't exist anymore, dependency is now connect/disconnect
    • Delegate/SigH support also const member functions now
    • Suppressed warnings within SparseSet on x86 platforms
    • Updated entt-in-action list
    • Review of the internals
    • Updated build system
    • More tests

    Moreover, ports that have been created/updated:

    • Added unofficial/unsupported port to/branch vs2015 (help is appreciated, otherwise it will get old soon)
    • Updated branch c++17.draft, an up-to-date port of EnTT to C++17 that will replace master sooner or later

    Finally, the documentation has been completely reviewed. The README file is now shorter than ever and I created a set of wiki pages with all the information and crash courses written so far. The wiki pages are also part of the online documentation prepared via doxygen (see menu, related pages) and therefore of the project, dir docs.

    Source code(tar.gz)
    Source code(zip)
  • v2.7.2(Aug 2, 2018)

    Mainly due to some important bugs:

    • Fixed major bug on sparse set (#120)
    • Fixed major bug in the snapshot stuff (#116)
    • Got a logo, finally!
    • Introduced entt::OneShotBubbleSort
    • Added entt::Registry::entity
    • Added entt::label
    • Some performance improvements
    • Updated documentation
    • Better build system
    Source code(tar.gz)
    Source code(zip)
  • v2.7.1(Jul 3, 2018)

    Bug fixing:

    • Runtime views were inherently bugged and they could result in undefined behavior under certain circumstances. They work as expected now.
    Source code(tar.gz)
    Source code(zip)
Owner
Michele Caini
I'm a freelancer and a senior software engineer. What else?
Michele Caini
A fast entity component system (ECS) for C & C++

Flecs is a fast and lightweight Entity Component System with a focus on high performance game development (join the Discord!). Highlights of the frame

Sander Mertens 2.9k Jul 30, 2022
Simple tower defense game using C++ with Entity Component System (ECS)

CubbyTower CubbyTower is a simple tower defense game using C++ with Entity Component System (ECS). The code is built on C++17 and can be compiled with

Chris Ohk 34 Jul 12, 2022
A C++14 Entity Component System

NOTICE: This project is currently in the progress of being rewritten for C++17. Check out this issue if you have any suggestions/know a good way to tr

Elnar Dakeshov 185 Jun 8, 2022
A lightweight but complete ECS implementation for modern C++.

ECS A lightweight but complete ECS implementation for modern C++. Features Cache friendly design implemented on top of an EnTT-like sparse set. Clean,

null 5 Jun 13, 2022
An open source C++ entity system.

anax ARCHIVED: as I haven't maintained this library for at least a couple of years. I don't have the time or interest to work on this. Please use anot

Miguel Martin 455 Jul 10, 2022
Yet another component system

Yet another component system Header-only c++11 entity component system Depends on Parallel hashmap for fast pointer container Compile time type name a

Devil Devilson 11 Jul 30, 2022
Godex is a Godot Engine ECS library.

Godex Godex is a Godot Engine ecs library. Disclaimer: this module is still in development, open an issues to report any problem or a new discussion i

GodotECS 687 Aug 4, 2022
This is an ECS archetecture in Game implemented by C++

ECS This is an implement of the ECS archetecture in Game by C++17 ⭐ Star us on GitHub — it helps! ECS Sun Entity-Component-System Compiler compatibili

yao tang 30 Jul 27, 2022
A faster drop-in replacement for giflib. It uses more RAM, but you get more speed.

GIFLIB-Turbo What is it? A faster drop-in replacement for GIFLIB Why did you write it? Starting in the late 80's, I was fascinated with computer graph

Larry Bank 27 Jun 9, 2022
Dragon's Dice Roller aims to be a lightweight, simple, reliable and easy-to-use dice roller for RPG games.

Dragon's Dice Roller is the first and (so far the only) open source RPG dice roller written in C available on GitHub. It aims to be a lightweight, simple, reliable and easy-to-use dice roller for any kind of role-playing game.

Michael Kolesidis 10 Apr 22, 2022
Replace Minecraft entity with MMD model.

KAIMyEntity Replace Minecraft entity with MMD model. KAIMyEntitySaba 将Github项目 benikabocha/saba (https://github.com/benikabocha/saba) 魔改成一个以JNI形式Expor

null 27 Jul 26, 2022
A foobar2000 component which allows you to load and play ncm files directly.

Play NCM files directly with our favourite How to setup and build project Download foobar2000 SDK and extract into vendor/sdk Download WTL from source

null 33 Jun 7, 2022
OGRE is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce games and demos utilising 3D hardware.

OGRE (Object-Oriented Graphics Rendering Engine) is a scene-oriented, flexible 3D engine written in C++ designed to make it easier and more intuitive for developers to produce games and demos utilising 3D hardware. The class library abstracts all the details of using the underlying system libraries like Direct3D and OpenGL and provides an interface based on world objects and other intuitive classes.

null 2.9k Aug 2, 2022
C++ game engine inspired by quake. Modern rendering and quake mapping tool integration.

Nuake Feel free to join the discord server for updates: What is it Nuake is a game engine written from scratch by myself. It is not meant to be a end-

Antoine Pilote 23 Jul 23, 2022
A lightweight game engine written in modern C++

Halley Game Engine A lightweight game engine written in C++17. It has been used to ship Wargroove, a turn-based strategy game, on Windows, Mac (experi

Rodrigo Braz Monteiro 3.1k Jul 30, 2022
🎨 Modern 2D/3D - Importer • Exporter • Util - Library, also called (AssetIO)

Brand-new modern 3D asset importer, exporter library. This library will include common 3D utils funcs. It is written with C99 but C++ wrappers or othe

Recep Aslantas 150 Jun 8, 2022
A library for high-performance, modern 2D graphics with SDL written in C.

SDL_gpu, a library for making hardware-accelerated 2D graphics easy. by Jonathan Dearborn SDL_gpu is licensed under the terms of the MIT License. See

Jonathan Dearborn 1k Jul 29, 2022
D2DX is a complete solution to make Diablo II run well on modern PCs.

D2DX D2DX is a preservation project for running classic Diablo II/LoD on modern PCs. Version 0.99.403b Mission statement Turn the game into a well beh

null 220 Aug 3, 2022
Exploring the modern rendering landscape

HellTech Engine An WIP exploration of the modern rendering landscape with Vulkan 1.2+ on Windows. REQUIREMENTS: Win10+ Vulkan1.2+ dedicated GPU ( ?, p

null 7 Jul 11, 2022