File: LuaUtil.cpp

package info (click to toggle)
freespace2 25.0.0~rc11%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 47,232 kB
  • sloc: cpp: 657,500; ansic: 22,305; sh: 293; python: 200; makefile: 198; xml: 181
file content (144 lines) | stat: -rw-r--r-- 3,257 bytes parent folder | download
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