Add parent/child
This commit is contained in:
@@ -87,7 +87,7 @@ entityid_t componentGetEntitiesWithComponent(
|
||||
componentid_t used = ENTITY_MANAGER.entitiesWithComponent[
|
||||
type * ENTITY_COUNT_MAX + i
|
||||
];
|
||||
if(used == 0xFF) continue;
|
||||
if(used == COMPONENT_ID_INVALID) continue;
|
||||
assertTrue(
|
||||
ENTITY_MANAGER.components[componentGetIndex(i, used)].type == type,
|
||||
"Component type mismatch in entitiesWithComponent lookup"
|
||||
|
||||
@@ -1,12 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#include "entity/entitymanager.h"
|
||||
|
||||
// Lazily recompute worldTransform from the parent chain.
|
||||
static void entityPositionUpdateWorld(entityposition_t *pos) {
|
||||
if(!pos->dirty) return;
|
||||
|
||||
if(pos->parentEntityId == ENTITY_ID_INVALID) {
|
||||
glm_mat4_copy(pos->localTransform, pos->worldTransform);
|
||||
} else {
|
||||
entityposition_t *parent = componentGetData(
|
||||
pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
entityPositionUpdateWorld(parent);
|
||||
glm_mat4_mul(parent->worldTransform, pos->localTransform, pos->worldTransform);
|
||||
}
|
||||
|
||||
pos->dirty = false;
|
||||
}
|
||||
|
||||
void entityPositionMarkDirty(entityposition_t *pos) {
|
||||
pos->dirty = true;
|
||||
for(uint8_t i = 0; i < pos->childCount; i++) {
|
||||
entityposition_t *child = componentGetData(
|
||||
pos->childEntityIds[i], pos->childComponentIds[i], COMPONENT_TYPE_POSITION
|
||||
);
|
||||
entityPositionMarkDirty(child);
|
||||
}
|
||||
}
|
||||
|
||||
void entityPositionInit(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
@@ -18,7 +45,12 @@ void entityPositionInit(
|
||||
glm_vec3_zero(pos->position);
|
||||
glm_vec3_zero(pos->rotation);
|
||||
glm_vec3_one(pos->scale);
|
||||
glm_mat4_identity(pos->transform);
|
||||
glm_mat4_identity(pos->localTransform);
|
||||
glm_mat4_identity(pos->worldTransform);
|
||||
pos->dirty = false;
|
||||
pos->parentEntityId = ENTITY_ID_INVALID;
|
||||
pos->parentComponentId = COMPONENT_ID_INVALID;
|
||||
pos->childCount = 0;
|
||||
}
|
||||
|
||||
void entityPositionLookAt(
|
||||
@@ -31,8 +63,9 @@ void entityPositionLookAt(
|
||||
entityposition_t *pos = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
glm_lookat(eye, target, up, pos->transform);
|
||||
glm_lookat(eye, target, up, pos->localTransform);
|
||||
entityPositionDecompose(pos);
|
||||
entityPositionMarkDirty(pos);
|
||||
}
|
||||
|
||||
void entityPositionGetTransform(
|
||||
@@ -43,7 +76,19 @@ void entityPositionGetTransform(
|
||||
entityposition_t *pos = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
glm_mat4_copy(pos->transform, dest);
|
||||
entityPositionUpdateWorld(pos);
|
||||
glm_mat4_copy(pos->worldTransform, dest);
|
||||
}
|
||||
|
||||
void entityPositionGetLocalTransform(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
mat4 dest
|
||||
) {
|
||||
entityposition_t *pos = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
glm_mat4_copy(pos->localTransform, dest);
|
||||
}
|
||||
|
||||
void entityPositionGetPosition(
|
||||
@@ -115,6 +160,54 @@ void entityPositionSetScale(
|
||||
entityPositionRebuild(pos);
|
||||
}
|
||||
|
||||
void entityPositionSetParent(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId,
|
||||
const entityid_t parentEntityId,
|
||||
const componentid_t parentComponentId
|
||||
) {
|
||||
entityposition_t *pos = componentGetData(
|
||||
entityId, componentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
|
||||
// Remove from old parent's child list.
|
||||
if(pos->parentEntityId != ENTITY_ID_INVALID) {
|
||||
entityposition_t *oldParent = componentGetData(
|
||||
pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
for(uint8_t i = 0; i < oldParent->childCount; i++) {
|
||||
if(
|
||||
oldParent->childEntityIds[i] == entityId &&
|
||||
oldParent->childComponentIds[i] == componentId
|
||||
) {
|
||||
oldParent->childCount--;
|
||||
for(uint8_t j = i; j < oldParent->childCount; j++) {
|
||||
oldParent->childEntityIds[j] = oldParent->childEntityIds[j + 1];
|
||||
oldParent->childComponentIds[j] = oldParent->childComponentIds[j + 1];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos->parentEntityId = parentEntityId;
|
||||
pos->parentComponentId = parentComponentId;
|
||||
|
||||
// Register with new parent.
|
||||
if(parentEntityId != ENTITY_ID_INVALID) {
|
||||
entityposition_t *parent = componentGetData(
|
||||
parentEntityId, parentComponentId, COMPONENT_TYPE_POSITION
|
||||
);
|
||||
if(parent->childCount < ENTITY_POSITION_CHILDREN_MAX) {
|
||||
parent->childEntityIds[parent->childCount] = entityId;
|
||||
parent->childComponentIds[parent->childCount] = componentId;
|
||||
parent->childCount++;
|
||||
}
|
||||
}
|
||||
|
||||
entityPositionMarkDirty(pos);
|
||||
}
|
||||
|
||||
entityposition_t *entityPositionGet(
|
||||
const entityid_t entityId,
|
||||
const componentid_t componentId
|
||||
@@ -125,57 +218,56 @@ entityposition_t *entityPositionGet(
|
||||
}
|
||||
|
||||
void entityPositionRebuild(entityposition_t *pos) {
|
||||
glm_mat4_identity(pos->transform);
|
||||
glm_translate(pos->transform, pos->position);
|
||||
glm_rotate_x(pos->transform, pos->rotation[0], pos->transform);
|
||||
glm_rotate_y(pos->transform, pos->rotation[1], pos->transform);
|
||||
glm_rotate_z(pos->transform, pos->rotation[2], pos->transform);
|
||||
glm_scale(pos->transform, pos->scale);
|
||||
glm_mat4_identity(pos->localTransform);
|
||||
glm_translate(pos->localTransform, pos->position);
|
||||
glm_rotate_x(pos->localTransform, pos->rotation[0], pos->localTransform);
|
||||
glm_rotate_y(pos->localTransform, pos->rotation[1], pos->localTransform);
|
||||
glm_rotate_z(pos->localTransform, pos->rotation[2], pos->localTransform);
|
||||
glm_scale(pos->localTransform, pos->scale);
|
||||
entityPositionMarkDirty(pos);
|
||||
}
|
||||
|
||||
void entityPositionDecompose(entityposition_t *pos) {
|
||||
// Translation: column 3
|
||||
pos->position[0] = pos->transform[3][0];
|
||||
pos->position[1] = pos->transform[3][1];
|
||||
pos->position[2] = pos->transform[3][2];
|
||||
pos->position[0] = pos->localTransform[3][0];
|
||||
pos->position[1] = pos->localTransform[3][1];
|
||||
pos->position[2] = pos->localTransform[3][2];
|
||||
|
||||
// Scale: length of each basis column (xyz only)
|
||||
pos->scale[0] = sqrtf(
|
||||
pos->transform[0][0] * pos->transform[0][0] +
|
||||
pos->transform[0][1] * pos->transform[0][1] +
|
||||
pos->transform[0][2] * pos->transform[0][2]
|
||||
pos->localTransform[0][0] * pos->localTransform[0][0] +
|
||||
pos->localTransform[0][1] * pos->localTransform[0][1] +
|
||||
pos->localTransform[0][2] * pos->localTransform[0][2]
|
||||
);
|
||||
pos->scale[1] = sqrtf(
|
||||
pos->transform[1][0] * pos->transform[1][0] +
|
||||
pos->transform[1][1] * pos->transform[1][1] +
|
||||
pos->transform[1][2] * pos->transform[1][2]
|
||||
pos->localTransform[1][0] * pos->localTransform[1][0] +
|
||||
pos->localTransform[1][1] * pos->localTransform[1][1] +
|
||||
pos->localTransform[1][2] * pos->localTransform[1][2]
|
||||
);
|
||||
pos->scale[2] = sqrtf(
|
||||
pos->transform[2][0] * pos->transform[2][0] +
|
||||
pos->transform[2][1] * pos->transform[2][1] +
|
||||
pos->transform[2][2] * pos->transform[2][2]
|
||||
pos->localTransform[2][0] * pos->localTransform[2][0] +
|
||||
pos->localTransform[2][1] * pos->localTransform[2][1] +
|
||||
pos->localTransform[2][2] * pos->localTransform[2][2]
|
||||
);
|
||||
|
||||
// Normalize columns to isolate the rotation matrix
|
||||
// Normalize columns to isolate the rotation matrix.
|
||||
float invS0 = pos->scale[0] > 0.0f ? 1.0f / pos->scale[0] : 0.0f;
|
||||
float invS1 = pos->scale[1] > 0.0f ? 1.0f / pos->scale[1] : 0.0f;
|
||||
float invS2 = pos->scale[2] > 0.0f ? 1.0f / pos->scale[2] : 0.0f;
|
||||
|
||||
mat4 r;
|
||||
glm_mat4_identity(r);
|
||||
r[0][0] = pos->transform[0][0] * invS0;
|
||||
r[0][1] = pos->transform[0][1] * invS0;
|
||||
r[0][2] = pos->transform[0][2] * invS0;
|
||||
r[1][0] = pos->transform[1][0] * invS1;
|
||||
r[1][1] = pos->transform[1][1] * invS1;
|
||||
r[1][2] = pos->transform[1][2] * invS1;
|
||||
r[2][0] = pos->transform[2][0] * invS2;
|
||||
r[2][1] = pos->transform[2][1] * invS2;
|
||||
r[2][2] = pos->transform[2][2] * invS2;
|
||||
r[0][0] = pos->localTransform[0][0] * invS0;
|
||||
r[0][1] = pos->localTransform[0][1] * invS0;
|
||||
r[0][2] = pos->localTransform[0][2] * invS0;
|
||||
r[1][0] = pos->localTransform[1][0] * invS1;
|
||||
r[1][1] = pos->localTransform[1][1] * invS1;
|
||||
r[1][2] = pos->localTransform[1][2] * invS1;
|
||||
r[2][0] = pos->localTransform[2][0] * invS2;
|
||||
r[2][1] = pos->localTransform[2][1] * invS2;
|
||||
r[2][2] = pos->localTransform[2][2] * invS2;
|
||||
|
||||
// Extract XYZ euler angles (R = Rx * Ry * Rz, column-major)
|
||||
// r[2][0] = sin(Y), r[2][1] = -sin(X)*cos(Y), r[2][2] = cos(X)*cos(Y)
|
||||
// r[0][0] = cos(Y)*cos(Z), r[1][0] = -cos(Y)*sin(Z)
|
||||
float sinBeta = glm_clamp(r[2][0], -1.0f, 1.0f);
|
||||
pos->rotation[1] = asinf(sinBeta);
|
||||
float cosBeta = cosf(pos->rotation[1]);
|
||||
@@ -184,10 +276,10 @@ void entityPositionDecompose(entityposition_t *pos) {
|
||||
pos->rotation[0] = atan2f(-r[2][1], r[2][2]);
|
||||
pos->rotation[2] = atan2f(-r[1][0], r[0][0]);
|
||||
} else {
|
||||
// Gimbal lock: pin Z to 0, recover X from the remaining degree of freedom
|
||||
// Gimbal lock: pin Z to 0, recover X.
|
||||
pos->rotation[2] = 0.0f;
|
||||
pos->rotation[0] = (sinBeta > 0.0f)
|
||||
? atan2f(r[0][1], r[1][1])
|
||||
: -atan2f(r[0][1], r[1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Copyright (c) 2026 Dominic Masters
|
||||
*
|
||||
*
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
@@ -8,18 +8,24 @@
|
||||
#pragma once
|
||||
#include "entity/entitybase.h"
|
||||
|
||||
#define ENTITY_POSITION_CHILDREN_MAX 8
|
||||
|
||||
typedef struct {
|
||||
mat4 transform;
|
||||
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.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
*/
|
||||
void entityPositionInit(
|
||||
const entityid_t entityId,
|
||||
@@ -27,13 +33,13 @@ void entityPositionInit(
|
||||
);
|
||||
|
||||
/**
|
||||
* Transforms the entity's position to look at a target point.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* 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 for the look at transformation.
|
||||
* @param eye The position of the camera/eye for the look at transformation.
|
||||
* @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,
|
||||
@@ -44,11 +50,11 @@ void entityPositionLookAt(
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the transform matrix of the entity position component.
|
||||
* Gets the world-space transform matrix, recomputing it lazily if dirty.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param dest The destination matrix to write the transform to.
|
||||
* @param dest Destination matrix.
|
||||
*/
|
||||
void entityPositionGetTransform(
|
||||
const entityid_t entityId,
|
||||
@@ -57,11 +63,20 @@ void entityPositionGetTransform(
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the cached position of the entity.
|
||||
* Gets the local transform matrix (does not include parent transforms).
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param dest The destination vec3 to write the position to.
|
||||
* @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,
|
||||
@@ -70,11 +85,7 @@ void entityPositionGetPosition(
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the position of the entity and rebuilds the transform matrix.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param position The new position.
|
||||
* Sets the local position and marks the world transform dirty.
|
||||
*/
|
||||
void entityPositionSetPosition(
|
||||
const entityid_t entityId,
|
||||
@@ -83,11 +94,7 @@ void entityPositionSetPosition(
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the cached euler rotation (XYZ, radians) of the entity.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param dest The destination vec3 to write the rotation to.
|
||||
* Gets the cached local euler rotation (XYZ, radians).
|
||||
*/
|
||||
void entityPositionGetRotation(
|
||||
const entityid_t entityId,
|
||||
@@ -96,12 +103,7 @@ void entityPositionGetRotation(
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the euler rotation (XYZ, radians) of the entity and rebuilds the
|
||||
* transform matrix.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param rotation The new euler rotation in radians.
|
||||
* Sets the local euler rotation (XYZ, radians) and marks the world transform dirty.
|
||||
*/
|
||||
void entityPositionSetRotation(
|
||||
const entityid_t entityId,
|
||||
@@ -110,11 +112,7 @@ void entityPositionSetRotation(
|
||||
);
|
||||
|
||||
/**
|
||||
* Gets the cached scale of the entity.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param dest The destination vec3 to write the scale to.
|
||||
* Gets the cached local scale.
|
||||
*/
|
||||
void entityPositionGetScale(
|
||||
const entityid_t entityId,
|
||||
@@ -123,11 +121,7 @@ void entityPositionGetScale(
|
||||
);
|
||||
|
||||
/**
|
||||
* Sets the scale of the entity and rebuilds the transform matrix.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @param scale The new scale.
|
||||
* Sets the local scale and marks the world transform dirty.
|
||||
*/
|
||||
void entityPositionSetScale(
|
||||
const entityid_t entityId,
|
||||
@@ -136,13 +130,24 @@ void entityPositionSetScale(
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns a direct pointer to the entity position component data.
|
||||
* After modifying position, rotation, or scale directly, call
|
||||
* entityPositionRebuild() to update the transform matrix.
|
||||
* Sets the parent of this entity's position component.
|
||||
* Pass ENTITY_ID_INVALID / COMPONENT_ID_INVALID to detach from any parent.
|
||||
*
|
||||
* @param entityId The entity ID.
|
||||
* @param componentId The component ID.
|
||||
* @return Pointer to the entity position component data.
|
||||
* @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,
|
||||
@@ -150,15 +155,18 @@ entityposition_t *entityPositionGet(
|
||||
);
|
||||
|
||||
/**
|
||||
* Internal function to rebuild the transform matrix of the entity position
|
||||
* component based on the current position, rotation, and scale.
|
||||
* Rebuilds the local transform matrix from the cached position/rotation/scale,
|
||||
* then marks this node and all descendants dirty.
|
||||
*/
|
||||
void entityPositionRebuild(entityposition_t *pos);
|
||||
|
||||
/**
|
||||
* Decomposes the transform matrix back into the position, rotation (XYZ euler,
|
||||
* radians), and scale cache fields. Call after any direct matrix modification.
|
||||
*
|
||||
* @param pos Pointer to the entity position component data.
|
||||
* Marks this node and all descendants as having a stale world transform.
|
||||
*/
|
||||
void entityPositionDecompose(entityposition_t *pos);
|
||||
void entityPositionMarkDirty(entityposition_t *pos);
|
||||
|
||||
/**
|
||||
* Decomposes the local transform matrix back into the position, rotation
|
||||
* (XYZ euler, radians), and scale cache fields.
|
||||
*/
|
||||
void entityPositionDecompose(entityposition_t *pos);
|
||||
|
||||
@@ -22,7 +22,7 @@ void entityInit(const entityid_t entityId) {
|
||||
) {
|
||||
ENTITY_MANAGER.entitiesWithComponent[
|
||||
compType * ENTITY_COUNT_MAX + entityId
|
||||
] = 0xFF;
|
||||
] = COMPONENT_ID_INVALID;
|
||||
}
|
||||
|
||||
ent->state |= ENTITY_STATE_ACTIVE;
|
||||
@@ -52,7 +52,7 @@ componentid_t entityAddComponent(
|
||||
}
|
||||
|
||||
assertUnreachable("Entity has no more component slots available");
|
||||
return 0xFF;
|
||||
return COMPONENT_ID_INVALID;
|
||||
}
|
||||
|
||||
componentid_t entityGetComponent(
|
||||
@@ -62,7 +62,7 @@ componentid_t entityGetComponent(
|
||||
componentid_t compId = ENTITY_MANAGER.entitiesWithComponent[
|
||||
type * ENTITY_COUNT_MAX + entityId
|
||||
];
|
||||
if(compId == 0xFF) return compId;
|
||||
if(compId == COMPONENT_ID_INVALID) return compId;
|
||||
assertTrue(
|
||||
ENTITY_MANAGER.components[componentGetIndex(entityId, compId)].type == type,
|
||||
"Component type mismatch"
|
||||
@@ -80,7 +80,7 @@ void entityDispose(const entityid_t entityId) {
|
||||
componentDispose(entityId, i);
|
||||
ENTITY_MANAGER.entitiesWithComponent[
|
||||
ENTITY_MANAGER.components[compInd].type * ENTITY_COUNT_MAX + entityId
|
||||
] = 0xFF;
|
||||
] = COMPONENT_ID_INVALID;
|
||||
}
|
||||
|
||||
ent->state = 0;
|
||||
|
||||
@@ -35,7 +35,7 @@ componentid_t entityAddComponent(
|
||||
|
||||
/**
|
||||
* Gets the ID of the component of the given type on the entity with the given
|
||||
* ID, or 0xFF if the entity lacks the component.
|
||||
* ID, or COMPONENT_ID_INVALID if the entity lacks the component.
|
||||
*
|
||||
* @param entityId The ID of the entity to get the component from.
|
||||
* @param type The type of the component to get.
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#define ENTITY_COUNT_MAX 20
|
||||
#define ENTITY_COMPONENT_COUNT_MAX 8
|
||||
|
||||
#define ENTITY_ID_INVALID 0xFF
|
||||
#define COMPONENT_ID_INVALID 0xFF
|
||||
|
||||
typedef uint8_t entityid_t;
|
||||
typedef uint8_t componentid_t;
|
||||
typedef uint16_t componentindex_t;
|
||||
@@ -15,7 +15,7 @@ entitymanager_t ENTITY_MANAGER;
|
||||
void entityManagerInit(void) {
|
||||
memoryZero(&ENTITY_MANAGER, sizeof(entitymanager_t));
|
||||
memorySet(
|
||||
ENTITY_MANAGER.entitiesWithComponent, 0xFF,
|
||||
ENTITY_MANAGER.entitiesWithComponent, COMPONENT_ID_INVALID,
|
||||
sizeof(entityid_t) * COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX
|
||||
);
|
||||
|
||||
@@ -33,7 +33,7 @@ entityid_t entityManagerAdd() {
|
||||
return i;
|
||||
}
|
||||
assertUnreachable("No more entity IDs available");
|
||||
return 0xFF;
|
||||
return ENTITY_ID_INVALID;
|
||||
}
|
||||
|
||||
void entityManagerDispose(void) {
|
||||
|
||||
@@ -97,7 +97,11 @@ moduleBaseFunction(moduleEntityPositionSetScale) {
|
||||
|
||||
moduleBaseFunction(moduleEntityPositionLookAt) {
|
||||
if(argc < 1) return moduleBaseThrow("Expected at least 1 argument");
|
||||
entityposition_t *pos = moduleEntityPositionGet(callInfo);
|
||||
componenthandle_t *h = scriptProtoGetValue(
|
||||
&MODULE_ENTITY_POSITION_PROTO, callInfo->this_value
|
||||
);
|
||||
if(!h) return jerry_undefined();
|
||||
entityposition_t *pos = entityPositionGet(h->eid, h->cid);
|
||||
if(!pos) return jerry_undefined();
|
||||
vec3 target;
|
||||
if(!moduleVec3AnyCheck(args[0], target)) {
|
||||
@@ -107,8 +111,37 @@ moduleBaseFunction(moduleEntityPositionLookAt) {
|
||||
if(argc >= 2 && !moduleVec3AnyCheck(args[1], up)) {
|
||||
return moduleBaseThrow("expected Vec3 up");
|
||||
}
|
||||
glm_lookat(pos->position, target, up, pos->transform);
|
||||
entityPositionDecompose(pos);
|
||||
entityPositionLookAt(h->eid, h->cid, target, up, pos->position);
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
||||
moduleBaseFunction(moduleEntityPositionGetParent) {
|
||||
componenthandle_t *h = scriptProtoGetValue(
|
||||
&MODULE_ENTITY_POSITION_PROTO, callInfo->this_value
|
||||
);
|
||||
if(!h) return jerry_undefined();
|
||||
entityposition_t *pos = entityPositionGet(h->eid, h->cid);
|
||||
if(!pos || pos->parentEntityId == ENTITY_ID_INVALID) return jerry_null();
|
||||
componenthandle_t ph = { .eid = pos->parentEntityId, .cid = pos->parentComponentId };
|
||||
return scriptProtoCreateValue(&MODULE_ENTITY_POSITION_PROTO, &ph);
|
||||
}
|
||||
|
||||
moduleBaseFunction(moduleEntityPositionSetParentProp) {
|
||||
componenthandle_t *h = scriptProtoGetValue(
|
||||
&MODULE_ENTITY_POSITION_PROTO, callInfo->this_value
|
||||
);
|
||||
if(!h) return jerry_undefined();
|
||||
|
||||
if(argc < 1 || jerry_value_is_null(args[0]) || jerry_value_is_undefined(args[0])) {
|
||||
entityPositionSetParent(h->eid, h->cid, ENTITY_ID_INVALID, COMPONENT_ID_INVALID);
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
||||
componenthandle_t *ph = scriptProtoGetValue(
|
||||
&MODULE_ENTITY_POSITION_PROTO, args[0]
|
||||
);
|
||||
if(!ph) return moduleBaseThrow("expected EntityPosition");
|
||||
entityPositionSetParent(h->eid, h->cid, ph->eid, ph->cid);
|
||||
return jerry_undefined();
|
||||
}
|
||||
|
||||
@@ -147,4 +180,9 @@ static void moduleEntityPOSITION(void) {
|
||||
&MODULE_ENTITY_POSITION_PROTO, "lookAt",
|
||||
moduleEntityPositionLookAt
|
||||
);
|
||||
|
||||
scriptProtoDefineProp(
|
||||
&MODULE_ENTITY_POSITION_PROTO, "parent",
|
||||
moduleEntityPositionGetParent, moduleEntityPositionSetParentProp
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user