Bring the entity-component system online: rendering, scene manager, scripting

entityRenderAll() (src/dusk/entity/entityrender.c) ports ac2's
scene.c:sceneRender() camera/view-matrix/draw-loop logic as a standalone
function - find the active camera, bind SHADER_UNLIT with its projection/
view, draw every COMPONENT_TYPE_RENDERABLE entity. display.c calls it each
frame between the screen clear and screenUnbind(), the same spot the old
sceneRender() used to sit.

A single-scene scene manager (src/dusk/scene/, ported from ac2 minus its
prefab system and physics/trigger stepping - that module hasn't been
ported yet) sits alongside this but isn't wired into the engine loop yet;
only one scene can ever exist (no SCENE_COUNT_MAX array).

entitymanager.c/h removed entirely: its three arrays (entities/components/
entitiesWithComponent) are now plain globals in entity.h/.c
(ENTITIES/COMPONENTS/ENTITIES_WITH_COMPONENT), and every entity/component
function across the whole ECS (entity, component, position, camera,
renderable, physics, trigger, animation) drops its entitymanager_t *mgr
parameter to operate on them directly - there was only ever one instance of
that struct in the whole engine, so the indirection bought nothing.

New duskscript bindings (src/dusk/script/native/entity/) expose entityAdd,
entityAddComponent/entityGetComponent, entitySetName/entityGetName/
entityFindByName, entityDispose/entityDisposeDeep,
entityPositionSetLocalPosition/entityPositionLookAt,
entityRenderableSetMesh (by name - cube/plane/sphere/capsule/triprism/quad),
and COMPONENT_TYPE_*/ENTITY_ID_INVALID/COMPONENT_ID_INVALID constants.
assets/init.ds uses them to spawn a camera (via LookAt from (3,3,3) at the
origin), a cube and a plane as the engine's first real content on the new
ECS.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
YourWishesandClaude Sonnet 5 committed 2026-10-15 09:08:20 -05:00
1 parent fdfdfa3a66
commit 9a24b3d7db
43 files changed
+1084 -605

No files matched your search

