Files
banjo-kazooie/src/core2/skeletalanim.c
2023-03-12 23:11:39 -05:00

278 lines
8.8 KiB
C

#include <ultra64.h>
#include "functions.h"
#include "variables.h"
#include "animation.h"
extern void animationFile_getBoneTransformList(void *, f32, BoneTransformList *);
extern void boneTransformList_interpolate(BoneTransformList *, BoneTransformList *, BoneTransformList *, f32);
extern BoneTransformList *boneTransformList_new(void);
/* .code */
static void skeletalAnim_clearTransition(SkeletalAnimation *self){
if(self->bone_transform != NULL){
boneTransformList_free(self->bone_transform);
self->bone_transform = NULL;
}
if(self->animation_bin != NULL){
assetcache_release(self->animation_bin);
self->animation_bin = NULL;
}
if(self->transition_start != NULL){
boneTransformList_free(self->transition_start);
self->transition_start = NULL;
}
if(self->transition_target != NULL){
boneTransformList_free(self->transition_target);
self->transition_target = NULL;
}
self->transition_duration = 0.0f;
}
static void __perform_callback(SkeletalAnimationCallback* arg0){
if(arg0->arg_count == 0){
((void(*)(void))(arg0->callback_fn))();
}
else if(arg0->arg_count == 1){
((void(*)(s32))(arg0->callback_fn))(arg0->arg);
}
}
void skeletalAnim_clearCallbacks(SkeletalAnimation *self){
if(self->callback_list != NULL){
vector_clear(self->callback_list);
}
}
enum asset_e skeletalAnim_getAnimId(SkeletalAnimation *self){
return self->animation_id;
}
f32 skeletalAnim_getProgress(SkeletalAnimation *self){
return self->progress;
}
void skeletalAnim_getProgressRange(SkeletalAnimation *self, f32 *prev_progress, f32 *progress){
*prev_progress = self->prev_progress;
*progress = self->progress;
}
BoneTransformList *skeletalAnim_getBoneTransformList(SkeletalAnimation *self){
self->unk14 = 0;
if(self->bone_transform == NULL){
self->bone_transform = boneTransformList_new();
}
if(self->unk30 != 0){
self->unk30 = 0;
return self->bone_transform;
}
if(self->animation_id == 0){
return self->bone_transform;
}
if(self->animation_bin == NULL){
self->animation_bin = (AnimationFile *)assetcache_get(self->animation_id);
}
if(0.0f == self->transition_duration){
animationFile_getBoneTransformList(self->animation_bin, self->progress, self->bone_transform);
return self->bone_transform;
}
if(self->transition_target == NULL){
self->transition_target = (BoneTransformList *) boneTransformList_new();
}
animationFile_getBoneTransformList(self->animation_bin, self->progress, self->transition_target);
boneTransformList_interpolate(self->bone_transform, self->transition_start, self->transition_target, self->transition_progress);
return self->bone_transform;
}
s32 skeletalAnim_getLoopCount(SkeletalAnimation *self){
return self->loop_count;
}
void skeletalAnim_setCallback_0(SkeletalAnimation *self, f32 when, GenFunction_0 fn){
SkeletalAnimationCallback *ptr;
if(self->callback_list == NULL){
self->callback_list = vector_new(sizeof(SkeletalAnimationCallback), 8);
}
ptr = (SkeletalAnimationCallback *)vector_pushBackNew(&self->callback_list);
ptr->when = when;
ptr->arg_count = 0;
ptr->callback_fn = fn;
ptr->arg = 0;
}
void skeletalAnim_setCallback_1(SkeletalAnimation *self, f32 when, GenFunction_1 fn, s32 arg){
SkeletalAnimationCallback *ptr;
if(self->callback_list == NULL){
self->callback_list = vector_new(sizeof(SkeletalAnimationCallback), 8);
}
ptr = (SkeletalAnimationCallback *)vector_pushBackNew(&self->callback_list);
ptr->when = when;
ptr->arg_count = 1;
ptr->callback_fn = fn;
ptr->arg = (s32)arg;
}
void skeletalAnim_free(SkeletalAnimation *self){
VLA * temp_a0;
skeletalAnim_clearTransition(self);
temp_a0 = self->callback_list;
if(temp_a0 != NULL){
vector_free(temp_a0);
}
free(self);
}
SkeletalAnimation *skeletalAnim_new(void){
SkeletalAnimation *self;
self = (SkeletalAnimation *)malloc(sizeof(SkeletalAnimation));
self->bone_transform = NULL;
self->animation_bin = NULL;
self->callback_list = 0;
self->unk14 = 0;
self->behavior = SKELETAL_ANIM_1_LOOP;
self->loop_count = 0;
self->animation_id = 0;
self->unk30 = 0;
self->transition_start = NULL;
self->transition_target = NULL;
self->progress = 0.0f;
self->duration = 0.0f;
self->prev_progress = 0.0f;
self->transition_progress = 0.0f;
self->transition_duration = 0.0f;
return self;
}
void skeletalAnim_func_80335918(SkeletalAnimation *self){
self->unk30 = 1;
}
void skeletalAnim_set(SkeletalAnimation *self, enum asset_e anim_id, f32 transistion_duration, f32 duration){
if(self->animation_bin != NULL && anim_id != self->animation_id){
assetcache_release(self->animation_bin);
self->animation_bin = NULL;
}
if(self->callback_list != NULL && anim_id != self->animation_id){
vector_free(self->callback_list);
self->callback_list = NULL;
}
self->progress = 0.0f;
self->duration = duration;
self->loop_count = 0;
self->animation_id = anim_id;
self->prev_progress = 0.0f;
self->transition_progress = 0.0f;
self->transition_duration = transistion_duration;
if(0.0f < transistion_duration){
if(self->bone_transform != NULL ){
BoneTransformList *tmp;
tmp = self->transition_start;
self->transition_start = self->bone_transform;
self->bone_transform = tmp;
if(self->transition_target != 0){
boneTransformList_reset(self->transition_target);
}
} else {
self->transition_duration = 0.0f;
}
}
}
//sets animation, but retains current animation's progress
void skeletalAnim_swap(SkeletalAnimation *self, enum asset_e anim_id, f32 transistion_duration, f32 duration){
f32 sp1C;
sp1C = skeletalAnim_getProgress(self);
skeletalAnim_set(self, anim_id, transistion_duration, duration);
skeletalAnim_setProgress(self, sp1C);
}
void skeletalAnim_setProgress(SkeletalAnimation *self, f32 progress){
self->progress = progress;
}
void skeletalAnim_setDuration(SkeletalAnimation *self, f32 duration){
self->duration = duration;
}
void skeletalAnim_setBehavior(SkeletalAnimation *self, enum skeletal_anim_e behavior){
self->behavior = behavior;
}
void skeletalAnim_update(SkeletalAnimation *self, f32 dt, s32 arg2) {
f32 pad2C;
SkeletalAnimationCallback *begin_ptr;
SkeletalAnimationCallback *end_ptr;
SkeletalAnimationCallback *i_ptr;
if (arg2 == 0) {
if (self->unk14 < 10) {
self->unk14++;
if (self->unk14 == 0xA) {
skeletalAnim_clearTransition(self);
}
}
}
if (self->animation_id != 0) {
self->prev_progress = self->progress;
if ( self->duration > 0.0f) {
if (self->behavior == SKELETAL_ANIM_1_LOOP) { //LOOP
self->progress += dt / self->duration;
while (self->progress >= 1.0f) {
self->progress -= 1.0f;
self->loop_count++;
}
} else if ((self->behavior == SKELETAL_ANIM_2_ONCE) && (self->loop_count == 0)) {
//FORWARD ONCE
self->progress += (dt / self->duration);
if (self->progress >= 1.0f) {
self->progress = 0.99999f;
self->loop_count++;
}
} else if ((self->behavior == SKELETAL_ANIM_3_BACKWARDS) && (self->progress > 0.0f)) {
//BACKWARDS ONCE
self->progress -= (dt / self->duration);
if (self->progress < 0.0f) {
self->progress = 0.0f;
}
}
}
if (self->callback_list != NULL) {
begin_ptr = vector_getBegin(self->callback_list);
end_ptr = vector_getEnd(self->callback_list);
for(i_ptr = begin_ptr; i_ptr < end_ptr; i_ptr++) {
if (((self->prev_progress < i_ptr->when) || (self->progress < self->prev_progress)) && ( i_ptr->when <= self->progress)) {
__perform_callback(i_ptr);
}
}
}
if (self->transition_duration > 0.0f) {
if (self->transition_progress < 1.0f) {
self->transition_progress += dt / self->transition_duration;
if (self->transition_progress >= 1.0f) {
self->transition_progress = 1.0f;
}
} else {
self->transition_duration = 0.0f;
if (self->bone_transform != 0) {
boneTransformList_reset(self->bone_transform);
}
}
}
}
}