From 7a6502a7a5007e4bed8c1dd10af39d4fa2b296a4 Mon Sep 17 00:00:00 2001 From: est31 Date: Sun, 17 Apr 2016 18:35:02 +0200 Subject: [PATCH 1/6] CONTRIBUTING: disallow signed git commits They break bzr-git, and bzr-git breaks the Minetest PPAs. --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 468ba0514..986f60027 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,7 @@ If you are planning to start some significant coding, you would benefit from ask - Have a title which begins with a capital letter - Be descriptive. (e.g. no `Update init.lua` or `Fix a problem`) - Have a first line with less than *80 characters* and have a second line that is *empty* + - Do **not** [sign your commits](https://git-scm.com/book/uz/v2/Git-Tools-Signing-Your-Work), as Minetest offers automatically built ppas over launchpad and it [would break](https://bugs.launchpad.net/bzr-git/+bug/1084403) if there were signed commits in master 4. Once you are happy with your changes, submit a pull request. - Open the [pull-request form](https://github.com/minetest/minetest/pull/new/master) From 2177f3090e6bb8037779a5b518f193a03094797f Mon Sep 17 00:00:00 2001 From: Ekdohibs Date: Fri, 22 Apr 2016 14:20:16 +0200 Subject: [PATCH 2/6] Fix mainmenu code downloading the public serverlist twice. Also, fix a nil error that can happen sometimes in menu_handle_key_up_down --- builtin/mainmenu/common.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 5bf39abd7..1fd89ff77 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -178,7 +178,7 @@ end -------------------------------------------------------------------------------- function menu_handle_key_up_down(fields, textlist, settingname) - local oldidx, newidx = core.get_textlist_index(textlist) + local oldidx, newidx = core.get_textlist_index(textlist), 1 if fields.key_up or fields.key_down then if fields.key_up and oldidx and oldidx > 1 then newidx = oldidx - 1 @@ -203,12 +203,20 @@ function asyncOnlineFavourites() end menudata.favorites = menudata.public_known menudata.favorites_is_public = true + + if not menudata.public_downloading then + menudata.public_downloading = true + else + return + end + core.handle_async( function(param) return core.get_favorites("online") end, nil, function(result) + menudata.public_downloading = nil local favs = order_favorite_list(result) if favs[1] then menudata.public_known = favs From 21079cc8ebae0bf694c1903c07bf3e1517feab99 Mon Sep 17 00:00:00 2001 From: Xunto Date: Thu, 21 Apr 2016 23:26:31 +0300 Subject: [PATCH 3/6] Fix bug that was leading to oversized tooltips containing multiline text when it have multiple lines --- src/guiFormSpecMenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 6492eb9d9..1a6ee91cd 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -2253,7 +2253,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase, this->bringToFront(m_tooltip_element); m_tooltip_element->setText(utf8_to_wide(tooltip_text).c_str()); s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; - s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; + s32 tooltip_height = m_tooltip_element->getTextHeight() + 5; v2u32 screenSize = driver->getScreenSize(); int tooltip_offset_x = m_btn_height; int tooltip_offset_y = m_btn_height; From 48939df9a5ef1ff20f4f9717d1341b51a50dff14 Mon Sep 17 00:00:00 2001 From: Ekdohibs Date: Mon, 4 Apr 2016 18:31:00 +0200 Subject: [PATCH 4/6] Escape more strings: formspecs, item descriptions, infotexts... Also, change the escape character to the more standard \x1b Thus, it can be used in the future for translation or colored text, for example. --- src/chat.cpp | 4 +-- src/game.cpp | 8 +++-- src/guiFormSpecMenu.cpp | 54 ++++++++++++++------------------- src/guiFormSpecMenu.h | 25 ++++++++++----- src/hud.cpp | 7 +++-- src/unittest/test_utilities.cpp | 19 ++++++++++++ src/util/string.cpp | 27 ----------------- src/util/string.h | 44 +++++++++++++++++++++------ 8 files changed, 105 insertions(+), 83 deletions(-) diff --git a/src/chat.cpp b/src/chat.cpp index 7a5196ed5..ab945444f 100644 --- a/src/chat.cpp +++ b/src/chat.cpp @@ -679,8 +679,8 @@ ChatBackend::~ChatBackend() void ChatBackend::addMessage(std::wstring name, std::wstring text) { - name = removeChatEscapes(name); - text = removeChatEscapes(text); + name = unescape_enriched(name); + text = unescape_enriched(text); // Note: A message may consist of multiple lines, for example the MOTD. WStrfnd fnd(text); diff --git a/src/game.cpp b/src/game.cpp index d513517b7..23f261cfd 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -3731,7 +3731,7 @@ void Game::handlePointingAtNode(GameRunData *runData, NodeMetadata *meta = map.getNodeMetadata(nodepos); if (meta) { - infotext = utf8_to_wide(meta->getString("infotext")); + infotext = unescape_enriched(utf8_to_wide(meta->getString("infotext"))); } else { MapNode n = map.getNodeNoEx(nodepos); @@ -3807,13 +3807,15 @@ void Game::handlePointingAtObject(GameRunData *runData, const v3f &player_position, bool show_debug) { - infotext = utf8_to_wide(runData->selected_object->infoText()); + infotext = unescape_enriched( + utf8_to_wide(runData->selected_object->infoText())); if (show_debug) { if (infotext != L"") { infotext += L"\n"; } - infotext += utf8_to_wide(runData->selected_object->debugInfoText()); + infotext += unescape_enriched(utf8_to_wide( + runData->selected_object->debugInfoText())); } if (input->getLeftState()) { diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 1a6ee91cd..23cff3eb7 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -609,8 +609,6 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, if(!data->explicit_size) warningstream<<"invalid use of button without a size[] element"< rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); FieldSpec spec( @@ -746,7 +743,7 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) spec.ftype = f_Table; for (unsigned int i = 0; i < items.size(); ++i) { - items[i] = unescape_string(items[i]); + items[i] = unescape_string(unescape_enriched(items[i])); } //now really show table @@ -818,7 +815,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) spec.ftype = f_Table; for (unsigned int i = 0; i < items.size(); ++i) { - items[i] = unescape_string(items[i]); + items[i] = unescape_string(unescape_enriched(items[i])); } //now really show list @@ -889,7 +886,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) } for (unsigned int i=0; i < items.size(); i++) { - e->addItem(utf8_to_wide(items[i]).c_str()); + e->addItem(unescape_string(unescape_enriched( + utf8_to_wide(items[i]))).c_str()); } if (str_initial_selection != "") @@ -930,8 +928,6 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - label = unescape_string(label); - std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( @@ -995,8 +991,6 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, if(m_form_src) default_val = m_form_src->resolveText(default_val); - default_val = unescape_string(default_val); - label = unescape_string(label); std::wstring wlabel = utf8_to_wide(label); @@ -1094,9 +1088,6 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, default_val = m_form_src->resolveText(default_val); - default_val = unescape_string(default_val); - label = unescape_string(label); - std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( @@ -1197,7 +1188,6 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) if(!data->explicit_size) warningstream<<"invalid use of label without a size[] element"< lines = split(text, '\n'); for (unsigned int i = 0; i != lines.size(); i++) { @@ -1243,7 +1233,8 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) ((parts.size() > 2) && (m_formspec_version > FORMSPEC_API_VERSION))) { std::vector v_pos = split(parts[0],','); - std::wstring text = utf8_to_wide(unescape_string(parts[1])); + std::wstring text = unescape_string( + unescape_enriched(utf8_to_wide(parts[1]))); MY_CHECKPOS("vertlabel",1); @@ -1330,7 +1321,6 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, image_name = unescape_string(image_name); pressed_image_name = unescape_string(pressed_image_name); - label = unescape_string(label); std::wstring wlabel = utf8_to_wide(label); @@ -1430,7 +1420,8 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) e->setNotClipped(true); for (unsigned int i = 0; i < buttons.size(); i++) { - e->addTab(utf8_to_wide(buttons[i]).c_str(), -1); + e->addTab(unescape_string(unescape_enriched( + utf8_to_wide(buttons[i]))).c_str(), -1); } if ((tab_index >= 0) && @@ -1489,7 +1480,6 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) m_default_tooltip_bgcolor, m_default_tooltip_color); - label = unescape_string(label); FieldSpec spec( name, utf8_to_wide(label), @@ -1604,14 +1594,14 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element) std::vector parts = split(element,';'); if (parts.size() == 2) { std::string name = parts[0]; - m_tooltips[name] = TooltipSpec(unescape_string(parts[1]), + m_tooltips[name] = TooltipSpec(parts[1], m_default_tooltip_bgcolor, m_default_tooltip_color); return; } else if (parts.size() == 4) { std::string name = parts[0]; video::SColor tmp_color1, tmp_color2; if ( parseColorString(parts[2], tmp_color1, false) && parseColorString(parts[3], tmp_color2, false) ) { - m_tooltips[name] = TooltipSpec(unescape_string(parts[1]), + m_tooltips[name] = TooltipSpec(parts[1], tmp_color1, tmp_color2); return; } @@ -2242,16 +2232,18 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase, } // Draw tooltip - std::string tooltip_text = ""; - if (hovering && !m_selected_item) - tooltip_text = item.getDefinition(m_gamedef->idef()).description; - if (tooltip_text != "") { - std::vector tt_rows = str_split(tooltip_text, '\n'); + std::wstring tooltip_text = L""; + if (hovering && !m_selected_item) { + tooltip_text = utf8_to_wide(item.getDefinition(m_gamedef->idef()).description); + tooltip_text = unescape_enriched(tooltip_text); + } + if (tooltip_text != L"") { + std::vector tt_rows = str_split(tooltip_text, L'\n'); m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor); m_tooltip_element->setOverrideColor(m_default_tooltip_color); m_tooltip_element->setVisible(true); this->bringToFront(m_tooltip_element); - m_tooltip_element->setText(utf8_to_wide(tooltip_text).c_str()); + m_tooltip_element->setText(tooltip_text.c_str()); s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; s32 tooltip_height = m_tooltip_element->getTextHeight() + 5; v2u32 screenSize = driver->getScreenSize(); @@ -2504,7 +2496,7 @@ void GUIFormSpecMenu::drawMenu() u32 delta = 0; if (id == -1) { m_old_tooltip_id = id; - m_old_tooltip = ""; + m_old_tooltip = L""; } else { if (id == m_old_tooltip_id) { delta = porting::getDeltaMs(m_hovered_time, getTimeMs()); @@ -2517,11 +2509,11 @@ void GUIFormSpecMenu::drawMenu() if (id != -1 && delta >= m_tooltip_show_delay) { for(std::vector::iterator iter = m_fields.begin(); iter != m_fields.end(); ++iter) { - if ( (iter->fid == id) && (m_tooltips[iter->fname].tooltip != "") ){ + if (iter->fid == id && m_tooltips[iter->fname].tooltip != L"") { if (m_old_tooltip != m_tooltips[iter->fname].tooltip) { m_old_tooltip = m_tooltips[iter->fname].tooltip; - m_tooltip_element->setText(utf8_to_wide(m_tooltips[iter->fname].tooltip).c_str()); - std::vector tt_rows = str_split(m_tooltips[iter->fname].tooltip, '\n'); + m_tooltip_element->setText(m_tooltips[iter->fname].tooltip.c_str()); + std::vector tt_rows = str_split(m_tooltips[iter->fname].tooltip, L'\n'); s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; int tooltip_offset_x = m_btn_height; @@ -2875,7 +2867,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) core::position2d(x, y)); if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { m_old_tooltip_id = -1; - m_old_tooltip = ""; + m_old_tooltip = L""; } if (!isChild(hovered,this)) { if (DoubleClickDetection(event)) { diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 005b91369..8774d306f 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "modalMenu.h" #include "guiTable.h" #include "network/networkprotocol.h" +#include "util/string.h" class IGameDef; class InventoryManager; @@ -191,18 +192,26 @@ class GUIFormSpecMenu : public GUIModalMenu bool scale; }; + /* The responsibility of unescaping the strings has been shifted + * from the formspec parsing methods to the draw methods. + * There still are a few exceptions: + * - Vertical label, because it modifies the string by inserting + * '\n' between each character, + * - Tab header, because it gives the string immediately to + * Irrlicht and we can't unescape it later. + */ struct FieldSpec { FieldSpec() { } FieldSpec(const std::string &name, const std::wstring &label, - const std::wstring &fdeflt, int id) : + const std::wstring &default_text, int id) : fname(name), - flabel(label), - fdefault(fdeflt), fid(id) { + flabel = unescape_string(unescape_enriched(label)); + fdefault = unescape_string(unescape_enriched(default_text)); send = false; ftype = f_Unknown; is_exit = false; @@ -235,12 +244,12 @@ class GUIFormSpecMenu : public GUIModalMenu } TooltipSpec(std::string a_tooltip, irr::video::SColor a_bgcolor, irr::video::SColor a_color): - tooltip(a_tooltip), bgcolor(a_bgcolor), color(a_color) { + tooltip = unescape_string(unescape_enriched(utf8_to_wide(a_tooltip))); } - std::string tooltip; + std::wstring tooltip; irr::video::SColor bgcolor; irr::video::SColor color; }; @@ -252,18 +261,18 @@ class GUIFormSpecMenu : public GUIModalMenu } StaticTextSpec(const std::wstring &a_text, const core::rect &a_rect): - text(a_text), rect(a_rect), parent_button(NULL) { + text = unescape_string(unescape_enriched(a_text)); } StaticTextSpec(const std::wstring &a_text, const core::rect &a_rect, gui::IGUIButton *a_parent_button): - text(a_text), rect(a_rect), parent_button(a_parent_button) { + text = unescape_string(unescape_enriched(a_text)); } std::wstring text; core::rect rect; @@ -406,7 +415,7 @@ protected: u32 m_tooltip_show_delay; s32 m_hovered_time; s32 m_old_tooltip_id; - std::string m_old_tooltip; + std::wstring m_old_tooltip; bool m_rmouse_auto_place; diff --git a/src/hud.cpp b/src/hud.cpp index 502865caa..19feaef7b 100644 --- a/src/hud.cpp +++ b/src/hud.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "hud.h" #include "settings.h" #include "util/numeric.h" +#include "util/string.h" #include "log.h" #include "gamedef.h" #include "itemdef.h" @@ -319,7 +320,7 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect size(0, 0, e->scale.X, text_height * e->scale.Y); - std::wstring text = utf8_to_wide(e->text); + std::wstring text = unescape_enriched(utf8_to_wide(e->text)); core::dimension2d textsize = font->getDimension(text.c_str()); v2s32 offset((e->align.X - 1.0) * (textsize.Width / 2), (e->align.Y - 1.0) * (textsize.Height / 2)); @@ -355,11 +356,11 @@ void Hud::drawLuaElements(const v3s16 &camera_offset) (e->number >> 8) & 0xFF, (e->number >> 0) & 0xFF); core::rect size(0, 0, 200, 2 * text_height); - std::wstring text = utf8_to_wide(e->name); + std::wstring text = unescape_enriched(utf8_to_wide(e->name)); font->draw(text.c_str(), size + pos, color); std::ostringstream os; os << distance << e->text; - text = utf8_to_wide(os.str()); + text = unescape_enriched(utf8_to_wide(os.str())); pos.Y += text_height; font->draw(text.c_str(), size + pos, color); break; } diff --git a/src/unittest/test_utilities.cpp b/src/unittest/test_utilities.cpp index 1785997de..d73975b9f 100644 --- a/src/unittest/test_utilities.cpp +++ b/src/unittest/test_utilities.cpp @@ -45,6 +45,7 @@ public: void testStringAllowed(); void testAsciiPrintableHelper(); void testUTF8(); + void testRemoveEscapes(); void testWrapRows(); void testIsNumber(); void testIsPowerOfTwo(); @@ -71,6 +72,7 @@ void TestUtilities::runTests(IGameDef *gamedef) TEST(testStringAllowed); TEST(testAsciiPrintableHelper); TEST(testUTF8); + TEST(testRemoveEscapes); TEST(testWrapRows); TEST(testIsNumber); TEST(testIsPowerOfTwo); @@ -253,6 +255,23 @@ void TestUtilities::testUTF8() == "the shovel dug a crumbly node!"); } +void TestUtilities::testRemoveEscapes() +{ + UASSERT(unescape_enriched( + L"abc\x1bXdef") == L"abcdef"); + UASSERT(unescape_enriched( + L"abc\x1b(escaped)def") == L"abcdef"); + UASSERT(unescape_enriched( + L"abc\x1b((escaped with parenthesis\\))def") == L"abcdef"); + UASSERT(unescape_enriched( + L"abc\x1b(incomplete") == L"abc"); + UASSERT(unescape_enriched( + L"escape at the end\x1b") == L"escape at the end"); + // Nested escapes not supported + UASSERT(unescape_enriched( + L"abc\x1b(outer \x1b(inner escape)escape)def") == L"abcescape)def"); +} + void TestUtilities::testWrapRows() { UASSERT(wrap_rows("12345678",4) == "1234\n5678"); diff --git a/src/util/string.cpp b/src/util/string.cpp index c8f528a77..2c4143c76 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -729,33 +729,6 @@ static bool parseNamedColorString(const std::string &value, video::SColor &color return true; } -std::wstring removeChatEscapes(const std::wstring &s) { - std::wstring output; - size_t i = 0; - while (i < s.length()) { - if (s[i] == L'\v') { - ++i; - if (i == s.length()) continue; - if (s[i] == L'(') { - ++i; - while (i < s.length() && s[i] != L')') { - if (s[i] == L'\\') { - ++i; - } - ++i; - } - ++i; - } else { - ++i; - } - continue; - } - output += s[i]; - ++i; - } - return output; -} - void str_replace(std::string &str, char from, char to) { std::replace(str.begin(), str.end(), from, to); diff --git a/src/util/string.h b/src/util/string.h index 9e59ab20a..40ef3e4d3 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -386,14 +386,6 @@ inline void str_replace(std::string &str, const std::string &pattern, } } -/** - * Remove all chat escape sequences in \p s. - * - * @param s The string in which to remove escape sequences. - * @return \p s, with escape sequences removed. - */ -std::wstring removeChatEscapes(const std::wstring &s); - /** * Replace all occurrences of the character \p from in \p str with \p to. * @@ -476,7 +468,7 @@ inline std::string wrap_rows(const std::string &from, * Removes backslashes from an escaped string (FormSpec strings) */ template -inline std::basic_string unescape_string(std::basic_string &s) +inline std::basic_string unescape_string(const std::basic_string &s) { std::basic_string res; @@ -492,6 +484,40 @@ inline std::basic_string unescape_string(std::basic_string &s) return res; } +/** + * Remove all escape sequences in \p s. + * + * @param s The string in which to remove escape sequences. + * @return \p s, with escape sequences removed. + */ +template +std::basic_string unescape_enriched(const std::basic_string &s) +{ + std::basic_string output; + size_t i = 0; + while (i < s.length()) { + if (s[i] == '\x1b') { + ++i; + if (i == s.length()) continue; + if (s[i] == '(') { + ++i; + while (i < s.length() && s[i] != ')') { + if (s[i] == '\\') { + ++i; + } + ++i; + } + ++i; + } else { + ++i; + } + continue; + } + output += s[i]; + ++i; + } + return output; +} /** * Checks that all characters in \p to_check are a decimal digits. From 46da0e8b3b7ac9f833b660afd34b24095531bcb0 Mon Sep 17 00:00:00 2001 From: gregorycu Date: Sun, 24 Apr 2016 14:56:56 +1000 Subject: [PATCH 5/6] Make GUIEngine use pause_fps_max not fps_max --- src/guiEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index 84bc8488e..ba286a91c 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -361,7 +361,7 @@ void GUIEngine::cloudPreProcess() /******************************************************************************/ void GUIEngine::cloudPostProcess() { - float fps_max = g_settings->getFloat("fps_max"); + float fps_max = g_settings->getFloat("pause_fps_max"); // Time of frame without fps limit u32 busytime_u32; From 31c1fca6fd5e200c4f4b24d7ba62b36a16494ed2 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Thu, 21 Apr 2016 21:54:30 +0200 Subject: [PATCH 6/6] tile.cpp: Automatically upscale lower resolution texture --- doc/lua_api.txt | 1 + src/client/tile.cpp | 23 ++++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index fdc736906..47624496b 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -243,6 +243,7 @@ Example: default_dirt.png^default_grass_side.png `default_grass_side.png` is overlayed over `default_dirt.png`. +The texture with the lower resolution will be automatically upscaled to the higher resolution texture. ### Texture grouping Textures can be grouped together by enclosing them in `(` and `)`. diff --git a/src/client/tile.cpp b/src/client/tile.cpp index e6668063c..72d626da7 100644 --- a/src/client/tile.cpp +++ b/src/client/tile.cpp @@ -1175,7 +1175,28 @@ bool TextureSource::generateImagePart(std::string part_of_name, core::rect(pos_from, dim), video::SColor(255,255,255,255), NULL);*/ - blit_with_alpha(image, baseimg, pos_from, pos_to, dim); + + core::dimension2d dim_dst = baseimg->getDimension(); + if (dim == dim_dst) { + blit_with_alpha(image, baseimg, pos_from, pos_to, dim); + } else if (dim.Width * dim.Height < dim_dst.Width * dim_dst.Height) { + // Upscale overlying image + video::IImage* scaled_image = m_device->getVideoDriver()-> + createImage(video::ECF_A8R8G8B8, dim_dst); + image->copyToScaling(scaled_image); + + blit_with_alpha(scaled_image, baseimg, pos_from, pos_to, dim_dst); + scaled_image->drop(); + } else { + // Upscale base image + video::IImage* scaled_base = m_device->getVideoDriver()-> + createImage(video::ECF_A8R8G8B8, dim); + baseimg->copyToScaling(scaled_base); + baseimg->drop(); + baseimg = scaled_base; + + blit_with_alpha(image, baseimg, pos_from, pos_to, dim); + } } //cleanup image->drop();