Class Entity

Class Documentation

class Entity

Lightweight wrapper around EnTT’s handle providing Portal’s component access API.

The Entity class wraps entt::handle (which combines an entity ID with a registry reference) and provides Portal-specific component manipulation and parent-child hierarchy support. Entity objects are value types that can be freely copied and passed around - they don’t own the underlying entity data, just reference it.

Key features:

  • Component management (add, remove, get, patch)

  • Parent-child hierarchy relationships via RelationshipComponent

  • Iteration over children and descendants

  • Type-safe component access with compile-time checks

All entities created through Registry automatically receive default components:

See also

Registry for entity creation and destruction

Example Usage:
// Entity is obtained from Registry, not constructed directly
auto player = registry.create_entity(STRING_ID("player"));

// Add components
player.add_component<HealthComponent>(100.0f);
player.add_component<VelocityComponent>(vec3{0, 0, 0});

// Access components
auto& health = player.get_component<HealthComponent>();
health.value -= 10.0f;

// Optional access
if (auto* armor = player.try_get_component<ArmorComponent>()) {
    armor->durability -= 5;
}

// Check component existence
if (player.has_component<TransformComponent>()) {
    // All entities have Transform by default
}

// Parent-child hierarchy
auto weapon = registry.create_entity(STRING_ID("sword"));
weapon.set_parent(player);

// Iterate children
for (auto child : player.children()) {
    // Process direct children
}

Note

Entity is a handle - it doesn’t own the entity data and can become invalid if the entity is destroyed. Use is_valid() to check validity.

Note

Component access methods assert in debug builds if the component doesn’t exist.

Public Functions

Entity() = default

Constructs an invalid (null) entity.

Default-constructed entities are invalid and cannot be used until assigned a valid entity handle.

Entity(entt::entity entity, entt::registry &reg)

Constructs an Entity wrapper from a raw entity ID and registry.

Note

This is typically called by Registry methods, not user code.

Parameters:
  • entity – The raw EnTT entity identifier

  • reg – Reference to the registry containing the entity

Entity(entt::handle handle)

Constructs an Entity wrapper from an EnTT handle.

Note

This is typically called by Registry methods, not user code.

Parameters:

handle – The EnTT handle (entity + registry)

template<typename T, typename ...Args>
inline T &add_component(Args&&... args)

Adds a component to this entity with constructor arguments.

Constructs the component in-place using the provided arguments and attaches it to this entity. Asserts if the component already exists.

Example:
auto& health = entity.add_component<HealthComponent>(100.0f);
entity.add_component<VelocityComponent>(vec3{1, 0, 0});

Note

Asserts in debug builds if the component already exists.

Template Parameters:
  • T – The component type to add

  • Args – Argument types for the component constructor

Parameters:

args – Arguments forwarded to the component constructor

Returns:

Reference to the newly created component

template<typename T>
inline void add_component()

Adds an empty (tag) component to this entity.

Specialized overload for empty component types (tags) that don’t require constructor arguments. Useful for marking entities with specific properties.

Example:
entity.add_component<PlayerTag>();
entity.add_component<TransformDirtyTag>();

Note

Asserts in debug builds if the component already exists.

Template Parameters:

T – The empty component type to add (must satisfy std::is_empty_v)

template<typename T, typename ...Func>
inline T &patch_component(Func&&... func)

Modifies a component through EnTT’s patch mechanism.

Applies the provided functors to the component, triggering EnTT’s update signal. This allows systems to register callbacks (via on_component_changed) that react to component modifications.

Example:
// Modify transform and trigger dirty flag
entity.patch_component<TransformComponent>([](auto& t) {
    t.position += vec3{1, 0, 0};
});

Note

Asserts if the component doesn’t exist.

Note

Use this instead of direct modification when you want change detection.

Template Parameters:
  • T – The component type to patch

  • Func – Functor types that accept T& or const T&

Parameters:

func – One or more functors to apply to the component

Returns:

Reference to the modified component

template<typename T>
inline void remove_component() const

Removes a component from this entity.

Destroys the component and removes it from the entity. Triggers EnTT’s destruction signal, allowing systems to clean up via on_component_removed.

Example:
if (entity.has_component<TemporaryEffectComponent>()) {
    entity.remove_component<TemporaryEffectComponent>();
}

Note

Asserts if the component doesn’t exist.

Template Parameters:

T – The component type to remove

void set_parent(Entity parent)

Sets the parent of this entity in the hierarchy.

Establishes a parent-child relationship by updating RelationshipComponent. If this entity already has a parent, it’s first removed from that parent’s child list before being added to the new parent.

See also

create_child_entity for creating entities with parents

Example:
auto player = registry.create_entity(STRING_ID("player"));
auto weapon = registry.create_entity(STRING_ID("sword"));
weapon.set_parent(player); // weapon is now child of player

