Refactor to centralize GUIButton styling/rendering code (#9090)
authorHugues Ross <hugues.ross@gmail.com>
Mon, 9 Dec 2019 20:06:51 +0000 (15:06 -0500)
committerrubenwardy <rw@rubenwardy.com>
Mon, 9 Dec 2019 20:06:51 +0000 (20:06 +0000)
18 files changed:
build/android/jni/Android.mk
doc/lua_api.txt
games/minimal/mods/test/formspec.lua
games/minimal/mods/test/textures/test_bg.png [new file with mode: 0644]
games/minimal/mods/test/textures/test_bg_hovered.png [new file with mode: 0644]
games/minimal/mods/test/textures/test_bg_pressed.png [new file with mode: 0644]
src/gui/CMakeLists.txt
src/gui/StyleSpec.h
src/gui/guiButton.cpp
src/gui/guiButton.h
src/gui/guiButtonImage.cpp [new file with mode: 0644]
src/gui/guiButtonImage.h [new file with mode: 0644]
src/gui/guiButtonItemImage.cpp [new file with mode: 0644]
src/gui/guiButtonItemImage.h [new file with mode: 0644]
src/gui/guiFormSpecMenu.cpp
src/gui/guiItemImage.cpp
src/irrlicht_changes/static_text.cpp
util/travis/clang-format-whitelist.txt

index e247665f860a57da1c8d357ea7cef376c0421d44..60070f9e8ba6c9154cdcce1627cb6f5028887ee0 100644 (file)
@@ -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   \
index 7ba3ad77d2a232c5444eacdfa64f07c0c110202d..b23bd915c4d93c02d3ec93e4989663fb37adab73 100644 (file)
@@ -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.
index 6371e3d442437826b25852e1445f3144302e498d..64b9ec0d5c7c15a9469607deded4e499c4c03302 100644 (file)
@@ -70,6 +70,13 @@ local style_fs = [[
        style[one_btn13;border=false]\r
        item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor]\r
 \r
+       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]\r
+       image_button[0,9.6;1,1;bubble.png;one_btn14;Bg]\r
+\r
+       style[one_btn15;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png]\r
+       item_image_button[1.25,9.6;1,1;default:sword_steel;one_btn15;Bg]\r
+\r
+\r
 \r
        container[2.75,0]\r
 \r
diff --git a/games/minimal/mods/test/textures/test_bg.png b/games/minimal/mods/test/textures/test_bg.png
new file mode 100644 (file)
index 0000000..f0f3929
Binary files /dev/null and b/games/minimal/mods/test/textures/test_bg.png differ
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 (file)
index 0000000..b9ce8fd
Binary files /dev/null and b/games/minimal/mods/test/textures/test_bg_hovered.png differ
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 (file)
index 0000000..76aafb8
Binary files /dev/null and b/games/minimal/mods/test/textures/test_bg_pressed.png differ
index 7b6f8fdb41c83e5bc04a39f23d0f50d36048eb60..a2ac0b19198f87c85536c7df9cd4ad26d5d92346 100644 (file)
@@ -2,6 +2,8 @@ set(gui_SRCS
        ${CMAKE_CURRENT_SOURCE_DIR}/guiBackgroundImage.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiBox.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/guiButton.cpp
+       ${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}/guiEditBoxWithScrollbar.cpp
index 5784a552c70226fbed79dbc0c082907572505167..f120fdedba241b947eaf2025e6a4d8bc947fee00 100644 (file)
@@ -17,7 +17,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "client/tile.h" // ITextureSource
 #include "irrlichttypes_extrabloated.h"
+#include "util/string.h"
 #include <array>
 
 #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];
index 6ed5d37729e04db23fb90e3482534bde5a410d56..6518bbd1f1639e766596a491ea4089e73b58198d 100644 (file)
@@ -5,11 +5,15 @@
 #include "guiButton.h"\r
 \r
 \r
+#include "client/guiscalingfilter.h"\r
+#include "client/tile.h"\r
 #include "IGUISkin.h"\r
 #include "IGUIEnvironment.h"\r
 #include "IVideoDriver.h"\r
 #include "IGUIFont.h"\r
+#include "irrlicht_changes/static_text.h"\r
 #include "porting.h"\r
+#include "StyleSpec.h"\r
 \r
 using namespace irr;\r
 using namespace gui;\r
@@ -49,6 +53,9 @@ GUIButton::GUIButton(IGUIEnvironment* environment, IGUIElement* parent,
                        core::clamp<u32>(Colors[i].getGreen() * COLOR_PRESSED_MOD, 0, 255),\r
                        core::clamp<u32>(Colors[i].getBlue() * COLOR_PRESSED_MOD, 0, 255));\r
        }\r
+       \r
+       StaticText = gui::StaticText::add(Environment, Text.c_str(), core::rect<s32>(0,0,rectangle.getWidth(),rectangle.getHeight()), false, false, this, id);\r
+       StaticText->setTextAlignment(EGUIA_CENTER, EGUIA_CENTER);\r
        // END PATCH\r
 }\r
 \r
