#include #include "luastack.hpp" #include "animqueue.hpp" AnimStep::AnimStep() {} AnimStep::~AnimStep() {} AnimQueue::AnimQueue() { size_limit_ = 10; // Default size limit. steps_.emplace_back(); AnimStep &init = steps_.back(); init.id_ = 0; init.facing_ = 0; init.xyz_ = util::XYZ(0,0,0); init.graphic_ = "nothing"; init.plane_ = "nowhere"; init.bits_ = AnimStep::HAS_EVERYTHING; } void AnimQueue::set_size_limit(int n) { assert(n >= 2); size_limit_ = n; } void AnimQueue::add(int64_t id, lua_State *L, int idx) { LuaSpecial tab(idx); LuaVar value; LuaStack LS(L, value); if (!LS.istable(tab)) { luaL_error(L, "animation spec must be a table"); } AnimStep step = steps_.back(); step.id_ = id; step.bits_ = 0; step.action_ = ""; LS.rawget(value, tab, "action"); if (!LS.isstring(value)) { luaL_error(L, "animation action is not optional and must be a string"); } step.action_ = LS.ckstring(value); LS.rawget(value, tab, "facing"); if (LS.isnumber(value)) { step.facing_ = LS.cknumber(value); step.bits_ |= AnimStep::HAS_FACING; } else if (!LS.isnil(value)) { luaL_error(L, "animation facing must be a number"); } LS.rawget(value, tab, "x"); if (LS.isnumber(value)) { step.xyz_.x = LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation X coordinate must be a number"); } LS.rawget(value, tab, "y"); if (LS.isnumber(value)) { step.xyz_.y = LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation Y coordinate must be a number"); } LS.rawget(value, tab, "z"); if (LS.isnumber(value)) { step.xyz_.z = LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation Z coordinate must be a number"); } LS.rawget(value, tab, "dx"); if (LS.isnumber(value)) { step.xyz_.x += LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation DX offset must be a number"); } LS.rawget(value, tab, "dy"); if (LS.isnumber(value)) { step.xyz_.y += LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation DY offset must be a number"); } LS.rawget(value, tab, "dz"); if (LS.isnumber(value)) { step.xyz_.z += LS.cknumber(value); step.bits_ |= AnimStep::HAS_XYZ; } else if (!LS.isnil(value)) { luaL_error(L, "animation DZ offset must be a number"); } LS.rawget(value, tab, "graphic"); if (LS.isstring(value)) { step.graphic_ = LS.ckstring(value); step.bits_ |= AnimStep::HAS_GRAPHIC; } else if (!LS.isnil(value)) { luaL_error(L, "animation graphic must be a string"); } LS.rawget(value, tab, "plane"); if (LS.isstring(value)) { step.plane_ = LS.ckstring(value); step.bits_ |= AnimStep::HAS_PLANE; } else if (!LS.isnil(value)) { luaL_error(L, "animation plane must be a string"); } steps_.push_back(step); while (int(steps_.size()) > size_limit_) { steps_.pop_front(); } AnimStep &init = steps_.front(); init.id_ = 0; init.action_ = ""; init.bits_ = AnimStep::HAS_EVERYTHING; } void AnimQueue::add(int64_t id, const std::string &action) { AnimStep step = steps_.back(); step.id_ = id; step.action_ = action; step.bits_ = 0; steps_.push_back(step); while (int(steps_.size()) > size_limit_) { steps_.pop_front(); } AnimStep &init = steps_.front(); init.id_ = 0; init.action_ = ""; init.bits_ = AnimStep::HAS_EVERYTHING; } void AnimQueue::set_facing(float f) { AnimStep &last = steps_.back(); last.bits_ |= AnimStep::HAS_FACING; last.facing_ = f; } void AnimQueue::set_xyz(util::XYZ xyz) { AnimStep &last = steps_.back(); last.bits_ |= AnimStep::HAS_XYZ; last.xyz_ = xyz; } void AnimQueue::set_graphic(const std::string &g) { AnimStep &last = steps_.back(); last.bits_ |= AnimStep::HAS_GRAPHIC; last.graphic_ = g; } void AnimQueue::set_plane(const std::string &p) { AnimStep &last = steps_.back(); last.bits_ |= AnimStep::HAS_PLANE; last.plane_ = p; } const std::string &AnimQueue::get_graphic() const { const AnimStep &last = steps_.back(); return last.graphic_; } const std::string &AnimQueue::get_plane() const { const AnimStep &last = steps_.back(); return last.plane_; } const util::XYZ &AnimQueue::get_xyz() const { const AnimStep &last = steps_.back(); return last.xyz_; } LuaDefine(unittests_animqueue, "c") { // Check initial state. AnimQueue aq; aq.set_size_limit(3); LuaAssert(L, aq.size() == 1); const AnimStep *st = &aq.nth(0); LuaAssert(L, st->id() == 0); LuaAssert(L, st->action() == ""); LuaAssert(L, st->bits() == AnimStep::HAS_EVERYTHING); LuaAssert(L, st->facing() == 0.0); LuaAssert(L, st->xyz() == util::XYZ(0,0,0)); LuaAssert(L, st->graphic() == "nothing"); LuaAssert(L, st->plane() == "nowhere"); // Add a step. aq.add(12345, "walk"); LuaAssert(L, aq.size() == 2); st = &aq.nth(1); LuaAssert(L, st->id() == 12345); LuaAssert(L, st->action() == "walk"); LuaAssert(L, st->bits() == 0); LuaAssert(L, st->facing() == 0.0); LuaAssert(L, st->xyz() == util::XYZ(0,0,0)); LuaAssert(L, st->graphic() == "nothing"); LuaAssert(L, st->plane() == "nowhere"); // Test the setters. aq.set_facing(180); LuaAssert(L, st->facing() == 180); LuaAssert(L, st->bits() == AnimStep::HAS_FACING); aq.set_xyz(util::XYZ(3,4,5)); LuaAssert(L, st->xyz() == util::XYZ(3, 4, 5)); LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ)); aq.set_plane("somewhere"); LuaAssert(L, st->plane() == "somewhere"); LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE)); aq.set_graphic("something"); LuaAssert(L, st->graphic() == "something"); LuaAssert(L, st->bits() == (AnimStep::HAS_FACING | AnimStep::HAS_XYZ | AnimStep::HAS_PLANE | AnimStep::HAS_GRAPHIC)); // Exceed the length limit, dropping first element. aq.add(12346, "walk"); aq.add(12347, "walk"); LuaAssert(L, aq.size() == 3); LuaAssert(L, aq.nth(0).id() == 0); LuaAssert(L, aq.nth(0).action() == ""); LuaAssert(L, aq.nth(0).bits() == AnimStep::HAS_EVERYTHING); LuaAssert(L, aq.nth(1).id() == 12346); LuaAssert(L, aq.nth(2).id() == 12347); return 0; }