Repository: godotengine/godot (language: cpp)

Issue:
"Game View" window mode can not be editor feature disabled with single-window mode
### Tested versions

Godot 4.4 master
24d74510e5831960f79837e5297853cb3286594e

### System information

Windows 10

### Issue description

The new "Game View" window mode from PR https://github.com/godotengine/godot/pull/97257 has issues so I have a desire to disable it (permanently).

This should be possible with the "Manage Editor Features" profiles but the result of disabling the "Game View" in that menu is that the entire editor runtime window does no longer work.

It either stops to show up the runtime game window at all or it renders at a tiny window size in the top-left corner of the editor viewport as an unchangeable, borderless window.

![Image](https://github.com/user-attachments/assets/d421262f-88ea-4d7a-80b2-d00fe6af7d0d)

Doing multiple editor restarts does not change anything about that issue.
Note that this likely has to do with the single-window mode of the editor.

### Steps to reproduce

- Disable the "Game View" feature in the editor "Manage Editor Features" menu.
- Enable single-window mode for the Editor.
- Start game from the editor.
- Experience the broken window handling.

### Minimal reproduction project (MRP)

N/A
See steps.


Discussion / hints:
I'll take a look, it's definitively something linked to the embedding process. I never worked with the profiles and editor features before. I thougth the plugins were not loaded when the feature is not enabled but it's not how it's done.

Fix patch:
diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp
index d611f0a773cf..212957dd2d9f 100644
--- a/editor/plugins/game_view_plugin.cpp
+++ b/editor/plugins/game_view_plugin.cpp
@@ -34,6 +34,7 @@
 #include "core/debugger/debugger_marshalls.h"
 #include "editor/debugger/editor_debugger_node.h"
 #include "editor/editor_command_palette.h"
+#include "editor/editor_feature_profile.h"
 #include "editor/editor_interface.h"
 #include "editor/editor_main_screen.h"
 #include "editor/editor_node.h"
@@ -49,6 +50,10 @@
 #include "scene/gui/separator.h"
 
 void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) {
+	if (!is_feature_enabled) {
+		return;
+	}
+
 	Array setup_data;
 	Dictionary settings;
 	settings["editors/panning/2d_editor_panning_scheme"] = EDITOR_GET("editors/panning/2d_editor_panning_scheme");
@@ -73,9 +78,17 @@ void GameViewDebugger::_session_started(Ref<EditorDebuggerSession> p_session) {
 }
 
 void GameViewDebugger::_session_stopped() {
+	if (!is_feature_enabled) {
+		return;
+	}
+
 	emit_signal(SNAME("session_stopped"));
 }
 
+void GameViewDebugger::set_is_feature_enabled(bool p_enabled) {
+	is_feature_enabled = p_enabled;
+}
+
 void GameViewDebugger::set_suspend(bool p_enabled) {
 	Array message;
 	message.append(p_enabled);
@@ -198,6 +211,9 @@ void GameView::_instance_starting_static(int p_idx, List<String> &r_arguments) {
 }
 
 void GameView::_instance_starting(int p_idx, List<String> &r_arguments) {
+	if (!is_feature_enabled) {
+		return;
+	}
 	if (p_idx == 0 && embed_on_play && make_floating_on_play && !window_wrapper->get_window_enabled() && EditorNode::get_singleton()->is_multi_window_enabled()) {
 		window_wrapper->restore_window_from_saved_position(floating_window_rect, floating_window_screen, floating_window_screen_rect);
 	}
@@ -206,6 +222,10 @@ void GameView::_instance_starting(int p_idx, List<String> &r_arguments) {
 }
 
 void GameView::_play_pressed() {
+	if (!is_feature_enabled) {
+		return;
+	}
+
 	OS::ProcessID current_process_id = EditorRunBar::get_singleton()->get_current_process();
 	if (current_process_id == 0) {
 		return;
@@ -231,6 +251,10 @@ void GameView::_play_pressed() {
 }
 
 void GameView::_stop_pressed() {
+	if (!is_feature_enabled) {
+		return;
+	}
+
 	EditorNode::get_singleton()->set_unfocused_low_processor_usage_mode_enabled(true);
 	embedded_process->reset();
 	_update_ui();
@@ -476,6 +500,10 @@ void GameView::_notification(int p_what) {
 	}
 }
 
+void GameView::set_is_feature_enabled(bool p_enabled) {
+	is_feature_enabled = p_enabled;
+}
+
 void GameView::set_state(const Dictionary &p_state) {
 	if (p_state.has("hide_selection")) {
 		hide_selection->set_pressed(p_state["hide_selection"]);
@@ -801,6 +829,22 @@ void GameViewPlugin::_notification(int p_what) {
 	}
 }
 
+void GameViewPlugin::_feature_profile_changed() {
+	bool is_feature_enabled = true;
+	Ref<EditorFeatureProfile> profile = EditorFeatureProfileManager::get_singleton()->get_current_profile();
+	if (profile.is_valid()) {
+		is_feature_enabled = !profile->is_feature_disabled(EditorFeatureProfile::FEATURE_GAME);
+	}
+
+	if (debugger.is_valid()) {
+		debugger->set_is_feature_enabled(is_feature_enabled);
+	}
+
+	if (game_view) {
+		game_view->set_is_feature_enabled(is_feature_enabled);
+	}
+}
+
 void GameViewPlugin::_window_visibility_changed(bool p_visible) {
 	_focus_another_editor();
 }
@@ -834,6 +878,8 @@ GameViewPlugin::GameViewPlugin() {
 	window_wrapper->set_v_size_flags(Control::SIZE_EXPAND_FILL);
 	window_wrapper->hide();
 	window_wrapper->connect("window_visibility_changed", callable_mp(this, &GameViewPlugin::_window_visibility_changed));
+
+	EditorFeatureProfileManager::get_singleton()->connect("current_feature_profile_changed", callable_mp(this, &GameViewPlugin::_feature_profile_changed));
 }
 
 GameViewPlugin::~GameViewPlugin() {
diff --git a/editor/plugins/game_view_plugin.h b/editor/plugins/game_view_plugin.h
index 64d679657c33..50d4170e92d3 100644
--- a/editor/plugins/game_view_plugin.h
+++ b/editor/plugins/game_view_plugin.h
@@ -47,6 +47,7 @@ class GameViewDebugger : public EditorDebuggerPlugin {
 private:
 	Vector<Ref<EditorDebuggerSession>> sessions;
 
+	bool is_feature_enabled = true;
 	int node_type = RuntimeNodeSelect::NODE_TYPE_NONE;
 	bool selection_visible = true;
 	int select_mode = RuntimeNodeSelect::SELECT_MODE_SINGLE;
@@ -59,6 +60,8 @@ class GameViewDebugger : public EditorDebuggerPlugin {
 	static void _bind_methods();
 
 public:
+	void set_is_feature_enabled(bool p_enabled);
+
 	void set_suspend(bool p_enabled);
 	void next_frame();
 
@@ -95,6 +98,7 @@ class GameView : public VBoxContainer {
 	Ref<GameViewDebugger> debugger;
 	WindowWrapper *window_wrapper = nullptr;
 
+	bool is_feature_enabled = true;
 	int active_sessions = 0;
 	int screen_index_before_start = -1;
 
@@ -163,6 +167,8 @@ class GameView : public VBoxContainer {
 	void _notification(int p_what);
 
 public:
+	void set_is_feature_enabled(bool p_enabled);
+
 	void set_state(const Dictionary &p_state);
 	Dictionary get_state() const;
 
@@ -182,6 +188,7 @@ class GameViewPlugin : public EditorPlugin {
 
 	String last_editor;
 
+	void _feature_profile_changed();
 	void _window_visibility_changed(bool p_visible);
 	void _save_last_editor(const String &p_editor);
 	void _focus_another_editor();


Test patch: