Can now pass tokens as values in animation steps
This commit is contained in:
@@ -55,33 +55,31 @@ static void parse_value(std::string_view vstr, AnimValue *v) {
|
||||
}
|
||||
|
||||
|
||||
static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val, LuaSlot tmp) {
|
||||
static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val) {
|
||||
AnimValue result;
|
||||
auto tboolean = LS.tryboolean(val);
|
||||
if (tboolean) {
|
||||
result.set_boolean(*tboolean);
|
||||
return result;
|
||||
int type = LS.type(val);
|
||||
switch (type) {
|
||||
case LUA_TBOOLEAN: {
|
||||
auto tbool = LS.tryboolean(val);
|
||||
if (tbool) result.set_boolean(*tbool);
|
||||
}
|
||||
case LUA_TNUMBER: {
|
||||
auto tnum = LS.trynumber(val);
|
||||
if (tnum) result.set_number(*tnum);
|
||||
}
|
||||
case LUA_TSTRING: {
|
||||
auto tstr = LS.trystringview(val);
|
||||
if (tstr) result.set_string(*tstr);
|
||||
}
|
||||
case LUA_TTABLE: {
|
||||
auto txyz = LS.tryxyz(val);
|
||||
if (txyz) result.set_dxyz(*txyz);
|
||||
}
|
||||
case LUA_TLIGHTUSERDATA: {
|
||||
auto ttoken = LS.trytoken(val);
|
||||
if (ttoken) result.set_token(*ttoken);
|
||||
}
|
||||
}
|
||||
auto tnumber = LS.trynumber(val);
|
||||
if (tnumber) {
|
||||
result.set_number(*tnumber);
|
||||
return result;
|
||||
}
|
||||
auto tstring = LS.trystringview(val);
|
||||
if (tstring) {
|
||||
result.set_string(*tstring);
|
||||
return result;
|
||||
}
|
||||
auto txyz = LS.tryxyz(val);
|
||||
if (txyz) {
|
||||
result.set_dxyz(*txyz);
|
||||
return result;
|
||||
}
|
||||
if (LS.rawequal(val, LuaToken("auto"))) {
|
||||
result.set_auto();
|
||||
return result;
|
||||
}
|
||||
result.set_uninitialized();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -89,26 +87,6 @@ void AnimState::set_persistent(const eng::string &name) {
|
||||
map_[name].persistent = true;
|
||||
}
|
||||
|
||||
void AnimState::set_boolean(const eng::string &name, bool v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_boolean(v);
|
||||
}
|
||||
|
||||
void AnimState::set_number(const eng::string &name, double v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_number(v);
|
||||
}
|
||||
|
||||
void AnimState::set_dxyz(const eng::string &name, const util::DXYZ &v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_dxyz(v);
|
||||
}
|
||||
|
||||
void AnimState::set_string(const eng::string &name, std::string_view v) {
|
||||
AnimValue &value = map_[name];
|
||||
value.set_string(v);
|
||||
}
|
||||
|
||||
void AnimState::print_debug_string(eng::ostringstream &oss) {
|
||||
bool first = true;
|
||||
if (map_.empty()) {
|
||||
@@ -126,11 +104,11 @@ void AnimState::print_debug_string(eng::ostringstream &oss) {
|
||||
}
|
||||
switch (value.type) {
|
||||
case SimpleDynamicTag::UNINITIALIZED: oss << "UNINITIALIZED"; break;
|
||||
case SimpleDynamicTag::AUTO: oss << "AUTO"; break;
|
||||
case SimpleDynamicTag::STRING: oss << value.s; break;
|
||||
case SimpleDynamicTag::TOKEN: oss << "[" << value.s << "]"; break;
|
||||
case SimpleDynamicTag::NUMBER: oss << value.x; break;
|
||||
case SimpleDynamicTag::BOOLEAN: oss << ((value.x == 1.0) ? "true":"false"); break;
|
||||
case SimpleDynamicTag::VECTOR: oss << value.x << "," << value.y << "," << value.z; break;
|
||||
case SimpleDynamicTag::STRING: oss << value.s; break;
|
||||
default: assert(false);
|
||||
}
|
||||
first = false;
|
||||
@@ -230,8 +208,8 @@ eng::string AnimState::add_defaults(const AnimState *other) {
|
||||
|
||||
|
||||
eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent, bool allowauto) {
|
||||
LuaVar key, val, tmp;
|
||||
LuaExtStack LS(LS0.state(), key, val, tmp);
|
||||
LuaVar key, val;
|
||||
LuaExtStack LS(LS0.state(), key, val);
|
||||
util::DXYZ xyz;
|
||||
|
||||
clear();
|
||||
@@ -247,12 +225,12 @@ eng::string AnimState::from_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent,
|
||||
if (!sv::is_lua_id(name)) {
|
||||
return "in animation key-value pairs, key must be a valid lua identifier.";
|
||||
}
|
||||
AnimValue parsedvalue = parse_anim_value(LS, val, tmp);
|
||||
AnimValue parsedvalue = parse_anim_value(LS, val);
|
||||
if (parsedvalue.type == SimpleDynamicTag::UNINITIALIZED) {
|
||||
return "in animation key-value pairs, value must be number, string, boolean, or xyz";
|
||||
return "in animation key-value pairs, value must be string, token, number, boolean, or xyz";
|
||||
}
|
||||
if ((parsedvalue.type == SimpleDynamicTag::AUTO) && !allowauto) {
|
||||
return "in animation key-value pairs, value must not be AUTO here.";
|
||||
if (parsedvalue.is_token("auto") && !allowauto) {
|
||||
return "in animation key-value pairs, value must not be [auto] here.";
|
||||
}
|
||||
AnimValue &mapentry = map_[name];
|
||||
mapentry.copy_value(parsedvalue);
|
||||
@@ -271,7 +249,7 @@ eng::string AnimState::merge(const AnimState &previous, const AnimState &update)
|
||||
const AnimValue &src = pair.second;
|
||||
|
||||
// Handle autocalculation rules.
|
||||
if (src.type == SimpleDynamicTag::AUTO) {
|
||||
if (src.is_token("auto")) {
|
||||
if (name == "facing") {
|
||||
if (!dst.persistent || dst.type != SimpleDynamicTag::NUMBER) {
|
||||
return "Cannot auto-calculate facing because facing has not been specified as a persistent number";
|
||||
@@ -306,12 +284,16 @@ eng::string AnimState::merge(const AnimState &previous, const AnimState &update)
|
||||
}
|
||||
|
||||
|
||||
void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent) {
|
||||
void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool transient, bool persistent) {
|
||||
LuaVar name, val;
|
||||
LuaExtStack LS(LS0.state(), name, val);
|
||||
LS.newtable(tab);
|
||||
for (const auto &pair : map_) {
|
||||
if (pair.second.persistent != persistent) continue;
|
||||
if (pair.second.persistent) {
|
||||
if (!persistent) continue;
|
||||
} else {
|
||||
if (!transient) continue;
|
||||
}
|
||||
LS.set(name, pair.first);
|
||||
const AnimValue &value = pair.second;
|
||||
if (value.type == SimpleDynamicTag::BOOLEAN) {
|
||||
@@ -320,6 +302,8 @@ void AnimState::to_lua(LuaCoreStack &LS0, LuaSlot tab, bool persistent) {
|
||||
LS.set(val, value.x);
|
||||
} else if (value.type == SimpleDynamicTag::STRING) {
|
||||
LS.set(val, std::string_view(value.s));
|
||||
} else if (value.type == SimpleDynamicTag::TOKEN) {
|
||||
LS.set(val, LuaToken(value.s));
|
||||
} else if (value.type == SimpleDynamicTag::VECTOR) {
|
||||
LS.newtable(val);
|
||||
LS.rawset(val, 1, value.x);
|
||||
|
||||
@@ -52,12 +52,7 @@
|
||||
// for all key-value pairs do:
|
||||
// write_string(key)
|
||||
// write_bool(persistent)
|
||||
// write_uint8(type) // T_STRING, T_NUMBER, T_BOOL, or T_XYZ
|
||||
// switch type:
|
||||
// T_STRING: write_string(value)
|
||||
// T_NUMBER: write_double(value)
|
||||
// T_BOOL: write_bool(value)
|
||||
// T_XYZ: write_xyz(value)
|
||||
// write_simple_dynamic(value)
|
||||
//
|
||||
// The encoded string produced by the loop above is called an "encstep".
|
||||
// That's short for "encoded animation step". The encstep has a hash
|
||||
@@ -107,10 +102,19 @@ struct AnimValue : public SimpleDynamicValue {
|
||||
|
||||
AnimValue() { persistent = false; }
|
||||
|
||||
void set_token(LuaToken token) {
|
||||
type = SimpleDynamicTag::TOKEN;
|
||||
s=token.str(); x=y=z=0;
|
||||
}
|
||||
|
||||
void set_dxyz(const util::DXYZ &xyz) {
|
||||
type = SimpleDynamicTag::VECTOR;
|
||||
s.clear(); x = xyz.x; y = xyz.y; z = xyz.z;
|
||||
}
|
||||
|
||||
bool is_token(const char *t) const {
|
||||
return (type == SimpleDynamicTag::TOKEN) && (s == t);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -141,10 +145,11 @@ public:
|
||||
// Set a single variable to a value of a specified type.
|
||||
// If the variable isn't present, add it.
|
||||
//
|
||||
void set_boolean(const eng::string &name, bool v);
|
||||
void set_number(const eng::string &name, double v);
|
||||
void set_dxyz(const eng::string &name, const util::DXYZ &value);
|
||||
void set_string(const eng::string &name, std::string_view value);
|
||||
void set_string(const eng::string &name, std::string_view v) { map_[name].set_string(v); }
|
||||
void set_token(const eng::string &name, LuaToken v) { map_[name].set_token(v); }
|
||||
void set_number(const eng::string &name, double v) { map_[name].set_number(v); }
|
||||
void set_boolean(const eng::string &name, bool v) { map_[name].set_boolean(v); }
|
||||
void set_dxyz(const eng::string &name, const util::DXYZ &v) { map_[name].set_dxyz(v); }
|
||||
|
||||
// Print a debug string into the stringstream.
|
||||
//
|
||||
@@ -217,10 +222,10 @@ public:
|
||||
|
||||
// Convert an animstate to a lua table.
|
||||
//
|
||||
// You can either convert the persistent key-value pairs, or the
|
||||
// nonpersistent. So you'll need two lua tables to store both.
|
||||
// You can specify whether you want to include the transient values, the
|
||||
// persistent values, or both.
|
||||
//
|
||||
void to_lua(LuaCoreStack &LS, LuaSlot tab, bool persistent);
|
||||
void to_lua(LuaCoreStack &LS, LuaSlot tab, bool transient, bool persistent);
|
||||
|
||||
// Parse a string, for unit testing.
|
||||
//
|
||||
|
||||
@@ -409,15 +409,14 @@ enum LuaTableType {
|
||||
struct LuaToken {
|
||||
private:
|
||||
// Convert a base36 number into a token. If the base36 number is
|
||||
// not valid, or if it exceeds 64 bits, then return maxint, ie,
|
||||
// the invalid token.
|
||||
// not valid, or if it exceeds 64 bits, then return zero.
|
||||
//
|
||||
static constexpr uint64_t parse(std::string_view str) {
|
||||
uint64_t result = 0;
|
||||
uint64_t maxint = uint64_t(-1);
|
||||
|
||||
// Leading zeros are not allowed.
|
||||
if ((!str.empty()) && (str[0]=='0')) return maxint;
|
||||
if ((!str.empty()) && (str[0]=='0')) return 0;
|
||||
|
||||
for (int i = 0; i < int(str.size()); i++) {
|
||||
char c = str[i];
|
||||
@@ -433,9 +432,9 @@ private:
|
||||
}
|
||||
// Multiply existing number by 36, then add the digit.
|
||||
// We have two checks to prevent integer overflow.
|
||||
if (result > (maxint / 36)) return maxint;
|
||||
if (result > (maxint / 36)) return 0;
|
||||
result *= 36;
|
||||
if (digit > (maxint - result)) return maxint;
|
||||
if (digit > (maxint - result)) return 0;
|
||||
result += digit;
|
||||
}
|
||||
return result;
|
||||
@@ -451,20 +450,21 @@ public:
|
||||
|
||||
// Construct a token from a string.
|
||||
//
|
||||
// If the string is not a valid token, then this initializes the
|
||||
// token to the invalid token.
|
||||
// If the string is not a valid base36 number, then this
|
||||
// initializes the token to the empty token (zero)
|
||||
//
|
||||
LuaToken(std::string_view s) : value(parse(s)) {}
|
||||
LuaToken(const eng::string &s) : value(parse(s)) {}
|
||||
|
||||
// Construct a token from a compile-time constant string.
|
||||
//
|
||||
// It appears that the code below throws an exception if the
|
||||
// string is invalid. But in reality, since this function is
|
||||
// string not parseable. But in reality, since this function is
|
||||
// consteval (evaluated at compile time), the error is
|
||||
// generated during the compilation.
|
||||
//
|
||||
consteval LuaToken(const char *s) : value(parse(s)) {
|
||||
if (is_invalid()) throw "Invalid token";
|
||||
if (empty()) throw "cannot parse token";
|
||||
}
|
||||
|
||||
// Construct a token from an int64.
|
||||
@@ -482,9 +482,9 @@ public:
|
||||
// Assignment operator.
|
||||
void operator =(const LuaToken &other) { value = other.value; }
|
||||
|
||||
// Empty: return true if the token is all zero bytes.
|
||||
// Empty: return true if the token is zero.
|
||||
//
|
||||
bool empty() const { return value == 0; }
|
||||
constexpr bool empty() const { return value == 0; }
|
||||
|
||||
// Compare two tokens for equality.
|
||||
//
|
||||
@@ -494,19 +494,12 @@ public:
|
||||
//
|
||||
void *voidvalue() const { return (void*)value; }
|
||||
|
||||
// Return true if it's the invalid token.
|
||||
//
|
||||
constexpr bool is_invalid() { return value == uint64_t(-1); }
|
||||
|
||||
// Convert the token to a string.
|
||||
//
|
||||
// The conversion to string consists of expressing the value
|
||||
// in base 36. The value 0 is expressed as the empty string.
|
||||
// in base 36.
|
||||
//
|
||||
eng::string str() const;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#include "serializelua.hpp"
|
||||
#include <cmath>
|
||||
|
||||
LuaTokenConstant(tangible_auto, "auto", "");
|
||||
|
||||
static void tangible_getall(LuaCoreStack &LS0, LuaSlot list, const util::IdVector &idv) {
|
||||
LuaVar tangibles, tan;
|
||||
LuaExtStack LS(LS0.state(), tangibles, tan);
|
||||
@@ -73,7 +75,7 @@ LuaDefine(tangible_animfinal, "tan",
|
||||
World *w = World::fetch_global_pointer(L);
|
||||
Tangible *tan = w->tangible_get(LS, tanobj, false);
|
||||
AnimState state = tan->anim_queue_.get_final_everything();
|
||||
state.to_lua(LS, result, true);
|
||||
state.to_lua(LS, result, true, true);
|
||||
return LS.result();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user