From 9284313d17ba906de449c6d39ef3ddacb6c73791 Mon Sep 17 00:00:00 2001 From: Hugues Ross Date: Mon, 9 Dec 2019 15:06:51 -0500 Subject: [PATCH] Refactor to centralize GUIButton styling/rendering code (#9090) --- build/android/jni/Android.mk | 2 + doc/lua_api.txt | 22 ++- games/minimal/mods/test/formspec.lua | 7 + games/minimal/mods/test/textures/test_bg.png | Bin 0 -> 972 bytes .../mods/test/textures/test_bg_hovered.png | Bin 0 -> 972 bytes .../mods/test/textures/test_bg_pressed.png | Bin 0 -> 971 bytes src/gui/CMakeLists.txt | 2 + src/gui/StyleSpec.h | 34 ++++ src/gui/guiButton.cpp | 115 +++++++++++--- src/gui/guiButton.h | 64 +++++--- src/gui/guiButtonImage.cpp | 149 ++++++++++++++++++ src/gui/guiButtonImage.h | 59 +++++++ src/gui/guiButtonItemImage.cpp | 57 +++++++ src/gui/guiButtonItemImage.h | 45 ++++++ src/gui/guiFormSpecMenu.cpp | 93 ++--------- src/gui/guiItemImage.cpp | 12 -- src/irrlicht_changes/static_text.cpp | 2 +- util/travis/clang-format-whitelist.txt | 4 + 18 files changed, 522 insertions(+), 145 deletions(-) create mode 100644 games/minimal/mods/test/textures/test_bg.png create mode 100644 games/minimal/mods/test/textures/test_bg_hovered.png create mode 100644 games/minimal/mods/test/textures/test_bg_pressed.png create mode 100644 src/gui/guiButtonImage.cpp create mode 100644 src/gui/guiButtonImage.h create mode 100644 src/gui/guiButtonItemImage.cpp create mode 100644 src/gui/guiButtonItemImage.h diff --git a/build/android/jni/Android.mk b/build/android/jni/Android.mk index e247665f8..60070f9e8 100644 --- a/build/android/jni/Android.mk +++ b/build/android/jni/Android.mk @@ -181,6 +181,8 @@ LOCAL_SRC_FILES := \ jni/src/gui/guiBackgroundImage.cpp \ jni/src/gui/guiBox.cpp \ jni/src/gui/guiButton.cpp \ + jni/src/gui/guiButtonImage.cpp \ + jni/src/gui/guiButtonItemImage.cpp \ jni/src/gui/guiChatConsole.cpp \ jni/src/gui/guiConfirmRegistration.cpp \ jni/src/gui/guiEditBoxWithScrollbar.cpp \ diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 7ba3ad77d..b23bd915c 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -2541,20 +2541,20 @@ Some types may inherit styles from parent types. * label * vertlabel, inherits from field * image_button -* item_image_button, inherits from image_button +* item_image_button * tabheader ### Valid Properties -* button, button_exit +* button, button_exit, image_button, item_image_button * alpha - boolean, whether to draw alpha in bgimg. Default true. * bgcolor - color, sets button tint. * bgcolor_hovered - color when hovered. Defaults to a lighter bgcolor when not provided. * bgcolor_pressed - color when pressed. Defaults to a darker bgcolor when not provided. - * bgimg - standard image. Defaults to none. - * bgimg_hovered - image when hovered. Defaults to bgimg when not provided. - * bgimg_pressed - image when pressed. Defaults to bgimg when not provided. + * bgimg - standard background image. Defaults to none. + * bgimg_hovered - background image when hovered. Defaults to bgimg when not provided. + * bgimg_pressed - background image when pressed. Defaults to bgimg when not provided. * border - boolean, draw border. Set to false to hide the bevelled button pane. Default true. * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color, default white. @@ -2572,13 +2572,11 @@ Some types may inherit styles from parent types. * textcolor - color. Default white. * label, vertlabel * noclip - boolean, set to true to allow the element to exceed formspec bounds. -* image_button - * alpha - boolean, whether to draw alpha in bgimg. Default true. - * border - boolean, draw border. Set to false to hide the bevelled button pane. Default false. - * noclip - boolean, set to true to allow the element to exceed formspec bounds. -* item_image_button - * border - boolean, draw border. Set to false to hide the bevelled button pane. Default false. - * noclip - boolean, set to true to allow the element to exceed formspec bounds. +* image_button (additional properties) + * fgimg - standard image. Defaults to none. + * fgimg_hovered - image when hovered. Defaults to fgimg when not provided. + * fgimg_pressed - image when pressed. Defaults to fgimg when not provided. + * NOTE: The parameters of any given image_button will take precedence over fgimg/fgimg_pressed * tabheader * noclip - boolean, set to true to allow the element to exceed formspec bounds. * textcolor - color. Default white. diff --git a/games/minimal/mods/test/formspec.lua b/games/minimal/mods/test/formspec.lua index 6371e3d44..64b9ec0d5 100644 --- a/games/minimal/mods/test/formspec.lua +++ b/games/minimal/mods/test/formspec.lua @@ -70,6 +70,13 @@ local style_fs = [[ style[one_btn13;border=false] item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor] + style[one_btn14;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png;fgimg=bubble.png;fgimg_hovered=default_apple.png;fgimg_pressed=heart.png] + image_button[0,9.6;1,1;bubble.png;one_btn14;Bg] + + style[one_btn15;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png] + item_image_button[1.25,9.6;1,1;default:sword_steel;one_btn15;Bg] + + container[2.75,0] diff --git a/games/minimal/mods/test/textures/test_bg.png b/games/minimal/mods/test/textures/test_bg.png new file mode 100644 index 0000000000000000000000000000000000000000..f0f3929265734de57382ff9decb2363e670692c2 GIT binary patch literal 972 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR3mE?5sDH|z(I2hM}Y3->|fgZH~;y_*eW xNqD+AhDc0JPH@XUIx7GG literal 0 HcmV?d00001 diff --git a/games/minimal/mods/test/textures/test_bg_hovered.png b/games/minimal/mods/test/textures/test_bg_hovered.png new file mode 100644 index 0000000000000000000000000000000000000000..b9ce8fd318bbcd3eeaaf587827de36dd78630d1c GIT binary patch literal 972 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR^y)((7vSmo1zO6dwhn zAuvKhAU8L6)v8th|Nj?XX*C__XZ{k`h?3y^w370~qErU=qQtZcqXmnCvw%__$whwY zK$^+G9z;6$gUEn*5Sfq3mE?5sDH|z(I2hM}Y3->|fgZH~;y_*eW xNqD+AhDc0JPH@v8IZ*%r literal 0 HcmV?d00001 diff --git a/games/minimal/mods/test/textures/test_bg_pressed.png b/games/minimal/mods/test/textures/test_bg_pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..76aafb8c13d322982670af732140c5d029a04afc GIT binary patch literal 971 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR?*)y%OVsdRq&C;-g?R z1V%^*SAkx7fL #pragma once @@ -36,6 +38,9 @@ public: BGIMG, BGIMG_HOVERED, BGIMG_PRESSED, + FGIMG, + FGIMG_HOVERED, + FGIMG_PRESSED, ALPHA, NUM_PROPERTIES, NONE @@ -66,6 +71,12 @@ public: return BGIMG_HOVERED; } else if (name == "bgimg_pressed") { return BGIMG_PRESSED; + } else if (name == "fgimg") { + return FGIMG; + } else if (name == "fgimg_hovered") { + return FGIMG_HOVERED; + } else if (name == "fgimg_pressed") { + return FGIMG_PRESSED; } else if (name == "alpha") { return ALPHA; } else { @@ -106,6 +117,29 @@ public: return color; } + video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc, + video::ITexture *def) const + { + const auto &val = properties[prop]; + if (val.empty()) { + return def; + } + + video::ITexture *texture = tsrc->getTexture(val); + + return texture; + } + + video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc) const + { + const auto &val = properties[prop]; + FATAL_ERROR_IF(val.empty(), "Unexpected missing property"); + + video::ITexture *texture = tsrc->getTexture(val); + + return texture; + } + bool getBool(Property prop, bool def) const { const auto &val = properties[prop]; diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 6ed5d3772..6518bbd1f 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -5,11 +5,15 @@ #include "guiButton.h" +#include "client/guiscalingfilter.h" +#include "client/tile.h" #include "IGUISkin.h" #include "IGUIEnvironment.h" #include "IVideoDriver.h" #include "IGUIFont.h" +#include "irrlicht_changes/static_text.h" #include "porting.h" +#include "StyleSpec.h" using namespace irr; using namespace gui; @@ -49,6 +53,9 @@ GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent, core::clamp(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255), core::clamp(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255)); } + + StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id); + StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER); // END PATCH } @@ -262,7 +269,7 @@ void GUIButton::draw() { // PATCH skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect, - Environment->getHovered() == this ? HoveredColors : Colors); + isHovered() ? HoveredColors : Colors); // END PATCH } else @@ -318,7 +325,7 @@ void GUIButton::draw() drawSprite(state, FocusTime, pos); // mouse over / off animation - state = Environment->getHovered() == this ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF; + state = isHovered() ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF; drawSprite(state, HoverTime, pos); } else @@ -328,23 +335,6 @@ void GUIButton::draw() } } - if (Text.size()) - { - IGUIFont* font = getActiveFont(); - - core::rect rect = AbsoluteRect; - if (Pressed) - { - rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X); - rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y); - } - - if (font) - font->draw(Text.c_str(), rect, - OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), - true, true, &AbsoluteClippingRect); - } - IGUIElement::draw(); } @@ -371,11 +361,18 @@ void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::p } EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const +{ + // PATCH + return getImageState(pressed, ButtonImages); + // END PATCH +} + +EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed, const ButtonImage* images) const { // figure state we should have EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED; bool focused = Environment->hasFocus((IGUIElement*)this); - bool mouseOver = static_cast(Environment->getHovered()) == this; // (static cast for Borland) + bool mouseOver = isHovered(); if (isEnabled()) { if ( pressed ) @@ -403,7 +400,7 @@ EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const } // find a compatible state that has images - while ( state != EGBIS_IMAGE_UP && !ButtonImages[(u32)state].Texture ) + while ( state != EGBIS_IMAGE_UP && !images[(u32)state].Texture ) { // PATCH switch ( state ) @@ -451,6 +448,8 @@ void GUIButton::setOverrideFont(IGUIFont* font) if (OverrideFont) OverrideFont->grab(); + + StaticText->setOverrideFont(font); } //! Gets the override font (if any) @@ -475,6 +474,8 @@ void GUIButton::setOverrideColor(video::SColor color) { OverrideColor = color; OverrideColorEnabled = true; + + StaticText->setOverrideColor(color); } video::SColor GUIButton::getOverrideColor() const @@ -540,6 +541,14 @@ void GUIButton::setHoveredImage(video::ITexture* image, const core::rect& p setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos); setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos); } + +//! Sets the text displayed by the button +void GUIButton::setText(const wchar_t* text) +{ + StaticText->setText(text); + + IGUIButton::setText(text); +} // END PATCH //! Sets if the button should behave like a push button. Which means it @@ -557,6 +566,14 @@ bool GUIButton::isPressed() const return Pressed; } +// PATCH +//! Returns if this element (or one of its direct children) is hovered +bool GUIButton::isHovered() const +{ + IGUIElement *hovered = Environment->getHovered(); + return hovered == this || (hovered != nullptr && hovered->getParent() == this); +} +// END PATCH //! Sets the pressed state of the button if this is a pushbutton void GUIButton::setPressed(bool pressed) @@ -565,6 +582,24 @@ void GUIButton::setPressed(bool pressed) { ClickTime = porting::getTimeMs(); Pressed = pressed; + + GUISkin* skin = dynamic_cast(Environment->getSkin()); + + for(IGUIElement *child : getChildren()) + { + core::rect originalRect = child->getRelativePosition(); + if (Pressed) { + child->setRelativePosition(originalRect + + core::dimension2d( + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y))); + } else { + child->setRelativePosition(originalRect - + core::dimension2d( + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), + skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y))); + } + } } } @@ -722,4 +757,42 @@ void GUIButton::setPressedColor(video::SColor color) PressedColors[i] = base.getInterpolated(color, d); } } + +//! Set element properties from a StyleSpec +void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc) +{ + if (style.isNotDefault(StyleSpec::BGCOLOR)) { + setColor(style.getColor(StyleSpec::BGCOLOR)); + } + if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) { + setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED)); + } + if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) { + setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED)); + } + + if (style.isNotDefault(StyleSpec::TEXTCOLOR)) { + setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR)); + } + setNotClipped(style.getBool(StyleSpec::NOCLIP, isNotClipped())); + setDrawBorder(style.getBool(StyleSpec::BORDER, DrawBorder)); + setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); + + if (style.isNotDefault(StyleSpec::BGIMG)) { + video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, tsrc); + video::ITexture *hovered_texture = style.getTexture(StyleSpec::BGIMG_HOVERED, tsrc, texture); + video::ITexture *pressed_texture = style.getTexture(StyleSpec::BGIMG_PRESSED, tsrc, texture); + + const core::position2di buttonCenter(AbsoluteRect.getCenter()); + core::position2d geom(buttonCenter); + + setImage(guiScalingImageButton( + Environment->getVideoDriver(), texture, geom.X, geom.Y)); + setHoveredImage(guiScalingImageButton( + Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y)); + setPressedImage(guiScalingImageButton( + Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); + setScaleImage(true); + } +} // END PATCH diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index 3c353d240..37b278d25 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -6,6 +6,8 @@ #include "IrrCompileConfig.h" +#include +#include "irrlicht_changes/static_text.h" #include "IGUIButton.h" #include "IGUISpriteBank.h" #include "ITexture.h" @@ -64,6 +66,9 @@ using namespace irr; #endif +class ISimpleTextureSource; +class StyleSpec; + class GUIButton : public gui::IGUIButton { public: @@ -122,6 +127,9 @@ public: //! Sets an image which should be displayed on the button when it is in hovered state. virtual void setHoveredImage(video::ITexture* image=nullptr); + + //! Sets the text displayed by the button + virtual void setText(const wchar_t* text) override; // END PATCH //! Sets an image which should be displayed on the button when it is in hovered state. @@ -172,6 +180,11 @@ public: //! Returns if the button is currently pressed virtual bool isPressed() const override; + // PATCH + //! Returns if this element (or one of its direct children) is hovered + bool isHovered() const; + // END PATCH + //! Sets if the button should use the skin to draw its border virtual void setDrawBorder(bool border=true) override; @@ -214,6 +227,9 @@ public: // PATCH void setHoveredColor(video::SColor color); void setPressedColor(video::SColor color); + + //! Set element properties from a StyleSpec + virtual void setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc); // END PATCH @@ -225,28 +241,6 @@ protected: void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center); gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const; -private: - - struct ButtonSprite - { - ButtonSprite() : Index(-1), Loop(false), Scale(false) - { - } - - bool operator==(const ButtonSprite& other) const - { - return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale; - } - - s32 Index; - video::SColor Color; - bool Loop; - bool Scale; - }; - - ButtonSprite ButtonSprites[gui::EGBS_COUNT]; - gui::IGUISpriteBank* SpriteBank; - struct ButtonImage { ButtonImage() : Texture(0), SourceRect(core::rect(0,0,0,0)) @@ -288,6 +282,30 @@ private: core::rect SourceRect; }; + gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed, const ButtonImage* images) const; + +private: + + struct ButtonSprite + { + ButtonSprite() : Index(-1), Loop(false), Scale(false) + { + } + + bool operator==(const ButtonSprite& other) const + { + return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale; + } + + s32 Index; + video::SColor Color; + bool Loop; + bool Scale; + }; + + ButtonSprite ButtonSprites[gui::EGBS_COUNT]; + gui::IGUISpriteBank* SpriteBank; + ButtonImage ButtonImages[gui::EGBIS_COUNT]; gui::IGUIFont* OverrideFont; @@ -310,5 +328,7 @@ private: // PATCH video::SColor HoveredColors[4]; video::SColor PressedColors[4]; + + gui::IGUIStaticText *StaticText; // END PATCH }; diff --git a/src/gui/guiButtonImage.cpp b/src/gui/guiButtonImage.cpp new file mode 100644 index 000000000..8796b845d --- /dev/null +++ b/src/gui/guiButtonImage.cpp @@ -0,0 +1,149 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 "guiButtonImage.h" + +#include "client/guiscalingfilter.h" +#include "debug.h" +#include "IGUIEnvironment.h" +#include "IGUIImage.h" +#include "IVideoDriver.h" +#include "StyleSpec.h" + +using namespace irr; +using namespace gui; + +GUIButtonImage::GUIButtonImage(gui::IGUIEnvironment *environment, + gui::IGUIElement *parent, s32 id, core::rect rectangle, bool noclip) + : GUIButton (environment, parent, id, rectangle, noclip) +{ + m_image = Environment->addImage( + core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), this); + m_image->setScaleImage(isScalingImage()); + sendToBack(m_image); +} + +bool GUIButtonImage::OnEvent(const SEvent& event) +{ + bool result = GUIButton::OnEvent(event); + + EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images); + video::ITexture *texture = m_foreground_images[(u32)imageState].Texture; + if (texture != nullptr) + m_image->setImage(texture); + + return result; +} + +void GUIButtonImage::setForegroundImage(EGUI_BUTTON_IMAGE_STATE state, + video::ITexture *image, const core::rect &sourceRect) +{ + if (state >= EGBIS_COUNT) + return; + + if (image) + image->grab(); + + u32 stateIdx = (u32)state; + if (m_foreground_images[stateIdx].Texture) + m_foreground_images[stateIdx].Texture->drop(); + + m_foreground_images[stateIdx].Texture = image; + m_foreground_images[stateIdx].SourceRect = sourceRect; + + EGUI_BUTTON_IMAGE_STATE imageState = getImageState(isPressed(), m_foreground_images); + if (imageState == stateIdx) + m_image->setImage(image); +} + +void GUIButtonImage::setForegroundImage(video::ITexture *image) +{ + setForegroundImage(gui::EGBIS_IMAGE_UP, image); +} + +void GUIButtonImage::setForegroundImage(video::ITexture *image, const core::rect &pos) +{ + setForegroundImage(gui::EGBIS_IMAGE_UP, image, pos); +} + +void GUIButtonImage::setPressedForegroundImage(video::ITexture *image) +{ + setForegroundImage(gui::EGBIS_IMAGE_DOWN, image); +} + +void GUIButtonImage::setPressedForegroundImage(video::ITexture *image, const core::rect &pos) +{ + setForegroundImage(gui::EGBIS_IMAGE_DOWN, image, pos); +} + +void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image) +{ + setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image); + setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image); +} + +void GUIButtonImage::setHoveredForegroundImage(video::ITexture *image, const core::rect &pos) +{ + setForegroundImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos); + setForegroundImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos); +} + +void GUIButtonImage::setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc) +{ + GUIButton::setFromStyle(style, tsrc); + + video::IVideoDriver *driver = Environment->getVideoDriver(); + + if (style.isNotDefault(StyleSpec::FGIMG)) { + video::ITexture *texture = style.getTexture(StyleSpec::FGIMG, tsrc); + video::ITexture *hovered_texture = style.getTexture(StyleSpec::FGIMG_HOVERED, tsrc, texture); + video::ITexture *pressed_texture = style.getTexture(StyleSpec::FGIMG_PRESSED, tsrc, texture); + + const core::position2di buttonCenter(AbsoluteRect.getCenter()); + core::position2d geom(buttonCenter); + + setForegroundImage(guiScalingImageButton(driver, texture, geom.X, geom.Y)); + setHoveredForegroundImage(guiScalingImageButton(driver, hovered_texture, geom.X, geom.Y)); + setPressedForegroundImage(guiScalingImageButton(driver, pressed_texture, geom.X, geom.Y)); + setScaleImage(true); + } +} + +void GUIButtonImage::setScaleImage(bool scaleImage) +{ + GUIButton::setScaleImage(scaleImage); + m_image->setScaleImage(scaleImage); +} + +GUIButtonImage *GUIButtonImage::addButton(IGUIEnvironment *environment, + const core::rect &rectangle, IGUIElement *parent, s32 id, + const wchar_t *text, const wchar_t *tooltiptext) +{ + GUIButtonImage *button = new GUIButtonImage(environment, + parent ? parent : environment->getRootGUIElement(), id, rectangle); + + if (text) + button->setText(text); + + if (tooltiptext) + button->setToolTipText(tooltiptext); + + button->drop(); + return button; +} diff --git a/src/gui/guiButtonImage.h b/src/gui/guiButtonImage.h new file mode 100644 index 000000000..15901ee5d --- /dev/null +++ b/src/gui/guiButtonImage.h @@ -0,0 +1,59 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 "guiButton.h" +#include "IGUIButton.h" + +using namespace irr; + +class GUIButtonImage : public GUIButton +{ +public: + //! constructor + GUIButtonImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, + s32 id, core::rect rectangle, bool noclip = false); + + virtual bool OnEvent(const SEvent& event) override; + + void setForegroundImage(gui::EGUI_BUTTON_IMAGE_STATE state, + video::ITexture *image = nullptr, + const core::rect &sourceRect = core::rect(0, 0, 0, 0)); + + void setForegroundImage(video::ITexture *image = nullptr); + void setForegroundImage(video::ITexture *image, const core::rect &pos); + + void setPressedForegroundImage(video::ITexture *image = nullptr); + void setPressedForegroundImage(video::ITexture *image, const core::rect &pos); + + void setHoveredForegroundImage(video::ITexture *image = nullptr); + void setHoveredForegroundImage(video::ITexture *image, const core::rect &pos); + + virtual void setFromStyle(const StyleSpec &style, ISimpleTextureSource *tsrc) override; + + virtual void setScaleImage(bool scaleImage=true) override; + + //! Do not drop returned handle + static GUIButtonImage *addButton(gui::IGUIEnvironment *environment, + const core::rect &rectangle, IGUIElement *parent, s32 id, + const wchar_t *text, const wchar_t *tooltiptext = L""); + +private: + ButtonImage m_foreground_images[gui::EGBIS_COUNT]; + gui::IGUIImage *m_image; +}; diff --git a/src/gui/guiButtonItemImage.cpp b/src/gui/guiButtonItemImage.cpp new file mode 100644 index 000000000..5c48b2acd --- /dev/null +++ b/src/gui/guiButtonItemImage.cpp @@ -0,0 +1,57 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 "guiButtonItemImage.h" + +#include "client/client.h" +#include "client/hud.h" // drawItemStack +#include "guiItemImage.h" +#include "IGUIEnvironment.h" +#include "itemdef.h" + +using namespace irr; +using namespace gui; + +GUIButtonItemImage::GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, + s32 id, core::rect rectangle, std::string item, Client *client, bool noclip) + : GUIButton (environment, parent, id, rectangle, noclip) +{ + m_image = new GUIItemImage(environment, this, id, + core::rect(0,0,rectangle.getWidth(),rectangle.getHeight()), + item, getActiveFont(), client); + sendToBack(m_image); + + m_item_name = item; + m_client = client; +} + +GUIButtonItemImage *GUIButtonItemImage::addButton(IGUIEnvironment *environment, + const core::rect &rectangle, IGUIElement *parent, s32 id, + const wchar_t *text, std::string item, Client *client) +{ + GUIButtonItemImage *button = new GUIButtonItemImage(environment, + parent ? parent : environment->getRootGUIElement(), + id, rectangle, item, client); + + if (text) + button->setText(text); + + button->drop(); + return button; +} diff --git a/src/gui/guiButtonItemImage.h b/src/gui/guiButtonItemImage.h new file mode 100644 index 000000000..0a61874da --- /dev/null +++ b/src/gui/guiButtonItemImage.h @@ -0,0 +1,45 @@ +/* +Minetest +Copyright (C) 2013 celeron55, Perttu Ahola + +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 "guiButton.h" +#include "IGUIButton.h" + +using namespace irr; + +class Client; +class GUIItemImage; + +class GUIButtonItemImage : public GUIButton +{ +public: + //! constructor + GUIButtonItemImage(gui::IGUIEnvironment *environment, gui::IGUIElement *parent, + s32 id, core::rect rectangle, std::string item, + Client *client, bool noclip = false); + + //! Do not drop returned handle + static GUIButtonItemImage *addButton(gui::IGUIEnvironment *environment, + const core::rect &rectangle, IGUIElement *parent, s32 id, + const wchar_t *text, std::string item, Client *client); + +private: + std::string m_item_name; + Client *m_client; + GUIItemImage *m_image; +}; diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index ed3445b5b..728747eb8 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -58,6 +58,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiBackgroundImage.h" #include "guiBox.h" #include "guiButton.h" +#include "guiButtonImage.h" +#include "guiButtonItemImage.h" #include "guiEditBoxWithScrollbar.h" #include "guiItemImage.h" #include "guiScrollBar.h" @@ -879,49 +881,7 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element, GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); auto style = getStyleForElement(type, name, (type != "button") ? "button" : ""); - if (style.isNotDefault(StyleSpec::BGCOLOR)) { - e->setColor(style.getColor(StyleSpec::BGCOLOR)); - } - if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) { - e->setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED)); - } - if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) { - e->setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED)); - } - - if (style.isNotDefault(StyleSpec::TEXTCOLOR)) { - e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR)); - } - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); - e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); - - if (style.isNotDefault(StyleSpec::BGIMG)) { - std::string image_name = style.get(StyleSpec::BGIMG, ""); - std::string hovered_image_name = style.get(StyleSpec::BGIMG_HOVERED, ""); - std::string pressed_image_name = style.get(StyleSpec::BGIMG_PRESSED, ""); - - video::ITexture *texture = 0; - video::ITexture *hovered_texture = 0; - video::ITexture *pressed_texture = 0; - texture = m_tsrc->getTexture(image_name); - if (!hovered_image_name.empty()) - hovered_texture = m_tsrc->getTexture(hovered_image_name); - else - hovered_texture = texture; - if (!pressed_image_name.empty()) - pressed_texture = m_tsrc->getTexture(pressed_image_name); - else - pressed_texture = texture; - - e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); - e->setImage(guiScalingImageButton( - Environment->getVideoDriver(), texture, geom.X, geom.Y)); - e->setHoveredImage(guiScalingImageButton( - Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y)); - e->setPressedImage(guiScalingImageButton( - Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); - e->setScaleImage(true); - } + e->setFromStyle(style, m_tsrc); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1876,33 +1836,31 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem spec.is_exit = true; video::ITexture *texture = 0; - video::ITexture *pressed_texture = 0; texture = m_tsrc->getTexture(image_name); - if (!pressed_image_name.empty()) - pressed_texture = m_tsrc->getTexture(pressed_image_name); - else - pressed_texture = texture; - GUIButton *e = GUIButton::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); + GUIButtonImage *e = GUIButtonImage::addButton(Environment, rect, this, spec.fid, spec.flabel.c_str()); if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } auto style = getStyleForElement("image_button", spec.fname); + e->setFromStyle(style, m_tsrc); - e->setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true)); - e->setImage(guiScalingImageButton( + // We explicitly handle these arguments *after* the style properties in + // order to override them if they are provided + e->setForegroundImage(guiScalingImageButton( Environment->getVideoDriver(), texture, geom.X, geom.Y)); - e->setPressedImage(guiScalingImageButton( - Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); + if (!pressed_image_name.empty()) { + video::ITexture *pressed_texture = m_tsrc->getTexture(pressed_image_name); + e->setPressedForegroundImage(guiScalingImageButton( + Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); + } e->setScaleImage(true); + if (parts.size() >= 7) { e->setNotClipped(noclip); e->setDrawBorder(drawborder); - } else { - e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); - e->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); } m_fields.push_back(spec); @@ -2083,11 +2041,10 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & 2 ); - gui::IGUIButton *e_btn = GUIButton::addButton(Environment, rect, this, spec_btn.fid, L""); + GUIButtonItemImage *e_btn = GUIButtonItemImage::addButton(Environment, rect, this, spec_btn.fid, spec_btn.flabel.c_str(), item_name, m_client); auto style = getStyleForElement("item_image_button", spec_btn.fname, "image_button"); - e_btn->setNotClipped(style.getBool(StyleSpec::NOCLIP, false)); - e_btn->setDrawBorder(style.getBool(StyleSpec::BORDER, true)); + e_btn->setFromStyle(style, m_tsrc); if (spec_btn.fname == data->focused_fieldname) { Environment->setFocus(e_btn); @@ -2097,24 +2054,6 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string & rect += data->basepos-padding; spec_btn.rect = rect; m_fields.push_back(spec_btn); - - // the spec for the item-image - FieldSpec spec_img( - name, - L"", - L"", - 258 + m_fields.size(), - 2 - ); - - GUIItemImage *e_img = new GUIItemImage(Environment, e_btn, spec_img.fid, - core::rect(0, 0, geom.X, geom.Y), item_name, m_font, m_client); - - e_img->setText(utf8_to_wide(label).c_str()); - - e_img->drop(); - - m_fields.push_back(spec_img); return; } errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl; diff --git a/src/gui/guiItemImage.cpp b/src/gui/guiItemImage.cpp index 799a60c66..f93d5476c 100644 --- a/src/gui/guiItemImage.cpp +++ b/src/gui/guiItemImage.cpp @@ -43,18 +43,6 @@ void GUIItemImage::draw() item.deSerialize(m_item_name, idef); // Viewport rectangle on screen core::rect rect = core::rect(AbsoluteRect); - if (Parent->getType() == gui::EGUIET_BUTTON && - ((irr::gui::IGUIButton *)Parent)->isPressed()) { -#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8) - rect += core::dimension2d(0.05 * (float)rect.getWidth(), - 0.05 * (float)rect.getHeight()); -#else - gui::IGUISkin *skin = Environment->getSkin(); - rect += core::dimension2d( - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X), - skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)); -#endif - } drawItemStack(Environment->getVideoDriver(), m_font, item, rect, &AbsoluteClippingRect, m_client, IT_ROT_NONE); video::SColor color(255, 255, 255, 255); diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index 5a0f82673..1375f033c 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -112,7 +112,7 @@ void StaticText::draw() #if USE_FREETYPE if (font->getType() == irr::gui::EGFT_CUSTOM) { irr::gui::CGUITTFont *tmp = static_cast(font); - tmp->draw(cText, frameRect, + tmp->draw(Text, frameRect, OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT), HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, diff --git a/util/travis/clang-format-whitelist.txt b/util/travis/clang-format-whitelist.txt index 30d1e9e1c..f15b37cf5 100644 --- a/util/travis/clang-format-whitelist.txt +++ b/util/travis/clang-format-whitelist.txt @@ -161,6 +161,10 @@ src/gui/guiBox.cpp src/gui/guiBox.h src/gui/guiButton.cpp src/gui/guiButton.h +src/gui/guiButtonImage.cpp +src/gui/guiButtonImage.h +src/gui/guiButtonItemImage.cpp +src/gui/guiButtonItemImage.h src/gui/guiChatConsole.cpp src/gui/guiChatConsole.h src/gui/guiConfirmRegistration.cpp -- 2.25.1