Skip to content

Commit

Permalink
Add 9-slice background support to button formspec elements (#9290)
Browse files Browse the repository at this point in the history
  • Loading branch information
Df458 authored and rubenwardy committed Jan 26, 2020
1 parent cde2a7f commit 60544ac
Show file tree
Hide file tree
Showing 9 changed files with 86 additions and 4 deletions.
2 changes: 2 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -2573,6 +2573,8 @@ Some types may inherit styles from parent types.
* bgcolor_pressed - color when pressed. Defaults to a darker bgcolor when not provided.
* bgimg - standard background image. Defaults to none.
* bgimg_hovered - background image when hovered. Defaults to bgimg when not provided.
* bgimg_middle - Makes the bgimg textures render in 9-sliced mode and defines the middle rect.
See background9[] documentation for more details
* 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.
Expand Down
3 changes: 3 additions & 0 deletions games/minimal/mods/test/formspec.lua
Expand Up @@ -78,6 +78,9 @@ local style_fs = [[
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]
style[one_btn16;border=false;bgimg=test_bg_9slice.png;bgimg_hovered=test_bg_9slice_hovered.png;bgimg_pressed=test_bg_9slice_pressed.png;bgimg_middle=4,6]
button[2.5,9.6;2,1;one_btn16;9-Slice Bg]
container[2.75,0]
Expand Down
Binary file added games/minimal/mods/test/textures/test_bg_9slice.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions src/gui/StyleSpec.h
Expand Up @@ -37,6 +37,7 @@ class StyleSpec
BORDER,
BGIMG,
BGIMG_HOVERED,
BGIMG_MIDDLE,
BGIMG_PRESSED,
FGIMG,
FGIMG_HOVERED,
Expand Down Expand Up @@ -69,6 +70,8 @@ class StyleSpec
return BGIMG;
} else if (name == "bgimg_hovered") {
return BGIMG_HOVERED;
} else if (name == "bgimg_middle") {
return BGIMG_MIDDLE;
} else if (name == "bgimg_pressed") {
return BGIMG_PRESSED;
} else if (name == "fgimg") {
Expand Down Expand Up @@ -117,6 +120,29 @@ class StyleSpec
return color;
}

irr::core::rect<s32> getRect(Property prop, irr::core::rect<s32> def) const
{
const auto &val = properties[prop];
if (val.empty())
return def;

irr::core::rect<s32> rect;
if (!parseRect(val, &rect))
return def;

return rect;
}

irr::core::rect<s32> getRect(Property prop) const
{
const auto &val = properties[prop];
FATAL_ERROR_IF(val.empty(), "Unexpected missing property");

irr::core::rect<s32> rect;
parseRect(val, &rect);
return rect;
}

video::ITexture *getTexture(Property prop, ISimpleTextureSource *tsrc,
video::ITexture *def) const
{
Expand Down Expand Up @@ -175,4 +201,36 @@ class StyleSpec
newspec |= other;
return newspec;
}

private:
bool parseRect(const std::string &value, irr::core::rect<s32> *parsed_rect) const
{
irr::core::rect<s32> rect;
std::vector<std::string> v_rect = split(value, ',');

if (v_rect.size() == 1) {
s32 x = stoi(v_rect[0]);
rect.UpperLeftCorner = irr::core::vector2di(x, x);
rect.LowerRightCorner = irr::core::vector2di(-x, -x);
} else if (v_rect.size() == 2) {
s32 x = stoi(v_rect[0]);
s32 y = stoi(v_rect[1]);
rect.UpperLeftCorner = irr::core::vector2di(x, y);
rect.LowerRightCorner = irr::core::vector2di(-x, -y);
// `-x` is interpreted as `w - x`
} else if (v_rect.size() == 4) {
rect.UpperLeftCorner = irr::core::vector2di(
stoi(v_rect[0]), stoi(v_rect[1]));
rect.LowerRightCorner = irr::core::vector2di(
stoi(v_rect[2]), stoi(v_rect[3]));
} else {
warningstream << "Invalid rectangle string format: \"" << value
<< "\"" << std::endl;
return false;
}

*parsed_rect = rect;

return true;
}
};
24 changes: 20 additions & 4 deletions src/gui/guiButton.cpp
Expand Up @@ -307,10 +307,25 @@ void GUIButton::draw()
}
}

driver->draw2DImage(ButtonImages[(u32)imageState].Texture,
ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
sourceRect, &AbsoluteClippingRect,
0, UseAlphaChannel);
// PATCH
video::ITexture* texture = ButtonImages[(u32)imageState].Texture;
if (BgMiddle.getArea() == 0) {
driver->draw2DImage(texture,
ScaleImage? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
sourceRect, &AbsoluteClippingRect,
0, UseAlphaChannel);
} else {
core::rect<s32> middle = BgMiddle;
// `-x` is interpreted as `w - x`
if (middle.LowerRightCorner.X < 0)
middle.LowerRightCorner.X += texture->getOriginalSize().Width;
if (middle.LowerRightCorner.Y < 0)
middle.LowerRightCorner.Y += texture->getOriginalSize().Height;
draw2DImage9Slice(driver, texture,
ScaleImage ? AbsoluteRect : core::rect<s32>(pos, sourceRect.getSize()),
middle, &AbsoluteClippingRect);
}
// END PATCH
}

if (SpriteBank)
Expand Down Expand Up @@ -804,5 +819,6 @@ void GUIButton::setFromStyle(const StyleSpec& style, ISimpleTextureSource *tsrc)
Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y));
setScaleImage(true);
}
BgMiddle = style.getRect(StyleSpec::BGIMG_MIDDLE, BgMiddle);
}
// END PATCH
2 changes: 2 additions & 0 deletions src/gui/guiButton.h
Expand Up @@ -330,5 +330,7 @@ class GUIButton : public gui::IGUIButton
video::SColor PressedColors[4];

gui::IGUIStaticText *StaticText;

core::rect<s32> BgMiddle;
// END PATCH
};
1 change: 1 addition & 0 deletions util/travis/clang-format-whitelist.txt
Expand Up @@ -196,6 +196,7 @@ src/gui/mainmenumanager.h
src/gui/modalMenu.h
src/guiscalingfilter.cpp
src/guiscalingfilter.h
src/gui/StyleSpec.h
src/gui/touchscreengui.cpp
src/httpfetch.cpp
src/hud.cpp
Expand Down

0 comments on commit 60544ac

Please sign in to comment.