diff --git a/src/duskrpg/cutscene/cutscene.h b/src/duskrpg/cutscene/cutscene.h index 1eb24838..f16d9708 100644 --- a/src/duskrpg/cutscene/cutscene.h +++ b/src/duskrpg/cutscene/cutscene.h @@ -125,3 +125,32 @@ typedef struct cutscene_s { .type = CUTSCENE_ITEM_TYPE_ENTITY_ITEM_PICKUP, \ .entityItemPickup = { (ENTITY_INDEX), MESSAGE } \ } + +/** + * Starts (or restarts) the entity's ANIMATION component from time 0. Does + * not block the cutscene; follow with CUTSCENE_ENTITY_ANIMATION_WAIT to + * wait for a non-looping animation to finish. + * + * @param LOOP See entityAnimationSetLoop(). + * @param SPEED See entityAnimationSetSpeed(). + */ +#define CUTSCENE_ENTITY_ANIMATION_PLAY(ENTITY_INDEX, LOOP, SPEED) \ + { \ + .type = CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_PLAY, \ + .entityAnimationPlay = { (ENTITY_INDEX), (LOOP), (SPEED) } \ + } + +/** Stops the entity's ANIMATION component immediately. */ +#define CUTSCENE_ENTITY_ANIMATION_STOP(ENTITY_INDEX) \ + { \ + .type = CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_STOP, \ + .entityAnimationStop = { (ENTITY_INDEX) } \ + } + +/** Blocks the cutscene until the entity's ANIMATION component stops + * playing; see cutsceneEntityAnimationWaitUpdate(). */ +#define CUTSCENE_ENTITY_ANIMATION_WAIT(ENTITY_INDEX) \ + { \ + .type = CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_WAIT, \ + .entityAnimationWait = { (ENTITY_INDEX) } \ + } diff --git a/src/duskrpg/cutscene/item/cutsceneitem.c b/src/duskrpg/cutscene/item/cutsceneitem.c index 345bec3e..6e124daf 100644 --- a/src/duskrpg/cutscene/item/cutsceneitem.c +++ b/src/duskrpg/cutscene/item/cutsceneitem.c @@ -50,6 +50,15 @@ CUTSCENE_ITEM_CALLBACKS[CUTSCENE_ITEM_TYPE_COUNT] = { }, [CUTSCENE_ITEM_TYPE_ENTITY_ITEM_PICKUP] = { cutsceneEntityItemPickupStart, cutsceneEntityItemPickupUpdate + }, + [CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_PLAY] = { + cutsceneEntityAnimationPlayStart, cutsceneEntityAnimationPlayUpdate + }, + [CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_STOP] = { + cutsceneEntityAnimationStopStart, cutsceneEntityAnimationStopUpdate + }, + [CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_WAIT] = { + cutsceneEntityAnimationWaitStart, cutsceneEntityAnimationWaitUpdate } }; diff --git a/src/duskrpg/cutscene/item/cutsceneitem.h b/src/duskrpg/cutscene/item/cutsceneitem.h index 5e987e96..b60b4781 100644 --- a/src/duskrpg/cutscene/item/cutsceneitem.h +++ b/src/duskrpg/cutscene/item/cutsceneitem.h @@ -18,6 +18,9 @@ #include "cutscene/item/entity/cutsceneentityadd.h" #include "cutscene/item/entity/cutsceneentityremove.h" #include "cutscene/item/entity/cutsceneentityitempickup.h" +#include "cutscene/item/entity/cutsceneentityanimationplay.h" +#include "cutscene/item/entity/cutsceneentityanimationstop.h" +#include "cutscene/item/entity/cutsceneentityanimationwait.h" #include "cutscene/item/ui/cutscenetext.h" typedef struct cutscene_s cutscene_t; @@ -37,6 +40,9 @@ typedef enum { CUTSCENE_ITEM_TYPE_ENTITY_ADD, CUTSCENE_ITEM_TYPE_ENTITY_REMOVE, CUTSCENE_ITEM_TYPE_ENTITY_ITEM_PICKUP, + CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_PLAY, + CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_STOP, + CUTSCENE_ITEM_TYPE_ENTITY_ANIMATION_WAIT, CUTSCENE_ITEM_TYPE_COUNT } cutsceneitemtype_t; @@ -56,6 +62,9 @@ typedef struct cutsceneitem_s { cutsceneentityadd_t entityAdd; cutsceneentityremove_t entityRemove; cutsceneentityitempickup_t entityItemPickup; + cutsceneentityanimationplay_t entityAnimationPlay; + cutsceneentityanimationstop_t entityAnimationStop; + cutsceneentityanimationwait_t entityAnimationWait; }; } cutsceneitem_t; diff --git a/src/duskrpg/cutscene/item/entity/CMakeLists.txt b/src/duskrpg/cutscene/item/entity/CMakeLists.txt index 6ee66018..d0c595fb 100644 --- a/src/duskrpg/cutscene/item/entity/CMakeLists.txt +++ b/src/duskrpg/cutscene/item/entity/CMakeLists.txt @@ -6,6 +6,9 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} PUBLIC cutsceneentityadd.c + cutsceneentityanimationplay.c + cutsceneentityanimationstop.c + cutsceneentityanimationwait.c cutsceneentityitempickup.c cutsceneentityremove.c cutsceneentityteleport.c diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.c b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.c new file mode 100644 index 00000000..7f0f4825 --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.c @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "cutscene/item/cutsceneitem.h" +#include "cutscene/cutscenesystem.h" +#include "entity/entitymanager.h" +#include "entity/component/animation/entityanimation.h" + +void cutsceneEntityAnimationPlayStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { + entityid_t entityId = cutsceneSystemGetEntity( + item->entityAnimationPlay.entityIndex + ); + componentid_t animComp = entityGetComponent( + CUTSCENE_SYSTEM.mgr, entityId, COMPONENT_TYPE_ANIMATION + ); + if(animComp == COMPONENT_ID_INVALID) return; + + entityAnimationSetLoop( + CUTSCENE_SYSTEM.mgr, entityId, animComp, item->entityAnimationPlay.loop + ); + entityAnimationSetSpeed( + CUTSCENE_SYSTEM.mgr, entityId, animComp, item->entityAnimationPlay.speed + ); + entityAnimationPlay(CUTSCENE_SYSTEM.mgr, entityId, animComp); +} + +bool_t cutsceneEntityAnimationPlayUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { + return true; +} diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.h b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.h new file mode 100644 index 00000000..b36d92c1 --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationplay.h @@ -0,0 +1,49 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct cutsceneitem_s cutsceneitem_t; +typedef union cutsceneitemdata_u cutsceneitemdata_t; + +typedef struct { + uint8_t entityIndex; + + /** See entityAnimationSetLoop(). */ + bool_t loop; + + /** See entityAnimationSetSpeed(). */ + float_t speed; +} cutsceneentityanimationplay_t; + +/** + * Starts an entity animation play item: sets loop/speed on the entity's + * ANIMATION component then starts it from time 0, via entityAnimationPlay(). + * No-op if the entity has no ANIMATION component. + * + * @param item The cutscene item. + * @param data Runtime data storage. + */ +void cutsceneEntityAnimationPlayStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +); + +/** + * Updates an entity animation play item (always completes immediately -- + * the animation keeps playing in the background via its own component + * update; use CUTSCENE_ENTITY_ANIMATION_WAIT to block on it finishing). + * + * @param item The cutscene item. + * @param data Runtime data storage. + * @returns true always. + */ +bool_t cutsceneEntityAnimationPlayUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +); diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.c b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.c new file mode 100644 index 00000000..1e8d775b --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.c @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "cutscene/item/cutsceneitem.h" +#include "cutscene/cutscenesystem.h" +#include "entity/entitymanager.h" +#include "entity/component/animation/entityanimation.h" + +void cutsceneEntityAnimationStopStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { + entityid_t entityId = cutsceneSystemGetEntity( + item->entityAnimationStop.entityIndex + ); + componentid_t animComp = entityGetComponent( + CUTSCENE_SYSTEM.mgr, entityId, COMPONENT_TYPE_ANIMATION + ); + if(animComp == COMPONENT_ID_INVALID) return; + + entityAnimationStop(CUTSCENE_SYSTEM.mgr, entityId, animComp); +} + +bool_t cutsceneEntityAnimationStopUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { + return true; +} diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.h b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.h new file mode 100644 index 00000000..7c1714c9 --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationstop.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct cutsceneitem_s cutsceneitem_t; +typedef union cutsceneitemdata_u cutsceneitemdata_t; + +typedef struct { + uint8_t entityIndex; +} cutsceneentityanimationstop_t; + +/** + * Starts an entity animation stop item: stops the entity's ANIMATION + * component immediately, via entityAnimationStop(). No-op if the entity + * has no ANIMATION component. + * + * @param item The cutscene item. + * @param data Runtime data storage. + */ +void cutsceneEntityAnimationStopStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +); + +/** + * Updates an entity animation stop item (always completes immediately). + * + * @param item The cutscene item. + * @param data Runtime data storage. + * @returns true always. + */ +bool_t cutsceneEntityAnimationStopUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +); diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.c b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.c new file mode 100644 index 00000000..8f67980e --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.c @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "cutscene/item/cutsceneitem.h" +#include "cutscene/cutscenesystem.h" +#include "entity/entitymanager.h" +#include "entity/component/animation/entityanimation.h" + +void cutsceneEntityAnimationWaitStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { +} + +bool_t cutsceneEntityAnimationWaitUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +) { + entityid_t entityId = cutsceneSystemGetEntity( + item->entityAnimationWait.entityIndex + ); + componentid_t animComp = entityGetComponent( + CUTSCENE_SYSTEM.mgr, entityId, COMPONENT_TYPE_ANIMATION + ); + if(animComp == COMPONENT_ID_INVALID) return true; + + return !entityAnimationIsPlaying(CUTSCENE_SYSTEM.mgr, entityId, animComp); +} diff --git a/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.h b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.h new file mode 100644 index 00000000..39162cc2 --- /dev/null +++ b/src/duskrpg/cutscene/item/entity/cutsceneentityanimationwait.h @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "dusk.h" + +typedef struct cutsceneitem_s cutsceneitem_t; +typedef union cutsceneitemdata_u cutsceneitemdata_t; + +typedef struct { + uint8_t entityIndex; +} cutsceneentityanimationwait_t; + +/** + * Starts an entity animation wait item. No setup needed -- completion is + * entirely driven by entityAnimationIsPlaying() in the update callback. + * + * @param item The cutscene item. + * @param data Runtime data storage. + */ +void cutsceneEntityAnimationWaitStart( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +); + +/** + * Updates an entity animation wait item: blocks the cutscene until the + * entity's ANIMATION component stops playing (e.g. a non-looping + * animation started with CUTSCENE_ENTITY_ANIMATION_PLAY reaching its + * final keyframe, or an explicit CUTSCENE_ENTITY_ANIMATION_STOP). + * Completes immediately if the entity has no ANIMATION component. + * + * @param item The cutscene item. + * @param data Runtime data storage. + * @returns true once the animation is no longer playing. + */ +bool_t cutsceneEntityAnimationWaitUpdate( + const cutsceneitem_t *item, + cutsceneitemdata_t *data +);