1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-07-03 22:44:30 +00:00

Revamp "AnimationContext" Docs, now called "AnimTaskQueue" (#1941)

* start using task terminology

* more docs

* format

* cleanups

* MoveActor -> ActorMove

* missed a couple

* hopefully the last changes

* comment explaining the group change

* some review

* dragorn review

* remove accidental file

* fix matching issue, now use while loop
This commit is contained in:
fig02 2024-06-18 23:46:36 -04:00 committed by GitHub
parent 7332e8ee76
commit 06bbdf88f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 310 additions and 262 deletions

View file

@ -396,7 +396,7 @@ typedef struct PlayState {
/* 0x10760 */ PauseContext pauseCtx; /* 0x10760 */ PauseContext pauseCtx;
/* 0x10A20 */ GameOverContext gameOverCtx; /* 0x10A20 */ GameOverContext gameOverCtx;
/* 0x10A24 */ EnvironmentContext envCtx; /* 0x10A24 */ EnvironmentContext envCtx;
/* 0x10B20 */ AnimationContext animationCtx; /* 0x10B20 */ AnimTaskQueue animTaskQueue;
/* 0x117A4 */ ObjectContext objectCtx; /* 0x117A4 */ ObjectContext objectCtx;
/* 0x11CBC */ RoomContext roomCtx; /* 0x11CBC */ RoomContext roomCtx;
/* 0x11D34 */ TransitionActorContext transiActorCtx; /* 0x11D34 */ TransitionActorContext transiActorCtx;

130
include/z64animation.h Executable file → Normal file
View file

@ -91,7 +91,7 @@ typedef enum {
#define ANIM_FLAG_0 (1 << 0) // (no effect outside of player) Related to scaling an animation from/to child/adult #define ANIM_FLAG_0 (1 << 0) // (no effect outside of player) Related to scaling an animation from/to child/adult
#define ANIM_FLAG_UPDATE_Y (1 << 1) #define ANIM_FLAG_UPDATE_Y (1 << 1)
#define ANIM_FLAG_PLAYER_2 (1 << 2) // (player-only) Related to scaling an animation from/to child/adult #define ANIM_FLAG_PLAYER_2 (1 << 2) // (player-only) Related to scaling an animation from/to child/adult
#define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) // (player-only) Call AnimationContext_SetMoveActor #define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) // (player-only) Call AnimTaskQueue_AddActorMove
#define ANIM_FLAG_NO_MOVE (1 << 4) #define ANIM_FLAG_NO_MOVE (1 << 4)
#define ANIM_FLAG_PLAYER_7 (1 << 7) // (player-only) #define ANIM_FLAG_PLAYER_7 (1 << 7) // (player-only)
@ -239,95 +239,95 @@ s16 Animation_GetLength(void* animation);
s16 Animation_GetLastFrame(void* animation); s16 Animation_GetLastFrame(void* animation);
/* /*
* Animation requests * Animation Task Queue
*/ */
typedef enum { typedef enum {
/* 0 */ ANIMENTRY_LOADFRAME, /* 0 */ ANIMTASK_LOAD_PLAYER_FRAME,
/* 1 */ ANIMENTRY_COPYALL, /* 1 */ ANIMTASK_COPY,
/* 2 */ ANIMENTRY_INTERP, /* 2 */ ANIMTASK_INTERP,
/* 3 */ ANIMENTRY_COPYTRUE, /* 3 */ ANIMTASK_COPY_USING_MAP,
/* 4 */ ANIMENTRY_COPYFALSE, /* 4 */ ANIMTASK_COPY_USING_MAP_INVERTED,
/* 5 */ ANIMENTRY_MOVEACTOR /* 5 */ ANIMTASK_ACTOR_MOVE
} AnimationType; } AnimTaskType;
typedef struct { typedef struct {
/* 0x000 */ DmaRequest req; /* 0x00 */ DmaRequest req;
/* 0x020 */ OSMesgQueue msgQueue; /* 0x20 */ OSMesgQueue msgQueue;
/* 0x038 */ OSMesg msg; /* 0x38 */ OSMesg msg;
} AnimEntryLoadFrame; // size = 0x3C } AnimTaskLoadPlayerFrame; // size = 0x3C
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
} AnimEntryCopyAll; // size = 0xC } AnimTaskCopy; // size = 0xC
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* base; /* 0x04 */ Vec3s* base;
/* 0x008 */ Vec3s* mod; /* 0x08 */ Vec3s* mod;
/* 0x00C */ f32 weight; /* 0x0C */ f32 weight;
} AnimEntryInterp; // size = 0x10 } AnimTaskInterp; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
/* 0x00C */ u8* copyFlag; /* 0x0C */ u8* limbCopyMap;
} AnimEntryCopyTrue; // size = 0x10 } AnimTaskCopyUsingMap; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
/* 0x00C */ u8* copyFlag; /* 0x0C */ u8* limbCopyMap;
} AnimEntryCopyFalse; // size = 0x10 } AnimTaskCopyUsingMapInverted; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ struct Actor* actor; /* 0x00 */ struct Actor* actor;
/* 0x004 */ struct SkelAnime* skelAnime; /* 0x04 */ struct SkelAnime* skelAnime;
/* 0x008 */ f32 diffScaleY; /* 0x08 */ f32 diffScaleY;
} AnimEntryMoveActor; // size = 0xC } AnimTaskActorMove; // size = 0xC
typedef union { typedef union {
AnimEntryLoadFrame load; AnimTaskLoadPlayerFrame loadPlayerFrame;
AnimEntryCopyAll copy; AnimTaskCopy copy;
AnimEntryInterp interp; AnimTaskInterp interp;
AnimEntryCopyTrue copy1; AnimTaskCopyUsingMap copyUsingMap;
AnimEntryCopyFalse copy0; AnimTaskCopyUsingMapInverted copyUsingMapInverted;
AnimEntryMoveActor move; AnimTaskActorMove actorMove;
} AnimationEntryData; // size = 0x3C } AnimTaskData; // size = 0x3C
typedef struct { typedef struct {
/* 0x00 */ u8 type; /* 0x00 */ u8 type;
/* 0x04 */ AnimationEntryData data; /* 0x04 */ AnimTaskData data;
} AnimationEntry; // size = 0x40 } AnimTask; // size = 0x40
#define ANIMATION_ENTRY_MAX 50 #define ANIM_TASK_QUEUE_MAX 50
typedef struct AnimationContext { typedef struct AnimTaskQueue {
s16 animationCount; s16 count;
AnimationEntry entries[ANIMATION_ENTRY_MAX]; AnimTask tasks[ANIM_TASK_QUEUE_MAX];
} AnimationContext; // size = 0xC84 } AnimTaskQueue; // size = 0xC84
void AnimationContext_SetLoadFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, void AnimTaskQueue_AddLoadPlayerFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount,
Vec3s* frameTable); Vec3s* frameTable);
void AnimationContext_SetCopyAll(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src); void AnimTaskQueue_AddCopy(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src);
void AnimationContext_SetCopyTrue(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); void AnimTaskQueue_AddInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight);
void AnimationContext_SetCopyFalse(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); void AnimTaskQueue_AddCopyUsingMap(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap);
void AnimationContext_SetInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight); void AnimTaskQueue_AddCopyUsingMapInverted(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap);
void AnimationContext_SetMoveActor(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY); void AnimTaskQueue_AddActorMove(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY);
void AnimationContext_SetNextQueue(struct PlayState* play); void AnimTaskQueue_SetNextGroup(struct PlayState* play);
void AnimationContext_DisableQueue(struct PlayState* play); void AnimTaskQueue_DisableTransformTasksForGroup(struct PlayState* play);
void AnimationContext_Reset(AnimationContext* animationCtx); void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue);
void AnimationContext_Update(struct PlayState* play, AnimationContext* animationCtx); void AnimTaskQueue_Update(struct PlayState* play, AnimTaskQueue* animTaskQueue);
/* /*
* Link animations * Link animations

View file

@ -284,7 +284,7 @@ void Play_Init(GameState* thisx) {
Effect_InitContext(this); Effect_InitContext(this);
EffectSs_InitInfo(this, 0x55); EffectSs_InitInfo(this, 0x55);
CollisionCheck_InitContext(this, &this->colChkCtx); CollisionCheck_InitContext(this, &this->colChkCtx);
AnimationContext_Reset(&this->animationCtx); AnimTaskQueue_Reset(&this->animTaskQueue);
Cutscene_InitContext(this, &this->csCtx); Cutscene_InitContext(this, &this->csCtx);
if (gSaveContext.nextCutsceneIndex != 0xFFEF) { if (gSaveContext.nextCutsceneIndex != 0xFFEF) {
@ -454,7 +454,7 @@ void Play_Init(GameState* thisx) {
gSaveContext.seqId = this->sequenceCtx.seqId; gSaveContext.seqId = this->sequenceCtx.seqId;
gSaveContext.natureAmbienceId = this->sequenceCtx.natureAmbienceId; gSaveContext.natureAmbienceId = this->sequenceCtx.natureAmbienceId;
func_8002DF18(this, GET_PLAYER(this)); func_8002DF18(this, GET_PLAYER(this));
AnimationContext_Update(this, &this->animationCtx); AnimTaskQueue_Update(this, &this->animTaskQueue);
gSaveContext.respawnFlag = 0; gSaveContext.respawnFlag = 0;
#if OOT_DEBUG #if OOT_DEBUG
@ -883,7 +883,7 @@ void Play_Update(PlayState* this) {
isPaused = IS_PAUSED(&this->pauseCtx); isPaused = IS_PAUSED(&this->pauseCtx);
PLAY_LOG(3555); PLAY_LOG(3555);
AnimationContext_Reset(&this->animationCtx); AnimTaskQueue_Reset(&this->animTaskQueue);
if (!OOT_DEBUG) {} if (!OOT_DEBUG) {}
@ -1000,7 +1000,7 @@ void Play_Update(PlayState* this) {
Interface_Update(this); Interface_Update(this);
PLAY_LOG(3765); PLAY_LOG(3765);
AnimationContext_Update(this, &this->animationCtx); AnimTaskQueue_Update(this, &this->animTaskQueue);
PLAY_LOG(3771); PLAY_LOG(3771);
SfxSource_UpdateAll(this); SfxSource_UpdateAll(this);

View file

@ -9,9 +9,6 @@ s32 SkelAnime_LoopFull(SkelAnime* skelAnime);
s32 SkelAnime_Once(SkelAnime* skelAnime); s32 SkelAnime_Once(SkelAnime* skelAnime);
s32 SkelAnime_LoopPartial(SkelAnime* skelAnime); s32 SkelAnime_LoopPartial(SkelAnime* skelAnime);
static u32 sDisableAnimQueueFlags = 0;
static u32 sAnimQueueFlags;
/** /**
* Draw a limb of type `LodLimb` * Draw a limb of type `LodLimb`
* Near or far display list is specified via `lod` * Near or far display list is specified via `lod`
@ -798,39 +795,64 @@ void SkelAnime_InterpFrameTable(s32 limbCount, Vec3s* dst, Vec3s* start, Vec3s*
} }
} }
static u32 sDisabledTransformTaskGroups = 0;
static u32 sCurAnimTaskGroup;
/** /**
* zeroes out the current request count * Clear the current task queue. The discarded tasks will then not be processed.
*/ */
void AnimationContext_Reset(AnimationContext* animationCtx) { void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue) {
animationCtx->animationCount = 0; animTaskQueue->count = 0;
} }
/** /**
* Shifts the queue flag to the next queue * Changes `sCurAnimTaskGroup` to the next group number.
*
* Task groups allow for disabling "transformative" tasks for a defined group.
* For more information see `AnimTaskQueue_DisableTransformTasksForGroup`.
*
* Note that `sCurAnimTaskGroup` is not a whole number that increments, it is handled at the bit-level.
* Every time the group number changes, a single bit moves 1 position to the left. This is an implementation detail
* that allows for `sDisabledTransformTaskGroups` to compare against a set of bit flags.
*/ */
void AnimationContext_SetNextQueue(PlayState* play) { void AnimTaskQueue_SetNextGroup(PlayState* play) {
sAnimQueueFlags <<= 1; sCurAnimTaskGroup <<= 1;
} }
/** /**
* Disables the current animation queue. Only load and move actor requests will be processed for that queue. * Marks the current task group as disabled so that "transformative" tasks are skipped.
* A transformative task is one that will alter the appearance of an animation.
* These include Copy, Interp, CopyUsingMap, and CopyUsingMapInverted.
*
* LoadPlayerFrame and ActorMove, which don't alter the appearance of an existing animation,
* will always run even if a group has its transformative tasks disabled.
*/ */
void AnimationContext_DisableQueue(PlayState* play) { void AnimTaskQueue_DisableTransformTasksForGroup(PlayState* play) {
sDisableAnimQueueFlags |= sAnimQueueFlags; sDisabledTransformTaskGroups |= sCurAnimTaskGroup;
} }
AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, AnimationType type) { /**
AnimationEntry* entry; * Creates a new task and adds it to the queue, if there is room for it.
s16 index = animationCtx->animationCount; *
* The `type` value for the task gets set here, but all other
* initialization must be handled by the caller.
*
* @return a pointer to the task, or NULL if it could not be added
*/
AnimTask* AnimTaskQueue_NewTask(AnimTaskQueue* animTaskQueue, s32 type) {
AnimTask* task;
s16 taskNumber = animTaskQueue->count;
if (index >= ANIMATION_ENTRY_MAX) { if (taskNumber >= ANIM_TASK_QUEUE_MAX) {
return NULL; return NULL;
} }
animationCtx->animationCount = index + 1; animTaskQueue->count = taskNumber + 1;
entry = &animationCtx->entries[index];
entry->type = type; task = &animTaskQueue->tasks[taskNumber];
return entry; task->type = type;
return task;
} }
#define LINK_ANIMATION_OFFSET(addr, offset) \ #define LINK_ANIMATION_OFFSET(addr, offset) \
@ -838,205 +860,230 @@ AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, Animat
(offset)) (offset))
/** /**
* Requests loading frame data from the Link animation into frameTable * Creates a task which will load a single frame of animation data from the link_animetion file.
* The asynchronous DMA request to load the data is made as soon as the task is created.
* When the task is processed later in the AnimTaskQueue, it will wait for the DMA to finish.
*/ */
void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, void AnimTaskQueue_AddLoadPlayerFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount,
Vec3s* frameTable) { Vec3s* frameTable) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_LOADFRAME); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_LOAD_PLAYER_FRAME);
if (entry != NULL) { if (task != NULL) {
LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation); LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation);
s32 pad; s32 pad;
osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1); osCreateMesgQueue(&task->data.loadPlayerFrame.msgQueue, &task->data.loadPlayerFrame.msg, 1);
DMA_REQUEST_ASYNC(&entry->data.load.req, frameTable, DMA_REQUEST_ASYNC(&task->data.loadPlayerFrame.req, frameTable,
LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)), LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)),
sizeof(Vec3s) * limbCount + 2, 0, &entry->data.load.msgQueue, NULL, "../z_skelanime.c", 2004); sizeof(Vec3s) * limbCount + 2, 0, &task->data.loadPlayerFrame.msgQueue, NULL,
"../z_skelanime.c", 2004);
} }
} }
/** /**
* Requests copying all vectors from src frame table into dst frame table * Creates a task which will copy all vectors from the `src` frame table to the `dest` frame table.
*
* Note: This task is "transformative", meaning it will alter the appearance of an animation.
* If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame.
*/ */
void AnimationContext_SetCopyAll(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src) { void AnimTaskQueue_AddCopy(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYALL); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY);
if (entry != NULL) { if (task != NULL) {
entry->data.copy.queueFlag = sAnimQueueFlags; task->data.copy.group = sCurAnimTaskGroup;
entry->data.copy.vecCount = vecCount; task->data.copy.vecCount = vecCount;
entry->data.copy.dst = dst; task->data.copy.dest = dest;
entry->data.copy.src = src; task->data.copy.src = src;
} }
} }
/** /**
* Requests interpolating between base and mod frame tables with the given weight, placing the result in base * Creates a task which will interpolate between the `base` and `mod` frame tables.
* The result of the interpolation will be placed in the original `base` table.
*
* Note: This task is "transformative", meaning it will alter the appearance of an animation.
* If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame.
*/ */
void AnimationContext_SetInterp(PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) { void AnimTaskQueue_AddInterp(PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_INTERP); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_INTERP);
if (entry != NULL) { if (task != NULL) {
entry->data.interp.queueFlag = sAnimQueueFlags; task->data.interp.group = sCurAnimTaskGroup;
entry->data.interp.vecCount = vecCount; task->data.interp.vecCount = vecCount;
entry->data.interp.base = base; task->data.interp.base = base;
entry->data.interp.mod = mod; task->data.interp.mod = mod;
entry->data.interp.weight = weight; task->data.interp.weight = weight;
} }
} }
/** /**
* Requests copying vectors from src frame table to dst frame table whose copy flag is true * Creates a task which will copy specified vectors from the `src` frame table to the `dest` frame table.
* Exactly which vectors will be copied is specified by the `limbCopyMap`.
*
* The copy map is an array of true/false flags that specify which limbs should have their data copied.
* Each index of the map corresponds to a limb number in the skeleton.
* Every limb that has `true` listed will have its data copied.
*
* Note: This task is "transformative", meaning it will alter the appearance of an animation.
* If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame.
*/ */
void AnimationContext_SetCopyTrue(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) { void AnimTaskQueue_AddCopyUsingMap(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYTRUE); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP);
if (entry != NULL) { if (task != NULL) {
entry->data.copy1.queueFlag = sAnimQueueFlags; task->data.copyUsingMap.group = sCurAnimTaskGroup;
entry->data.copy1.vecCount = vecCount; task->data.copyUsingMap.vecCount = vecCount;
entry->data.copy1.dst = dst; task->data.copyUsingMap.dest = dest;
entry->data.copy1.src = src; task->data.copyUsingMap.src = src;
entry->data.copy1.copyFlag = copyFlag; task->data.copyUsingMap.limbCopyMap = limbCopyMap;
} }
} }
/** /**
* Requests copying vectors from src frame table to dst frame table whose copy flag is false * Identical to `AnimTaskQueue_AddCopyUsingMap`, except the meaning of the flags in the `limbCopyMap` are inverted.
* Any entry that specifies `false` will be copied, and any entry that specifies `true` will not.
*
* Note: This task is "transformative", meaning it will alter the appearance of an animation.
* If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame.
*/ */
void AnimationContext_SetCopyFalse(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) { void AnimTaskQueue_AddCopyUsingMapInverted(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYFALSE); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP_INVERTED);
if (entry != NULL) { if (task != NULL) {
entry->data.copy0.queueFlag = sAnimQueueFlags; task->data.copyUsingMapInverted.group = sCurAnimTaskGroup;
entry->data.copy0.vecCount = vecCount; task->data.copyUsingMapInverted.vecCount = vecCount;
entry->data.copy0.dst = dst; task->data.copyUsingMapInverted.dest = dest;
entry->data.copy0.src = src; task->data.copyUsingMapInverted.src = src;
entry->data.copy0.copyFlag = copyFlag; task->data.copyUsingMapInverted.limbCopyMap = limbCopyMap;
} }
} }
/** /**
* Requests moving an actor according to the translation of its root limb * Creates a task which will move an actor according to the translation of its root limb for the current frame.
*/ */
void AnimationContext_SetMoveActor(PlayState* play, Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY) { void AnimTaskQueue_AddActorMove(PlayState* play, Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_MOVEACTOR); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_ACTOR_MOVE);
if (entry != NULL) { if (task != NULL) {
entry->data.move.actor = actor; task->data.actorMove.actor = actor;
entry->data.move.skelAnime = skelAnime; task->data.actorMove.skelAnime = skelAnime;
entry->data.move.diffScaleY = moveDiffScaleY; task->data.actorMove.diffScaleY = moveDiffScaleY;
} }
} }
/** /**
* Receives the request for Link's animation frame data * Wait for the DMA request submitted by `AnimTaskQueue_AddLoadPlayerFrame` to complete.
*/ */
void AnimationContext_LoadFrame(PlayState* play, AnimationEntryData* data) { void AnimTask_LoadPlayerFrame(PlayState* play, AnimTaskData* data) {
AnimEntryLoadFrame* entry = &data->load; AnimTaskLoadPlayerFrame* task = &data->loadPlayerFrame;
osRecvMesg(&entry->msgQueue, NULL, OS_MESG_BLOCK); osRecvMesg(&task->msgQueue, NULL, OS_MESG_BLOCK);
} }
/** /**
* If the entry's queue is enabled, copies all vectors from src frame table to dst frame table * Copy all data from the `src` frame table to the `dest` table.
*/ */
void AnimationContext_CopyAll(PlayState* play, AnimationEntryData* data) { void AnimTask_Copy(PlayState* play, AnimTaskData* data) {
AnimEntryCopyAll* entry = &data->copy; AnimTaskCopy* task = &data->copy;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++) { for (i = 0; i < task->vecCount; i++) {
*dst++ = *src++; *dest++ = *src++;
} }
} }
} }
/** /**
* If the entry's queue is enabled, interpolates between the base and mod frame tables, placing the result in base * Interpolate between the `base` and `mod` frame tables.
*/ */
void AnimationContext_Interp(PlayState* play, AnimationEntryData* data) { void AnimTask_Interp(PlayState* play, AnimTaskData* data) {
AnimEntryInterp* entry = &data->interp; AnimTaskInterp* task = &data->interp;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
SkelAnime_InterpFrameTable(entry->vecCount, entry->base, entry->base, entry->mod, entry->weight); SkelAnime_InterpFrameTable(task->vecCount, task->base, task->base, task->mod, task->weight);
} }
} }
/** /**
* If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is true * Copy all data from the `src` frame table to the `dest` table according to the copy map.
*/ */
void AnimationContext_CopyTrue(PlayState* play, AnimationEntryData* data) { void AnimTask_CopyUsingMap(PlayState* play, AnimTaskData* data) {
AnimEntryCopyTrue* entry = &data->copy1; AnimTaskCopyUsingMap* task = &data->copyUsingMap;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
u8* copyFlag = entry->copyFlag; u8* limbCopyMap = task->limbCopyMap;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++, dst++, src++) { for (i = 0; i < task->vecCount; i++, dest++, src++) {
if (*copyFlag++) { if (*limbCopyMap++) {
*dst = *src; *dest = *src;
} }
} }
} }
} }
/** /**
* If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is false * Copy all data from the `src` frame table to the `dest` table according to the inverted copy map.
*/ */
void AnimationContext_CopyFalse(PlayState* play, AnimationEntryData* data) { void AnimTask_CopyUsingMapInverted(PlayState* play, AnimTaskData* data) {
AnimEntryCopyFalse* entry = &data->copy0; AnimTaskCopyUsingMapInverted* task = &data->copyUsingMapInverted;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
u8* copyFlag = entry->copyFlag; u8* limbCopyMap = task->limbCopyMap;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++, dst++, src++) { for (i = 0; i < task->vecCount; i++, dest++, src++) {
if (!(*copyFlag++)) { if (!(*limbCopyMap++)) {
*dst = *src; *dest = *src;
} }
} }
} }
} }
/** /**
* Moves an actor according to the translation of its root limb * Move an actor according to the translation of its root limb for the current animation frame.
*/ */
void AnimationContext_MoveActor(PlayState* play, AnimationEntryData* data) { void AnimTask_ActorMove(PlayState* play, AnimTaskData* data) {
AnimEntryMoveActor* entry = &data->move; AnimTaskActorMove* task = &data->actorMove;
Actor* actor = entry->actor; Actor* actor = task->actor;
Vec3f diff; Vec3f diff;
SkelAnime_UpdateTranslation(entry->skelAnime, &diff, actor->shape.rot.y); SkelAnime_UpdateTranslation(task->skelAnime, &diff, actor->shape.rot.y);
actor->world.pos.x += diff.x * actor->scale.x; actor->world.pos.x += diff.x * actor->scale.x;
actor->world.pos.y += diff.y * actor->scale.y * entry->diffScaleY; actor->world.pos.y += diff.y * actor->scale.y * task->diffScaleY;
actor->world.pos.z += diff.z * actor->scale.z; actor->world.pos.z += diff.z * actor->scale.z;
} }
typedef void (*AnimationEntryCallback)(struct PlayState* play, AnimationEntryData* data); typedef void (*AnimTaskFunc)(struct PlayState* play, AnimTaskData* data);
/** /**
* Performs all requests in the animation queue, then resets the queue flags. * Update the AnimTaskQueue, processing all tasks in order.
* Variables related to anim task groups are then reset for the next frame.
*/ */
void AnimationContext_Update(PlayState* play, AnimationContext* animationCtx) { void AnimTaskQueue_Update(PlayState* play, AnimTaskQueue* animTaskQueue) {
static AnimationEntryCallback animFuncs[] = { static AnimTaskFunc animTaskFuncs[] = {
AnimationContext_LoadFrame, AnimationContext_CopyAll, AnimationContext_Interp, AnimTask_LoadPlayerFrame, AnimTask_Copy, AnimTask_Interp, AnimTask_CopyUsingMap,
AnimationContext_CopyTrue, AnimationContext_CopyFalse, AnimationContext_MoveActor, AnimTask_CopyUsingMapInverted, AnimTask_ActorMove,
}; };
AnimationEntry* entry = animationCtx->entries; AnimTask* task = animTaskQueue->tasks;
for (; animationCtx->animationCount != 0; animationCtx->animationCount--) { while (animTaskQueue->count != 0) {
animFuncs[entry->type](play, &entry->data); animTaskFuncs[task->type](play, &task->data);
entry++; task++;
animTaskQueue->count--;
} }
sAnimQueueFlags = 1; sCurAnimTaskGroup = 1 << 0;
sDisableAnimQueueFlags = 0; sDisabledTransformTaskGroups = 0;
} }
/** /**
@ -1125,8 +1172,8 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) {
LinkAnimation_SetUpdateFunction(skelAnime); LinkAnimation_SetUpdateFunction(skelAnime);
} }
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
1.0f - (skelAnime->morphWeight / prevMorphWeight)); 1.0f - (skelAnime->morphWeight / prevMorphWeight));
return 0; return 0;
} }
@ -1135,8 +1182,8 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) {
* jointTable and morphTable * jointTable and morphTable
*/ */
void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) { void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) {
AnimationContext_SetLoadFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount,
skelAnime->jointTable); skelAnime->jointTable);
if (skelAnime->morphWeight != 0) { if (skelAnime->morphWeight != 0) {
f32 updateRate = R_UPDATE_RATE * 0.5f; f32 updateRate = R_UPDATE_RATE * 0.5f;
@ -1144,8 +1191,8 @@ void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) {
if (skelAnime->morphWeight <= 0.0f) { if (skelAnime->morphWeight <= 0.0f) {
skelAnime->morphWeight = 0.0f; skelAnime->morphWeight = 0.0f;
} else { } else {
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
skelAnime->morphWeight); skelAnime->morphWeight);
} }
} }
} }
@ -1212,14 +1259,14 @@ void LinkAnimation_Change(PlayState* play, SkelAnime* skelAnime, LinkAnimationHe
morphFrames = -morphFrames; morphFrames = -morphFrames;
} else { } else {
skelAnime->update.link = LinkAnimation_Morph; skelAnime->update.link = LinkAnimation_Morph;
AnimationContext_SetLoadFrame(play, animation, (s32)startFrame, skelAnime->limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)startFrame, skelAnime->limbCount,
skelAnime->morphTable); skelAnime->morphTable);
} }
skelAnime->morphWeight = 1.0f; skelAnime->morphWeight = 1.0f;
skelAnime->morphRate = 1.0f / morphFrames; skelAnime->morphRate = 1.0f / morphFrames;
} else { } else {
LinkAnimation_SetUpdateFunction(skelAnime); LinkAnimation_SetUpdateFunction(skelAnime);
AnimationContext_SetLoadFrame(play, animation, (s32)startFrame, skelAnime->limbCount, skelAnime->jointTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)startFrame, skelAnime->limbCount, skelAnime->jointTable);
skelAnime->morphWeight = 0.0f; skelAnime->morphWeight = 0.0f;
} }
@ -1270,7 +1317,7 @@ void LinkAnimation_PlayLoopSetSpeed(PlayState* play, SkelAnime* skelAnime, LinkA
* Requests copying jointTable to morphTable * Requests copying jointTable to morphTable
*/ */
void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) { void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) {
AnimationContext_SetCopyAll(play, skelAnime->limbCount, skelAnime->morphTable, skelAnime->jointTable); AnimTaskQueue_AddCopy(play, skelAnime->limbCount, skelAnime->morphTable, skelAnime->jointTable);
} }
/** /**
@ -1278,28 +1325,28 @@ void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) {
* unused * unused
*/ */
void LinkAnimation_CopyMorphToJoint(PlayState* play, SkelAnime* skelAnime) { void LinkAnimation_CopyMorphToJoint(PlayState* play, SkelAnime* skelAnime) {
AnimationContext_SetCopyAll(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable); AnimTaskQueue_AddCopy(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable);
} }
/** /**
* Requests loading frame data from the Link animation into morphTable * Requests loading frame data from the Link animation into morphTable
*/ */
void LinkAnimation_LoadToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { void LinkAnimation_LoadToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) {
AnimationContext_SetLoadFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->morphTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->morphTable);
} }
/** /**
* Requests loading frame data from the Link animation into jointTable * Requests loading frame data from the Link animation into jointTable
*/ */
void LinkAnimation_LoadToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { void LinkAnimation_LoadToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) {
AnimationContext_SetLoadFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->jointTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->jointTable);
} }
/** /**
* Requests interpolating between jointTable and morphTable, placing the result in jointTable * Requests interpolating between jointTable and morphTable, placing the result in jointTable
*/ */
void LinkAnimation_InterpJointMorph(PlayState* play, SkelAnime* skelAnime, f32 weight) { void LinkAnimation_InterpJointMorph(PlayState* play, SkelAnime* skelAnime, f32 weight) {
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, weight); AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, weight);
} }
/** /**
@ -1309,12 +1356,12 @@ void LinkAnimation_BlendToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnima
LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) { LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) {
Vec3s* alignedBlendTable; Vec3s* alignedBlendTable;
AnimationContext_SetLoadFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->jointTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->jointTable);
alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable);
AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight); AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight);
} }
/** /**
@ -1324,12 +1371,12 @@ void LinkAnimation_BlendToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnima
LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) { LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) {
Vec3s* alignedBlendTable; Vec3s* alignedBlendTable;
AnimationContext_SetLoadFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->morphTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->morphTable);
alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable);
AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight); AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight);
} }
/** /**

View file

@ -177,19 +177,19 @@ void DemoEc_UpdateBgFlags(DemoEc* this, PlayState* play) {
void func_8096D594(DemoEc* this, PlayState* play) { void func_8096D594(DemoEc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_8096D5D4(DemoEc* this, PlayState* play) { void func_8096D5D4(DemoEc* this, PlayState* play) {
this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.baseTransl = this->skelAnime.jointTable[0];
this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_8096D64C(DemoEc* this, PlayState* play) { void func_8096D64C(DemoEc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void DemoEc_UpdateEyes(DemoEc* this) { void DemoEc_UpdateEyes(DemoEc* this) {

View file

@ -55,7 +55,7 @@ s32 DemoIk_CheckForCue(PlayState* play, u16 cueId, s32 cueChannel) {
void DemoIk_SetMove(DemoIk* this, PlayState* play) { void DemoIk_SetMove(DemoIk* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_0;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void DemoIk_EndMove(DemoIk* this) { void DemoIk_EndMove(DemoIk* this) {

View file

@ -338,7 +338,7 @@ void func_80A795C8(EnIn* this, PlayState* play) {
void func_80A79690(SkelAnime* skelAnime, EnIn* this, PlayState* play) { void func_80A79690(SkelAnime* skelAnime, EnIn* this, PlayState* play) {
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }

View file

@ -757,7 +757,7 @@ void EnNb_InitDemo6KInConfrontation(EnNb* this, PlayState* play) {
void func_80AB2688(EnNb* this, PlayState* play) { void func_80AB2688(EnNb* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_0;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80AB26C8(EnNb* this) { void func_80AB26C8(EnNb* this) {

View file

@ -392,7 +392,7 @@ s32 EnRu1_UpdateSkelAnime(EnRu1* this) {
void func_80AEB364(EnRu1* this, PlayState* play) { void func_80AEB364(EnRu1* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_0;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80AEB3A4(EnRu1* this, PlayState* play) { void func_80AEB3A4(EnRu1* this, PlayState* play) {
@ -463,7 +463,7 @@ void func_80AEB6E0(EnRu1* this, PlayState* play) {
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }
@ -474,7 +474,7 @@ void func_80AEB738(EnRu1* this, PlayState* play) {
skelAnime->prevTransl = skelAnime->jointTable[0]; skelAnime->prevTransl = skelAnime->jointTable[0];
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }

View file

@ -61,7 +61,7 @@ void func_80862FA8(EnTest* this, PlayState* play);
s32 EnTest_ReactToProjectile(PlayState* play, EnTest* this); s32 EnTest_ReactToProjectile(PlayState* play, EnTest* this);
static u8 sJointCopyFlags[] = { static u8 sUpperBodyLimbCopyMap[] = {
false, // STALFOS_LIMB_NONE false, // STALFOS_LIMB_NONE
false, // STALFOS_LIMB_ROOT false, // STALFOS_LIMB_ROOT
false, // STALFOS_LIMB_UPPERBODY_ROOT false, // STALFOS_LIMB_UPPERBODY_ROOT
@ -1742,15 +1742,15 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
case 1: case 1:
Animation_Change(&this->upperSkelanime, &gStalfosBlockWithShieldAnim, 2.0f, 0.0f, Animation_Change(&this->upperSkelanime, &gStalfosBlockWithShieldAnim, 2.0f, 0.0f,
Animation_GetLastFrame(&gStalfosBlockWithShieldAnim), 2, 2.0f); Animation_GetLastFrame(&gStalfosBlockWithShieldAnim), 2, 2.0f);
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
this->unk_7DE++; this->unk_7DE++;
break; break;
case 2: case 2:
SkelAnime_Update(&this->upperSkelanime); SkelAnime_Update(&this->upperSkelanime);
SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
break; break;
case 3: case 3:
@ -1769,7 +1769,7 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
this->upperSkelanime.jointTable, this->skelAnime.jointTable, this->upperSkelanime.jointTable, this->skelAnime.jointTable,
1.0f - (this->upperSkelanime.morphWeight / oldWeight)); 1.0f - (this->upperSkelanime.morphWeight / oldWeight));
SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
break; break;
} }

View file

@ -255,20 +255,20 @@ void func_80B3C8CC(EnXc* this, PlayState* play) {
if (skelAnime->jointTable[0].y >= skelAnime->baseTransl.y) { if (skelAnime->jointTable[0].y >= skelAnime->baseTransl.y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }
void func_80B3C924(EnXc* this, PlayState* play) { void func_80B3C924(EnXc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80B3C964(EnXc* this, PlayState* play) { void func_80B3C964(EnXc* this, PlayState* play) {
this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.baseTransl = this->skelAnime.jointTable[0];
this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80B3C9DC(EnXc* this) { void func_80B3C9DC(EnXc* this) {

View file

@ -346,7 +346,7 @@ void func_80B4B834(CsCmdActorCue* cue, Vec3f* dest) {
void func_80B4B874(EnZl1* this, PlayState* play) { void func_80B4B874(EnZl1* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_0;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80B4B8B4(EnZl1* this, PlayState* play) { void func_80B4B8B4(EnZl1* this, PlayState* play) {

View file

@ -299,7 +299,7 @@ void EnZl4_UpdateFace(EnZl4* this) {
void EnZl4_SetMove(EnZl4* this, PlayState* play) { void EnZl4_SetMove(EnZl4* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_0;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80B5BB78(EnZl4* this, PlayState* play) { void func_80B5BB78(EnZl4* this, PlayState* play) {

View file

@ -1989,7 +1989,7 @@ void Player_AnimReplaceApplyFlags(PlayState* play, Player* this, s32 flags) {
this->skelAnime.moveFlags = flags & 0xFF; this->skelAnime.moveFlags = flags & 0xFF;
Player_ZeroSpeedXZ(this); Player_ZeroSpeedXZ(this);
AnimationContext_DisableQueue(play); AnimTaskQueue_DisableTransformTasksForGroup(play);
} }
void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags,
@ -3071,8 +3071,8 @@ s32 func_808358F0(Player* this, PlayState* play) {
if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) || if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) ||
(func_808335F4(this) == animSeg)) { (func_808335F4(this) == animSeg)) {
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable); this->skelAnime.jointTable);
} else { } else {
LinkAnimation_Update(play, &this->upperSkelAnime); LinkAnimation_Update(play, &this->upperSkelAnime);
} }
@ -3425,22 +3425,22 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) {
// The functionality contained within this block of code is never used in practice // The functionality contained within this block of code is never used in practice
// because `upperAnimInterpWeight` is always 0. // because `upperAnimInterpWeight` is always 0.
if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) {
AnimationContext_SetCopyFalse(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, AnimTaskQueue_AddCopyUsingMapInverted(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable, sUpperBodyLimbCopyMap); this->skelAnime.jointTable, sUpperBodyLimbCopyMap);
} }
Math_StepToF(&this->upperAnimInterpWeight, 0.0f, 0.25f); Math_StepToF(&this->upperAnimInterpWeight, 0.0f, 0.25f);
AnimationContext_SetInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight); this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight);
} else if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { } else if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) {
// Only copy the upper body animation to the upper body limbs in the main skeleton. // Only copy the upper body animation to the upper body limbs in the main skeleton.
// Doing so allows the main skeleton to play its own animation for the lower body limbs. // Doing so allows the main skeleton to play its own animation for the lower body limbs.
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
} else { } else {
// Copy all of the upper body animation into the whole main skeleton. // Copy all of the upper body animation into the whole main skeleton.
// The upper body has full control of all limbs. // The upper body has full control of all limbs.
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable); this->upperSkelAnime.jointTable);
} }
return true; return true;
@ -4650,7 +4650,7 @@ s32 Player_ActionChange_12(Player* this, PlayState* play) {
this->actor.bgCheckFlags |= BGCHECKFLAG_GROUND; this->actor.bgCheckFlags |= BGCHECKFLAG_GROUND;
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f); LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f);
AnimationContext_DisableQueue(play); AnimTaskQueue_DisableTransformTasksForGroup(play);
this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
@ -8105,10 +8105,10 @@ void Player_Action_80841BA8(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->skelAnime); LinkAnimation_Update(play, &this->skelAnime);
if (Player_HoldsTwoHandedWeapon(this)) { if (Player_HoldsTwoHandedWeapon(this)) {
AnimationContext_SetLoadFrame(play, func_80833338(this), 0, this->skelAnime.limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, func_80833338(this), 0, this->skelAnime.limbCount,
this->skelAnime.morphTable); this->skelAnime.morphTable);
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->skelAnime.morphTable, sUpperBodyLimbCopyMap); this->skelAnime.morphTable, sUpperBodyLimbCopyMap);
} }
Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play); Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play);
@ -9033,7 +9033,7 @@ void Player_Action_8084411C(Player* this, PlayState* play) {
} else if ((this->ledgeClimbType >= PLAYER_LEDGE_CLIMB_2) && (this->yDistToLedge < 150.0f) && } else if ((this->ledgeClimbType >= PLAYER_LEDGE_CLIMB_2) && (this->yDistToLedge < 150.0f) &&
(((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) > (((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) >
(70.0f * this->ageProperties->unk_08))) { (70.0f * this->ageProperties->unk_08))) {
AnimationContext_DisableQueue(play); AnimTaskQueue_DisableTransformTasksForGroup(play);
if (this->stateFlags1 & PLAYER_STATE1_2) { if (this->stateFlags1 & PLAYER_STATE1_2) {
func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG); func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG);
} else { } else {
@ -11345,9 +11345,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
Player_UpdateCamAndSeqModes(play, this); Player_UpdateCamAndSeqModes(play, this);
if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) { if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) {
AnimationContext_SetMoveActor( AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime,
play, &this->actor, &this->skelAnime, (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f
(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f : this->ageProperties->unk_08); : this->ageProperties->unk_08);
} }
Player_UpdateShapeYaw(this, play); Player_UpdateShapeYaw(this, play);
@ -11417,8 +11417,10 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
} }
} }
} }
// Because Player updates early relative to most actors, his animation tasks will belong to group 0.
AnimationContext_SetNextQueue(play); // Task group 1 is set here at the end of Player's update, meaning tasks that get added by other
// actors will be in a different group.
AnimTaskQueue_SetNextGroup(play);
} }
Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos); Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos);
@ -12635,8 +12637,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
LinkAnimation_AnimateFrame(play, &this->skelAnime); LinkAnimation_AnimateFrame(play, &this->skelAnime);
} }
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.morphTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.morphTable, this->skelAnime.jointTable);
this->skelAnime.jointTable);
if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != PLAYER_CSACTION_NONE)) { if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != PLAYER_CSACTION_NONE)) {
if (this->csAction == PLAYER_CSACTION_7) { if (this->csAction == PLAYER_CSACTION_7) {
@ -12674,16 +12675,16 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
func_80832698(this, NA_SE_VO_LI_LASH); func_80832698(this, NA_SE_VO_LI_LASH);
} }
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable); this->upperSkelAnime.jointTable);
} else { } else {
if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) { if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) {
Player_PlaySfx(this, NA_SE_IT_LASH); Player_PlaySfx(this, NA_SE_IT_LASH);
func_80832698(this, NA_SE_VO_LI_LASH); func_80832698(this, NA_SE_VO_LI_LASH);
} }
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
} }
} else { } else {
LinkAnimationHeader* anim = NULL; LinkAnimationHeader* anim = NULL;