diff --git a/doc/lua_api.txt b/doc/lua_api.txt index e1ee42b94..9249703f6 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1607,6 +1607,16 @@ To specify the value of the alpha channel, append `#AA` to the end of the color (e.g. `colorname#08`). For named colors the hexadecimal string representing the alpha value must (always) be two hexadecimal digits. +`ColorSpec` +----------- +A ColorSpec specifies a 32-bit color. It can be written in either: +table form, each element ranging from 0..255 (a, if absent, defaults to 255): + `colorspec = {a=255, r=0, g=255, b=0}` +numerical form, the raw integer value of an ARGB8 quad: + `colorspec = 0xFF00FF00` +or string form, a ColorString (defined above): + `colorspec = "green"` + Vector helpers -------------- @@ -2481,7 +2491,7 @@ This is basically a reference to a C++ `ServerActiveObject` * `name`: `"breath"` or `"health"` * `hud_definition`: definition to replace builtin definition * `set_sky(bgcolor, type, {texture names})` - * `bgcolor`: `{r=0...255, g=0...255, b=0...255}` or `nil`, defaults to white + * `bgcolor`: ColorSpec, defaults to white * Available types: * `"regular"`: Uses 0 textures, `bgcolor` ignored * `"skybox"`: Uses 6 textures, `bgcolor` used @@ -2507,13 +2517,13 @@ This is basically a reference to a C++ `ServerActiveObject` * `get_nametag_attributes()` * returns a table with the attributes of the nametag of the player * { - color = { a = 0...255, r = 0...255, g = 0...255, b = 0...255 } + color = {a=0..255, r=0..255, g=0..255, b=0..255}, } * `set_nametag_attributes(attributes)` * sets the attributes of the nametag of the player * `attributes`: { - color = { a = 0...255, r = 0...255, g = 0...255, b = 0...255 } + color = ColorSpec, } ### `InvRef` @@ -3023,7 +3033,7 @@ Definition tables ^ List can be shortened to needed length ]] alpha = 255, use_texture_alpha = false, -- Use texture's alpha channel - post_effect_color = {a=0, r=0, g=0, b=0}, -- If player is inside node + post_effect_color = "green#0F", -- If player is inside node, see "ColorSpec" paramtype = "none", -- See "Nodes" --[[ ^ paramtype = "light" allows light to propagate from or through the node with light value ^ falling by 1 per node. This line is essential for a light source node to spread its light. ]] diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 8f82b692a..c0728177f 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -162,18 +162,13 @@ void read_object_properties(lua_State *L, int index, lua_pop(L, 1); lua_getfield(L, -1, "colors"); - if(lua_istable(L, -1)){ - prop->colors.clear(); + if (lua_istable(L, -1)) { int table = lua_gettop(L); - lua_pushnil(L); - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - if(lua_isstring(L, -1)) - prop->colors.push_back(readARGB8(L, -1)); - else - prop->colors.push_back(video::SColor(255, 255, 255, 255)); - // removes value, keeps key for next iteration - lua_pop(L, 1); + prop->colors.clear(); + for (lua_pushnil(L); lua_next(L, table); lua_pop(L, 1)) { + video::SColor color(255, 255, 255, 255); + read_color(L, -1, &color); + prop->colors.push_back(color); } } lua_pop(L, 1); @@ -357,8 +352,7 @@ ContentFeatures read_content_features(lua_State *L, int index) /* Other stuff */ lua_getfield(L, index, "post_effect_color"); - if(!lua_isnil(L, -1)) - f.post_effect_color = readARGB8(L, -1); + read_color(L, -1, &f.post_effect_color); lua_pop(L, 1); f.param_type = (ContentParamType)getenumfield(L, index, "paramtype", diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index 9d6829815..6fb6f623a 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -23,35 +23,23 @@ extern "C" { } #include "util/numeric.h" +#include "util/string.h" #include "common/c_converter.h" #include "constants.h" #define CHECK_TYPE(index, name, type) do { \ - int t = lua_type(L, (index)); \ - if (t != (type)) { \ - throw LuaError(std::string("Invalid ") + (name) + \ - " (expected " + lua_typename(L, (type)) + \ - " got " + lua_typename(L, t) + ")."); \ - } \ -} while(0) + int t = lua_type(L, (index)); \ + if (t != (type)) { \ + throw LuaError(std::string("Invalid ") + (name) + \ + " (expected " + lua_typename(L, (type)) + \ + " got " + lua_typename(L, t) + ")."); \ + } \ + } while(0) #define CHECK_POS_COORD(name) CHECK_TYPE(-1, "position coordinate '" name "'", LUA_TNUMBER) #define CHECK_POS_TAB(index) CHECK_TYPE(index, "position", LUA_TTABLE) -void push_ARGB8(lua_State *L, video::SColor color) -{ - lua_newtable(L); - lua_pushnumber(L, color.getAlpha()); - lua_setfield(L, -2, "a"); - lua_pushnumber(L, color.getRed()); - lua_setfield(L, -2, "r"); - lua_pushnumber(L, color.getGreen()); - lua_setfield(L, -2, "g"); - lua_pushnumber(L, color.getBlue()); - lua_setfield(L, -2, "b"); -} - void push_v3f(lua_State *L, v3f p) { lua_newtable(L); @@ -176,6 +164,19 @@ v3f check_v3f(lua_State *L, int index) return pos; } +void push_ARGB8(lua_State *L, video::SColor color) +{ + lua_newtable(L); + lua_pushnumber(L, color.getAlpha()); + lua_setfield(L, -2, "a"); + lua_pushnumber(L, color.getRed()); + lua_setfield(L, -2, "r"); + lua_pushnumber(L, color.getGreen()); + lua_setfield(L, -2, "g"); + lua_pushnumber(L, color.getBlue()); + lua_setfield(L, -2, "b"); +} + void pushFloatPos(lua_State *L, v3f p) { p /= BS; @@ -212,13 +213,31 @@ v3s16 check_v3s16(lua_State *L, int index) return floatToInt(pf, 1.0); } -video::SColor readARGB8(lua_State *L, int index) +bool read_color(lua_State *L, int index, video::SColor *color) +{ + if (lua_istable(L, index)) { + *color = read_ARGB8(L, index); + } else if (lua_isnumber(L, index)) { + color->set(lua_tonumber(L, index)); + } else if (lua_isstring(L, index)) { + video::SColor parsed_color; + if (!parseColorString(lua_tostring(L, index), parsed_color, true)) + return false; + + *color = parsed_color; + } else { + return false; + } + + return true; +} + +video::SColor read_ARGB8(lua_State *L, int index) { video::SColor color(0); CHECK_TYPE(index, "ARGB color", LUA_TTABLE); lua_getfield(L, index, "a"); - if(lua_isnumber(L, -1)) - color.setAlpha(lua_tonumber(L, -1)); + color.setAlpha(lua_isnumber(L, -1) ? lua_tonumber(L, -1) : 0xFF); lua_pop(L, 1); lua_getfield(L, index, "r"); color.setRed(lua_tonumber(L, -1)); diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index ff1fcaadf..e99826404 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -76,7 +76,6 @@ void setfloatfield(lua_State *L, int table, void setboolfield(lua_State *L, int table, const char *fieldname, bool value); - v3f checkFloatPos (lua_State *L, int index); v2f check_v2f (lua_State *L, int index); v2s16 check_v2s16 (lua_State *L, int index); @@ -87,7 +86,10 @@ v3f read_v3f (lua_State *L, int index); v2f read_v2f (lua_State *L, int index); v2s16 read_v2s16 (lua_State *L, int index); v2s32 read_v2s32 (lua_State *L, int index); -video::SColor readARGB8 (lua_State *L, int index); +video::SColor read_ARGB8 (lua_State *L, int index); +bool read_color (lua_State *L, int index, + video::SColor *color); + aabb3f read_aabb3f (lua_State *L, int index, f32 scale); v3s16 read_v3s16 (lua_State *L, int index); std::vector read_aabb3f_vector (lua_State *L, int index, f32 scale); @@ -100,11 +102,8 @@ void pushFloatPos (lua_State *L, v3f p); void push_v3f (lua_State *L, v3f p); void push_v2f (lua_State *L, v2f p); - - -void warn_if_field_exists (lua_State *L, - int table, - const char *fieldname, - const std::string &message); +void warn_if_field_exists(lua_State *L, int table, + const char *fieldname, + const std::string &message); #endif /* C_CONVERTER_H_ */ diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 74903df5f..c83c8c747 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1222,8 +1222,7 @@ int ObjectRef::l_set_sky(lua_State *L) return 0; video::SColor bgcolor(255,255,255,255); - if (!lua_isnil(L, 2)) - bgcolor = readARGB8(L, 2); + read_color(L, 2, &bgcolor); std::string type = luaL_checkstring(L, 3); @@ -1283,11 +1282,13 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L) if (playersao == NULL) return 0; - video::SColor color = playersao->getNametagColor(); lua_getfield(L, 2, "color"); - if (!lua_isnil(L, -1)) - color = readARGB8(L, -1); - playersao->setNametagColor(color); + if (!lua_isnil(L, -1)) { + video::SColor color = playersao->getNametagColor(); + if (!read_color(L, -1, &color)) + return 0; + playersao->setNametagColor(color); + } lua_pushboolean(L, true); return 1;