@@ -262,7 +269,7 @@ void GUIButton::draw()
                {\r
                        // PATCH\r
                        skin->drawColored3DButtonPaneStandard(this, AbsoluteRect, &AbsoluteClippingRect,\r
-                               Environment->getHovered() == this ? HoveredColors : Colors);\r
+                               isHovered() ? HoveredColors : Colors);\r
                        // END PATCH\r
                }\r
                else\r
@@ -318,7 +325,7 @@ void GUIButton::draw()
                        drawSprite(state, FocusTime, pos);\r
 \r
                        // mouse over / off animation\r
-                       state = Environment->getHovered() == this ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;\r
+                       state = isHovered() ? EGBS_BUTTON_MOUSE_OVER : EGBS_BUTTON_MOUSE_OFF;\r
                        drawSprite(state, HoverTime, pos);\r
                }\r
                else\r
@@ -328,23 +335,6 @@ void GUIButton::draw()
                }\r
        }\r
 \r
-       if (Text.size())\r
-       {\r
-               IGUIFont* font = getActiveFont();\r
-\r
-               core::rect<s32> rect = AbsoluteRect;\r
-               if (Pressed)\r
-               {\r
-                       rect.UpperLeftCorner.X += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_X);\r
-                       rect.UpperLeftCorner.Y += skin->getSize(EGDS_BUTTON_PRESSED_TEXT_OFFSET_Y);\r
-               }\r
-\r
-               if (font)\r
-                       font->draw(Text.c_str(), rect,\r
-                               OverrideColorEnabled ? OverrideColor : skin->getColor(isEnabled() ? EGDC_BUTTON_TEXT : EGDC_GRAY_TEXT),\r
-                               true, true, &AbsoluteClippingRect);\r
-       }\r
-\r
        IGUIElement::draw();\r
 }\r
 \r
@@ -371,11 +361,18 @@ void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::p
 }\r
 \r
 EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const\r
+{\r
+       // PATCH\r
+       return getImageState(pressed, ButtonImages);\r
+       // END PATCH\r
+}\r
+\r
+EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed, const ButtonImage* images) const\r
 {\r
        // figure state we should have\r
        EGUI_BUTTON_IMAGE_STATE state = EGBIS_IMAGE_DISABLED;\r
        bool focused = Environment->hasFocus((IGUIElement*)this);\r
-       bool mouseOver = static_cast<const IGUIElement*>(Environment->getHovered()) == this;    // (static cast for Borland)\r
+       bool mouseOver = isHovered();\r
        if (isEnabled())\r
        {\r
                if ( pressed )\r
@@ -403,7 +400,7 @@ EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const
        }\r
 \r
        // find a compatible state that has images\r
-       while ( state != EGBIS_IMAGE_UP && !ButtonImages[(u32)state].Texture )\r
+       while ( state != EGBIS_IMAGE_UP && !images[(u32)state].Texture )\r
        {\r
                // PATCH\r
                switch ( state )\r
@@ -451,6 +448,8 @@ void GUIButton::setOverrideFont(IGUIFont* font)
 \r
        if (OverrideFont)\r
                OverrideFont->grab();\r
+\r
+       StaticText->setOverrideFont(font);\r
 }\r
 \r
 //! Gets the override font (if any)\r
@@ -475,6 +474,8 @@ void GUIButton::setOverrideColor(video::SColor color)
 {\r
        OverrideColor = color;\r
        OverrideColorEnabled = true;\r
+\r
+       StaticText->setOverrideColor(color);\r
 }\r
 \r
 video::SColor GUIButton::getOverrideColor() const\r
@@ -540,6 +541,14 @@ void GUIButton::setHoveredImage(video::ITexture* image, const core::rect<s32>& p
        setImage(gui::EGBIS_IMAGE_UP_MOUSEOVER, image, pos);\r
        setImage(gui::EGBIS_IMAGE_UP_FOCUSED_MOUSEOVER, image, pos);\r
 }\r
+\r
+//! Sets the text displayed by the button\r
+void GUIButton::setText(const wchar_t* text)\r
+{\r
+       StaticText->setText(text);\r
+\r
+       IGUIButton::setText(text);\r
+}\r
 // END PATCH\r
 \r
 //! Sets if the button should behave like a push button. Which means it\r
@@ -557,6 +566,14 @@ bool GUIButton::isPressed() const
        return Pressed;\r
 }\r
 \r
