1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Add allow_close[] element to formspecs (#15971)

This commit is contained in:
Vincent Robinson 2025-04-16 16:20:39 -07:00 committed by GitHub
parent 04e82749db
commit fd85737460
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 71 additions and 44 deletions

View file

@ -57,6 +57,7 @@ Some can be changed in the key config dialog in the settings tab.
| T | Chat | | T | Chat |
| / | Command | | / | Command |
| Esc | Pause menu/abort/exit (pauses only singleplayer game) | | Esc | Pause menu/abort/exit (pauses only singleplayer game) |
| Ctrl + Esc | Exit directly to main menu from anywhere, bypassing pause menu |
| + | Increase view range | | + | Increase view range |
| - | Decrease view range | | - | Decrease view range |
| K | Enable/disable fly mode (needs fly privilege) | | K | Enable/disable fly mode (needs fly privilege) |

View file

@ -2903,6 +2903,13 @@ Elements
* For information on converting forms to the new coordinate system, see `Migrating * For information on converting forms to the new coordinate system, see `Migrating
to Real Coordinates`. to Real Coordinates`.
### `allow_close[<bool>]`
* When set to false, the formspec will not close when the user tries to close
it with the Escape key or similar. Default true.
* The formspec can still be closed with `*_exit[]` elements and
`core.close_formspec()`, regardless of this setting.
### `container[<X>,<Y>]` ### `container[<X>,<Y>]`
* Start of a container block, moves all physical elements in the container by * Start of a container block, moves all physical elements in the container by
@ -6206,8 +6213,10 @@ Call these functions only at load time!
* `table`: See `core.explode_table_event` * `table`: See `core.explode_table_event`
* `scrollbar`: See `core.explode_scrollbar_event` * `scrollbar`: See `core.explode_scrollbar_event`
* Special case: `["quit"]="true"` is sent when the user actively * Special case: `["quit"]="true"` is sent when the user actively
closed the form by mouse click, keypress or through a button_exit[] closed the form by mouse click, keypress or through a `button_exit[]`
element. element.
* Special case: `["try_quit"]="true"` is sent when the user tries to
close the formspec, but the formspec used `allow_close[false]`.
* Special case: `["key_enter"]="true"` is sent when the user pressed * Special case: `["key_enter"]="true"` is sent when the user pressed
the Enter key and the focus was either nowhere (causing the formspec the Enter key and the focus was either nowhere (causing the formspec
to be closed) or on a button. If the focus was on a text field, to be closed) or on a button. If the focus was on a text field,

View file

@ -339,10 +339,11 @@ local pages = {
[[ [[
formspec_version[3] formspec_version[3]
size[12,13] size[12,13]
allow_close[false]
image_button[0,0;1,1;logo.png;rc_image_button_1x1;1x1] image_button[0,0;1,1;logo.png;rc_image_button_1x1;1x1]
image_button[1,0;2,2;logo.png;rc_image_button_2x2;2x2] image_button_exit[1,0;2,2;logo.png;rc_image_button_2x2;2x2 exit]
button[0,2;1,1;rc_button_1x1;1x1] button[0,2;1,1;rc_button_1x1;1x1]
button[1,2;2,2;rc_button_2x2;2x2] button_exit[1,2;2,2;rc_button_2x2;2x2 exit]
item_image[0,4;1,1;air] item_image[0,4;1,1;air]
item_image[1,4;2,2;air] item_image[1,4;2,2;air]
item_image_button[0,6;1,1;testformspec:node;rc_item_image_button_1x1;1x1] item_image_button[0,6;1,1;testformspec:node;rc_item_image_button_1x1;1x1]
@ -575,6 +576,10 @@ core.register_on_player_receive_fields(function(player, formname, fields)
if fields.submit_window then if fields.submit_window then
show_test_formspec(player:get_player_name()) show_test_formspec(player:get_player_name())
end end
if fields.try_quit then
core.chat_send_player(player:get_player_name(), "Quit attempt received")
end
end) end)
core.register_chatcommand("test_formspec", { core.register_chatcommand("test_formspec", {

View file

@ -1050,10 +1050,6 @@ void Game::shutdown()
if (g_touchcontrols) if (g_touchcontrols)
g_touchcontrols->hide(); g_touchcontrols->hide();
// only if the shutdown progress bar isn't shown yet
if (m_shutdown_progress == 0.0f)
showOverlayMessage(N_("Shutting down..."), 0, 0);
clouds.reset(); clouds.reset();
gui_chat_console.reset(); gui_chat_console.reset();
@ -1065,6 +1061,10 @@ void Game::shutdown()
g_menumgr.deleteFront(); g_menumgr.deleteFront();
} }
// only if the shutdown progress bar isn't shown yet
if (m_shutdown_progress == 0.0f)
showOverlayMessage(N_("Shutting down..."), 0, 0);
chat_backend->addMessage(L"", L"# Disconnected."); chat_backend->addMessage(L"", L"# Disconnected.");
chat_backend->addMessage(L"", L""); chat_backend->addMessage(L"", L"");

View file

@ -205,6 +205,9 @@ void GameFormSpec::init(Client *client, RenderingEngine *rendering_engine, Input
m_input = input; m_input = input;
m_pause_script = std::make_unique<PauseMenuScripting>(client); m_pause_script = std::make_unique<PauseMenuScripting>(client);
m_pause_script->loadBuiltin(); m_pause_script->loadBuiltin();
// Make sure any remaining game callback requests are cleared out.
*g_gamecallback = MainGameCallback();
} }
void GameFormSpec::deleteFormspec() void GameFormSpec::deleteFormspec()

View file

@ -148,6 +148,10 @@ bool MyEventReceiver::OnEvent(const SEvent &event)
} }
fullscreen_is_down = event.KeyInput.PressedDown; fullscreen_is_down = event.KeyInput.PressedDown;
return true; return true;
} else if (keyCode == EscapeKey &&
event.KeyInput.PressedDown && event.KeyInput.Control) {
g_gamecallback->disconnect();
return true;
} }
} }

