From 4c001bd24854b56f6e09372c4ac6870770053f98 Mon Sep 17 00:00:00 2001 From: grorp Date: Wed, 26 Jun 2024 15:25:27 +0200 Subject: [PATCH] Make button sprites (scrollbar arrows) DPI-aware (#14772) --- irr/include/IGUIButton.h | 5 +--- irr/include/IGUISkin.h | 6 +++++ irr/src/CGUIButton.cpp | 40 +++++++++++++++---------------- irr/src/CGUIButton.h | 10 +++----- irr/src/CGUISkin.h | 7 ++++++ src/client/clientlauncher.cpp | 1 + src/gui/guiButton.cpp | 44 ++++++++++++++++------------------- src/gui/guiButton.h | 8 ++----- src/gui/guiSkin.h | 7 ++++++ 9 files changed, 67 insertions(+), 61 deletions(-) diff --git a/irr/include/IGUIButton.h b/irr/include/IGUIButton.h index 0fbf866ac..8870f8b1c 100644 --- a/irr/include/IGUIButton.h +++ b/irr/include/IGUIButton.h @@ -200,7 +200,7 @@ class IGUIButton : public IGUIElement \param loop: True if the animation should loop, false if not \param scale: True if the sprite should scale to button size, false if not */ virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, - video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false, bool scale = false) = 0; + video::SColor color = video::SColor(255, 255, 255, 255), bool loop = false) = 0; //! Get the sprite-index for the given state or -1 when no sprite is set virtual s32 getSpriteIndex(EGUI_BUTTON_STATE state) const = 0; @@ -211,9 +211,6 @@ class IGUIButton : public IGUIElement //! Returns if the sprite in the given state does loop virtual bool getSpriteLoop(EGUI_BUTTON_STATE state) const = 0; - //! Returns if the sprite in the given state is scaled - virtual bool getSpriteScale(EGUI_BUTTON_STATE state) const = 0; - //! Sets if the button should behave like a push button. /** Which means it can be in two states: Normal or Pressed. With a click on the button, the user can change the state of the button. */ diff --git a/irr/include/IGUISkin.h b/irr/include/IGUISkin.h index 6ec456472..36b510606 100644 --- a/irr/include/IGUISkin.h +++ b/irr/include/IGUISkin.h @@ -374,6 +374,12 @@ const c8 *const GUISkinFontNames[EGDF_COUNT + 1] = { class IGUISkin : virtual public IReferenceCounted { public: + //! returns display density scaling factor + virtual float getScale() const = 0; + + //! sets display density scaling factor + virtual void setScale(float scale) = 0; + //! returns default color virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const = 0; diff --git a/irr/src/CGUIButton.cpp b/irr/src/CGUIButton.cpp index f023024f9..60bab5f83 100644 --- a/irr/src/CGUIButton.cpp +++ b/irr/src/CGUIButton.cpp @@ -75,12 +75,11 @@ void CGUIButton::setSpriteBank(IGUISpriteBank *sprites) SpriteBank = sprites; } -void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale) +void CGUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) { ButtonSprites[(u32)state].Index = index; ButtonSprites[(u32)state].Color = color; ButtonSprites[(u32)state].Loop = loop; - ButtonSprites[(u32)state].Scale = scale; } //! Get the sprite-index for the given state or -1 when no sprite is set @@ -101,12 +100,6 @@ bool CGUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const return ButtonSprites[(u32)state].Loop; } -//! Returns if the sprite in the given state is scaled -bool CGUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const -{ - return ButtonSprites[(u32)state].Scale; -} - //! called if an event happened. bool CGUIButton::OnEvent(const SEvent &event) { @@ -294,19 +287,26 @@ void CGUIButton::draw() void CGUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di ¢er) { u32 stateIdx = (u32)state; + s32 spriteIdx = ButtonSprites[stateIdx].Index; + if (spriteIdx == -1) + return; - if (ButtonSprites[stateIdx].Index != -1) { - if (ButtonSprites[stateIdx].Scale) { - const video::SColor colors[] = {ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color, ButtonSprites[stateIdx].Color}; - SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect, - &AbsoluteClippingRect, colors, - os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop); - } else { - SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center, - &AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, os::Timer::getTime(), - ButtonSprites[stateIdx].Loop, true); - } - } + u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber; + core::rect srcRect = SpriteBank->getPositions()[rectIdx]; + + IGUISkin *skin = Environment->getSkin(); + s32 scale = std::max(std::floor(skin->getScale()), 1.0f); + core::rect rect(center, srcRect.getSize() * scale); + rect -= rect.getSize() / 2; + + const video::SColor colors[] = { + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + }; + SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors, + os::Timer::getTime() - startTime, ButtonSprites[stateIdx].Loop); } EGUI_BUTTON_IMAGE_STATE CGUIButton::getImageState(bool pressed) const diff --git a/irr/src/CGUIButton.h b/irr/src/CGUIButton.h index 8ff36c9a7..8a1434025 100644 --- a/irr/src/CGUIButton.h +++ b/irr/src/CGUIButton.h @@ -92,7 +92,7 @@ class CGUIButton : public IGUIButton */ virtual void setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color = video::SColor(255, 255, 255, 255), - bool loop = false, bool scale = false) override; + bool loop = false) override; //! Get the sprite-index for the given state or -1 when no sprite is set s32 getSpriteIndex(EGUI_BUTTON_STATE state) const override; @@ -103,9 +103,6 @@ class CGUIButton : public IGUIButton //! Returns if the sprite in the given state does loop bool getSpriteLoop(EGUI_BUTTON_STATE state) const override; - //! Returns if the sprite in the given state is scaled - bool getSpriteScale(EGUI_BUTTON_STATE state) const override; - //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. @@ -158,19 +155,18 @@ class CGUIButton : public IGUIButton struct ButtonSprite { ButtonSprite() : - Index(-1), Loop(false), Scale(false) + Index(-1), Loop(false) { } bool operator==(const ButtonSprite &other) const { - return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale; + return Index == other.Index && Color == other.Color && Loop == other.Loop; } s32 Index; video::SColor Color; bool Loop; - bool Scale; }; ButtonSprite ButtonSprites[EGBS_COUNT]; diff --git a/irr/src/CGUISkin.h b/irr/src/CGUISkin.h index 130e5fada..68eae1c73 100644 --- a/irr/src/CGUISkin.h +++ b/irr/src/CGUISkin.h @@ -24,6 +24,12 @@ class CGUISkin : public IGUISkin //! destructor virtual ~CGUISkin(); + //! returns display density scaling factor + virtual float getScale() const override { return Scale; } + + //! sets display density scaling factor + virtual void setScale(float scale) override { Scale = scale; } + //! returns default color video::SColor getColor(EGUI_DEFAULT_COLOR color) const override; @@ -210,6 +216,7 @@ class CGUISkin : public IGUISkin EGUI_SKIN_TYPE getType() const override; private: + float Scale = 1.0f; video::SColor Colors[EGDC_COUNT]; s32 Sizes[EGDS_COUNT]; u32 Icons[EGDI_COUNT]; diff --git a/src/client/clientlauncher.cpp b/src/client/clientlauncher.cpp index f64d02844..5365d70f9 100644 --- a/src/client/clientlauncher.cpp +++ b/src/client/clientlauncher.cpp @@ -352,6 +352,7 @@ void ClientLauncher::config_guienv() float density = rangelim(g_settings->getFloat("gui_scaling"), 0.5f, 20) * RenderingEngine::getDisplayDensity(); + skin->setScale(density); skin->setSize(gui::EGDS_CHECK_BOX_WIDTH, (s32)(17.0f * density)); skin->setSize(gui::EGDS_SCROLLBAR_SIZE, (s32)(21.0f * density)); skin->setSize(gui::EGDS_WINDOW_BUTTON_WIDTH, (s32)(15.0f * density)); diff --git a/src/gui/guiButton.cpp b/src/gui/guiButton.cpp index 4e47e7425..d78433edd 100644 --- a/src/gui/guiButton.cpp +++ b/src/gui/guiButton.cpp @@ -89,12 +89,11 @@ void GUIButton::setSpriteBank(IGUISpriteBank* sprites) SpriteBank = sprites; } -void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop, bool scale) +void GUIButton::setSprite(EGUI_BUTTON_STATE state, s32 index, video::SColor color, bool loop) { ButtonSprites[(u32)state].Index = index; ButtonSprites[(u32)state].Color = color; ButtonSprites[(u32)state].Loop = loop; - ButtonSprites[(u32)state].Scale = scale; } //! Get the sprite-index for the given state or -1 when no sprite is set @@ -115,12 +114,6 @@ bool GUIButton::getSpriteLoop(EGUI_BUTTON_STATE state) const return ButtonSprites[(u32)state].Loop; } -//! Returns if the sprite in the given state is scaled -bool GUIButton::getSpriteScale(EGUI_BUTTON_STATE state) const -{ - return ButtonSprites[(u32)state].Scale; -} - //! called if an event happened. bool GUIButton::OnEvent(const SEvent& event) { @@ -354,23 +347,26 @@ void GUIButton::draw() void GUIButton::drawSprite(EGUI_BUTTON_STATE state, u32 startTime, const core::position2di& center) { u32 stateIdx = (u32)state; + s32 spriteIdx = ButtonSprites[stateIdx].Index; + if (spriteIdx == -1) + return; - if (ButtonSprites[stateIdx].Index != -1) - { - if ( ButtonSprites[stateIdx].Scale ) - { - const video::SColor colors[] = {ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color,ButtonSprites[stateIdx].Color}; - SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, AbsoluteRect.UpperLeftCorner, - &AbsoluteClippingRect, colors[0], // FIXME: remove [0] - porting::getTimeMs()-startTime, ButtonSprites[stateIdx].Loop); - } - else - { - SpriteBank->draw2DSprite(ButtonSprites[stateIdx].Index, center, - &AbsoluteClippingRect, ButtonSprites[stateIdx].Color, startTime, porting::getTimeMs(), - ButtonSprites[stateIdx].Loop, true); - } - } + u32 rectIdx = SpriteBank->getSprites()[spriteIdx].Frames[0].rectNumber; + core::rect srcRect = SpriteBank->getPositions()[rectIdx]; + + IGUISkin *skin = Environment->getSkin(); + s32 scale = std::max(std::floor(skin->getScale()), 1.0f); + core::rect rect(center, srcRect.getSize() * scale); + rect -= rect.getSize() / 2; + + const video::SColor colors[] = { + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + ButtonSprites[stateIdx].Color, + }; + SpriteBank->draw2DSprite(spriteIdx, rect, &AbsoluteClippingRect, colors, + porting::getTimeMs() - startTime, ButtonSprites[stateIdx].Loop); } EGUI_BUTTON_IMAGE_STATE GUIButton::getImageState(bool pressed) const diff --git a/src/gui/guiButton.h b/src/gui/guiButton.h index c96f1ca4e..4fad8747c 100644 --- a/src/gui/guiButton.h +++ b/src/gui/guiButton.h @@ -92,7 +92,7 @@ class GUIButton : public gui::IGUIButton */ virtual void setSprite(gui::EGUI_BUTTON_STATE state, s32 index, video::SColor color=video::SColor(255,255,255,255), - bool loop=false, bool scale=false) override; + bool loop=false) override; //! Get the sprite-index for the given state or -1 when no sprite is set virtual s32 getSpriteIndex(gui::EGUI_BUTTON_STATE state) const override; @@ -103,9 +103,6 @@ class GUIButton : public gui::IGUIButton //! Returns if the sprite in the given state does loop virtual bool getSpriteLoop(gui::EGUI_BUTTON_STATE state) const override; - //! Returns if the sprite in the given state is scaled - virtual bool getSpriteScale(gui::EGUI_BUTTON_STATE state) const override; - //! Sets if the button should behave like a push button. Which means it //! can be in two states: Normal or Pressed. With a click on the button, //! the user can change the state of the button. @@ -230,13 +227,12 @@ class GUIButton : public gui::IGUIButton { bool operator==(const ButtonSprite &other) const { - return Index == other.Index && Color == other.Color && Loop == other.Loop && Scale == other.Scale; + return Index == other.Index && Color == other.Color && Loop == other.Loop; } s32 Index = -1; video::SColor Color; bool Loop = false; - bool Scale = false; }; ButtonSprite ButtonSprites[gui::EGBS_COUNT]; diff --git a/src/gui/guiSkin.h b/src/gui/guiSkin.h index 623a9c30a..33df7a933 100644 --- a/src/gui/guiSkin.h +++ b/src/gui/guiSkin.h @@ -27,6 +27,12 @@ namespace gui //! destructor virtual ~GUISkin(); + //! returns display density scaling factor + virtual float getScale() const { return Scale; } + + //! sets display density scaling factor + virtual void setScale(float scale) { Scale = scale; } + //! returns default color virtual video::SColor getColor(EGUI_DEFAULT_COLOR color) const; @@ -292,6 +298,7 @@ namespace gui private: + float Scale = 1.0f; video::SColor Colors[EGDC_COUNT]; s32 Sizes[EGDS_COUNT]; u32 Icons[EGDI_COUNT];