+// PATCH\r
+//! Returns if this element (or one of its direct children) is hovered\r
+bool GUIButton::isHovered() const\r
+{\r
+       IGUIElement *hovered = Environment->getHovered();\r
+       return  hovered == this || (hovered != nullptr && hovered->getParent() == this);\r
+}\r
+// END PATCH\r
 \r
 //! Sets the pressed state of the button if this is a pushbutton\r
 void GUIButton::setPressed(bool pressed)\r
@@ -565,6 +582,24 @@ void GUIButton::setPressed(bool pressed)
        {\r
                ClickTime = porting::getTimeMs();\r
                Pressed = pressed;\r
+\r
+               GUISkin* skin = dynamic_cast<GUISkin*>(Environment->getSkin());\r
+\r
+               for(IGUIElement *child : getChildren())\r
+               {\r
+                       core::rect<s32> originalRect = child->getRelativePosition();\r
+                       if (Pressed) {\r
+                               child->setRelativePosition(originalRect +\r
+                                               core::dimension2d<s32>(\r
+                                                       skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),\r
+                                                       skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));\r
+                       } else {\r
+                               child->setRelativePosition(originalRect -\r
+                                               core::dimension2d<s32>(\r
+                                                       skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_X),\r
+                                                       skin->getSize(irr::gui::EGDS_BUTTON_PRESSED_IMAGE_OFFSET_Y)));\r
+                       }\r
+               }\r
        }\r
 }\r
 \r
@@ -722,4 +757,42 @@ void GUIButton::setPressedColor(video::SColor color)
                PressedColors[i] = base.getInterpolated(color, d);\r
        }\r
 }\r
+\r
+//! Set element properties from a StyleSpec\r
+void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc)\r
+{\r
+       if (style.isNotDefault(StyleSpec::BGCOLOR)) {\r
+               setColor(style.getColor(StyleSpec::BGCOLOR));\r
+       }\r
+       if (style.isNotDefault(StyleSpec::BGCOLOR_HOVERED)) {\r
+               setHoveredColor(style.getColor(StyleSpec::BGCOLOR_HOVERED));\r
+       }\r
+       if (style.isNotDefault(StyleSpec::BGCOLOR_PRESSED)) {\r
+               setPressedColor(style.getColor(StyleSpec::BGCOLOR_PRESSED));\r
+       }\r
+\r
+       if (style.isNotDefault(StyleSpec::TEXTCOLOR)) {\r
+               setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR));\r
+       }\r
+       setNotClipped(style.getBool(StyleSpec::NOCLIP, isNotClipped()));\r
+       setDrawBorder(style.getBool(StyleSpec::BORDER, DrawBorder));\r
+       setUseAlphaChannel(style.getBool(StyleSpec::ALPHA, true));\r
+\r
+       if (style.isNotDefault(StyleSpec::BGIMG)) {\r
+               video::ITexture *texture = style.getTexture(StyleSpec::BGIMG, tsrc);\r
+               video::ITexture *hovered_texture = style.getTexture(StyleSpec::BGIMG_HOVERED, tsrc, texture);\r
+               video::ITexture *pressed_texture = style.getTexture(StyleSpec::BGIMG_PRESSED, tsrc, texture);\r
+\r
+               const core::position2di buttonCenter(AbsoluteRect.getCenter());\r
+               core::position2d<s32> geom(buttonCenter);\r
+\r
+               setImage(guiScalingImageButton(\r
+                                       Environment->getVideoDriver(), texture, geom.X, geom.Y));\r
+               setHoveredImage(guiScalingImageButton(\r
+                                       Environment->getVideoDriver(), hovered_texture, geom.X, geom.Y));\r
+               setPressedImage(guiScalingImageButton(\r
+                                       Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));\r
+               setScaleImage(true);\r
+       }\r
+}\r
 // END PATCH\r
