From 2a059cd513a9b577ec552516bc830899ec1e6f71 Mon Sep 17 00:00:00 2001 From: Allen Pestaluky Date: Thu, 26 Mar 2026 10:33:40 -0400 Subject: [PATCH] Change embedded window options to use three stacked dots and add HDR window information. Co-authored-by: Josh Jones --- editor/run/embedded_process.cpp | 2 - editor/run/game_view_plugin.cpp | 259 ++++++++++++++++++++++++------ editor/run/game_view_plugin.h | 33 +++- scene/debugger/scene_debugger.cpp | 58 +++++++ scene/debugger/scene_debugger.h | 6 + 5 files changed, 305 insertions(+), 53 deletions(-) diff --git a/editor/run/embedded_process.cpp b/editor/run/embedded_process.cpp index c702e2fed0..d621ee055c 100644 --- a/editor/run/embedded_process.cpp +++ b/editor/run/embedded_process.cpp @@ -82,7 +82,6 @@ void EmbeddedProcessBase::_project_settings_changed() { void EmbeddedProcessBase::_bind_methods() { ADD_SIGNAL(MethodInfo("embedding_completed")); ADD_SIGNAL(MethodInfo("embedding_failed")); - ADD_SIGNAL(MethodInfo("embedded_process_updated")); ADD_SIGNAL(MethodInfo("embedded_process_focused")); } @@ -304,7 +303,6 @@ void EmbeddedProcess::_update_embedded_process() { } DisplayServer::get_singleton()->embed_process(window->get_window_id(), current_process_id, get_screen_embedded_window_rect(), is_visible_in_tree(), must_grab_focus); - emit_signal(SNAME("embedded_process_updated")); } void EmbeddedProcess::_timer_embedding_timeout() { diff --git a/editor/run/game_view_plugin.cpp b/editor/run/game_view_plugin.cpp index bf4b33e514..dba74514b5 100644 --- a/editor/run/game_view_plugin.cpp +++ b/editor/run/game_view_plugin.cpp @@ -151,6 +151,8 @@ void GameViewDebugger::_session_started(Ref p_session) { p_session->send_message("scene:setup_embedded_shortcuts", { shortcut_settings }); + p_session->send_message("scene:setup_game_view", Array()); + emit_signal(SNAME("session_started")); } @@ -162,6 +164,22 @@ void GameViewDebugger::_session_stopped() { emit_signal(SNAME("session_stopped")); } +void GameViewDebugger::window_request_size() { + for (Ref &I : sessions) { + if (I->is_active()) { + I->send_message("scene:window_request_size", Array()); + } + } +} + +void GameViewDebugger::hdr_output_request_state() { + for (Ref &I : sessions) { + if (I->is_active()) { + I->send_message("scene:hdr_output_request_state", Array()); + } + } +} + void GameViewDebugger::set_suspend(bool p_enabled) { Array message; message.append(p_enabled); @@ -273,6 +291,15 @@ void GameViewDebugger::set_debug_mute_audio(bool p_enabled) { EditorDebuggerNode::get_singleton()->set_debug_mute_audio(p_enabled); } +void GameViewDebugger::toggle_hdr_output_requested() { + for (Ref &I : sessions) { + if (I->is_active()) { + I->send_message("scene:hdr_output_toggle_requested"); + I->send_message("scene:hdr_output_request_state", Array()); + } + } +} + void GameViewDebugger::set_camera_override(bool p_enabled) { EditorDebuggerNode::get_singleton()->set_camera_override(p_enabled ? camera_override_mode : EditorDebuggerNode::OVERRIDE_NONE); } @@ -330,6 +357,9 @@ void GameViewDebugger::_feature_profile_changed() { void GameViewDebugger::_bind_methods() { ADD_SIGNAL(MethodInfo("session_started")); ADD_SIGNAL(MethodInfo("session_stopped")); + ADD_SIGNAL(MethodInfo("setup_complete")); + ADD_SIGNAL(MethodInfo("game_window_size_received", PropertyInfo(Variant::VECTOR2I, "size"))); + ADD_SIGNAL(MethodInfo("hdr_state_received", PropertyInfo(Variant::ARRAY, "hdr_state"))); } bool GameViewDebugger::add_screenshot_callback(const Callable &p_callaback, const Rect2i &p_rect) { @@ -374,6 +404,15 @@ bool GameViewDebugger::capture(const String &p_message, const Array &p_data, int if (p_message == "game_view:get_screenshot") { return _msg_get_screenshot(p_data); + } else if (p_message == "game_view:setup_complete") { + emit_signal(SNAME("setup_complete")); + return true; + } else if (p_message == "game_view:window_size") { + emit_signal(SNAME("game_window_size_received"), p_data); + return true; + } else if (p_message == "game_view:hdr_state") { + emit_signal(SNAME("hdr_state_received"), p_data); + return true; } else { // Any other messages with this prefix should be ignored. WARN_PRINT("GameViewDebugger unknown message: " + p_message); @@ -578,11 +617,6 @@ void GameView::_embedding_failed() { state_label->set_text(TTRC("Connection impossible to the game process.")); } -void GameView::_embedded_process_updated() { - const Rect2i game_rect = embedded_process->get_screen_embedded_window_rect(); - game_size_label->set_text(vformat("%dx%d", game_rect.size.x, game_rect.size.y)); -} - void GameView::_embedded_process_focused() { if (embed_on_play && !window_wrapper->get_window_enabled()) { EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_GAME); @@ -613,6 +647,8 @@ void GameView::_update_debugger_buttons() { suspend_button->set_disabled(empty); camera_override_button->set_disabled(empty); speed_state_button->set_disabled(empty); + game_size_label->set_visible(!empty); + game_size_placeholder->set_visible(empty); bool disabled = time_scale_index == DEFAULT_TIME_SCALE_INDEX; reset_speed_button->set_disabled(empty || disabled); @@ -627,9 +663,42 @@ void GameView::_update_debugger_buttons() { suspend_button->set_pressed(false); camera_override_button->set_pressed(false); _reset_time_scales(); + game_size_label->set_text(""); + game_size_label->set_tooltip_text(""); + game_window_size = Size2i(-1, -1); + hdr_output_enabled = false; + output_max_linear_value = 1.0f; } next_frame_button->set_disabled(!suspend_button->is_pressed()); + + menu = game_window_options_menu->get_popup(); + if (empty) { + int menu_item_index = menu->get_item_index(WINDOW_SEPARATOR_DYNAMIC_RANGE); + if (menu_item_index >= 0) { + menu->remove_item(menu_item_index); + } + menu_item_index = menu->get_item_index(WINDOW_REQUEST_HDR_OUTPUT); + if (menu_item_index >= 0) { + menu->remove_item(menu_item_index); + } + menu_item_index = menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR); + if (menu_item_index >= 0) { + menu->remove_item(menu_item_index); + } + } else { + int menu_item_index = menu->get_item_index(WINDOW_SEPARATOR_DYNAMIC_RANGE); + if (menu_item_index < 0) { + menu->add_separator(TTRC("Window Dynamic Range"), WINDOW_SEPARATOR_DYNAMIC_RANGE); + } + if (menu->get_item_index(WINDOW_REQUEST_HDR_OUTPUT) < 0) { + if (menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR) < 0) { + menu->add_item(TTRC("Loading..."), WINDOW_HDR_OUTPUT_ERROR); + menu->set_item_disabled(menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR), true); + menu->set_item_tooltip(menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR), ""); + } + } + } } void GameView::_handle_shortcut_requested(int p_embed_action) { @@ -700,30 +769,43 @@ void GameView::_selection_options_menu_id_pressed(int p_id) { menu->set_item_checked(menu->get_item_index(SELECTION_PREFER_GROUP), selection_prefer_group); } -void GameView::_embed_options_menu_menu_id_pressed(int p_id) { +void GameView::_game_window_options_menu_menu_id_pressed(int p_id) { switch (p_id) { - case EMBED_RUN_GAME_EMBEDDED: { + case WINDOW_RUN_GAME_EMBEDDED: { embed_on_play = !embed_on_play; int game_mode = EDITOR_GET("run/window_placement/game_embed_mode"); if (game_mode == 0) { // Save only if not overridden by editor. EditorSettings::get_singleton()->set_project_metadata("game_view", "embed_on_play", embed_on_play); } } break; - case EMBED_MAKE_FLOATING_ON_PLAY: { + case WINDOW_MAKE_FLOATING_ON_PLAY: { make_floating_on_play = !make_floating_on_play; int game_mode = EDITOR_GET("run/window_placement/game_embed_mode"); if (game_mode == 0) { // Save only if not overridden by editor. EditorSettings::get_singleton()->set_project_metadata("game_view", "make_floating_on_play", make_floating_on_play); } } break; - case SIZE_MODE_FIXED: - case SIZE_MODE_KEEP_ASPECT: - case SIZE_MODE_STRETCH: { - embed_size_mode = (EmbedSizeMode)p_id; - EditorSettings::get_singleton()->set_project_metadata("game_view", "embed_size_mode", p_id); + case WINDOW_SIZE_MODE_FIXED: + case WINDOW_SIZE_MODE_KEEP_ASPECT: + case WINDOW_SIZE_MODE_STRETCH: { + switch (p_id) { + case WINDOW_SIZE_MODE_FIXED: { + embed_size_mode = EmbedSizeMode::SIZE_MODE_FIXED; + } break; + case WINDOW_SIZE_MODE_KEEP_ASPECT: { + embed_size_mode = EmbedSizeMode::SIZE_MODE_KEEP_ASPECT; + } break; + case WINDOW_SIZE_MODE_STRETCH: { + embed_size_mode = EmbedSizeMode::SIZE_MODE_STRETCH; + } break; + } + EditorSettings::get_singleton()->set_project_metadata("game_view", "embed_size_mode", embed_size_mode); _update_embed_window_size(); } break; + case WINDOW_REQUEST_HDR_OUTPUT: { + debugger->toggle_hdr_output_requested(); + } break; } _update_embed_menu_options(); _update_ui(); @@ -816,14 +898,12 @@ GameView::EmbedAvailability GameView::_get_embed_available() { } void GameView::_update_ui() { - bool show_game_size = false; EmbedAvailability available = _get_embed_available(); switch (available) { case EMBED_AVAILABLE: if (embedded_process->is_embedding_completed()) { state_label->set_text(""); - show_game_size = true; } else if (embedded_process->is_embedding_in_progress()) { state_label->set_text(TTRC("Game starting...")); } else if (EditorRunBar::get_singleton()->is_playing()) { @@ -864,21 +944,34 @@ void GameView::_update_ui() { } else { state_label->add_theme_color_override(SceneStringName(font_color), state_label->get_theme_color(SNAME("warning_color"), EditorStringName(Editor))); } - - game_size_label->set_visible(show_game_size); } void GameView::_update_embed_menu_options() { bool is_multi_window = window_wrapper->is_window_available(); - PopupMenu *menu = embed_options_menu->get_popup(); - menu->set_item_checked(menu->get_item_index(EMBED_RUN_GAME_EMBEDDED), embed_on_play); - menu->set_item_checked(menu->get_item_index(EMBED_MAKE_FLOATING_ON_PLAY), make_floating_on_play && is_multi_window); + PopupMenu *menu = game_window_options_menu->get_popup(); + menu->set_item_checked(menu->get_item_index(WINDOW_RUN_GAME_EMBEDDED), embed_on_play); + menu->set_item_checked(menu->get_item_index(WINDOW_MAKE_FLOATING_ON_PLAY), make_floating_on_play && is_multi_window); - menu->set_item_checked(menu->get_item_index(SIZE_MODE_FIXED), embed_size_mode == SIZE_MODE_FIXED); - menu->set_item_checked(menu->get_item_index(SIZE_MODE_KEEP_ASPECT), embed_size_mode == SIZE_MODE_KEEP_ASPECT); - menu->set_item_checked(menu->get_item_index(SIZE_MODE_STRETCH), embed_size_mode == SIZE_MODE_STRETCH); + menu->set_item_checked(menu->get_item_index(WINDOW_SIZE_MODE_FIXED), embed_size_mode == SIZE_MODE_FIXED); + menu->set_item_checked(menu->get_item_index(WINDOW_SIZE_MODE_KEEP_ASPECT), embed_size_mode == SIZE_MODE_KEEP_ASPECT); + menu->set_item_checked(menu->get_item_index(WINDOW_SIZE_MODE_STRETCH), embed_size_mode == SIZE_MODE_STRETCH); - menu->set_item_disabled(menu->get_item_index(EMBED_MAKE_FLOATING_ON_PLAY), !embed_on_play || !is_multi_window); + menu->set_item_disabled(menu->get_item_index(WINDOW_MAKE_FLOATING_ON_PLAY), !embed_on_play || !is_multi_window); +} + +void GameView::_update_game_window_size_label() { + String window_size_string = game_window_size.x < 0 ? "" : vformat("%dx%d", game_window_size.x, game_window_size.y); + game_size_label->set_text(hdr_output_enabled ? vformat("%s %s (%.2f)", window_size_string, TTRC("HDR"), output_max_linear_value) + : window_size_string); + game_size_label->set_tooltip_text( + vformat(TTR("Window size: %s\nMode: %s\nMaximum linear value: %.2f%s"), + window_size_string, + hdr_output_enabled ? TTRC("HDR") : TTRC("SDR"), + output_max_linear_value, + hdr_output_enabled ? vformat(TTR("\nReference luminance: %.0f nits\nMaximum luminance: %.0f nits"), + current_reference_luminance, + current_max_luminance) + : "")); } void GameView::_update_embed_window_size() { @@ -919,6 +1012,72 @@ void GameView::_debug_mute_audio_button_pressed() { debugger->set_debug_mute_audio(debug_mute_audio); } +void GameView::_setup_complete() { + debugger->window_request_size(); + debugger->hdr_output_request_state(); +} + +void GameView::_game_window_size_received(const Array &p_state) { + ERR_FAIL_COND_MSG(p_state.size() != 1, "_game_window_size_received: invalid number of arguments"); + game_window_size = p_state[0]; + _update_game_window_size_label(); +} + +void GameView::_hdr_state_received(const Array &p_state) { + ERR_FAIL_COND_MSG(p_state.size() != 7, "_hdr_state_received: invalid number of arguments"); + + PopupMenu *menu = game_window_options_menu->get_popup(); + + // Matches SceneDebugger::_msg_hdr_output_request_state + bool requested = p_state[0]; + hdr_output_enabled = p_state[1]; + current_reference_luminance = p_state[2]; + current_max_luminance = p_state[3]; + output_max_linear_value = p_state[4]; + display_server_supports_hdr_output = p_state[5]; + renderer_supports_hdr_output = p_state[6]; + + int request_hdr_output_index = menu->get_item_index(WINDOW_REQUEST_HDR_OUTPUT); + if (display_server_supports_hdr_output && renderer_supports_hdr_output) { + if (menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR) >= 0) { + menu->remove_item(menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR)); + } + + if (request_hdr_output_index < 0) { + menu->add_check_item(TTRC("Request HDR Output"), WINDOW_REQUEST_HDR_OUTPUT); + } + menu->set_item_checked(menu->get_item_index(WINDOW_REQUEST_HDR_OUTPUT), requested); + + if (requested && !hdr_output_enabled) { + String error_text = TTRC("Window does not support HDR output."); + String error_tooltip_text = TTRC("Move the game window to a screen\nthat is operating in HDR mode."); + menu->add_item(error_text, WINDOW_HDR_OUTPUT_ERROR); + int error_item_index = menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR); + menu->set_item_disabled(error_item_index, true); + menu->set_item_tooltip(error_item_index, error_tooltip_text); + } + } else { + if (request_hdr_output_index >= 0) { + menu->remove_item(request_hdr_output_index); + } + int error_item_index = menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR); + String error_text = !display_server_supports_hdr_output ? TTRC("Display server does not support HDR output.") + : TTRC("Renderer does not support HDR output."); + String error_tooltip_text = !display_server_supports_hdr_output ? TTRC("Change the display/display_server/driver\nadvanced project setting to a driver\nthat supports HDR output.") + : TTRC("Change the rendering/renderer/rendering_method\nproject setting to a renderer that supports HDR output and\nthe rendering/rendering_device/driver advanced project\nsetting to a driver that supports HDR output."); + if (error_item_index < 0) { + menu->add_item(error_text, WINDOW_HDR_OUTPUT_ERROR); + error_item_index = menu->get_item_index(WINDOW_HDR_OUTPUT_ERROR); + menu->set_item_disabled(error_item_index, true); + } else { + menu->set_item_text(error_item_index, error_text); + } + menu->set_item_tooltip(error_item_index, error_tooltip_text); + } + + _update_game_window_size_label(); +} + void GameView::_camera_override_button_toggled(bool p_pressed) { _update_debugger_buttons(); @@ -984,13 +1143,14 @@ void GameView::_notification(int p_what) { hide_selection->set_button_icon(get_editor_theme_icon(hide_selection->is_pressed() ? SNAME("GuiVisibilityHidden") : SNAME("GuiVisibilityVisible"))); selection_options_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); - embed_options_menu->set_button_icon(get_editor_theme_icon(SNAME("KeepAspect"))); debug_mute_audio_button->set_button_icon(get_editor_theme_icon(debug_mute_audio ? SNAME("AudioMute") : SNAME("AudioStreamPlayer"))); camera_override_button->set_button_icon(get_editor_theme_icon(SNAME("Camera"))); camera_override_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + game_window_options_menu->set_button_icon(get_editor_theme_icon(SNAME("GuiTabMenuHl"))); + _update_speed_state_size(); _update_speed_state_color(); } break; @@ -1454,26 +1614,6 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe embedding_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL); main_menu_fc->add_child(embedding_hb); - embed_options_menu = memnew(MenuButton); - embedding_hb->add_child(embed_options_menu); - embed_options_menu->set_flat(false); - embed_options_menu->set_theme_type_variation("FlatMenuButton"); - embed_options_menu->set_h_size_flags(SIZE_SHRINK_END); - embed_options_menu->set_tooltip_text(TTRC("Embedding Options")); - - menu = embed_options_menu->get_popup(); - menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_embed_options_menu_menu_id_pressed)); - menu->add_check_item(TTRC("Embed Game on Next Play"), EMBED_RUN_GAME_EMBEDDED); - menu->add_check_item(TTRC("Make Game Workspace Floating on Next Play"), EMBED_MAKE_FLOATING_ON_PLAY); - menu->add_separator(TTRC("Embedded Window Sizing")); - - menu->add_radio_check_item(TTRC("Fixed Size"), SIZE_MODE_FIXED); - menu->set_item_tooltip(menu->get_item_index(SIZE_MODE_FIXED), TTRC("Embedded game size is based on project settings.\nThe 'Keep Aspect' mode is used when the Game Workspace is smaller than the desired size.")); - menu->add_radio_check_item(TTRC("Keep Aspect Ratio"), SIZE_MODE_KEEP_ASPECT); - menu->set_item_tooltip(menu->get_item_index(SIZE_MODE_KEEP_ASPECT), TTRC("Keep the aspect ratio of the embedded game.")); - menu->add_radio_check_item(TTRC("Stretch to Fit"), SIZE_MODE_STRETCH); - menu->set_item_tooltip(menu->get_item_index(SIZE_MODE_STRETCH), TTRC("Embedded game size stretches to fit the Game Workspace.")); - game_size_label = memnew(Label()); embedding_hb->add_child(game_size_label); game_size_label->hide(); @@ -1483,6 +1623,31 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe game_size_label->set_custom_minimum_size(Size2(80 * EDSCALE, 0)); game_size_label->set_h_size_flags(SIZE_EXPAND_FILL); game_size_label->set_horizontal_alignment(HorizontalAlignment::HORIZONTAL_ALIGNMENT_RIGHT); + game_size_label->set_mouse_filter(MouseFilter::MOUSE_FILTER_PASS); + + game_size_placeholder = memnew(Control()); + embedding_hb->add_child(game_size_placeholder); + game_size_placeholder->set_h_size_flags(game_size_label->get_h_size_flags()); + + game_window_options_menu = memnew(MenuButton); + embedding_hb->add_child(game_window_options_menu); + game_window_options_menu->set_flat(false); + game_window_options_menu->set_theme_type_variation("FlatMenuButton"); + game_window_options_menu->set_h_size_flags(SIZE_SHRINK_END); + game_window_options_menu->set_tooltip_text(TTRC("Game Window Options")); + + menu = game_window_options_menu->get_popup(); + menu->connect(SceneStringName(id_pressed), callable_mp(this, &GameView::_game_window_options_menu_menu_id_pressed)); + menu->add_check_item(TTRC("Embed Game on Next Play"), WINDOW_RUN_GAME_EMBEDDED); + menu->add_check_item(TTRC("Make Game Workspace Floating on Next Play"), WINDOW_MAKE_FLOATING_ON_PLAY); + + menu->add_separator(TTRC("Embedded Window Sizing")); + menu->add_radio_check_item(TTRC("Fixed Size"), WINDOW_SIZE_MODE_FIXED); + menu->set_item_tooltip(menu->get_item_index(WINDOW_SIZE_MODE_FIXED), TTRC("Embedded game size is based on project settings.\nThe 'Keep Aspect' mode is used when the Game Workspace is smaller than the desired size.")); + menu->add_radio_check_item(TTRC("Keep Aspect Ratio"), WINDOW_SIZE_MODE_KEEP_ASPECT); + menu->set_item_tooltip(menu->get_item_index(WINDOW_SIZE_MODE_KEEP_ASPECT), TTRC("Keep the aspect ratio of the embedded game.")); + menu->add_radio_check_item(TTRC("Stretch to Fit"), WINDOW_SIZE_MODE_STRETCH); + menu->set_item_tooltip(menu->get_item_index(WINDOW_SIZE_MODE_STRETCH), TTRC("Embedded game size stretches to fit the Game Workspace.")); panel = memnew(Panel); add_child(panel); @@ -1493,7 +1658,6 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe embedded_process->set_anchors_and_offsets_preset(PRESET_FULL_RECT); embedded_process->connect("embedding_failed", callable_mp(this, &GameView::_embedding_failed)); embedded_process->connect("embedding_completed", callable_mp(this, &GameView::_embedding_completed)); - embedded_process->connect("embedded_process_updated", callable_mp(this, &GameView::_embedded_process_updated)); embedded_process->connect("embedded_process_focused", callable_mp(this, &GameView::_embedded_process_focused)); embedded_process->set_custom_minimum_size(Size2i(100, 100)); @@ -1517,6 +1681,9 @@ GameView::GameView(Ref p_debugger, EmbeddedProcessBase *p_embe p_debugger->connect("session_started", callable_mp(this, &GameView::_sessions_changed)); p_debugger->connect("session_stopped", callable_mp(this, &GameView::_sessions_changed)); + p_debugger->connect("setup_complete", callable_mp(this, &GameView::_setup_complete)); + p_debugger->connect("game_window_size_received", callable_mp(this, &GameView::_game_window_size_received)); + p_debugger->connect("hdr_state_received", callable_mp(this, &GameView::_hdr_state_received)); p_wrapper->set_override_close_request(true); p_wrapper->connect("window_close_requested", callable_mp(this, &GameView::_window_close_request)); diff --git a/editor/run/game_view_plugin.h b/editor/run/game_view_plugin.h index a42a4bf91a..ddcc21dd9d 100644 --- a/editor/run/game_view_plugin.h +++ b/editor/run/game_view_plugin.h @@ -82,6 +82,9 @@ public: bool add_screenshot_callback(const Callable &p_callaback, const Rect2i &p_rect); + void window_request_size(); + void hdr_output_request_state(); + void set_suspend(bool p_enabled); void next_frame(); @@ -98,6 +101,8 @@ public: void set_debug_mute_audio(bool p_enabled); + void toggle_hdr_output_requested(); + void set_camera_override(bool p_enabled); void set_camera_manipulate_mode(EditorDebuggerNode::CameraOverride p_mode); @@ -119,10 +124,16 @@ class GameView : public VBoxContainer { CAMERA_RESET_3D, CAMERA_MODE_INGAME, CAMERA_MODE_EDITORS, - EMBED_RUN_GAME_EMBEDDED, - EMBED_MAKE_FLOATING_ON_PLAY, SELECTION_AVOID_LOCKED, SELECTION_PREFER_GROUP, + WINDOW_RUN_GAME_EMBEDDED, + WINDOW_MAKE_FLOATING_ON_PLAY, + WINDOW_SIZE_MODE_FIXED, + WINDOW_SIZE_MODE_KEEP_ASPECT, + WINDOW_SIZE_MODE_STRETCH, + WINDOW_SEPARATOR_DYNAMIC_RANGE, + WINDOW_REQUEST_HDR_OUTPUT, + WINDOW_HDR_OUTPUT_ERROR, }; enum EmbedSizeMode { @@ -181,8 +192,9 @@ class GameView : public VBoxContainer { MenuButton *camera_override_menu = nullptr; HBoxContainer *embedding_hb = nullptr; - MenuButton *embed_options_menu = nullptr; + MenuButton *game_window_options_menu = nullptr; Label *game_size_label = nullptr; + Control *game_size_placeholder = nullptr; Panel *panel = nullptr; EmbeddedProcessBase *embedded_process = nullptr; Label *state_label = nullptr; @@ -192,6 +204,14 @@ class GameView : public VBoxContainer { Array time_scale_label = { "1/16", "1/8", "1/4", "1/2", "3/4", "1.0", "1.25", "1.5", "1.75", "2.0", "4.0", "8.0", "16.0" }; int time_scale_index = DEFAULT_TIME_SCALE_INDEX; + Size2i game_window_size = Size2i(-1, -1); + bool hdr_output_enabled = false; + float current_max_luminance = 0.0f; + float current_reference_luminance = 0.0f; + float output_max_linear_value = 1.0f; + bool display_server_supports_hdr_output = false; + bool renderer_supports_hdr_output = false; + MenuButton *speed_state_button = nullptr; Button *reset_speed_button = nullptr; @@ -206,7 +226,7 @@ class GameView : public VBoxContainer { void _node_type_pressed(int p_option); void _select_mode_pressed(int p_option); void _selection_options_menu_id_pressed(int p_id); - void _embed_options_menu_menu_id_pressed(int p_id); + void _game_window_options_menu_menu_id_pressed(int p_id); void _reset_time_scales(); void _speed_state_menu_pressed(int p_id); @@ -222,13 +242,13 @@ class GameView : public VBoxContainer { void _stop_pressed(); void _embedding_completed(); void _embedding_failed(); - void _embedded_process_updated(); void _embedded_process_focused(); void _editor_or_project_settings_changed(); EmbedAvailability _get_embed_available(); void _update_ui(); void _update_embed_menu_options(); + void _update_game_window_size_label(); void _update_embed_window_size(); void _update_arguments_for_instance(int p_idx, List &r_arguments); void _show_update_window_wrapper(); @@ -236,6 +256,9 @@ class GameView : public VBoxContainer { void _hide_selection_toggled(bool p_pressed); void _debug_mute_audio_button_pressed(); + void _setup_complete(); + void _game_window_size_received(const Array &p_state); + void _hdr_state_received(const Array &p_state); void _camera_override_button_toggled(bool p_pressed); void _camera_override_menu_id_pressed(int p_id); diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp index d725282c73..9adf9b8943 100644 --- a/scene/debugger/scene_debugger.cpp +++ b/scene/debugger/scene_debugger.cpp @@ -52,6 +52,8 @@ #include "scene/main/window.h" // SceneTree:get_root() #include "scene/resources/packed_scene.h" #include "servers/audio/audio_server.h" +#include "servers/display/display_server.h" +#include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_server.h" #ifndef _3D_DISABLED @@ -137,11 +139,27 @@ void SceneDebugger::_handle_embed_input(const Ref &p_event, const Di } } +void SceneDebugger::_on_window_size_changed() { + _msg_window_request_size(Array()); +} + +void SceneDebugger::_on_output_max_linear_value_changed(float max_linear_value) { + _msg_hdr_output_request_state(Array()); +} + Error SceneDebugger::_msg_setup_scene(const Array &p_args) { SceneTree::get_singleton()->get_root()->connect(SceneStringName(window_input), callable_mp_static(SceneDebugger::_handle_input).bind(DebuggerMarshalls::deserialize_key_shortcut(p_args))); return OK; } +Error SceneDebugger::_msg_setup_game_view(const Array &p_args) { + Window *root = SceneTree::get_singleton()->get_root(); + root->connect("size_changed", callable_mp_static(SceneDebugger::_on_window_size_changed)); + root->connect("output_max_linear_value_changed", callable_mp_static(SceneDebugger::_on_output_max_linear_value_changed)); + EngineDebugger::get_singleton()->send_message("game_view:setup_complete", Array()); + return OK; +} + Error SceneDebugger::_msg_request_scene_tree(const Array &p_args) { LiveEditor::get_singleton()->_send_tree(); return OK; @@ -218,6 +236,42 @@ Error SceneDebugger::_msg_debug_mute_audio(const Array &p_args) { return OK; } +Error SceneDebugger::_msg_window_request_size(const Array &p_args) { + Array size; + size.append(SceneTree::get_singleton()->get_root()->get_size()); + EngineDebugger::get_singleton()->send_message("game_view:window_size", size); + return OK; +} + +Error SceneDebugger::_msg_hdr_output_request_state(const Array &p_args) { + DisplayServer *ds = DisplayServer::get_singleton(); + bool renderer_supports_hdr_output = false; +#if defined(RD_ENABLED) + RenderingDevice *rendering_device = RD::get_singleton(); + if (rendering_device && rendering_device->has_feature(RD::SUPPORTS_HDR_OUTPUT)) { + renderer_supports_hdr_output = true; + } +#endif + + Array state; + state.append(ds->window_is_hdr_output_requested()); + state.append(ds->window_is_hdr_output_enabled()); + state.append(ds->window_get_hdr_output_current_reference_luminance()); + state.append(ds->window_get_hdr_output_current_max_luminance()); + state.append(ds->window_get_output_max_linear_value()); + state.append(ds->has_feature(DisplayServerEnums::Feature::FEATURE_HDR_OUTPUT)); + state.append(renderer_supports_hdr_output); + + EngineDebugger::get_singleton()->send_message("game_view:hdr_state", state); + return OK; +} + +Error SceneDebugger::_msg_hdr_output_toggle_requested(const Array &p_args) { + DisplayServer *ds = DisplayServer::get_singleton(); + ds->window_request_hdr_output(!ds->window_is_hdr_output_requested()); + return OK; +} + Error SceneDebugger::_msg_override_cameras(const Array &p_args) { ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA); bool enable = p_args[0]; @@ -548,6 +602,7 @@ Error SceneDebugger::parse_message(void *p_user, const String &p_msg, const Arra void SceneDebugger::_init_message_handlers() { message_handlers["setup_scene"] = _msg_setup_scene; + message_handlers["setup_game_view"] = _msg_setup_game_view; message_handlers["setup_embedded_shortcuts"] = _msg_setup_embedded_shortcuts; message_handlers["request_scene_tree"] = _msg_request_scene_tree; message_handlers["save_node"] = _msg_save_node; @@ -560,6 +615,9 @@ void SceneDebugger::_init_message_handlers() { message_handlers["next_frame"] = _msg_next_frame; message_handlers["speed_changed"] = _msg_speed_changed; message_handlers["debug_mute_audio"] = _msg_debug_mute_audio; + message_handlers["window_request_size"] = _msg_window_request_size; + message_handlers["hdr_output_request_state"] = _msg_hdr_output_request_state; + message_handlers["hdr_output_toggle_requested"] = _msg_hdr_output_toggle_requested; message_handlers["override_cameras"] = _msg_override_cameras; message_handlers["transform_camera_2d"] = _msg_transform_camera_2d; #ifndef _3D_DISABLED diff --git a/scene/debugger/scene_debugger.h b/scene/debugger/scene_debugger.h index 9acc093ab2..56a1c602d4 100644 --- a/scene/debugger/scene_debugger.h +++ b/scene/debugger/scene_debugger.h @@ -54,6 +54,8 @@ public: 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 _on_window_size_changed(); + static void _on_output_max_linear_value_changed(float output_max_linear_value); static void _save_node(ObjectID id, const String &p_path); static void _set_node_owner_recursive(Node *p_node, Node *p_owner); @@ -67,6 +69,7 @@ private: static void _init_message_handlers(); static Error _msg_setup_scene(const Array &p_args); + static Error _msg_setup_game_view(const Array &p_args); static Error _msg_setup_embedded_shortcuts(const Array &p_args); static Error _msg_request_scene_tree(const Array &p_args); static Error _msg_save_node(const Array &p_args); @@ -79,6 +82,9 @@ private: static Error _msg_next_frame(const Array &p_args); static Error _msg_speed_changed(const Array &p_args); static Error _msg_debug_mute_audio(const Array &p_args); + static Error _msg_window_request_size(const Array &p_args); + static Error _msg_hdr_output_request_state(const Array &p_args); + static Error _msg_hdr_output_toggle_requested(const Array &p_args); static Error _msg_override_cameras(const Array &p_args); static Error _msg_set_object_property(const Array &p_args); static Error _msg_set_object_property_field(const Array &p_args);