diff options
30 files changed, 241 insertions, 77 deletions
diff --git a/core/extension/extension_api_dump.cpp b/core/extension/extension_api_dump.cpp index 310817c952..e6e0fff266 100644 --- a/core/extension/extension_api_dump.cpp +++ b/core/extension/extension_api_dump.cpp @@ -218,7 +218,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { String name = t == Variant::VARIANT_MAX ? String("Variant") : Variant::get_type_name(t); Dictionary d2; d2["name"] = name; - uint32_t size; + uint32_t size = 0; switch (i) { case 0: size = type_size_array[j].size_32_bits_real_float; @@ -333,7 +333,7 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() { last_type = t; } Dictionary d3; - uint32_t offset; + uint32_t offset = 0; switch (i) { case 0: offset = member_offset_array[idx].offset_32_bits_real_float; diff --git a/core/io/dir_access.cpp b/core/io/dir_access.cpp index f86dfe8057..79e7fa16e3 100644 --- a/core/io/dir_access.cpp +++ b/core/io/dir_access.cpp @@ -492,6 +492,7 @@ PackedStringArray DirAccess::get_files() { PackedStringArray DirAccess::get_files_at(const String &p_path) { Ref<DirAccess> da = DirAccess::open(p_path); + ERR_FAIL_COND_V_MSG(da.is_null(), PackedStringArray(), vformat("Couldn't open directory at path \"%s\".", p_path)); return da->get_files(); } @@ -501,6 +502,7 @@ PackedStringArray DirAccess::get_directories() { PackedStringArray DirAccess::get_directories_at(const String &p_path) { Ref<DirAccess> da = DirAccess::open(p_path); + ERR_FAIL_COND_V_MSG(da.is_null(), PackedStringArray(), vformat("Couldn't open directory at path \"%s\".", p_path)); return da->get_directories(); } diff --git a/core/math/bvh_structs.inc b/core/math/bvh_structs.inc index 58c8f0479a..06f6e5d05d 100644 --- a/core/math/bvh_structs.inc +++ b/core/math/bvh_structs.inc @@ -100,7 +100,11 @@ public: num_items++; return id; } +#ifdef DEV_ENABLED return -1; +#else + ERR_FAIL_V_MSG(0, "BVH request_item error."); +#endif } }; diff --git a/core/variant/callable.cpp b/core/variant/callable.cpp index 28efb43fc5..b35e2f004b 100644 --- a/core/variant/callable.cpp +++ b/core/variant/callable.cpp @@ -63,6 +63,21 @@ void Callable::callp(const Variant **p_arguments, int p_argcount, Variant &r_ret } } +Variant Callable::callv(const Array &p_arguments) const { + int argcount = p_arguments.size(); + const Variant **argptrs = nullptr; + if (argcount) { + argptrs = (const Variant **)alloca(sizeof(Variant *) * argcount); + for (int i = 0; i < argcount; i++) { + argptrs[i] = &p_arguments[i]; + } + } + CallError ce; + Variant ret; + callp(argptrs, argcount, ret, ce); + return ret; +} + Error Callable::rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const { if (is_null()) { r_call_error.error = CallError::CALL_ERROR_INSTANCE_IS_NULL; diff --git a/core/variant/callable.h b/core/variant/callable.h index 1f1c983eb3..0305dc55c3 100644 --- a/core/variant/callable.h +++ b/core/variant/callable.h @@ -71,6 +71,7 @@ public: void callp(const Variant **p_arguments, int p_argcount, Variant &r_return_value, CallError &r_call_error) const; void call_deferredp(const Variant **p_arguments, int p_argcount) const; + Variant callv(const Array &p_arguments) const; Error rpcp(int p_id, const Variant **p_arguments, int p_argcount, CallError &r_call_error) const; diff --git a/core/variant/variant_call.cpp b/core/variant/variant_call.cpp index 2501d9fd44..1831f7b72a 100644 --- a/core/variant/variant_call.cpp +++ b/core/variant/variant_call.cpp @@ -1859,6 +1859,7 @@ static void _register_variant_builtin_methods() { /* Callable */ + bind_method(Callable, callv, sarray("arguments"), varray()); bind_method(Callable, is_null, sarray(), varray()); bind_method(Callable, is_custom, sarray(), varray()); bind_method(Callable, is_standard, sarray(), varray()); diff --git a/doc/classes/Callable.xml b/doc/classes/Callable.xml index 1fcaf6d866..dd48ee6790 100644 --- a/doc/classes/Callable.xml +++ b/doc/classes/Callable.xml @@ -81,6 +81,13 @@ [/codeblock] </description> </method> + <method name="callv" qualifiers="const"> + <return type="Variant" /> + <param index="0" name="arguments" type="Array" /> + <description> + Calls the method represented by this [Callable]. Contrary to [method call], this method does not take a variable number of arguments but expects all arguments to be passed via a single [Array]. + </description> + </method> <method name="get_method" qualifiers="const"> <return type="StringName" /> <description> diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index f93a14b4ac..6d3f3a7362 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1548,6 +1548,8 @@ </constant> <constant name="WINDOW_EVENT_DPI_CHANGE" value="6" enum="WindowEvent"> </constant> + <constant name="WINDOW_EVENT_TITLEBAR_CHANGE" value="7" enum="WindowEvent"> + </constant> <constant name="VSYNC_DISABLED" value="0" enum="VSyncMode"> No vertical synchronization, which means the engine will display frames as fast as possible (tearing may be visible). </constant> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index 2bae2d9592..c585b54ee1 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -455,6 +455,11 @@ Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. </description> </signal> + <signal name="titlebar_changed"> + <description> + Emitted when window title bar decorations are changed, e.g., macOS window enter/exit full screen mode, or extend-to-title flag is changed. + </description> + </signal> <signal name="visibility_changed"> <description> Emitted when [Window] is made visible or disappears. diff --git a/editor/editor_feature_profile.cpp b/editor/editor_feature_profile.cpp index 708173ea26..9549ffb09b 100644 --- a/editor/editor_feature_profile.cpp +++ b/editor/editor_feature_profile.cpp @@ -763,7 +763,7 @@ void EditorFeatureProfileManager::_update_selected_profile() { TreeItem *root = class_list->create_item(); TreeItem *features = class_list->create_item(root); - TreeItem *last_feature; + TreeItem *last_feature = nullptr; features->set_text(0, TTR("Main Features:")); for (int i = 0; i < EditorFeatureProfile::FEATURE_MAX; i++) { TreeItem *feature; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index c8bd9a9c44..673fa3404c 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -429,7 +429,7 @@ void EditorNode::_version_control_menu_option(int p_idx) { void EditorNode::_update_title() { const String appname = ProjectSettings::get_singleton()->get("application/config/name"); - String title = (appname.is_empty() ? TTR("Unnamed Project") : appname) + String(" - ") + VERSION_NAME; + String title = (appname.is_empty() ? TTR("Unnamed Project") : appname); const String edited = editor_data.get_edited_scene_root() ? editor_data.get_edited_scene_root()->get_scene_file_path() : String(); if (!edited.is_empty()) { // Display the edited scene name before the program name so that it can be seen in the OS task bar. @@ -439,8 +439,10 @@ void EditorNode::_update_title() { // Display the "modified" mark before anything else so that it can always be seen in the OS task bar. title = vformat("(*) %s", title); } - - DisplayServer::get_singleton()->window_set_title(title); + DisplayServer::get_singleton()->window_set_title(title + String(" - ") + VERSION_NAME); + if (project_title) { + project_title->set_text(title); + } } void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) { @@ -659,6 +661,12 @@ void EditorNode::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { Engine::get_singleton()->set_editor_hint(true); + Window *window = static_cast<Window *>(get_tree()->get_root()); + if (window) { + // Handle macOS fullscreen and extend-to-title changes. + window->connect("titlebar_changed", callable_mp(this, &EditorNode::_titlebar_resized)); + } + OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec"))); get_tree()->get_root()->set_as_audio_listener_3d(false); get_tree()->get_root()->set_as_audio_listener_2d(false); @@ -713,6 +721,8 @@ void EditorNode::_notification(int p_what) { ProjectSettings::get_singleton()->save(); } + _titlebar_resized(); + /* DO NOT LOAD SCENES HERE, WAIT FOR FILE SCANNING AND REIMPORT TO COMPLETE */ } break; @@ -1170,6 +1180,18 @@ void EditorNode::_reload_project_settings() { void EditorNode::_vp_resized() { } +void EditorNode::_titlebar_resized() { + const Size2 &margin = DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID); + if (left_menu_spacer) { + int w = (gui_base->is_layout_rtl()) ? margin.y : margin.x; + left_menu_spacer->set_custom_minimum_size(Size2(w, 0)); + } + if (right_menu_spacer) { + int w = (gui_base->is_layout_rtl()) ? margin.x : margin.y; + right_menu_spacer->set_custom_minimum_size(Size2(w, 0)); + } +} + void EditorNode::_version_button_pressed() { DisplayServer::get_singleton()->clipboard_set(version_btn->get_meta(META_TEXT_TO_COPY)); } @@ -3390,7 +3412,7 @@ void EditorNode::add_editor_plugin(EditorPlugin *p_editor, bool p_config_changed tb->add_theme_font_size_override("font_size", singleton->gui_base->get_theme_font_size(SNAME("main_button_font_size"), SNAME("EditorFonts"))); singleton->main_editor_buttons.push_back(tb); - singleton->main_editor_button_vb->add_child(tb); + singleton->main_editor_button_hb->add_child(tb); singleton->editor_table.push_back(p_editor); singleton->distraction_free->move_to_front(); @@ -6590,14 +6612,14 @@ EditorNode::EditorNode() { if (can_expand) { // Add spacer to avoid other controls under window minimize/maximize/close buttons (left side). - Control *menu_spacer = memnew(Control); - menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); - menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).x, 0)); - menu_hb->add_child(menu_spacer); + left_menu_spacer = memnew(Control); + left_menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_hb->add_child(left_menu_spacer); } main_menu = memnew(MenuBar); menu_hb->add_child(main_menu); + main_menu->add_theme_style_override("hover", gui_base->get_theme_stylebox(SNAME("MenuHover"), SNAME("EditorStyles"))); main_menu->set_flat(true); main_menu->set_start_index(0); // Main menu, add to the start of global menu. @@ -6766,22 +6788,30 @@ EditorNode::EditorNode() { project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); // Spacer to center 2D / 3D / Script buttons. - Control *left_spacer = memnew(Control); + HBoxContainer *left_spacer = memnew(HBoxContainer); left_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + left_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); menu_hb->add_child(left_spacer); - menu_hb->add_spacer(); + if (can_expand && global_menu) { + project_title = memnew(Label); + project_title->add_theme_font_override("font", gui_base->get_theme_font(SNAME("bold"), SNAME("EditorFonts"))); + project_title->add_theme_font_size_override("font_size", gui_base->get_theme_font_size(SNAME("bold_size"), SNAME("EditorFonts"))); + project_title->set_focus_mode(Control::FOCUS_NONE); + project_title->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); + project_title->set_vertical_alignment(VERTICAL_ALIGNMENT_CENTER); + project_title->set_h_size_flags(Control::SIZE_EXPAND_FILL); + left_spacer->add_child(project_title); + } - main_editor_button_vb = memnew(HBoxContainer); - menu_hb->add_child(main_editor_button_vb); + main_editor_button_hb = memnew(HBoxContainer); + menu_hb->add_child(main_editor_button_hb); // Options are added and handled by DebuggerEditorPlugin. debug_menu = memnew(PopupMenu); debug_menu->set_name(TTR("Debug")); main_menu->add_child(debug_menu); - menu_hb->add_spacer(); - settings_menu = memnew(PopupMenu); settings_menu->set_name(TTR("Editor")); main_menu->add_child(settings_menu); @@ -6855,6 +6885,7 @@ EditorNode::EditorNode() { // Spacer to center 2D / 3D / Script buttons. Control *right_spacer = memnew(Control); right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + right_spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL); menu_hb->add_child(right_spacer); launch_pad = memnew(PanelContainer); @@ -6965,10 +6996,9 @@ EditorNode::EditorNode() { if (can_expand) { // Add spacer to avoid other controls under the window minimize/maximize/close buttons (right side). - Control *menu_spacer = memnew(Control); - menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); - menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).y, 0)); - menu_hb->add_child(menu_spacer); + right_menu_spacer = memnew(Control); + right_menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_hb->add_child(right_menu_spacer); } String current_renderer = GLOBAL_GET("rendering/renderer/rendering_method"); @@ -7523,9 +7553,9 @@ EditorNode::EditorNode() { screenshot_timer->set_owner(get_owner()); // Adjust spacers to center 2D / 3D / Script buttons. - int max_w = MAX(launch_pad_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); + int max_w = MAX(launch_pad->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0)); - right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - launch_pad_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - launch_pad->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); // Extend menu bar to window title. if (can_expand) { diff --git a/editor/editor_node.h b/editor/editor_node.h index 14dab11358..fab280bc14 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -322,6 +322,9 @@ private: HBoxContainer *bottom_hb = nullptr; Control *vp_base = nullptr; + Label *project_title = nullptr; + Control *left_menu_spacer = nullptr; + Control *right_menu_spacer = nullptr; EditorTitleBar *menu_hb = nullptr; VBoxContainer *main_screen_vbox = nullptr; MenuBar *main_menu = nullptr; @@ -397,7 +400,7 @@ private: String current_path; MenuButton *update_spinner = nullptr; - HBoxContainer *main_editor_button_vb = nullptr; + HBoxContainer *main_editor_button_hb = nullptr; Vector<Button *> main_editor_buttons; Vector<EditorPlugin *> editor_table; @@ -560,6 +563,7 @@ private: void _close_messages(); void _show_messages(); void _vp_resized(); + void _titlebar_resized(); void _version_button_pressed(); int _save_external_resources(); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 1fb9b42449..e2ed8e44c4 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -134,7 +134,7 @@ void ThemeItemImportTree::_update_items_tree() { data_type_node->set_checked(IMPORT_ITEM_DATA, false); data_type_node->set_editable(IMPORT_ITEM_DATA, true); - List<TreeItem *> *item_list; + List<TreeItem *> *item_list = nullptr; switch (dt) { case Theme::DATA_TYPE_COLOR: @@ -398,7 +398,7 @@ void ThemeItemImportTree::_restore_selected_item(TreeItem *p_tree_item) { void ThemeItemImportTree::_update_total_selected(Theme::DataType p_data_type) { ERR_FAIL_INDEX_MSG(p_data_type, Theme::DATA_TYPE_MAX, "Theme item data type is out of bounds."); - Label *total_selected_items_label; + Label *total_selected_items_label = nullptr; switch (p_data_type) { case Theme::DATA_TYPE_COLOR: total_selected_items_label = total_selected_colors_label; @@ -562,7 +562,7 @@ void ThemeItemImportTree::_select_all_data_type_pressed(int p_data_type) { } Theme::DataType data_type = (Theme::DataType)p_data_type; - List<TreeItem *> *item_list; + List<TreeItem *> *item_list = nullptr; switch (data_type) { case Theme::DATA_TYPE_COLOR: @@ -617,7 +617,7 @@ void ThemeItemImportTree::_select_full_data_type_pressed(int p_data_type) { } Theme::DataType data_type = (Theme::DataType)p_data_type; - List<TreeItem *> *item_list; + List<TreeItem *> *item_list = nullptr; switch (data_type) { case Theme::DATA_TYPE_COLOR: @@ -674,7 +674,7 @@ void ThemeItemImportTree::_deselect_all_data_type_pressed(int p_data_type) { } Theme::DataType data_type = (Theme::DataType)p_data_type; - List<TreeItem *> *item_list; + List<TreeItem *> *item_list = nullptr; switch (data_type) { case Theme::DATA_TYPE_COLOR: @@ -982,17 +982,17 @@ ThemeItemImportTree::ThemeItemImportTree() { for (int i = 0; i < Theme::DATA_TYPE_MAX; i++) { Theme::DataType dt = (Theme::DataType)i; - TextureRect *select_items_icon; - Label *select_items_label; - Button *deselect_all_items_button; - Button *select_all_items_button; - Button *select_full_items_button; - Label *total_selected_items_label; - - String items_title = ""; - String select_all_items_tooltip = ""; - String select_full_items_tooltip = ""; - String deselect_all_items_tooltip = ""; + TextureRect *select_items_icon = nullptr; + Label *select_items_label = nullptr; + Button *deselect_all_items_button = nullptr; + Button *select_all_items_button = nullptr; + Button *select_full_items_button = nullptr; + Label *total_selected_items_label = nullptr; + + String items_title; + String select_all_items_tooltip; + String select_full_items_tooltip; + String deselect_all_items_tooltip; switch (dt) { case Theme::DATA_TYPE_COLOR: diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 573e57ca04..4563dbb0f7 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -133,7 +133,7 @@ void SceneCreateDialog::update_dialog() { root_name = scene_name.get_file().get_basename(); } - if (!root_name.is_valid_identifier()) { + if (root_name.is_empty() || root_name.validate_node_name().size() != root_name.size()) { update_error(node_error_label, MSG_ERROR, TTR("Invalid root node name.")); is_valid = false; } diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 004bb7dcd1..34723c7d4b 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -2664,21 +2664,17 @@ Vector2i DisplayServerMacOS::window_get_safe_title_margins(WindowID p_window) co ERR_FAIL_COND_V(!windows.has(p_window), Vector2i()); const WindowData &wd = windows[p_window]; - float max_x = 0.f; - NSButton *cb = [wd.window_object standardWindowButton:NSWindowCloseButton]; - if (cb) { - max_x = MAX(max_x, [cb frame].origin.x + [cb frame].size.width); - } - NSButton *mb = [wd.window_object standardWindowButton:NSWindowMiniaturizeButton]; - if (mb) { - max_x = MAX(max_x, [mb frame].origin.x + [mb frame].size.width); - } - NSButton *zb = [wd.window_object standardWindowButton:NSWindowZoomButton]; - if (zb) { - max_x = MAX(max_x, [zb frame].origin.x + [zb frame].size.width); + if (!wd.window_button_view) { + return Vector2i(); } - return Vector2i(max_x * screen_get_max_scale(), 0); + float max_x = wd.wb_offset.x + [wd.window_button_view frame].size.width; + + if ([wd.window_object windowTitlebarLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft) { + return Vector2i(0, max_x * screen_get_max_scale()); + } else { + return Vector2i(max_x * screen_get_max_scale(), 0); + } } void DisplayServerMacOS::window_set_custom_window_buttons(WindowData &p_wd, bool p_enabled) { @@ -2687,7 +2683,11 @@ void DisplayServerMacOS::window_set_custom_window_buttons(WindowData &p_wd, bool p_wd.window_button_view = nil; } if (p_enabled) { - float window_buttons_spacing = NSMinX([[p_wd.window_object standardWindowButton:NSWindowMiniaturizeButton] frame]) - NSMinX([[p_wd.window_object standardWindowButton:NSWindowCloseButton] frame]); + float cb_frame = NSMinX([[p_wd.window_object standardWindowButton:NSWindowCloseButton] frame]); + float mb_frame = NSMinX([[p_wd.window_object standardWindowButton:NSWindowMiniaturizeButton] frame]); + bool is_rtl = ([p_wd.window_object windowTitlebarLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft); + + float window_buttons_spacing = (is_rtl) ? (cb_frame - mb_frame) : (mb_frame - cb_frame); [p_wd.window_object setTitleVisibility:NSWindowTitleHidden]; [[p_wd.window_object standardWindowButton:NSWindowZoomButton] setHidden:YES]; @@ -2695,7 +2695,7 @@ void DisplayServerMacOS::window_set_custom_window_buttons(WindowData &p_wd, bool [[p_wd.window_object standardWindowButton:NSWindowCloseButton] setHidden:YES]; p_wd.window_button_view = [[GodotButtonView alloc] initWithFrame:NSZeroRect]; - [p_wd.window_button_view initButtons:window_buttons_spacing offset:NSMakePoint(p_wd.wb_offset.x, p_wd.wb_offset.y)]; + [p_wd.window_button_view initButtons:window_buttons_spacing offset:NSMakePoint(p_wd.wb_offset.x, p_wd.wb_offset.y) rtl:is_rtl]; [p_wd.window_view addSubview:p_wd.window_button_view]; } else { [p_wd.window_object setTitleVisibility:NSWindowTitleVisible]; @@ -2741,6 +2741,7 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win } } [wd.window_object setFrame:rect display:YES]; + send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE); } break; case WINDOW_FLAG_BORDERLESS: { // OrderOut prevents a lose focus bug with the window. diff --git a/platform/macos/godot_button_view.h b/platform/macos/godot_button_view.h index e41910878d..e7627a9e9b 100644 --- a/platform/macos/godot_button_view.h +++ b/platform/macos/godot_button_view.h @@ -41,9 +41,10 @@ NSPoint offset; CGFloat spacing; bool mouse_in_group; + bool rtl; } -- (void)initButtons:(CGFloat)button_spacing offset:(NSPoint)button_offset; +- (void)initButtons:(CGFloat)button_spacing offset:(NSPoint)button_offset rtl:(bool)is_rtl; - (void)displayButtons; @end diff --git a/platform/macos/godot_button_view.mm b/platform/macos/godot_button_view.mm index ae04c02bd5..9106f0b0db 100644 --- a/platform/macos/godot_button_view.mm +++ b/platform/macos/godot_button_view.mm @@ -39,15 +39,17 @@ offset = NSMakePoint(8, 8); spacing = 20; mouse_in_group = false; + rtl = false; return self; } -- (void)initButtons:(CGFloat)button_spacing offset:(NSPoint)button_offset { +- (void)initButtons:(CGFloat)button_spacing offset:(NSPoint)button_offset rtl:(bool)is_rtl { spacing = button_spacing; + rtl = is_rtl; NSButton *close_button = [NSWindow standardWindowButton:NSWindowCloseButton forStyleMask:NSWindowStyleMaskTitled]; - [close_button setFrameOrigin:NSMakePoint(0, 0)]; + [close_button setFrameOrigin:NSMakePoint(rtl ? spacing * 2 : 0, 0)]; [self addSubview:close_button]; NSButton *miniaturize_button = [NSWindow standardWindowButton:NSWindowMiniaturizeButton forStyleMask:NSWindowStyleMaskTitled]; @@ -55,13 +57,17 @@ [self addSubview:miniaturize_button]; NSButton *zoom_button = [NSWindow standardWindowButton:NSWindowZoomButton forStyleMask:NSWindowStyleMaskTitled]; - [zoom_button setFrameOrigin:NSMakePoint(spacing * 2, 0)]; + [zoom_button setFrameOrigin:NSMakePoint(rtl ? 0 : spacing * 2, 0)]; [self addSubview:zoom_button]; offset.y = button_offset.y - zoom_button.frame.size.height / 2; offset.x = button_offset.x - zoom_button.frame.size.width / 2; - [self setFrameSize:NSMakeSize(zoom_button.frame.origin.x + zoom_button.frame.size.width, zoom_button.frame.size.height)]; + if (rtl) { + [self setFrameSize:NSMakeSize(close_button.frame.origin.x + close_button.frame.size.width, close_button.frame.size.height)]; + } else { + [self setFrameSize:NSMakeSize(zoom_button.frame.origin.x + zoom_button.frame.size.width, zoom_button.frame.size.height)]; + } [self displayButtons]; } @@ -70,8 +76,13 @@ return; } - [self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; - [self setFrameOrigin:NSMakePoint(offset.x, self.window.frame.size.height - self.frame.size.height - offset.y)]; + if (rtl) { + [self setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; + [self setFrameOrigin:NSMakePoint(self.window.frame.size.width - self.frame.size.width - offset.x, self.window.frame.size.height - self.frame.size.height - offset.y)]; + } else { + [self setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; + [self setFrameOrigin:NSMakePoint(offset.x, self.window.frame.size.height - self.frame.size.height - offset.y)]; + } } - (BOOL)_mouseInGroup:(NSButton *)button { diff --git a/platform/macos/godot_window.h b/platform/macos/godot_window.h index 9fc5599e86..d3653fda82 100644 --- a/platform/macos/godot_window.h +++ b/platform/macos/godot_window.h @@ -38,9 +38,11 @@ @interface GodotWindow : NSWindow { DisplayServer::WindowID window_id; + NSTimeInterval anim_duration; } - (void)setWindowID:(DisplayServer::WindowID)wid; +- (void)setAnimDuration:(NSTimeInterval)duration; @end diff --git a/platform/macos/godot_window.mm b/platform/macos/godot_window.mm index e205e7546d..bc51da4f72 100644 --- a/platform/macos/godot_window.mm +++ b/platform/macos/godot_window.mm @@ -37,9 +37,22 @@ - (id)init { self = [super init]; window_id = DisplayServer::INVALID_WINDOW_ID; + anim_duration = -1.0f; return self; } +- (void)setAnimDuration:(NSTimeInterval)duration { + anim_duration = duration; +} + +- (NSTimeInterval)animationResizeTime:(NSRect)newFrame { + if (anim_duration > 0) { + return anim_duration; + } else { + return [super animationResizeTime:newFrame]; + } +} + - (void)setWindowID:(DisplayServerMacOS::WindowID)wid { window_id = wid; } diff --git a/platform/macos/godot_window_delegate.h b/platform/macos/godot_window_delegate.h index 98c226aa2f..01cc13a016 100644 --- a/platform/macos/godot_window_delegate.h +++ b/platform/macos/godot_window_delegate.h @@ -38,6 +38,8 @@ @interface GodotWindowDelegate : NSObject <NSWindowDelegate> { DisplayServer::WindowID window_id; + NSRect old_frame; + NSWindowStyleMask old_style_mask; } - (void)setWindowID:(DisplayServer::WindowID)wid; diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm index 94d40924b2..279fd2a359 100644 --- a/platform/macos/godot_window_delegate.mm +++ b/platform/macos/godot_window_delegate.mm @@ -32,6 +32,7 @@ #include "display_server_macos.h" #include "godot_button_view.h" +#include "godot_window.h" @implementation GodotWindowDelegate @@ -69,6 +70,26 @@ ds->window_destroy(window_id); } +- (NSArray<NSWindow *> *)customWindowsToEnterFullScreenForWindow:(NSWindow *)window { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); + if (!ds || !ds->has_window(window_id)) { + return nullptr; + } + + old_frame = [window frame]; + old_style_mask = [window styleMask]; + + NSMutableArray<NSWindow *> *windows = [[NSMutableArray alloc] init]; + [windows addObject:window]; + + return windows; +} + +- (void)window:(NSWindow *)window startCustomAnimationToEnterFullScreenWithDuration:(NSTimeInterval)duration { + [(GodotWindow *)window setAnimDuration:duration]; + [window setFrame:[[window screen] frame] display:YES animate:YES]; +} + - (void)windowDidEnterFullScreen:(NSNotification *)notification { DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); if (!ds || !ds->has_window(window_id)) { @@ -81,6 +102,7 @@ // Reset window size limits. [wd.window_object setContentMinSize:NSMakeSize(0, 0)]; [wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; + [(GodotWindow *)wd.window_object setAnimDuration:-1.0f]; // Reset custom window buttons. if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) { @@ -89,6 +111,33 @@ // Force window resize event. [self windowDidResize:notification]; + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE); +} + +- (NSArray<NSWindow *> *)customWindowsToExitFullScreenForWindow:(NSWindow *)window { + DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton(); + if (!ds || !ds->has_window(window_id)) { + return nullptr; + } + + DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); + + // Restore custom window buttons. + if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) { + ds->window_set_custom_window_buttons(wd, true); + } + + ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_TITLEBAR_CHANGE); + + NSMutableArray<NSWindow *> *windows = [[NSMutableArray alloc] init]; + [windows addObject:wd.window_object]; + return windows; +} + +- (void)window:(NSWindow *)window startCustomAnimationToExitFullScreenWithDuration:(NSTimeInterval)duration { + [(GodotWindow *)window setAnimDuration:duration]; + [window setStyleMask:old_style_mask]; + [window setFrame:old_frame display:YES animate:YES]; } - (void)windowDidExitFullScreen:(NSNotification *)notification { @@ -100,6 +149,8 @@ DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); wd.fullscreen = false; + [(GodotWindow *)wd.window_object setAnimDuration:-1.0f]; + // Set window size limits. const float scale = ds->screen_get_max_scale(); if (wd.min_size != Size2i()) { @@ -111,11 +162,6 @@ [wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)]; } - // Restore custom window buttons. - if ([wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView) { - ds->window_set_custom_window_buttons(wd, true); - } - // Restore resizability state. if (wd.resize_disabled) { [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable]; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index ef0172c612..3c45b90612 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -4703,7 +4703,10 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p queue_redraw(); return true; } - p_search_previous ? current_line-- : current_line++; + + if (current_line != ending_line) { + p_search_previous ? current_line-- : current_line++; + } } if (p_from_selection && selection.active) { diff --git a/scene/main/window.cpp b/scene/main/window.cpp index ebe9587b31..cf30ca259d 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -389,6 +389,9 @@ void Window::_event_callback(DisplayServer::WindowEvent p_event) { _propagate_window_notification(this, NOTIFICATION_WM_DPI_CHANGE); emit_signal(SNAME("dpi_changed")); } break; + case DisplayServer::WINDOW_EVENT_TITLEBAR_CHANGE: { + emit_signal(SNAME("titlebar_changed")); + } break; } } @@ -1782,6 +1785,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("visibility_changed")); ADD_SIGNAL(MethodInfo("about_to_popup")); ADD_SIGNAL(MethodInfo("theme_changed")); + ADD_SIGNAL(MethodInfo("titlebar_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); BIND_CONSTANT(NOTIFICATION_THEME_CHANGED); diff --git a/scene/resources/visual_shader.h b/scene/resources/visual_shader.h index 4116eaa196..3aba550f03 100644 --- a/scene/resources/visual_shader.h +++ b/scene/resources/visual_shader.h @@ -90,11 +90,10 @@ public: struct Varying { String name; - VaryingMode mode; - VaryingType type; + VaryingMode mode = VARYING_MODE_MAX; + VaryingType type = VARYING_TYPE_MAX; - Varying() { - } + Varying() {} Varying(String p_name, VaryingMode p_mode, VaryingType p_type) : name(p_name), mode(p_mode), type(p_type) {} diff --git a/servers/display_server.cpp b/servers/display_server.cpp index e1a1c71420..4b97bede56 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -824,6 +824,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_EVENT_CLOSE_REQUEST); BIND_ENUM_CONSTANT(WINDOW_EVENT_GO_BACK_REQUEST); BIND_ENUM_CONSTANT(WINDOW_EVENT_DPI_CHANGE); + BIND_ENUM_CONSTANT(WINDOW_EVENT_TITLEBAR_CHANGE); BIND_ENUM_CONSTANT(VSYNC_DISABLED); BIND_ENUM_CONSTANT(VSYNC_ENABLED); diff --git a/servers/display_server.h b/servers/display_server.h index 42c254cd2f..8eafccc040 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -336,6 +336,7 @@ public: WINDOW_EVENT_CLOSE_REQUEST, WINDOW_EVENT_GO_BACK_REQUEST, WINDOW_EVENT_DPI_CHANGE, + WINDOW_EVENT_TITLEBAR_CHANGE, }; virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0; diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 63fd10886d..35953a7120 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -479,6 +479,9 @@ void RenderForwardClustered::_render_list_template(RenderingDevice::DrawListID p if ((surf->owner->base_flags & (INSTANCE_DATA_FLAG_MULTIMESH | INSTANCE_DATA_FLAG_PARTICLES)) == INSTANCE_DATA_FLAG_MULTIMESH) { mesh_storage->_multimesh_get_motion_vectors_offsets(surf->owner->data->base, push_constant.multimesh_motion_vectors_current_offset, push_constant.multimesh_motion_vectors_previous_offset); + } else { + push_constant.multimesh_motion_vectors_current_offset = 0; + push_constant.multimesh_motion_vectors_previous_offset = 0; } RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(SceneState::PushConstant)); diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 2190f41603..ac1daad05c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -3302,7 +3302,7 @@ void RendererSceneRenderRD::_render_shadow_pass(RID p_light, RID p_shadow_atlas, ERR_FAIL_COND(!light_instance); Rect2i atlas_rect; - uint32_t atlas_size; + uint32_t atlas_size = 1; RID atlas_fb; bool using_dual_paraboloid = false; diff --git a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp index b87b4d4a0f..800a742cb6 100644 --- a/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/texture_storage.cpp @@ -795,6 +795,8 @@ void TextureStorage::texture_2d_layered_initialize(RID p_texture, const Vector<R case RS::TEXTURE_LAYERED_CUBEMAP_ARRAY: { texture.rd_type = RD::TEXTURE_TYPE_CUBE_ARRAY; } break; + default: + ERR_FAIL(); // Shouldn't happen, silence warnings. } texture.rd_format = ret_format.format; diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index b9df0ec8ac..57378708ba 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -743,7 +743,7 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i r_attrib_element_size = 0; r_skin_element_size = 0; - uint32_t *size_accum; + uint32_t *size_accum = nullptr; for (int i = 0; i < RS::ARRAY_MAX; i++) { r_offsets[i] = 0; // Reset @@ -847,8 +847,12 @@ void RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, i } } - r_offsets[i] = (*size_accum); - (*size_accum) += elem_size; + if (size_accum != nullptr) { + r_offsets[i] = (*size_accum); + (*size_accum) += elem_size; + } else { + r_offsets[i] = 0; + } } } |