~jadedctrl/gem-xwx-moe

~jadedctrl/gem-xwx-moe/gemujo_ludo/mods.niaj/fasado/subtitles/menu.lua
 ..
0 --[[
1 Subtitles — adds subtitles to Minetest.
2
3 Copyright © 2022‒2023, Silver Sandstone <@SilverSandstone@craftodon.social>
4
5 Permission is hereby granted, free of charge, to any person obtaining a
6 copy of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom the
10 Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22 ]]
23
24
25 --- Implements the subtitle menu GUI.
26
27
28 local S = subtitles.S;
29
30
31 local MAX_HEIGHT = 10.5;
32
33
34 --- Creates a menu formspec for the specified player.
35 -- @param player The username or ObjectRef of the player.
36 -- @param embedded This should be true if the menu is being embedded in another formspec.
37 -- @param options A table of extra options: width, height.
38 -- @return A formspec string.
39 function subtitles.get_menu_formspec(player, embedded, options)
40 local agent = subtitles.get_agent(player);
41 player = agent.username;
42 options = options or {};
43
44 local _esc = minetest.formspec_escape;
45 local natural_height = 3.75 + #subtitles.SubtitleDisplay.implementations * 1.25;
46 local width = options.width or 8;
47 local height = options.height or math.min(natural_height, MAX_HEIGHT);
48 local display_name = agent:get_display_name();
49
50 -- Style:
51 local style = {};
52 local selection_colour = '#80808040';
53 local panel = 'subtitles_panel.png;4';
54 local disabled_mod = '^subtitles_slash.png';
55 local state_icon = 'subtitles_icon.png';
56 local footsteps_icon = 'subtitles_footsteps.png';
57 local circle = 'subtitles_circle.png';
58
59 if minetest.get_modpath('rp_formspec') then
60 -- Repixture style:
61 table.insert_all(style,
62 {
63 'background9[0,0;0,0;ui_formspec_bg_short.png^[resize:384x192;true;24] bgcolor[#00000000]', -- Background
64 'style_type[button,image_button;border=false]', -- Reset buttons
65 'style_type[button,image_button;bgimg=ui_button_1w_inactive.png^[resize:48x48;bgimg_middle=21,18,-20,-24]', -- Passive button image
66 'style_type[button:pressed,image_button:pressed;bgimg=ui_button_1w_active.png^[resize:48x48;bgimg_middle=21,21,-20,-21]', -- Active button image
67 });
68 selection_colour = '#33333340';
69 panel = 'ui_itemslot.png^[resize:72x72;32';
70 elseif minetest.get_modpath('mcl_core') then
71 -- MineClone style:
72 panel = 'subtitles_mcl_panel.png;4';
73 elseif embedded and minetest.get_modpath('i3') then
74 -- i3 style:
75 panel = 'subtitles_i3_panel.png;4';
76 state_icon = 'subtitles_icon_flat_hd.png';
77 footsteps_icon = 'subtitles_i3_footsteps.png';
78 disabled_mod = '^[multiply:#9F9F9F';
79 circle = 'subtitles_i3_circle.png';
80 end;
81
82 -- State:
83 local enabled = agent:get_enabled();
84 local state_label;
85 local toggle_tooltip;
86 if enabled then
87 state_label = S('Subtitles enabled');
88 toggle_tooltip = S('Click to disable subtitles');
89 else
90 state_label = S('Subtitles disabled');
91 toggle_tooltip = S('Click to enable subtitles');
92 state_icon = state_icon .. disabled_mod;
93 end;
94
95 local footsteps = agent:get_footsteps_enabled();
96 local footsteps_tooltip;
97 if footsteps then
98 footsteps_tooltip = S('Footsteps enabled');
99 else
100 footsteps_tooltip = S('Footsteps disabled');
101 footsteps_icon = footsteps_icon .. disabled_mod;
102 end;
103
104 -- Main menu:
105 local formspec =
106 {
107 ('size[%f,%f] real_coordinates[true]'):format(width, height),
108 table.concat(style, ''),
109 -- Toggle button:
110 ('image_button[0.25,0.25;1,1;%s;toggle;]'):format(_esc(state_icon)),
111 ('tooltip[toggle;%s]'):format(_esc(toggle_tooltip)),
112 -- State label:
113 --('label[1.5,0.75;%s]'):format(_esc(state_label)),
114 ('hypertext[1.5,0.5;%f,1;state_label;<big><b>%s</b></big>]'):format(width - 1.75, _esc(state_label)),
115
116 -- Mode panel:
117 ('image[0.25,2.0;%f,%f;%s]'):format(width - 0.5, height - 3.5, panel),
118 ('label[0.25,1.75;%s]'):format(_esc(S('Display mode:'))),
119
120 -- Footsteps button:
121 ('image_button[0.25,%f;1,1;%s;footsteps;]'):format(height - 1.25, _esc(footsteps_icon)),
122 ('tooltip[footsteps;%s]'):format(_esc(footsteps and S('Footsteps enabled') or S('Footsteps disabled'))),
123 -- Exit button:
124 ('button_exit[%f,%f;3,1;done;%s]'):format(width - 3.25, height - 1.25, _esc(S('Done'))),
125
126 -- Mode list:
127 ('scroll_container[0.25,2.0;%f,%f;mode_list_scrollbar;vertical;]'):format(width - 0.5, height - 3.5),
128 ('scrollbaroptions[max=%d]'):format(math.max(0, natural_height - height)),
129 ('scrollbar[%f,2.0;0.5,%f;vertical;mode_list_scrollbar;]'):format(width - 0.5, height - 3.5),
130 };
131 if embedded then
132 formspec[1] = '';
133 end;
134
135 -- Display modes:
136 for index, impl in ipairs(subtitles.SubtitleDisplay.implementations) do
137 local y = 0.25 + (index - 1) * 1.25;
138 if impl.NAME == display_name then
139 local colour = enabled and '#00FF00' or '#BFBFBF';
140 table.insert_all(formspec,
141 {
142 ('box[0.125,%f;%f,1.25;%s]'):format(y - 0.125, width - 0.75, selection_colour),
143 ('image[%f,%f;1,1;%s^[multiply:%s]'):format(width - 1.75, y, circle, colour),
144 });
145 end;
146 table.insert_all(formspec,
147 {
148 ('image[0.25,%f;1,1;%s]'):format(y, _esc(impl.ICON)),
149 ('button[1.5,%f;%f,1;display_%s;%s]'):format(y, width - 3.5, impl.NAME, _esc(impl.TITLE)),
150 ('tooltip[display_%s;%s]'):format(impl.NAME, _esc(impl.DESCRIPTION or impl.TITLE)),
151 });
152 end;
153
154 table.insert(formspec, 'scroll_container_end[]');
155
156 return table.concat(formspec, '');
157 end;
158
159
160 --- Shows the subtitle menu to the specified player.
161 -- @param player The username or ObjectRef of the player.
162 function subtitles.show_menu(player)
163 local formspec = subtitles.get_menu_formspec(player);
164 if type(player) ~= 'string' then
165 player = player:get_player_name();
166 end;
167 minetest.show_formspec(player, 'subtitles:menu', formspec);
168 end;
169
170
171 --- Handles receiving fields from the menu formspec.
172 -- @param player The username or ObjectRef of the player.
173 -- @param fields A table of fields.
174 -- @param embedded If this is true, the menu will not be re-shown.
175 function subtitles.menu_receive_fields(player, fields, embedded)
176 local function _reshow()
177 if not embedded then
178 subtitles.show_menu(player);
179 end;
180 end;
181
182 local agent = subtitles.get_agent(player);
183
184 if fields.toggle then
185 agent:toggle_enabled();
186 _reshow();
187 return;
188 end;
189
190 if fields.footsteps then
191 agent:toggle_footsteps_enabled();
192 _reshow();
193 return;
194 end;
195
196 for __, impl in ipairs(subtitles.SubtitleDisplay.implementations) do
197 if fields['display_' .. impl.NAME] then
198 agent:set_display_name(impl.NAME);
199 _reshow();
200 return;
201 end;
202 end;
203 end;
204
205
206 if not subtitles.settings.inventory_integration then
207 return;
208 end;
209
210
211 -- Unified Inventory integration:
212 if minetest.get_modpath('unified_inventory') then
213 unified_inventory.register_button('subtitles',
214 {
215 type = 'image';
216 image = 'subtitles_icon.png';
217 tooltip = S('Subtitles');
218 hide_lite = false;
219 action = subtitles.show_menu;
220 });
221 end;
222
223
224 -- i3 integration:
225 if minetest.get_modpath('i3') then
226 i3.new_tab('subtitles',
227 {
228 description = S('Subtitles');
229 image = 'subtitles_icon.png';
230 formspec =
231 function(player, data, fs)
232 fs(subtitles.get_menu_formspec(player, true, {width = 10.25, height = 12}));
233 end;
234 fields =
235 function(player, data, fields)
236 subtitles.menu_receive_fields(player, fields, true);
237 i3.set_fs(player);
238 end;
239 });
240 end;
241
242
243 -- SFInv integration via SFInv Buttons:
244 if minetest.get_modpath('sfinv_buttons') then
245 sfinv_buttons.register_button('subtitles',
246 {
247 image = 'subtitles_icon.png';
248 tooltip = S('Configure your subtitle preferences');
249 title = S('Subtitles');
250 action = subtitles.show_menu;
251 });
252 end;
253
254
255 -- Repixture integration:
256 if minetest.get_modpath('rp_formspec') then
257 rp_formspec.register_page('subtitles:subtitles', 'label[1,1;?]');
258 rp_formspec.register_invpage('subtitles:subtitles', {});
259 rp_formspec.register_invtab('subtitles:subtitles', {icon = 'subtitles_rp_icon.png', tooltip = S('Subtitles')});
260
261 local old_set_current_invpage = rp_formspec.set_current_invpage;
262 function rp_formspec.set_current_invpage(player, page)
263 if page == 'subtitles:subtitles' then
264 subtitles.show_menu(player);
265 else
266 old_set_current_invpage(player, page);
267 end;
268 end;
269 end;