3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "util/numeric.h"
26 #include "util/string.h"
27 #include "common/c_converter.h"
28 #include "constants.h"
31 #define CHECK_TYPE(index, name, type) do { \
32 int t = lua_type(L, (index)); \
34 throw LuaError(std::string("Invalid ") + (name) + \
35 " (expected " + lua_typename(L, (type)) + \
36 " got " + lua_typename(L, t) + ")."); \
39 #define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER)
40 #define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE)
43 void push_v3f(lua_State *L, v3f p)
46 lua_pushnumber(L, p.X);
47 lua_setfield(L, -2, "x");
48 lua_pushnumber(L, p.Y);
49 lua_setfield(L, -2, "y");
50 lua_pushnumber(L, p.Z);
51 lua_setfield(L, -2, "z");
54 void push_v2f(lua_State *L, v2f p)
57 lua_pushnumber(L, p.X);
58 lua_setfield(L, -2, "x");
59 lua_pushnumber(L, p.Y);
60 lua_setfield(L, -2, "y");
63 v2s16 read_v2s16(lua_State *L, int index)
67 lua_getfield(L, index, "x");
68 p.X = lua_tonumber(L, -1);
70 lua_getfield(L, index, "y");
71 p.Y = lua_tonumber(L, -1);
76 v2s16 check_v2s16(lua_State *L, int index)
80 lua_getfield(L, index, "x");
82 p.X = lua_tonumber(L, -1);
84 lua_getfield(L, index, "y");
86 p.Y = lua_tonumber(L, -1);
91 v2s32 read_v2s32(lua_State *L, int index)
95 lua_getfield(L, index, "x");
96 p.X = lua_tonumber(L, -1);
98 lua_getfield(L, index, "y");
99 p.Y = lua_tonumber(L, -1);
104 v2f read_v2f(lua_State *L, int index)
107 CHECK_POS_TAB(index);
108 lua_getfield(L, index, "x");
109 p.X = lua_tonumber(L, -1);
111 lua_getfield(L, index, "y");
112 p.Y = lua_tonumber(L, -1);
117 v2f check_v2f(lua_State *L, int index)
120 CHECK_POS_TAB(index);
121 lua_getfield(L, index, "x");
122 CHECK_POS_COORD("x");
123 p.X = lua_tonumber(L, -1);
125 lua_getfield(L, index, "y");
126 CHECK_POS_COORD("y");
127 p.Y = lua_tonumber(L, -1);
132 v3f read_v3f(lua_State *L, int index)
135 CHECK_POS_TAB(index);
136 lua_getfield(L, index, "x");
137 pos.X = lua_tonumber(L, -1);
139 lua_getfield(L, index, "y");
140 pos.Y = lua_tonumber(L, -1);
142 lua_getfield(L, index, "z");
143 pos.Z = lua_tonumber(L, -1);
148 v3f check_v3f(lua_State *L, int index)
151 CHECK_POS_TAB(index);
152 lua_getfield(L, index, "x");
153 CHECK_POS_COORD("x");
154 pos.X = lua_tonumber(L, -1);
156 lua_getfield(L, index, "y");
157 CHECK_POS_COORD("y");
158 pos.Y = lua_tonumber(L, -1);
160 lua_getfield(L, index, "z");
161 CHECK_POS_COORD("z");
162 pos.Z = lua_tonumber(L, -1);
167 void push_ARGB8(lua_State *L, video::SColor color)
170 lua_pushnumber(L, color.getAlpha());
171 lua_setfield(L, -2, "a");
172 lua_pushnumber(L, color.getRed());
173 lua_setfield(L, -2, "r");
174 lua_pushnumber(L, color.getGreen());
175 lua_setfield(L, -2, "g");
176 lua_pushnumber(L, color.getBlue());
177 lua_setfield(L, -2, "b");
180 void pushFloatPos(lua_State *L, v3f p)
186 v3f checkFloatPos(lua_State *L, int index)
188 return check_v3f(L, index) * BS;
191 void push_v3s16(lua_State *L, v3s16 p)
194 lua_pushnumber(L, p.X);
195 lua_setfield(L, -2, "x");
196 lua_pushnumber(L, p.Y);
197 lua_setfield(L, -2, "y");
198 lua_pushnumber(L, p.Z);
199 lua_setfield(L, -2, "z");
202 v3s16 read_v3s16(lua_State *L, int index)
204 // Correct rounding at <0
205 v3f pf = read_v3f(L, index);
206 return floatToInt(pf, 1.0);
209 v3s16 check_v3s16(lua_State *L, int index)
211 // Correct rounding at <0
212 v3f pf = check_v3f(L, index);
213 return floatToInt(pf, 1.0);
216 bool read_color(lua_State *L, int index, video::SColor *color)
218 if (lua_istable(L, index)) {
219 *color = read_ARGB8(L, index);
220 } else if (lua_isnumber(L, index)) {
221 color->set(lua_tonumber(L, index));
222 } else if (lua_isstring(L, index)) {
223 video::SColor parsed_color;
224 if (!parseColorString(lua_tostring(L, index), parsed_color, true))
227 *color = parsed_color;
235 video::SColor read_ARGB8(lua_State *L, int index)
237 video::SColor color(0);
238 CHECK_TYPE(index, "ARGB color", LUA_TTABLE);
239 lua_getfield(L, index, "a");
240 color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF);
242 lua_getfield(L, index, "r");
243 color.setRed(lua_tonumber(L, -1));
245 lua_getfield(L, index, "g");
246 color.setGreen(lua_tonumber(L, -1));
248 lua_getfield(L, index, "b");
249 color.setBlue(lua_tonumber(L, -1));
254 aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
257 if(lua_istable(L, index)){
258 lua_rawgeti(L, index, 1);
259 box.MinEdge.X = lua_tonumber(L, -1) * scale;
261 lua_rawgeti(L, index, 2);
262 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
264 lua_rawgeti(L, index, 3);
265 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
267 lua_rawgeti(L, index, 4);
268 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
270 lua_rawgeti(L, index, 5);
271 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
273 lua_rawgeti(L, index, 6);
274 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
280 std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
282 std::vector<aabb3f> boxes;
283 if(lua_istable(L, index)){
284 int n = lua_objlen(L, index);
285 // Check if it's a single box or a list of boxes
286 bool possibly_single_box = (n == 6);
287 for(int i = 1; i <= n && possibly_single_box; i++){
288 lua_rawgeti(L, index, i);
289 if(!lua_isnumber(L, -1))
290 possibly_single_box = false;
293 if(possibly_single_box){
295 boxes.push_back(read_aabb3f(L, index, scale));
297 // Read a list of boxes
298 for(int i = 1; i <= n; i++){
299 lua_rawgeti(L, index, i);
300 boxes.push_back(read_aabb3f(L, -1, scale));
308 size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result)
311 index = lua_gettop(L) + 1 + index;
313 size_t num_strings = 0;
315 if (lua_istable(L, index)) {
317 while (lua_next(L, index)) {
318 if (lua_isstring(L, -1)) {
319 result->push_back(lua_tostring(L, -1));
324 } else if (lua_isstring(L, index)) {
325 result->push_back(lua_tostring(L, index));
336 bool getstringfield(lua_State *L, int table,
337 const char *fieldname, std::string &result)
339 lua_getfield(L, table, fieldname);
341 if(lua_isstring(L, -1)){
343 const char *ptr = lua_tolstring(L, -1, &len);
345 result.assign(ptr, len);
353 bool getintfield(lua_State *L, int table,
354 const char *fieldname, int &result)
356 lua_getfield(L, table, fieldname);
358 if(lua_isnumber(L, -1)){
359 result = lua_tonumber(L, -1);
366 bool getintfield(lua_State *L, int table,
367 const char *fieldname, u8 &result)
369 lua_getfield(L, table, fieldname);
371 if(lua_isnumber(L, -1)){
372 result = lua_tonumber(L, -1);
379 bool getintfield(lua_State *L, int table,
380 const char *fieldname, u16 &result)
382 lua_getfield(L, table, fieldname);
384 if(lua_isnumber(L, -1)){
385 result = lua_tonumber(L, -1);
392 bool getintfield(lua_State *L, int table,
393 const char *fieldname, u32 &result)
395 lua_getfield(L, table, fieldname);
397 if(lua_isnumber(L, -1)){
398 result = lua_tonumber(L, -1);
405 bool getfloatfield(lua_State *L, int table,
406 const char *fieldname, float &result)
408 lua_getfield(L, table, fieldname);
410 if(lua_isnumber(L, -1)){
411 result = lua_tonumber(L, -1);
418 bool getboolfield(lua_State *L, int table,
419 const char *fieldname, bool &result)
421 lua_getfield(L, table, fieldname);
423 if(lua_isboolean(L, -1)){
424 result = lua_toboolean(L, -1);
431 size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
432 std::vector<std::string> *result)
434 lua_getfield(L, table, fieldname);
436 size_t num_strings_read = read_stringlist(L, -1, result);
439 return num_strings_read;
442 std::string checkstringfield(lua_State *L, int table,
443 const char *fieldname)
445 lua_getfield(L, table, fieldname);
446 CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
448 const char *s = lua_tolstring(L, -1, &len);
450 return std::string(s, len);
453 std::string getstringfield_default(lua_State *L, int table,
454 const char *fieldname, const std::string &default_)
456 std::string result = default_;
457 getstringfield(L, table, fieldname, result);
461 int getintfield_default(lua_State *L, int table,
462 const char *fieldname, int default_)
464 int result = default_;
465 getintfield(L, table, fieldname, result);
469 float getfloatfield_default(lua_State *L, int table,
470 const char *fieldname, float default_)
472 float result = default_;
473 getfloatfield(L, table, fieldname, result);
477 bool getboolfield_default(lua_State *L, int table,
478 const char *fieldname, bool default_)
480 bool result = default_;
481 getboolfield(L, table, fieldname, result);
485 void setintfield(lua_State *L, int table,
486 const char *fieldname, int value)
488 lua_pushinteger(L, value);
491 lua_setfield(L, table, fieldname);
494 void setfloatfield(lua_State *L, int table,
495 const char *fieldname, float value)
497 lua_pushnumber(L, value);
500 lua_setfield(L, table, fieldname);
503 void setboolfield(lua_State *L, int table,
504 const char *fieldname, bool value)
506 lua_pushboolean(L, value);
509 lua_setfield(L, table, fieldname);