index 3c353d240459b391edd49ad4bacf97d83862af0e..37b278d25aca18830264a91e701819dacdd7cefd 100644 (file)
@@ -6,6 +6,8 @@
 \r
 #include "IrrCompileConfig.h"\r
 \r
+#include <IGUIStaticText.h>\r
+#include "irrlicht_changes/static_text.h"\r
 #include "IGUIButton.h"\r
 #include "IGUISpriteBank.h"\r
 #include "ITexture.h"\r
@@ -64,6 +66,9 @@ using namespace irr;
 \r
 #endif\r
 \r
+class ISimpleTextureSource;\r
+class StyleSpec;\r
+\r
 class GUIButton : public gui::IGUIButton\r
 {\r
 public:\r
@@ -122,6 +127,9 @@ public:
 \r
        //! Sets an image which should be displayed on the button when it is in hovered state.\r
        virtual void setHoveredImage(video::ITexture* image=nullptr);\r
+\r
+       //! Sets the text displayed by the button\r
+       virtual void setText(const wchar_t* text) override;\r
        // END PATCH\r
 \r
        //! Sets an image which should be displayed on the button when it is in hovered state.\r
@@ -172,6 +180,11 @@ public:
        //! Returns if the button is currently pressed\r
        virtual bool isPressed() const override;\r
 \r
+       // PATCH\r
+       //! Returns if this element (or one of its direct children) is hovered\r
+       bool isHovered() const;\r
+       // END PATCH\r
+\r
        //! Sets if the button should use the skin to draw its border\r
        virtual void setDrawBorder(bool border=true) override;\r
 \r
@@ -214,6 +227,9 @@ public:
        // PATCH\r
        void setHoveredColor(video::SColor color);\r
        void setPressedColor(video::SColor color);\r
+\r
+       //! Set element properties from a StyleSpec\r
+       virtual void setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc);\r
        // END PATCH\r
 \r
 \r
@@ -225,28 +241,6 @@ protected:
        void drawSprite(gui::EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center);\r
        gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed) const;\r
 \r
-private:\r
-\r
-       struct ButtonSprite\r
-       {\r
-               ButtonSprite() : Index(-1), Loop(false), Scale(false)\r
-               {\r
-               }\r
-\r
-               bool operator==(const ButtonSprite& other) const\r
-               {\r
-                       return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;\r
-               }\r
-\r
-               s32 Index;\r
-               video::SColor Color;\r
-               bool Loop;\r
-               bool Scale;\r
-       };\r
-\r
-       ButtonSprite ButtonSprites[gui::EGBS_COUNT];\r
-       gui::IGUISpriteBank* SpriteBank;\r
-\r
        struct ButtonImage\r
        {\r
                ButtonImage() : Texture(0), SourceRect(core::rect<s32>(0,0,0,0))\r
@@ -288,6 +282,30 @@ private:
                core::rect<s32> SourceRect;\r
        };\r
 \r
