1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#include "LuaUtil.h"
#include "scripting/api/objs/vecmath.h"
namespace {
const char* mainStateRefName = "_lua_mainthread";
}
namespace luacpp {
namespace util {
const char* getValueName(ValueType type)
{
switch (type) {
case ValueType::NONE:
return "none";
case ValueType::NIL:
return "nil";
case ValueType::BOOLEAN:
return "boolean";
case ValueType::LIGHTUSERDATA:
return "light userdata";
case ValueType::STRING:
return "string";
case ValueType::NUMBER:
return "number";
case ValueType::TABLE:
return "table";
case ValueType::FUNCTION:
return "function";
case ValueType::USERDATA:
return "userdata";
case ValueType::THREAD:
return "thread";
default:
return "unknown";
}
}
void initializeLuaSupportLib(lua_State* L)
{
auto mainThread = lua_pushthread(L);
Assertion(mainThread, "Must be called with the main thread as the parameter!");
lua_setfield(L, LUA_REGISTRYINDEX, mainStateRefName);
}
lua_State* getMainThread(lua_State* L)
{
if (lua_pushthread(L)) {
// State is the main thread, just return that
lua_pop(L, 1);
return L;
}
lua_pushstring(L, mainStateRefName);
lua_rawget(L, LUA_REGISTRYINDEX);
auto state = lua_tothread(L, -1);
// Need to pop both the thread from L and the main thread to return the stack back to neutral
lua_pop(L, 2);
return state;
}
vec3d valueToVec3d(const LuaValue &luaValue)
{
if (luaValue.is(luacpp::ValueType::TABLE))
{
vec3d tablePoint = vmd_zero_vector;
int index = 0;
bool is_array = false;
bool is_table = false;
// we have to go deeper
luacpp::LuaTable childTable;
childTable.setReference(luaValue.getReference());
for (const auto &childEntry : childTable)
{
// note: this is pre-increment
if (index >= 3)
throw LuaException("Vec3d table has more than three entries!");
if (!childEntry.second.is(luacpp::ValueType::NUMBER))
throw LuaException("Value in vec3d table is not a number!");
auto number = static_cast<float>(childEntry.second.getValue<double>());
if (childEntry.first.is(luacpp::ValueType::STRING))
{
is_table = true;
if (is_array)
throw LuaException("Vec3d table has an unexpected format!");
const auto &str = childEntry.first.getValue<SCP_string>();
if (lcase_equal(str, "x"))
tablePoint.xyz.x = number;
else if (lcase_equal(str, "y"))
tablePoint.xyz.y = number;
else if (lcase_equal(str, "z"))
tablePoint.xyz.z = number;
else
throw LuaException("Vec3d table has an entry other than x/X, y/Y, or z/Z!");
}
else
{
is_array = true;
if (is_table)
throw LuaException("Vec3d table has an unexpected format!");
tablePoint.a1d[index] = number;
}
index++;
}
// note: this is post-increment
if (index < 3)
throw LuaException("Vec3d table has fewer than three entries!");
return tablePoint;
}
else if (luaValue.is(luacpp::ValueType::USERDATA))
{
try
{
vec3d v;
luaValue.getValue(scripting::api::l_Vector.Get(&v));
return v;
}
catch (const luacpp::LuaException& /*e*/)
{
throw LuaException("Userdata in vec3d table is not a vector!");
}
}
else
{
throw LuaException("Vec3d value is of an unhandled type!");
}
}
} // namespace util
} // namespace luacpp
|