From 28438bba27168289be59a26d3ae55e3f3658d8d3 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Fri, 3 Oct 2014 06:11:21 +0200 Subject: [PATCH] Add [colorize modifier --- doc/lua_api.txt | 32 +++++++++------- src/guiFormSpecMenu.cpp | 81 +++++------------------------------------ src/guiFormSpecMenu.h | 3 -- src/guiTable.cpp | 14 +++---- src/tile.cpp | 41 ++++++++++++++++++++- src/util/string.cpp | 63 ++++++++++++++++++++++++++++++++ src/util/string.h | 3 +- 7 files changed, 138 insertions(+), 99 deletions(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 4db0dc40f..131a63fa5 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -262,6 +262,10 @@ Advanced texture modifiers: Apply a mask to the base image. The mask is applied using binary AND. + [colorize: + Colorize the textures with given color + as ColorString + Sounds ------- Only OGG Vorbis files are supported. @@ -985,16 +989,16 @@ list[;;,;,;] ^ Show an inventory list listcolors[;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering listcolors[;;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering ^ Sets color of slots border listcolors[;;;;] -^ Sets background color of slots in HEX-Color format +^ Sets background color of slots as ColorString ^ Sets background color of slots on mouse hovering ^ Sets color of slots border ^ Sets default background color of tooltips @@ -1002,8 +1006,8 @@ listcolors[;;;;;;,] ^ Adds tooltip for an element -^ tooltip background color in HEX-Color format (optional) -^ tooltip font color in HEX-Color format (optional) +^ tooltip background color as ColorString (optional) +^ tooltip font color as ColorString (optional) image[,;,;] @@ -1015,7 +1019,7 @@ item_image[,;,;] ^ Position and size units are inventory slots bgcolor[;] -^ Sets background color of formspec in HEX-Color format +^ Sets background color of formspec as ColorString ^ If true the background color is drawn fullscreen (does not effect the size of the formspec) background[,;,;] @@ -1136,7 +1140,7 @@ box[,;,;] ^ simple colored semitransparent box ^ x and y position the box relative to the top left of the menu ^ w and h are the size of box -^ color in HEX-Color format +^ color as ColorString dropdown[,;;;,, ...,;] ^ show a dropdown field @@ -1182,15 +1186,15 @@ table[,;,;;,,...,;] tableoptions[;;...] ^ sets options for table[]: ^ color=#RRGGBB -^^ default text color (HEX-Color), defaults to #FFFFFF +^^ default text color (ColorString), defaults to #FFFFFF ^ background=#RRGGBB -^^ table background color (HEX-Color), defaults to #000000 +^^ table background color (ColorString), defaults to #000000 ^ border= ^^ should the table be drawn with a border? (default true) ^ highlight=#RRGGBB -^^ highlight background color (HEX-Color), defaults to #466432 +^^ highlight background color (ColorString), defaults to #466432 ^ highlight_text=#RRGGBB -^^ highlight text color (HEX-Color), defaults to #FFFFFF +^^ highlight text color (ColorString), defaults to #FFFFFF ^ opendepth= ^^ all subtrees up to depth < value are open (default value = 0) ^^ only useful when there is a column of type "tree" @@ -1200,7 +1204,7 @@ tablecolumns[,,,...;,,;...] ^ types: text, image, color, indent, tree ^^ text: show cell contents as text ^^ image: cell contents are an image index, use column options to define images -^^ color: cell contents are a HEX-Color and define color of following cell +^^ color: cell contents are a ColorString and define color of following cell ^^ indent: cell contents are a number and define indentation of following cell ^^ tree: same as indent, but user can open and close subtrees (treeview-like) ^ column options: @@ -1231,8 +1235,8 @@ Inventory location: - "nodemeta:,,": Any node metadata - "detached:": A detached inventory -HEX-Color ---------- +ColorString +----------- #RGB ^ defines a color in hexadecimal format #RGBA diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index f50fd15e5..2439de7fa 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -50,6 +50,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "main.h" #include "settings.h" #include "client.h" +#include "util/string.h" // for parseColorString() #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -1575,7 +1576,7 @@ void GUIFormSpecMenu::parseBox(parserData* data,std::string element) video::SColor tmp_color; - if (parseColor(parts[2], tmp_color, false)) { + if (parseColorString(parts[2], tmp_color, false)) { BoxDrawSpec spec(pos, geom, tmp_color); m_boxes.push_back(spec); @@ -1595,7 +1596,7 @@ void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element) if (((parts.size() == 1) || (parts.size() == 2)) || ((parts.size() > 2) && (m_formspec_version > FORMSPEC_API_VERSION))) { - parseColor(parts[0],m_bgcolor,false); + parseColorString(parts[0],m_bgcolor,false); if (parts.size() == 2) { std::string fullscreen = parts[1]; @@ -1613,20 +1614,20 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) if (((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) || ((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION))) { - parseColor(parts[0], m_slotbg_n, false); - parseColor(parts[1], m_slotbg_h, false); + parseColorString(parts[0], m_slotbg_n, false); + parseColorString(parts[1], m_slotbg_h, false); if (parts.size() >= 3) { - if (parseColor(parts[2], m_slotbordercolor, false)) { + if (parseColorString(parts[2], m_slotbordercolor, false)) { m_slotborder = true; } } if (parts.size() == 5) { video::SColor tmp_color; - if (parseColor(parts[3], tmp_color, false)) + if (parseColorString(parts[3], tmp_color, false)) m_default_tooltip_bgcolor = tmp_color; - if (parseColor(parts[4], tmp_color, false)) + if (parseColorString(parts[4], tmp_color, false)) m_default_tooltip_color = tmp_color; } return; @@ -1644,7 +1645,7 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element) } else if (parts.size() == 4) { std::string name = parts[0]; video::SColor tmp_color1, tmp_color2; - if ( parseColor(parts[2], tmp_color1, false) && parseColor(parts[3], tmp_color2, false) ) { + if ( parseColorString(parts[2], tmp_color1, false) && parseColorString(parts[3], tmp_color2, false) ) { m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], tmp_color1, tmp_color2); return; } @@ -3388,67 +3389,3 @@ std::wstring GUIFormSpecMenu::getLabelByID(s32 id) } return L""; } - -bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color, - bool quiet) -{ - const char *hexpattern = NULL; - if (value[0] == '#') { - if (value.size() == 9) - hexpattern = "#RRGGBBAA"; - else if (value.size() == 7) - hexpattern = "#RRGGBB"; - else if (value.size() == 5) - hexpattern = "#RGBA"; - else if (value.size() == 4) - hexpattern = "#RGB"; - } - - if (hexpattern) { - assert(strlen(hexpattern) == value.size()); - video::SColor outcolor(255, 255, 255, 255); - for (size_t pos = 0; pos < value.size(); ++pos) { - // '#' in the pattern means skip that character - if (hexpattern[pos] == '#') - continue; - - // Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A' - // Read one or two digits, depending on hexpattern - unsigned char c1, c2; - if (hexpattern[pos+1] == hexpattern[pos]) { - // Two digits, e.g. hexpattern == "#RRGGBB" - if (!hex_digit_decode(value[pos], c1) || - !hex_digit_decode(value[pos+1], c2)) - goto fail; - ++pos; - } - else { - // One digit, e.g. hexpattern == "#RGB" - if (!hex_digit_decode(value[pos], c1)) - goto fail; - c2 = c1; - } - u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f); - - // Update outcolor with newly read color part - if (hexpattern[pos] == 'R') - outcolor.setRed(colorpart); - else if (hexpattern[pos] == 'G') - outcolor.setGreen(colorpart); - else if (hexpattern[pos] == 'B') - outcolor.setBlue(colorpart); - else if (hexpattern[pos] == 'A') - outcolor.setAlpha(colorpart); - } - - color = outcolor; - return true; - } - - // Optionally, named colors could be implemented here - -fail: - if (!quiet) - errorstream<<"Invalid color: \""< &content, cell->content_index = allocString(s.substr(2)); } else if (s[0] == '#' && s.size() >= 7 && - GUIFormSpecMenu::parseColor( + parseColorString( s.substr(0,7), cell->color, false)) { // single # for color cell->color_defined = true; @@ -211,15 +211,15 @@ void GUITable::setTable(const TableOptions &options, const std::string &name = options[k].name; const std::string &value = options[k].value; if (name == "color") - GUIFormSpecMenu::parseColor(value, m_color, false); + parseColorString(value, m_color, false); else if (name == "background") - GUIFormSpecMenu::parseColor(value, m_background, false); + parseColorString(value, m_background, false); else if (name == "border") m_border = is_yes(value); else if (name == "highlight") - GUIFormSpecMenu::parseColor(value, m_highlight, false); + parseColorString(value, m_highlight, false); else if (name == "highlight_text") - GUIFormSpecMenu::parseColor(value, m_highlight_text, false); + parseColorString(value, m_highlight_text, false); else if (name == "opendepth") opendepth = stoi(value); else @@ -416,7 +416,7 @@ void GUITable::setTable(const TableOptions &options, else if (columntype == COLUMN_TYPE_COLOR) { for (s32 i = 0; i < rowcount; ++i) { video::SColor cellcolor(255, 255, 255, 255); - if (GUIFormSpecMenu::parseColor(content[i * colcount + j], cellcolor, true)) + if (parseColorString(content[i * colcount + j], cellcolor, true)) rows[i].colors.push_back(std::make_pair(cellcolor, j+span)); } } diff --git a/src/tile.cpp b/src/tile.cpp index ebef77fb9..fa2f4c84e 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "gamedef.h" #include "strfnd.h" +#include "util/string.h" // for parseColorString() #ifdef __ANDROID__ #include @@ -1588,10 +1589,46 @@ bool TextureSource::generateImagePart(std::string part_of_name, << filename << "\"."; } } + /* + [colorize:color + Overlays image with given color + color = color as ColorString + */ + else if (part_of_name.substr(0,10) == "[colorize:") { + Strfnd sf(part_of_name); + sf.next(":"); + std::string color_str = sf.next(":"); + + if (baseimg == NULL) { + errorstream << "generateImagePart(): baseimg != NULL " + << "for part_of_name=\"" << part_of_name + << "\", cancelling." << std::endl; + return false; + } + + video::SColor color; + if (!parseColorString(color_str, color, false)) + return false; + + core::dimension2d dim = baseimg->getDimension(); + video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim); + + if (!img) { + errorstream << "generateImagePart(): Could not create image " + << "for part_of_name=\"" << part_of_name + << "\", cancelling." << std::endl; + return false; + } + + img->fill(video::SColor(color)); + // Overlay the colored image + blit_with_alpha_overlay(img, baseimg, v2s32(0,0), v2s32(0,0), dim); + img->drop(); + } else { - errorstream<<"generateImagePart(): Invalid " - " modification: \""< #include @@ -303,3 +304,65 @@ u64 read_seed(const char *str) return num; } + +bool parseColorString(const std::string &value, video::SColor &color, bool quiet) +{ + const char *hexpattern = NULL; + video::SColor outcolor(255, 255, 255, 255); + + if (value[0] == '#') { + if (value.size() == 9) + hexpattern = "#RRGGBBAA"; + else if (value.size() == 7) + hexpattern = "#RRGGBB"; + else if (value.size() == 5) + hexpattern = "#RGBA"; + else if (value.size() == 4) + hexpattern = "#RGB"; + } + + if (!hexpattern) + goto fail; + + assert(strlen(hexpattern) == value.size()); + for (size_t pos = 0; pos < value.size(); ++pos) { + // '#' in the pattern means skip that character + if (hexpattern[pos] == '#') + continue; + + // Else assume hexpattern[pos] is one of 'R' 'G' 'B' 'A' + // Read one or two digits, depending on hexpattern + unsigned char c1, c2; + if (hexpattern[pos+1] == hexpattern[pos]) { + // Two digits, e.g. hexpattern == "#RRGGBB" + if (!hex_digit_decode(value[pos], c1) || + !hex_digit_decode(value[pos+1], c2)) + goto fail; + ++pos; + } else { + // One digit, e.g. hexpattern == "#RGB" + if (!hex_digit_decode(value[pos], c1)) + goto fail; + c2 = c1; + } + u32 colorpart = ((c1 & 0x0f) << 4) | (c2 & 0x0f); + + // Update outcolor with newly read color part + if (hexpattern[pos] == 'R') + outcolor.setRed(colorpart); + else if (hexpattern[pos] == 'G') + outcolor.setGreen(colorpart); + else if (hexpattern[pos] == 'B') + outcolor.setBlue(colorpart); + else if (hexpattern[pos] == 'A') + outcolor.setAlpha(colorpart); + } + + color = outcolor; + return true; + +fail: + if (!quiet) + errorstream << "Invalid color: \"" << value << "\"" << std::endl; + return false; +} diff --git a/src/util/string.h b/src/util/string.h index 54a5a458e..e46fbf4e9 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -20,7 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #ifndef UTIL_STRING_HEADER #define UTIL_STRING_HEADER -#include "../irrlichttypes.h" +#include "irrlichttypes_bloated.h" #include #include #include @@ -349,6 +349,7 @@ std::string writeFlagString(u32 flags, const FlagDesc *flagdesc, u32 flagmask); size_t mystrlcpy(char *dst, const char *src, size_t size); char *mystrtok_r(char *s, const char *sep, char **lasts); u64 read_seed(const char *str); +bool parseColorString(const std::string &value, video::SColor &color, bool quiet); #endif -- 2.25.1