Parameters:

parent – The entity to become this entity’s parent

bool remove_child(Entity child)

Removes a child from this entity’s child list.

Breaks the parent-child relationship, making the child a top-level entity. The child entity itself is not destroyed, only orphaned.

Example:
if (player.remove_child(weapon)) {
    // weapon is no longer attached to player
}

Parameters:

child – The child entity to remove

Returns:

true if the child was found and removed, false otherwise

template<typename T>
inline T &get_component()

Retrieves a reference to a component.

Returns a reference to the specified component type. The component must exist or an assertion will fire in debug builds.

Example:
auto& transform = entity.get_component<TransformComponent>();
transform.position = vec3{10, 0, 0};

Note

Asserts if the component doesn’t exist. Use try_get_component() for optional access.

Template Parameters:

T – The component type to retrieve

Returns:

Reference to the component

template<typename T>
inline const T &get_component() const

Retrieves a const reference to a component.

Note

Asserts if the component doesn’t exist.

Template Parameters:

T – The component type to retrieve

Returns:

Const reference to the component

template<typename T>
inline T *try_get_component()

Attempts to retrieve a pointer to a component.

Returns a pointer to the component if it exists, or nullptr if not. This is the safe way to access optional components without assertions.

Example:
if (auto* armor = entity.try_get_component<ArmorComponent>()) {
    armor->durability -= damage;
} else {
    // Entity has no armor, apply damage directly to health
}

Template Parameters:

T – The component type to retrieve

Returns:

Pointer to the component, or nullptr if not found

template<typename T>
inline const T *try_get_component() const

Attempts to retrieve a const pointer to a component.

Template Parameters:

T – The component type to retrieve

Returns:

Const pointer to the component, or nullptr if not found

template<typename ...T>
inline bool has_component() const

Checks if the entity has all specified components.

Returns true only if the entity possesses all of the specified component types. Supports checking multiple components at once.

Example:
if (entity.has_component<TransformComponent, RenderComponent>()) {
    // Entity is renderable
}

Template Parameters:

T – Component types to check for

Returns:

true if all components exist, false otherwise

template<typename ...T>
inline bool has_any() const

Checks if the entity has any of the specified components.

Returns true if the entity possesses at least one of the specified component types.

Example:
if (entity.has_any<HealthComponent, ShieldComponent>()) {
    // Entity has some form of protection
}

Template Parameters:

T – Component types to check for

Returns:

true if any component exists, false otherwise

bool is_valid() const

Checks if this entity handle is valid.

An entity is invalid if it’s default-constructed or if the underlying entity has been destroyed.

Returns:

true if the entity is valid, false otherwise

entt::entity get_id() const

Returns the raw EnTT entity identifier.

Returns:

The underlying entt::entity ID

StringId get_name() const

Returns the entity’s name.

Returns:

The entity’s StringId name, or “Unnamed” if no NameComponent exists

operator uint32_t() const

Converts the entity to its numeric ID.

Returns:

The entity ID as uint32_t

operator entt::entity() const

Converts to the raw EnTT entity type.

Returns:

The underlying entt::entity

operator bool() const

Checks validity via bool conversion.

Returns:

true if the entity is valid

bool operator==(const Entity &other) const

Compares two entities for equality.

Parameters:

other – The entity to compare against

Returns:

true if both entities refer to the same underlying entity

Entity get_parent() const

Returns this entity’s parent.

Returns:

The parent entity, or an invalid entity if no parent exists

entt::entity get_parent_id() const

Returns the raw EnTT ID of this entity’s parent.

Returns:

The parent’s entity ID, or entt::null if no parent

ChildRange children() const

Returns a range of direct children.

Provides an iterable range over this entity’s immediate children. Uses ChildIterator which traverses the sibling linked list.

Example:
for (auto child : entity.children()) {
    child.get_component<TransformComponent>().update();
}

Returns:

ChildRange for use with range-based for loops

RecursiveChildRange descendants() const

Returns a range of all descendants (recursive).

Provides an iterable range over this entity’s entire subtree using depth-first traversal. Uses RecursiveChildIterator with internal stack.

Example:
// Disable all entities in the subtree
for (auto descendant : entity.descendants()) {
    descendant.add_component<DisabledTag>();
}

Returns:

RecursiveChildRange for use with range-based for loops

bool is_ancestor_of(Entity other) const

Checks if this entity is an ancestor of another.

Parameters:

other – The potential descendant

Returns:

true if other is a descendant of this entity

bool is_descendant_of(Entity other) const

Checks if this entity is a descendant of another.

Parameters:

other – The potential ancestor

Returns:

true if this entity is a descendant of other

entt::registry &get_registry() const

Returns the registry containing this entity.

Returns:

Reference to the entt::registry