/** * Copyright (c) 2026 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #pragma once #include "entity/entitybase.h" #define ENTITY_POSITION_CHILDREN_MAX 8 typedef struct { mat4 localTransform; mat4 worldTransform; vec3 position; vec3 rotation; vec3 scale; bool dirty; entityid_t parentEntityId; componentid_t parentComponentId; uint8_t childCount; entityid_t childEntityIds[ENTITY_POSITION_CHILDREN_MAX]; componentid_t childComponentIds[ENTITY_POSITION_CHILDREN_MAX]; } entityposition_t; /** * Initialize the entity position component. */ void entityPositionInit( const entityid_t entityId, const componentid_t componentId ); /** * Transforms the entity's local transform to look at a target point. * * @param entityId The entity ID. * @param componentId The component ID. * @param target The target point to look at. * @param up The up vector. * @param eye The eye/camera position. */ void entityPositionLookAt( const entityid_t entityId, const componentid_t componentId, vec3 target, vec3 up, vec3 eye ); /** * Gets the world-space transform matrix, recomputing it lazily if dirty. * * @param entityId The entity ID. * @param componentId The component ID. * @param dest Destination matrix. */ void entityPositionGetTransform( const entityid_t entityId, const componentid_t componentId, mat4 dest ); /** * Gets the local transform matrix (does not include parent transforms). * * @param entityId The entity ID. * @param componentId The component ID. * @param dest Destination matrix. */ void entityPositionGetLocalTransform( const entityid_t entityId, const componentid_t componentId, mat4 dest ); /** * Gets the cached local position. */ void entityPositionGetPosition( const entityid_t entityId, const componentid_t componentId, vec3 dest ); /** * Sets the local position and marks the world transform dirty. */ void entityPositionSetPosition( const entityid_t entityId, const componentid_t componentId, vec3 position ); /** * Gets the cached local euler rotation (XYZ, radians). */ void entityPositionGetRotation( const entityid_t entityId, const componentid_t componentId, vec3 dest ); /** * Sets the local euler rotation (XYZ, radians) and marks the world transform dirty. */ void entityPositionSetRotation( const entityid_t entityId, const componentid_t componentId, vec3 rotation ); /** * Gets the cached local scale. */ void entityPositionGetScale( const entityid_t entityId, const componentid_t componentId, vec3 dest ); /** * Sets the local scale and marks the world transform dirty. */ void entityPositionSetScale( const entityid_t entityId, const componentid_t componentId, vec3 scale ); /** * Sets the parent of this entity's position component. * Pass ENTITY_ID_INVALID / COMPONENT_ID_INVALID to detach from any parent. * * @param entityId The child entity ID. * @param componentId The child component ID. * @param parentEntityId The parent entity ID. * @param parentComponentId The parent component ID. */ void entityPositionSetParent( const entityid_t entityId, const componentid_t componentId, const entityid_t parentEntityId, const componentid_t parentComponentId ); /** * Returns a direct pointer to the entity position component data. * After modifying localTransform directly, call entityPositionMarkDirty(). */ entityposition_t *entityPositionGet( const entityid_t entityId, const componentid_t componentId ); /** * Rebuilds the local transform matrix from the cached position/rotation/scale, * then marks this node and all descendants dirty. */ void entityPositionRebuild(entityposition_t *pos); /** * Marks this node and all descendants as having a stale world transform. */ void entityPositionMarkDirty(entityposition_t *pos); /** * Disposes this entity and all of its position-component descendants * recursively. Detaches from any parent before destroying. * * @param entityId The root entity ID. * @param componentId The root position component ID. */ void entityPositionDisposeDeep( const entityid_t entityId, const componentid_t componentId ); /** * Decomposes the local transform matrix back into the position, rotation * (XYZ euler, radians), and scale cache fields. */ void entityPositionDecompose(entityposition_t *pos);