1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-09 12:50:35 +00:00

Merge pull request #103841 from GustJc/embed_add_hotkeys

Add Embed Game Window shortcut hotkeys support for `suspend/pause` and `next frame` buttons
This commit is contained in:
Thaddeus Crews
2025-04-27 19:21:16 -05:00
6 changed files with 88 additions and 0 deletions

View File

@@ -915,6 +915,14 @@ void ScriptEditorDebugger::_msg_window_title(uint64_t p_thread_id, const Array &
emit_signal(SNAME("remote_window_title_changed"), p_data[0]);
}
void ScriptEditorDebugger::_msg_embed_suspend_toggle(uint64_t p_thread_id, const Array &p_data) {
emit_signal(SNAME("embed_shortcut_requested"), EMBED_SUSPEND_TOGGLE);
}
void ScriptEditorDebugger::_msg_embed_next_frame(uint64_t p_thread_id, const Array &p_data) {
emit_signal(SNAME("embed_shortcut_requested"), EMBED_NEXT_FRAME);
}
void ScriptEditorDebugger::_parse_message(const String &p_msg, uint64_t p_thread_id, const Array &p_data) {
emit_signal(SNAME("debug_data"), p_msg, p_data);
@@ -963,6 +971,8 @@ void ScriptEditorDebugger::_init_parse_message_handlers() {
parse_message_handlers["filesystem:update_file"] = &ScriptEditorDebugger::_msg_filesystem_update_file;
parse_message_handlers["evaluation_return"] = &ScriptEditorDebugger::_msg_evaluation_return;
parse_message_handlers["window:title"] = &ScriptEditorDebugger::_msg_window_title;
parse_message_handlers["request_embed_suspend_toggle"] = &ScriptEditorDebugger::_msg_embed_suspend_toggle;
parse_message_handlers["request_embed_next_frame"] = &ScriptEditorDebugger::_msg_embed_next_frame;
}
void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType p_type) {
@@ -1905,6 +1915,7 @@ void ScriptEditorDebugger::_bind_methods() {
ADD_SIGNAL(MethodInfo("set_breakpoint", PropertyInfo("script"), PropertyInfo(Variant::INT, "line"), PropertyInfo(Variant::BOOL, "enabled")));
ADD_SIGNAL(MethodInfo("clear_breakpoints"));
ADD_SIGNAL(MethodInfo("errors_cleared"));
ADD_SIGNAL(MethodInfo("embed_shortcut_requested", PropertyInfo(Variant::INT, "embed_shortcut_action")));
}
void ScriptEditorDebugger::add_debugger_tab(Control *p_control) {

View File

@@ -226,6 +226,8 @@ private:
void _msg_filesystem_update_file(uint64_t p_thread_id, const Array &p_data);
void _msg_evaluation_return(uint64_t p_thread_id, const Array &p_data);
void _msg_window_title(uint64_t p_thread_id, const Array &p_data);
void _msg_embed_suspend_toggle(uint64_t p_thread_id, const Array &p_data);
void _msg_embed_next_frame(uint64_t p_thread_id, const Array &p_data);
void _parse_message(const String &p_msg, uint64_t p_thread_id, const Array &p_data);
void _set_reason_text(const String &p_reason, MessageType p_type);
@@ -287,6 +289,11 @@ protected:
static void _bind_methods();
public:
enum EmbedShortcutAction {
EMBED_SUSPEND_TOGGLE,
EMBED_NEXT_FRAME,
};
void request_remote_objects(const TypedArray<uint64_t> &p_obj_ids, bool p_update_selection = true);
void update_remote_object(ObjectID p_obj_id, const String &p_prop, const Variant &p_value, const String &p_field = "");

View File

@@ -97,6 +97,12 @@ void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) {
mute_audio_data.append(mute_audio);
p_session->send_message("scene:debug_mute_audio", mute_audio_data);
Dictionary shortcut_settings;
shortcut_settings["editor/suspend_resume_embedded_project"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("editor/suspend_resume_embedded_project"));
shortcut_settings["editor/next_frame_embedded_project"] = DebuggerMarshalls::serialize_key_shortcut(ED_GET_SHORTCUT("editor/next_frame_embedded_project"));
p_session->send_message("scene:setup_embedded_shortcuts", { shortcut_settings });
emit_signal(SNAME("session_started"));
}
@@ -419,6 +425,23 @@ void GameView::_update_debugger_buttons() {
next_frame_button->set_disabled(!suspend_button->is_pressed());
}
void GameView::_handle_shortcut_requested(int p_embed_action) {
switch (p_embed_action) {
case ScriptEditorDebugger::EMBED_SUSPEND_TOGGLE: {
_toggle_suspend_button();
} break;
case ScriptEditorDebugger::EMBED_NEXT_FRAME: {
debugger->next_frame();
} break;
}
}
void GameView::_toggle_suspend_button() {
const bool new_pressed = !suspend_button->is_pressed();
suspend_button->set_pressed(new_pressed);
_suspend_button_toggled(new_pressed);
}
void GameView::_suspend_button_toggled(bool p_pressed) {
_update_debugger_buttons();
@@ -773,12 +796,14 @@ void GameView::_attach_script_debugger() {
if (embedded_script_debugger) {
embedded_script_debugger->connect("remote_window_title_changed", callable_mp(this, &GameView::_remote_window_title_changed));
embedded_script_debugger->connect("embed_shortcut_requested", callable_mp(this, &GameView::_handle_shortcut_requested));
}
}
void GameView::_detach_script_debugger() {
if (embedded_script_debugger) {
embedded_script_debugger->disconnect("remote_window_title_changed", callable_mp(this, &GameView::_remote_window_title_changed));
embedded_script_debugger->disconnect("embed_shortcut_requested", callable_mp(this, &GameView::_handle_shortcut_requested));
embedded_script_debugger = nullptr;
}
}
@@ -930,6 +955,9 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
suspend_button->connect(SceneStringName(toggled), callable_mp(this, &GameView::_suspend_button_toggled));
suspend_button->set_tooltip_text(TTR("Suspend"));
suspend_button->set_accessibility_name(TTRC("Suspend"));
ED_SHORTCUT("editor/suspend_resume_embedded_project", TTRC("Suspend/Resume Embedded Project"), Key::F9);
ED_SHORTCUT_OVERRIDE("editor/suspend_resume_embedded_project", "macos", KeyModifierMask::META | KeyModifierMask::SHIFT | Key::B);
suspend_button->set_shortcut(ED_GET_SHORTCUT("editor/suspend_resume_embedded_project"));
next_frame_button = memnew(Button);
main_menu_hbox->add_child(next_frame_button);
@@ -937,6 +965,7 @@ GameView::GameView(Ref<GameViewDebugger> p_debugger, WindowWrapper *p_wrapper) {
next_frame_button->connect(SceneStringName(pressed), callable_mp(*debugger, &GameViewDebugger::next_frame));
next_frame_button->set_tooltip_text(TTR("Next Frame"));
next_frame_button->set_accessibility_name(TTRC("Next Frame"));
next_frame_button->set_shortcut(ED_SHORTCUT("editor/next_frame_embedded_project", TTRC("Next Frame"), Key::F10));
main_menu_hbox->add_child(memnew(VSeparator));

View File

@@ -161,6 +161,8 @@ class GameView : public VBoxContainer {
void _update_debugger_buttons();
void _handle_shortcut_requested(int p_embed_action);
void _toggle_suspend_button();
void _suspend_button_toggled(bool p_pressed);
void _node_type_pressed(int p_option);

View File

@@ -114,6 +114,29 @@ void SceneDebugger::_handle_input(const Ref<InputEvent> &p_event, const Ref<Shor
}
}
void SceneDebugger::_handle_embed_input(const Ref<InputEvent> &p_event, const Dictionary &p_settings) {
Ref<InputEventKey> k = p_event;
if (k.is_null() || !k->is_pressed()) {
return;
}
Ref<Shortcut> p_shortcut = p_settings.get("editor/next_frame_embedded_project", Ref<Shortcut>());
if (p_shortcut.is_valid() && p_shortcut->matches_event(k)) {
EngineDebugger::get_singleton()->send_message("request_embed_next_frame", Array());
return;
}
if (k->is_echo()) {
return;
} // Shortcuts that doesn't need is_echo goes below here
p_shortcut = p_settings.get("editor/suspend_resume_embedded_project", Ref<Shortcut>());
if (p_shortcut.is_valid() && p_shortcut->matches_event(k)) {
EngineDebugger::get_singleton()->send_message("request_embed_suspend_toggle", Array());
return;
}
}
Error SceneDebugger::_msg_setup_scene(const Array &p_args, SceneTree *p_scene_tree, LiveEditor *p_live_editor, RuntimeNodeSelect *p_runtime_node_select) {
p_scene_tree->get_root()->connect(SceneStringName(window_input), callable_mp_static(SceneDebugger::_handle_input).bind(DebuggerMarshalls::deserialize_key_shortcut(p_args)));
return OK;
@@ -228,6 +251,19 @@ Error SceneDebugger::_msg_reload_cached_files(const Array &p_args, SceneTree *p_
return OK;
}
Error SceneDebugger::_msg_setup_embedded_shortcuts(const Array &p_args, SceneTree *p_scene_tree, LiveEditor *p_live_editor, RuntimeNodeSelect *p_runtime_node_select) {
ERR_FAIL_COND_V(p_args.is_empty() || p_args[0].get_type() != Variant::DICTIONARY, ERR_INVALID_DATA);
Dictionary dict = p_args[0];
LocalVector<Variant> keys = dict.get_key_list();
for (const Variant &key : keys) {
dict[key] = DebuggerMarshalls::deserialize_key_shortcut(dict[key]);
}
SceneTree::get_singleton()->get_root()->connect(SceneStringName(window_input), callable_mp_static(SceneDebugger::_handle_embed_input).bind(dict));
return OK;
}
// region Live editing.
Error SceneDebugger::_msg_live_set_root(const Array &p_args, SceneTree *p_scene_tree, LiveEditor *p_live_editor, RuntimeNodeSelect *p_runtime_node_select) {
@@ -427,6 +463,7 @@ void SceneDebugger::_init_parse_message_handlers() {
#define HANDLER(name) parse_message_handlers[#name] = _msg_##name
HANDLER(setup_scene);
HANDLER(setup_embedded_shortcuts);
HANDLER(request_scene_tree);
HANDLER(save_node);
HANDLER(inspect_objects);

View File

@@ -65,6 +65,7 @@ public:
#ifdef DEBUG_ENABLED
private:
static void _handle_input(const Ref<InputEvent> &p_event, const Ref<Shortcut> &p_shortcut);
static void _handle_embed_input(const Ref<InputEvent> &p_event, const Dictionary &p_settings);
static void _save_node(ObjectID id, const String &p_path);
static void _set_node_owner_recursive(Node *p_node, Node *p_owner);
@@ -80,6 +81,7 @@ private:
#define HANDLER(name) static Error _msg_##name(const Array &p_args, SceneTree *p_scene_tree, LiveEditor *p_live_editor, RuntimeNodeSelect *p_runtime_node_select)
HANDLER(setup_scene);
HANDLER(setup_embedded_shortcuts);
HANDLER(request_scene_tree);
HANDLER(save_node);
HANDLER(inspect_objects);