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]>
172 lines
4.7 KiB
C
172 lines
4.7 KiB
C
/**
|
|
* Copyright (c) 2026 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#pragma once
|
|
#include "entity/entitybase.h"
|
|
#include "animation/animation.h"
|
|
|
|
typedef struct {
|
|
animation_t anim;
|
|
|
|
/**
|
|
* Playback rate multiplier; 1.0 = normal speed. This branch's
|
|
* animation_t has no speed field of its own (animationUpdate() just
|
|
* takes a deltaTime), so the multiplier is tracked here and applied to
|
|
* TIME.delta before calling animationUpdate() each tick.
|
|
*/
|
|
float_t speed;
|
|
|
|
/**
|
|
* True while entityAnimationUpdate() should advance anim's time each
|
|
* tick. This branch's animation_t has no playing field of its own --
|
|
* advancing is purely a function of whether animationUpdate() is
|
|
* called -- so playback gating lives here instead.
|
|
*/
|
|
bool_t playing;
|
|
} entityanimation_t;
|
|
|
|
/**
|
|
* Initializes the animation component: no keyframes set, and registers
|
|
* entityAnimationUpdate as an update callback. Call
|
|
* entityAnimationSetKeyframes() before entityAnimationPlay().
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
*/
|
|
void entityAnimationInit(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId
|
|
);
|
|
|
|
/**
|
|
* Gets the underlying animation structure (temporarily) for the given
|
|
* entity. Prefer the dedicated getters/setters where possible.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @return The animation component data for the given entity and
|
|
* component ID.
|
|
*/
|
|
entityanimation_t *entityAnimationGet(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId
|
|
);
|
|
|
|
/**
|
|
* Sets the entity's keyframes, stopped, at speed 1.0, non-looping. See
|
|
* animationInit() -- keyframes/keyframeCounts and the keyframe_t data
|
|
* they point to are not copied, and must outlive this component (e.g.
|
|
* static/const arrays owned by the caller).
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @param keyframes Flat array of keyframe_t, one contiguous run per layer
|
|
* (layer's run length is keyframeCounts[layer]) -- see animationInit().
|
|
* @param keyframeCounts Array of layerCount keyframe counts, matching the
|
|
* per-layer runs in keyframes.
|
|
* @param layerCount The number of layers/channels.
|
|
*/
|
|
void entityAnimationSetKeyframes(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId,
|
|
keyframe_t *keyframes,
|
|
uint16_t *keyframeCounts,
|
|
const uint16_t layerCount
|
|
);
|
|
|
|
/**
|
|
* Starts (or restarts) playback from time 0.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
*/
|
|
void entityAnimationPlay(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId
|
|
);
|
|
|
|
/**
|
|
* Stops playback without resetting the current time.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
*/
|
|
void entityAnimationStop(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId
|
|
);
|
|
|
|
/**
|
|
* Checks whether the animation is currently playing.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @return True if playing.
|
|
*/
|
|
bool_t entityAnimationIsPlaying(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId
|
|
);
|
|
|
|
/**
|
|
* Sets whether the animation loops on reaching its final keyframe, rather
|
|
* than stopping there.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @param loop True to loop, false to stop at the end.
|
|
*/
|
|
void entityAnimationSetLoop(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId,
|
|
const bool_t loop
|
|
);
|
|
|
|
/**
|
|
* Sets the animation's playback rate multiplier.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @param speed The new playback rate; 1.0 = normal speed.
|
|
*/
|
|
void entityAnimationSetSpeed(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId,
|
|
const float_t speed
|
|
);
|
|
|
|
/**
|
|
* Evaluates one of the animation's channels at its current playback
|
|
* time, regardless of whether it's currently playing.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @param channelIndex The channel to evaluate, in [0, channelCount) as
|
|
* passed to entityAnimationSetKeyframes().
|
|
* @return That channel's value at the current time.
|
|
*/
|
|
float_t entityAnimationGetValue(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId,
|
|
const uint16_t channelIndex
|
|
);
|
|
|
|
/**
|
|
* Per-tick update for the animation component: calls animationUpdate()
|
|
* (a no-op if not playing). Registered automatically as an update
|
|
* callback by entityAnimationInit.
|
|
*
|
|
* @param entityId The entity ID.
|
|
* @param componentId The component ID.
|
|
* @param user Unused.
|
|
*/
|
|
void entityAnimationUpdate(
|
|
const entityid_t entityId,
|
|
const componentid_t componentId,
|
|
void *user
|
|
);
|