View file

@ -168,7 +168,7 @@ GUIEngine::GUIEngine(JoystickController *joystick,
"", "",
false); false);
m_menu->allowClose(false); m_menu->defaultAllowClose(false);
m_menu->lockSize(true,v2u32(800,600)); m_menu->lockSize(true,v2u32(800,600));
// Initialize scripting // Initialize scripting

View file

@ -105,7 +105,6 @@ GUIFormSpecMenu::GUIFormSpecMenu(JoystickController *joystick,
current_keys_pending.key_down = false; current_keys_pending.key_down = false;
current_keys_pending.key_up = false; current_keys_pending.key_up = false;
current_keys_pending.key_enter = false; current_keys_pending.key_enter = false;
current_keys_pending.key_escape = false;
m_tooltip_show_delay = (u32)g_settings->getS32("tooltip_show_delay"); m_tooltip_show_delay = (u32)g_settings->getS32("tooltip_show_delay");
m_tooltip_append_itemname = g_settings->getBool("tooltip_append_itemname"); m_tooltip_append_itemname = g_settings->getBool("tooltip_append_itemname");
@ -2833,6 +2832,11 @@ void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
m_fields.push_back(spec); m_fields.push_back(spec);
} }
void GUIFormSpecMenu::parseAllowClose(parserData *data, const std::string &element)
{
m_allowclose = is_yes(element);
}
void GUIFormSpecMenu::removeAll() void GUIFormSpecMenu::removeAll()
{ {
// Remove children // Remove children
@ -2901,6 +2905,7 @@ const std::unordered_map<std::string, std::function<void(GUIFormSpecMenu*, GUIFo
{"scroll_container_end", &GUIFormSpecMenu::parseScrollContainerEnd}, {"scroll_container_end", &GUIFormSpecMenu::parseScrollContainerEnd},
{"set_focus", &GUIFormSpecMenu::parseSetFocus}, {"set_focus", &GUIFormSpecMenu::parseSetFocus},
{"model", &GUIFormSpecMenu::parseModel}, {"model", &GUIFormSpecMenu::parseModel},
{"allow_close", &GUIFormSpecMenu::parseAllowClose},
}; };
@ -3003,6 +3008,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
field_close_on_enter.clear(); field_close_on_enter.clear();
m_dropdown_index_event.clear(); m_dropdown_index_event.clear();
m_allowclose = m_default_allowclose;
m_bgnonfullscreen = true; m_bgnonfullscreen = true;
m_bgfullscreen = false; m_bgfullscreen = false;
@ -3788,12 +3794,12 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode)
if (quitmode == quit_mode_accept) { if (quitmode == quit_mode_accept) {
fields["quit"] = "true"; fields["quit"] = "true";
} } else if (quitmode == quit_mode_cancel) {
if (quitmode == quit_mode_cancel) {
fields["quit"] = "true"; fields["quit"] = "true";
m_text_dst->gotText(fields); m_text_dst->gotText(fields);
return; return;
} else if (quitmode == quit_mode_try) {
fields["try_quit"] = "true";
} }
if (current_keys_pending.key_down) { if (current_keys_pending.key_down) {
@ -3816,11 +3822,6 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode)
current_field_enter_pending.clear(); current_field_enter_pending.clear();
} }
if (current_keys_pending.key_escape) {
fields["key_escape"] = "true";
current_keys_pending.key_escape = false;
}
for (const GUIFormSpecMenu::FieldSpec &s : m_fields) { for (const GUIFormSpecMenu::FieldSpec &s : m_fields) {
if (s.send) { if (s.send) {
std::string name = s.fname; std::string name = s.fname;
@ -3997,6 +3998,8 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
if (m_allowclose) { if (m_allowclose) {
acceptInput(quit_mode_accept); acceptInput(quit_mode_accept);
quitMenu(); quitMenu();
} else {
acceptInput(quit_mode_try);
} }
} }
} }
@ -4013,6 +4016,7 @@ void GUIFormSpecMenu::tryClose()
acceptInput(quit_mode_cancel); acceptInput(quit_mode_cancel);
quitMenu(); quitMenu();
} else { } else {
acceptInput(quit_mode_try);
m_text_dst->gotText(L"MenuQuit"); m_text_dst->gotText(L"MenuQuit");
} }
} }
@ -4059,9 +4063,13 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
FATAL_ERROR("Reached a source line that can't ever been reached"); FATAL_ERROR("Reached a source line that can't ever been reached");
break; break;
} }
if (current_keys_pending.key_enter && m_allowclose) { if (current_keys_pending.key_enter) {
if (m_allowclose) {
acceptInput(quit_mode_accept); acceptInput(quit_mode_accept);
quitMenu(); quitMenu();
} else {
acceptInput(quit_mode_try);
}
} else { } else {
acceptInput(); acceptInput();
} }
@ -4806,14 +4814,9 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
s32 caller_id = event.GUIEvent.Caller->getID(); s32 caller_id = event.GUIEvent.Caller->getID();
if (caller_id == 257) { if (caller_id == 257) {
if (m_allowclose) {
acceptInput(quit_mode_accept); acceptInput(quit_mode_accept);
quitMenu();
} else {
acceptInput();
m_text_dst->gotText(L"ExitButton"); m_text_dst->gotText(L"ExitButton");
} quitMenu();
// quitMenu deallocates menu
return true; return true;
} }
@ -4842,12 +4845,9 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
} }
if (s.is_exit) { if (s.is_exit) {
if (m_allowclose) {
acceptInput(quit_mode_accept); acceptInput(quit_mode_accept);
quitMenu();
} else {
m_text_dst->gotText(L"ExitButton"); m_text_dst->gotText(L"ExitButton");
} quitMenu();
return true; return true;
} }
@ -4910,15 +4910,18 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
} }
} }
if (m_allowclose && close_on_enter) {
current_keys_pending.key_enter = true; current_keys_pending.key_enter = true;
if (close_on_enter) {
if (m_allowclose) {
acceptInput(quit_mode_accept); acceptInput(quit_mode_accept);
quitMenu(); quitMenu();
} else { } else {
current_keys_pending.key_enter = true; acceptInput(quit_mode_try);
}
} else {
acceptInput(); acceptInput();
} }
// quitMenu deallocates menu
return true; return true;
} }
} }