+19 -1
View File
@@ -1,2 +1,20 @@
// Entry point, run once by the engine after every other system is ready. // Entry point, run once by the engine after every other system is ready.
consolePrint("Test");
var camera = entityAdd();
var cameraPosition = entityAddComponent(camera, COMPONENT_TYPE_POSITION);
entityAddComponent(camera, COMPONENT_TYPE_CAMERA);
entityPositionLookAt(camera, cameraPosition, 3, 3, 3, 0, 0, 0);
var cube = entityAdd();
var cubePosition = entityAddComponent(cube, COMPONENT_TYPE_POSITION);
var cubeRenderable = entityAddComponent(cube, COMPONENT_TYPE_RENDERABLE);
entityRenderableSetMesh(cube, cubeRenderable, "cube");
entityPositionSetLocalPosition(cube, cubePosition, 0, 0, 0);
var plane = entityAdd();
var planePosition = entityAddComponent(plane, COMPONENT_TYPE_POSITION);
var planeRenderable = entityAddComponent(plane, COMPONENT_TYPE_RENDERABLE);
entityRenderableSetMesh(plane, planeRenderable, "plane");
entityPositionSetLocalPosition(plane, planePosition, 0, 0, 0);
consolePrint("Camera, cube and plane created");
+1 -3
View File
@@ -82,12 +82,10 @@ add_subdirectory(error)
add_subdirectory(input) add_subdirectory(input)
add_subdirectory(locale) add_subdirectory(locale)
add_subdirectory(perf) add_subdirectory(perf)
add_subdirectory(rpg)
add_subdirectory(script)
add_subdirectory(scene) add_subdirectory(scene)
add_subdirectory(script)
add_subdirectory(system) add_subdirectory(system)
add_subdirectory(time) add_subdirectory(time)
add_subdirectory(ui)
add_subdirectory(save) add_subdirectory(save)
add_subdirectory(util) add_subdirectory(util)
add_subdirectory(thread) add_subdirectory(thread)
+4 -4
View File
@@ -7,7 +7,8 @@
#include "display/display.h" #include "display/display.h"
#include "display/framebuffer/framebuffer.h" #include "display/framebuffer/framebuffer.h"
#include "scene/scene.h" #include "entity/entity.h"
#include "entity/entityrender.h"
#include "display/spritebatch/spritebatch.h" #include "display/spritebatch/spritebatch.h"
#include "display/mesh/quad.h" #include "display/mesh/quad.h"
#include "display/mesh/cube.h" #include "display/mesh/cube.h"
@@ -16,7 +17,6 @@
#include "display/mesh/capsule.h" #include "display/mesh/capsule.h"
#include "display/mesh/triprism.h" #include "display/mesh/triprism.h"
#include "display/screen/screen.h" #include "display/screen/screen.h"
#include "ui/ui.h"
#include "display/text/text.h" #include "display/text/text.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
@@ -76,14 +76,14 @@ errorret_t displayUpdate(void) {
spriteBatchClear(); spriteBatchClear();
errorChain(frameBufferBind(NULL)); errorChain(frameBufferBind(NULL));
// Bind screen and render scene // Bind screen and render the entity world
errorChain(screenBind()); errorChain(screenBind());
frameBufferClear( frameBufferClear(
FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH, FRAMEBUFFER_CLEAR_COLOR | FRAMEBUFFER_CLEAR_DEPTH,
SCREEN.background SCREEN.background
); );
errorChain(sceneRender()); errorChain(entityRenderAll());
// Finish up // Finish up
screenUnbind(); screenUnbind();
+4 -14
View File
@@ -11,11 +11,9 @@
#include "time/time.h" #include "time/time.h"
#include "input/input.h" #include "input/input.h"
#include "locale/localemanager.h" #include "locale/localemanager.h"
#include "rpg/rpg.h"
#include "display/display.h" #include "display/display.h"
#include "scene/scene.h" #include "entity/entity.h"
#include "asset/asset.h" #include "asset/asset.h"
#include "ui/ui.h"
#include "assert/assert.h" #include "assert/assert.h"
#ifdef DUSK_NETWORK #ifdef DUSK_NETWORK
#include "network/network.h" #include "network/network.h"
@@ -48,13 +46,11 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
errorChain(localeManagerInit()); errorChain(localeManagerInit());
errorChain(displayInit()); errorChain(displayInit());
errorChain(audioInit()); errorChain(audioInit());
errorChain(rpgInit()); entityManagerInit();
errorChain(uiInit());
#ifdef DUSK_NETWORK #ifdef DUSK_NETWORK
errorChain(networkInit()); errorChain(networkInit());
#endif #endif
errorChain(scriptInit()); errorChain(scriptInit());
errorChain(sceneInit());
// Runs once every other system is ready, so init.ds can use any of them. // Runs once every other system is ready, so init.ds can use any of them.
scripterror_t scriptInitError; scripterror_t scriptInitError;
@@ -70,8 +66,6 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) {
consolePrint("Assertions real"); consolePrint("Assertions real");
#endif #endif
sceneSet(SCENE_TYPE_INITIAL);
errorOk(); errorOk();
} }
@@ -85,10 +79,8 @@ errorret_t engineUpdate(void) {
inputUpdate(); inputUpdate();
consoleUpdate(); consoleUpdate();
errorChain(audioUpdateEarly()); errorChain(audioUpdateEarly());
errorChain(rpgUpdate());
errorChain(sceneUpdate());
errorChain(assetUpdate()); errorChain(assetUpdate());
errorChain(uiUpdate()); entityManagerUpdate();
// Render // Render
errorChain(displayUpdate()); errorChain(displayUpdate());
@@ -102,14 +94,12 @@ void engineExit(void) {
} }
errorret_t engineDispose(void) { errorret_t engineDispose(void) {
errorChain(sceneDispose());
errorChain(scriptDispose()); errorChain(scriptDispose());
entityManagerDispose();
#ifdef DUSK_NETWORK #ifdef DUSK_NETWORK
errorChain(networkDispose()); errorChain(networkDispose());
#endif #endif
errorChain(rpgDispose());
localeManagerDispose(); localeManagerDispose();
errorChain(uiDispose());
errorChain(audioDispose()); errorChain(audioDispose());
consoleDispose(); consoleDispose();
errorChain(displayDispose()); errorChain(displayDispose());
+1 -1
View File
@@ -7,7 +7,7 @@
target_sources(${DUSK_LIBRARY_TARGET_NAME} target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
entity.c entity.c
entitymanager.c entityrender.c
component.c component.c
) )
+13 -22
View File
@@ -5,7 +5,7 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#include "entitymanager.h" #include "entity.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
@@ -28,41 +28,37 @@ componentdefinition_t COMPONENT_DEFINITIONS[] = {
}; };
void componentInit( void componentInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const componenttype_t type const componenttype_t type
) { ) {
assertNotNull(mgr, "Entity manager cannot be null");
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB"); assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB"); assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB"); assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot initialize null component"); assertTrue(type != COMPONENT_TYPE_NULL, "Cannot initialize null component");
componentindex_t index = componentGetIndex(entityId, componentId); componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &mgr->components[index]; component_t *cmp = &COMPONENTS[index];
memoryZero(cmp, sizeof(component_t)); memoryZero(cmp, sizeof(component_t));
cmp->type = type; cmp->type = type;
if(COMPONENT_DEFINITIONS[type].init) { if(COMPONENT_DEFINITIONS[type].init) {
COMPONENT_DEFINITIONS[type].init(mgr, entityId, componentId); COMPONENT_DEFINITIONS[type].init(entityId, componentId);
} }
} }
void * componentGetData( void * componentGetData(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const componenttype_t type const componenttype_t type
) { ) {
assertNotNull(mgr, "Entity manager cannot be null");
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB"); assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB"); assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB"); assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot get data of null component"); assertTrue(type != COMPONENT_TYPE_NULL, "Cannot get data of null component");
componentindex_t index = componentGetIndex(entityId, componentId); componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &mgr->components[index]; component_t *cmp = &COMPONENTS[index];
assertTrue(cmp->type == type, "Component type mismatch"); assertTrue(cmp->type == type, "Component type mismatch");
return &cmp->data; return &cmp->data;
@@ -78,12 +74,10 @@ componentindex_t componentGetIndex(
} }
entityid_t componentGetEntitiesWithComponent( entityid_t componentGetEntitiesWithComponent(
entitymanager_t *mgr,
const componenttype_t type, const componenttype_t type,
entityid_t outEntities[ENTITY_COUNT_MAX], entityid_t outEntities[ENTITY_COUNT_MAX],
componentid_t outComponents[ENTITY_COUNT_MAX] componentid_t outComponents[ENTITY_COUNT_MAX]
) { ) {
assertNotNull(mgr, "Entity manager cannot be null");
assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB"); assertTrue(type < COMPONENT_TYPE_COUNT, "Component type OOB");
assertTrue(type != COMPONENT_TYPE_NULL, "Cannot check NULL type"); assertTrue(type != COMPONENT_TYPE_NULL, "Cannot check NULL type");
assertNotNull(outEntities, "Output entities array cannot be null"); assertNotNull(outEntities, "Output entities array cannot be null");
@@ -91,16 +85,16 @@ entityid_t componentGetEntitiesWithComponent(
entityid_t written = 0; entityid_t written = 0;
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) { for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
componentid_t used = mgr->entitiesWithComponent[ componentid_t used = ENTITIES_WITH_COMPONENT[
type * ENTITY_COUNT_MAX + i type * ENTITY_COUNT_MAX + i
]; ];
if(used == COMPONENT_ID_INVALID) continue; if(used == COMPONENT_ID_INVALID) continue;
assertTrue( assertTrue(
mgr->components[componentGetIndex(i, used)].type == type, COMPONENTS[componentGetIndex(i, used)].type == type,
"Component type mismatch in entitiesWithComponent lookup" "Component type mismatch in entitiesWithComponent lookup"
); );
assertTrue( assertTrue(
(mgr->entities[i].state & ENTITY_STATE_ACTIVE) != 0, (ENTITIES[i].state & ENTITY_STATE_ACTIVE) != 0,
"Inactive entity in entitiesWithComponent lookup" "Inactive entity in entitiesWithComponent lookup"
); );
assertTrue( assertTrue(
@@ -117,35 +111,32 @@ entityid_t componentGetEntitiesWithComponent(
return written; return written;
} }
errorret_t componentRenderAll(entitymanager_t *mgr) { errorret_t componentRenderAll(void) {
assertNotNull(mgr, "Entity manager cannot be null");
for(entityid_t eid = 0; eid < ENTITY_COUNT_MAX; eid++) { for(entityid_t eid = 0; eid < ENTITY_COUNT_MAX; eid++) {
if(!(mgr->entities[eid].state & ENTITY_STATE_ACTIVE)) continue; if(!(ENTITIES[eid].state & ENTITY_STATE_ACTIVE)) continue;
for(componentid_t cid = 0; cid < ENTITY_COMPONENT_COUNT_MAX; cid++) { for(componentid_t cid = 0; cid < ENTITY_COMPONENT_COUNT_MAX; cid++) {
component_t *cmp = &mgr->components[componentGetIndex(eid, cid)]; component_t *cmp = &COMPONENTS[componentGetIndex(eid, cid)];
if(cmp->type == COMPONENT_TYPE_NULL) continue; if(cmp->type == COMPONENT_TYPE_NULL) continue;
if(!COMPONENT_DEFINITIONS[cmp->type].render) continue; if(!COMPONENT_DEFINITIONS[cmp->type].render) continue;
errorChain(COMPONENT_DEFINITIONS[cmp->type].render(mgr, eid, cid)); errorChain(COMPONENT_DEFINITIONS[cmp->type].render(eid, cid));
} }
} }
errorOk(); errorOk();
} }
void componentDispose( void componentDispose(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
assertNotNull(mgr, "Entity manager cannot be null");
assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB"); assertTrue(entityId < ENTITY_COUNT_MAX, "Entity ID OOB");
assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB"); assertTrue(componentId < ENTITY_COMPONENT_COUNT_MAX, "Component ID OOB");
componentindex_t index = componentGetIndex(entityId, componentId); componentindex_t index = componentGetIndex(entityId, componentId);
component_t *cmp = &mgr->components[index]; component_t *cmp = &COMPONENTS[index];
if(cmp->type == COMPONENT_TYPE_NULL) return; if(cmp->type == COMPONENT_TYPE_NULL) return;
if(COMPONENT_DEFINITIONS[cmp->type].dispose) { if(COMPONENT_DEFINITIONS[cmp->type].dispose) {
COMPONENT_DEFINITIONS[cmp->type].dispose(mgr, entityId, componentId); COMPONENT_DEFINITIONS[cmp->type].dispose(entityId, componentId);
} }
cmp->type = COMPONENT_TYPE_NULL; cmp->type = COMPONENT_TYPE_NULL;
+1 -14
View File
@@ -23,12 +23,10 @@ typedef union {
/** /**
* Callback signature for a component's init/dispose hooks. * Callback signature for a component's init/dispose hooks.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
typedef void (*componentcallback_t)( typedef void (*componentcallback_t)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -36,13 +34,11 @@ typedef void (*componentcallback_t)(
/** /**
* Callback signature for a component's render hook. * Callback signature for a component's render hook.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return Error state. * @return Error state.
*/ */
typedef errorret_t (*componentcallbackerror_t)( typedef errorret_t (*componentcallbackerror_t)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -76,13 +72,11 @@ extern componentdefinition_t COMPONENT_DEFINITIONS[];
/** /**
* Initializes a component of the given type for the entity with component ID. * Initializes a component of the given type for the entity with component ID.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param type The type of the component to initialize. * @param type The type of the component to initialize.
*/ */
void componentInit( void componentInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const componenttype_t type const componenttype_t type
@@ -91,14 +85,12 @@ void componentInit(
/** /**
* Gets the pointer to the data of a component for the entity with component ID. * Gets the pointer to the data of a component for the entity with component ID.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param type The type of the component to get, only used for assertion. * @param type The type of the component to get, only used for assertion.
* @return A pointer to the component data. * @return A pointer to the component data.
*/ */
void * componentGetData( void * componentGetData(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const componenttype_t type const componenttype_t type
@@ -119,7 +111,6 @@ componentindex_t componentGetIndex(
/** /**
* Gets the entity IDs of all entities with a component of the given type. * Gets the entity IDs of all entities with a component of the given type.
* *
* @param mgr The entity manager to search.
* @param type The type of the component to get entities for. * @param type The type of the component to get entities for.
* @param outEntities An array to write the entity IDs to, must be at least * @param outEntities An array to write the entity IDs to, must be at least
* ENTITY_COUNT_MAX in size. * ENTITY_COUNT_MAX in size.
@@ -127,7 +118,6 @@ componentindex_t componentGetIndex(
* @return The number of entity IDs written to outEntities. * @return The number of entity IDs written to outEntities.
*/ */
entityid_t componentGetEntitiesWithComponent( entityid_t componentGetEntitiesWithComponent(
entitymanager_t *mgr,
const componenttype_t type, const componenttype_t type,
entityid_t outEntities[ENTITY_COUNT_MAX], entityid_t outEntities[ENTITY_COUNT_MAX],
componentid_t outComponents[ENTITY_COUNT_MAX] componentid_t outComponents[ENTITY_COUNT_MAX]
@@ -136,12 +126,10 @@ entityid_t componentGetEntitiesWithComponent(
/** /**
* Disposes of a component for the entity with component ID. * Disposes of a component for the entity with component ID.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void componentDispose( void componentDispose(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -151,7 +139,6 @@ void componentDispose(
* Iterates all active entities and all their component slots. No-op for * Iterates all active entities and all their component slots. No-op for
* components whose definition has render == NULL. * components whose definition has render == NULL.
* *
* @param mgr The entity manager to render.
* @return Error state. * @return Error state.
*/ */
errorret_t componentRenderAll(entitymanager_t *mgr); errorret_t componentRenderAll(void);
@@ -6,53 +6,49 @@
*/ */
#include "entityanimation.h" #include "entityanimation.h"
#include "entity/entitymanager.h" #include "entity/entity.h"
#include "util/memory.h" #include "util/memory.h"
#include "time/time.h" #include "time/time.h"
void entityAnimationInit( void entityAnimationInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
memoryZero(animComp, sizeof(entityanimation_t)); memoryZero(animComp, sizeof(entityanimation_t));
animComp->speed = 1.0f; animComp->speed = 1.0f;
entityUpdateAdd(mgr, entityId, entityAnimationUpdate, componentId, NULL); entityUpdateAdd(entityId, entityAnimationUpdate, componentId, NULL);
} }
entityanimation_t *entityAnimationGet( entityanimation_t *entityAnimationGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
return componentGetData( return componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_ANIMATION entityId, componentId, COMPONENT_TYPE_ANIMATION
); );
} }
void entityAnimationSetKeyframes( void entityAnimationSetKeyframes(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
keyframe_t *keyframes, keyframe_t *keyframes,
uint16_t *keyframeCounts, uint16_t *keyframeCounts,
const uint16_t layerCount const uint16_t layerCount
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
animationInit(&animComp->anim, keyframes, keyframeCounts, layerCount); animationInit(&animComp->anim, keyframes, keyframeCounts, layerCount);
animComp->speed = 1.0f; animComp->speed = 1.0f;
animComp->playing = false; animComp->playing = false;
} }
void entityAnimationPlay( void entityAnimationPlay(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
animComp->anim.time = 0.0f; animComp->anim.time = 0.0f;
// Clear the internal completed latch so a previously-finished // Clear the internal completed latch so a previously-finished
// (non-looping) animation can actually advance again. // (non-looping) animation can actually advance again.
@@ -61,61 +57,55 @@ void entityAnimationPlay(
} }
void entityAnimationStop( void entityAnimationStop(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
animComp->playing = false; animComp->playing = false;
} }
bool_t entityAnimationIsPlaying( bool_t entityAnimationIsPlaying(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
return animComp->playing; return animComp->playing;
} }
void entityAnimationSetLoop( void entityAnimationSetLoop(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const bool_t loop const bool_t loop
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
if(loop) animComp->anim.flags |= ANIMATION_FLAG_LOOP; if(loop) animComp->anim.flags |= ANIMATION_FLAG_LOOP;
else animComp->anim.flags &= ~ANIMATION_FLAG_LOOP; else animComp->anim.flags &= ~ANIMATION_FLAG_LOOP;
} }
void entityAnimationSetSpeed( void entityAnimationSetSpeed(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const float_t speed const float_t speed
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
animComp->speed = speed; animComp->speed = speed;
} }
float_t entityAnimationGetValue( float_t entityAnimationGetValue(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint16_t channelIndex const uint16_t channelIndex
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
return animationGetLayerValue(&animComp->anim, channelIndex); return animationGetLayerValue(&animComp->anim, channelIndex);
} }
void entityAnimationUpdate( void entityAnimationUpdate(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
) { ) {
entityanimation_t *animComp = entityAnimationGet(mgr, entityId, componentId); entityanimation_t *animComp = entityAnimationGet(entityId, componentId);
if(!animComp->playing) return; if(!animComp->playing) return;
animationUpdate(&animComp->anim, TIME.delta * animComp->speed); animationUpdate(&animComp->anim, TIME.delta * animComp->speed);
} }
@@ -34,12 +34,10 @@ typedef struct {
* entityAnimationUpdate as an update callback. Call * entityAnimationUpdate as an update callback. Call
* entityAnimationSetKeyframes() before entityAnimationPlay(). * entityAnimationSetKeyframes() before entityAnimationPlay().
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityAnimationInit( void entityAnimationInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -48,14 +46,12 @@ void entityAnimationInit(
* Gets the underlying animation structure (temporarily) for the given * Gets the underlying animation structure (temporarily) for the given
* entity. Prefer the dedicated getters/setters where possible. * entity. Prefer the dedicated getters/setters where possible.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The animation component data for the given entity and * @return The animation component data for the given entity and
* component ID. * component ID.
*/ */
entityanimation_t *entityAnimationGet( entityanimation_t *entityAnimationGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -66,7 +62,6 @@ entityanimation_t *entityAnimationGet(
* they point to are not copied, and must outlive this component (e.g. * they point to are not copied, and must outlive this component (e.g.
* static/const arrays owned by the caller). * static/const arrays owned by the caller).
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param keyframes Flat array of keyframe_t, one contiguous run per layer * @param keyframes Flat array of keyframe_t, one contiguous run per layer
@@ -76,7 +71,6 @@ entityanimation_t *entityAnimationGet(
* @param layerCount The number of layers/channels. * @param layerCount The number of layers/channels.
*/ */
void entityAnimationSetKeyframes( void entityAnimationSetKeyframes(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
keyframe_t *keyframes, keyframe_t *keyframes,
@@ -87,12 +81,10 @@ void entityAnimationSetKeyframes(
/** /**
* Starts (or restarts) playback from time 0. * Starts (or restarts) playback from time 0.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityAnimationPlay( void entityAnimationPlay(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -100,12 +92,10 @@ void entityAnimationPlay(
/** /**
* Stops playback without resetting the current time. * Stops playback without resetting the current time.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityAnimationStop( void entityAnimationStop(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -113,13 +103,11 @@ void entityAnimationStop(
/** /**
* Checks whether the animation is currently playing. * Checks whether the animation is currently playing.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return True if playing. * @return True if playing.
*/ */
bool_t entityAnimationIsPlaying( bool_t entityAnimationIsPlaying(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -128,13 +116,11 @@ bool_t entityAnimationIsPlaying(
* Sets whether the animation loops on reaching its final keyframe, rather * Sets whether the animation loops on reaching its final keyframe, rather
* than stopping there. * than stopping there.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param loop True to loop, false to stop at the end. * @param loop True to loop, false to stop at the end.
*/ */
void entityAnimationSetLoop( void entityAnimationSetLoop(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const bool_t loop const bool_t loop
@@ -143,13 +129,11 @@ void entityAnimationSetLoop(
/** /**
* Sets the animation's playback rate multiplier. * Sets the animation's playback rate multiplier.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param speed The new playback rate; 1.0 = normal speed. * @param speed The new playback rate; 1.0 = normal speed.
*/ */
void entityAnimationSetSpeed( void entityAnimationSetSpeed(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const float_t speed const float_t speed
@@ -159,7 +143,6 @@ void entityAnimationSetSpeed(
* Evaluates one of the animation's channels at its current playback * Evaluates one of the animation's channels at its current playback
* time, regardless of whether it's currently playing. * time, regardless of whether it's currently playing.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param channelIndex The channel to evaluate, in [0, channelCount) as * @param channelIndex The channel to evaluate, in [0, channelCount) as
@@ -167,7 +150,6 @@ void entityAnimationSetSpeed(
* @return That channel's value at the current time. * @return That channel's value at the current time.
*/ */
float_t entityAnimationGetValue( float_t entityAnimationGetValue(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint16_t channelIndex const uint16_t channelIndex
@@ -178,13 +160,11 @@ float_t entityAnimationGetValue(
* (a no-op if not playing). Registered automatically as an update * (a no-op if not playing). Registered automatically as an update
* callback by entityAnimationInit. * callback by entityAnimationInit.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param user Unused. * @param user Unused.
*/ */
void entityAnimationUpdate( void entityAnimationUpdate(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
@@ -5,18 +5,16 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#include "entity/entitymanager.h"
#include "entity/entity.h" #include "entity/entity.h"
#include "entity/component/display/entityposition.h" #include "entity/component/display/entityposition.h"
#include "display/screen/screen.h" #include "display/screen/screen.h"
void entityCameraInit( void entityCameraInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entitycamera_t *cam = (entitycamera_t *)componentGetData( entitycamera_t *cam = (entitycamera_t *)componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_CAMERA entityId, componentId, COMPONENT_TYPE_CAMERA
); );
cam->nearClip = 0.1f; cam->nearClip = 0.1f;
cam->farClip = 5000.0f; cam->farClip = 5000.0f;
@@ -25,13 +23,12 @@ void entityCameraInit(
} }
void entityCameraGetProjection( void entityCameraGetProjection(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 out mat4 out
) { ) {
entitycamera_t *cam = (entitycamera_t *)componentGetData( entitycamera_t *cam = (entitycamera_t *)componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_CAMERA entityId, componentId, COMPONENT_TYPE_CAMERA
); );
if( if(
@@ -64,26 +61,25 @@ void entityCameraGetProjection(
} }
} }
entityid_t entityCameraGetCurrent(entitymanager_t *mgr) { entityid_t entityCameraGetCurrent(void) {
entityid_t camEnts[ENTITY_COUNT_MAX]; entityid_t camEnts[ENTITY_COUNT_MAX];
componentid_t camComps[ENTITY_COUNT_MAX]; componentid_t camComps[ENTITY_COUNT_MAX];
entityid_t count = componentGetEntitiesWithComponent( entityid_t count = componentGetEntitiesWithComponent(
mgr, COMPONENT_TYPE_CAMERA, camEnts, camComps COMPONENT_TYPE_CAMERA, camEnts, camComps
); );
if(count == 0) return ENTITY_ID_INVALID; if(count == 0) return ENTITY_ID_INVALID;
return camEnts[0]; return camEnts[0];
} }
void entityCameraGetForward( void entityCameraGetForward(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
vec2 out vec2 out
) { ) {
componentid_t posComp = entityGetComponent( componentid_t posComp = entityGetComponent(
mgr, entityId, COMPONENT_TYPE_POSITION entityId, COMPONENT_TYPE_POSITION
); );
mat4 transform; mat4 transform;
entityPositionGetTransform(mgr, entityId, posComp, transform); entityPositionGetTransform(entityId, posComp, transform);
// transform is an object->world matrix; column 2 is the entity's local Z // transform is an object->world matrix; column 2 is the entity's local Z
// axis expressed in world space. Cameras look down their local -Z. // axis expressed in world space. Cameras look down their local -Z.
float_t fx = -transform[2][0]; float_t fx = -transform[2][0];
@@ -95,15 +91,14 @@ void entityCameraGetForward(
} }
void entityCameraGetRight( void entityCameraGetRight(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
vec2 out vec2 out
) { ) {
componentid_t posComp = entityGetComponent( componentid_t posComp = entityGetComponent(
mgr, entityId, COMPONENT_TYPE_POSITION entityId, COMPONENT_TYPE_POSITION
); );
mat4 transform; mat4 transform;
entityPositionGetTransform(mgr, entityId, posComp, transform); entityPositionGetTransform(entityId, posComp, transform);
// transform is an object->world matrix; column 0 is the entity's local X // transform is an object->world matrix; column 0 is the entity's local X
// (right) axis expressed in world space. // (right) axis expressed in world space.
float_t rx = transform[0][0]; float_t rx = transform[0][0];
@@ -115,7 +110,6 @@ void entityCameraGetRight(
} }
void entityCameraLookAtPixelPerfect( void entityCameraLookAtPixelPerfect(
entitymanager_t *mgr,
const entityid_t ent, const entityid_t ent,
const componentid_t posComp, const componentid_t posComp,
const componentid_t camComp, const componentid_t camComp,
@@ -124,7 +118,7 @@ void entityCameraLookAtPixelPerfect(
const float_t scale const float_t scale
) { ) {
entitycamera_t *cam = (entitycamera_t *)componentGetData( entitycamera_t *cam = (entitycamera_t *)componentGetData(
mgr, ent, camComp, COMPONENT_TYPE_CAMERA ent, camComp, COMPONENT_TYPE_CAMERA
); );
float_t dist = ( float_t dist = (
(float_t)SCREEN.height / (2.0f * scale * tanf(cam->perspective.fov * 0.5f)) (float_t)SCREEN.height / (2.0f * scale * tanf(cam->perspective.fov * 0.5f))
@@ -136,5 +130,5 @@ void entityCameraLookAtPixelPerfect(
point[2] + eyeOffset[2] point[2] + eyeOffset[2]
}; };
vec3 up = { 0.0f, 0.0f, -1.0f }; vec3 up = { 0.0f, 0.0f, -1.0f };
entityPositionLookAt(mgr, ent, posComp, eye, (float_t *)point, up); entityPositionLookAt(ent, posComp, eye, (float_t *)point, up);
} }
@@ -37,12 +37,10 @@ typedef struct {
/** /**
* Initializes an entity camera component. * Initializes an entity camera component.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityCameraInit( void entityCameraInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -50,13 +48,11 @@ void entityCameraInit(
/** /**
* Renders out the projection matrix for the given camera. * Renders out the projection matrix for the given camera.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param out The output projection matrix. * @param out The output projection matrix.
*/ */
void entityCameraGetProjection( void entityCameraGetProjection(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 out mat4 out
@@ -66,21 +62,18 @@ void entityCameraGetProjection(
* Returns the entity ID of the first active camera, or ENTITY_ID_INVALID if * Returns the entity ID of the first active camera, or ENTITY_ID_INVALID if
* none are active. * none are active.
* *
* @param mgr The entity manager to search.
*/ */
entityid_t entityCameraGetCurrent(entitymanager_t *mgr); entityid_t entityCameraGetCurrent(void);
/** /**
* Gets the camera's horizontal forward direction (XZ plane) from its * Gets the camera's horizontal forward direction (XZ plane) from its
* position component. Automatically finds the position component on the * position component. Automatically finds the position component on the
* entity. * entity.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The camera entity ID. * @param entityId The camera entity ID.
* @param out Output vec2: {forwardX, forwardZ} normalized. * @param out Output vec2: {forwardX, forwardZ} normalized.
*/ */
void entityCameraGetForward( void entityCameraGetForward(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
vec2 out vec2 out
); );
@@ -89,12 +82,10 @@ void entityCameraGetForward(
* Gets the camera's horizontal right direction (XZ plane) from its position * Gets the camera's horizontal right direction (XZ plane) from its position
* component. Automatically finds the position component on the entity. * component. Automatically finds the position component on the entity.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The camera entity ID. * @param entityId The camera entity ID.
* @param out Output vec2: {rightX, rightZ} normalized. * @param out Output vec2: {rightX, rightZ} normalized.
*/ */
void entityCameraGetRight( void entityCameraGetRight(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
vec2 out vec2 out
); );
@@ -103,7 +94,6 @@ void entityCameraGetRight(
* Positions the camera to look at a 3D point at a pixel-perfect distance * Positions the camera to look at a 3D point at a pixel-perfect distance
* derived from the camera's FOV and screen height. * derived from the camera's FOV and screen height.
* *
* @param mgr The entity manager that owns the entity.
* @param ent The camera entity ID. * @param ent The camera entity ID.
* @param posComp The position component ID. * @param posComp The position component ID.
* @param camComp The camera component ID. * @param camComp The camera component ID.
@@ -112,7 +102,6 @@ void entityCameraGetRight(
* @param scale Pixels per world unit. 1.0 = pixel perfect, 2.0 = 2px per unit. * @param scale Pixels per world unit. 1.0 = pixel perfect, 2.0 = 2px per unit.
*/ */
void entityCameraLookAtPixelPerfect( void entityCameraLookAtPixelPerfect(
entitymanager_t *mgr,
const entityid_t ent, const entityid_t ent,
const componentid_t posComp, const componentid_t posComp,
const componentid_t camComp, const componentid_t camComp,
@@ -5,16 +5,15 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#include "entity/entitymanager.h" #include "entity/entity.h"
#include "assert/assert.h" #include "assert/assert.h"
void entityPositionInit( void entityPositionInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
pos->flags = 0; pos->flags = 0;
@@ -29,7 +28,6 @@ void entityPositionInit(
} }
void entityPositionLookAt( void entityPositionLookAt(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 eye, vec3 eye,
@@ -37,7 +35,7 @@ void entityPositionLookAt(
vec3 up vec3 up
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
// glm_lookat() produces a view matrix (world -> eye space). Every other // glm_lookat() produces a view matrix (world -> eye space). Every other
// setter treats localTransform as this entity's placement in world space // setter treats localTransform as this entity's placement in world space
@@ -50,19 +48,18 @@ void entityPositionLookAt(
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_PRS_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_PRS_DIRTY)
& ~(ENTITY_POSITION_FLAG_ROTATION_DIRTY | & ~(ENTITY_POSITION_FLAG_ROTATION_DIRTY |
ENTITY_POSITION_FLAG_POSITION_DIRTY); ENTITY_POSITION_FLAG_POSITION_DIRTY);
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionGetTransform( void entityPositionGetTransform(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 dest mat4 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsureWorld(mgr, pos); entityPositionEnsureWorld(pos);
glm_mat4_copy( glm_mat4_copy(
pos->parentEntityId == ENTITY_ID_INVALID pos->parentEntityId == ENTITY_ID_INVALID
? pos->localTransform : pos->worldTransform, ? pos->localTransform : pos->worldTransform,
@@ -71,71 +68,67 @@ void entityPositionGetTransform(
} }
void entityPositionGetLocalTransform( void entityPositionGetLocalTransform(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 dest mat4 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsureLocal(pos); entityPositionEnsureLocal(pos);
glm_mat4_copy(pos->localTransform, dest); glm_mat4_copy(pos->localTransform, dest);
} }
void entityPositionGetLocalPosition( void entityPositionGetLocalPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->position, dest); glm_vec3_copy(pos->position, dest);
} }
void entityPositionGetWorldPosition( void entityPositionGetWorldPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->position, dest); glm_vec3_copy(pos->position, dest);
return; return;
} }
entityPositionEnsureWorld(mgr, pos); entityPositionEnsureWorld(pos);
dest[0] = pos->worldTransform[3][0]; dest[0] = pos->worldTransform[3][0];
dest[1] = pos->worldTransform[3][1]; dest[1] = pos->worldTransform[3][1];
dest[2] = pos->worldTransform[3][2]; dest[2] = pos->worldTransform[3][2];
} }
void entityPositionSetWorldPosition( void entityPositionSetWorldPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 position vec3 position
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
glm_vec3_copy(position, pos->position); glm_vec3_copy(position, pos->position);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
return; return;
} }
entityposition_t *parent = componentGetData( entityposition_t *parent = componentGetData(
mgr, pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsureWorld(mgr, parent); entityPositionEnsureWorld(parent);
mat4 invParent; mat4 invParent;
glm_mat4_inv(parent->worldTransform, invParent); glm_mat4_inv(parent->worldTransform, invParent);
vec3 localPos; vec3 localPos;
@@ -143,52 +136,49 @@ void entityPositionSetWorldPosition(
glm_vec3_copy(localPos, pos->position); glm_vec3_copy(localPos, pos->position);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionSetLocalPosition( void entityPositionSetLocalPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 position vec3 position
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
glm_vec3_copy(position, pos->position); glm_vec3_copy(position, pos->position);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_POSITION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionGetLocalRotation( void entityPositionGetLocalRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->rotation, dest); glm_vec3_copy(pos->rotation, dest);
} }
void entityPositionGetWorldRotation( void entityPositionGetWorldRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->rotation, dest); glm_vec3_copy(pos->rotation, dest);
return; return;
} }
entityPositionEnsureWorld(mgr, pos); entityPositionEnsureWorld(pos);
const float_t (*wt)[4] = pos->worldTransform; const float_t (*wt)[4] = pos->worldTransform;
const float_t sx = sqrtf( const float_t sx = sqrtf(
wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2] wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]
@@ -219,40 +209,38 @@ void entityPositionGetWorldRotation(
} }
void entityPositionSetLocalRotation( void entityPositionSetLocalRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 rotation vec3 rotation
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
glm_vec3_copy(rotation, pos->rotation); glm_vec3_copy(rotation, pos->rotation);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionSetWorldRotation( void entityPositionSetWorldRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 rotation vec3 rotation
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
glm_vec3_copy(rotation, pos->rotation); glm_vec3_copy(rotation, pos->rotation);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
return; return;
} }
entityposition_t *parent = componentGetData( entityposition_t *parent = componentGetData(
mgr, pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsureWorld(mgr, parent); entityPositionEnsureWorld(parent);
// Build target world rotation matrix (unit scale) from XYZ euler. // Build target world rotation matrix (unit scale) from XYZ euler.
const float_t c0 = cosf(rotation[0]), s0 = sinf(rotation[0]); const float_t c0 = cosf(rotation[0]), s0 = sinf(rotation[0]);
@@ -319,37 +307,35 @@ void entityPositionSetWorldRotation(
} }
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionGetLocalScale( void entityPositionGetLocalScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->scale, dest); glm_vec3_copy(pos->scale, dest);
} }
void entityPositionGetWorldScale( void entityPositionGetWorldScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
entityPositionEnsurePRS(pos); entityPositionEnsurePRS(pos);
glm_vec3_copy(pos->scale, dest); glm_vec3_copy(pos->scale, dest);
return; return;
} }
entityPositionEnsureWorld(mgr, pos); entityPositionEnsureWorld(pos);
const float_t (*wt)[4] = pos->worldTransform; const float_t (*wt)[4] = pos->worldTransform;
dest[0] = sqrtf(wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]); dest[0] = sqrtf(wt[0][0]*wt[0][0] + wt[0][1]*wt[0][1] + wt[0][2]*wt[0][2]);
dest[1] = sqrtf(wt[1][0]*wt[1][0] + wt[1][1]*wt[1][1] + wt[1][2]*wt[1][2]); dest[1] = sqrtf(wt[1][0]*wt[1][0] + wt[1][1]*wt[1][1] + wt[1][2]*wt[1][2]);
@@ -357,40 +343,38 @@ void entityPositionGetWorldScale(
} }
void entityPositionSetLocalScale( void entityPositionSetLocalScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 scale vec3 scale
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
glm_vec3_copy(scale, pos->scale); glm_vec3_copy(scale, pos->scale);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionSetWorldScale( void entityPositionSetWorldScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 scale vec3 scale
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
if(pos->parentEntityId == ENTITY_ID_INVALID) { if(pos->parentEntityId == ENTITY_ID_INVALID) {
glm_vec3_copy(scale, pos->scale); glm_vec3_copy(scale, pos->scale);
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
return; return;
} }
entityposition_t *parent = componentGetData( entityposition_t *parent = componentGetData(
mgr, pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION pos->parentEntityId, pos->parentComponentId, COMPONENT_TYPE_POSITION
); );
entityPositionEnsureWorld(mgr, parent); entityPositionEnsureWorld(parent);
const float_t (*pt)[4] = parent->worldTransform; const float_t (*pt)[4] = parent->worldTransform;
const float_t psx = sqrtf( const float_t psx = sqrtf(
pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2] pt[0][0]*pt[0][0] + pt[0][1]*pt[0][1] + pt[0][2]*pt[0][2]
@@ -406,24 +390,23 @@ void entityPositionSetWorldScale(
pos->scale[2] = psz > 0.0f ? scale[2] / psz : scale[2]; pos->scale[2] = psz > 0.0f ? scale[2] / psz : scale[2];
pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY) pos->flags = (pos->flags | ENTITY_POSITION_FLAG_ROTATION_DIRTY)
& ~ENTITY_POSITION_FLAG_PRS_DIRTY; & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionSetParent( void entityPositionSetParent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityid_t parentEntityId, const entityid_t parentEntityId,
const componentid_t parentComponentId const componentid_t parentComponentId
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
// Remove from old parent's child list. // Remove from old parent's child list.
if(pos->parentEntityId != ENTITY_ID_INVALID) { if(pos->parentEntityId != ENTITY_ID_INVALID) {
entityposition_t *oldParent = componentGetData( entityposition_t *oldParent = componentGetData(
mgr, pos->parentEntityId, pos->parentComponentId, pos->parentEntityId, pos->parentComponentId,
COMPONENT_TYPE_POSITION COMPONENT_TYPE_POSITION
); );
for(uint8_t i = 0; i < oldParent->childCount; i++) { for(uint8_t i = 0; i < oldParent->childCount; i++) {
@@ -447,7 +430,7 @@ void entityPositionSetParent(
// Register with new parent. // Register with new parent.
if(parentEntityId != ENTITY_ID_INVALID) { if(parentEntityId != ENTITY_ID_INVALID) {
entityposition_t *parent = componentGetData( entityposition_t *parent = componentGetData(
mgr, parentEntityId, parentComponentId, COMPONENT_TYPE_POSITION parentEntityId, parentComponentId, COMPONENT_TYPE_POSITION
); );
if(parent->childCount < ENTITY_POSITION_CHILDREN_MAX) { if(parent->childCount < ENTITY_POSITION_CHILDREN_MAX) {
parent->childEntityIds[parent->childCount] = entityId; parent->childEntityIds[parent->childCount] = entityId;
@@ -456,62 +439,59 @@ void entityPositionSetParent(
} }
} }
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
entityid_t entityPositionGetParent( entityid_t entityPositionGetParent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityposition_t *pos = componentGetData( entityposition_t *pos = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
return pos->parentEntityId; return pos->parentEntityId;
} }
entityposition_t *entityPositionGet( entityposition_t *entityPositionGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
return componentGetData( return componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_POSITION entityId, componentId, COMPONENT_TYPE_POSITION
); );
} }
void entityPositionRebuild(entitymanager_t *mgr, entityposition_t *pos) { void entityPositionRebuild(entityposition_t *pos) {
pos->flags = ( pos->flags = (
pos->flags | pos->flags |
ENTITY_POSITION_FLAG_ROTATION_DIRTY | ENTITY_POSITION_FLAG_ROTATION_DIRTY |
ENTITY_POSITION_FLAG_POSITION_DIRTY ENTITY_POSITION_FLAG_POSITION_DIRTY
) & ~ENTITY_POSITION_FLAG_PRS_DIRTY; ) & ~ENTITY_POSITION_FLAG_PRS_DIRTY;
entityPositionMarkDirty(mgr, pos); entityPositionMarkDirty(pos);
} }
void entityPositionMarkDirty(entitymanager_t *mgr, entityposition_t *pos) { void entityPositionMarkDirty(entityposition_t *pos) {
if(pos->flags & ENTITY_POSITION_FLAG_WORLD_DIRTY) return; if(pos->flags & ENTITY_POSITION_FLAG_WORLD_DIRTY) return;
pos->flags |= ENTITY_POSITION_FLAG_WORLD_DIRTY; pos->flags |= ENTITY_POSITION_FLAG_WORLD_DIRTY;
for(uint8_t i = 0; i < pos->childCount; i++) { for(uint8_t i = 0; i < pos->childCount; i++) {
entityposition_t *child = componentGetData( entityposition_t *child = componentGetData(
mgr, pos->childEntityIds[i], pos->childComponentIds[i], pos->childEntityIds[i], pos->childComponentIds[i],
COMPONENT_TYPE_POSITION COMPONENT_TYPE_POSITION
); );
entityPositionMarkDirty(mgr, child); entityPositionMarkDirty(child);
} }
} }
void entityPositionDisposeDeep( void entityPositionDisposeDeep(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityposition_t *pos = entityPositionGet(mgr, entityId, componentId); entityposition_t *pos = entityPositionGet(entityId, componentId);
// Detach from parent so the parent's child list stays consistent. // Detach from parent so the parent's child list stays consistent.
if(pos->parentEntityId != ENTITY_ID_INVALID) { if(pos->parentEntityId != ENTITY_ID_INVALID) {
entityPositionSetParent( entityPositionSetParent(
mgr, entityId, componentId, ENTITY_ID_INVALID, COMPONENT_ID_INVALID entityId, componentId, ENTITY_ID_INVALID, COMPONENT_ID_INVALID
); );
} }
@@ -526,16 +506,16 @@ void entityPositionDisposeDeep(
// Sever child's parent link so it won't try to modify our disposed // Sever child's parent link so it won't try to modify our disposed
// data. // data.
entityposition_t *child = entityPositionGet( entityposition_t *child = entityPositionGet(
mgr, childEntityIds[i], childComponentIds[i] childEntityIds[i], childComponentIds[i]
); );
child->parentEntityId = ENTITY_ID_INVALID; child->parentEntityId = ENTITY_ID_INVALID;
child->parentComponentId = COMPONENT_ID_INVALID; child->parentComponentId = COMPONENT_ID_INVALID;
} }
entityDispose(mgr, entityId); entityDispose(entityId);
for(uint8_t i = 0; i < childCount; i++) { for(uint8_t i = 0; i < childCount; i++) {
entityPositionDisposeDeep(mgr, childEntityIds[i], childComponentIds[i]); entityPositionDisposeDeep(childEntityIds[i], childComponentIds[i]);
} }
} }
@@ -642,7 +622,7 @@ void entityPositionEnsureLocal(entityposition_t *pos) {
); );
} }
void entityPositionEnsureWorld(entitymanager_t *mgr, entityposition_t *pos) { void entityPositionEnsureWorld(entityposition_t *pos) {
if(!(pos->flags & ENTITY_POSITION_FLAG_WORLD_DIRTY)) return; if(!(pos->flags & ENTITY_POSITION_FLAG_WORLD_DIRTY)) return;
entityPositionEnsureLocal(pos); entityPositionEnsureLocal(pos);
@@ -650,10 +630,10 @@ void entityPositionEnsureWorld(entitymanager_t *mgr, entityposition_t *pos) {
// Parented: world = parent.world x local. worldTransform must be // Parented: world = parent.world x local. worldTransform must be
// written because children (and this node's getters) read it. // written because children (and this node's getters) read it.
entityposition_t *parent = componentGetData( entityposition_t *parent = componentGetData(
mgr, pos->parentEntityId, pos->parentComponentId, pos->parentEntityId, pos->parentComponentId,
COMPONENT_TYPE_POSITION COMPONENT_TYPE_POSITION
); );
entityPositionEnsureWorld(mgr, parent); entityPositionEnsureWorld(parent);
glm_mat4_mul( glm_mat4_mul(
parent->worldTransform, pos->localTransform, pos->worldTransform parent->worldTransform, pos->localTransform, pos->worldTransform
); );
@@ -83,12 +83,10 @@ typedef struct {
* Initializes the entity position component, setting identity transforms and * Initializes the entity position component, setting identity transforms and
* zeroing all parent/child state. * zeroing all parent/child state.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityPositionInit( void entityPositionInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -99,7 +97,6 @@ void entityPositionInit(
* setter), not as a view matrix -- invert entityPositionGetTransform()'s * setter), not as a view matrix -- invert entityPositionGetTransform()'s
* result to get a view matrix for rendering. * result to get a view matrix for rendering.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param eye The eye/camera position. * @param eye The eye/camera position.
@@ -107,7 +104,6 @@ void entityPositionInit(
* @param up The up vector. * @param up The up vector.
*/ */
void entityPositionLookAt( void entityPositionLookAt(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 eye, vec3 eye,
@@ -118,13 +114,11 @@ void entityPositionLookAt(
/** /**
* Gets the world-space transform matrix, recomputing it lazily if dirty. * Gets the world-space transform matrix, recomputing it lazily if dirty.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination matrix. * @param dest Destination matrix.
*/ */
void entityPositionGetTransform( void entityPositionGetTransform(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 dest mat4 dest
@@ -133,13 +127,11 @@ void entityPositionGetTransform(
/** /**
* Gets the local transform matrix (does not include parent transforms). * Gets the local transform matrix (does not include parent transforms).
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination matrix. * @param dest Destination matrix.
*/ */
void entityPositionGetLocalTransform( void entityPositionGetLocalTransform(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
mat4 dest mat4 dest
@@ -150,13 +142,11 @@ void entityPositionGetLocalTransform(
* first if ENTITY_POSITION_FLAG_PRS_DIRTY is set; never triggers a matrix * first if ENTITY_POSITION_FLAG_PRS_DIRTY is set; never triggers a matrix
* rebuild or world-transform update. * rebuild or world-transform update.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetLocalPosition( void entityPositionGetLocalPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -166,13 +156,11 @@ void entityPositionGetLocalPosition(
* Gets the world-space position. For parentless entities this is the same as * Gets the world-space position. For parentless entities this is the same as
* the local position. * the local position.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetWorldPosition( void entityPositionGetWorldPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -183,13 +171,11 @@ void entityPositionGetWorldPosition(
* to entityPositionSetLocalPosition. For parented entities the position is * to entityPositionSetLocalPosition. For parented entities the position is
* converted to local space via the inverted parent world transform. * converted to local space via the inverted parent world transform.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param position The desired world-space position. * @param position The desired world-space position.
*/ */
void entityPositionSetWorldPosition( void entityPositionSetWorldPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 position vec3 position
@@ -199,13 +185,11 @@ void entityPositionSetWorldPosition(
* Sets the local position, marks localTransform and worldTransform (self + * Sets the local position, marks localTransform and worldTransform (self +
* descendants) dirty. * descendants) dirty.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param position The new local position. * @param position The new local position.
*/ */
void entityPositionSetLocalPosition( void entityPositionSetLocalPosition(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 position vec3 position
@@ -215,13 +199,11 @@ void entityPositionSetLocalPosition(
* Gets the cached local euler rotation (XYZ, radians). Decomposes * Gets the cached local euler rotation (XYZ, radians). Decomposes
* localTransform first if ENTITY_POSITION_FLAG_PRS_DIRTY is set. * localTransform first if ENTITY_POSITION_FLAG_PRS_DIRTY is set.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetLocalRotation( void entityPositionGetLocalRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -232,13 +214,11 @@ void entityPositionGetLocalRotation(
* world transform. For parentless entities this is the same as local * world transform. For parentless entities this is the same as local
* rotation. * rotation.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetWorldRotation( void entityPositionGetWorldRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -247,13 +227,11 @@ void entityPositionGetWorldRotation(
/** /**
* Sets the local euler rotation (XYZ, radians) and marks transforms dirty. * Sets the local euler rotation (XYZ, radians) and marks transforms dirty.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param rotation The new local rotation. * @param rotation The new local rotation.
*/ */
void entityPositionSetLocalRotation( void entityPositionSetLocalRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 rotation vec3 rotation
@@ -265,13 +243,11 @@ void entityPositionSetLocalRotation(
* parented entities the rotation is converted to local space by removing * parented entities the rotation is converted to local space by removing
* the parent world rotation. * the parent world rotation.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param rotation The desired world-space euler rotation. * @param rotation The desired world-space euler rotation.
*/ */
void entityPositionSetWorldRotation( void entityPositionSetWorldRotation(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 rotation vec3 rotation
@@ -281,13 +257,11 @@ void entityPositionSetWorldRotation(
* Gets the cached local scale. Decomposes localTransform first if * Gets the cached local scale. Decomposes localTransform first if
* ENTITY_POSITION_FLAG_PRS_DIRTY is set. * ENTITY_POSITION_FLAG_PRS_DIRTY is set.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetLocalScale( void entityPositionGetLocalScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -297,13 +271,11 @@ void entityPositionGetLocalScale(
* Gets the world-space scale by extracting column lengths from the world * Gets the world-space scale by extracting column lengths from the world
* transform. For parentless entities this is the same as local scale. * transform. For parentless entities this is the same as local scale.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest Destination vector. * @param dest Destination vector.
*/ */
void entityPositionGetWorldScale( void entityPositionGetWorldScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -312,13 +284,11 @@ void entityPositionGetWorldScale(
/** /**
* Sets the local scale and marks transforms dirty. * Sets the local scale and marks transforms dirty.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param scale The new local scale. * @param scale The new local scale.
*/ */
void entityPositionSetLocalScale( void entityPositionSetLocalScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 scale vec3 scale
@@ -329,13 +299,11 @@ void entityPositionSetLocalScale(
* entityPositionSetLocalScale. For parented entities the scale is converted * entityPositionSetLocalScale. For parented entities the scale is converted
* to local space by dividing by the parent world scale (assumes no shear). * to local space by dividing by the parent world scale (assumes no shear).
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param scale The desired world-space scale. * @param scale The desired world-space scale.
*/ */
void entityPositionSetWorldScale( void entityPositionSetWorldScale(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 scale vec3 scale
@@ -345,14 +313,12 @@ void entityPositionSetWorldScale(
* Sets the parent of this entity's position component. * Sets the parent of this entity's position component.
* Pass ENTITY_ID_INVALID / COMPONENT_ID_INVALID to detach from any parent. * Pass ENTITY_ID_INVALID / COMPONENT_ID_INVALID to detach from any parent.
* *
* @param mgr The entity manager that owns both entities.
* @param entityId The child entity ID. * @param entityId The child entity ID.
* @param componentId The child component ID. * @param componentId The child component ID.
* @param parentEntityId The parent entity ID. * @param parentEntityId The parent entity ID.
* @param parentComponentId The parent component ID. * @param parentComponentId The parent component ID.
*/ */
void entityPositionSetParent( void entityPositionSetParent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityid_t parentEntityId, const entityid_t parentEntityId,
@@ -362,13 +328,11 @@ void entityPositionSetParent(
/** /**
* Gets the entity ID of this position component's parent. * Gets the entity ID of this position component's parent.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The parent entity ID, or ENTITY_ID_INVALID if unparented. * @return The parent entity ID, or ENTITY_ID_INVALID if unparented.
*/ */
entityid_t entityPositionGetParent( entityid_t entityPositionGetParent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -379,13 +343,11 @@ entityid_t entityPositionGetParent(
* set ENTITY_POSITION_FLAG_WORLD_DIRTY on self and descendants. After * set ENTITY_POSITION_FLAG_WORLD_DIRTY on self and descendants. After
* modifying PRS directly, call entityPositionRebuild() instead. * modifying PRS directly, call entityPositionRebuild() instead.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return Pointer to the component data. * @return Pointer to the component data.
*/ */
entityposition_t *entityPositionGet( entityposition_t *entityPositionGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -397,31 +359,27 @@ entityposition_t *entityPositionGet(
* ENTITY_POSITION_FLAG_PRS_DIRTY, propagates ENTITY_POSITION_FLAG_WORLD_DIRTY * ENTITY_POSITION_FLAG_PRS_DIRTY, propagates ENTITY_POSITION_FLAG_WORLD_DIRTY
* to self and all descendants. * to self and all descendants.
* *
* @param mgr The entity manager that owns pos and its descendants.
* @param pos The position component whose PRS was modified. * @param pos The position component whose PRS was modified.
*/ */
void entityPositionRebuild(entitymanager_t *mgr, entityposition_t *pos); void entityPositionRebuild(entityposition_t *pos);
/** /**
* Sets ENTITY_POSITION_FLAG_WORLD_DIRTY on this node and all descendants, * Sets ENTITY_POSITION_FLAG_WORLD_DIRTY on this node and all descendants,
* indicating that worldTransform must be recomputed before it is read. * indicating that worldTransform must be recomputed before it is read.
* Call this after modifying localTransform directly. * Call this after modifying localTransform directly.
* *
* @param mgr The entity manager that owns pos and its descendants.
* @param pos The position component to mark dirty. * @param pos The position component to mark dirty.
*/ */
void entityPositionMarkDirty(entitymanager_t *mgr, entityposition_t *pos); void entityPositionMarkDirty(entityposition_t *pos);
/** /**
* Disposes this entity and all of its position-component descendants * Disposes this entity and all of its position-component descendants
* recursively. Detaches from any parent before destroying. * recursively. Detaches from any parent before destroying.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The root entity ID. * @param entityId The root entity ID.
* @param componentId The root position component ID. * @param componentId The root position component ID.
*/ */
void entityPositionDisposeDeep( void entityPositionDisposeDeep(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -454,7 +412,6 @@ void entityPositionEnsureLocal(entityposition_t *pos);
* Internal. Recomputes worldTransform from the parent chain if * Internal. Recomputes worldTransform from the parent chain if
* ENTITY_POSITION_FLAG_WORLD_DIRTY is set. * ENTITY_POSITION_FLAG_WORLD_DIRTY is set.
* *
* @param mgr The entity manager that owns pos and its ancestors.
* @param pos The position component to update. * @param pos The position component to update.
*/ */
void entityPositionEnsureWorld(entitymanager_t *mgr, entityposition_t *pos); void entityPositionEnsureWorld(entityposition_t *pos);
@@ -6,7 +6,7 @@
*/ */
#include "entityrenderable.h" #include "entityrenderable.h"
#include "entity/entitymanager.h" #include "entity/entity.h"
#include "display/shader/shadermaterial.h" #include "display/shader/shadermaterial.h"
#include "display/shader/shaderunlit.h" #include "display/shader/shaderunlit.h"
#include "display/display.h" #include "display/display.h"
@@ -15,12 +15,11 @@
#include "assert/assert.h" #include "assert/assert.h"
void entityRenderableInit( void entityRenderableInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
memoryZero(r, sizeof(entityrenderable_t)); memoryZero(r, sizeof(entityrenderable_t));
r->type = ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL; r->type = ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL;
@@ -34,44 +33,40 @@ void entityRenderableInit(
} }
void entityRenderableDispose( void entityRenderableDispose(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
} }
void entityRenderableSetType( void entityRenderableSetType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityrenderabletype_t type const entityrenderabletype_t type
) { ) {
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
r->type = type; r->type = type;
} }
void entityRenderableSetPriority( void entityRenderableSetPriority(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const int8_t priority const int8_t priority
) { ) {
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
r->priority = priority; r->priority = priority;
} }
void entityRenderableSetColor( void entityRenderableSetColor(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const color_t color const color_t color
) { ) {
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
assertTrue( assertTrue(
r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL, r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL,
@@ -81,7 +76,6 @@ void entityRenderableSetColor(
} }
void entityRenderableSetMesh( void entityRenderableSetMesh(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint8_t slot, const uint8_t slot,
@@ -91,7 +85,7 @@ void entityRenderableSetMesh(
assertTrue(slot < ENTITY_RENDERABLE_MESHES_MAX, "Mesh slot out of bounds"); assertTrue(slot < ENTITY_RENDERABLE_MESHES_MAX, "Mesh slot out of bounds");
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
assertTrue( assertTrue(
r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL, r->type == ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL,
@@ -107,11 +101,9 @@ void entityRenderableSetMesh(
} }
void entityRenderableSetDraw( void entityRenderableSetDraw(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
errorret_t (*draw)( errorret_t (*draw)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
@@ -120,7 +112,7 @@ void entityRenderableSetDraw(
) { ) {
assertNotNull(draw, "Draw callback cannot be null"); assertNotNull(draw, "Draw callback cannot be null");
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
r->type = ENTITY_RENDERABLE_TYPE_CUSTOM; r->type = ENTITY_RENDERABLE_TYPE_CUSTOM;
r->data.custom.draw = draw; r->data.custom.draw = draw;
@@ -128,12 +120,11 @@ void entityRenderableSetDraw(
} }
errorret_t entityRenderableDraw( errorret_t entityRenderableDraw(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityrenderable_t *r = componentGetData( entityrenderable_t *r = componentGetData(
mgr, entityId, componentId, COMPONENT_TYPE_RENDERABLE entityId, componentId, COMPONENT_TYPE_RENDERABLE
); );
switch(r->type) { switch(r->type) {
case ENTITY_RENDERABLE_TYPE_SPRITEBATCH: case ENTITY_RENDERABLE_TYPE_SPRITEBATCH:
@@ -142,7 +133,7 @@ errorret_t entityRenderableDraw(
return entityRenderableDrawMaterial(&r->data.material); return entityRenderableDrawMaterial(&r->data.material);
case ENTITY_RENDERABLE_TYPE_CUSTOM: case ENTITY_RENDERABLE_TYPE_CUSTOM:
return entityRenderableDrawCustom( return entityRenderableDrawCustom(
mgr, entityId, componentId, &r->data.custom entityId, componentId, &r->data.custom
); );
default: default:
assertUnreachable("Invalid renderable type"); assertUnreachable("Invalid renderable type");
@@ -183,10 +174,9 @@ errorret_t entityRenderableDrawMaterial(const entityrenderablematerial_t *m) {
} }
errorret_t entityRenderableDrawCustom( errorret_t entityRenderableDrawCustom(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityrenderablecustom_t *custom const entityrenderablecustom_t *custom
) { ) {
return custom->draw(mgr, entityId, componentId, custom->drawUser); return custom->draw(entityId, componentId, custom->drawUser);
} }
@@ -40,7 +40,6 @@ typedef struct {
typedef struct { typedef struct {
errorret_t (*draw)( errorret_t (*draw)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
@@ -70,12 +69,10 @@ typedef struct {
* ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL with the unlit shader, a white * ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL with the unlit shader, a white
* cube, and depth-test enabled. * cube, and depth-test enabled.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to initialize the component for. * @param entityId The entity to initialize the component for.
* @param componentId The renderable component of the entity. * @param componentId The renderable component of the entity.
*/ */
void entityRenderableInit( void entityRenderableInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -83,12 +80,10 @@ void entityRenderableInit(
/** /**
* Disposes the entity renderable component. * Disposes the entity renderable component.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to dispose the component for. * @param entityId The entity to dispose the component for.
* @param componentId The renderable component of the entity. * @param componentId The renderable component of the entity.
*/ */
void entityRenderableDispose( void entityRenderableDispose(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -97,13 +92,11 @@ void entityRenderableDispose(
* Sets the rendering type for the renderable component. Resets * Sets the rendering type for the renderable component. Resets
* type-specific data to zero. * type-specific data to zero.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to configure. * @param entityId The entity to configure.
* @param componentId The renderable component. * @param componentId The renderable component.
* @param type The rendering type to use. * @param type The rendering type to use.
*/ */
void entityRenderableSetType( void entityRenderableSetType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityrenderabletype_t type const entityrenderabletype_t type
@@ -113,13 +106,11 @@ void entityRenderableSetType(
* Sets the render priority. 0 = auto (derived from type/flags). Higher * Sets the render priority. 0 = auto (derived from type/flags). Higher
* values render later (on top). Use non-zero to force ordering. * values render later (on top). Use non-zero to force ordering.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to configure. * @param entityId The entity to configure.
* @param componentId The renderable component. * @param componentId The renderable component.
* @param priority The priority value, or 0 for auto. * @param priority The priority value, or 0 for auto.
*/ */
void entityRenderableSetPriority( void entityRenderableSetPriority(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const int8_t priority const int8_t priority
@@ -130,13 +121,11 @@ void entityRenderableSetPriority(
* (or defaults to) ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL -- asserts * (or defaults to) ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL -- asserts
* otherwise. * otherwise.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to configure. * @param entityId The entity to configure.
* @param componentId The renderable component. * @param componentId The renderable component.
* @param color The color to tint the material with. * @param color The color to tint the material with.
*/ */
void entityRenderableSetColor( void entityRenderableSetColor(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const color_t color const color_t color
@@ -147,7 +136,6 @@ void entityRenderableSetColor(
* count override). Only meaningful when the renderable is (or defaults * count override). Only meaningful when the renderable is (or defaults
* to) ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL -- asserts otherwise. * to) ENTITY_RENDERABLE_TYPE_SHADER_MATERIAL -- asserts otherwise.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to configure. * @param entityId The entity to configure.
* @param componentId The renderable component. * @param componentId The renderable component.
* @param slot Index into the material's meshes array (0 to * @param slot Index into the material's meshes array (0 to
@@ -155,7 +143,6 @@ void entityRenderableSetColor(
* @param mesh The mesh to draw in that slot. * @param mesh The mesh to draw in that slot.
*/ */
void entityRenderableSetMesh( void entityRenderableSetMesh(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint8_t slot, const uint8_t slot,
@@ -166,18 +153,15 @@ void entityRenderableSetMesh(
* Sets the draw callback, switching the type to * Sets the draw callback, switching the type to
* ENTITY_RENDERABLE_TYPE_CUSTOM. * ENTITY_RENDERABLE_TYPE_CUSTOM.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to configure. * @param entityId The entity to configure.
* @param componentId The renderable component of the entity. * @param componentId The renderable component of the entity.
* @param draw The draw callback to assign. * @param draw The draw callback to assign.
* @param user Userdata passed to the callback. * @param user Userdata passed to the callback.
*/ */
void entityRenderableSetDraw( void entityRenderableSetDraw(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
errorret_t (*draw)( errorret_t (*draw)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
@@ -188,13 +172,11 @@ void entityRenderableSetDraw(
/** /**
* Draws the entity using its renderable component data. * Draws the entity using its renderable component data.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to draw. * @param entityId The entity to draw.
* @param componentId The renderable component of the entity. * @param componentId The renderable component of the entity.
* @return Any error state that happened. * @return Any error state that happened.
*/ */
errorret_t entityRenderableDraw( errorret_t entityRenderableDraw(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -220,14 +202,12 @@ errorret_t entityRenderableDrawMaterial(const entityrenderablematerial_t *m);
/** /**
* Internal. Invokes a custom-type renderable's draw callback. * Internal. Invokes a custom-type renderable's draw callback.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity being drawn. * @param entityId The entity being drawn.
* @param componentId The renderable component of the entity. * @param componentId The renderable component of the entity.
* @param custom The custom draw data. * @param custom The custom draw data.
* @return Error state. * @return Error state.
*/ */
errorret_t entityRenderableDrawCustom( errorret_t entityRenderableDrawCustom(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityrenderablecustom_t *custom const entityrenderablecustom_t *custom
@@ -6,15 +6,14 @@
*/ */
#include "entityphysics.h" #include "entityphysics.h"
#include "entity/entitymanager.h" #include "entity/entity.h"
#include "util/memory.h" #include "util/memory.h"
void entityPhysicsInit( void entityPhysicsInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
memoryZero(phys, sizeof(entityphysics_t)); memoryZero(phys, sizeof(entityphysics_t));
@@ -30,106 +29,95 @@ void entityPhysicsInit(
} }
entityphysics_t *entityPhysicsGet( entityphysics_t *entityPhysicsGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
return componentGetData(mgr, entityId, componentId, COMPONENT_TYPE_PHYSICS); return componentGetData(entityId, componentId, COMPONENT_TYPE_PHYSICS);
} }
void entityPhysicsSetShape( void entityPhysicsSetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsshape_t shape const physicsshape_t shape
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
phys->shape = shape; phys->shape = shape;
} }
physicsshape_t entityPhysicsGetShape( physicsshape_t entityPhysicsGetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
return phys->shape; return phys->shape;
} }
void entityPhysicsGetVelocity( void entityPhysicsGetVelocity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
glm_vec3_copy(phys->velocity, dest); glm_vec3_copy(phys->velocity, dest);
} }
void entityPhysicsSetVelocity( void entityPhysicsSetVelocity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 velocity vec3 velocity
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
glm_vec3_copy(velocity, phys->velocity); glm_vec3_copy(velocity, phys->velocity);
} }
void entityPhysicsApplyImpulse( void entityPhysicsApplyImpulse(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 impulse vec3 impulse
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
if(phys->type == PHYSICS_BODY_STATIC) return; if(phys->type == PHYSICS_BODY_STATIC) return;
glm_vec3_add(phys->velocity, impulse, phys->velocity); glm_vec3_add(phys->velocity, impulse, phys->velocity);
} }
bool_t entityPhysicsIsOnGround( bool_t entityPhysicsIsOnGround(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
return phys->onGround; return phys->onGround;
} }
void entityPhysicsSetBodyType( void entityPhysicsSetBodyType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsbodytype_t type const physicsbodytype_t type
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
phys->type = type; phys->type = type;
} }
physicsbodytype_t entityPhysicsGetBodyType( physicsbodytype_t entityPhysicsGetBodyType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
return phys->type; return phys->type;
} }
void entityPhysicsSetCollideMask( void entityPhysicsSetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint32_t mask const uint32_t mask
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
phys->collideMask = mask; phys->collideMask = mask;
} }
uint32_t entityPhysicsGetCollideMask( uint32_t entityPhysicsGetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entityphysics_t *phys = entityPhysicsGet(mgr, entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
return phys->collideMask; return phys->collideMask;
} }
@@ -31,12 +31,10 @@ typedef struct {
* Initializes the physics component: defaults to a dynamic 1x1x1 cube * Initializes the physics component: defaults to a dynamic 1x1x1 cube
* body, zero velocity, unit gravity scale, and onGround false. * body, zero velocity, unit gravity scale, and onGround false.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityPhysicsInit( void entityPhysicsInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -46,13 +44,11 @@ void entityPhysicsInit(
* This is really just intended for doing operations faster than using the * This is really just intended for doing operations faster than using the
* getters and setters, but it is preferred that you use those. * getters and setters, but it is preferred that you use those.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The physics component data for the given entity and component ID. * @return The physics component data for the given entity and component ID.
*/ */
entityphysics_t *entityPhysicsGet( entityphysics_t *entityPhysicsGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -62,13 +58,11 @@ entityphysics_t *entityPhysicsGet(
* state, so if you change from a cube to a sphere, it will keep the same * state, so if you change from a cube to a sphere, it will keep the same
* velocity and onGround state. * velocity and onGround state.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param shape The new shape to set on the physics body. * @param shape The new shape to set on the physics body.
*/ */
void entityPhysicsSetShape( void entityPhysicsSetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsshape_t shape const physicsshape_t shape
@@ -77,13 +71,11 @@ void entityPhysicsSetShape(
/** /**
* Gets the shape of the entity's physics body. * Gets the shape of the entity's physics body.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The shape of the physics body. * @return The shape of the physics body.
*/ */
physicsshape_t entityPhysicsGetShape( physicsshape_t entityPhysicsGetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -91,13 +83,11 @@ physicsshape_t entityPhysicsGetShape(
/** /**
* Gets the velocity of the entity's physics body. * Gets the velocity of the entity's physics body.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param dest The destination vec3 to write the velocity to. * @param dest The destination vec3 to write the velocity to.
*/ */
void entityPhysicsGetVelocity( void entityPhysicsGetVelocity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 dest vec3 dest
@@ -107,13 +97,11 @@ void entityPhysicsGetVelocity(
* Sets the velocity of the entity's physics body. This is not an impulse, so * Sets the velocity of the entity's physics body. This is not an impulse, so
* it will be affected by mass and drag. * it will be affected by mass and drag.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param velocity The new velocity to set on the physics body. * @param velocity The new velocity to set on the physics body.
*/ */
void entityPhysicsSetVelocity( void entityPhysicsSetVelocity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 velocity vec3 velocity
@@ -124,13 +112,11 @@ void entityPhysicsSetVelocity(
* velocity change that is not affected by mass or drag. No-op on STATIC * velocity change that is not affected by mass or drag. No-op on STATIC
* bodies. * bodies.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param impulse The impulse to apply to the physics body. * @param impulse The impulse to apply to the physics body.
*/ */
void entityPhysicsApplyImpulse( void entityPhysicsApplyImpulse(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
vec3 impulse vec3 impulse
@@ -140,13 +126,11 @@ void entityPhysicsApplyImpulse(
* Returns true if the entity's physics body rested on a surface during the * Returns true if the entity's physics body rested on a surface during the
* last physicsWorldStep. * last physicsWorldStep.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return True if the body is on the ground, false otherwise. * @return True if the body is on the ground, false otherwise.
*/ */
bool_t entityPhysicsIsOnGround( bool_t entityPhysicsIsOnGround(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -154,13 +138,11 @@ bool_t entityPhysicsIsOnGround(
/** /**
* Sets the body type of the entity's physics body. * Sets the body type of the entity's physics body.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param type The body type to set. * @param type The body type to set.
*/ */
void entityPhysicsSetBodyType( void entityPhysicsSetBodyType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsbodytype_t type const physicsbodytype_t type
@@ -169,13 +151,11 @@ void entityPhysicsSetBodyType(
/** /**
* Gets the body type of the entity's physics body. * Gets the body type of the entity's physics body.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The body type of the physics body. * @return The body type of the physics body.
*/ */
physicsbodytype_t entityPhysicsGetBodyType( physicsbodytype_t entityPhysicsGetBodyType(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -184,13 +164,11 @@ physicsbodytype_t entityPhysicsGetBodyType(
* Sets the collision mask of the entity's physics body. Two bodies only * Sets the collision mask of the entity's physics body. Two bodies only
* collide if their masks share at least one set bit. * collide if their masks share at least one set bit.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param mask The new collision mask to set on the physics body. * @param mask The new collision mask to set on the physics body.
*/ */
void entityPhysicsSetCollideMask( void entityPhysicsSetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint32_t mask const uint32_t mask
@@ -199,13 +177,11 @@ void entityPhysicsSetCollideMask(
/** /**
* Gets the collision mask of the entity's physics body. * Gets the collision mask of the entity's physics body.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The collision mask of the physics body. * @return The collision mask of the physics body.
*/ */
uint32_t entityPhysicsGetCollideMask( uint32_t entityPhysicsGetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -6,15 +6,14 @@
*/ */
#include "entitytrigger.h" #include "entitytrigger.h"
#include "entity/entitymanager.h" #include "entity/entity.h"
#include "util/memory.h" #include "util/memory.h"
void entityTriggerInit( void entityTriggerInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
memoryZero(trig, sizeof(entitytrigger_t)); memoryZero(trig, sizeof(entitytrigger_t));
@@ -26,78 +25,70 @@ void entityTriggerInit(
} }
entitytrigger_t *entityTriggerGet( entitytrigger_t *entityTriggerGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
return componentGetData(mgr, entityId, componentId, COMPONENT_TYPE_TRIGGER); return componentGetData(entityId, componentId, COMPONENT_TYPE_TRIGGER);
} }
void entityTriggerSetShape( void entityTriggerSetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsshape_t shape const physicsshape_t shape
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
trig->shape = shape; trig->shape = shape;
} }
physicsshape_t entityTriggerGetShape( physicsshape_t entityTriggerGetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
return trig->shape; return trig->shape;
} }
void entityTriggerSetCollideMask( void entityTriggerSetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint32_t mask const uint32_t mask
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
trig->collideMask = mask; trig->collideMask = mask;
} }
uint32_t entityTriggerGetCollideMask( uint32_t entityTriggerGetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
return trig->collideMask; return trig->collideMask;
} }
uint8_t entityTriggerGetOccupantCount( uint8_t entityTriggerGetOccupantCount(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
return trig->occupantCount; return trig->occupantCount;
} }
entityid_t entityTriggerGetOccupantEntityId( entityid_t entityTriggerGetOccupantEntityId(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint8_t index const uint8_t index
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
if(index >= trig->occupantCount) return ENTITY_ID_INVALID; if(index >= trig->occupantCount) return ENTITY_ID_INVALID;
return trig->occupants[index].entityId; return trig->occupants[index].entityId;
} }
bool_t entityTriggerIsOccupyingEntity( bool_t entityTriggerIsOccupyingEntity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityid_t otherEntityId const entityid_t otherEntityId
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
for(uint8_t i = 0; i < trig->occupantCount; i++) { for(uint8_t i = 0; i < trig->occupantCount; i++) {
if(trig->occupants[i].entityId == otherEntityId) return true; if(trig->occupants[i].entityId == otherEntityId) return true;
} }
@@ -20,7 +20,6 @@
* Callback invoked for a trigger's onEnter/onActive/onMove/onLeave events. * Callback invoked for a trigger's onEnter/onActive/onMove/onLeave events.
* See entityTriggerOnEnterAdd() and its onActive/onMove/onLeave siblings. * See entityTriggerOnEnterAdd() and its onActive/onMove/onLeave siblings.
* *
* @param mgr The entity manager that owns both entities.
* @param triggerEntityId The entity ID of the trigger volume. * @param triggerEntityId The entity ID of the trigger volume.
* @param triggerComponentId The TRIGGER component ID. * @param triggerComponentId The TRIGGER component ID.
* @param otherEntityId The entity ID that entered/is inside/left the * @param otherEntityId The entity ID that entered/is inside/left the
@@ -29,7 +28,6 @@
* @param user The user pointer passed to the matching *Add() call. * @param user The user pointer passed to the matching *Add() call.
*/ */
typedef void (*triggercallback_t)( typedef void (*triggercallback_t)(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
@@ -93,12 +91,10 @@ typedef struct {
* Initializes the trigger component: defaults to a 1x1x1 cube volume, no * Initializes the trigger component: defaults to a 1x1x1 cube volume, no
* tracked occupants, and no event subscribers. * tracked occupants, and no event subscribers.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
*/ */
void entityTriggerInit( void entityTriggerInit(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -107,13 +103,11 @@ void entityTriggerInit(
* Gets the underlying trigger structure (temporarily) for the given * Gets the underlying trigger structure (temporarily) for the given
* entity. Prefer the dedicated getters/setters where possible. * entity. Prefer the dedicated getters/setters where possible.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The trigger component data for the given entity and component ID. * @return The trigger component data for the given entity and component ID.
*/ */
entitytrigger_t *entityTriggerGet( entitytrigger_t *entityTriggerGet(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -121,13 +115,11 @@ entitytrigger_t *entityTriggerGet(
/** /**
* Sets the shape of the trigger volume. * Sets the shape of the trigger volume.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param shape The new shape to set on the trigger volume. * @param shape The new shape to set on the trigger volume.
*/ */
void entityTriggerSetShape( void entityTriggerSetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const physicsshape_t shape const physicsshape_t shape
@@ -136,13 +128,11 @@ void entityTriggerSetShape(
/** /**
* Gets the shape of the trigger volume. * Gets the shape of the trigger volume.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The shape of the trigger volume. * @return The shape of the trigger volume.
*/ */
physicsshape_t entityTriggerGetShape( physicsshape_t entityTriggerGetShape(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -151,13 +141,11 @@ physicsshape_t entityTriggerGetShape(
* Sets the collision mask of the trigger volume. An entity's PHYSICS body * Sets the collision mask of the trigger volume. An entity's PHYSICS body
* is only detected if their masks share at least one set bit. * is only detected if their masks share at least one set bit.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param mask The new collision mask to set on the trigger volume. * @param mask The new collision mask to set on the trigger volume.
*/ */
void entityTriggerSetCollideMask( void entityTriggerSetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint32_t mask const uint32_t mask
@@ -166,13 +154,11 @@ void entityTriggerSetCollideMask(
/** /**
* Gets the collision mask of the trigger volume. * Gets the collision mask of the trigger volume.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The collision mask of the trigger volume. * @return The collision mask of the trigger volume.
*/ */
uint32_t entityTriggerGetCollideMask( uint32_t entityTriggerGetCollideMask(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -180,13 +166,11 @@ uint32_t entityTriggerGetCollideMask(
/** /**
* Gets the number of entities currently overlapping this trigger. * Gets the number of entities currently overlapping this trigger.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @return The number of currently tracked occupants. * @return The number of currently tracked occupants.
*/ */
uint8_t entityTriggerGetOccupantCount( uint8_t entityTriggerGetOccupantCount(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId const componentid_t componentId
); );
@@ -195,7 +179,6 @@ uint8_t entityTriggerGetOccupantCount(
* Gets the entity ID of the occupant at the given index, in [0, * Gets the entity ID of the occupant at the given index, in [0,
* entityTriggerGetOccupantCount()). Order is not stable across steps. * entityTriggerGetOccupantCount()). Order is not stable across steps.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param index The occupant index. * @param index The occupant index.
@@ -203,7 +186,6 @@ uint8_t entityTriggerGetOccupantCount(
* of range. * of range.
*/ */
entityid_t entityTriggerGetOccupantEntityId( entityid_t entityTriggerGetOccupantEntityId(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const uint8_t index const uint8_t index
@@ -212,14 +194,12 @@ entityid_t entityTriggerGetOccupantEntityId(
/** /**
* Checks whether a specific entity is currently overlapping this trigger. * Checks whether a specific entity is currently overlapping this trigger.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param otherEntityId The entity ID to check for. * @param otherEntityId The entity ID to check for.
* @return True if otherEntityId is a currently tracked occupant. * @return True if otherEntityId is a currently tracked occupant.
*/ */
bool_t entityTriggerIsOccupyingEntity( bool_t entityTriggerIsOccupyingEntity(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const entityid_t otherEntityId const entityid_t otherEntityId
@@ -9,13 +9,12 @@
#include "assert/assert.h" #include "assert/assert.h"
void entityTriggerOnEnterAdd( void entityTriggerOnEnterAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
void *user void *user
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
assertTrue( assertTrue(
trig->onEnterCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX, trig->onEnterCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX,
"Trigger onEnter callback slots full" "Trigger onEnter callback slots full"
@@ -26,12 +25,11 @@ void entityTriggerOnEnterAdd(
} }
void entityTriggerOnEnterRemove( void entityTriggerOnEnterRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
for(uint8_t i = 0; i < trig->onEnterCount; i++) { for(uint8_t i = 0; i < trig->onEnterCount; i++) {
if(trig->onEnter[i] != callback) continue; if(trig->onEnter[i] != callback) continue;
trig->onEnterCount--; trig->onEnterCount--;
@@ -44,13 +42,12 @@ void entityTriggerOnEnterRemove(
} }
void entityTriggerOnActiveAdd( void entityTriggerOnActiveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
void *user void *user
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
assertTrue( assertTrue(
trig->onActiveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX, trig->onActiveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX,
"Trigger onActive callback slots full" "Trigger onActive callback slots full"
@@ -61,12 +58,11 @@ void entityTriggerOnActiveAdd(
} }
void entityTriggerOnActiveRemove( void entityTriggerOnActiveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
for(uint8_t i = 0; i < trig->onActiveCount; i++) { for(uint8_t i = 0; i < trig->onActiveCount; i++) {
if(trig->onActive[i] != callback) continue; if(trig->onActive[i] != callback) continue;
trig->onActiveCount--; trig->onActiveCount--;
@@ -79,13 +75,12 @@ void entityTriggerOnActiveRemove(
} }
void entityTriggerOnMoveAdd( void entityTriggerOnMoveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
void *user void *user
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
assertTrue( assertTrue(
trig->onMoveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX, trig->onMoveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX,
"Trigger onMove callback slots full" "Trigger onMove callback slots full"
@@ -96,12 +91,11 @@ void entityTriggerOnMoveAdd(
} }
void entityTriggerOnMoveRemove( void entityTriggerOnMoveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
for(uint8_t i = 0; i < trig->onMoveCount; i++) { for(uint8_t i = 0; i < trig->onMoveCount; i++) {
if(trig->onMove[i] != callback) continue; if(trig->onMove[i] != callback) continue;
trig->onMoveCount--; trig->onMoveCount--;
@@ -114,13 +108,12 @@ void entityTriggerOnMoveRemove(
} }
void entityTriggerOnLeaveAdd( void entityTriggerOnLeaveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
void *user void *user
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
assertTrue( assertTrue(
trig->onLeaveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX, trig->onLeaveCount < ENTITY_TRIGGER_CALLBACK_COUNT_MAX,
"Trigger onLeave callback slots full" "Trigger onLeave callback slots full"
@@ -131,12 +124,11 @@ void entityTriggerOnLeaveAdd(
} }
void entityTriggerOnLeaveRemove( void entityTriggerOnLeaveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
) { ) {
entitytrigger_t *trig = entityTriggerGet(mgr, entityId, componentId); entitytrigger_t *trig = entityTriggerGet(entityId, componentId);
for(uint8_t i = 0; i < trig->onLeaveCount; i++) { for(uint8_t i = 0; i < trig->onLeaveCount; i++) {
if(trig->onLeave[i] != callback) continue; if(trig->onLeave[i] != callback) continue;
trig->onLeaveCount--; trig->onLeaveCount--;
@@ -149,72 +141,68 @@ void entityTriggerOnLeaveRemove(
} }
void entityTriggerFireEnter( void entityTriggerFireEnter(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
const componentid_t otherComponentId const componentid_t otherComponentId
) { ) {
entitytrigger_t *trig = entityTriggerGet( entitytrigger_t *trig = entityTriggerGet(
mgr, triggerEntityId, triggerComponentId triggerEntityId, triggerComponentId
); );
for(uint8_t i = 0; i < trig->onEnterCount; i++) { for(uint8_t i = 0; i < trig->onEnterCount; i++) {
trig->onEnter[i]( trig->onEnter[i](
mgr, triggerEntityId, triggerComponentId, triggerEntityId, triggerComponentId,
otherEntityId, otherComponentId, trig->onEnterUser[i] otherEntityId, otherComponentId, trig->onEnterUser[i]
); );
} }
} }
void entityTriggerFireActive( void entityTriggerFireActive(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
const componentid_t otherComponentId const componentid_t otherComponentId
) { ) {
entitytrigger_t *trig = entityTriggerGet( entitytrigger_t *trig = entityTriggerGet(
mgr, triggerEntityId, triggerComponentId triggerEntityId, triggerComponentId
); );
for(uint8_t i = 0; i < trig->onActiveCount; i++) { for(uint8_t i = 0; i < trig->onActiveCount; i++) {
trig->onActive[i]( trig->onActive[i](
mgr, triggerEntityId, triggerComponentId, triggerEntityId, triggerComponentId,
otherEntityId, otherComponentId, trig->onActiveUser[i] otherEntityId, otherComponentId, trig->onActiveUser[i]
); );
} }
} }
void entityTriggerFireMove( void entityTriggerFireMove(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
const componentid_t otherComponentId const componentid_t otherComponentId
) { ) {
entitytrigger_t *trig = entityTriggerGet( entitytrigger_t *trig = entityTriggerGet(
mgr, triggerEntityId, triggerComponentId triggerEntityId, triggerComponentId
); );
for(uint8_t i = 0; i < trig->onMoveCount; i++) { for(uint8_t i = 0; i < trig->onMoveCount; i++) {
trig->onMove[i]( trig->onMove[i](
mgr, triggerEntityId, triggerComponentId, triggerEntityId, triggerComponentId,
otherEntityId, otherComponentId, trig->onMoveUser[i] otherEntityId, otherComponentId, trig->onMoveUser[i]
); );
} }
} }
void entityTriggerFireLeave( void entityTriggerFireLeave(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
const componentid_t otherComponentId const componentid_t otherComponentId
) { ) {
entitytrigger_t *trig = entityTriggerGet( entitytrigger_t *trig = entityTriggerGet(
mgr, triggerEntityId, triggerComponentId triggerEntityId, triggerComponentId
); );
for(uint8_t i = 0; i < trig->onLeaveCount; i++) { for(uint8_t i = 0; i < trig->onLeaveCount; i++) {
trig->onLeave[i]( trig->onLeave[i](
mgr, triggerEntityId, triggerComponentId, triggerEntityId, triggerComponentId,
otherEntityId, otherComponentId, trig->onLeaveUser[i] otherEntityId, otherComponentId, trig->onLeaveUser[i]
); );
} }
@@ -12,14 +12,12 @@
* Subscribes a callback to a trigger's onEnter event, fired the step an * Subscribes a callback to a trigger's onEnter event, fired the step an
* entity begins overlapping the trigger volume. * entity begins overlapping the trigger volume.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback to invoke. * @param callback The callback to invoke.
* @param user Arbitrary pointer forwarded to the callback unchanged. * @param user Arbitrary pointer forwarded to the callback unchanged.
*/ */
void entityTriggerOnEnterAdd( void entityTriggerOnEnterAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
@@ -30,13 +28,11 @@ void entityTriggerOnEnterAdd(
* Unsubscribes a previously added onEnter callback. No-op if not * Unsubscribes a previously added onEnter callback. No-op if not
* currently subscribed. * currently subscribed.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback that was passed to entityTriggerOnEnterAdd(). * @param callback The callback that was passed to entityTriggerOnEnterAdd().
*/ */
void entityTriggerOnEnterRemove( void entityTriggerOnEnterRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
@@ -47,14 +43,12 @@ void entityTriggerOnEnterRemove(
* entity continues overlapping the trigger volume (starting the step * entity continues overlapping the trigger volume (starting the step
* after onEnter fired). * after onEnter fired).
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback to invoke. * @param callback The callback to invoke.
* @param user Arbitrary pointer forwarded to the callback unchanged. * @param user Arbitrary pointer forwarded to the callback unchanged.
*/ */
void entityTriggerOnActiveAdd( void entityTriggerOnActiveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
@@ -65,13 +59,11 @@ void entityTriggerOnActiveAdd(
* Unsubscribes a previously added onActive callback. No-op if not * Unsubscribes a previously added onActive callback. No-op if not
* currently subscribed. * currently subscribed.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback that was passed to entityTriggerOnActiveAdd(). * @param callback The callback that was passed to entityTriggerOnActiveAdd().
*/ */
void entityTriggerOnActiveRemove( void entityTriggerOnActiveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
@@ -82,14 +74,12 @@ void entityTriggerOnActiveRemove(
* onActive on any step where the overlapping entity's position changed * onActive on any step where the overlapping entity's position changed
* since the previous step. * since the previous step.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback to invoke. * @param callback The callback to invoke.
* @param user Arbitrary pointer forwarded to the callback unchanged. * @param user Arbitrary pointer forwarded to the callback unchanged.
*/ */
void entityTriggerOnMoveAdd( void entityTriggerOnMoveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
@@ -100,13 +90,11 @@ void entityTriggerOnMoveAdd(
* Unsubscribes a previously added onMove callback. No-op if not currently * Unsubscribes a previously added onMove callback. No-op if not currently
* subscribed. * subscribed.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback that was passed to entityTriggerOnMoveAdd(). * @param callback The callback that was passed to entityTriggerOnMoveAdd().
*/ */
void entityTriggerOnMoveRemove( void entityTriggerOnMoveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
@@ -116,14 +104,12 @@ void entityTriggerOnMoveRemove(
* Subscribes a callback to a trigger's onLeave event, fired the step an * Subscribes a callback to a trigger's onLeave event, fired the step an
* entity stops overlapping the trigger volume. * entity stops overlapping the trigger volume.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback to invoke. * @param callback The callback to invoke.
* @param user Arbitrary pointer forwarded to the callback unchanged. * @param user Arbitrary pointer forwarded to the callback unchanged.
*/ */
void entityTriggerOnLeaveAdd( void entityTriggerOnLeaveAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback, const triggercallback_t callback,
@@ -134,13 +120,11 @@ void entityTriggerOnLeaveAdd(
* Unsubscribes a previously added onLeave callback. No-op if not * Unsubscribes a previously added onLeave callback. No-op if not
* currently subscribed. * currently subscribed.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity ID. * @param entityId The entity ID.
* @param componentId The component ID. * @param componentId The component ID.
* @param callback The callback that was passed to entityTriggerOnLeaveAdd(). * @param callback The callback that was passed to entityTriggerOnLeaveAdd().
*/ */
void entityTriggerOnLeaveRemove( void entityTriggerOnLeaveRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
const triggercallback_t callback const triggercallback_t callback
@@ -150,14 +134,12 @@ void entityTriggerOnLeaveRemove(
* Internal. Invokes every subscribed onEnter callback for a trigger. * Internal. Invokes every subscribed onEnter callback for a trigger.
* Called by triggerSystemStep() when an entity begins overlapping. * Called by triggerSystemStep() when an entity begins overlapping.
* *
* @param mgr The entity manager that owns both entities.
* @param triggerEntityId The entity ID of the trigger volume. * @param triggerEntityId The entity ID of the trigger volume.
* @param triggerComponentId The TRIGGER component ID. * @param triggerComponentId The TRIGGER component ID.
* @param otherEntityId The entity ID that entered the trigger volume. * @param otherEntityId The entity ID that entered the trigger volume.
* @param otherComponentId The other entity's POSITION component ID. * @param otherComponentId The other entity's POSITION component ID.
*/ */
void entityTriggerFireEnter( void entityTriggerFireEnter(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
@@ -168,14 +150,12 @@ void entityTriggerFireEnter(
* Internal. Invokes every subscribed onActive callback for a trigger. * Internal. Invokes every subscribed onActive callback for a trigger.
* Called by triggerSystemStep() for every entity still overlapping. * Called by triggerSystemStep() for every entity still overlapping.
* *
* @param mgr The entity manager that owns both entities.
* @param triggerEntityId The entity ID of the trigger volume. * @param triggerEntityId The entity ID of the trigger volume.
* @param triggerComponentId The TRIGGER component ID. * @param triggerComponentId The TRIGGER component ID.
* @param otherEntityId The entity ID still inside the trigger volume. * @param otherEntityId The entity ID still inside the trigger volume.
* @param otherComponentId The other entity's POSITION component ID. * @param otherComponentId The other entity's POSITION component ID.
*/ */
void entityTriggerFireActive( void entityTriggerFireActive(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
@@ -187,14 +167,12 @@ void entityTriggerFireActive(
* Called by triggerSystemStep() when an overlapping entity's position * Called by triggerSystemStep() when an overlapping entity's position
* changed since the previous step. * changed since the previous step.
* *
* @param mgr The entity manager that owns both entities.
* @param triggerEntityId The entity ID of the trigger volume. * @param triggerEntityId The entity ID of the trigger volume.
* @param triggerComponentId The TRIGGER component ID. * @param triggerComponentId The TRIGGER component ID.
* @param otherEntityId The entity ID that moved within the trigger volume. * @param otherEntityId The entity ID that moved within the trigger volume.
* @param otherComponentId The other entity's POSITION component ID. * @param otherComponentId The other entity's POSITION component ID.
*/ */
void entityTriggerFireMove( void entityTriggerFireMove(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
@@ -205,14 +183,12 @@ void entityTriggerFireMove(
* Internal. Invokes every subscribed onLeave callback for a trigger. * Internal. Invokes every subscribed onLeave callback for a trigger.
* Called by triggerSystemStep() when an entity stops overlapping. * Called by triggerSystemStep() when an entity stops overlapping.
* *
* @param mgr The entity manager that owns both entities.
* @param triggerEntityId The entity ID of the trigger volume. * @param triggerEntityId The entity ID of the trigger volume.
* @param triggerComponentId The TRIGGER component ID. * @param triggerComponentId The TRIGGER component ID.
* @param otherEntityId The entity ID that left the trigger volume. * @param otherEntityId The entity ID that left the trigger volume.
* @param otherComponentId The other entity's POSITION component ID. * @param otherComponentId The other entity's POSITION component ID.
*/ */
void entityTriggerFireLeave( void entityTriggerFireLeave(
entitymanager_t *mgr,
const entityid_t triggerEntityId, const entityid_t triggerEntityId,
const componentid_t triggerComponentId, const componentid_t triggerComponentId,
const entityid_t otherEntityId, const entityid_t otherEntityId,
+80 -40
View File
@@ -5,14 +5,63 @@
* https://opensource.org/licenses/MIT * https://opensource.org/licenses/MIT
*/ */
#include "entitymanager.h" #include "entity.h"
#include "component/display/entityposition.h" #include "component/display/entityposition.h"
#include "util/memory.h" #include "util/memory.h"
#include "util/string.h" #include "util/string.h"
#include "assert/assert.h" #include "assert/assert.h"
#include "console/console.h"
void entityInit(entitymanager_t *mgr, const entityid_t entityId) { entity_t ENTITIES[ENTITY_COUNT_MAX];
entity_t *ent = &mgr->entities[entityId]; component_t COMPONENTS[ENTITY_COUNT_MAX * ENTITY_COMPONENT_COUNT_MAX];
componentid_t ENTITIES_WITH_COMPONENT[COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX];
void entityManagerInit(void) {
memoryZero(ENTITIES, sizeof(ENTITIES));
memoryZero(COMPONENTS, sizeof(COMPONENTS));
memorySet(
ENTITIES_WITH_COMPONENT, COMPONENT_ID_INVALID,
sizeof(ENTITIES_WITH_COMPONENT)
);
size_t totalSize =
sizeof(ENTITIES) + sizeof(COMPONENTS) + sizeof(ENTITIES_WITH_COMPONENT);
consolePrint(
"Entity manager size: %zu bytes (%.2f KB)",
totalSize,
totalSize / 1024.0f
);
}
entityid_t entityManagerAdd(void) {
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if((ENTITIES[i].state & ENTITY_STATE_ACTIVE) != 0) continue;
entityInit(i);
return i;
}
assertUnreachable("No more entity IDs available");
return ENTITY_ID_INVALID;
}
void entityManagerUpdate(void) {
entityid_t i = 0;
while(i < ENTITY_COUNT_MAX) {
if((ENTITIES[i].state & ENTITY_STATE_ACTIVE) != 0) {
entityUpdate(i);
}
i++;
}
}
void entityManagerDispose(void) {
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if((ENTITIES[i].state & ENTITY_STATE_ACTIVE) == 0) continue;
entityDispose(i);
}
}
void entityInit(const entityid_t entityId) {
entity_t *ent = &ENTITIES[entityId];
memoryZero(ent, sizeof(entity_t)); memoryZero(ent, sizeof(entity_t));
@@ -22,7 +71,7 @@ void entityInit(entitymanager_t *mgr, const entityid_t entityId) {
compType < COMPONENT_TYPE_COUNT; compType < COMPONENT_TYPE_COUNT;
compType++ compType++
) { ) {
mgr->entitiesWithComponent[ ENTITIES_WITH_COMPONENT[
compType * ENTITY_COUNT_MAX + entityId compType * ENTITY_COUNT_MAX + entityId
] = COMPONENT_ID_INVALID; ] = COMPONENT_ID_INVALID;
} }
@@ -31,7 +80,6 @@ void entityInit(entitymanager_t *mgr, const entityid_t entityId) {
} }
componentid_t entityAddComponent( componentid_t entityAddComponent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componenttype_t type const componenttype_t type
) { ) {
@@ -39,15 +87,15 @@ componentid_t entityAddComponent(
for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) { for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) {
compInd = componentGetIndex(entityId, i); compInd = componentGetIndex(entityId, i);
if(mgr->components[compInd].type != COMPONENT_TYPE_NULL) { if(COMPONENTS[compInd].type != COMPONENT_TYPE_NULL) {
assertTrue( assertTrue(
mgr->components[compInd].type != type, COMPONENTS[compInd].type != type,
"Entity already has component of this type" "Entity already has component of this type"
); );
continue; continue;
} }
componentInit(mgr, entityId, i, type); componentInit(entityId, i, type);
mgr->entitiesWithComponent[ ENTITIES_WITH_COMPONENT[
type * ENTITY_COUNT_MAX + entityId type * ENTITY_COUNT_MAX + entityId
] = i; ] = i;
return i; return i;
@@ -58,98 +106,93 @@ componentid_t entityAddComponent(
} }
componentid_t entityGetComponent( componentid_t entityGetComponent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componenttype_t type const componenttype_t type
) { ) {
componentid_t compId = mgr->entitiesWithComponent[ componentid_t compId = ENTITIES_WITH_COMPONENT[
type * ENTITY_COUNT_MAX + entityId type * ENTITY_COUNT_MAX + entityId
]; ];
if(compId == COMPONENT_ID_INVALID) return compId; if(compId == COMPONENT_ID_INVALID) return compId;
assertTrue( assertTrue(
mgr->components[componentGetIndex(entityId, compId)].type == type, COMPONENTS[componentGetIndex(entityId, compId)].type == type,
"Component type mismatch" "Component type mismatch"
); );
return compId; return compId;
} }
void entitySetName( void entitySetName(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const char_t *name const char_t *name
) { ) {
stringCopy(mgr->entities[entityId].name, name, ENTITY_NAME_MAX); stringCopy(ENTITIES[entityId].name, name, ENTITY_NAME_MAX);
} }
const char_t *entityGetName( const char_t *entityGetName(
entitymanager_t *mgr,
const entityid_t entityId const entityid_t entityId
) { ) {
return mgr->entities[entityId].name; return ENTITIES[entityId].name;
} }
entityid_t entityFindByName( entityid_t entityFindByName(
entitymanager_t *mgr,
const char_t *name const char_t *name
) { ) {
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) { for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if(!(mgr->entities[i].state & ENTITY_STATE_ACTIVE)) continue; if(!(ENTITIES[i].state & ENTITY_STATE_ACTIVE)) continue;
if(stringEquals(mgr->entities[i].name, name)) return i; if(stringEquals(ENTITIES[i].name, name)) return i;
} }
return ENTITY_ID_INVALID; return ENTITY_ID_INVALID;
} }
void entityDisposeDeep(entitymanager_t *mgr, const entityid_t entityId) { void entityDisposeDeep(const entityid_t entityId) {
componentid_t posComp = entityGetComponent( componentid_t posComp = entityGetComponent(
mgr, entityId, COMPONENT_TYPE_POSITION entityId, COMPONENT_TYPE_POSITION
); );
if(posComp != COMPONENT_ID_INVALID) { if(posComp != COMPONENT_ID_INVALID) {
entityPositionDisposeDeep(mgr, entityId, posComp); entityPositionDisposeDeep(entityId, posComp);
} else { } else {
entityDispose(mgr, entityId); entityDispose(entityId);
} }
} }
void entityUpdate(entitymanager_t *mgr, const entityid_t entityId) { void entityUpdate(const entityid_t entityId) {
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
for(uint8_t i = 0; i < ent->updateCount; i++) { for(uint8_t i = 0; i < ent->updateCount; i++) {
ent->onUpdate[i]( ent->onUpdate[i](
mgr, entityId, ent->updateComponentId[i], ent->updateUser[i] entityId, ent->updateComponentId[i], ent->updateUser[i]
); );
} }
} }
void entityDispose(entitymanager_t *mgr, const entityid_t entityId) { void entityDispose(const entityid_t entityId) {
componentindex_t compInd; componentindex_t compInd;
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
for(uint8_t i = 0; i < ent->disposeCount; i++) { for(uint8_t i = 0; i < ent->disposeCount; i++) {
ent->onDispose[i]( ent->onDispose[i](
mgr, entityId, ent->disposeComponentId[i], ent->disposeUser[i] entityId, ent->disposeComponentId[i], ent->disposeUser[i]
); );
} }
for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) { for(componentid_t i = 0; i < ENTITY_COMPONENT_COUNT_MAX; i++) {
compInd = componentGetIndex(entityId, i); compInd = componentGetIndex(entityId, i);
componenttype_t type = mgr->components[compInd].type; componenttype_t type = COMPONENTS[compInd].type;
if(type == COMPONENT_TYPE_NULL) continue; if(type == COMPONENT_TYPE_NULL) continue;
mgr->entitiesWithComponent[ ENTITIES_WITH_COMPONENT[
type * ENTITY_COUNT_MAX + entityId type * ENTITY_COUNT_MAX + entityId
] = COMPONENT_ID_INVALID; ] = COMPONENT_ID_INVALID;
componentDispose(mgr, entityId, i); componentDispose(entityId, i);
} }
ent->state = 0; ent->state = 0;
} }
void entityUpdateAdd( void entityUpdateAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback, const entitycallback_t callback,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
) { ) {
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
assertTrue( assertTrue(
ent->updateCount < ENTITY_UPDATE_CALLBACK_COUNT_MAX, ent->updateCount < ENTITY_UPDATE_CALLBACK_COUNT_MAX,
"Entity update callback slots full" "Entity update callback slots full"
@@ -161,11 +204,10 @@ void entityUpdateAdd(
} }
void entityUpdateRemove( void entityUpdateRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback const entitycallback_t callback
) { ) {
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
for(uint8_t i = 0; i < ent->updateCount; i++) { for(uint8_t i = 0; i < ent->updateCount; i++) {
if(ent->onUpdate[i] != callback) continue; if(ent->onUpdate[i] != callback) continue;
ent->updateCount--; ent->updateCount--;
@@ -179,13 +221,12 @@ void entityUpdateRemove(
} }
void entityDisposeAdd( void entityDisposeAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback, const entitycallback_t callback,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
) { ) {
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
assertTrue( assertTrue(
ent->disposeCount < ENTITY_DISPOSE_CALLBACK_COUNT_MAX, ent->disposeCount < ENTITY_DISPOSE_CALLBACK_COUNT_MAX,
"Entity dispose callback slots full" "Entity dispose callback slots full"
@@ -197,11 +238,10 @@ void entityDisposeAdd(
} }
void entityDisposeRemove( void entityDisposeRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback const entitycallback_t callback
) { ) {
entity_t *ent = &mgr->entities[entityId]; entity_t *ent = &ENTITIES[entityId];
for(uint8_t i = 0; i < ent->disposeCount; i++) { for(uint8_t i = 0; i < ent->disposeCount; i++) {
if(ent->onDispose[i] != callback) continue; if(ent->onDispose[i] != callback) continue;
ent->disposeCount--; ent->disposeCount--;
+32 -27
View File
@@ -16,7 +16,6 @@
#define ENTITY_NAME_MAX 32 #define ENTITY_NAME_MAX 32
typedef void (*entitycallback_t)( typedef void (*entitycallback_t)(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componentid_t componentId, const componentid_t componentId,
void *user void *user
@@ -35,24 +34,49 @@ typedef struct {
void *disposeUser[ENTITY_DISPOSE_CALLBACK_COUNT_MAX]; void *disposeUser[ENTITY_DISPOSE_CALLBACK_COUNT_MAX];
} entity_t; } entity_t;
extern entity_t ENTITIES[ENTITY_COUNT_MAX];
extern component_t COMPONENTS[ENTITY_COUNT_MAX * ENTITY_COMPONENT_COUNT_MAX];
extern componentid_t ENTITIES_WITH_COMPONENT[COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX];
/**
* Initializes the entity system, marking all entities and components as
* unused.
*/
void entityManagerInit(void);
/**
* Adds / Reserves a new entity ID.
*
* @return The new entity ID.
*/
entityid_t entityManagerAdd(void);
/**
* Updates all active entities.
*/
void entityManagerUpdate(void);
/**
* Disposes of the entity system, in turn freeing all entities and
* components.
*/
void entityManagerDispose(void);
/** /**
* Initializes an entity with the given ID. * Initializes an entity with the given ID.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to initialize. * @param entityId The ID of the entity to initialize.
*/ */
void entityInit(entitymanager_t *mgr, const entityid_t entityId); void entityInit(const entityid_t entityId);
/** /**
* Adds a component of the given type to the entity with the given ID. * Adds a component of the given type to the entity with the given ID.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to add the component to. * @param entityId The ID of the entity to add the component to.
* @param type The type of the component to add. * @param type The type of the component to add.
* @return The ID of the entity with component. * @return The ID of the entity with component.
*/ */
componentid_t entityAddComponent( componentid_t entityAddComponent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componenttype_t type const componenttype_t type
); );
@@ -61,13 +85,11 @@ componentid_t entityAddComponent(
* Gets the ID of the component of the given type on the entity with the * Gets the ID of the component of the given type on the entity with the
* given ID, or COMPONENT_ID_INVALID if the entity lacks the component. * given ID, or COMPONENT_ID_INVALID if the entity lacks the component.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to get the component from. * @param entityId The ID of the entity to get the component from.
* @param type The type of the component to get. * @param type The type of the component to get.
* @return The ID of the component. * @return The ID of the component.
*/ */
componentid_t entityGetComponent( componentid_t entityGetComponent(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const componenttype_t type const componenttype_t type
); );
@@ -78,13 +100,11 @@ componentid_t entityGetComponent(
* entity referenceable by name, e.g. as a parent via * entity referenceable by name, e.g. as a parent via
* entityPositionSetParent(). * entityPositionSetParent().
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to name. * @param entityId The ID of the entity to name.
* @param name The name to give the entity. Must be shorter than * @param name The name to give the entity. Must be shorter than
* ENTITY_NAME_MAX. * ENTITY_NAME_MAX.
*/ */
void entitySetName( void entitySetName(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const char_t *name const char_t *name
); );
@@ -92,65 +112,56 @@ void entitySetName(
/** /**
* Gets an entity's name, or an empty string if it has none. * Gets an entity's name, or an empty string if it has none.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to get the name of. * @param entityId The ID of the entity to get the name of.
* @return The entity's name. * @return The entity's name.
*/ */
const char_t *entityGetName( const char_t *entityGetName(
entitymanager_t *mgr,
const entityid_t entityId const entityid_t entityId
); );
/** /**
* Finds the first active entity with the given name. * Finds the first active entity with the given name.
* *
* @param mgr The entity manager to search.
* @param name The name to search for. * @param name The name to search for.
* @return The entity ID, or ENTITY_ID_INVALID if no active entity matches. * @return The entity ID, or ENTITY_ID_INVALID if no active entity matches.
*/ */
entityid_t entityFindByName( entityid_t entityFindByName(
entitymanager_t *mgr,
const char_t *name const char_t *name
); );
/** /**
* Runs all registered update callbacks for the entity. * Runs all registered update callbacks for the entity.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to update. * @param entityId The ID of the entity to update.
*/ */
void entityUpdate(entitymanager_t *mgr, const entityid_t entityId); void entityUpdate(const entityid_t entityId);
/** /**
* Disposes of an entity with the given ID. Fires all dispose callbacks * Disposes of an entity with the given ID. Fires all dispose callbacks
* before cleaning up components and state. * before cleaning up components and state.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The ID of the entity to dispose of. * @param entityId The ID of the entity to dispose of.
*/ */
void entityDispose(entitymanager_t *mgr, const entityid_t entityId); void entityDispose(const entityid_t entityId);
/** /**
* Disposes of an entity and all of its position-component descendants * Disposes of an entity and all of its position-component descendants
* recursively. If the entity has no position component, behaves like * recursively. If the entity has no position component, behaves like
* entityDispose. * entityDispose.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The root entity ID. * @param entityId The root entity ID.
*/ */
void entityDisposeDeep(entitymanager_t *mgr, const entityid_t entityId); void entityDisposeDeep(const entityid_t entityId);
/** /**
* Registers an update callback, invoked each time entityUpdate is called. * Registers an update callback, invoked each time entityUpdate is called.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to register on. * @param entityId The entity to register on.
* @param callback The function to call. * @param callback The function to call.
* @param componentId The component ID passed back to the callback. * @param componentId The component ID passed back to the callback.
* @param user Userdata passed back to the callback. * @param user Userdata passed back to the callback.
*/ */
void entityUpdateAdd( void entityUpdateAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback, const entitycallback_t callback,
const componentid_t componentId, const componentid_t componentId,
@@ -160,12 +171,10 @@ void entityUpdateAdd(
/** /**
* Removes a previously registered update callback. * Removes a previously registered update callback.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to remove from. * @param entityId The entity to remove from.
* @param callback The function to remove. * @param callback The function to remove.
*/ */
void entityUpdateRemove( void entityUpdateRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback const entitycallback_t callback
); );
@@ -174,14 +183,12 @@ void entityUpdateRemove(
* Registers a dispose callback, invoked at the start of entityDispose * Registers a dispose callback, invoked at the start of entityDispose
* before any component or state cleanup. * before any component or state cleanup.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to register on. * @param entityId The entity to register on.
* @param callback The function to call. * @param callback The function to call.
* @param componentId The component ID passed back to the callback. * @param componentId The component ID passed back to the callback.
* @param user Userdata passed back to the callback. * @param user Userdata passed back to the callback.
*/ */
void entityDisposeAdd( void entityDisposeAdd(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback, const entitycallback_t callback,
const componentid_t componentId, const componentid_t componentId,
@@ -191,12 +198,10 @@ void entityDisposeAdd(
/** /**
* Removes a previously registered dispose callback. * Removes a previously registered dispose callback.
* *
* @param mgr The entity manager that owns the entity.
* @param entityId The entity to remove from. * @param entityId The entity to remove from.
* @param callback The function to remove. * @param callback The function to remove.
*/ */
void entityDisposeRemove( void entityDisposeRemove(
entitymanager_t *mgr,
const entityid_t entityId, const entityid_t entityId,
const entitycallback_t callback const entitycallback_t callback
); );
-5
View File
@@ -17,8 +17,3 @@
typedef uint8_t entityid_t; typedef uint8_t entityid_t;
typedef uint8_t componentid_t; typedef uint8_t componentid_t;
typedef uint16_t componentindex_t; typedef uint16_t componentindex_t;
// Forward declared here (rather than in component.h) so every entity/
// component header can reference entitymanager_t* regardless of include
// order, without needing a full entitymanager.h include.
typedef struct entitymanager_t entitymanager_t;
-56
View File
@@ -1,56 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "entitymanager.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "console/console.h"
void entityManagerInit(entitymanager_t *mgr) {
assertNotNull(mgr, "Entity manager cannot be null");
memoryZero(mgr, sizeof(entitymanager_t));
memorySet(
mgr->entitiesWithComponent, COMPONENT_ID_INVALID,
sizeof(componentid_t) * COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX
);
consolePrint(
"Entity manager size: %zu bytes (%.2f KB)",
sizeof(entitymanager_t),
sizeof(entitymanager_t) / 1024.0f
);
}
entityid_t entityManagerAdd(entitymanager_t *mgr) {
assertNotNull(mgr, "Entity manager cannot be null");
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if((mgr->entities[i].state & ENTITY_STATE_ACTIVE) != 0) continue;
entityInit(mgr, i);
return i;
}
assertUnreachable("No more entity IDs available");
return ENTITY_ID_INVALID;
}
void entityManagerUpdate(entitymanager_t *mgr) {
assertNotNull(mgr, "Entity manager cannot be null");
entityid_t i = 0;
while(i < ENTITY_COUNT_MAX) {
if((mgr->entities[i].state & ENTITY_STATE_ACTIVE) != 0) {
entityUpdate(mgr, i);
}
i++;
}
}
void entityManagerDispose(entitymanager_t *mgr) {
assertNotNull(mgr, "Entity manager cannot be null");
for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) {
if((mgr->entities[i].state & ENTITY_STATE_ACTIVE) == 0) continue;
entityDispose(mgr, i);
}
}
-46
View File
@@ -1,46 +0,0 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "entity.h"
typedef struct entitymanager_t {
entity_t entities[ENTITY_COUNT_MAX];
component_t components[ENTITY_COUNT_MAX * ENTITY_COMPONENT_COUNT_MAX];
componentid_t entitiesWithComponent[COMPONENT_TYPE_COUNT * ENTITY_COUNT_MAX];
} entitymanager_t;
/**
* Initializes an entity manager, marking all entities and components as
* unused.
*
* @param mgr The entity manager to initialize.
*/
void entityManagerInit(entitymanager_t *mgr);
/**
* Adds / Reserves a new entity ID in the given manager.
*
* @param mgr The entity manager to allocate the entity in.
* @return The new entity ID.
*/
entityid_t entityManagerAdd(entitymanager_t *mgr);
/**
* Updates all active entities in the given manager.
*
* @param mgr The entity manager to update.
*/
void entityManagerUpdate(entitymanager_t *mgr);
/**
* Disposes of the entity manager, in turn freeing all entities and
* components.
*
* @param mgr The entity manager to dispose.
*/
void entityManagerDispose(entitymanager_t *mgr);
+64
View File
@@ -0,0 +1,64 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "entityrender.h"
#include "component/display/entitycamera.h"
#include "component/display/entityposition.h"
#include "component/display/entityrenderable.h"
#include "display/shader/shaderunlit.h"
errorret_t entityRenderAll(void) {
entityid_t camEntity = entityCameraGetCurrent();
if(camEntity == ENTITY_ID_INVALID) errorOk();
componentid_t camComp = entityGetComponent(
camEntity, COMPONENT_TYPE_CAMERA
);
componentid_t camPosComp = entityGetComponent(
camEntity, COMPONENT_TYPE_POSITION
);
mat4 proj;
entityCameraGetProjection(camEntity, camComp, proj);
mat4 view;
glm_mat4_identity(view);
if(camPosComp != COMPONENT_ID_INVALID) {
mat4 camTransform;
entityPositionGetTransform(camEntity, camPosComp, camTransform);
// Position components always store world-space placement (eye ->
// world), regardless of how they were set (SetPosition/Rotation or
// LookAt) -- invert to get the view matrix (world -> eye).
glm_mat4_inv(camTransform, view);
}
errorChain(shaderBind(&SHADER_UNLIT));
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_PROJECTION, proj));
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_VIEW, view));
entityid_t renderEntities[ENTITY_COUNT_MAX];
componentid_t renderComponents[ENTITY_COUNT_MAX];
entityid_t renderCount = componentGetEntitiesWithComponent(
COMPONENT_TYPE_RENDERABLE, renderEntities, renderComponents
);
for(entityid_t i = 0; i < renderCount; i++) {
mat4 model;
componentid_t posComp = entityGetComponent(
renderEntities[i], COMPONENT_TYPE_POSITION
);
if(posComp == COMPONENT_ID_INVALID) {
glm_mat4_identity(model);
} else {
entityPositionGetTransform(renderEntities[i], posComp, model);
}
errorChain(shaderSetMatrix(&SHADER_UNLIT, SHADER_UNLIT_MODEL, model));
errorChain(entityRenderableDraw(renderEntities[i], renderComponents[i]));
}
errorOk();
}
+18
View File
@@ -0,0 +1,18 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "entity.h"
#include "error/error.h"
/**
* Renders every COMPONENT_TYPE_RENDERABLE entity, from the view of its
* first COMPONENT_TYPE_CAMERA entity. A no-op if there is no camera.
*
* @return Error state.
*/
errorret_t entityRenderAll(void);
+9
View File
@@ -0,0 +1,9 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
scene.c
)
+75
View File
@@ -0,0 +1,75 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scene.h"
#include "entity/entity.h"
#include "entity/entityrender.h"
#include "assert/assert.h"
#include "util/memory.h"
#include "time/time.h"
scenemanager_t SCENE_MANAGER;
errorret_t sceneInit(void) {
memoryZero(&SCENE_MANAGER, sizeof(scenemanager_t));
SCENE_MANAGER.active = SCENE_ID_INVALID;
errorOk();
}
sceneid_t sceneCreate(void) {
assertTrue(!SCENE_MANAGER.scene.used, "Scene is already in use");
SCENE_MANAGER.scene.used = true;
return 0;
}
void sceneDestroy(const sceneid_t id) {
assertTrue(id == 0, "Scene ID OOB");
if(!SCENE_MANAGER.scene.used) return;
SCENE_MANAGER.scene.used = false;
if(SCENE_MANAGER.active == id) SCENE_MANAGER.active = SCENE_ID_INVALID;
}
void sceneSetActive(const sceneid_t id) {
assertTrue(
id == SCENE_ID_INVALID || id == 0, "Scene ID OOB"
);
SCENE_MANAGER.active = id;
}
sceneid_t sceneGetActive(void) {
return SCENE_MANAGER.active;
}
errorret_t sceneUpdate(void) {
#if DUSK_TIME_DYNAMIC
if(TIME.dynamicUpdate) errorOk();
#endif
errorChain(sceneFixedUpdate());
errorOk();
}
errorret_t sceneFixedUpdate(void) {
if(SCENE_MANAGER.active == SCENE_ID_INVALID) errorOk();
entityManagerUpdate();
errorOk();
}
errorret_t sceneRender(void) {
if(SCENE_MANAGER.active != SCENE_ID_INVALID) {
errorChain(entityRenderAll());
}
errorOk();
}
errorret_t sceneDispose(void) {
sceneDestroy(0);
errorOk();
}
+106
View File
@@ -0,0 +1,106 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "scenebase.h"
#include "error/error.h"
typedef struct {
bool_t used;
} scene_t;
typedef struct {
scene_t scene;
sceneid_t active;
} scenemanager_t;
extern scenemanager_t SCENE_MANAGER;
/**
* Initialises the scene manager. No scenes are created or active until
* sceneCreate()/sceneSetActive() are called.
*
* @return An error if the init failed, or errorOk() if it succeeded.
*/
errorret_t sceneInit(void);
/**
* Creates the single scene. There is no per-scene entity pool -- entities
* are global (see entity.h) -- so this just marks the scene as used. Not
* made active automatically.
*
* @return The ID of the new scene (always 0).
*/
sceneid_t sceneCreate(void);
/**
* Destroys the scene. Does not touch the global entity arrays -- entity
* lifecycle is the engine's job (entityManagerInit()/entityManagerDispose()),
* not scoped to scene create/destroy. If the scene was active, no scene is
* active afterwards.
*
* @param id The ID of the scene to destroy. Must be 0.
*/
void sceneDestroy(const sceneid_t id);
/**
* Sets which scene is active. Only the active scene is ticked and rendered
* by sceneUpdate()/sceneRender(). Previously active scenes are left running
* in the background (paused, not disposed) until sceneDestroy() is called.
*
* @param id The ID of the scene to make active, or SCENE_ID_INVALID to make
* no scene active.
*/
void sceneSetActive(const sceneid_t id);
/**
* Gets the ID of the currently active scene.
*
* @return The active scene ID, or SCENE_ID_INVALID if none is active.
*/
sceneid_t sceneGetActive(void);
/**
* Called every frame (every call to engineUpdate). On a non-dynamic-time
* platform (DUSK_TIME_DYNAMIC undefined) every frame is itself a fixed
* timestep, so this calls sceneFixedUpdate() every time. On a
* dynamic-time platform, most calls are sub-steps still accumulating
* toward the next fixed timestep (TIME.dynamicUpdate is true) and do
* nothing here; this calls sceneFixedUpdate() only on the one call where
* TIME.dynamicUpdate is false, i.e. exactly once per fixed timestep.
*
* @return An error if the update failed, or errorOk() if it succeeded.
*/
errorret_t sceneUpdate(void);
/**
* Ticks the active scene's entities (update callbacks) by one fixed
* timestep (TIME.delta). Called by sceneUpdate() at the fixed-timestep
* cadence described there -- never once per rendered frame on a
* dynamic-time platform, so game logic stays frame-rate independent and
* deterministic. Does not step physics or triggers yet -- physicsworld_t/
* triggersystem_t haven't been ported from ac2 onto this branch, so a
* scene's entities can't collide or trigger each other until that lands.
*
* @return An error if the update failed, or errorOk() if it succeeded.
*/
errorret_t sceneFixedUpdate(void);
/**
* Renders the active scene's entities, from the view of its active
* camera (see entityRenderAll).
*
* @return An error if the render failed, or errorOk() if it succeeded.
*/
errorret_t sceneRender(void);
/**
* Destroys the scene.
*
* @return An error if the dispose failed, or errorOk() if it succeeded.
*/
errorret_t sceneDispose(void);
+13
View File
@@ -0,0 +1,13 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "dusk.h"
#define SCENE_ID_INVALID 0xFF
typedef uint8_t sceneid_t;
+3
View File
@@ -7,3 +7,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC PUBLIC
scriptnativeconsole.c scriptnativeconsole.c
) )
# Subdirs
add_subdirectory(entity)
@@ -0,0 +1,12 @@
# Copyright (c) 2026 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
target_sources(${DUSK_LIBRARY_TARGET_NAME}
PUBLIC
scriptnativeentity.c
scriptnativeentitymanager.c
scriptnativeentityposition.c
scriptnativeentityrenderable.c
)
@@ -0,0 +1,126 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptnativeentity.h"
#include "entity/entity.h"
#include "util/memory.h"
#include "assert/assert.h"
SCRIPT_NATIVE(scriptNativeEntityAddComponent) {
entityid_t entityId;
componenttype_t type;
componentid_t componentId;
scriptArgCount(runtime, argc, 2, 2);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
type = (componenttype_t)scriptArgInteger(runtime, args, argc, 1);
componentId = entityAddComponent(entityId, type);
return scriptNumber((float)componentId);
}
SCRIPT_NATIVE(scriptNativeEntityGetComponent) {
entityid_t entityId;
componenttype_t type;
componentid_t componentId;
scriptArgCount(runtime, argc, 2, 2);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
type = (componenttype_t)scriptArgInteger(runtime, args, argc, 1);
componentId = entityGetComponent(entityId, type);
return scriptNumber((float)componentId);
}
SCRIPT_NATIVE(scriptNativeEntitySetName) {
entityid_t entityId;
scriptstring_t *name;
char_t buffer[ENTITY_NAME_MAX];
uint16_t length;
scriptArgCount(runtime, argc, 2, 2);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
name = scriptArgString(runtime, args, argc, 1);
// name->data isn't null terminated - entitySetName needs a C string.
length = name->length;
if(length > ENTITY_NAME_MAX - 1) length = ENTITY_NAME_MAX - 1;
if(length) memoryCopy(buffer, name->data, length);
buffer[length] = 0;
entitySetName(entityId, buffer);
return scriptUndefined();
}
SCRIPT_NATIVE(scriptNativeEntityGetName) {
entityid_t entityId;
scriptArgCount(runtime, argc, 1, 1);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
return scriptStringFromC(
runtime, entityGetName(entityId)
);
}
SCRIPT_NATIVE(scriptNativeEntityFindByName) {
scriptstring_t *name;
char_t buffer[ENTITY_NAME_MAX];
uint16_t length;
entityid_t entityId;
scriptArgCount(runtime, argc, 1, 1);
name = scriptArgString(runtime, args, argc, 0);
length = name->length;
if(length > ENTITY_NAME_MAX - 1) length = ENTITY_NAME_MAX - 1;
if(length) memoryCopy(buffer, name->data, length);
buffer[length] = 0;
entityId = entityFindByName(buffer);
return scriptNumber((float)entityId);
}
SCRIPT_NATIVE(scriptNativeEntityDispose) {
entityid_t entityId;
scriptArgCount(runtime, argc, 1, 1);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
entityDispose(entityId);
return scriptUndefined();
}
SCRIPT_NATIVE(scriptNativeEntityDisposeDeep) {
entityid_t entityId;
scriptArgCount(runtime, argc, 1, 1);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
entityDisposeDeep(entityId);
return scriptUndefined();
}
void scriptNativeEntityRegister(scriptruntime_t *runtime) {
assertNotNull(runtime, "scriptNativeEntityRegister needs a runtime, not NULL");
scriptBuiltinAdd(runtime, "entityAddComponent", scriptNativeEntityAddComponent);
scriptBuiltinAdd(runtime, "entityGetComponent", scriptNativeEntityGetComponent);
scriptBuiltinAdd(runtime, "entitySetName", scriptNativeEntitySetName);
scriptBuiltinAdd(runtime, "entityGetName", scriptNativeEntityGetName);
scriptBuiltinAdd(runtime, "entityFindByName", scriptNativeEntityFindByName);
scriptBuiltinAdd(runtime, "entityDispose", scriptNativeEntityDispose);
scriptBuiltinAdd(runtime, "entityDisposeDeep", scriptNativeEntityDisposeDeep);
scriptBuiltinAddInt(runtime, "ENTITY_ID_INVALID", ENTITY_ID_INVALID);
scriptBuiltinAddInt(runtime, "COMPONENT_ID_INVALID", COMPONENT_ID_INVALID);
#define X(enumName, type, field, init, dispose, render) \
scriptBuiltinAddInt(runtime, "COMPONENT_TYPE_" #enumName, COMPONENT_TYPE_##enumName);
#include "entity/componentlist.h"
#undef X
}
@@ -0,0 +1,107 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/script.h"
#include "entity/entity.h"
/**
* Registers the entity natives (entityAddComponent, entityGetComponent,
* entitySetName, entityGetName, entityFindByName, entityDispose,
* entityDisposeDeep) and the ENTITY_ID_INVALID/COMPONENT_ID_INVALID and
* COMPONENT_TYPE_* constants they take, against the engine's global
* entity/component arrays (entity.h). See scriptNativeEntityManagerRegister
* for the entityAdd() native.
*
* @param runtime The runtime to add them to.
*/
void scriptNativeEntityRegister(scriptruntime_t *runtime);
/**
* Native implementation of entityAddComponent(entityId, type): adds a
* component of the given COMPONENT_TYPE_* to the entity.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID and a component type.
* @param argc Number of arguments.
* @param self The native function value.
* @return The new component's ID.
*/
SCRIPT_NATIVE(scriptNativeEntityAddComponent);
/**
* Native implementation of entityGetComponent(entityId, type): finds the
* entity's component of the given COMPONENT_TYPE_*, or COMPONENT_ID_INVALID
* if it has none.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID and a component type.
* @param argc Number of arguments.
* @param self The native function value.
* @return The component's ID, or COMPONENT_ID_INVALID.
*/
SCRIPT_NATIVE(scriptNativeEntityGetComponent);
/**
* Native implementation of entitySetName(entityId, name): names an entity,
* making it referenceable by entityFindByName.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID and a name.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntitySetName);
/**
* Native implementation of entityGetName(entityId): gets an entity's name,
* or an empty string if it has none.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID.
* @param argc Number of arguments.
* @param self The native function value.
* @return The entity's name.
*/
SCRIPT_NATIVE(scriptNativeEntityGetName);
/**
* Native implementation of entityFindByName(name): finds the first active
* entity with the given name, or ENTITY_ID_INVALID if none matches.
*
* @param runtime The runtime.
* @param args The arguments: a name.
* @param argc Number of arguments.
* @param self The native function value.
* @return The entity's ID, or ENTITY_ID_INVALID.
*/
SCRIPT_NATIVE(scriptNativeEntityFindByName);
/**
* Native implementation of entityDispose(entityId): disposes an entity and
* its components.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntityDispose);
/**
* Native implementation of entityDisposeDeep(entityId): disposes an entity
* and, recursively, every position-component descendant of it.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntityDisposeDeep);
@@ -0,0 +1,20 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptnativeentitymanager.h"
#include "assert/assert.h"
SCRIPT_NATIVE(scriptNativeEntityAdd) {
scriptArgCount(runtime, argc, 0, 0);
return scriptNumber((float)entityManagerAdd());
}
void scriptNativeEntityManagerRegister(scriptruntime_t *runtime) {
assertNotNull(runtime, "scriptNativeEntityManagerRegister needs a runtime, not NULL");
scriptBuiltinAdd(runtime, "entityAdd", scriptNativeEntityAdd);
}
@@ -0,0 +1,28 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/script.h"
#include "entity/entity.h"
/**
* Registers the entityAdd() native.
*
* @param runtime The runtime to add it to.
*/
void scriptNativeEntityManagerRegister(scriptruntime_t *runtime);
/**
* Native implementation of entityAdd(): reserves a new entity ID.
*
* @param runtime The runtime.
* @param args Unused, takes no arguments.
* @param argc Number of arguments.
* @param self The native function value.
* @return The new entity's ID.
*/
SCRIPT_NATIVE(scriptNativeEntityAdd);
@@ -0,0 +1,61 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptnativeentityposition.h"
#include "entity/entity.h"
#include "assert/assert.h"
SCRIPT_NATIVE(scriptNativeEntityPositionSetLocalPosition) {
entityid_t entityId;
componentid_t componentId;
vec3 position;
scriptArgCount(runtime, argc, 5, 5);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
componentId = (componentid_t)scriptArgInteger(runtime, args, argc, 1);
position[0] = scriptArgNumber(runtime, args, argc, 2).as.number;
position[1] = scriptArgNumber(runtime, args, argc, 3).as.number;
position[2] = scriptArgNumber(runtime, args, argc, 4).as.number;
entityPositionSetLocalPosition(
entityId, componentId, position
);
return scriptUndefined();
}
SCRIPT_NATIVE(scriptNativeEntityPositionLookAt) {
entityid_t entityId;
componentid_t componentId;
vec3 eye;
vec3 target;
vec3 up = { 0.0f, 1.0f, 0.0f };
scriptArgCount(runtime, argc, 8, 8);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
componentId = (componentid_t)scriptArgInteger(runtime, args, argc, 1);
eye[0] = scriptArgNumber(runtime, args, argc, 2).as.number;
eye[1] = scriptArgNumber(runtime, args, argc, 3).as.number;
eye[2] = scriptArgNumber(runtime, args, argc, 4).as.number;
target[0] = scriptArgNumber(runtime, args, argc, 5).as.number;
target[1] = scriptArgNumber(runtime, args, argc, 6).as.number;
target[2] = scriptArgNumber(runtime, args, argc, 7).as.number;
entityPositionLookAt(entityId, componentId, eye, target, up);
return scriptUndefined();
}
void scriptNativeEntityPositionRegister(scriptruntime_t *runtime) {
assertNotNull(runtime, "scriptNativeEntityPositionRegister needs a runtime, not NULL");
scriptBuiltinAdd(
runtime, "entityPositionSetLocalPosition",
scriptNativeEntityPositionSetLocalPosition
);
scriptBuiltinAdd(
runtime, "entityPositionLookAt", scriptNativeEntityPositionLookAt
);
}
@@ -0,0 +1,45 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/script.h"
#include "entity/component/display/entityposition.h"
/**
* Registers the entityPositionSetLocalPosition and entityPositionLookAt
* natives.
*
* @param runtime The runtime to add it to.
*/
void scriptNativeEntityPositionRegister(scriptruntime_t *runtime);
/**
* Native implementation of
* entityPositionSetLocalPosition(entityId, componentId, x, y, z).
*
* @param runtime The runtime.
* @param args The arguments: an entity ID, a position component ID, and x/y/z.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntityPositionSetLocalPosition);
/**
* Native implementation of
* entityPositionLookAt(entityId, componentId, eyeX, eyeY, eyeZ, targetX,
* targetY, targetZ): places the entity at eye, facing target, with world
* up (0, 1, 0) - SCRIPT_PARAMS_MAX leaves no room for an up argument too.
*
* @param runtime The runtime.
* @param args The arguments: an entity ID, a position component ID, and the
* eye and target points.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntityPositionLookAt);
@@ -0,0 +1,71 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "scriptnativeentityrenderable.h"
#include "entity/entity.h"
#include "error/scriptraise.h"
#include "display/mesh/cube.h"
#include "display/mesh/plane.h"
#include "display/mesh/sphere.h"
#include "display/mesh/capsule.h"
#include "display/mesh/triprism.h"
#include "display/mesh/quad.h"
#include "util/memory.h"
#include "util/string.h"
#include "assert/assert.h"
#define SCRIPT_NATIVE_ENTITY_RENDERABLE_MESH_NAME_MAX 16
// Scripts don't have mesh assets to point at yet, so this just names the
// engine's built in primitive shapes.
static mesh_t *scriptNativeEntityRenderableResolveMesh(const char_t *name) {
if(stringEquals(name, "cube")) return &CUBE_MESH_SIMPLE;
if(stringEquals(name, "plane")) return &PLANE_MESH_SIMPLE;
if(stringEquals(name, "sphere")) return &SPHERE_MESH_SIMPLE;
if(stringEquals(name, "capsule")) return &CAPSULE_MESH_SIMPLE;
if(stringEquals(name, "triprism")) return &TRIPRISM_MESH_SIMPLE;
if(stringEquals(name, "quad")) return &QUAD_MESH_SIMPLE;
return NULL;
}
SCRIPT_NATIVE(scriptNativeEntityRenderableSetMesh) {
entityid_t entityId;
componentid_t componentId;
scriptstring_t *nameArg;
char_t name[SCRIPT_NATIVE_ENTITY_RENDERABLE_MESH_NAME_MAX];
uint16_t length;
mesh_t *mesh;
scriptArgCount(runtime, argc, 3, 3);
entityId = (entityid_t)scriptArgInteger(runtime, args, argc, 0);
componentId = (componentid_t)scriptArgInteger(runtime, args, argc, 1);
nameArg = scriptArgString(runtime, args, argc, 2);
// nameArg->data isn't null terminated - need a C string to compare.
length = nameArg->length;
if(length > SCRIPT_NATIVE_ENTITY_RENDERABLE_MESH_NAME_MAX - 1) {
length = SCRIPT_NATIVE_ENTITY_RENDERABLE_MESH_NAME_MAX - 1;
}
if(length) memoryCopy(name, nameArg->data, length);
name[length] = 0;
mesh = scriptNativeEntityRenderableResolveMesh(name);
if(!mesh) scriptRaise(runtime, "Unknown mesh '%s'", name);
entityRenderableSetMesh(
entityId, componentId, 0, mesh
);
return scriptUndefined();
}
void scriptNativeEntityRenderableRegister(scriptruntime_t *runtime) {
assertNotNull(runtime, "scriptNativeEntityRenderableRegister needs a runtime, not NULL");
scriptBuiltinAdd(
runtime, "entityRenderableSetMesh", scriptNativeEntityRenderableSetMesh
);
}
@@ -0,0 +1,32 @@
/**
* Copyright (c) 2026 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "script/script.h"
#include "entity/component/display/entityrenderable.h"
/**
* Registers the entityRenderableSetMesh native.
*
* @param runtime The runtime to add it to.
*/
void scriptNativeEntityRenderableRegister(scriptruntime_t *runtime);
/**
* Native implementation of
* entityRenderableSetMesh(entityId, componentId, name): sets slot 0 of a
* material renderable to one of the engine's built in primitive meshes, by
* name - "cube", "plane", "sphere", "capsule", "triprism" or "quad".
*
* @param runtime The runtime.
* @param args The arguments: an entity ID, a renderable component ID, and a
* mesh name.
* @param argc Number of arguments.
* @param self The native function value.
* @return undefined.
*/
SCRIPT_NATIVE(scriptNativeEntityRenderableSetMesh);
+8
View File
@@ -7,6 +7,10 @@
#include "script.h" #include "script.h"
#include "native/scriptnativeconsole.h" #include "native/scriptnativeconsole.h"
#include "native/entity/scriptnativeentity.h"
#include "native/entity/scriptnativeentitymanager.h"
#include "native/entity/scriptnativeentityposition.h"
#include "native/entity/scriptnativeentityrenderable.h"
#include "builtin/scriptbuiltinregister.h" #include "builtin/scriptbuiltinregister.h"
#include "console/console.h" #include "console/console.h"
#include "asset/asset.h" #include "asset/asset.h"
@@ -68,6 +72,10 @@ errorret_t scriptInit(void) {
scriptBuiltinsRegister(SCRIPT.runtime); scriptBuiltinsRegister(SCRIPT.runtime);
scriptNativeConsoleRegister(SCRIPT.runtime); scriptNativeConsoleRegister(SCRIPT.runtime);
scriptNativeEntityManagerRegister(SCRIPT.runtime);
scriptNativeEntityRegister(SCRIPT.runtime);
scriptNativeEntityPositionRegister(SCRIPT.runtime);
scriptNativeEntityRenderableRegister(SCRIPT.runtime);
scriptVmAttach(SCRIPT.runtime); scriptVmAttach(SCRIPT.runtime);
scriptRuntimeSetPrintHandler(SCRIPT.runtime, scriptPrintHandler); scriptRuntimeSetPrintHandler(SCRIPT.runtime, scriptPrintHandler);
scriptRuntimeSetLoadHandler(SCRIPT.runtime, scriptLoadHandler); scriptRuntimeSetLoadHandler(SCRIPT.runtime, scriptLoadHandler);