diff --git a/src/api/graphics.c b/src/api/graphics.c index 1bf48ddf..539390a0 100644 --- a/src/api/graphics.c +++ b/src/api/graphics.c @@ -1,5 +1,6 @@ #include "api/lovr.h" #include "graphics/graphics.h" +#include "graphics/animator.h" #include "graphics/material.h" #include "graphics/mesh.h" #include "graphics/model.h" @@ -73,6 +74,7 @@ static void luax_readvertices(lua_State* L, int index, vec_float_t* points) { int l_lovrGraphicsInit(lua_State* L) { lua_newtable(L); luaL_register(L, NULL, lovrGraphics); + luax_registertype(L, "Animator", lovrAnimator); luax_registertype(L, "Font", lovrFont); luax_registertype(L, "Material", lovrMaterial); luax_registertype(L, "Mesh", lovrMesh); @@ -570,6 +572,13 @@ int l_lovrGraphicsPrint(lua_State* L) { // Types +int l_lovrGraphicsNewAnimator(lua_State* L) { + Model* model = luax_checktype(L, 1, Model); + Animator* animator = lovrAnimatorCreate(model->modelData->animationData); + luax_pushtype(L, Animator, animator); + return 1; +} + int l_lovrGraphicsNewFont(lua_State* L) { Blob* blob = NULL; float size; @@ -810,6 +819,7 @@ const luaL_Reg lovrGraphics[] = { { "sphere", l_lovrGraphicsSphere }, { "skybox", l_lovrGraphicsSkybox }, { "print", l_lovrGraphicsPrint }, + { "newAnimator", l_lovrGraphicsNewAnimator }, { "newFont", l_lovrGraphicsNewFont }, { "newMaterial", l_lovrGraphicsNewMaterial }, { "newMesh", l_lovrGraphicsNewMesh }, diff --git a/src/api/lovr.h b/src/api/lovr.h index 7313a811..5ccbe906 100644 --- a/src/api/lovr.h +++ b/src/api/lovr.h @@ -15,6 +15,7 @@ int l_lovrMathInit(lua_State* L); int l_lovrPhysicsInit(lua_State* L); int l_lovrTimerInit(lua_State* L); +extern const luaL_Reg lovrAnimator[]; extern const luaL_Reg lovrAudio[]; extern const luaL_Reg lovrBallJoint[]; extern const luaL_Reg lovrBoxShape[]; diff --git a/src/api/types/animator.c b/src/api/types/animator.c new file mode 100644 index 00000000..4c40c954 --- /dev/null +++ b/src/api/types/animator.c @@ -0,0 +1,13 @@ +#include "api/lovr.h" +#include "graphics/animator.h" + +int l_lovrAnimatorGetAnimationCount(lua_State* L) { + Animator* animator = luax_checktype(L, 1, Animator); + lua_pushnumber(L, lovrAnimatorGetAnimationCount(animator)); + return 1; +} + +const luaL_Reg lovrAnimator[] = { + { "getAnimationCount", l_lovrAnimatorGetAnimationCount }, + { NULL, NULL } +}; diff --git a/src/graphics/animator.c b/src/graphics/animator.c new file mode 100644 index 00000000..7fc6ba2e --- /dev/null +++ b/src/graphics/animator.c @@ -0,0 +1,19 @@ +#include "graphics/animator.h" + +Animator* lovrAnimatorCreate(AnimationData* animationData) { + Animator* animator = lovrAlloc(sizeof(Animator), lovrAnimatorDestroy); + if (!animator) return NULL; + + animator->animationData = animationData; + + return animator; +} + +void lovrAnimatorDestroy(const Ref* ref) { + Animator* animator = containerof(ref, Animator); + free(animator); +} + +int lovrAnimatorGetAnimationCount(Animator* animator) { + return animator->animationData->animations.length; +} diff --git a/src/graphics/animator.h b/src/graphics/animator.h new file mode 100644 index 00000000..65fada8c --- /dev/null +++ b/src/graphics/animator.h @@ -0,0 +1,13 @@ +#include "util.h" +#include "loaders/animation.h" + +#pragma once + +typedef struct { + Ref ref; + AnimationData* animationData; +} Animator; + +Animator* lovrAnimatorCreate(AnimationData* animationData); +void lovrAnimatorDestroy(const Ref* ref); +int lovrAnimatorGetAnimationCount(Animator* animator); diff --git a/src/loaders/animation.c b/src/loaders/animation.c index 212f0f8f..83177e20 100644 --- a/src/loaders/animation.c +++ b/src/loaders/animation.c @@ -5,13 +5,12 @@ AnimationData* lovrAnimationDataCreate(const char* name) { AnimationData* animationData = malloc(sizeof(AnimationData)); if (!animationData) return NULL; - animationData->name = name; - map_init(&animationData->channels); + vec_init(&animationData->animations); return animationData; } void lovrAnimationDataDestroy(AnimationData* animationData) { - map_deinit(&animationData->channels); + vec_deinit(&animationData->animations); free(animationData); } diff --git a/src/loaders/animation.h b/src/loaders/animation.h index e7e961a4..e404c2c1 100644 --- a/src/loaders/animation.h +++ b/src/loaders/animation.h @@ -23,7 +23,13 @@ typedef struct { const char* name; map_channel_t channels; int channelCount; +} Animation; + +typedef vec_t(Animation) vec_animation_t; + +typedef struct { + vec_animation_t animations; } AnimationData; -AnimationData* lovrAnimationDataCreate(const char* name); +AnimationData* lovrAnimationDataCreate(); void lovrAnimationDataDestroy(AnimationData* animationData); diff --git a/src/loaders/model.c b/src/loaders/model.c index 6c58b2a4..30265895 100644 --- a/src/loaders/model.c +++ b/src/loaders/model.c @@ -385,14 +385,16 @@ ModelData* lovrModelDataCreate(Blob* blob) { assimpNodeTraversal(modelData, scene->mRootNode, &nodeIndex); // Animations - modelData->animationCount = scene->mNumAnimations; - modelData->animations = malloc(modelData->animationCount * sizeof(AnimationData*)); - for (int i = 0; i < modelData->animationCount; i++) { + modelData->animationData = lovrAnimationDataCreate(); + for (unsigned int i = 0; i < scene->mNumAnimations; i++) { struct aiAnimation* assimpAnimation = scene->mAnimations[i]; - AnimationData* animationData = lovrAnimationDataCreate(assimpAnimation->mName.data); - animationData->channelCount = assimpAnimation->mNumChannels; - for (int j = 0; j < animationData->channelCount; j++) { + Animation animation; + animation.name = strdup(assimpAnimation->mName.data); + animation.channelCount = assimpAnimation->mNumChannels; + map_init(&animation.channels); + + for (int j = 0; j < animation.channelCount; j++) { struct aiNodeAnim* assimpChannel = assimpAnimation->mChannels[j]; AnimationChannel channel; @@ -428,10 +430,10 @@ ModelData* lovrModelDataCreate(Blob* blob) { vec_push(&channel.scaleKeyframes, keyframe); } - map_set(&animationData->channels, channel.node, channel); + map_set(&animation.channels, channel.node, channel); } - modelData->animations[i] = animationData; + vec_push(&modelData->animationData->animations, animation); } aiReleaseImport(scene); @@ -444,9 +446,7 @@ void lovrModelDataDestroy(ModelData* modelData) { vec_deinit(&modelData->nodes[i].primitives); } - for (int i = 0; i < modelData->animationCount; i++) { - lovrAnimationDataDestroy(modelData->animations[i]); - } + lovrAnimationDataDestroy(modelData->animationData); for (int i = 0; i < modelData->materialCount; i++) { lovrMaterialDataDestroy(modelData->materials[i]); diff --git a/src/loaders/model.h b/src/loaders/model.h index 530743db..49dce681 100644 --- a/src/loaders/model.h +++ b/src/loaders/model.h @@ -47,7 +47,7 @@ typedef struct { ModelPrimitive* primitives; vec_bone_t bones; map_int_t boneMap; - AnimationData** animations; + AnimationData* animationData; MaterialData** materials; ModelVertices vertices; ModelIndices indices;