278 lines
8.8 KiB
C
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|