diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 75c92055d63..bad407aa0a6 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -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) { diff --git a/editor/debugger/script_editor_debugger.h b/editor/debugger/script_editor_debugger.h index ac8e3fc7cd8..a2a9f2721e6 100644 --- a/editor/debugger/script_editor_debugger.h +++ b/editor/debugger/script_editor_debugger.h @@ -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 &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 = ""); diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index fdff2ccaa65..978f44d1c81 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -97,6 +97,12 @@ void GameViewDebugger::_session_started(Ref 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 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 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)); diff --git a/editor/plugins/game_view_plugin.h b/editor/plugins/game_view_plugin.h index 23f4176c845..fc77a9f48c1 100644 --- a/editor/plugins/game_view_plugin.h +++ b/editor/plugins/game_view_plugin.h @@ -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); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index 6894158644b..0ceacd11555 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -114,6 +114,29 @@ void SceneDebugger::_handle_input(const Ref &p_event, const Ref &p_event, const Dictionary &p_settings) { + Ref k = p_event; + if (k.is_null() || !k->is_pressed()) { + return; + } + + Ref p_shortcut = p_settings.get("editor/next_frame_embedded_project", Ref()); + 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()); + 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 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); diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 97a4d78b976..fe923ed4779 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -65,6 +65,7 @@ public: #ifdef DEBUG_ENABLED private: static void _handle_input(const Ref &p_event, const Ref &p_shortcut); + static void _handle_embed_input(const Ref &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);