浏览代码

Add Embed Game Window hotkeys support and pause/next frame shortcuts

Gustavo Jaruga Cruz 4 月之前
父节点
当前提交
bf18021462

+ 11 - 0
editor/debugger/script_editor_debugger.cpp

@@ -905,6 +905,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);
 
@@ -953,6 +961,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) {
@@ -1894,6 +1904,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) {

+ 7 - 0
editor/debugger/script_editor_debugger.h

@@ -225,6 +225,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);
@@ -286,6 +288,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 = "");
 

+ 29 - 0
editor/plugins/game_view_plugin.cpp

@@ -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));
 

+ 2 - 0
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);

+ 37 - 0
scene/debugger/scene_debugger.cpp

@@ -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);

+ 2 - 0
scene/debugger/scene_debugger.h

@@ -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);