View file

@ -47,7 +47,8 @@ enum FormspecFieldType {
enum FormspecQuitMode { enum FormspecQuitMode {
quit_mode_no, quit_mode_no,
quit_mode_accept, quit_mode_accept,
quit_mode_cancel quit_mode_cancel,
quit_mode_try,
}; };
enum ButtonEventType : u8 enum ButtonEventType : u8
@ -203,9 +204,9 @@ public:
m_text_dst = text_dst; m_text_dst = text_dst;
} }
void allowClose(bool value) void defaultAllowClose(bool value)
{ {
m_allowclose = value; m_default_allowclose = value;
} }
void setDebugView(bool value) void setDebugView(bool value)
@ -363,6 +364,7 @@ protected:
u64 m_hovered_time = 0; u64 m_hovered_time = 0;
s32 m_old_tooltip_id = -1; s32 m_old_tooltip_id = -1;
bool m_default_allowclose = true;
bool m_allowclose = true; bool m_allowclose = true;
bool m_lock = false; bool m_lock = false;
v2u32 m_lockscreensize; v2u32 m_lockscreensize;
@ -422,7 +424,6 @@ private:
bool key_up; bool key_up;
bool key_down; bool key_down;
bool key_enter; bool key_enter;
bool key_escape;
}; };
fs_key_pending current_keys_pending; fs_key_pending current_keys_pending;
@ -484,6 +485,7 @@ private:
void parseStyle(parserData *data, const std::string &element); void parseStyle(parserData *data, const std::string &element);
void parseSetFocus(parserData *, const std::string &element); void parseSetFocus(parserData *, const std::string &element);
void parseModel(parserData *data, const std::string &element); void parseModel(parserData *data, const std::string &element);
void parseAllowClose(parserData *data, const std::string &element);
bool parseMiddleRect(const std::string &value, core::rect<s32> *parsed_rect); bool parseMiddleRect(const std::string &value, core::rect<s32> *parsed_rect);