+       gui::EGUI_BUTTON_IMAGE_STATE getImageState(bool pressed, const ButtonImage* images) const;\r
+\r
+private:\r
+\r
+       struct ButtonSprite\r
+       {\r
+               ButtonSprite() : Index(-1), Loop(false), Scale(false)\r
+               {\r
+               }\r
+\r
+               bool operator==(const ButtonSprite& other) const\r
+               {\r
+                       return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale;\r
+               }\r
+\r
+               s32 Index;\r
+               video::SColor Color;\r
+               bool Loop;\r
+               bool Scale;\r
+       };\r
+\r
+       ButtonSprite ButtonSprites[gui::EGBS_COUNT];\r
+       gui::IGUISpriteBank* SpriteBank;\r
+\r
        ButtonImage ButtonImages[gui::EGBIS_COUNT];\r
 \r
        gui::IGUIFont* OverrideFont;\r
@@ -310,5 +328,7 @@ private:
        // PATCH\r
        video::SColor HoveredColors[4];\r
        video::SColor PressedColors[4];\r
+\r
+       gui::IGUIStaticText *StaticText;\r
        // END PATCH\r
 };\r
diff --git a/src/gui/guiButtonImage.cpp b/src/gui/guiButtonImage.cpp
new file mode 100644 (file)
index 0000000..8796b84
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@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 "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<s32> rectangle, bool noclip)
+       : GUIButton (environment, parent, id, rectangle, noclip)
+{
+       m_image = Environment->addImage(
+                       core::rect<s32>(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<s32> &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<s32> &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<s32> &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<s32> &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<s32> 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<s32> &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 (file)
index 0000000..15901ee
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@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 "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<s32> 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<s32> &sourceRect = core::rect<s32>(0, 0, 0, 0));
+
+       void setForegroundImage(video::ITexture *image = nullptr);
+       void setForegroundImage(video::ITexture *image, const core::rect<s32> &pos);
+
+       void setPressedForegroundImage(video::ITexture *image = nullptr);
+       void setPressedForegroundImage(video::ITexture *image, const core::rect<s32> &pos);
+
+       void setHoveredForegroundImage(video::ITexture *image = nullptr);
+       void setHoveredForegroundImage(video::ITexture *image, const core::rect<s32> &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<s32> &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 (file)
index 0000000..5c48b2a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@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 "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<s32> rectangle, std::string item, Client *client, bool noclip)
+               : GUIButton (environment, parent, id, rectangle, noclip)
+{
+       m_image = new GUIItemImage(environment, this, id,
+                       core::rect<s32>(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<s32> &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 (file)
index 0000000..0a61874
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@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 "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<s32> rectangle, std::string item,
+                       Client *client, bool noclip = false);
+
+       //! Do not drop returned handle
+       static GUIButtonItemImage *addButton(gui::IGUIEnvironment *environment,
+                       const core::rect<s32> &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;
+};
index ed3445b5b58efd49c068040e2180b96ae3751075..728747eb86eee215fcde9c2aa45b4562a9eb9245 100644 (file)
@@ -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<s32>(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;
index 799a60c661adc1fa41b16f90d3203f143a5004e7..f93d5476c98a9f2140a09bd7eb8ba84c7edf06a5 100644 (file)
@@ -43,18 +43,6 @@ void GUIItemImage::draw()
        item.deSerialize(m_item_name, idef);
        // Viewport rectangle on screen
        core::rect<s32> rect = core::rect<s32>(AbsoluteRect);
-       if (Parent->getType() == gui::EGUIET_BUTTON &&
-                       ((irr::gui::IGUIButton *)Parent)->isPressed()) {
-#if (IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 8)
-               rect += core::dimension2d<s32>(0.05 * (float)rect.getWidth(),
-                               0.05 * (float)rect.getHeight());
-#else
-               gui::IGUISkin *skin = Environment->getSkin();
-               rect += core::dimension2d<s32>(
-                               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);
index 5a0f82673401fa56047950d595dccbf771bec300..1375f033c344bccb0a3d8c20633533ebeb6b4483 100644 (file)
@@ -112,7 +112,7 @@ void StaticText::draw()
 #if USE_FREETYPE
                                if (font->getType() == irr::gui::EGFT_CUSTOM) {
                                        irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(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,
index 30d1e9e1cf6762566fd8914a2fe4178d552a6abc..f15b37cf5e3b28e91d3fc08a147016c884338ed1 100644 (file)
@@ -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