From 61730dd89b47ab55532859d91149857f208bd7d2 Mon Sep 17 00:00:00 2001 From: bjorn Date: Fri, 8 Oct 2021 14:25:03 -0700 Subject: [PATCH] ModelData exposes its animations; --- src/api/api.h | 2 + src/api/l_data.c | 14 +++++ src/api/l_data_modelData.c | 113 +++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+) diff --git a/src/api/api.h b/src/api/api.h index e56135eb..732a6fbc 100644 --- a/src/api/api.h +++ b/src/api/api.h @@ -17,6 +17,7 @@ typedef struct { #define ENTRY(s) { sizeof(s) - 1, s } +extern StringEntry lovrAnimationProperty[]; extern StringEntry lovrArcMode[]; extern StringEntry lovrAttributeType[]; extern StringEntry lovrAudioMaterial[]; @@ -49,6 +50,7 @@ extern StringEntry lovrPermission[]; extern StringEntry lovrSampleFormat[]; extern StringEntry lovrShaderType[]; extern StringEntry lovrShapeType[]; +extern StringEntry lovrSmoothMode[]; extern StringEntry lovrStencilAction[]; extern StringEntry lovrTextureFormat[]; extern StringEntry lovrTextureType[]; diff --git a/src/api/l_data.c b/src/api/l_data.c index 1339e769..eea3be6d 100644 --- a/src/api/l_data.c +++ b/src/api/l_data.c @@ -9,6 +9,20 @@ #include #include +StringEntry lovrAnimationProperty[] = { + [PROP_TRANSLATION] = ENTRY("translation"), + [PROP_ROTATION] = ENTRY("rotation"), + [PROP_SCALE] = ENTRY("scale"), + { 0 } +}; + +StringEntry lovrSmoothMode[] = { + [SMOOTH_STEP] = ENTRY("step"), + [SMOOTH_LINEAR] = ENTRY("linear"), + [SMOOTH_CUBIC] = ENTRY("cubic"), + { 0 } +}; + static int l_lovrDataNewBlob(lua_State* L) { size_t size; uint8_t* data = NULL; diff --git a/src/api/l_data_modelData.c b/src/api/l_data_modelData.c index 7ef38919..433e5ff3 100644 --- a/src/api/l_data_modelData.c +++ b/src/api/l_data_modelData.c @@ -44,6 +44,25 @@ static ModelMaterial* luax_checkmaterial(lua_State* L, int index, ModelData* mod } } +static ModelAnimation* luax_checkanimation(lua_State* L, int index, ModelData* model) { + switch (lua_type(L, index)) { + case LUA_TNUMBER: { + uint32_t animation = lua_tointeger(L, index) - 1; + lovrCheck(animation < model->animationCount, "Invalid animation index '%d'", animation + 1); + return &model->animations[animation]; + } + case LUA_TSTRING: { + size_t length; + const char* name = lua_tolstring(L, index, &length); + uint64_t hash = hash64(name, length); + uint64_t entry = map_get(&model->animationMap, hash); + lovrCheck(entry != MAP_NIL, "ModelData has no animation named '%s'", name); + return &model->animations[(uint32_t) entry]; + } + default: return luax_typeerror(L, index, "number or string"), NULL; + } +} + static int l_lovrModelDataGetBlobCount(lua_State* L) { ModelData* model = luax_checktype(L, 1, ModelData); lua_pushinteger(L, model->blobCount); @@ -403,6 +422,91 @@ static int l_lovrModelDataGetMaterialValue(lua_State* L) { return 1; } +static int l_lovrModelDataGetAnimationCount(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + lua_pushinteger(L, model->animationCount); + return 1; +} + +static int l_lovrModelDataGetAnimationName(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + uint32_t index = luaL_checkinteger(L, 2) - 1; + lovrCheck(index < model->animationCount, "Invalid animation index '%d'", index + 1); + lua_pushstring(L, model->animations[index].name); + return 1; +} + +static int l_lovrModelDataGetAnimationDuration(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + lua_pushnumber(L, animation->duration); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelCount(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + lua_pushinteger(L, animation->channelCount); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelNode(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + uint32_t index = luaL_checkinteger(L, 3) - 1; + lovrCheck(index < animation->channelCount, "Invalid channel index '%d'", index + 1); + ModelAnimationChannel* channel = &animation->channels[index]; + lua_pushinteger(L, channel->nodeIndex); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelProperty(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + uint32_t index = luaL_checkinteger(L, 3) - 1; + lovrCheck(index < animation->channelCount, "Invalid channel index '%d'", index + 1); + ModelAnimationChannel* channel = &animation->channels[index]; + luax_pushenum(L, AnimationProperty, channel->property); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelSmoothMode(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + uint32_t index = luaL_checkinteger(L, 3) - 1; + lovrCheck(index < animation->channelCount, "Invalid channel index '%d'", index + 1); + ModelAnimationChannel* channel = &animation->channels[index]; + luax_pushenum(L, SmoothMode, channel->smoothing); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelKeyframeCount(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + uint32_t index = luaL_checkinteger(L, 3) - 1; + lovrCheck(index < animation->channelCount, "Invalid channel index '%d'", index + 1); + ModelAnimationChannel* channel = &animation->channels[index]; + lua_pushinteger(L, channel->keyframeCount); + return 1; +} + +static int l_lovrModelDataGetAnimationChannelKeyframe(lua_State* L) { + ModelData* model = luax_checktype(L, 1, ModelData); + ModelAnimation* animation = luax_checkanimation(L, 2, model); + uint32_t index = luaL_checkinteger(L, 3) - 1; + lovrCheck(index < animation->channelCount, "Invalid channel index '%d'", index + 1); + ModelAnimationChannel* channel = &animation->channels[index]; + uint32_t keyframe = luaL_checkinteger(L, 4) - 1; + lovrCheck(keyframe < channel->keyframeCount, "Invalid keyframe index '%d'", keyframe + 1); + lua_pushnumber(L, channel->times[keyframe]); + size_t counts[] = { [PROP_TRANSLATION] = 3, [PROP_ROTATION] = 4, [PROP_SCALE] = 3 }; + size_t count = counts[channel->property]; + for (uint32_t i = 0; i < count; i++) { + lua_pushnumber(L, channel->data[keyframe * count + i]); + } + return count + 1; +} + static int l_lovrModelDataGetSkinCount(lua_State* L) { ModelData* model = luax_checktype(L, 1, ModelData); lua_pushinteger(L, model->skinCount); @@ -466,6 +570,15 @@ const luaL_Reg lovrModelData[] = { { "getMaterialImage", l_lovrModelDataGetMaterialImage }, { "getMaterialColor", l_lovrModelDataGetMaterialColor }, { "getMaterialValue", l_lovrModelDataGetMaterialValue }, + { "getAnimationCount", l_lovrModelDataGetAnimationCount }, + { "getAnimationName", l_lovrModelDataGetAnimationName }, + { "getAnimationDuration", l_lovrModelDataGetAnimationDuration }, + { "getAnimationChannelCount", l_lovrModelDataGetAnimationChannelCount }, + { "getAnimationChannelNode", l_lovrModelDataGetAnimationChannelNode }, + { "getAnimationChannelProperty", l_lovrModelDataGetAnimationChannelProperty }, + { "getAnimationChannelSmoothMode", l_lovrModelDataGetAnimationChannelSmoothMode }, + { "getAnimationChannelKeyframeCount", l_lovrModelDataGetAnimationChannelKeyframeCount }, + { "getAnimationChannelKeyframe", l_lovrModelDataGetAnimationChannelKeyframe }, { "getSkinCount", l_lovrModelDataGetSkinCount }, { "getSkinJoints", l_lovrModelDataGetSkinJoints }, { "getSkinInverseBindMatrix", l_lovrModelDataGetSkinInverseBindMatrix },