]> git.lizzy.rs Git - dragonfireclient.git/blob - src/script/common/c_converter.cpp
SAPI: Accept either ARGB8 table or ColorString to specify colors
[dragonfireclient.git] / src / script / common / c_converter.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19
20 extern "C" {
21 #include "lua.h"
22 #include "lauxlib.h"
23 }
24
25 #include "util/numeric.h"
26 #include "util/string.h"
27 #include "common/c_converter.h"
28 #include "constants.h"
29
30
31 #define CHECK_TYPE(index, name, type) do { \
32                 int t = lua_type(L, (index)); \
33                 if (t != (type)) { \
34                         throw LuaError(std::string("Invalid ") + (name) + \
35                                 " (expected " + lua_typename(L, (type)) + \
36                                 " got " + lua_typename(L, t) + ")."); \
37                 } \
38         } while(0)
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)
41
42
43 void push_v3f(lua_State *L, v3f p)
44 {
45         lua_newtable(L);
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");
52 }
53
54 void push_v2f(lua_State *L, v2f p)
55 {
56         lua_newtable(L);
57         lua_pushnumber(L, p.X);
58         lua_setfield(L, -2, "x");
59         lua_pushnumber(L, p.Y);
60         lua_setfield(L, -2, "y");
61 }
62
63 v2s16 read_v2s16(lua_State *L, int index)
64 {
65         v2s16 p;
66         CHECK_POS_TAB(index);
67         lua_getfield(L, index, "x");
68         p.X = lua_tonumber(L, -1);
69         lua_pop(L, 1);
70         lua_getfield(L, index, "y");
71         p.Y = lua_tonumber(L, -1);
72         lua_pop(L, 1);
73         return p;
74 }
75
76 v2s16 check_v2s16(lua_State *L, int index)
77 {
78         v2s16 p;
79         CHECK_POS_TAB(index);
80         lua_getfield(L, index, "x");
81         CHECK_POS_COORD("x");
82         p.X = lua_tonumber(L, -1);
83         lua_pop(L, 1);
84         lua_getfield(L, index, "y");
85         CHECK_POS_COORD("y");
86         p.Y = lua_tonumber(L, -1);
87         lua_pop(L, 1);
88         return p;
89 }
90
91 v2s32 read_v2s32(lua_State *L, int index)
92 {
93         v2s32 p;
94         CHECK_POS_TAB(index);
95         lua_getfield(L, index, "x");
96         p.X = lua_tonumber(L, -1);
97         lua_pop(L, 1);
98         lua_getfield(L, index, "y");
99         p.Y = lua_tonumber(L, -1);
100         lua_pop(L, 1);
101         return p;
102 }
103
104 v2f read_v2f(lua_State *L, int index)
105 {
106         v2f p;
107         CHECK_POS_TAB(index);
108         lua_getfield(L, index, "x");
109         p.X = lua_tonumber(L, -1);
110         lua_pop(L, 1);
111         lua_getfield(L, index, "y");
112         p.Y = lua_tonumber(L, -1);
113         lua_pop(L, 1);
114         return p;
115 }
116
117 v2f check_v2f(lua_State *L, int index)
118 {
119         v2f p;
120         CHECK_POS_TAB(index);
121         lua_getfield(L, index, "x");
122         CHECK_POS_COORD("x");
123         p.X = lua_tonumber(L, -1);
124         lua_pop(L, 1);
125         lua_getfield(L, index, "y");
126         CHECK_POS_COORD("y");
127         p.Y = lua_tonumber(L, -1);
128         lua_pop(L, 1);
129         return p;
130 }
131
132 v3f read_v3f(lua_State *L, int index)
133 {
134         v3f pos;
135         CHECK_POS_TAB(index);
136         lua_getfield(L, index, "x");
137         pos.X = lua_tonumber(L, -1);
138         lua_pop(L, 1);
139         lua_getfield(L, index, "y");
140         pos.Y = lua_tonumber(L, -1);
141         lua_pop(L, 1);
142         lua_getfield(L, index, "z");
143         pos.Z = lua_tonumber(L, -1);
144         lua_pop(L, 1);
145         return pos;
146 }
147
148 v3f check_v3f(lua_State *L, int index)
149 {
150         v3f pos;
151         CHECK_POS_TAB(index);
152         lua_getfield(L, index, "x");
153         CHECK_POS_COORD("x");
154         pos.X = lua_tonumber(L, -1);
155         lua_pop(L, 1);
156         lua_getfield(L, index, "y");
157         CHECK_POS_COORD("y");
158         pos.Y = lua_tonumber(L, -1);
159         lua_pop(L, 1);
160         lua_getfield(L, index, "z");
161         CHECK_POS_COORD("z");
162         pos.Z = lua_tonumber(L, -1);
163         lua_pop(L, 1);
164         return pos;
165 }
166
167 void push_ARGB8(lua_State *L, video::SColor color)
168 {
169         lua_newtable(L);
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");
178 }
179
180 void pushFloatPos(lua_State *L, v3f p)
181 {
182         p /= BS;
183         push_v3f(L, p);
184 }
185
186 v3f checkFloatPos(lua_State *L, int index)
187 {
188         return check_v3f(L, index) * BS;
189 }
190
191 void push_v3s16(lua_State *L, v3s16 p)
192 {
193         lua_newtable(L);
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");
200 }
201
202 v3s16 read_v3s16(lua_State *L, int index)
203 {
204         // Correct rounding at <0
205         v3f pf = read_v3f(L, index);
206         return floatToInt(pf, 1.0);
207 }
208
209 v3s16 check_v3s16(lua_State *L, int index)
210 {
211         // Correct rounding at <0
212         v3f pf = check_v3f(L, index);
213         return floatToInt(pf, 1.0);
214 }
215
216 bool read_color(lua_State *L, int index, video::SColor *color)
217 {
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))
225                         return false;
226
227                 *color = parsed_color;
228         } else {
229                 return false;
230         }
231
232         return true;
233 }
234
235 video::SColor read_ARGB8(lua_State *L, int index)
236 {
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);
241         lua_pop(L, 1);
242         lua_getfield(L, index, "r");
243         color.setRed(lua_tonumber(L, -1));
244         lua_pop(L, 1);
245         lua_getfield(L, index, "g");
246         color.setGreen(lua_tonumber(L, -1));
247         lua_pop(L, 1);
248         lua_getfield(L, index, "b");
249         color.setBlue(lua_tonumber(L, -1));
250         lua_pop(L, 1);
251         return color;
252 }
253
254 aabb3f read_aabb3f(lua_State *L, int index, f32 scale)
255 {
256         aabb3f box;
257         if(lua_istable(L, index)){
258                 lua_rawgeti(L, index, 1);
259                 box.MinEdge.X = lua_tonumber(L, -1) * scale;
260                 lua_pop(L, 1);
261                 lua_rawgeti(L, index, 2);
262                 box.MinEdge.Y = lua_tonumber(L, -1) * scale;
263                 lua_pop(L, 1);
264                 lua_rawgeti(L, index, 3);
265                 box.MinEdge.Z = lua_tonumber(L, -1) * scale;
266                 lua_pop(L, 1);
267                 lua_rawgeti(L, index, 4);
268                 box.MaxEdge.X = lua_tonumber(L, -1) * scale;
269                 lua_pop(L, 1);
270                 lua_rawgeti(L, index, 5);
271                 box.MaxEdge.Y = lua_tonumber(L, -1) * scale;
272                 lua_pop(L, 1);
273                 lua_rawgeti(L, index, 6);
274                 box.MaxEdge.Z = lua_tonumber(L, -1) * scale;
275                 lua_pop(L, 1);
276         }
277         return box;
278 }
279
280 std::vector<aabb3f> read_aabb3f_vector(lua_State *L, int index, f32 scale)
281 {
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;
291                         lua_pop(L, 1);
292                 }
293                 if(possibly_single_box){
294                         // Read a single box
295                         boxes.push_back(read_aabb3f(L, index, scale));
296                 } else {
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));
301                                 lua_pop(L, 1);
302                         }
303                 }
304         }
305         return boxes;
306 }
307
308 size_t read_stringlist(lua_State *L, int index, std::vector<std::string> *result)
309 {
310         if (index < 0)
311                 index = lua_gettop(L) + 1 + index;
312
313         size_t num_strings = 0;
314
315         if (lua_istable(L, index)) {
316                 lua_pushnil(L);
317                 while (lua_next(L, index)) {
318                         if (lua_isstring(L, -1)) {
319                                 result->push_back(lua_tostring(L, -1));
320                                 num_strings++;
321                         }
322                         lua_pop(L, 1);
323                 }
324         } else if (lua_isstring(L, index)) {
325                 result->push_back(lua_tostring(L, index));
326                 num_strings++;
327         }
328
329         return num_strings;
330 }
331
332 /*
333         Table field getters
334 */
335
336 bool getstringfield(lua_State *L, int table,
337                 const char *fieldname, std::string &result)
338 {
339         lua_getfield(L, table, fieldname);
340         bool got = false;
341         if(lua_isstring(L, -1)){
342                 size_t len = 0;
343                 const char *ptr = lua_tolstring(L, -1, &len);
344                 if (ptr) {
345                         result.assign(ptr, len);
346                         got = true;
347                 }
348         }
349         lua_pop(L, 1);
350         return got;
351 }
352
353 bool getintfield(lua_State *L, int table,
354                 const char *fieldname, int &result)
355 {
356         lua_getfield(L, table, fieldname);
357         bool got = false;
358         if(lua_isnumber(L, -1)){
359                 result = lua_tonumber(L, -1);
360                 got = true;
361         }
362         lua_pop(L, 1);
363         return got;
364 }
365
366 bool getintfield(lua_State *L, int table,
367                 const char *fieldname, u8 &result)
368 {
369         lua_getfield(L, table, fieldname);
370         bool got = false;
371         if(lua_isnumber(L, -1)){
372                 result = lua_tonumber(L, -1);
373                 got = true;
374         }
375         lua_pop(L, 1);
376         return got;
377 }
378
379 bool getintfield(lua_State *L, int table,
380                 const char *fieldname, u16 &result)
381 {
382         lua_getfield(L, table, fieldname);
383         bool got = false;
384         if(lua_isnumber(L, -1)){
385                 result = lua_tonumber(L, -1);
386                 got = true;
387         }
388         lua_pop(L, 1);
389         return got;
390 }
391
392 bool getintfield(lua_State *L, int table,
393                 const char *fieldname, u32 &result)
394 {
395         lua_getfield(L, table, fieldname);
396         bool got = false;
397         if(lua_isnumber(L, -1)){
398                 result = lua_tonumber(L, -1);
399                 got = true;
400         }
401         lua_pop(L, 1);
402         return got;
403 }
404
405 bool getfloatfield(lua_State *L, int table,
406                 const char *fieldname, float &result)
407 {
408         lua_getfield(L, table, fieldname);
409         bool got = false;
410         if(lua_isnumber(L, -1)){
411                 result = lua_tonumber(L, -1);
412                 got = true;
413         }
414         lua_pop(L, 1);
415         return got;
416 }
417
418 bool getboolfield(lua_State *L, int table,
419                 const char *fieldname, bool &result)
420 {
421         lua_getfield(L, table, fieldname);
422         bool got = false;
423         if(lua_isboolean(L, -1)){
424                 result = lua_toboolean(L, -1);
425                 got = true;
426         }
427         lua_pop(L, 1);
428         return got;
429 }
430
431 size_t getstringlistfield(lua_State *L, int table, const char *fieldname,
432                 std::vector<std::string> *result)
433 {
434         lua_getfield(L, table, fieldname);
435
436         size_t num_strings_read = read_stringlist(L, -1, result);
437
438         lua_pop(L, 1);
439         return num_strings_read;
440 }
441
442 std::string checkstringfield(lua_State *L, int table,
443                 const char *fieldname)
444 {
445         lua_getfield(L, table, fieldname);
446         CHECK_TYPE(-1, std::string("field \"") + fieldname + '"', LUA_TSTRING);
447         size_t len;
448         const char *s = lua_tolstring(L, -1, &len);
449         lua_pop(L, 1);
450         return std::string(s, len);
451 }
452
453 std::string getstringfield_default(lua_State *L, int table,
454                 const char *fieldname, const std::string &default_)
455 {
456         std::string result = default_;
457         getstringfield(L, table, fieldname, result);
458         return result;
459 }
460
461 int getintfield_default(lua_State *L, int table,
462                 const char *fieldname, int default_)
463 {
464         int result = default_;
465         getintfield(L, table, fieldname, result);
466         return result;
467 }
468
469 float getfloatfield_default(lua_State *L, int table,
470                 const char *fieldname, float default_)
471 {
472         float result = default_;
473         getfloatfield(L, table, fieldname, result);
474         return result;
475 }
476
477 bool getboolfield_default(lua_State *L, int table,
478                 const char *fieldname, bool default_)
479 {
480         bool result = default_;
481         getboolfield(L, table, fieldname, result);
482         return result;
483 }
484
485 void setintfield(lua_State *L, int table,
486                 const char *fieldname, int value)
487 {
488         lua_pushinteger(L, value);
489         if(table < 0)
490                 table -= 1;
491         lua_setfield(L, table, fieldname);
492 }
493
494 void setfloatfield(lua_State *L, int table,
495                 const char *fieldname, float value)
496 {
497         lua_pushnumber(L, value);
498         if(table < 0)
499                 table -= 1;
500         lua_setfield(L, table, fieldname);
501 }
502
503 void setboolfield(lua_State *L, int table,
504                 const char *fieldname, bool value)
505 {
506         lua_pushboolean(L, value);
507         if(table < 0)
508                 table -= 1;
509         lua_setfield(L, table, fieldname);
510 }
511
512