Skip to content

Commit f780bae

Browse files
author
Hugues Ross
authoredApr 11, 2020
Formspecs: Add state-selection to style elements (#9378)
1 parent ba3587e commit f780bae

22 files changed

+454
-317
lines changed
 

Diff for: ‎doc/lua_api.txt

+45-16
Original file line numberDiff line numberDiff line change
@@ -2188,12 +2188,12 @@ Elements
21882188

21892189
* 9-sliced background. See https://en.wikipedia.org/wiki/9-slice_scaling
21902190
* Middle is a rect which defines the middle of the 9-slice.
2191-
* `x` - The middle will be x pixels from all sides.
2192-
* `x,y` - The middle will be x pixels from the horizontal and y from the vertical.
2193-
* `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values
2194-
will be added to the width and height of the texture, allowing it to be used as the
2195-
distance from the far end.
2196-
* All numbers in middle are integers.
2191+
* `x` - The middle will be x pixels from all sides.
2192+
* `x,y` - The middle will be x pixels from the horizontal and y from the vertical.
2193+
* `x,y,x2,y2` - The middle will start at x,y, and end at x2, y2. Negative x2 and y2 values
2194+
will be added to the width and height of the texture, allowing it to be used as the
2195+
distance from the far end.
2196+
* All numbers in middle are integers.
21972197
* Example for formspec 8x4 in 16x resolution:
21982198
image shall be sized 8 times 16px times 4 times 16px
21992199
* If `auto_clip` is `true`, the background is clipped to the formspec size
@@ -2508,16 +2508,28 @@ Elements
25082508
* `span=<value>`: number of following columns to affect
25092509
(default: infinite).
25102510

2511-
### `style[<name 1>,<name 2>,...;<prop1>;<prop2>;...]`
2511+
### `style[<selector 1>,<selector 2>;<prop1>;<prop2>;...]`
25122512

2513-
* Set the style for the named element(s) `name`.
2513+
* Set the style for the element(s) matching `selector` by name.
2514+
* `selector` can be one of:
2515+
* `<name>` - An element name.
2516+
* `<name>:<state>` - An element name, a colon, and one or more states.
2517+
* `state` is a list of states separated by the `+` character.
2518+
* If a state is provided, the style will only take effect when the element is in that state.
2519+
* All provided states must be active for the style to apply.
25142520
* Note: this **must** be before the element is defined.
25152521
* See [Styling Formspecs].
25162522

25172523

2518-
### `style_type[<type 1>,<type 2>,...;<prop1>;<prop2>;...]`
2524+
### `style_type[<selector 1>,<selector 2>;<prop1>;<prop2>;...]`
25192525

2520-
* Sets the style for all elements of type(s) `type` which appear after this element.
2526+
* Set the style for the element(s) matching `selector` by type.
2527+
* `selector` can be one of:
2528+
* `<type>` - An element type.
2529+
* `<type>:<state>` - An element type, a colon, and one or more states.
2530+
* `state` is a list of states separated by the `+` character.
2531+
* If a state is provided, the style will only take effect when the element is in that state.
2532+
* All provided states must be active for the style to apply.
25212533
* See [Styling Formspecs].
25222534

25232535
Migrating to Real Coordinates
@@ -2560,23 +2572,32 @@ Styling Formspecs
25602572

25612573
Formspec elements can be themed using the style elements:
25622574

2563-
style[<name 1>,<name 2>,...;<prop1>;<prop2>;...]
2564-
style_type[<type 1>,<type 2>,...;<prop1>;<prop2>;...]
2575+
style[<name 1>,<name 2>;<prop1>;<prop2>;...]
2576+
style[<name 1>:<state>,<name 2>:<state>;<prop1>;<prop2>;...]
2577+
style_type[<type 1>,<type 2>;<prop1>;<prop2>;...]
2578+
style_type[<type 1>:<state>,<type 2>:<state>;<prop1>;<prop2>;...]
25652579

25662580
Where a prop is:
25672581

25682582
property_name=property_value
25692583

2584+
For example:
2585+
2586+
style_type[button;bgcolor=#006699]
2587+
style[world_delete;bgcolor=red;textcolor=yellow]
2588+
button[4,3.95;2.6,1;world_delete;Delete]
2589+
25702590
A name/type can optionally be a comma separated list of names/types, like so:
25712591

25722592
world_delete,world_create,world_configure
25732593
button,image_button
25742594

2575-
For example:
2595+
Any name/type in the list can also be accompanied by a `+`-separated list of states, like so:
25762596

2577-
style_type[button;bgcolor=#006699]
2578-
style[world_delete;bgcolor=red;textcolor=yellow]
2579-
button[4,3.95;2.6,1;world_delete;Delete]
2597+
world_delete:hovered+pressed
2598+
button:pressed
2599+
2600+
States allow you to apply styles in response to changes in the element, instead of applying at all times.
25802601

25812602
Setting a property to nothing will reset it to the default value. For example:
25822603

@@ -2654,6 +2675,14 @@ Some types may inherit styles from parent types.
26542675
* noclip - boolean, set to true to allow the element to exceed formspec bounds.
26552676
* textcolor - color. Default white.
26562677

2678+
### Valid States
2679+
2680+
* *all elements*
2681+
* default - Equivalent to providing no states
2682+
* button, button_exit, image_button, item_image_button
2683+
* hovered - Active when the mouse is hovering over the element
2684+
* pressed - Active when the button is pressed
2685+
26572686
Markup Language
26582687
---------------
26592688

Diff for: ‎games/minimal/mods/test/formspec.lua

+4-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ local style_fs = [[
6565
style[one_btn13;border=false]
6666
item_image_button[1.25,8.35;1,1;default:sword_steel;one_btn13;NoBor]
6767
68-
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]
68+
style[one_btn14;border=false;bgimg=test_bg.png;fgimg=bubble.png]
69+
style[one_btn14:hovered;bgimg=test_bg_hovered.png;fgimg=default_apple.png;textcolor=red]
70+
style[one_btn14:pressed;bgimg=test_bg_pressed.png;fgimg=heart.png;textcolor=green]
71+
style[one_btn14:hovered+pressed;textcolor=blue]
6972
image_button[0,9.6;1,1;bubble.png;one_btn14;Bg]
7073
7174
style[one_btn15;border=false;bgimg=test_bg.png;bgimg_hovered=test_bg_hovered.png;bgimg_pressed=test_bg_pressed.png]

Diff for: ‎src/client/game.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -1556,7 +1556,8 @@ bool Game::connectToServer(const std::string &playername,
15561556
} else {
15571557
registration_confirmation_shown = true;
15581558
(new GUIConfirmRegistration(guienv, guienv->getRootGUIElement(), -1,
1559-
&g_menumgr, client, playername, password, connection_aborted))->drop();
1559+
&g_menumgr, client, playername, password,
1560+
connection_aborted, texture_src))->drop();
15601561
}
15611562
} else {
15621563
wait_time += dtime;
@@ -1711,19 +1712,19 @@ inline bool Game::handleCallbacks()
17111712

17121713
if (g_gamecallback->changepassword_requested) {
17131714
(new GUIPasswordChange(guienv, guiroot, -1,
1714-
&g_menumgr, client))->drop();
1715+
&g_menumgr, client, texture_src))->drop();
17151716
g_gamecallback->changepassword_requested = false;
17161717
}
17171718

17181719
if (g_gamecallback->changevolume_requested) {
17191720
(new GUIVolumeChange(guienv, guiroot, -1,
1720-
&g_menumgr))->drop();
1721+
&g_menumgr, texture_src))->drop();
17211722
g_gamecallback->changevolume_requested = false;
17221723
}
17231724

17241725
if (g_gamecallback->keyconfig_requested) {
17251726
(new GUIKeyChangeMenu(guienv, guiroot, -1,
1726-
&g_menumgr))->drop();
1727+
&g_menumgr, texture_src))->drop();
17271728
g_gamecallback->keyconfig_requested = false;
17281729
}
17291730

Diff for: ‎src/gui/StyleSpec.h

+59-6
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
1818
*/
1919

2020
#include "client/tile.h" // ITextureSource
21+
#include "debug.h"
2122
#include "irrlichttypes_extrabloated.h"
2223
#include "util/string.h"
2324
#include <array>
@@ -31,25 +32,34 @@ class StyleSpec
3132
{
3233
TEXTCOLOR,
3334
BGCOLOR,
34-
BGCOLOR_HOVERED,
35-
BGCOLOR_PRESSED,
35+
BGCOLOR_HOVERED, // Note: Deprecated property
36+
BGCOLOR_PRESSED, // Note: Deprecated property
3637
NOCLIP,
3738
BORDER,
3839
BGIMG,
39-
BGIMG_HOVERED,
40+
BGIMG_HOVERED, // Note: Deprecated property
4041
BGIMG_MIDDLE,
41-
BGIMG_PRESSED,
42+
BGIMG_PRESSED, // Note: Deprecated property
4243
FGIMG,
43-
FGIMG_HOVERED,
44-
FGIMG_PRESSED,
44+
FGIMG_HOVERED, // Note: Deprecated property
45+
FGIMG_PRESSED, // Note: Deprecated property
4546
ALPHA,
4647
NUM_PROPERTIES,
4748
NONE
4849
};
50+
enum State
51+
{
52+
STATE_DEFAULT = 0,
53+
STATE_HOVERED = 1 << 0,
54+
STATE_PRESSED = 1 << 1,
55+
NUM_STATES = 1 << 2,
56+
STATE_INVALID = 1 << 3,
57+
};
4958

5059
private:
5160
std::array<bool, NUM_PROPERTIES> property_set{};
5261
std::array<std::string, NUM_PROPERTIES> properties;
62+
State state_map = STATE_DEFAULT;
5363

5464
public:
5565
static Property GetPropertyByName(const std::string &name)
@@ -99,6 +109,49 @@ class StyleSpec
99109
property_set[prop] = true;
100110
}
101111

112+
//! Parses a name and returns the corresponding state enum
113+
static State getStateByName(const std::string &name)
114+
{
115+
if (name == "default") {
116+
return STATE_DEFAULT;
117+
} else if (name == "hovered") {
118+
return STATE_HOVERED;
119+
} else if (name == "pressed") {
120+
return STATE_PRESSED;
121+
} else {
122+
return STATE_INVALID;
123+
}
124+
}
125+
126+
//! Gets the state that this style is intended for
127+
State getState() const
128+
{
129+
return state_map;
130+
}
131+
132+
//! Set the given state on this style
133+
void addState(State state)
134+
{
135+
FATAL_ERROR_IF(state >= NUM_STATES, "Out-of-bounds state received");
136+
137+
state_map = static_cast<State>(state_map | state);
138+
}
139+
140+
//! Using a list of styles mapped to state values, calculate the final
141+
// combined style for a state by propagating values in its component states
142+
static StyleSpec getStyleFromStatePropagation(const std::array<StyleSpec, NUM_STATES> &styles, State state)
143+
{
144+
StyleSpec temp = styles[StyleSpec::STATE_DEFAULT];
145+
temp.state_map = state;
146+
for (int i = StyleSpec::STATE_DEFAULT + 1; i <= state; i++) {
147+
if ((state & i) != 0) {
148+
temp = temp | styles[i];
149+
}
150+
}
151+
152+
return temp;
153+
}
154+
102155
video::SColor getColor(Property prop, video::SColor def) const
103156
{
104157
const auto &val = properties[prop];

0 commit comments

Comments
 (0)
Please sign in to comment.