diff options
Diffstat (limited to 'src/gui')
29 files changed, 259 insertions, 702 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 513b13e8e..4434b14a0 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -11,7 +11,6 @@ set(gui_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/guiButtonImage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiButtonItemImage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiChatConsole.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/guiConfirmRegistration.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiEditBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiEditBoxWithScrollbar.cpp ${CMAKE_CURRENT_SOURCE_DIR}/guiEngine.cpp diff --git a/src/gui/StyleSpec.h b/src/gui/StyleSpec.h index fc92a861b..7a45e07d1 100644 --- a/src/gui/StyleSpec.h +++ b/src/gui/StyleSpec.h @@ -45,6 +45,7 @@ public: BGIMG_PRESSED, // Note: Deprecated property FGIMG, FGIMG_HOVERED, // Note: Deprecated property + FGIMG_MIDDLE, FGIMG_PRESSED, // Note: Deprecated property ALPHA, CONTENT_OFFSET, @@ -101,6 +102,8 @@ public: return FGIMG; } else if (name == "fgimg_hovered") { return FGIMG_HOVERED; + } else if (name == "fgimg_middle") { + return FGIMG_MIDDLE; } else if (name == "fgimg_pressed") { return FGIMG_PRESSED; } else if (name == "alpha") { diff --git a/src/gui/guiAnimatedImage.cpp b/src/gui/guiAnimatedImage.cpp index b1447c45f..890763e71 100644 --- a/src/gui/guiAnimatedImage.cpp +++ b/src/gui/guiAnimatedImage.cpp @@ -9,40 +9,37 @@ #include <vector> GUIAnimatedImage::GUIAnimatedImage(gui::IGUIEnvironment *env, gui::IGUIElement *parent, - s32 id, const core::rect<s32> &rectangle, const std::string &texture_name, - s32 frame_count, s32 frame_duration, ISimpleTextureSource *tsrc) : - gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle), m_tsrc(tsrc) + s32 id, const core::rect<s32> &rectangle) : + gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle) { - m_texture = m_tsrc->getTexture(texture_name); - - m_frame_count = std::max(frame_count, 1); - m_frame_duration = std::max(frame_duration, 0); - - if (m_texture != nullptr) { - core::dimension2d<u32> size = m_texture->getOriginalSize(); - if (size.Height < (u64)m_frame_count) - m_frame_count = size.Height; - } else { - // No need to step an animation if we have nothing to draw - m_frame_count = 1; - } } void GUIAnimatedImage::draw() { - // Render the current frame - if (m_texture != nullptr) { - video::IVideoDriver *driver = Environment->getVideoDriver(); + if (m_texture == nullptr) + return; - const video::SColor color(255, 255, 255, 255); - const video::SColor colors[] = {color, color, color, color}; + video::IVideoDriver *driver = Environment->getVideoDriver(); + + core::dimension2d<u32> size = m_texture->getOriginalSize(); + + if ((u32)m_frame_count > size.Height) + m_frame_count = size.Height; + if (m_frame_idx >= m_frame_count) + m_frame_idx = m_frame_count - 1; - core::dimension2d<u32> size = m_texture->getOriginalSize(); - size.Height /= m_frame_count; + size.Height /= m_frame_count; - draw2DImageFilterScaled(driver, m_texture, AbsoluteRect, - core::rect<s32>(core::position2d<s32>(0, size.Height * m_frame_idx), size), - NoClip ? nullptr : &AbsoluteClippingRect, colors, true); + core::rect<s32> rect(core::position2d<s32>(0, size.Height * m_frame_idx), size); + core::rect<s32> *cliprect = NoClip ? nullptr : &AbsoluteClippingRect; + + if (m_middle.getArea() == 0) { + const video::SColor color(255, 255, 255, 255); + const video::SColor colors[] = {color, color, color, color}; + draw2DImageFilterScaled(driver, m_texture, AbsoluteRect, rect, cliprect, + colors, true); + } else { + draw2DImage9Slice(driver, m_texture, AbsoluteRect, rect, m_middle, cliprect); } // Step the animation @@ -55,7 +52,7 @@ void GUIAnimatedImage::draw() m_global_time = new_global_time; // Advance by the number of elapsed frames, looping if necessary - m_frame_idx += u32(m_frame_time / m_frame_duration); + m_frame_idx += (u32)(m_frame_time / m_frame_duration); m_frame_idx %= m_frame_count; // If 1 or more frames have elapsed, reset the frame time counter with @@ -63,11 +60,3 @@ void GUIAnimatedImage::draw() m_frame_time %= m_frame_duration; } } - - -void GUIAnimatedImage::setFrameIndex(s32 frame) -{ - s32 idx = std::max(frame, 0); - if (idx > 0 && idx < m_frame_count) - m_frame_idx = idx; -} diff --git a/src/gui/guiAnimatedImage.h b/src/gui/guiAnimatedImage.h index f8e6a506e..885aedece 100644 --- a/src/gui/guiAnimatedImage.h +++ b/src/gui/guiAnimatedImage.h @@ -1,6 +1,7 @@ #pragma once #include "irrlichttypes_extrabloated.h" +#include <algorithm> #include <string> class ISimpleTextureSource; @@ -8,21 +9,33 @@ class ISimpleTextureSource; class GUIAnimatedImage : public gui::IGUIElement { public: GUIAnimatedImage(gui::IGUIEnvironment *env, gui::IGUIElement *parent, - s32 id, const core::rect<s32> &rectangle, const std::string &texture_name, - s32 frame_count, s32 frame_duration, ISimpleTextureSource *tsrc); + s32 id, const core::rect<s32> &rectangle); virtual void draw() override; - void setFrameIndex(s32 frame); + void setTexture(video::ITexture *texture) { m_texture = texture; }; + video::ITexture *getTexture() const { return m_texture; }; + + void setMiddleRect(const core::rect<s32> &middle) { m_middle = middle; }; + core::rect<s32> getMiddleRect() const { return m_middle; }; + + void setFrameDuration(u64 duration) { m_frame_duration = duration; }; + u64 getFrameDuration() const { return m_frame_duration; }; + + void setFrameCount(s32 count) { m_frame_count = std::max(count, 1); }; + s32 getFrameCount() const { return m_frame_count; }; + + void setFrameIndex(s32 frame) { m_frame_idx = std::max(frame, 0); }; s32 getFrameIndex() const { return m_frame_idx; }; private: - ISimpleTextureSource *m_tsrc; - video::ITexture *m_texture = nullptr; + u64 m_global_time = 0; s32 m_frame_idx = 0; s32 m_frame_count = 1; - u64 m_frame_duration = 1; + u64 m_frame_duration = 0; u64 m_frame_time = 0; + + core::rect<s32> m_middle; }; diff --git a/src/gui/guiBackgroundImage.cpp b/src/gui/guiBackgroundImage.cpp index 21c1e88cf..8d0d1c010 100644 --- a/src/gui/guiBackgroundImage.cpp +++ b/src/gui/guiBackgroundImage.cpp @@ -44,25 +44,19 @@ void GUIBackgroundImage::draw() core::rect<s32> rect = AbsoluteRect; if (m_autoclip) - rect.LowerRightCorner += Parent->getAbsolutePosition().getSize(); + rect.LowerRightCorner += Parent->getAbsoluteClippingRect().getSize(); video::IVideoDriver *driver = Environment->getVideoDriver(); + core::rect<s32> srcrect(core::position2d<s32>(0, 0), + core::dimension2di(texture->getOriginalSize())); + if (m_middle.getArea() == 0) { const video::SColor color(255, 255, 255, 255); const video::SColor colors[] = {color, color, color, color}; - draw2DImageFilterScaled(driver, texture, rect, - core::rect<s32>(core::position2d<s32>(0, 0), - core::dimension2di(texture->getOriginalSize())), - nullptr, colors, true); + draw2DImageFilterScaled(driver, texture, rect, srcrect, nullptr, colors, true); } else { - core::rect<s32> middle = m_middle; - // `-x` is interpreted as `w - x` - if (middle.LowerRightCorner.X < 0) - middle.LowerRightCorner.X += texture->getOriginalSize().Width; - if (middle.LowerRightCorner.Y < 0) - middle.LowerRightCorner.Y += texture->getOriginalSize().Height; - draw2DImage9Slice(driver, texture, rect, middle); + draw2DImage9Slice(driver, texture, rect, srcrect, m_middle); } IGUIElement::draw(); diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index ba95b81c3..c38d901c4 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -320,15 +320,9 @@ void GUIButton::draw() sourceRect, &AbsoluteClippingRect,
image_colors, UseAlphaChannel);
} else {
- core::rect<s32> middle = BgMiddle;
- // `-x` is interpreted as `w - x`
- if (middle.LowerRightCorner.X < 0)
- middle.LowerRightCorner.X += texture->getOriginalSize().Width;
- if (middle.LowerRightCorner.Y < 0)
- middle.LowerRightCorner.Y += texture->getOriginalSize().Height;
draw2DImage9Slice(driver, texture,
ScaleImage ? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
- middle, &AbsoluteClippingRect, image_colors);
+ sourceRect, BgMiddle, &AbsoluteClippingRect, image_colors);
}
// END PATCH
}
diff --git a/src/gui/guiButtonImage.cpp b/src/gui/guiButtonImage.cpp index b507ffece..4ab770a99 100644 --- a/src/gui/guiButtonImage.cpp +++ b/src/gui/guiButtonImage.cpp @@ -32,15 +32,15 @@ using namespace gui; GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc, bool noclip) - : GUIButton (environment, parent, id, rectangle, tsrc, noclip) + : GUIButton(environment, parent, id, rectangle, tsrc, noclip) { - m_image = Environment->addImage( - core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), this); - m_image->setScaleImage(isScalingImage()); + GUIButton::setScaleImage(true); + m_image = new GUIAnimatedImage(environment, this, id, rectangle); sendToBack(m_image); } -void GUIButtonImage::setForegroundImage(video::ITexture *image) +void GUIButtonImage::setForegroundImage(video::ITexture *image, + const core::rect<s32> &middle) { if (image == m_foreground_image) return; @@ -52,11 +52,12 @@ void GUIButtonImage::setForegroundImage(video::ITexture *image) m_foreground_image->drop(); m_foreground_image = image; - m_image->setImage(image); + m_image->setTexture(image); + m_image->setMiddleRect(middle); } //! Set element properties from a StyleSpec -void GUIButtonImage::setFromStyle(const StyleSpec& style) +void GUIButtonImage::setFromStyle(const StyleSpec &style) { GUIButton::setFromStyle(style); @@ -67,19 +68,13 @@ void GUIButtonImage::setFromStyle(const StyleSpec& style) getTextureSource()); setForegroundImage(guiScalingImageButton(driver, texture, - AbsoluteRect.getWidth(), AbsoluteRect.getHeight())); - setScaleImage(true); + AbsoluteRect.getWidth(), AbsoluteRect.getHeight()), + style.getRect(StyleSpec::FGIMG_MIDDLE, m_image->getMiddleRect())); } else { - setForegroundImage(nullptr); + setForegroundImage(); } } -void GUIButtonImage::setScaleImage(bool scaleImage) -{ - GUIButton::setScaleImage(scaleImage); - m_image->setScaleImage(scaleImage); -} - GUIButtonImage *GUIButtonImage::addButton(IGUIEnvironment *environment, const core::rect<s32> &rectangle, ISimpleTextureSource *tsrc, IGUIElement *parent, s32 id, const wchar_t *text, diff --git a/src/gui/guiButtonImage.h b/src/gui/guiButtonImage.h index 59a25b4f0..554934518 100644 --- a/src/gui/guiButtonImage.h +++ b/src/gui/guiButtonImage.h @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiButton.h" #include "IGUIButton.h" +#include "guiAnimatedImage.h" using namespace irr; @@ -32,12 +33,11 @@ public: s32 id, core::rect<s32> rectangle, ISimpleTextureSource *tsrc, bool noclip = false); - void setForegroundImage(video::ITexture *image = nullptr); + void setForegroundImage(video::ITexture *image = nullptr, + const core::rect<s32> &middle = core::rect<s32>()); //! Set element properties from a StyleSpec - virtual void setFromStyle(const StyleSpec& style) override; - - virtual void setScaleImage(bool scaleImage=true) override; + virtual void setFromStyle(const StyleSpec &style) override; //! Do not drop returned handle static GUIButtonImage *addButton(gui::IGUIEnvironment *environment, @@ -47,5 +47,5 @@ public: private: video::ITexture *m_foreground_image = nullptr; - gui::IGUIImage *m_image; + GUIAnimatedImage *m_image; }; diff --git a/src/gui/guiChatConsole.cpp b/src/gui/guiChatConsole.cpp index 01e10ea2e..280f7e45b 100644 --- a/src/gui/guiChatConsole.cpp +++ b/src/gui/guiChatConsole.cpp @@ -76,9 +76,9 @@ GUIChatConsole::GUIChatConsole( m_background_color.setBlue(clamp_u8(myround(console_color.Z))); } - u16 chat_font_size = g_settings->getU16("chat_font_size"); + const u16 chat_font_size = g_settings->getU16("chat_font_size"); m_font = g_fontengine->getFont(chat_font_size != 0 ? - chat_font_size : FONT_SIZE_UNSPECIFIED, FM_Mono); + rangelim(chat_font_size, 5, 72) : FONT_SIZE_UNSPECIFIED, FM_Mono); if (!m_font) { errorstream << "GUIChatConsole: Unable to load mono font" << std::endl; diff --git a/src/gui/guiConfirmRegistration.cpp b/src/gui/guiConfirmRegistration.cpp deleted file mode 100644 index b8887a4af..000000000 --- a/src/gui/guiConfirmRegistration.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* -Minetest -Copyright (C) 2018 srifqi, Muhammad Rifqi Priyo Susanto - <muhammadrifqipriyosusanto@gmail.com> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#include "guiConfirmRegistration.h" -#include "client/client.h" -#include "guiButton.h" -#include <IGUICheckBox.h> -#include <IGUIButton.h> -#include <IGUIStaticText.h> -#include <IGUIFont.h> -#include "guiEditBoxWithScrollbar.h" -#include "porting.h" - -#ifdef HAVE_TOUCHSCREENGUI - #include "client/renderingengine.h" -#endif - -#include "gettext.h" - -// Continuing from guiPasswordChange.cpp -const int ID_confirmPassword = 262; -const int ID_confirm = 263; -const int ID_intotext = 264; -const int ID_cancel = 265; -const int ID_message = 266; - -GUIConfirmRegistration::GUIConfirmRegistration(gui::IGUIEnvironment *env, - gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client, - const std::string &playername, const std::string &password, - bool *aborted, ISimpleTextureSource *tsrc) : - GUIModalMenu(env, parent, id, menumgr), - m_client(client), m_playername(playername), m_password(password), - m_aborted(aborted), m_tsrc(tsrc) -{ -#ifdef HAVE_TOUCHSCREENGUI - m_touchscreen_visible = false; -#endif -} - -GUIConfirmRegistration::~GUIConfirmRegistration() -{ - removeChildren(); -} - -void GUIConfirmRegistration::removeChildren() -{ - const core::list<gui::IGUIElement *> &children = getChildren(); - core::list<gui::IGUIElement *> children_copy; - for (gui::IGUIElement *i : children) - children_copy.push_back(i); - for (gui::IGUIElement *i : children_copy) - i->remove(); -} - -void GUIConfirmRegistration::regenerateGui(v2u32 screensize) -{ - acceptInput(); - removeChildren(); - - /* - Calculate new sizes and positions - */ -#ifdef HAVE_TOUCHSCREENGUI - const float s = m_gui_scale * RenderingEngine::getDisplayDensity() / 2; -#else - const float s = m_gui_scale; -#endif - DesiredRect = core::rect<s32>( - screensize.X / 2 - 600 * s / 2, - screensize.Y / 2 - 360 * s / 2, - screensize.X / 2 + 600 * s / 2, - screensize.Y / 2 + 360 * s / 2 - ); - recalculateAbsolutePosition(false); - - v2s32 size = DesiredRect.getSize(); - v2s32 topleft_client(0, 0); - - const wchar_t *text; - - /* - Add stuff - */ - s32 ypos = 30 * s; - { - core::rect<s32> rect2(0, 0, 540 * s, 180 * s); - rect2 += topleft_client + v2s32(30 * s, ypos); - static const std::string info_text_template = strgettext( - "You are about to join this server with the name \"%s\" for the " - "first time.\n" - "If you proceed, a new account using your credentials will be " - "created on this server.\n" - "Please retype your password and click 'Register and Join' to " - "confirm account creation, or click 'Cancel' to abort."); - char info_text_buf[1024]; - porting::mt_snprintf(info_text_buf, sizeof(info_text_buf), - info_text_template.c_str(), m_playername.c_str()); - - std::wstring info_text_w = utf8_to_wide(info_text_buf); - gui::IGUIEditBox *e = new GUIEditBoxWithScrollBar(info_text_w.c_str(), - true, Environment, this, ID_intotext, rect2, false, true); - e->drop(); - e->setMultiLine(true); - e->setWordWrap(true); - e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); - } - - ypos += 200 * s; - { - core::rect<s32> rect2(0, 0, 540 * s, 30 * s); - rect2 += topleft_client + v2s32(30 * s, ypos); - gui::IGUIEditBox *e = Environment->addEditBox(m_pass_confirm.c_str(), - rect2, true, this, ID_confirmPassword); - e->setPasswordBox(true); - Environment->setFocus(e); - } - - ypos += 50 * s; - { - core::rect<s32> rect2(0, 0, 230 * s, 35 * s); - rect2 = rect2 + v2s32(size.X / 2 - 220 * s, ypos); - text = wgettext("Register and Join"); - GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_confirm, text); - delete[] text; - } - { - core::rect<s32> rect2(0, 0, 120 * s, 35 * s); - rect2 = rect2 + v2s32(size.X / 2 + 70 * s, ypos); - text = wgettext("Cancel"); - GUIButton::addButton(Environment, rect2, m_tsrc, this, ID_cancel, text); - delete[] text; - } - { - core::rect<s32> rect2(0, 0, 500 * s, 40 * s); - rect2 += topleft_client + v2s32(30 * s, ypos + 40 * s); - text = wgettext("Passwords do not match!"); - IGUIElement *e = Environment->addStaticText( - text, rect2, false, true, this, ID_message); - e->setVisible(false); - delete[] text; - } -} - -void GUIConfirmRegistration::drawMenu() -{ - gui::IGUISkin *skin = Environment->getSkin(); - if (!skin) - return; - video::IVideoDriver *driver = Environment->getVideoDriver(); - - video::SColor bgcolor(140, 0, 0, 0); - driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect); - - gui::IGUIElement::draw(); -#ifdef __ANDROID__ - getAndroidUIInput(); -#endif -} - -void GUIConfirmRegistration::closeMenu(bool goNext) -{ - if (goNext) { - m_client->confirmRegistration(); - } else { - *m_aborted = true; - infostream << "Connect aborted [Escape]" << std::endl; - } - quitMenu(); -} - -void GUIConfirmRegistration::acceptInput() -{ - gui::IGUIElement *e; - e = getElementFromId(ID_confirmPassword); - if (e) - m_pass_confirm = e->getText(); -} - -bool GUIConfirmRegistration::processInput() -{ - if (utf8_to_wide(m_password) != m_pass_confirm) { - gui::IGUIElement *e = getElementFromId(ID_message); - if (e) - e->setVisible(true); - return false; - } - return true; -} - -bool GUIConfirmRegistration::OnEvent(const SEvent &event) -{ - if (event.EventType == EET_KEY_INPUT_EVENT) { - // clang-format off - if ((event.KeyInput.Key == KEY_ESCAPE || - event.KeyInput.Key == KEY_CANCEL) && - event.KeyInput.PressedDown) { - closeMenu(false); - return true; - } - // clang-format on - if (event.KeyInput.Key == KEY_RETURN && event.KeyInput.PressedDown) { - acceptInput(); - if (processInput()) - closeMenu(true); - return true; - } - } - - if (event.EventType != EET_GUI_EVENT) - return Parent ? Parent->OnEvent(event) : false; - - if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { - if (!canTakeFocus(event.GUIEvent.Element)) { - infostream << "GUIConfirmRegistration: Not allowing focus change." - << std::endl; - // Returning true disables focus change - return true; - } - } else if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED) { - switch (event.GUIEvent.Caller->getID()) { - case ID_confirm: - acceptInput(); - if (processInput()) - closeMenu(true); - return true; - case ID_cancel: - closeMenu(false); - return true; - } - } else if (event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) { - switch (event.GUIEvent.Caller->getID()) { - case ID_confirmPassword: - acceptInput(); - if (processInput()) - closeMenu(true); - return true; - } - } - - return false; -} - -#ifdef __ANDROID__ -bool GUIConfirmRegistration::getAndroidUIInput() -{ - if (!hasAndroidUIInput() || m_jni_field_name != "password") - return false; - - // still waiting - if (porting::getInputDialogState() == -1) - return true; - - m_jni_field_name.clear(); - - gui::IGUIElement *e = getElementFromId(ID_confirmPassword); - - if (!e || e->getType() != irr::gui::EGUIET_EDIT_BOX) - return false; - - std::string text = porting::getInputDialogValue(); - e->setText(utf8_to_wide(text).c_str()); - return false; -} -#endif diff --git a/src/gui/guiConfirmRegistration.h b/src/gui/guiConfirmRegistration.h deleted file mode 100644 index d8387201d..000000000 --- a/src/gui/guiConfirmRegistration.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -Minetest -Copyright (C) 2018 srifqi, Muhammad Rifqi Priyo Susanto - <muhammadrifqipriyosusanto@gmail.com> - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License along -with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -#pragma once - -#include "irrlichttypes_extrabloated.h" -#include "modalMenu.h" -#include <string> - -class Client; -class ISimpleTextureSource; - -class GUIConfirmRegistration : public GUIModalMenu -{ -public: - GUIConfirmRegistration(gui::IGUIEnvironment *env, gui::IGUIElement *parent, - s32 id, IMenuManager *menumgr, Client *client, - const std::string &playername, const std::string &password, - bool *aborted, ISimpleTextureSource *tsrc); - ~GUIConfirmRegistration(); - - void removeChildren(); - /* - Remove and re-add (or reposition) stuff - */ - void regenerateGui(v2u32 screensize); - - void drawMenu(); - - void closeMenu(bool goNext); - - void acceptInput(); - - bool processInput(); - - bool OnEvent(const SEvent &event); -#ifdef __ANDROID__ - bool getAndroidUIInput(); -#endif - -private: - std::wstring getLabelByID(s32 id) { return L""; } - std::string getNameByID(s32 id) { return "password"; } - - Client *m_client = nullptr; - const std::string &m_playername; - const std::string &m_password; - bool *m_aborted = nullptr; - std::wstring m_pass_confirm = L""; - ISimpleTextureSource *m_tsrc; -}; diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index b65b31304..01f3f8fd5 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -622,9 +622,9 @@ void GUIEngine::updateTopLeftTextSize() } /******************************************************************************/ -s32 GUIEngine::playSound(const SimpleSoundSpec &spec, bool looped) +s32 GUIEngine::playSound(const SimpleSoundSpec &spec) { - s32 handle = m_sound_manager->playSound(spec, looped); + s32 handle = m_sound_manager->playSound(spec); return handle; } diff --git a/src/gui/guiEngine.h b/src/gui/guiEngine.h index d7e6485ef..2f182ca81 100644 --- a/src/gui/guiEngine.h +++ b/src/gui/guiEngine.h @@ -296,7 +296,7 @@ private: clouddata m_cloud; /** start playing a sound and return handle */ - s32 playSound(const SimpleSoundSpec &spec, bool looped); + s32 playSound(const SimpleSoundSpec &spec); /** stop playing a sound started with playSound() */ void stopSound(s32 handle); diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index 85bd04900..1f9914e72 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -127,7 +127,8 @@ GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick, GUIFormSpecMenu::~GUIFormSpecMenu() { - removeChildren(); + removeAllChildren(); + removeTooltip(); for (auto &table_it : m_tables) table_it.second->drop(); @@ -137,8 +138,6 @@ GUIFormSpecMenu::~GUIFormSpecMenu() checkbox_it.second->drop(); for (auto &scrollbar_it : m_scrollbars) scrollbar_it.second->drop(); - for (auto &background_it : m_backgrounds) - background_it->drop(); for (auto &tooltip_rect_it : m_tooltip_rects) tooltip_rect_it.first->drop(); for (auto &clickthrough_it : m_clickthrough_elements) @@ -176,14 +175,8 @@ void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client, } } -void GUIFormSpecMenu::removeChildren() +void GUIFormSpecMenu::removeTooltip() { - const core::list<gui::IGUIElement*> &children = getChildren(); - - while (!children.empty()) { - (*children.getLast())->remove(); - } - if (m_tooltip_element) { m_tooltip_element->remove(); m_tooltip_element->drop(); @@ -201,16 +194,7 @@ void GUIFormSpecMenu::setInitialFocus() // 5. first focusable (not statictext, not tabheader) // 6. first child element - core::list<gui::IGUIElement*> children = getChildren(); - - // in case "children" contains any NULL elements, remove them - for (core::list<gui::IGUIElement*>::Iterator it = children.begin(); - it != children.end();) { - if (*it) - ++it; - else - it = children.erase(it); - } + const auto& children = getChildren(); // 1. first empty editbox for (gui::IGUIElement *it : children) { @@ -238,8 +222,7 @@ void GUIFormSpecMenu::setInitialFocus() } // 4. last button - for (core::list<gui::IGUIElement*>::Iterator it = children.getLast(); - it != children.end(); --it) { + for (auto it = children.rbegin(); it != children.rend(); ++it) { if ((*it)->getType() == gui::EGUIET_BUTTON) { Environment->setFocus(*it); return; @@ -259,7 +242,7 @@ void GUIFormSpecMenu::setInitialFocus() if (children.empty()) Environment->setFocus(this); else - Environment->setFocus(*(children.begin())); + Environment->setFocus(children.front()); } GUITable* GUIFormSpecMenu::getTable(const std::string &tablename) @@ -784,101 +767,99 @@ void GUIFormSpecMenu::parseScrollBarOptions(parserData* data, const std::string void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element) { std::vector<std::string> parts; - if (!precheckElement("image", element, 2, 3, parts)) + if (!precheckElement("image", element, 2, 4, parts)) return; - if (parts.size() >= 3) { - std::vector<std::string> v_pos = split(parts[0],','); - std::vector<std::string> v_geom = split(parts[1],','); - std::string name = unescape_string(parts[2]); + size_t offset = parts.size() >= 3; + + std::vector<std::string> v_pos = split(parts[0],','); + MY_CHECKPOS("image", 0); - MY_CHECKPOS("image", 0); + std::vector<std::string> v_geom; + if (parts.size() >= 3) { + v_geom = split(parts[1],','); MY_CHECKGEOM("image", 1); + } - v2s32 pos; - v2s32 geom; + std::string name = unescape_string(parts[1 + offset]); + video::ITexture *texture = m_tsrc->getTexture(name); - if (data->real_coordinates) { - pos = getRealCoordinateBasePos(v_pos); - geom = getRealCoordinateGeometry(v_geom); + v2s32 pos; + v2s32 geom; + + if (parts.size() < 3) { + if (texture != nullptr) { + core::dimension2du dim = texture->getOriginalSize(); + geom.X = dim.Width; + geom.Y = dim.Height; } else { - pos = getElementBasePos(&v_pos); - geom.X = stof(v_geom[0]) * (float)imgsize.X; - geom.Y = stof(v_geom[1]) * (float)imgsize.Y; + geom = v2s32(0); } + } - if (!data->explicit_size) - warningstream<<"invalid use of image without a size[] element"<<std::endl; - - video::ITexture *texture = m_tsrc->getTexture(name); - if (!texture) { - errorstream << "GUIFormSpecMenu::parseImage() Unable to load texture:" - << std::endl << "\t" << name << std::endl; - return; + if (data->real_coordinates) { + pos = getRealCoordinateBasePos(v_pos); + if (parts.size() >= 3) + geom = getRealCoordinateGeometry(v_geom); + } else { + pos = getElementBasePos(&v_pos); + if (parts.size() >= 3) { + geom.X = stof(v_geom[0]) * (float)imgsize.X; + geom.Y = stof(v_geom[1]) * (float)imgsize.Y; } - - FieldSpec spec( - name, - L"", - L"", - 258 + m_fields.size(), - 1 - ); - core::rect<s32> rect(pos, pos + geom); - gui::IGUIImage *e = Environment->addImage(rect, data->current_parent, - spec.fid, 0, true); - e->setImage(texture); - e->setScaleImage(true); - auto style = getDefaultStyleForElement("image", spec.fname); - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); - m_fields.push_back(spec); - - // images should let events through - e->grab(); - m_clickthrough_elements.push_back(e); - return; } - // Else: 2 arguments in "parts" - - std::vector<std::string> v_pos = split(parts[0],','); - std::string name = unescape_string(parts[1]); - - MY_CHECKPOS("image", 0); - - v2s32 pos = getElementBasePos(&v_pos); - if (!data->explicit_size) - warningstream<<"invalid use of image without a size[] element"<<std::endl; - - video::ITexture *texture = m_tsrc->getTexture(name); - if (!texture) { - errorstream << "GUIFormSpecMenu::parseImage() Unable to load texture:" - << std::endl << "\t" << name << std::endl; - return; - } + warningstream << "Invalid use of image without a size[] element" << std::endl; FieldSpec spec( name, L"", L"", - 258 + m_fields.size() + 258 + m_fields.size(), + 1 ); - gui::IGUIImage *e = Environment->addImage(texture, pos, true, - data->current_parent, spec.fid, 0); + + core::rect<s32> rect = core::rect<s32>(pos, pos + geom); + + core::rect<s32> middle; + if (parts.size() >= 4) + parseMiddleRect(parts[3], &middle); + + // Temporary fix for issue #12581 in 5.6.0. + // Use legacy image when not rendering 9-slice image because GUIAnimatedImage + // uses NNAA filter which causes visual artifacts when image uses alpha blending. + + gui::IGUIElement *e; + if (middle.getArea() > 0) { + GUIAnimatedImage *image = new GUIAnimatedImage(Environment, data->current_parent, + spec.fid, rect); + + image->setTexture(texture); + image->setMiddleRect(middle); + e = image; + } + else { + gui::IGUIImage *image = Environment->addImage(rect, data->current_parent, spec.fid, nullptr, true); + image->setImage(texture); + image->setScaleImage(true); + image->grab(); // compensate for drop in addImage + e = image; + } + auto style = getDefaultStyleForElement("image", spec.fname); e->setNotClipped(style.getBool(StyleSpec::NOCLIP, m_formspec_version < 3)); - m_fields.push_back(spec); - // images should let events through - e->grab(); + // Animated images should let events through m_clickthrough_elements.push_back(e); + + m_fields.push_back(spec); } void GUIFormSpecMenu::parseAnimatedImage(parserData *data, const std::string &element) { std::vector<std::string> parts; - if (!precheckElement("animated_image", element, 6, 7, parts)) + if (!precheckElement("animated_image", element, 6, 8, parts)) return; std::vector<std::string> v_pos = split(parts[0], ','); @@ -904,7 +885,8 @@ void GUIFormSpecMenu::parseAnimatedImage(parserData *data, const std::string &el } if (!data->explicit_size) - warningstream << "Invalid use of animated_image without a size[] element" << std::endl; + warningstream << "Invalid use of animated_image without a size[] element" + << std::endl; FieldSpec spec( name, @@ -917,9 +899,17 @@ void GUIFormSpecMenu::parseAnimatedImage(parserData *data, const std::string &el core::rect<s32> rect = core::rect<s32>(pos, pos + geom); - GUIAnimatedImage *e = new GUIAnimatedImage(Environment, data->current_parent, spec.fid, - rect, texture_name, frame_count, frame_duration, m_tsrc); + core::rect<s32> middle; + if (parts.size() >= 8) + parseMiddleRect(parts[7], &middle); + + GUIAnimatedImage *e = new GUIAnimatedImage(Environment, data->current_parent, + spec.fid, rect); + e->setTexture(m_tsrc->getTexture(texture_name)); + e->setMiddleRect(middle); + e->setFrameDuration(frame_duration); + e->setFrameCount(frame_count); if (parts.size() >= 7) e->setFrameIndex(stoi(parts[6]) - 1); @@ -1044,6 +1034,35 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, m_fields.push_back(spec); } +bool GUIFormSpecMenu::parseMiddleRect(const std::string &value, core::rect<s32> *parsed_rect) +{ + core::rect<s32> rect; + std::vector<std::string> v_rect = split(value, ','); + + if (v_rect.size() == 1) { + s32 x = stoi(v_rect[0]); + rect.UpperLeftCorner = core::vector2di(x, x); + rect.LowerRightCorner = core::vector2di(-x, -x); + } else if (v_rect.size() == 2) { + s32 x = stoi(v_rect[0]); + s32 y = stoi(v_rect[1]); + rect.UpperLeftCorner = core::vector2di(x, y); + rect.LowerRightCorner = core::vector2di(-x, -y); + // `-x` is interpreted as `w - x` + } else if (v_rect.size() == 4) { + rect.UpperLeftCorner = core::vector2di(stoi(v_rect[0]), stoi(v_rect[1])); + rect.LowerRightCorner = core::vector2di(stoi(v_rect[2]), stoi(v_rect[3])); + } else { + warningstream << "Invalid rectangle string format: \"" << value + << "\"" << std::endl; + return false; + } + + *parsed_rect = rect; + + return true; +} + void GUIFormSpecMenu::parseBackground(parserData* data, const std::string &element) { std::vector<std::string> parts; @@ -1085,25 +1104,8 @@ void GUIFormSpecMenu::parseBackground(parserData* data, const std::string &eleme } core::rect<s32> middle; - if (parts.size() >= 5) { - std::vector<std::string> v_middle = split(parts[4], ','); - if (v_middle.size() == 1) { - s32 x = stoi(v_middle[0]); - middle.UpperLeftCorner = core::vector2di(x, x); - middle.LowerRightCorner = core::vector2di(-x, -x); - } else if (v_middle.size() == 2) { - s32 x = stoi(v_middle[0]); - s32 y = stoi(v_middle[1]); - middle.UpperLeftCorner = core::vector2di(x, y); - middle.LowerRightCorner = core::vector2di(-x, -y); - // `-x` is interpreted as `w - x` - } else if (v_middle.size() == 4) { - middle.UpperLeftCorner = core::vector2di(stoi(v_middle[0]), stoi(v_middle[1])); - middle.LowerRightCorner = core::vector2di(stoi(v_middle[2]), stoi(v_middle[3])); - } else { - warningstream << "Invalid rectangle given to middle param of background[] element" << std::endl; - } - } + if (parts.size() >= 5) + parseMiddleRect(parts[4], &middle); if (!data->explicit_size && !clip) warningstream << "invalid use of unclipped background without a size[] element" << std::endl; @@ -1124,17 +1126,15 @@ void GUIFormSpecMenu::parseBackground(parserData* data, const std::string &eleme rect = core::rect<s32>(-pos, pos); } - GUIBackgroundImage *e = new GUIBackgroundImage(Environment, this, spec.fid, - rect, name, middle, m_tsrc, clip); + GUIBackgroundImage *e = new GUIBackgroundImage(Environment, data->background_parent.get(), + spec.fid, rect, name, middle, m_tsrc, clip); FATAL_ERROR_IF(!e, "Failed to create background formspec element"); e->setNotClipped(true); - e->setVisible(false); // the element is drawn manually before all others - - m_backgrounds.push_back(e); m_fields.push_back(spec); + e->drop(); } void GUIFormSpecMenu::parseTableOptions(parserData* data, const std::string &element) @@ -1686,7 +1686,7 @@ void GUIFormSpecMenu::parseField(parserData* data, const std::string &element, void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &element) { - MY_CHECKCLIENT("list"); + MY_CHECKCLIENT("hypertext"); std::vector<std::string> parts; if (!precheckElement("hypertext", element, 4, 4, parts)) @@ -1746,25 +1746,27 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) return; std::vector<std::string> v_pos = split(parts[0],','); - std::string text = parts[1]; MY_CHECKPOS("label",0); if(!data->explicit_size) warningstream<<"invalid use of label without a size[] element"<<std::endl; - std::vector<std::string> lines = split(text, '\n'); - auto style = getDefaultStyleForElement("label", ""); gui::IGUIFont *font = style.getFont(); if (!font) font = m_font; - for (unsigned int i = 0; i != lines.size(); i++) { - std::wstring wlabel_colors = translate_string( - utf8_to_wide(unescape_string(lines[i]))); - // Without color escapes to get the font dimensions - std::wstring wlabel_plain = unescape_enriched(wlabel_colors); + EnrichedString str(unescape_string(utf8_to_wide(parts[1]))); + size_t str_pos = 0; + + for (size_t i = 0; str_pos < str.size(); ++i) { + // Split per line + size_t str_nl = str.getString().find(L'\n', str_pos); + if (str_nl == std::wstring::npos) + str_nl = str.getString().size(); + EnrichedString line = str.substr(str_pos, str_nl - str_pos); + str_pos += line.size() + 1; core::rect<s32> rect; @@ -1781,7 +1783,7 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) rect = core::rect<s32>( pos.X, pos.Y, - pos.X + font->getDimension(wlabel_plain.c_str()).Width, + pos.X + font->getDimension(line.c_str()).Width, pos.Y + imgsize.Y); } else { @@ -1803,19 +1805,19 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element) rect = core::rect<s32>( pos.X, pos.Y - m_btn_height, - pos.X + font->getDimension(wlabel_plain.c_str()).Width, + pos.X + font->getDimension(line.c_str()).Width, pos.Y + m_btn_height); } FieldSpec spec( "", - wlabel_colors, + L"", L"", 258 + m_fields.size(), 4 ); gui::IGUIStaticText *e = gui::StaticText::add(Environment, - spec.flabel.c_str(), rect, false, false, data->current_parent, + line, rect, false, false, data->current_parent, spec.fid); e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER); @@ -3049,7 +3051,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) } // Remove children - removeChildren(); + removeAllChildren(); + removeTooltip(); for (auto &table_it : m_tables) table_it.second->drop(); @@ -3059,8 +3062,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) checkbox_it.second->drop(); for (auto &scrollbar_it : m_scrollbars) scrollbar_it.second->drop(); - for (auto &background_it : m_backgrounds) - background_it->drop(); for (auto &tooltip_rect_it : m_tooltip_rects) tooltip_rect_it.first->drop(); for (auto &clickthrough_it : m_clickthrough_elements) @@ -3082,7 +3083,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) mydata.current_parent = this; m_inventorylists.clear(); - m_backgrounds.clear(); m_tables.clear(); m_checkboxes.clear(); m_scrollbars.clear(); @@ -3229,8 +3229,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) offset = v2s32(0,0); } - double gui_scaling = g_settings->getFloat("gui_scaling"); - double screen_dpi = RenderingEngine::getDisplayDensity() * 96; + const double gui_scaling = g_settings->getFloat("gui_scaling", 0.5f, 42.0f); + const double screen_dpi = RenderingEngine::getDisplayDensity() * 96; double use_imgsize; if (m_lock) { @@ -3336,10 +3336,19 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) gui::IGUIFont *old_font = skin->getFont(); skin->setFont(m_font); + // Add a new element that will hold all the background elements as its children. + // Because it is the first added element, all backgrounds will be behind all + // the other elements. + // (We use an arbitrarily big rect. The actual size is determined later by + // clipping to `this`.) + core::rect<s32> background_parent_rect(0, 0, 100000, 100000); + mydata.background_parent.reset(new gui::IGUIElement(EGUIET_ELEMENT, Environment, + this, -1, background_parent_rect)); + pos_offset = v2f32(); // used for formspec versions < 3 - core::list<IGUIElement *>::Iterator legacy_sort_start = Children.getLast(); + std::list<IGUIElement *>::iterator legacy_sort_start = std::prev(Children.end()); // last element if (enable_prepends) { // Backup the coordinates so that prepends can use the coordinates of choice. @@ -3354,7 +3363,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // legacy sorting for formspec versions < 3 if (m_formspec_version >= 3) // prepends do not need to be reordered - legacy_sort_start = Children.getLast(); + legacy_sort_start = std::prev(Children.end()); // last element else if (version_backup >= 3) // only prepends elements have to be reordered legacySortElements(legacy_sort_start); @@ -3435,7 +3444,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) } } -void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator from) +void GUIFormSpecMenu::legacySortElements(std::list<IGUIElement *>::iterator from) { /* Draw order for formspec_version <= 2: @@ -3452,17 +3461,16 @@ void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator fro if (from == Children.end()) from = Children.begin(); else - from++; + ++from; - core::list<IGUIElement *>::Iterator to = Children.end(); + std::list<IGUIElement *>::iterator to = Children.end(); // 1: Copy into a sortable container - std::vector<IGUIElement *> elements; - for (auto it = from; it != to; ++it) - elements.emplace_back(*it); + std::vector<IGUIElement *> elements(from, to); // 2: Sort the container std::stable_sort(elements.begin(), elements.end(), [this] (const IGUIElement *a, const IGUIElement *b) -> bool { + // TODO: getSpecByID is a linear search. It should made O(1), or cached here. const FieldSpec *spec_a = getSpecByID(a->getID()); const FieldSpec *spec_b = getSpecByID(b->getID()); return spec_a && spec_b && @@ -3470,10 +3478,7 @@ void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator fro }); // 3: Re-assign the pointers - for (auto e : elements) { - *from = e; - from++; - } + reorderChildren(from, to, elements); } #ifdef __ANDROID__ @@ -3591,15 +3596,6 @@ void GUIFormSpecMenu::drawMenu() } } - /* - Draw backgrounds - */ - for (gui::IGUIElement *e : m_backgrounds) { - e->setVisible(true); - e->draw(); - e->setVisible(false); - } - // Some elements are only visible while being drawn for (gui::IGUIElement *e : m_clickthrough_elements) e->setVisible(true); @@ -3607,12 +3603,11 @@ void GUIFormSpecMenu::drawMenu() /* This is where all the drawing happens. */ - core::list<IGUIElement*>::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - if ((*it)->isNotClipped() || + for (auto child : Children) + if (child->isNotClipped() || AbsoluteClippingRect.isRectCollided( - (*it)->getAbsolutePosition())) - (*it)->draw(); + child->getAbsolutePosition())) + child->draw(); for (gui::IGUIElement *e : m_clickthrough_elements) e->setVisible(false); @@ -4520,7 +4515,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if ((s.ftype == f_TabHeader) && (s.fid == event.GUIEvent.Caller->getID())) { if (!s.sound.empty() && m_sound_manager) - m_sound_manager->playSound(s.sound, false, 1.0f); + m_sound_manager->playSound(SimpleSoundSpec(s.sound, 1.0f)); s.send = true; acceptInput(); s.send = false; @@ -4565,7 +4560,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if (s.ftype == f_Button || s.ftype == f_CheckBox) { if (!s.sound.empty() && m_sound_manager) - m_sound_manager->playSound(s.sound, false, 1.0f); + m_sound_manager->playSound(SimpleSoundSpec(s.sound, 1.0f)); s.send = true; if (s.is_exit) { @@ -4590,7 +4585,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } } if (!s.sound.empty() && m_sound_manager) - m_sound_manager->playSound(s.sound, false, 1.0f); + m_sound_manager->playSound(SimpleSoundSpec(s.sound, 1.0f)); s.send = true; acceptInput(quit_mode_no); @@ -4608,7 +4603,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) s.fdefault = L""; } else if (s.ftype == f_Unknown || s.ftype == f_HyperText) { if (!s.sound.empty() && m_sound_manager) - m_sound_manager->playSound(s.sound, false, 1.0f); + m_sound_manager->playSound(SimpleSoundSpec(s.sound, 1.0f)); s.send = true; acceptInput(); s.send = false; diff --git a/src/gui/guiFormSpecMenu.h b/src/gui/guiFormSpecMenu.h index 0b4d3879d..c01ff817b 100644 --- a/src/gui/guiFormSpecMenu.h +++ b/src/gui/guiFormSpecMenu.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <unordered_set> #include "irrlichttypes_extrabloated.h" +#include "irr_ptr.h" #include "inventorymanager.h" #include "modalMenu.h" #include "guiInventoryList.h" @@ -211,7 +212,7 @@ public: m_lockscreensize = basescreensize; } - void removeChildren(); + void removeTooltip(); void setInitialFocus(); void setFocus(const std::string &elementname) @@ -313,7 +314,6 @@ protected: std::vector<GUIInventoryList *> m_inventorylists; std::vector<ListRingSpec> m_inventory_rings; - std::vector<gui::IGUIElement *> m_backgrounds; std::unordered_map<std::string, bool> field_close_on_enter; std::unordered_map<std::string, bool> m_dropdown_index_event; std::vector<FieldSpec> m_fields; @@ -375,6 +375,7 @@ private: GUITable::TableOptions table_options; GUITable::TableColumns table_columns; gui::IGUIElement *current_parent = nullptr; + irr_ptr<gui::IGUIElement> background_parent; GUIInventoryList::Options inventorylist_options; @@ -456,6 +457,8 @@ private: void parseSetFocus(const std::string &element); void parseModel(parserData *data, const std::string &element); + bool parseMiddleRect(const std::string &value, core::rect<s32> *parsed_rect); + void tryClose(); void showTooltip(const std::wstring &text, const irr::video::SColor &color, @@ -466,7 +469,7 @@ private: * types were drawn before others. * This function sorts the elements in the old order for backwards compatibility. */ - void legacySortElements(core::list<IGUIElement *>::Iterator from); + void legacySortElements(std::list<IGUIElement *>::iterator from); int m_btn_height; gui::IGUIFont *m_font = nullptr; diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 29d5138f0..021f5f0a9 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -93,7 +93,8 @@ GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env, GUIKeyChangeMenu::~GUIKeyChangeMenu() { - removeChildren(); + removeAllChildren(); + key_used_text = nullptr; for (key_setting *ks : key_settings) { delete[] ks->button_name; @@ -102,23 +103,10 @@ GUIKeyChangeMenu::~GUIKeyChangeMenu() key_settings.clear(); } -void GUIKeyChangeMenu::removeChildren() -{ - const core::list<gui::IGUIElement*> &children = getChildren(); - core::list<gui::IGUIElement*> children_copy; - for (gui::IGUIElement*i : children) { - children_copy.push_back(i); - } - - for (gui::IGUIElement *i : children_copy) { - i->remove(); - } - key_used_text = nullptr; -} - void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { - removeChildren(); + removeAllChildren(); + key_used_text = nullptr; const float s = m_gui_scale; DesiredRect = core::rect<s32>( @@ -136,7 +124,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) core::rect<s32> rect(0, 0, 600 * s, 40 * s); rect += topleft + v2s32(25 * s, 3 * s); //gui::IGUIStaticText *t = - const wchar_t *text = wgettext("Keybindings. (If this menu screws up, remove stuff from minetest.conf)"); + const wchar_t *text = wgettext("Keybindings."); Environment->addStaticText(text, rect, false, true, this, -1); delete[] text; diff --git a/src/gui/guiKeyChangeMenu.h b/src/gui/guiKeyChangeMenu.h index 1c0f40247..84a898774 100644 --- a/src/gui/guiKeyChangeMenu.h +++ b/src/gui/guiKeyChangeMenu.h @@ -46,7 +46,6 @@ public: IMenuManager *menumgr, ISimpleTextureSource *tsrc); ~GUIKeyChangeMenu(); - void removeChildren(); /* Remove and re-add (or reposition) stuff */ diff --git a/src/gui/guiMainMenu.h b/src/gui/guiMainMenu.h index 1dca8bf2d..9b8ff383c 100644 --- a/src/gui/guiMainMenu.h +++ b/src/gui/guiMainMenu.h @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include "irrlichttypes_extrabloated.h" +#include "gameparams.h" #include <string> #include <list> @@ -50,5 +51,7 @@ struct MainMenuData { // Data to be passed to the script MainMenuDataForScript script_data; + ELoginRegister allow_login_or_register = ELoginRegister::Any; + MainMenuData() = default; }; diff --git a/src/gui/guiPasswordChange.cpp b/src/gui/guiPasswordChange.cpp index c983260f6..c39df176b 100644 --- a/src/gui/guiPasswordChange.cpp +++ b/src/gui/guiPasswordChange.cpp @@ -51,23 +51,6 @@ GUIPasswordChange::GUIPasswordChange(gui::IGUIEnvironment* env, { } -GUIPasswordChange::~GUIPasswordChange() -{ - removeChildren(); -} - -void GUIPasswordChange::removeChildren() -{ - const core::list<gui::IGUIElement *> &children = getChildren(); - core::list<gui::IGUIElement *> children_copy; - for (gui::IGUIElement *i : children) { - children_copy.push_back(i); - } - - for (gui::IGUIElement *i : children_copy) { - i->remove(); - } -} void GUIPasswordChange::regenerateGui(v2u32 screensize) { /* @@ -78,7 +61,7 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize) /* Remove stuff */ - removeChildren(); + removeAllChildren(); /* Calculate new sizes and positions diff --git a/src/gui/guiPasswordChange.h b/src/gui/guiPasswordChange.h index 7141100c0..452702add 100644 --- a/src/gui/guiPasswordChange.h +++ b/src/gui/guiPasswordChange.h @@ -31,9 +31,7 @@ public: GUIPasswordChange(gui::IGUIEnvironment *env, gui::IGUIElement *parent, s32 id, IMenuManager *menumgr, Client *client, ISimpleTextureSource *tsrc); - ~GUIPasswordChange(); - void removeChildren(); /* Remove and re-add (or reposition) stuff */ diff --git a/src/gui/guiPathSelectMenu.cpp b/src/gui/guiPathSelectMenu.cpp index 489927a11..9c63e06b5 100644 --- a/src/gui/guiPathSelectMenu.cpp +++ b/src/gui/guiPathSelectMenu.cpp @@ -32,13 +32,12 @@ GUIFileSelectMenu::GUIFileSelectMenu(gui::IGUIEnvironment* env, GUIFileSelectMenu::~GUIFileSelectMenu() { - removeChildren(); setlocale(LC_NUMERIC, "C"); } void GUIFileSelectMenu::regenerateGui(v2u32 screensize) { - removeChildren(); + removeAllChildren(); m_fileOpenDialog = 0; core::dimension2du size(600 * m_gui_scale, 400 * m_gui_scale); diff --git a/src/gui/guiScrollContainer.cpp b/src/gui/guiScrollContainer.cpp index 0fe4c41bd..2d71f3453 100644 --- a/src/gui/guiScrollContainer.cpp +++ b/src/gui/guiScrollContainer.cpp @@ -59,12 +59,11 @@ bool GUIScrollContainer::OnEvent(const SEvent &event) void GUIScrollContainer::draw() { if (isVisible()) { - core::list<IGUIElement *>::Iterator it = Children.begin(); - for (; it != Children.end(); ++it) - if ((*it)->isNotClipped() || + for (auto child : Children) + if (child->isNotClipped() || AbsoluteClippingRect.isRectCollided( - (*it)->getAbsolutePosition())) - (*it)->draw(); + child->getAbsolutePosition())) + child->draw(); } } diff --git a/src/gui/guiTable.cpp b/src/gui/guiTable.cpp index 79ae1aea3..3929d678b 100644 --- a/src/gui/guiTable.cpp +++ b/src/gui/guiTable.cpp @@ -84,7 +84,7 @@ GUITable::GUITable(gui::IGUIEnvironment *env, #endif core::rect<s32> relative_rect = m_scrollbar->getRelativePosition(); s32 width = (relative_rect.getWidth() / (2.0 / 3.0)) * density * - g_settings->getFloat("gui_scaling"); + g_settings->getFloat("gui_scaling", 0.5f, 20.0f); m_scrollbar->setRelativePosition(core::rect<s32>( relative_rect.LowerRightCorner.X-width,relative_rect.UpperLeftCorner.Y, relative_rect.LowerRightCorner.X,relative_rect.LowerRightCorner.Y diff --git a/src/gui/guiVolumeChange.cpp b/src/gui/guiVolumeChange.cpp index 61ab758a1..0f6f43fe9 100644 --- a/src/gui/guiVolumeChange.cpp +++ b/src/gui/guiVolumeChange.cpp @@ -45,32 +45,12 @@ GUIVolumeChange::GUIVolumeChange(gui::IGUIEnvironment* env, { } -GUIVolumeChange::~GUIVolumeChange() -{ - removeChildren(); -} - -void GUIVolumeChange::removeChildren() -{ - if (gui::IGUIElement *e = getElementFromId(ID_soundText)) - e->remove(); - - if (gui::IGUIElement *e = getElementFromId(ID_soundExitButton)) - e->remove(); - - if (gui::IGUIElement *e = getElementFromId(ID_soundSlider)) - e->remove(); - - if (gui::IGUIElement *e = getElementFromId(ID_soundMuteButton)) - e->remove(); -} - void GUIVolumeChange::regenerateGui(v2u32 screensize) { /* Remove stuff */ - removeChildren(); + removeAllChildren(); /* Calculate new sizes and positions */ diff --git a/src/gui/guiVolumeChange.h b/src/gui/guiVolumeChange.h index 466e17f9d..ccdaca00b 100644 --- a/src/gui/guiVolumeChange.h +++ b/src/gui/guiVolumeChange.h @@ -31,9 +31,6 @@ public: GUIVolumeChange(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, ISimpleTextureSource *tsrc); - ~GUIVolumeChange(); - - void removeChildren(); /* Remove and re-add (or reposition) stuff */ diff --git a/src/gui/mainmenumanager.h b/src/gui/mainmenumanager.h index 102492255..76d357340 100644 --- a/src/gui/mainmenumanager.h +++ b/src/gui/mainmenumanager.h @@ -64,10 +64,6 @@ public: // Remove all entries if there are duplicates m_stack.remove(menu); - /*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast(); - assert(*i == menu); - m_stack.erase(i);*/ - if(!m_stack.empty()) m_stack.back()->setVisible(true); } diff --git a/src/gui/modalMenu.cpp b/src/gui/modalMenu.cpp index 56a5d2cb9..cfc4d5c5a 100644 --- a/src/gui/modalMenu.cpp +++ b/src/gui/modalMenu.cpp @@ -40,7 +40,7 @@ GUIModalMenu::GUIModalMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, m_menumgr(menumgr), m_remap_dbl_click(remap_dbl_click) { - m_gui_scale = g_settings->getFloat("gui_scaling"); + m_gui_scale = std::max(g_settings->getFloat("gui_scaling"), 0.5f); #ifdef HAVE_TOUCHSCREENGUI float d = RenderingEngine::getDisplayDensity(); m_gui_scale *= 1.1 - 0.3 * d + 0.2 * d * d; @@ -108,19 +108,6 @@ void GUIModalMenu::quitMenu() #endif } -void GUIModalMenu::removeChildren() -{ - const core::list<gui::IGUIElement *> &children = getChildren(); - core::list<gui::IGUIElement *> children_copy; - for (gui::IGUIElement *i : children) { - children_copy.push_back(i); - } - - for (gui::IGUIElement *i : children_copy) { - i->remove(); - } -} - // clang-format off bool GUIModalMenu::DoubleClickDetection(const SEvent &event) { @@ -265,13 +252,6 @@ bool GUIModalMenu::preprocessEvent(const SEvent &event) return retval; m_jni_field_name = field_name; - /*~ Imperative, as in "Enter/type in text". - Don't forget the space. */ - std::string message = gettext("Enter "); - std::string label = wide_to_utf8(getLabelByID(hovered->getID())); - if (label.empty()) - label = "text"; - message += strgettext(label) + ":"; // single line text input int type = 2; diff --git a/src/gui/modalMenu.h b/src/gui/modalMenu.h index 06e78f06b..e37c41533 100644 --- a/src/gui/modalMenu.h +++ b/src/gui/modalMenu.h @@ -47,7 +47,6 @@ public: bool canTakeFocus(gui::IGUIElement *e); void draw(); void quitMenu(); - void removeChildren(); virtual void regenerateGui(v2u32 screensize) = 0; virtual void drawMenu() = 0; diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index ebe1a6325..d483c136e 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -843,7 +843,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) s32 dy = Y - m_pointerpos[event.TouchInput.ID].Y; // adapt to similar behaviour as pc screen - double d = g_settings->getFloat("mouse_sensitivity") * 3.0f; + const double d = g_settings->getFloat("mouse_sensitivity", 0.001f, 10.0f) * 3.0f; m_camera_yaw_change -= dx * d; m_camera_pitch = MYMIN(MYMAX(m_camera_pitch + (dy * d), -180), 180); |