diff --git a/k3ex.py b/k3ex.py index 34b62e7..0d0d752 100644 --- a/k3ex.py +++ b/k3ex.py @@ -115,6 +115,8 @@ def write_some_data(context, filepath, doExportEverything): out.write(struct.pack("4f", m.col[c][0], m.col[c][1], m.col[c][2], m.col[c][3])) for b in dabones: out.write(struct.pack("B", dabones.index(b.parent) if b.parent else 255)) + for b in dabones: + out.write(b.name.encode("UTF-8") + b'\x00') for v in vertdict.keys(): out.write(struct.pack("3f", v[0][0], v[0][2], -v[0][1])) diff --git a/src/game.c b/src/game.c index 64aacf5..8abc5ca 100644 --- a/src/game.c +++ b/src/game.c @@ -685,7 +685,7 @@ void game_update() { size_t boneCount = Game.entities.render[ci].cache ? k3MdlGetBoneCount(Game.entities.render[ci].cache) : 0; if(boneCount) { - struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned); + /*struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned); if(!cb) { cb = game_ensurecomponent(Game.entities.render[ci].entity, boned); @@ -741,7 +741,7 @@ void game_update() { glm_decompose(cb->anim.cache.inter[m], cb->bones[m].translation, rot, scaleignore); glm_mat4_quat(cb->anim.cache.inter[m], cb->bones[m].rotation); } - } + }*/ } dGeomID gid = cp->geom; @@ -776,7 +776,7 @@ void game_update() { for(size_t cm = 0; cm < Game.entities.movementCount; cm++) { struct CBoned *cb = game_getcomponent(Game.entities.movement[cm].entity, boned); - if(cb && cb->anim.standard) { + /*if(cb && cb->anim.standard) { struct CPhysics *cp = game_getcomponent(Game.entities.movement[cm].entity, physics); if(cp && cp->geom) { dBodyID bid = dGeomGetBody(cp->geom); @@ -789,7 +789,7 @@ void game_update() { } } } - } + }*/ } for(size_t i = 0; i < Game.conveyorCount; i++) { @@ -876,7 +876,6 @@ void game_update() { vec3 dif; glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif); glm_vec3_scale_as(dif, conveyor->speed * (conveyor->active <= 0 ? -1 : 1), dif); - //printf("set %f %f %f\n", dif[0], dif[1], dif[2]); dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response } } @@ -950,7 +949,7 @@ void game_cleanup() { Game.entities.renderCount = 0; for(size_t i = 0; i < Game.entities.bonedCount; i++) { - free(Game.entities.boned[i].bones); + //free(Game.entities.boned[i].bones); } Game.entities.bonedCount = 0; diff --git a/src/game.h b/src/game.h index d1aad89..3268f22 100644 --- a/src/game.h +++ b/src/game.h @@ -118,14 +118,7 @@ struct CPlayerCtrl { struct CBoned { uint16_t entity; - size_t size; - struct k3AnimationBone *bones; - - struct { - uint16_t id; - struct k3Animator cache; - bool standard; - } anim; + struct k3Animator animator; }; #define CONVEYOR_TYPE_LOOP 0 diff --git a/src/loaders.inc b/src/loaders.inc index e0b818a..eefde57 100644 --- a/src/loaders.inc +++ b/src/loaders.inc @@ -33,6 +33,17 @@ static int mdlloader(void *ud, struct ResManRes *res) { uint8_t *boneParents = malloc(header.boneCount); fread(boneParents, 1, header.boneCount, f); + char boneNames[1500] = {}; + size_t boneNamesLen = 0; + for(size_t b = 0; b < header.boneCount; b++) { + while(1) { + fread(boneNames + boneNamesLen, 1, 1, f); + if(boneNames[boneNamesLen++] == 0) { + break; + } + } + } + vec3 *pos = malloc(sizeof(*pos) * header.vertCount); fread(pos, sizeof(vec3), header.vertCount, f); @@ -59,6 +70,8 @@ static int mdlloader(void *ud, struct ResManRes *res) { struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents); + k3MdlSetBoneNames(mdl, boneNames); + k3MdlSetDebugName(mdl, res->name); free(pos); @@ -87,22 +100,19 @@ static int mdlloader(void *ud, struct ResManRes *res) { for(size_t i = 0; i < header.animCount; i++) { struct { uint16_t id; - uint16_t frames; + uint16_t frameCount; uint16_t fps; uint16_t zero; } info; fread(&info, sizeof(info), 1, f); - struct k3Animation *anim = malloc(sizeof(*anim)); - anim->frames = _mm_malloc(sizeof(*anim->frames) * info.frames * header.boneCount, 16); - anim->boneParents = boneParents; - anim->invBind = invBind; + struct k3AnimationFountain *anim = _mm_malloc(sizeof(*anim) + sizeof(*anim->frames) * info.frameCount * header.boneCount, 16); anim->id = info.id; anim->fps = info.fps; - anim->frameCount = info.frames; - anim->boneCount = header.boneCount; + anim->frameCount = info.frameCount; + anim->bones = header.boneCount; - fread(anim->frames, sizeof(*anim->frames), info.frames * header.boneCount, f); + fread(anim->frames, sizeof(*anim->frames), info.frameCount * header.boneCount, f); k3MdlAddAnim(mdl, anim); } diff --git a/src/luaapi.c b/src/luaapi.c index 74db793..b91346a 100644 --- a/src/luaapi.c +++ b/src/luaapi.c @@ -183,15 +183,6 @@ struct mixitem { int type; }; -struct Animator { - struct k3Mdl *mdl; - struct k3Animator animator; - struct k3AnimationBone *bones; - - bool playing; - double playStartTime; -}; - static int game_addentity(lua_State *L) { lua_Integer li; int i; @@ -347,7 +338,7 @@ static int game_addentity(lua_State *L) { setstrstatic("mdl", c.mdl, sizeof(c.mdl)); - //c.animator.base = NULL; + c.cache = k3MdlCopySubs((struct k3Mdl*) resman_ref(RESMAN_MODEL, c.mdl)); game_addcomponent(render, &c); } @@ -380,76 +371,7 @@ static int game_addentity(lua_State *L) { c.entity = id; - lua_getfield(L, -1, "size"); - if(lua_isnil(L, -1)) { - lua_pop(L, 1); - lua_getfield(L, -1, "bones"); - c.size = lua_isnil(L, -1) ? 0 : luaL_len(L, -1); - } else { - c.size = lua_tointeger(L, -1); - lua_pop(L, 1); - lua_getfield(L, -1, "bones"); - } - - c.bones = _mm_malloc(sizeof(*c.bones) * c.size, 16); - - if(lua_isnil(L, -1)) { - glm_quat_identity_array((versor*) c.bones, c.size * 2); - } else { - for(size_t i = 0; i < c.size; i++) { - lua_rawgeti(L, -1, i + 1); // bone - - if(lua_isnil(L, -1)) { - c.bones[i].translation[0] = 0; - c.bones[i].translation[1] = 0; - c.bones[i].translation[2] = 0; - c.bones[i].translation[3] = 1; - - c.bones[i].rotation[0] = 0; - c.bones[i].rotation[1] = 0; - c.bones[i].rotation[2] = 0; - c.bones[i].rotation[3] = 1; - } else { - lua_rawgeti(L, -1, 1); // translation - lua_rawgeti(L, -1, 1); // x - lua_rawgeti(L, -2, 2); // y - lua_rawgeti(L, -3, 3); // z - lua_rawgeti(L, -4, 4); // w - c.bones[i].translation[0] = lua_tonumber(L, -4); - c.bones[i].translation[1] = lua_tonumber(L, -3); - c.bones[i].translation[2] = lua_tonumber(L, -2); - c.bones[i].translation[3] = lua_tonumber(L, -1); - lua_pop(L, 5); - - lua_rawgeti(L, -1, 2); // rotation - lua_rawgeti(L, -1, 1); // x - lua_rawgeti(L, -2, 2); // y - lua_rawgeti(L, -3, 3); // z - lua_rawgeti(L, -4, 4); // w - c.bones[i].rotation[0] = lua_tonumber(L, -4); - c.bones[i].rotation[1] = lua_tonumber(L, -3); - c.bones[i].rotation[2] = lua_tonumber(L, -2); - c.bones[i].rotation[3] = lua_tonumber(L, -1); - lua_pop(L, 5); - } - - lua_pop(L, 1); - } - } - - lua_pop(L, 1); - - lua_getfield(L, -1, "anim"); - if(lua_istable(L, -1)) { - lua_getfield(L, -1, "id"); - c.anim.id = lua_tointeger(L, -1); - lua_pop(L, 1); - - lua_getfield(L, -1, "standard"); - c.anim.standard = lua_toboolean(L, -1); - lua_pop(L, 1); - } - lua_pop(L, 1); + k3AnimatorInit(&c.animator, game_getcomponent(id, render)->cache); game_addcomponent(boned, &c); } @@ -912,26 +834,15 @@ static int game_batch(lua_State *L) { struct k3AnimationBone *bones = NULL; - if(lua_gettop(L) >= 4) { - struct Animator *anim = lua_touserdata(L, 4); - - if(anim->playing) { - k3AnimatorSet(&anim->animator, glfwGetTime() - anim->playStartTime); - } - - bones = anim->bones; - - size_t boneCount = k3MdlGetBoneCount(anim->mdl); - - for(size_t m = 0; m < boneCount; m++) { - vec3 scaleignore; - mat4 rot; - glm_decompose(anim->animator.inter[m], bones[m].translation, rot, scaleignore); - glm_mat4_quat(anim->animator.inter[m], bones[m].rotation); + if(lua_type(L, 4) == LUA_TUSERDATA) { + struct k3Animator *animator = *(void**) lua_touserdata(L, 4); + if(animator->playing) { + k3AnimatorSet(animator, glfwGetTime() - animator->playStartTime); } + bones = animator->bones; } - if(lua_gettop(L) >= 3) { + if(lua_type(L, 3) == LUA_TTABLE) { mat4 anchor; for(int i = 0; i < 16; i++) { lua_rawgeti(L, 3, i + 1); @@ -1084,8 +995,8 @@ static int game_cphysics_get(lua_State *L) { } else if(!strcmp(k, "vel")) { lua_newtable(L); - dBodyID bid = dGeomGetBody(c->geom); - if(bid) { + dBodyID bid; + if(c->geom && (bid = dGeomGetBody(c->geom))) { const float *v = dBodyGetLinearVel(bid); lua_pushnumber(L, v[0]); @@ -1196,7 +1107,7 @@ static int game_cboned_get(lua_State *L) { const char *k = lua_tostring(L, 2); - if(!strcmp(k, "bones")) { + /*if(!strcmp(k, "bones")) { lua_newtable(L); for(size_t i = 0; i < c->size; i++) { @@ -1231,6 +1142,13 @@ static int game_cboned_get(lua_State *L) { *c2 = c; luaL_setmetatable(L, "k3cbonedanim"); + return 1; + }*/ + + if(!strcmp(k, "animator")) { + *(void**) lua_newuserdata(L, sizeof(struct k3Animator*)) = &c->animator; + luaL_setmetatable(L, "k4animatorptr"); + return 1; } @@ -1242,7 +1160,7 @@ static int game_cboned_set(lua_State *L) { const char *k = lua_tostring(L, 2); - if(!strcmp(k, "bones")) { + /*if(!strcmp(k, "bones")) { size_t newlen = luaL_len(L, 3); if(newlen != c->size) { @@ -1276,7 +1194,7 @@ static int game_cboned_set(lua_State *L) { lua_pop(L, 1); } - } + }*/ return 0; } @@ -1284,14 +1202,14 @@ static int game_cboned_set(lua_State *L) { static int game_cbonedanim_set(lua_State *L) { struct CBoned *c = *(struct CBoned**) lua_touserdata(L, 1); - const char *k = lua_tostring(L, 2); + /*const char *k = lua_tostring(L, 2); if(!strcmp(k, "id")) { c->anim.id = lua_tointeger(L, 3); - c->anim.cache.base = NULL; + //c->anim.cache.base = NULL; } else if(!strcmp(k, "standard")) { c->anim.standard = lua_toboolean(L, 3); - } + }*/ return 0; } @@ -1413,13 +1331,47 @@ static int game_k3mdl_addmesh(lua_State *L) { k3MdlAddMesh(mdl, &mat, start, count); } +static int game_k3mdl_query_weights(lua_State *L) { + struct k3Mdl *mdl = *(struct k3Mdl**) lua_touserdata(L, 1); + + int qbone = k3MdlGetBoneFromName(mdl, lua_tostring(L, 2)); + if(qbone < 0) { + return 0; + } + + size_t bones = k3MdlGetBoneCount(mdl); + + float w[bones]; + memset(w, 0, sizeof(*w) * bones); + + k3MdlQueryWeights(mdl, qbone, w); + + // Inclusive + if(lua_toboolean(L, 3)) { + w[qbone] = 1.0f; + } + + lua_newtable(L); + for(size_t b = 0; b < bones; b++) { + // Invert + if(lua_toboolean(L, 4)) { + w[b] = 1.0f - w[b]; + } + + lua_pushnumber(L, w[b]); + lua_rawseti(L, -2, b + 1); + } + + return 1; +} + static int game_k3mdl_get(lua_State *L) { struct k3Mdl *mdl = *(struct k3Mdl**) lua_touserdata(L, 1); - size_t count; - struct k3Mesh *meshes = k3MdlGetMeshes(mdl, &count); - if(lua_type(L, 2) == LUA_TNUMBER) { + size_t count; + struct k3Mesh *meshes = k3MdlGetMeshes(mdl, &count); + lua_Integer i = lua_tointeger(L, 2); if(i >= 1 && i <= count) { struct k3Mat **m = lua_newuserdata(L, sizeof(*m)); @@ -1428,8 +1380,14 @@ static int game_k3mdl_get(lua_State *L) { } else { lua_pushnil(L); } - } else if(!strcmp(lua_tostring(L, 2), "addmesh")) { - lua_pushcfunction(L, game_k3mdl_addmesh); + } else { + const char *key = lua_tostring(L, 2); + + if(!strcmp(key, "addmesh")) { + lua_pushcfunction(L, game_k3mdl_addmesh); + } else if(!strcmp(key, "query_weights")) { + lua_pushcfunction(L, game_k3mdl_query_weights); + } } return 1; @@ -2687,55 +2645,169 @@ static int dagame_kill(lua_State *L) { } static int dagame_animator(lua_State *L) { - struct Animator *this = lua_newuserdata(L, sizeof(*this)); + struct k3Animator *this = (*(void**) lua_newuserdata(L, sizeof(void*)) = calloc(1, sizeof(struct k3Animator))); - this->mdl = *(struct k3Mdl**) lua_touserdata(L, 1); - memset(&this->animator, 0, sizeof(this->animator)); - - size_t boneCount = k3MdlGetBoneCount(this->mdl); - this->bones = _mm_malloc(boneCount * sizeof(*this->bones), 16); - for(size_t b = 0; b < boneCount; b++) { - this->bones[b].translation[0] = 0; - this->bones[b].translation[1] = 0; - this->bones[b].translation[2] = 0; - this->bones[b].translation[3] = 1; - - this->bones[b].rotation[0] = 0; - this->bones[b].rotation[1] = 0; - this->bones[b].rotation[2] = 0; - this->bones[b].rotation[3] = 1; - } + k3AnimatorInit(this, *(struct k3Mdl**) lua_touserdata(L, 1)); luaL_setmetatable(L, "k4animator"); return 1; } +static struct k3Animation *parse_animation_table(struct k3Animator *this) { + enum k3AnimationOp op; + + lua_getfield(L, -1, "type"); + if(!strcmp(lua_tostring(L, -1), "base")) { + lua_pop(L, 1); + op = k3_ANIM_BASIC; + } else if(!strcmp(lua_tostring(L, -1), "blend")) { + lua_pop(L, 1); + op = k3_ANIM_BLEND; + } else if(!strcmp(lua_tostring(L, -1), "add")) { + lua_pop(L, 1); + op = k3_ANIM_ADD; + } else { + lua_pop(L, 1); + return NULL; + } + + if(op == k3_ANIM_BASIC) { + lua_getfield(L, -1, "id"); + size_t idx = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "loop"); + bool loop = lua_toboolean(L, -1); + lua_pop(L, 1); + + struct k3AnimationBasic *b = calloc(1, sizeof(*b)); + b->op = op; + b->bones = k3MdlGetBoneCount(this->mdl); + b->fountain = k3MdlGetAnim(this->mdl, idx); + b->loop = loop; + + if(!b->fountain) { + k3Log(k3_ERR, "Base %lu does not exist", idx); + } + + return (struct k3Animation*) b; + } else if(op == k3_ANIM_BLEND) { + struct k3AnimationBlend *b = calloc(1, sizeof(*b)); + b->op = op; + b->bones = k3MdlGetBoneCount(this->mdl); + + lua_len(L, -1); + b->children = lua_tointeger(L, -1); + lua_pop(L, 1); + + b->subs = calloc(b->children, sizeof(*b->subs)); + b->weights = calloc(b->children * b->bones, sizeof(*b->weights)); + b->offsets = calloc(b->children, sizeof(*b->offsets)); + b->speeds = calloc(b->children, sizeof(*b->speeds)); + + for(size_t c = 0; c < b->children; c++) { + lua_geti(L, -1, c + 1); + lua_getfield(L, -1, "anim"); + b->subs[c] = parse_animation_table(this); + if(!b->subs[c]) { + k3Log(k3_WARN, "Invalid child %lu in animation blend", c); + } + lua_pop(L, 1); + lua_getfield(L, -1, "w"); + if(lua_type(L, -1) == LUA_TNUMBER) { + float f = lua_tonumber(L, -1); + for(size_t i = 0; i < b->bones; i++) { + b->weights[c * b->bones + i] = f; + } + } else if(lua_type(L, -1) == LUA_TTABLE) { + for(size_t i = 0; i < b->bones; i++) { + lua_geti(L, -1, i + 1); + b->weights[c * b->bones + i] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + } else { + k3Log(k3_WARN, "Invalid weights in for child %lu", c); + } + lua_pop(L, 1); + lua_getfield(L, -1, "speed"); + if(lua_type(L, -1) == LUA_TNUMBER) { + b->speeds[c] = lua_tonumber(L, -1); + } else { + b->speeds[c] = 1; + } + lua_pop(L, 1); + lua_getfield(L, -1, "offset"); + if(lua_type(L, -1) == LUA_TNUMBER) { + b->offsets[c] = lua_tonumber(L, -1); + } + lua_pop(L, 1); + lua_pop(L, 1); + } + + return (struct k3Animation*) b; + } else if(op == k3_ANIM_ADD) { + struct k3AnimationAdd *a = calloc(1, sizeof(*a)); + a->op = op; + a->bones = k3MdlGetBoneCount(this->mdl); + + lua_geti(L, -1, 1); + a->sub1 = parse_animation_table(this); + lua_pop(L, 1); + + lua_geti(L, -1, 2); + a->sub2 = parse_animation_table(this); + lua_pop(L, 1); + + lua_getfield(L, -1, "scale"); + if(lua_type(L, -1) == LUA_TNUMBER) { + a->scale = lua_tonumber(L, -1); + } else { + a->scale = 1; + } + lua_pop(L, 1); + + return (struct k3Animation*) a; + } + + return NULL; +} + static int dagame_animator_set(lua_State *L) { - struct Animator *this = lua_touserdata(L, 1); + struct k3Animator *this = *(void**) lua_touserdata(L, 1); - size_t animIdx = lua_tointeger(L, 2); - - this->animator.base = k3MdlGetAnim(this->mdl, animIdx); - this->animator.loop = false; + k3AnimationFree(this->anim); + this->anim = parse_animation_table(this); this->playStartTime = glfwGetTime(); - k3AnimatorSet(&this->animator, 0); + k3AnimatorSet(this, 0); lua_pushvalue(L, 1); - return 1; } static int dagame_animator_play(lua_State *L) { - struct Animator *this = lua_touserdata(L, 1); + struct k3Animator *this = *(void**) lua_touserdata(L, 1); this->playing = true; this->playStartTime = glfwGetTime(); + + lua_pushvalue(L, 1); + return 1; +} + +static int dagame_animator_get(lua_State *L) { + struct k3Animator *this = *(void**) lua_touserdata(L, 1); + + *(void**) lua_newuserdata(L, sizeof(void*)) = this->anim; + this->anim->ref++; + luaL_setmetatable(L, "k3animation"); + + return 1; } static int dagame_animator_index(lua_State *L) { - struct Animator *this = lua_touserdata(L, 1); + struct k3Animator *this = *(void**) lua_touserdata(L, 1); const char *key = lua_tostring(L, 2); @@ -2745,11 +2817,49 @@ static int dagame_animator_index(lua_State *L) { } else if(!strcmp(key, "play")) { lua_pushcfunction(L, dagame_animator_play); return 1; - } else if(!strcmp(key, "time")) { - lua_pushnumber(L, this->animator.time); + } else if(!strcmp(key, "get")) { + lua_pushcfunction(L, dagame_animator_get); return 1; - } else if(!strcmp(key, "loop")) { - lua_pushboolean(L, this->animator.loop); + } else if(!strcmp(key, "time")) { + lua_pushnumber(L, this->time); + return 1; + } else if(!strcmp(key, "model")) { + *(struct k3Mdl**) lua_newuserdata(L, sizeof(void*)) = this->mdl; + luaL_setmetatable(L, "k3mdl"); + + return 1; + } else if(!strcmp(key, "bones")) { + size_t bones = k3MdlGetBoneCount(this->mdl); + + lua_newtable(L); + for(size_t i = 0; i < bones; i++) { + lua_newtable(L); + + lua_newtable(L); + lua_pushnumber(L, this->bones[i].translation[0]); + lua_pushnumber(L, this->bones[i].translation[1]); + lua_pushnumber(L, this->bones[i].translation[2]); + lua_pushnumber(L, this->bones[i].translation[3]); + lua_rawseti(L, -5, 4); + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + lua_setfield(L, -2, "translation"); + + lua_newtable(L); + lua_pushnumber(L, this->bones[i].rotation[0]); + lua_pushnumber(L, this->bones[i].rotation[1]); + lua_pushnumber(L, this->bones[i].rotation[2]); + lua_pushnumber(L, this->bones[i].rotation[3]); + lua_rawseti(L, -5, 4); + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + lua_setfield(L, -2, "rotation"); + + lua_rawseti(L, -2, i + 1); + } + return 1; } @@ -2757,14 +2867,197 @@ static int dagame_animator_index(lua_State *L) { } static int dagame_animator_newindex(lua_State *L) { - struct Animator *this = lua_touserdata(L, 1); + struct k3Animator *this = *(void**) lua_touserdata(L, 1); const char *key = lua_tostring(L, 2); if(!strcmp(key, "time")) { - k3AnimatorSet(&this->animator, lua_tonumber(L, 3)); + k3AnimatorSet(this, lua_tonumber(L, 3)); } else if(!strcmp(key, "loop")) { - this->animator.loop = lua_toboolean(L, 3); + //this->animator.loop = lua_toboolean(L, 3); + } else if(!strcmp(key, "bones")) { + size_t bones = k3MdlGetBoneCount(this->mdl); + + for(size_t i = 0; i < bones; i++) { + lua_rawgeti(L, 3, i + 1); + + lua_getfield(L, -1, "translation"); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + lua_rawgeti(L, -4, 4); + this->bones[i].translation[0] = lua_tonumber(L, -4); + this->bones[i].translation[1] = lua_tonumber(L, -3); + this->bones[i].translation[2] = lua_tonumber(L, -2); + this->bones[i].translation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_getfield(L, -1, "rotation"); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + lua_rawgeti(L, -4, 4); + this->bones[i].rotation[0] = lua_tonumber(L, -4); + this->bones[i].rotation[1] = lua_tonumber(L, -3); + this->bones[i].rotation[2] = lua_tonumber(L, -2); + this->bones[i].rotation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_pop(L, 1); + } + } + + return 0; +} + +static int dagame_animator_gc(lua_State *L) { + struct k3Animator *this = *(void**) lua_touserdata(L, 1); + + k3AnimationFree(this->anim); + free(this); + + return 0; +} + +struct AnimBlendSub { + struct k3AnimationBlend *blend; + size_t c; +}; + +static int dagame_animation_index(lua_State *L) { + struct k3Animation *anim = *(void**) lua_touserdata(L, 1); + + const char *key = NULL; + size_t keyi = 0; + + if(lua_type(L, 2) == LUA_TNUMBER) { + keyi = lua_tointeger(L, 2); + } else { + key = lua_tostring(L, 2); + } + + if(key && !strcmp(key, "type")) { + + switch(anim->op) { + case k3_ANIM_BASIC: + lua_pushstring(L, "base"); + break; + case k3_ANIM_BLEND: + lua_pushstring(L, "blend"); + break; + case k3_ANIM_ADD: + lua_pushstring(L, "add"); + break; + default: + lua_pushnil(L); + break; + } + + return 1; + + } + + if(anim->op == k3_ANIM_BASIC) { + struct k3AnimationBasic *basic = (void*) anim; + + if(key && !strcmp(key, "loop")) { + lua_pushboolean(L, basic->loop); + return 1; + } + } else if(anim->op == k3_ANIM_BLEND) { + struct k3AnimationBlend *blend = (void*) anim; + + if(keyi == 0 || keyi > blend->children) { + lua_pushnil(L); + } else { + struct AnimBlendSub *i = lua_newuserdata(L, sizeof(*i)); + i->blend = blend; + i->blend->ref++; + i->c = keyi; + luaL_setmetatable(L, "k3animationblendsub"); + } + + return 1; + } else if(anim->op == k3_ANIM_ADD) { + struct k3AnimationAdd *add = (void*) anim; + + if(key && !strcmp(key, "scale")) { + lua_pushnumber(L, add->scale); + } else if(keyi == 1 || keyi == 2) { + struct k3Animation** s = lua_newuserdata(L, sizeof(*s)); + *s = keyi == 1 ? add->sub1 : add->sub2; + (*s)->ref++; + luaL_setmetatable(L, "k3animation"); + } + + return 1; + } + + return 0; +} + +static int dagame_animation_gc(lua_State *L) { + struct k3Animation *anim = *(void**) lua_touserdata(L, 1); + + k3AnimationFree(anim); + + return 0; +} + +static int dagame_animationblendsub_index(lua_State *L) { + struct AnimBlendSub *i = lua_touserdata(L, 1); + + const char *key = lua_tostring(L, 2); + + if(!strcmp(key, "anim")) { + *(void**) lua_newuserdata(L, sizeof(void*)) = i->blend->subs[i->c - 1]; + i->blend->subs[i->c - 1]->ref++; + luaL_setmetatable(L, "k3animation"); + return 1; + } else if(!strcmp(key, "w")) { + lua_newtable(L); + for(size_t b = 0; b < i->blend->bones; b++) { + lua_pushnumber(L, i->blend->weights[i->blend->bones * (i->c - 1) + b]); + lua_rawseti(L, -2, b + 1); + } + return 1; + } else if(!strcmp(key, "speed")) { + lua_pushnumber(L, i->blend->speeds[i->c - 1]); + return 1; + } else if(!strcmp(key, "offset")) { + lua_pushnumber(L, i->blend->offsets[i->c - 1]); + return 1; + } + + return 0; +} + +static int dagame_animationblendsub_newindex(lua_State *L) { + struct AnimBlendSub *i = lua_touserdata(L, 1); + + const char *key = lua_tostring(L, 2); + + if(!strcmp(key, "anim")) { + return luaL_error(L, "Setting anim field is unsupported."); + } else if(!strcmp(key, "w")) { + if(lua_type(L, 3) == LUA_TNUMBER) { + float val = lua_tonumber(L, 3); + for(size_t b = 0; b < i->blend->bones; b++) { + i->blend->weights[i->blend->bones * (i->c - 1) + b] = val; + } + } else if(lua_type(L, 3) == LUA_TTABLE) { + for(size_t b = 0; b < i->blend->bones; b++) { + lua_rawgeti(L, 3, b + 1); + i->blend->weights[i->blend->bones * (i->c - 1) + b] = lua_tonumber(L, -1); + lua_pop(L, 1); + } + } else { + return luaL_error(L, "w field may be either number or table or numbers."); + } + } else if(!strcmp(key, "speed")) { + i->blend->speeds[i->c - 1] = lua_tonumber(L, 3); + } else if(!strcmp(key, "offset")) { + i->blend->offsets[i->c - 1] = lua_tonumber(L, 3); } return 0; @@ -3209,9 +3502,45 @@ void luaapi_init() { lua_pushcfunction(L, dagame_animator_newindex); lua_setfield(L, -2, "__newindex"); + lua_pushcfunction(L, dagame_animator_gc); + lua_setfield(L, -2, "__gc"); + lua_pushboolean(L, 0); lua_setfield(L, -2, "__metatable"); lua_pop(L, 1); + + luaL_newmetatable(L, "k4animatorptr"); + lua_pushcfunction(L, dagame_animator_index); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, dagame_animator_newindex); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3animation"); + lua_pushcfunction(L, dagame_animation_index); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, dagame_animation_gc); + lua_setfield(L, -2, "__gc"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3animationblendsub"); + lua_pushcfunction(L, dagame_animationblendsub_index); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, dagame_animationblendsub_newindex); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, dagame_animation_gc); + lua_setfield(L, -2, "__gc"); + lua_pop(L, 1); } void luaapi_load(const char *name) { diff --git a/src/main.c b/src/main.c index 8a5caa5..7d0bde6 100644 --- a/src/main.c +++ b/src/main.c @@ -590,7 +590,11 @@ int main(int argc_, char **argv_) { if(c->cache) { struct CBoned *b = game_getcomponent(c->entity, boned); - k3Batch(c->cache, transform, b ? b->bones : NULL); + if(b && b->animator.anim) { + k3AnimatorStep(&b->animator, dt); + } + + k3Batch(c->cache, transform, b ? b->animator.bones : NULL); } } diff --git a/src/net_client.c b/src/net_client.c index eca190f..e88dcc1 100644 --- a/src/net_client.c +++ b/src/net_client.c @@ -114,7 +114,7 @@ static void interpret_pkt(ENetPacket *pkt) { c->holding = b_ru16(&b); } if(ctype == CMD_CTYPE_BONED) { struct CBoned *c = game_ensurecomponent(ent, boned); - c->anim.standard = b_ru8(&b); + /*c->anim.standard =*/ b_ru8(&b); } } else if(cmd == CMD_SC_POSUPDATE) { uint16_t lastOurTick = b_ru16(&b); diff --git a/src/net_server.c b/src/net_server.c index 1eec7b3..a347b56 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -121,7 +121,7 @@ static void send_full_state(ENetPeer **peers, size_t peerCount) { b_wu16(&b, c->entity); - b_wu8(&b, c->anim.standard); + b_wu8(&b, 0/*c->anim.standard*/); } if(peers) {