Function pod_component

Synopsis

#include <include/flecs/cpp/component.hpp>

template <typename T>
flecs::entity pod_component(const flecs::world &world, const char *name=nullptr, bool allow_tag=true)

Description

Plain old datatype, no lifecycle actions are registered

Source

Lines 606-694 in include/flecs/cpp/component.hpp.

template <typename T>
flecs::entity pod_component(const flecs::world& world, const char *name = nullptr, bool allow_tag = true) {
    bool implicit_name = false;
    if (!name) {
        name = _::name_helper<T>::name();

        /* Keep track of whether name was explicitly set. If not, and the 
         * component was already registered, just use the registered name.
         *
         * The registered name may differ from the typename as the registered
         * name includes the flecs scope. This can in theory be different from
         * the C++ namespace though it is good practice to keep them the same */
        implicit_name = true;
    }

    world_t *world_ptr = world.c_ptr();
    entity_t id = 0;

    if (_::cpp_type<T>::registered()) {
        /* Obtain component id. Because the component is already registered,
         * this operation does nothing besides returning the existing id */
        id = _::cpp_type<T>::id_no_lifecycle(world_ptr, name, allow_tag);

        /* If entity is not empty check if the name matches */
        if (ecs_get_type(world_ptr, id) != nullptr) {
            if (!implicit_name && id >= EcsFirstUserComponentId) {
                char *path = ecs_get_path_w_sep(
                    world_ptr, 0, id, 0, "::", nullptr);
                ecs_assert(!strcmp(path, name), 
                    ECS_INCONSISTENT_COMPONENT_NAME, name);
                ecs_os_free(path);
            }
        } else {
            /* Register name with entity, so that when the entity is created the
             * correct id will be resolved from the name. Only do this when the
             * entity is empty.*/
            ecs_add_path_w_sep(world_ptr, id, 0, name, "::", "::");
        }

        /* If a component was already registered with this id but with a 
         * different size, the ecs_new_component function will fail. */

        /* We need to explicitly call ecs_new_component here again. Even though
         * the component was already registered, it may have been registered
         * with a different world. This ensures that the component is registered
         * with the same id for the current world. 
         * If the component was registered already, nothing will change. */
        ecs_entity_t entity = ecs_new_component(
            world.c_ptr(), id, nullptr, 
            _::cpp_type<T>::size(), 
            _::cpp_type<T>::alignment());

        (void)entity;

        ecs_assert(entity == id, ECS_INTERNAL_ERROR, NULL);

        /* This functionality could have been put in id_no_lifecycle, but since
         * this code happens when a component is registered, and the entire API
         * calls id_no_lifecycle, this would add a lot of overhead to each call.
         * This is why when using multiple worlds, components should be 
         * registered explicitly. */
    } else {
        /* If the component is not yet registered, ensure no other component
         * or entity has been registered with this name */
        ecs_entity_t entity = ecs_lookup_fullpath(world_ptr, name);

        /* If entity exists, compare symbol name to ensure that the component
         * we are trying to register under this name is the same */
        if (entity) {
            const EcsName *name_comp = static_cast<EcsName*>(ecs_get_mut_w_id(
                world.c_ptr(), entity, ecs_id(EcsName), NULL));
            ecs_assert(name_comp != NULL, ECS_INTERNAL_ERROR, NULL);
            ecs_assert(name_comp->symbol != NULL, ECS_INTERNAL_ERROR, NULL);

            const char *symbol = _::name_helper<T>::name();

            ecs_assert(!strcmp(name_comp->symbol, symbol), 
                ECS_COMPONENT_NAME_IN_USE, name);

            (void)name_comp;
            (void)symbol;
        }

        /* Register id as usual */
        id = _::cpp_type<T>::id_no_lifecycle(world_ptr, name, allow_tag);
    }

    return world.entity(id);
}