From 8e00035f086c62558d03217a1f4c03594618344e Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Sun, 1 Dec 2024 00:45:09 +0100 Subject: [PATCH 01/91] Introduce `Viewport` functions for keeping the mouse over state consistent --- doc/classes/Viewport.xml | 14 ++++++++++++++ scene/main/viewport.cpp | 18 ++++++++++++++++++ scene/main/viewport.h | 2 ++ 3 files changed, 34 insertions(+) diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 3e772c4e884b..1f28a3443139 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -188,6 +188,20 @@ If [member handle_input_locally] is set to [code]false[/code], this method will try finding the first parent viewport that is set to handle input locally, and return its value for [method is_input_handled] instead. + + + + Inform the Viewport that the mouse has entered its area. Use this function before sending an [InputEventMouseButton] or [InputEventMouseMotion] to the [Viewport] with [method Viewport.push_input]. See also [method notify_mouse_exited]. + [b]Note:[/b] In most cases, it is not necessary to call this function because [SubViewport] nodes that are children of [SubViewportContainer] are notified automatically. This is only necessary when interacting with viewports in non-default ways, for example as textures in [TextureRect] or with an [Area3D] that forwards input events. + + + + + + Inform the Viewport that the mouse has left its area. Use this function when the node that displays the viewport notices the mouse has left the area of the displayed viewport. See also [method notify_mouse_entered]. + [b]Note:[/b] In most cases, it is not necessary to call this function because [SubViewport] nodes that are children of [SubViewportContainer] are notified automatically. This is only necessary when interacting with viewports in non-default ways, for example as textures in [TextureRect] or with an [Area3D] that forwards input events. + + diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 6c83c7843fb8..6073a2950fb3 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -3257,6 +3257,22 @@ void Viewport::_push_unhandled_input_internal(const Ref &p_event) { } } +void Viewport::notify_mouse_entered() { + if (gui.mouse_in_viewport) { + WARN_PRINT_ED("The Viewport was previously notified that the mouse is in its area. There is no need to notify it at this time."); + return; + } + notification(NOTIFICATION_VP_MOUSE_ENTER); +} + +void Viewport::notify_mouse_exited() { + if (!gui.mouse_in_viewport) { + WARN_PRINT_ED("The Viewport was previously notified that the mouse has left its area. There is no need to notify it at this time."); + return; + } + _mouse_leave_viewport(); +} + void Viewport::set_physics_object_picking(bool p_enable) { ERR_MAIN_THREAD_GUARD; physics_object_picking = p_enable; @@ -4679,6 +4695,8 @@ void Viewport::_bind_methods() { #ifndef DISABLE_DEPRECATED ClassDB::bind_method(D_METHOD("push_unhandled_input", "event", "in_local_coords"), &Viewport::push_unhandled_input, DEFVAL(false)); #endif // DISABLE_DEPRECATED + ClassDB::bind_method(D_METHOD("notify_mouse_entered"), &Viewport::notify_mouse_entered); + ClassDB::bind_method(D_METHOD("notify_mouse_exited"), &Viewport::notify_mouse_exited); ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position); ClassDB::bind_method(D_METHOD("warp_mouse", "position"), &Viewport::warp_mouse); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 3a5ad2d83cb4..940b001f1f36 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -578,6 +578,8 @@ class Viewport : public Node { #ifndef DISABLE_DEPRECATED void push_unhandled_input(const Ref &p_event, bool p_local_coords = false); #endif // DISABLE_DEPRECATED + void notify_mouse_entered(); + void notify_mouse_exited(); void set_disable_input(bool p_disable); bool is_input_disabled() const; From 52ee437d7e13582a2a341a9c5da9b129ddd22738 Mon Sep 17 00:00:00 2001 From: Kiro Date: Sun, 29 Dec 2024 16:35:10 +0100 Subject: [PATCH 02/91] try Fixing Variant workaround --- core/object/make_virtuals.py | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/core/object/make_virtuals.py b/core/object/make_virtuals.py index 2974346a46f2..2358e1378499 100644 --- a/core/object/make_virtuals.py +++ b/core/object/make_virtuals.py @@ -127,7 +127,7 @@ def generate_version(argcount, const=False, returns=False, required=False): callptrargsptr += ", " argtext += f"m_type{i + 1}" callargtext += f"m_type{i + 1} arg{i + 1}" - callsiargs += f"_to_variant(arg{i + 1})" + callsiargs += f"arg{i + 1}" callsiargptrs += f"&vargs[{i}]" callptrargs += ( f"PtrToArg::EncodeT argval{i + 1} = (PtrToArg::EncodeT)arg{i + 1};\\\n" @@ -200,37 +200,6 @@ def run(target, source, env): #define GDVIRTUAL_TRACK(m_virtual, m_initialized) #endif -// MSVC WORKAROUND START -// FIXME The below helper functions are needed to work around an MSVC bug. -// They should be removed (by modifying core/object/make_virtuals.py) once the bug ceases to be triggered. -// The bug is triggered by the following code: -// `Variant(arg)` -// Through the introduction of the move constructor, MSVC forgets that `operator Variant()` -// is also a valid way to resolve this call. So for some argument types, it fails the call because -// it cannot convert to `Variant`. -// The function `_to_variant` helps the compiler select `.operator Variant()` for appropriate arguments using SFINAE. - -template -struct has_variant_operator : std::false_type {}; - -template -struct has_variant_operator().operator Variant())>> : std::true_type {}; - -// Function that is enabled if T has `.operator Variant()`. -template -_ALWAYS_INLINE_ typename std::enable_if::value, Variant>::type -_to_variant(T&& t) { - return std::forward(t).operator Variant(); -} - -// Function that is enabled if T does not have `.operator Variant()`. -template -_ALWAYS_INLINE_ typename std::enable_if::value, Variant>::type -_to_variant(T&& t) { - return Variant(std::forward(t)); -} -// MSVC WORKAROUND END - """ for i in range(max_versions + 1): From 4cef91e0f56142b0326e54d1d89ed4d6932bc64d Mon Sep 17 00:00:00 2001 From: Danil Alexeev Date: Sat, 4 Jan 2025 17:12:55 +0300 Subject: [PATCH 03/91] =?UTF-8?q?Editor:=20Fix=20`Ctrl+Click`=20on=20enum?= =?UTF-8?q?=20values=20=E2=80=8B=E2=80=8Bdoes=20nothing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/gdscript/gdscript_editor.cpp | 42 ++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index c20c17f34860..7ee8d8c42614 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -3684,12 +3684,12 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co case GDScriptParser::ClassNode::Member::GROUP: return ERR_BUG; case GDScriptParser::ClassNode::Member::CLASS: { - String type_name; - String enum_name; - GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(member.get_datatype()), type_name, enum_name); + String doc_type_name; + String doc_enum_name; + GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(member.get_datatype()), doc_type_name, doc_enum_name); r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS; - r_result.class_name = type_name; + r_result.class_name = doc_type_name; } break; case GDScriptParser::ClassNode::Member::CONSTANT: r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT; @@ -3712,11 +3712,11 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co } if (member.type != GDScriptParser::ClassNode::Member::CLASS) { - String type_name; - String enum_name; - GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(base_type), type_name, enum_name); + String doc_type_name; + String doc_enum_name; + GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(base_type), doc_type_name, doc_enum_name); - r_result.class_name = type_name; + r_result.class_name = doc_type_name; r_result.class_member = name; } @@ -3934,21 +3934,35 @@ static Error _lookup_symbol_from_base(const GDScriptParser::DataType &p_base, co case GDScriptParser::DataType::ENUM: { if (base_type.is_meta_type) { if (base_type.enum_values.has(p_symbol)) { - String type_name; - String enum_name; - GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(base_type), type_name, enum_name); + String doc_type_name; + String doc_enum_name; + GDScriptDocGen::doctype_from_gdtype(GDScriptAnalyzer::type_from_metatype(base_type), doc_type_name, doc_enum_name); - if (CoreConstants::is_global_enum(enum_name)) { + if (CoreConstants::is_global_enum(doc_enum_name)) { r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT; r_result.class_name = "@GlobalScope"; r_result.class_member = p_symbol; return OK; } else { - const int dot_pos = enum_name.rfind_char('.'); + const int dot_pos = doc_enum_name.rfind_char('.'); if (dot_pos >= 0) { r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT; - r_result.class_name = enum_name.left(dot_pos); + r_result.class_name = doc_enum_name.left(dot_pos); r_result.class_member = p_symbol; + if (base_type.class_type != nullptr) { + const String enum_name = doc_enum_name.substr(dot_pos + 1); + if (base_type.class_type->has_member(enum_name)) { + const GDScriptParser::ClassNode::Member member = base_type.class_type->get_member(enum_name); + if (member.type == GDScriptParser::ClassNode::Member::ENUM) { + for (const GDScriptParser::EnumNode::Value &value : member.m_enum->values) { + if (value.identifier->name == p_symbol) { + r_result.location = value.line; + break; + } + } + } + } + } return OK; } } From 791ad97beba0dbfa4260daa2213e71341ba8abf1 Mon Sep 17 00:00:00 2001 From: Kilian Strunz Date: Tue, 14 Jan 2025 13:36:29 +0100 Subject: [PATCH 04/91] Respect order of externsions for ResourceFormatSavers with at_front --- editor/editor_node.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4d4f8c2307d6..371627dd5cf1 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1442,16 +1442,11 @@ void EditorNode::save_resource_as(const Ref &p_resource, const String file->add_filter("*." + E, E.to_upper()); preferred.push_back(E); } - // Lowest priority extension. + // Lowest provided extension priority. List::Element *res_element = preferred.find("res"); if (res_element) { preferred.move_to_back(res_element); } - // Highest priority extension. - List::Element *tres_element = preferred.find("tres"); - if (tres_element) { - preferred.move_to_front(tres_element); - } if (!p_at_path.is_empty()) { file->set_current_dir(p_at_path); From c91c604eaa66d2307d13655ce513392e3bae77d6 Mon Sep 17 00:00:00 2001 From: Nazarii Date: Tue, 14 Jan 2025 19:35:42 +0200 Subject: [PATCH 05/91] Use AHashMap for RBMap nodes and HashMap input_activity --- scene/animation/animation_blend_tree.h | 2 +- scene/animation/animation_tree.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index 36a391ebdbde..1b3d7f236e39 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -410,7 +410,7 @@ class AnimationNodeBlendTree : public AnimationRootNode { Vector connections; }; - RBMap nodes; + AHashMap nodes; Vector2 graph_offset; diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index 5ac24b498577..d5b1d4ea460b 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -306,8 +306,8 @@ class AnimationTree : public AnimationMixer { uint64_t last_pass = 0; real_t activity = 0.0; }; - mutable HashMap> input_activity_map; - mutable HashMap *> input_activity_map_get; + mutable AHashMap> input_activity_map; + mutable AHashMap *> input_activity_map_get; NodePath animation_player; From 8fd71e6b17811cfdd7cc222c97eff4f81edcf4c5 Mon Sep 17 00:00:00 2001 From: Lars Pettersson Date: Fri, 13 Dec 2024 15:49:15 +0100 Subject: [PATCH 06/91] Fix default `AudioBusLayout` not loading correctly --- editor/editor_audio_buses.cpp | 64 ++++++++++------------------------- 1 file changed, 17 insertions(+), 47 deletions(-) diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index ae685a824b27..9881087b3e39 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -1265,41 +1265,11 @@ void EditorAudioBuses::_load_layout() { } void EditorAudioBuses::_load_default_layout() { - String layout_path = GLOBAL_GET("audio/buses/default_bus_layout"); - - Ref state; - if (ResourceLoader::exists(layout_path)) { - state = ResourceLoader::load(layout_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); - } - if (state.is_null()) { - EditorNode::get_singleton()->show_warning(vformat(TTR("There is no '%s' file."), layout_path)); - return; - } - - edited_path = layout_path; - file->set_text(String(TTR("Layout:")) + " " + layout_path.get_file()); - AudioServer::get_singleton()->set_bus_layout(state); - _rebuild_buses(); - EditorUndoRedoManager::get_singleton()->clear_history(EditorUndoRedoManager::GLOBAL_HISTORY); - callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); + open_layout(GLOBAL_GET("audio/buses/default_bus_layout")); } void EditorAudioBuses::_file_dialog_callback(const String &p_string) { - if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_OPEN_FILE) { - Ref state = ResourceLoader::load(p_string, "", ResourceFormatLoader::CACHE_MODE_IGNORE); - if (state.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout.")); - return; - } - - edited_path = p_string; - file->set_text(String(TTR("Layout:")) + " " + p_string.get_file()); - AudioServer::get_singleton()->set_bus_layout(state); - _rebuild_buses(); - EditorUndoRedoManager::get_singleton()->clear_history(EditorUndoRedoManager::GLOBAL_HISTORY); - callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); - - } else if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { + if (file_dialog->get_file_mode() == EditorFileDialog::FILE_MODE_SAVE_FILE) { if (new_layout) { Ref empty_state; empty_state.instantiate(); @@ -1307,18 +1277,12 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) { } Error err = ResourceSaver::save(AudioServer::get_singleton()->generate_bus_layout(), p_string); - if (err != OK) { EditorNode::get_singleton()->show_warning(vformat(TTR("Error saving file: %s"), p_string)); return; } - - edited_path = p_string; - file->set_text(String(TTR("Layout:")) + " " + p_string.get_file()); - _rebuild_buses(); - EditorUndoRedoManager::get_singleton()->clear_history(EditorUndoRedoManager::GLOBAL_HISTORY); - callable_mp(this, &EditorAudioBuses::_select_layout).call_deferred(); } + open_layout(p_string); } void EditorAudioBuses::_bind_methods() { @@ -1330,9 +1294,10 @@ EditorAudioBuses::EditorAudioBuses() { top_hb = memnew(HBoxContainer); add_child(top_hb); + edited_path = ResourceUID::ensure_path(GLOBAL_GET("audio/buses/default_bus_layout")); + file = memnew(Label); - String layout_path = GLOBAL_GET("audio/buses/default_bus_layout"); - file->set_text(String(TTR("Layout:")) + " " + layout_path.get_file()); + file->set_text(vformat("%s %s", TTR("Layout:"), edited_path.get_file())); file->set_clip_text(true); file->set_h_size_flags(SIZE_EXPAND_FILL); top_hb->add_child(file); @@ -1386,8 +1351,6 @@ EditorAudioBuses::EditorAudioBuses() { set_v_size_flags(SIZE_EXPAND_FILL); - edited_path = GLOBAL_GET("audio/buses/default_bus_layout"); - file_dialog = memnew(EditorFileDialog); List ext; ResourceLoader::get_recognized_extensions_for_type("AudioBusLayout", &ext); @@ -1405,14 +1368,21 @@ EditorAudioBuses::EditorAudioBuses() { void EditorAudioBuses::open_layout(const String &p_path) { EditorNode::get_bottom_panel()->make_item_visible(this); - Ref state = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); + const String path = ResourceUID::ensure_path(p_path); + + if (!ResourceLoader::exists(path)) { + EditorNode::get_singleton()->show_warning(vformat(TTR(R"(Can't open audio bus layout: "%s" doesn't exist.)"), path)); + return; + } + + Ref state = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_IGNORE); if (state.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("Invalid file, not an audio bus layout.")); + EditorNode::get_singleton()->show_warning(vformat(TTR(R"(Can't open audio bus layout: "%s" is not a valid audio bus layout.)"), path)); return; } - edited_path = p_path; - file->set_text(p_path.get_file()); + edited_path = path; + file->set_text(vformat("%s %s", TTR("Layout:"), path.get_file())); AudioServer::get_singleton()->set_bus_layout(state); _rebuild_buses(); EditorUndoRedoManager::get_singleton()->clear_history(EditorUndoRedoManager::GLOBAL_HISTORY); From f355c9ad371be28740f5e9732c2b84f3f918d4d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Fri, 17 Jan 2025 19:20:05 +0200 Subject: [PATCH 07/91] [iOS] Fix provisioning profile specifier / UUID validation. --- platform/ios/export/export_plugin.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index 3684089d09d8..4f5d2b48dedb 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -423,12 +423,12 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ bool dbg_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG).operator String().is_empty() || (dbg_sign_id != "iPhone Developer" && dbg_sign_id != "iPhone Distribution"); bool rel_manual = !p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE).operator String().is_empty() || (rel_sign_id != "iPhone Developer" && rel_sign_id != "iPhone Distribution"); - bool valid_dbg_specifier = false; - bool valid_rel_specifier = false; - Variant provisioning_profile_specifier_dbg_variant = p_preset->get_or_env("application/provisioning_profile_specifier_debug", ENV_IOS_PROFILE_SPECIFIER_DEBUG, &valid_dbg_specifier); + String provisioning_profile_specifier_dbg = p_preset->get_or_env("application/provisioning_profile_specifier_debug", ENV_IOS_PROFILE_SPECIFIER_DEBUG).operator String(); + bool valid_dbg_specifier = !provisioning_profile_specifier_dbg.is_empty(); dbg_manual |= valid_dbg_specifier; - Variant provisioning_profile_specifier_rel_variant = p_preset->get_or_env("application/provisioning_profile_specifier_release", ENV_IOS_PROFILE_SPECIFIER_RELEASE, &valid_rel_specifier); + String provisioning_profile_specifier_rel = p_preset->get_or_env("application/provisioning_profile_specifier_release", ENV_IOS_PROFILE_SPECIFIER_RELEASE).operator String(); + bool valid_rel_specifier = !provisioning_profile_specifier_rel.is_empty(); rel_manual |= valid_rel_specifier; String str; @@ -466,13 +466,11 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ int export_method = p_preset->get(p_debug ? "application/export_method_debug" : "application/export_method_release"); strnew += lines[i].replace("$export_method", export_method_string[export_method]) + "\n"; } else if (lines[i].contains("$provisioning_profile_specifier_debug")) { - String specifier = provisioning_profile_specifier_dbg_variant.get_type() != Variant::NIL ? provisioning_profile_specifier_dbg_variant : ""; - strnew += lines[i].replace("$provisioning_profile_specifier_debug", specifier) + "\n"; + strnew += lines[i].replace("$provisioning_profile_specifier_debug", provisioning_profile_specifier_dbg) + "\n"; } else if (lines[i].contains("$provisioning_profile_specifier_release")) { - String specifier = provisioning_profile_specifier_rel_variant.get_type() != Variant::NIL ? provisioning_profile_specifier_rel_variant : ""; - strnew += lines[i].replace("$provisioning_profile_specifier_release", specifier) + "\n"; + strnew += lines[i].replace("$provisioning_profile_specifier_release", provisioning_profile_specifier_rel) + "\n"; } else if (lines[i].contains("$provisioning_profile_specifier")) { - String specifier = p_debug ? provisioning_profile_specifier_dbg_variant : provisioning_profile_specifier_rel_variant; + String specifier = p_debug ? provisioning_profile_specifier_dbg : provisioning_profile_specifier_rel; strnew += lines[i].replace("$provisioning_profile_specifier", specifier) + "\n"; } else if (lines[i].contains("$provisioning_profile_uuid_release")) { strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE)) + "\n"; @@ -491,11 +489,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref &p_ strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n"; } } else if (lines[i].contains("$provisioning_profile_uuid")) { - bool valid = false; - String uuid = p_debug ? p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG, &valid) : p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE, &valid); - if (!valid || uuid.is_empty()) { - Variant variant = p_debug ? provisioning_profile_specifier_dbg_variant : provisioning_profile_specifier_rel_variant; - valid = p_debug ? valid_dbg_specifier : valid_rel_specifier; + String uuid = p_debug ? p_preset->get_or_env("application/provisioning_profile_uuid_debug", ENV_IOS_PROFILE_UUID_DEBUG) : p_preset->get_or_env("application/provisioning_profile_uuid_release", ENV_IOS_PROFILE_UUID_RELEASE); + if (uuid.is_empty()) { + Variant variant = p_debug ? provisioning_profile_specifier_dbg : provisioning_profile_specifier_rel; + bool valid = p_debug ? valid_dbg_specifier : valid_rel_specifier; uuid = valid ? variant : ""; } strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; From 0ceb992ffaf2f66e62f34bd35ac35b6d436a9b76 Mon Sep 17 00:00:00 2001 From: Chaosus Date: Sun, 19 Jan 2025 15:52:42 +0300 Subject: [PATCH 08/91] Fix incomplete FPS spinbox display in sprite frames editor --- editor/plugins/sprite_frames_editor_plugin.cpp | 6 ++++++ editor/plugins/sprite_frames_editor_plugin.h | 1 + 2 files changed, 7 insertions(+) diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 5cea634e6df8..2f45e3fedecd 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -1284,6 +1284,10 @@ void SpriteFramesEditor::_animation_loop_changed() { undo_redo->commit_action(); } +void SpriteFramesEditor::_animation_speed_resized() { + anim_speed->update_minimum_size(); +} + void SpriteFramesEditor::_animation_speed_changed(double p_value) { if (updating) { return; @@ -1970,6 +1974,8 @@ SpriteFramesEditor::SpriteFramesEditor() { anim_speed->set_step(0.01); anim_speed->set_custom_arrow_step(1); anim_speed->set_tooltip_text(TTR("Animation Speed")); + anim_speed->get_line_edit()->set_expand_to_text_length_enabled(true); + anim_speed->get_line_edit()->connect(SceneStringName(resized), callable_mp(this, &SpriteFramesEditor::_animation_speed_resized)); anim_speed->connect(SceneStringName(value_changed), callable_mp(this, &SpriteFramesEditor::_animation_speed_changed)); hbc_animlist->add_child(anim_speed); diff --git a/editor/plugins/sprite_frames_editor_plugin.h b/editor/plugins/sprite_frames_editor_plugin.h index 896294482c15..6e58a355a0a8 100644 --- a/editor/plugins/sprite_frames_editor_plugin.h +++ b/editor/plugins/sprite_frames_editor_plugin.h @@ -222,6 +222,7 @@ class SpriteFramesEditor : public HSplitContainer { void _animation_remove_confirmed(); void _animation_search_text_changed(const String &p_text); void _animation_loop_changed(); + void _animation_speed_resized(); void _animation_speed_changed(double p_value); void _frame_list_gui_input(const Ref &p_event); From 9e36c044ea1ac854dcb74c5c077846972216c238 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Sun, 19 Jan 2025 16:18:13 +0100 Subject: [PATCH 09/91] Fix resource details will unexpectedly expand --- editor/editor_resource_picker.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 00eb59fa76af..754afad9056a 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -1053,7 +1053,6 @@ void EditorResourcePicker::_duplicate_selected_resources() { EditorResourcePicker::EditorResourcePicker(bool p_hide_assign_button_controls) { assign_button = memnew(Button); assign_button->set_flat(true); - assign_button->set_action_mode(BaseButton::ACTION_MODE_BUTTON_PRESS); assign_button->set_h_size_flags(SIZE_EXPAND_FILL); assign_button->set_expand_icon(true); assign_button->set_clip_text(true); From 9030f76984427c5bd83471e67f348782d03e7d6d Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Mon, 20 Jan 2025 14:52:56 +0100 Subject: [PATCH 10/91] Fix Jolt note in WorldBoundaryShape3D documentation The dimensions are around the shape's origin, not the world origin (i.e. `(0, 0, 0)` in global coordinates). --- doc/classes/WorldBoundaryShape3D.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/classes/WorldBoundaryShape3D.xml b/doc/classes/WorldBoundaryShape3D.xml index 0f6224c40c85..0770dd51211e 100644 --- a/doc/classes/WorldBoundaryShape3D.xml +++ b/doc/classes/WorldBoundaryShape3D.xml @@ -5,7 +5,7 @@ A 3D world boundary shape, intended for use in physics. [WorldBoundaryShape3D] works like an infinite plane that forces all physics bodies to stay above it. The [member plane]'s normal determines which direction is considered as "above" and in the editor, the line over the plane represents this direction. It can for example be used for endless flat floors. - [b]Note:[/b] When the physics engine is set to [b]Jolt Physics[/b] in the project settings ([member ProjectSettings.physics/3d/physics_engine]), [WorldBoundaryShape3D] has a finite size (centered at the world origin). It can be adjusted by changing [member ProjectSettings.physics/jolt_physics_3d/limits/world_boundary_shape_size]. + [b]Note:[/b] When the physics engine is set to [b]Jolt Physics[/b] in the project settings ([member ProjectSettings.physics/3d/physics_engine]), [WorldBoundaryShape3D] has a finite size (centered at the shape's origin). It can be adjusted by changing [member ProjectSettings.physics/jolt_physics_3d/limits/world_boundary_shape_size]. From a5e8c266af11d5ef4cf714c2fb0b1ebe2fa1924e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Tue, 21 Jan 2025 08:37:08 +0200 Subject: [PATCH 11/91] [RTL] Fix `ready` signal sent too early in single threaded RTL. --- scene/gui/rich_text_label.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 87c7062f2cc4..6475dc50e8e7 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2914,7 +2914,6 @@ bool RichTextLabel::_find_layout_subitem(Item *from, Item *to) { void RichTextLabel::_thread_function(void *p_userdata) { set_current_thread_safe_for_nodes(true); _process_line_caches(); - updating.store(false); callable_mp(this, &RichTextLabel::_thread_end).call_deferred(); } @@ -3082,7 +3081,6 @@ bool RichTextLabel::_validate_line_caches() { } else { updating.store(true); _process_line_caches(); - updating.store(false); if (!scroll_visible) { vscroll->hide(); } @@ -3094,6 +3092,7 @@ bool RichTextLabel::_validate_line_caches() { void RichTextLabel::_process_line_caches() { // Shape invalid lines. if (!is_inside_tree()) { + updating.store(false); return; } @@ -3116,6 +3115,7 @@ void RichTextLabel::_process_line_caches() { main->first_invalid_font_line.store(i); if (stop_thread.load()) { + updating.store(false); return; } } @@ -3132,6 +3132,7 @@ void RichTextLabel::_process_line_caches() { main->first_resized_line.store(i); if (stop_thread.load()) { + updating.store(false); return; } } @@ -3147,6 +3148,7 @@ void RichTextLabel::_process_line_caches() { main->first_invalid_font_line.store(i); if (stop_thread.load()) { + updating.store(false); return; } loaded.store(double(i) / double(main->lines.size())); @@ -3155,6 +3157,7 @@ void RichTextLabel::_process_line_caches() { main->first_invalid_line.store(main->lines.size()); main->first_resized_line.store(main->lines.size()); main->first_invalid_font_line.store(main->lines.size()); + updating.store(false); if (fit_content) { update_minimum_size(); From aca5cfc91346371a60e42476af52a3a9fa6afde2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Wed, 8 Jan 2025 13:43:17 +0100 Subject: [PATCH 12/91] Rationalize parsing of file system cache --- editor/editor_file_system.cpp | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/editor/editor_file_system.cpp b/editor/editor_file_system.cpp index b8ce3ff65bf7..cd9c5048f3b3 100644 --- a/editor/editor_file_system.cpp +++ b/editor/editor_file_system.cpp @@ -383,33 +383,23 @@ void EditorFileSystem::_scan_filesystem() { name = cpath.path_join(name); FileCache fc; - fc.type = split[1]; - if (fc.type.contains_char('/')) { - fc.type = split[1].get_slice("/", 0); - fc.resource_script_class = split[1].get_slice("/", 1); - } + fc.type = split[1].get_slice("/", 0); + fc.resource_script_class = split[1].get_slice("/", 1); fc.uid = split[2].to_int(); fc.modification_time = split[3].to_int(); fc.import_modification_time = split[4].to_int(); fc.import_valid = split[5].to_int() != 0; fc.import_group_file = split[6].strip_edges(); - fc.script_class_name = split[7].get_slice("<>", 0); - fc.script_class_extends = split[7].get_slice("<>", 1); - fc.script_class_icon_path = split[7].get_slice("<>", 2); - fc.import_md5 = split[7].get_slice("<>", 3); - String dest_paths = split[7].get_slice("<>", 4); - if (!dest_paths.is_empty()) { - fc.import_dest_paths = dest_paths.split("<*>"); - } - - String deps = split[8].strip_edges(); - if (deps.length()) { - Vector dp = deps.split("<>"); - for (int i = 0; i < dp.size(); i++) { - const String &path = dp[i]; - fc.deps.push_back(path); - } + { + const Vector &slices = split[7].split("<>"); + ERR_CONTINUE(slices.size() < 5); + fc.script_class_name = slices[0]; + fc.script_class_extends = slices[1]; + fc.script_class_icon_path = slices[2]; + fc.import_md5 = slices[3]; + fc.import_dest_paths = slices[4].split("<*>"); } + fc.deps = split[8].strip_edges().split("<>"); file_cache[name] = fc; } From ce139f75773d3fb36dac8a620ddc5849240b64aa Mon Sep 17 00:00:00 2001 From: Mark DiBarry Date: Sun, 19 Jan 2025 13:29:06 -0500 Subject: [PATCH 13/91] Fix editor parallax grid snap movement --- scene/2d/parallax_2d.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scene/2d/parallax_2d.cpp b/scene/2d/parallax_2d.cpp index 5cb9bf45f785..f07a89df3d25 100644 --- a/scene/2d/parallax_2d.cpp +++ b/scene/2d/parallax_2d.cpp @@ -69,7 +69,9 @@ void Parallax2D::_notification(int p_what) { #ifdef TOOLS_ENABLED void Parallax2D::_edit_set_position(const Point2 &p_position) { - set_scroll_offset(p_position); + // Avoids early return for grid snap compatibility + scroll_offset = p_position; + _update_scroll(); } #endif // TOOLS_ENABLED From e9b164adf7942746052e135e921a6ca70bc0c667 Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Wed, 22 Jan 2025 13:42:30 +0100 Subject: [PATCH 14/91] Fix ColorPicker hide save/load swatches for pressets_visible --- scene/gui/color_picker.cpp | 16 +++++++++------- scene/gui/color_picker.h | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 6eb65a008cc8..9770669aa021 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -2038,8 +2038,7 @@ void ColorPicker::set_presets_visible(bool p_visible) { return; } presets_visible = p_visible; - btn_preset->set_visible(p_visible); - btn_recent_preset->set_visible(p_visible); + swatches_vbc->set_visible(p_visible); } bool ColorPicker::are_presets_visible() const { @@ -2348,6 +2347,9 @@ ColorPicker::ColorPicker() { _update_controls(); updating = false; + swatches_vbc = memnew(VBoxContainer); + real_vbox->add_child(swatches_vbc); + preset_container = memnew(GridContainer); preset_container->set_h_size_flags(SIZE_EXPAND_FILL); preset_container->set_columns(PRESET_COLUMN_COUNT); @@ -2357,7 +2359,7 @@ ColorPicker::ColorPicker() { HBoxContainer *palette_box = memnew(HBoxContainer); palette_box->set_h_size_flags(SIZE_EXPAND_FILL); - real_vbox->add_child(palette_box); + swatches_vbc->add_child(palette_box); btn_preset = memnew(Button); btn_preset->set_text("Swatches"); @@ -2382,9 +2384,9 @@ ColorPicker::ColorPicker() { palette_name = memnew(Label); palette_name->hide(); palette_name->set_mouse_filter(MOUSE_FILTER_PASS); - real_vbox->add_child(palette_name); + swatches_vbc->add_child(palette_name); - real_vbox->add_child(preset_container); + swatches_vbc->add_child(preset_container); recent_preset_hbc = memnew(HBoxContainer); recent_preset_hbc->set_v_size_flags(SIZE_SHRINK_BEGIN); @@ -2398,9 +2400,9 @@ ColorPicker::ColorPicker() { btn_recent_preset->set_focus_mode(FOCUS_NONE); btn_recent_preset->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT); btn_recent_preset->connect(SceneStringName(toggled), callable_mp(this, &ColorPicker::_show_hide_preset).bind(btn_recent_preset, recent_preset_hbc)); - real_vbox->add_child(btn_recent_preset); + swatches_vbc->add_child(btn_recent_preset); - real_vbox->add_child(recent_preset_hbc); + swatches_vbc->add_child(recent_preset_hbc); set_pick_color(Color(1, 1, 1)); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 7a689cc773a0..059cae51dd06 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -157,6 +157,7 @@ class ColorPicker : public VBoxContainer { Control *wheel = nullptr; Control *wheel_uv = nullptr; TextureRect *sample = nullptr; + VBoxContainer *swatches_vbc = nullptr; GridContainer *preset_container = nullptr; HBoxContainer *recent_preset_hbc = nullptr; Button *btn_add_preset = nullptr; From cdaeb3176463b67accfdba7752c263f56cba36e1 Mon Sep 17 00:00:00 2001 From: Yelloween <134299963+Yelloween10@users.noreply.github.com> Date: Wed, 22 Jan 2025 18:53:26 +0300 Subject: [PATCH 15/91] Fix Make Sub-Resources Unique shortcut focus --- editor/inspector_dock.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index dc2fc72a48b5..036c0eca9b6b 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -750,7 +750,6 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { object_menu = memnew(MenuButton); object_menu->set_flat(false); object_menu->set_theme_type_variation("FlatMenuButton"); - object_menu->set_shortcut_context(this); property_tools_hb->add_child(object_menu); object_menu->set_tooltip_text(TTR("Manage object properties.")); object_menu->get_popup()->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_menu)); From a36f0642040738106807ea29ccba4cced09976ba Mon Sep 17 00:00:00 2001 From: Giganzo <158825920+Giganzo@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:23:29 +0100 Subject: [PATCH 16/91] Fix ColorPicker load/save swatches button interactions --- scene/gui/color_picker.cpp | 25 +++++-------------------- scene/gui/color_picker.h | 3 +-- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 90b7b2b2b765..30fd62075bfd 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -1770,13 +1770,6 @@ void ColorPicker::_pick_finished() { } void ColorPicker::_update_menu_items() { - if (!options_menu) { - options_menu = memnew(PopupMenu); - add_child(options_menu, false, INTERNAL_MODE_FRONT); - options_menu->force_parent_owned(); - options_menu->connect("id_pressed", callable_mp(this, &ColorPicker::_options_menu_cbk)); - } - options_menu->clear(); options_menu->reset_size(); @@ -1802,16 +1795,6 @@ void ColorPicker::_update_menu_items() { } } -void ColorPicker::_update_menu() { - _update_menu_items(); - Rect2 gt = menu_btn->get_screen_rect(); - menu_btn->reset_size(); - int min_size = menu_btn->get_minimum_size().width; - Vector2 popup_pos = gt.get_end() - Vector2(min_size, 0); - options_menu->set_position(popup_pos); - options_menu->popup(); -} - void ColorPicker::_options_menu_cbk(int p_which) { if (!file_dialog) { file_dialog = memnew(FileDialog); @@ -2369,13 +2352,15 @@ ColorPicker::ColorPicker() { btn_preset->connect(SceneStringName(toggled), callable_mp(this, &ColorPicker::_show_hide_preset).bind(btn_preset, preset_container)); palette_box->add_child(btn_preset); - menu_btn = memnew(Button); + menu_btn = memnew(MenuButton); menu_btn->set_flat(true); menu_btn->set_tooltip_text(ETR("Show all options available.")); - menu_btn->set_focus_mode(FOCUS_NONE); - menu_btn->connect(SceneStringName(pressed), callable_mp(this, &ColorPicker::_update_menu)); + menu_btn->connect("about_to_popup", callable_mp(this, &ColorPicker::_update_menu_items)); palette_box->add_child(menu_btn); + options_menu = menu_btn->get_popup(); + options_menu->connect(SceneStringName(id_pressed), callable_mp(this, &ColorPicker::_options_menu_cbk)); + palette_name = memnew(Label); palette_name->hide(); palette_name->set_mouse_filter(MOUSE_FILTER_PASS); diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index 7a689cc773a0..531ce17c6087 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -144,7 +144,7 @@ class ColorPicker : public VBoxContainer { TextureRect *picker_texture_rect = nullptr; Color picker_color; FileDialog *file_dialog = nullptr; - Button *menu_btn = nullptr; + MenuButton *menu_btn = nullptr; PopupMenu *options_menu = nullptr; MarginContainer *internal_margin = nullptr; @@ -305,7 +305,6 @@ class ColorPicker : public VBoxContainer { void _target_gui_input(const Ref &p_event); void _pick_finished(); void _update_menu_items(); - void _update_menu(); void _options_menu_cbk(int p_which); // Legacy color picking. From 57700b056326c6e10fc50c692ebc7e45cdb941cc Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Mon, 5 Aug 2024 19:20:14 +0200 Subject: [PATCH 17/91] Make EditorSpinSlider display a slider for floats with a step of 1.0 Integers still don't display a slider (and use up/down arrows instead), so that they can be quickly distinguished from floats in the inspector. However, this now makes floats with a step of 1.0 look different from integers in the inspector. --- doc/classes/EditorSpinSlider.xml | 3 +++ editor/editor_properties.cpp | 1 + editor/gui/editor_spin_slider.cpp | 19 ++++++++++++++++++- editor/gui/editor_spin_slider.h | 4 ++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/classes/EditorSpinSlider.xml b/doc/classes/EditorSpinSlider.xml index 6cd375a46de9..b0b3f0faf76c 100644 --- a/doc/classes/EditorSpinSlider.xml +++ b/doc/classes/EditorSpinSlider.xml @@ -10,6 +10,9 @@ + + If [code]true[/code], the [EditorSpinSlider] is considered to be editing an integer value. If [code]false[/code], the [EditorSpinSlider] is considered to be editing a floating-point value. This is used to determine whether a slider should be drawn. The slider is only drawn for floats; integers use up-down arrows similar to [SpinBox] instead. + If [code]true[/code], the slider will not draw background. diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index b1a4bb76f325..73f6c70f3423 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -1343,6 +1343,7 @@ void EditorPropertyInteger::setup(int64_t p_min, int64_t p_max, int64_t p_step, EditorPropertyInteger::EditorPropertyInteger() { spin = memnew(EditorSpinSlider); spin->set_flat(true); + spin->set_editing_integer(true); add_child(spin); add_focusable(spin); spin->connect(SceneStringName(value_changed), callable_mp(this, &EditorPropertyInteger::_value_changed)); diff --git a/editor/gui/editor_spin_slider.cpp b/editor/gui/editor_spin_slider.cpp index cef23fdda1f1..a9d8e3ae6c6e 100644 --- a/editor/gui/editor_spin_slider.cpp +++ b/editor/gui/editor_spin_slider.cpp @@ -376,7 +376,7 @@ void EditorSpinSlider::_draw_spin_slider() { TS->free_rid(num_rid); if (!hide_slider) { - if (get_step() == 1) { + if (editing_integer) { Ref updown2 = read_only ? theme_cache.updown_disabled_icon : theme_cache.updown_icon; int updown_vofs = (size.height - updown2->get_height()) / 2; if (rtl) { @@ -530,6 +530,19 @@ bool EditorSpinSlider::is_hiding_slider() const { return hide_slider; } +void EditorSpinSlider::set_editing_integer(bool p_editing_integer) { + if (p_editing_integer == editing_integer) { + return; + } + + editing_integer = p_editing_integer; + queue_redraw(); +} + +bool EditorSpinSlider::is_editing_integer() const { + return editing_integer; +} + void EditorSpinSlider::set_label(const String &p_label) { label = p_label; queue_redraw(); @@ -689,11 +702,15 @@ void EditorSpinSlider::_bind_methods() { ClassDB::bind_method(D_METHOD("set_hide_slider", "hide_slider"), &EditorSpinSlider::set_hide_slider); ClassDB::bind_method(D_METHOD("is_hiding_slider"), &EditorSpinSlider::is_hiding_slider); + ClassDB::bind_method(D_METHOD("set_editing_integer", "editing_integer"), &EditorSpinSlider::set_editing_integer); + ClassDB::bind_method(D_METHOD("is_editing_integer"), &EditorSpinSlider::is_editing_integer); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "label"), "set_label", "get_label"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "suffix"), "set_suffix", "get_suffix"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "read_only"), "set_read_only", "is_read_only"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hide_slider"), "set_hide_slider", "is_hiding_slider"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "editing_integer"), "set_editing_integer", "is_editing_integer"); ADD_SIGNAL(MethodInfo("grabbed")); ADD_SIGNAL(MethodInfo("ungrabbed")); diff --git a/editor/gui/editor_spin_slider.h b/editor/gui/editor_spin_slider.h index dfc50878dd22..f3fe6e2145ea 100644 --- a/editor/gui/editor_spin_slider.h +++ b/editor/gui/editor_spin_slider.h @@ -71,6 +71,7 @@ class EditorSpinSlider : public Range { bool hide_slider = false; bool flat = false; + bool editing_integer = false; void _grab_start(); void _grab_end(); @@ -113,6 +114,9 @@ class EditorSpinSlider : public Range { void set_hide_slider(bool p_hide); bool is_hiding_slider() const; + void set_editing_integer(bool p_editing_integer); + bool is_editing_integer() const; + void set_read_only(bool p_enable); bool is_read_only() const; From c8087567c97adc09890dbb49d8abfde44378d8cb Mon Sep 17 00:00:00 2001 From: Riteo Date: Fri, 24 Jan 2025 15:10:46 +0100 Subject: [PATCH 18/91] Wayland: Check custom cursor resource reference for cache invalidation Images don't have RIDs and this way of checking stuff broke the cursor cache. Let's do like all other platforms and check the resource reference instead. --- platform/linuxbsd/wayland/display_server_wayland.cpp | 4 ++-- platform/linuxbsd/wayland/display_server_wayland.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 532eaa6bcf49..f9b34ff043bf 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -1033,7 +1033,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref &p_cursor HashMap::Iterator cursor_c = custom_cursors.find(p_shape); if (cursor_c) { - if (cursor_c->value.rid == p_cursor->get_rid() && cursor_c->value.hotspot == p_hotspot) { + if (cursor_c->value.resource == p_cursor && cursor_c->value.hotspot == p_hotspot) { // We have a cached cursor. Nice. wayland_thread.cursor_set_shape(p_shape); return; @@ -1049,7 +1049,7 @@ void DisplayServerWayland::cursor_set_custom_image(const Ref &p_cursor CustomCursor &cursor = custom_cursors[p_shape]; - cursor.rid = p_cursor->get_rid(); + cursor.resource = p_cursor; cursor.hotspot = p_hotspot; wayland_thread.cursor_shape_set_custom_image(p_shape, image, p_hotspot); diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index 8c3bac9c7e3b..43a8b01b3208 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -101,7 +101,7 @@ class DisplayServerWayland : public DisplayServer { }; struct CustomCursor { - RID rid; + Ref resource; Point2i hotspot; }; From 2c35077148312868e51b14547bc794ad568466cd Mon Sep 17 00:00:00 2001 From: havi05 Date: Sun, 5 Jan 2025 23:12:36 +0100 Subject: [PATCH 19/91] Itemlist - fix `text_overrun_behavior` --- scene/gui/item_list.cpp | 64 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 262d27264fff..f2598a2d1326 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -1201,7 +1201,7 @@ void ItemList::_notification(int p_what) { const int y = base_ofs.y + separators[i]; if (rtl && scroll_bar_v->is_visible()) { - draw_line(Vector2(theme_cache.panel_style->get_margin(SIDE_LEFT) * 2 + scroll_bar_v_min.width, y), Vector2(width + theme_cache.panel_style->get_margin(SIDE_LEFT) + scroll_bar_v_min.width, y), theme_cache.guide_color); + draw_line(Vector2(theme_cache.panel_style->get_margin(SIDE_LEFT) + scroll_bar_v_min.width, y), Vector2(width + theme_cache.panel_style->get_margin(SIDE_LEFT) + scroll_bar_v_min.width, y), theme_cache.guide_color); } else { draw_line(Vector2(theme_cache.panel_style->get_margin(SIDE_LEFT), y), Vector2(width + theme_cache.panel_style->get_margin(SIDE_LEFT), y), theme_cache.guide_color); } @@ -1358,16 +1358,7 @@ void ItemList::_notification(int p_what) { } if (!items[i].text.is_empty()) { - int max_len = -1; - Vector2 size2 = items[i].text_buf->get_size(); - if (fixed_column_width) { - max_len = fixed_column_width; - } else if (same_column_width) { - max_len = items[i].rect_cache.size.x; - } else { - max_len = size2.x; - } Color txt_modulate; if (items[i].selected && hovered == i) { @@ -1392,15 +1383,18 @@ void ItemList::_notification(int p_what) { text_ofs.y += MAX(theme_cache.v_separation, 0) / 2; - if (rtl) { - text_ofs.x = size.width - text_ofs.x - max_len; - } - items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_CENTER); float text_w = items[i].rect_cache.size.width; + if (wraparound_items && items[i].rect_cache.size.width > width) { + text_w -= items[i].rect_cache.size.width - width; + } items.write[i].text_buf->set_width(text_w); + if (rtl) { + text_ofs.x = size.width - text_ofs.x - text_w; + } + if (theme_cache.font_outline_size > 0 && theme_cache.font_outline_color.a > 0) { items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color); } @@ -1423,11 +1417,17 @@ void ItemList::_notification(int p_what) { text_ofs += base_ofs; text_ofs += items[i].rect_cache.position; - float text_w = width - text_ofs.x + theme_cache.panel_style->get_margin(SIDE_LEFT); + float text_w = items[i].rect_cache.size.width - (items[i].get_icon_size().x * icon_scale) - MAX(theme_cache.h_separation, 0); + if (wraparound_items && items[i].rect_cache.size.width > width) { + text_w -= items[i].rect_cache.size.width - width; + } items.write[i].text_buf->set_width(text_w); if (rtl) { - text_ofs.x = size.width - width - theme_cache.panel_style->get_margin(SIDE_RIGHT); + text_ofs.x = size.width - items[i].rect_cache.size.width + (items[i].get_icon_size().x * icon_scale) - text_ofs.x + MAX(theme_cache.h_separation, 0); + if (wraparound_items) { + text_ofs.x += MAX(items[i].rect_cache.size.width - width, 0); + } items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_RIGHT); } else { items.write[i].text_buf->set_alignment(HORIZONTAL_ALIGNMENT_LEFT); @@ -1437,12 +1437,16 @@ void ItemList::_notification(int p_what) { items[i].text_buf->draw_outline(get_canvas_item(), text_ofs, theme_cache.font_outline_size, theme_cache.font_outline_color); } - if (rtl) { - if (width - items[i].rect_cache.position.x - (MAX(theme_cache.h_separation, 0) / 2) - int(scroll_bar_h->get_value()) > 0) { + if (fixed_column_width > 0) { + if (items[i].rect_cache.size.width - (items[i].get_icon_size().x * icon_scale) - MAX(theme_cache.h_separation, 0) > 0) { items[i].text_buf->draw(get_canvas_item(), text_ofs, txt_modulate); } } else { - if (width - text_ofs.x + theme_cache.panel_style->get_margin(SIDE_LEFT) > 0) { + if (wraparound_items) { + if (width - (items[i].get_icon_size().x * icon_scale) - MAX(theme_cache.h_separation, 0) - int(scroll_bar_h->get_value()) > 0) { + items[i].text_buf->draw(get_canvas_item(), text_ofs, txt_modulate); + } + } else { items[i].text_buf->draw(get_canvas_item(), text_ofs, txt_modulate); } } @@ -1506,8 +1510,6 @@ void ItemList::force_update_list_size() { int max_width = -1; if (fixed_column_width) { max_width = fixed_column_width; - } else if (same_column_width) { - max_width = items[i].rect_cache.size.x; } items.write[i].text_buf->set_width(max_width); Size2 s = items[i].text_buf->get_size(); @@ -1595,13 +1597,12 @@ void ItemList::force_update_list_size() { } } - Size2 scroll_bar_v_min = scroll_bar_v->is_visible() ? scroll_bar_v->get_combined_minimum_size() : Size2(); float scroll_bar_v_page = MAX(0, size.height - theme_cache.panel_style->get_minimum_size().height); float scroll_bar_v_max = MAX(scroll_bar_v_page, ofs.y + max_h); float scroll_bar_h_page = MAX(0, size.width - theme_cache.panel_style->get_minimum_size().width); float scroll_bar_h_max = 0; if (!wraparound_items) { - scroll_bar_h_max = MAX(scroll_bar_h_page, max_w) - scroll_bar_v_min.width; + scroll_bar_h_max = MAX(scroll_bar_h_page, max_w); } if (scroll_bar_v_page >= scroll_bar_v_max || is_layout_rtl()) { @@ -1626,7 +1627,6 @@ void ItemList::force_update_list_size() { scroll_bar_v->hide(); } else { auto_width_value += scroll_bar_v_minwidth; - scroll_bar_h_max += scroll_bar_v_minwidth; scroll_bar_v->show(); if (do_autoscroll_to_bottom) { @@ -1634,7 +1634,7 @@ void ItemList::force_update_list_size() { } } - if (is_layout_rtl()) { + if (is_layout_rtl() && !wraparound_items) { scroll_bar_h->set_max(scroll_bar_h_page); scroll_bar_h->set_min(-(scroll_bar_h_max - scroll_bar_h_page)); } else { @@ -1692,7 +1692,7 @@ int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const { pos.x += scroll_bar_h->get_value(); if (is_layout_rtl()) { - pos.x = get_size().width - pos.x - theme_cache.panel_style->get_margin(SIDE_LEFT) - theme_cache.panel_style->get_margin(SIDE_RIGHT); + pos.x = get_size().width - pos.x - scroll_bar_h->get_value() - theme_cache.panel_style->get_margin(SIDE_LEFT) - theme_cache.panel_style->get_margin(SIDE_RIGHT); } int closest = -1; @@ -1701,8 +1701,16 @@ int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const { for (int i = 0; i < items.size(); i++) { Rect2 rc = items[i].rect_cache; - if (i % current_columns == current_columns - 1 && wraparound_items) { - rc.size.width = get_size().width - rc.position.x; // Make sure you can still select the last item when clicking past the column. + if (i % current_columns == current_columns - 1) { // Make sure you can still select the last item when clicking past the column. + if (is_layout_rtl()) { + rc.size.width = get_size().width - scroll_bar_h->get_value() + rc.position.x; + } else { + rc.size.width = get_size().width + scroll_bar_h->get_value() - rc.position.x; + } + } + + if (rc.size.x < 0) { + continue; // Skip negative item sizes, because they are off screen. } if (rc.has_point(pos)) { From f380b003519a6c297aff8d393bf47dc55bff1bcf Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Sat, 25 Jan 2025 17:35:00 +0100 Subject: [PATCH 20/91] Override mass properties for `Area3D` when using Jolt Physics --- modules/jolt_physics/objects/jolt_area_3d.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/jolt_physics/objects/jolt_area_3d.cpp b/modules/jolt_physics/objects/jolt_area_3d.cpp index eeaeca0faa1e..145f18667e7d 100644 --- a/modules/jolt_physics/objects/jolt_area_3d.cpp +++ b/modules/jolt_physics/objects/jolt_area_3d.cpp @@ -92,6 +92,9 @@ void JoltArea3D::_add_to_space() { jolt_settings->mMotionType = _get_motion_type(); jolt_settings->mIsSensor = true; jolt_settings->mUseManifoldReduction = false; + jolt_settings->mOverrideMassProperties = JPH::EOverrideMassProperties::MassAndInertiaProvided; + jolt_settings->mMassPropertiesOverride.mMass = 1.0f; + jolt_settings->mMassPropertiesOverride.mInertia = JPH::Mat44::sIdentity(); if (JoltProjectSettings::areas_detect_static_bodies()) { jolt_settings->mCollideKinematicVsNonDynamic = true; From 998e3dfcf7ec1fb6aaede9a7e1cc5618550a111f Mon Sep 17 00:00:00 2001 From: Malcolm Anderson Date: Fri, 24 Jan 2025 15:56:54 -0800 Subject: [PATCH 21/91] Update the app bundle's creation time to match the build time on macOS Co-authored-by: bruvzg <7645683+bruvzg@users.noreply.github.com> --- platform/macos/SCsub | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/macos/SCsub b/platform/macos/SCsub index 429cec22344e..9efb1a66b289 100644 --- a/platform/macos/SCsub +++ b/platform/macos/SCsub @@ -33,7 +33,16 @@ def generate_bundle(target, source, env): templ = Dir("#misc/dist/macos_tools.app").abspath if os.path.exists(app_dir): shutil.rmtree(app_dir) - shutil.copytree(templ, app_dir, ignore=shutil.ignore_patterns("Contents/Info.plist")) + + # Create the .app bundle directory itself from scratch so that the creation + # date is accurate, but copy the rest of the template over. + os.mkdir(app_dir) + shutil.copytree( + os.path.join(templ, "Contents"), + os.path.join(app_dir, "Contents"), + ignore=shutil.ignore_patterns("Info.plist"), + ) + if not os.path.isdir(app_dir + "/Contents/MacOS"): os.mkdir(app_dir + "/Contents/MacOS") if target_bin != "": @@ -66,6 +75,7 @@ def generate_bundle(target, source, env): sign_command += [Dir("#misc/dist/macos").abspath + "/editor.entitlements"] sign_command += [app_dir] subprocess.run(sign_command) + else: # Template bundle. app_prefix = "godot." + env["platform"] From 922642440132bf7b070a16240c3a21d119584403 Mon Sep 17 00:00:00 2001 From: kobewi Date: Sat, 18 Jan 2025 20:27:51 +0100 Subject: [PATCH 22/91] Fix inspector jumping when gaining focus --- doc/classes/EditorInspector.xml | 1 - editor/editor_inspector.cpp | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/classes/EditorInspector.xml b/doc/classes/EditorInspector.xml index 0bbd55f00757..644cbe5b5817 100644 --- a/doc/classes/EditorInspector.xml +++ b/doc/classes/EditorInspector.xml @@ -51,7 +51,6 @@ - diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 3f3b06b428a6..b79d1243ba6c 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -2996,6 +2996,7 @@ void EditorInspector::update_tree() { int current_focusable = -1; // Temporarily disable focus following on the root inspector to avoid jumping while the inspector is updating. + bool was_following = get_root_inspector()->is_following_focus(); get_root_inspector()->set_follow_focus(false); if (property_focusable != -1) { @@ -3024,7 +3025,7 @@ void EditorInspector::update_tree() { _clear(!object); if (!object) { - get_root_inspector()->set_follow_focus(true); + get_root_inspector()->set_follow_focus(was_following); return; } @@ -3890,7 +3891,7 @@ void EditorInspector::update_tree() { EditorNode::get_singleton()->hide_unused_editors(); } - get_root_inspector()->set_follow_focus(true); + get_root_inspector()->set_follow_focus(was_following); } void EditorInspector::update_property(const String &p_prop) { @@ -4742,6 +4743,15 @@ void EditorInspector::_notification(int p_what) { update_tree(); } } break; + + case NOTIFICATION_FOCUS_ENTER: { + set_follow_focus(true); + } break; + + case NOTIFICATION_FOCUS_EXIT: { + // Don't follow focus when the inspector is not focused. Prevents potential jumping when gaining focus. + set_follow_focus(false); + } break; } } @@ -4898,7 +4908,6 @@ EditorInspector::EditorInspector() { base_vbox->add_child(main_vbox); set_horizontal_scroll_mode(SCROLL_MODE_DISABLED); - set_follow_focus(true); changing = 0; search_box = nullptr; From 6df21a8fdcb9a54e62e385f218189aaa086a98e5 Mon Sep 17 00:00:00 2001 From: Anish Mishra Date: Sat, 25 Jan 2025 00:07:20 +0530 Subject: [PATCH 23/91] Android: Keep swipe-to-dismiss disabled by default --- .../doc_classes/EditorExportPlatformAndroid.xml | 9 +++++---- platform/android/export/export_plugin.cpp | 12 ++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/platform/android/doc_classes/EditorExportPlatformAndroid.xml b/platform/android/doc_classes/EditorExportPlatformAndroid.xml index 4c9e6630b647..7f2c825dcf8e 100644 --- a/platform/android/doc_classes/EditorExportPlatformAndroid.xml +++ b/platform/android/doc_classes/EditorExportPlatformAndroid.xml @@ -44,6 +44,11 @@ Path to an APK file to use as a custom export template for release exports. If left empty, default template is used. [b]Note:[/b] This is only used if [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] is disabled. + + If [code]true[/code], [url=https://developer.android.com/design/ui/wear/guides/components/swipe-to-dismiss]Swipe to dismiss[/url] will be enabled. + This functionality is intended for smartwatches and is generally ignored on standard Android devices. However, some devices may not ignore it. Therefore, it is recommended to keep this feature disabled for standard Android apps to avoid unexpected behavior. + [b]Note:[/b] This is [code]false[/code] by default. To enable this behavior, [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] is required. + Path to a ZIP file holding the source for the export template used in a Gradle build. If left empty, the default template is used. @@ -615,10 +620,6 @@ Application version visible to the user. Falls back to [member ProjectSettings.application/config/version] if left empty. - - If [code]true[/code], [url=https://developer.android.com/design/ui/wear/guides/components/swipe-to-dismiss]Swipe to dismiss[/url] will be enabled on Wear OS. - [b]Note:[/b] This is [code]true[/code] by default. To disable this behavior, [member EditorExportPlatformAndroid.gradle_build/use_gradle_build] is required. - The extended reality (XR) mode for this application. diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index c6991d777ea3..679e31494b74 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -1005,7 +1005,7 @@ void EditorExportPlatformAndroid::_write_tmp_manifest(const Ref &p_preset) { const String themes_xml_path = ExportTemplateManager::get_android_build_directory(p_preset).path_join("res/values/themes.xml"); - bool enable_swipe_to_dismiss = p_preset->get("wear_os/swipe_to_dismiss"); + bool enable_swipe_to_dismiss = p_preset->get("gesture/swipe_to_dismiss"); if (!FileAccess::exists(themes_xml_path)) { print_error("res/values/themes.xml does not exist."); @@ -1850,10 +1850,10 @@ String EditorExportPlatformAndroid::get_export_option_warning(const EditorExport if (!is_package_name_valid(pn, &pn_err)) { return TTR("Invalid package name:") + " " + pn_err; } - } else if (p_name == "wear_os/swipe_to_dismiss") { + } else if (p_name == "gesture/swipe_to_dismiss") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); - if (!bool(p_preset->get("wear_os/swipe_to_dismiss")) && !gradle_build_enabled) { - return TTR("\"Use Gradle Build\" must be enabled to disable \"Swipe to dismiss\"."); + if (bool(p_preset->get("gesture/swipe_to_dismiss")) && !gradle_build_enabled) { + return TTR("\"Use Gradle Build\" is required to enable \"Swipe to dismiss\"."); } } else if (p_name == "gradle_build/use_gradle_build") { bool gradle_build_enabled = p_preset->get("gradle_build/use_gradle_build"); @@ -2000,7 +2000,7 @@ void EditorExportPlatformAndroid::get_export_options(List *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "xr_features/xr_mode", PROPERTY_HINT_ENUM, "Regular,OpenXR"), XR_MODE_REGULAR, false, true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "wear_os/swipe_to_dismiss"), true)); + r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "gesture/swipe_to_dismiss"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/immersive_mode"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "screen/support_small"), true)); @@ -2039,7 +2039,7 @@ bool EditorExportPlatformAndroid::get_export_option_visibility(const EditorExpor p_option == "package/exclude_from_recents" || p_option == "package/show_in_app_library" || p_option == "package/show_as_launcher_app" || - p_option == "wear_os/swipe_to_dismiss" || + p_option == "gesture/swipe_to_dismiss" || p_option == "apk_expansion/enable" || p_option == "apk_expansion/SALT" || p_option == "apk_expansion/public_key") { From cb7085340ef583d324a0c6436a39266ad9707a0f Mon Sep 17 00:00:00 2001 From: "Silc Lizard (Tokage) Renew" <61938263+TokageItLab@users.noreply.github.com> Date: Sun, 26 Jan 2025 00:57:37 +0900 Subject: [PATCH 24/91] Add saving flag hack to Skeleton and revert reset timing of animation --- editor/editor_node.cpp | 6 ++---- scene/3d/retarget_modifier_3d.cpp | 6 ------ scene/3d/retarget_modifier_3d.h | 4 ++++ scene/3d/skeleton_3d.cpp | 18 ++++++++++++++++-- scene/3d/skeleton_3d.h | 4 ++++ scene/3d/skeleton_modifier_3d.h | 4 ++++ scene/3d/spring_bone_collision_3d.cpp | 10 ---------- scene/3d/spring_bone_collision_3d.h | 3 --- scene/3d/spring_bone_simulator_3d.cpp | 13 +++++++++++++ scene/3d/spring_bone_simulator_3d.h | 8 ++++++++ 10 files changed, 51 insertions(+), 25 deletions(-) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4b7abdf2b072..cbb691d1ecc0 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1913,14 +1913,12 @@ void EditorNode::_save_scene(String p_file, int idx) { return; } - List>> anim_backups; - _reset_animation_mixers(scene, &anim_backups); - scene->propagate_notification(NOTIFICATION_EDITOR_PRE_SAVE); editor_data.apply_changes_in_editors(); save_default_environment(); - + List>> anim_backups; + _reset_animation_mixers(scene, &anim_backups); _save_editor_states(p_file, idx); Ref sdata; diff --git a/scene/3d/retarget_modifier_3d.cpp b/scene/3d/retarget_modifier_3d.cpp index f40af5dfd268..9b070b8d1409 100644 --- a/scene/3d/retarget_modifier_3d.cpp +++ b/scene/3d/retarget_modifier_3d.cpp @@ -465,12 +465,6 @@ void RetargetModifier3D::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { _update_child_skeletons(); } break; -#ifdef TOOLS_ENABLED - case NOTIFICATION_EDITOR_PRE_SAVE: { - _reset_child_skeleton_poses(); - _force_update_child_skeletons(); - } break; -#endif // TOOLS_ENABLED case NOTIFICATION_EXIT_TREE: { _reset_child_skeletons(); } break; diff --git a/scene/3d/retarget_modifier_3d.h b/scene/3d/retarget_modifier_3d.h index f3c46cffde69..07bc60a21355 100644 --- a/scene/3d/retarget_modifier_3d.h +++ b/scene/3d/retarget_modifier_3d.h @@ -117,6 +117,10 @@ class RetargetModifier3D : public SkeletonModifier3D { void set_profile(Ref p_profile); Ref get_profile() const; +#ifdef TOOLS_ENABLED + virtual bool is_processed_on_saving() const override { return true; } +#endif + RetargetModifier3D(); virtual ~RetargetModifier3D(); }; diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index bf3022fd6a21..3fd77d4641a7 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -327,8 +327,10 @@ void Skeleton3D::_notification(int p_what) { } break; #ifdef TOOLS_ENABLED case NOTIFICATION_EDITOR_PRE_SAVE: { - force_update_all_dirty_bones(); - emit_signal(SceneStringName(skeleton_updated)); + saving = true; + } break; + case NOTIFICATION_EDITOR_POST_SAVE: { + saving = false; } break; #endif // TOOLS_ENABLED case NOTIFICATION_UPDATE_SKELETON: { @@ -940,6 +942,13 @@ void Skeleton3D::_make_dirty() { void Skeleton3D::_update_deferred(UpdateFlag p_update_flag) { if (is_inside_tree()) { +#ifdef TOOLS_ENABLED + if (saving) { + update_flags |= p_update_flag; + _notification(NOTIFICATION_UPDATE_SKELETON); + return; + } +#endif //TOOLS_ENABLED if (update_flags == UPDATE_FLAG_NONE && !updating) { notify_deferred_thread_group(NOTIFICATION_UPDATE_SKELETON); // It must never be called more than once in a single frame. } @@ -1165,6 +1174,11 @@ void Skeleton3D::_process_modifiers() { if (!mod) { continue; } +#ifdef TOOLS_ENABLED + if (saving && !mod->is_processed_on_saving()) { + continue; + } +#endif //TOOLS_ENABLED real_t influence = mod->get_influence(); if (influence < 1.0) { LocalVector old_poses; diff --git a/scene/3d/skeleton_3d.h b/scene/3d/skeleton_3d.h index 09ed303f33c8..5b91b50cb99e 100644 --- a/scene/3d/skeleton_3d.h +++ b/scene/3d/skeleton_3d.h @@ -66,6 +66,10 @@ class SkinReference : public RefCounted { class Skeleton3D : public Node3D { GDCLASS(Skeleton3D, Node3D); +#ifdef TOOLS_ENABLED + bool saving = false; +#endif //TOOLS_ENABLED + #ifndef DISABLE_DEPRECATED bool animate_physical_bones = true; Node *simulator = nullptr; diff --git a/scene/3d/skeleton_modifier_3d.h b/scene/3d/skeleton_modifier_3d.h index 86e9d9a67aa5..c7106cb06a50 100644 --- a/scene/3d/skeleton_modifier_3d.h +++ b/scene/3d/skeleton_modifier_3d.h @@ -91,6 +91,10 @@ class SkeletonModifier3D : public Node3D { static Vector3 get_vector_from_axis(Vector3::Axis p_axis); static Vector3::Axis get_axis_from_bone_axis(BoneAxis p_axis); +#ifdef TOOLS_ENABLED + virtual bool is_processed_on_saving() const { return false; } +#endif + SkeletonModifier3D(); }; diff --git a/scene/3d/spring_bone_collision_3d.cpp b/scene/3d/spring_bone_collision_3d.cpp index 25ad37fecadd..76ea1a373d39 100644 --- a/scene/3d/spring_bone_collision_3d.cpp +++ b/scene/3d/spring_bone_collision_3d.cpp @@ -180,13 +180,3 @@ Vector3 SpringBoneCollision3D::collide(const Transform3D &p_center, float p_bone Vector3 SpringBoneCollision3D::_collide(const Transform3D &p_center, float p_bone_radius, float p_bone_length, const Vector3 &p_current) const { return Vector3(0, 0, 0); } - -#ifdef TOOLS_ENABLED -void SpringBoneCollision3D::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_EDITOR_PRE_SAVE: { - sync_pose(); - } break; - } -} -#endif // TOOLS_ENABLED diff --git a/scene/3d/spring_bone_collision_3d.h b/scene/3d/spring_bone_collision_3d.h index 713891e04d51..31676ba5257b 100644 --- a/scene/3d/spring_bone_collision_3d.h +++ b/scene/3d/spring_bone_collision_3d.h @@ -47,9 +47,6 @@ class SpringBoneCollision3D : public Node3D { void _validate_property(PropertyInfo &p_property) const; static void _bind_methods(); -#ifdef TOOLS_ENABLED - virtual void _notification(int p_what); -#endif // TOOLS_ENABLED virtual Vector3 _collide(const Transform3D &p_center, float p_bone_radius, float p_bone_length, const Vector3 &p_current) const; diff --git a/scene/3d/spring_bone_simulator_3d.cpp b/scene/3d/spring_bone_simulator_3d.cpp index dfec87a28c20..6ceacd695a74 100644 --- a/scene/3d/spring_bone_simulator_3d.cpp +++ b/scene/3d/spring_bone_simulator_3d.cpp @@ -397,6 +397,12 @@ void SpringBoneSimulator3D::_notification(int p_what) { case NOTIFICATION_LOCAL_TRANSFORM_CHANGED: { update_gizmos(); } break; + case NOTIFICATION_EDITOR_PRE_SAVE: { + saving = true; + } break; + case NOTIFICATION_EDITOR_POST_SAVE: { + saving = false; + } break; #endif // TOOLS_ENABLED } } @@ -1467,6 +1473,13 @@ void SpringBoneSimulator3D::_process_modification() { } _find_collisions(); _process_collisions(); + +#ifdef TOOLS_ENABLED + if (saving) { + return; // Collision position has been reset but we don't want to process simulating on saving. Abort. + } +#endif //TOOLS_ENABLED + double delta = skeleton->get_modifier_callback_mode_process() == Skeleton3D::MODIFIER_CALLBACK_MODE_PROCESS_IDLE ? skeleton->get_process_delta_time() : skeleton->get_physics_process_delta_time(); for (int i = 0; i < settings.size(); i++) { _init_joints(skeleton, settings[i]); diff --git a/scene/3d/spring_bone_simulator_3d.h b/scene/3d/spring_bone_simulator_3d.h index 5db2e3bfc006..ade2b6405135 100644 --- a/scene/3d/spring_bone_simulator_3d.h +++ b/scene/3d/spring_bone_simulator_3d.h @@ -36,6 +36,10 @@ class SpringBoneSimulator3D : public SkeletonModifier3D { GDCLASS(SpringBoneSimulator3D, SkeletonModifier3D); +#ifdef TOOLS_ENABLED + bool saving = false; +#endif //TOOLS_ENABLED + bool joints_dirty = false; LocalVector collisions; // To process collisions for sync position with skeleton. @@ -274,6 +278,10 @@ class SpringBoneSimulator3D : public SkeletonModifier3D { // To process manually. void reset(); + +#ifdef TOOLS_ENABLED + virtual bool is_processed_on_saving() const override { return true; } +#endif }; VARIANT_ENUM_CAST(SpringBoneSimulator3D::BoneDirection); From fddf30d028d68bfdc840fa1df55c4b4c38570301 Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Mon, 27 Jan 2025 17:32:27 +0100 Subject: [PATCH 25/91] Fix patch PCKs incorrectly marking imported resources for removal --- editor/export/editor_export_platform.cpp | 78 ++++++++++++------------ 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index b931e6feba29..8b44a6f88ab0 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -50,6 +50,26 @@ #include "scene/resources/image_texture.h" #include "scene/resources/packed_scene.h" +class EditorExportSaveProxy { + HashSet saved_paths; + EditorExportPlatform::EditorExportSaveFunction save_func; + bool tracking_saves = false; + +public: + bool has_saved(const String &p_path) const { return saved_paths.has(p_path); } + + Error save_file(void *p_userdata, const String &p_path, const Vector &p_data, int p_file, int p_total, const Vector &p_enc_in_filters, const Vector &p_enc_ex_filters, const Vector &p_key, uint64_t p_seed) { + if (tracking_saves) { + saved_paths.insert(p_path.simplify_path().trim_prefix("res://")); + } + + return save_func(p_userdata, p_path, p_data, p_file, p_total, p_enc_in_filters, p_enc_ex_filters, p_key, p_seed); + } + + EditorExportSaveProxy(EditorExportPlatform::EditorExportSaveFunction p_save_func, bool p_track_saves) : + save_func(p_save_func), tracking_saves(p_track_saves) {} +}; + static int _get_pad(int p_alignment, int p_n) { int rest = p_n % p_alignment; int pad = 0; @@ -60,17 +80,6 @@ static int _get_pad(int p_alignment, int p_n) { return pad; } -template -static bool _has_pack_path(const T &p_paths, const String &p_path) { - for (const String &E : p_paths) { - if (E.simplify_path().trim_prefix("res://") == p_path) { - return true; - } - } - - return false; -} - #define PCK_PADDING 16 bool EditorExportPlatform::fill_log_messages(RichTextLabel *p_log, Error p_err) { @@ -1140,9 +1149,10 @@ Error EditorExportPlatform::export_project_files(const Ref & } } + EditorExportSaveProxy save_proxy(p_save_func, p_remove_func != nullptr); + Error err = OK; Vector> export_plugins = EditorExport::get_singleton()->get_export_plugins(); - Vector extra_paths; struct SortByName { bool operator()(const Ref &left, const Ref &right) const { @@ -1163,12 +1173,10 @@ Error EditorExportPlatform::export_project_files(const Ref & } } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - err = p_save_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, 0, paths.size(), enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } - - extra_paths.push_back(export_plugins[i]->extra_files[j].path); } export_plugins.write[i]->_clear(); @@ -1281,7 +1289,7 @@ Error EditorExportPlatform::export_project_files(const Ref & } for (int j = 0; j < export_plugins[i]->extra_files.size(); j++) { - err = p_save_func(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, export_plugins[i]->extra_files[j].path, export_plugins[i]->extra_files[j].data, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1290,8 +1298,6 @@ Error EditorExportPlatform::export_project_files(const Ref & path_remaps.push_back(path); path_remaps.push_back(export_plugins[i]->extra_files[j].path); } - - extra_paths.push_back(export_plugins[i]->extra_files[j].path); } if (export_plugins[i]->skipped) { @@ -1313,7 +1319,7 @@ Error EditorExportPlatform::export_project_files(const Ref & if (importer_type == "keep") { // Just keep file as-is. Vector array = FileAccess::get_file_as_bytes(path); - err = p_save_func(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; @@ -1356,13 +1362,13 @@ Error EditorExportPlatform::export_project_files(const Ref & sarr.resize(cs.size()); memcpy(sarr.ptrw(), cs.ptr(), sarr.size()); - err = p_save_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } // Now actual remapped file: sarr = FileAccess::get_file_as_bytes(export_path); - err = p_save_func(p_udata, export_path, sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, export_path, sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1392,14 +1398,14 @@ Error EditorExportPlatform::export_project_files(const Ref & if (remap == "path") { String remapped_path = config->get_value("remap", remap); Vector array = FileAccess::get_file_as_bytes(remapped_path); - err = p_save_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); } else if (remap.begins_with("path.")) { String feature = remap.get_slice(".", 1); if (remap_features.has(feature)) { String remapped_path = config->get_value("remap", remap); Vector array = FileAccess::get_file_as_bytes(remapped_path); - err = p_save_func(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, remapped_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); } else { // Remove paths if feature not enabled. config->erase_section_key("remap", remap); @@ -1425,7 +1431,7 @@ Error EditorExportPlatform::export_project_files(const Ref & sarr.resize(cs.size()); memcpy(sarr.ptrw(), cs.ptr(), sarr.size()); - err = p_save_func(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, path + ".import", sarr, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; @@ -1446,7 +1452,7 @@ Error EditorExportPlatform::export_project_files(const Ref & } Vector array = FileAccess::get_file_as_bytes(export_path); - err = p_save_func(p_udata, export_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, export_path, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1510,7 +1516,7 @@ Error EditorExportPlatform::export_project_files(const Ref & new_file.write[j] = utf8[j]; } - err = p_save_func(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, from + ".remap", new_file, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1532,7 +1538,7 @@ Error EditorExportPlatform::export_project_files(const Ref & } else { array = FileAccess::get_file_as_bytes(forced_export[i]); } - err = p_save_func(p_udata, forced_export[i], array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, forced_export[i], array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1541,7 +1547,7 @@ Error EditorExportPlatform::export_project_files(const Ref & Dictionary int_export = get_internal_export_files(p_preset, p_debug); for (const Variant &int_name : int_export.keys()) { const PackedByteArray &array = int_export[int_name]; - err = p_save_func(p_udata, int_name, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, int_name, array, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } @@ -1553,22 +1559,16 @@ Error EditorExportPlatform::export_project_files(const Ref & Vector data = FileAccess::get_file_as_bytes(engine_cfb); DirAccess::remove_file_or_error(engine_cfb); - err = p_save_func(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key, seed); + err = save_proxy.save_file(p_udata, "res://" + config_file, data, idx, total, enc_in_filters, enc_ex_filters, key, seed); if (err != OK) { return err; } if (p_remove_func) { - for (const String &E : PackedData::get_singleton()->get_file_paths()) { - String simplified_path = E.simplify_path(); - if (simplified_path == config_file) { - continue; - } - - String pack_path = simplified_path.trim_suffix(".remap"); - - if (!_has_pack_path(paths, pack_path) && !_has_pack_path(extra_paths, pack_path) && !_has_pack_path(path_remaps, pack_path) && !_has_pack_path(forced_export, pack_path)) { - err = p_remove_func(p_udata, E); + HashSet currently_loaded_paths = PackedData::get_singleton()->get_file_paths(); + for (const String &path : currently_loaded_paths) { + if (!save_proxy.has_saved(path)) { + err = p_remove_func(p_udata, path); if (err != OK) { return err; } From 3580509fee8828ee219ac4836cacde79175bda72 Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Fri, 24 Jan 2025 20:44:47 -0500 Subject: [PATCH 26/91] Fix flickering in embedded game when paused --- editor/plugins/game_view_plugin.cpp | 54 +++++++++++++++++++++++------ editor/plugins/game_view_plugin.h | 4 +++ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index 723c762a72a5..ad501e77a6d8 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -301,6 +301,7 @@ void GameView::_stop_pressed() { } _detach_script_debugger(); + paused = false; EditorNode::get_singleton()->set_unfocused_low_processor_usage_mode_enabled(true); embedded_process->reset(); @@ -515,15 +516,26 @@ void GameView::_update_embed_menu_options() { } void GameView::_update_embed_window_size() { - if (embed_size_mode == SIZE_MODE_FIXED || embed_size_mode == SIZE_MODE_KEEP_ASPECT) { - //The embedded process control will need the desired window size. - EditorRun::WindowPlacement placement = EditorRun::get_window_placement(); - embedded_process->set_window_size(placement.size); + if (paused) { + // When paused, Godot does not re-render. As a result, resizing the game window to a larger size + // causes artifacts and flickering. However, resizing to a smaller size seems fine. + // To prevent artifacts and flickering, we will force the game window to maintain its size. + // Using the same technique as SIZE_MODE_FIXED, the embedded process control will + // prevent resizing the game to a larger size while maintaining the aspect ratio. + embedded_process->set_window_size(size_paused); + embedded_process->set_keep_aspect(false); + } else { - //Stretch... No need for the window size. - embedded_process->set_window_size(Size2i()); + if (embed_size_mode == SIZE_MODE_FIXED || embed_size_mode == SIZE_MODE_KEEP_ASPECT) { + // The embedded process control will need the desired window size. + EditorRun::WindowPlacement placement = EditorRun::get_window_placement(); + embedded_process->set_window_size(placement.size); + } else { + // Stretch... No need for the window size. + embedded_process->set_window_size(Size2i()); + } + embedded_process->set_keep_aspect(embed_size_mode == SIZE_MODE_KEEP_ASPECT); } - embedded_process->set_keep_aspect(embed_size_mode == SIZE_MODE_KEEP_ASPECT); } void GameView::_hide_selection_toggled(bool p_pressed) { @@ -787,7 +799,8 @@ void GameView::_window_close_request() { embedded_process->reset(); // When the embedding is not complete, we need to kill the process. - if (embedded_process->is_embedding_in_progress()) { + // If the game is paused, the close request will not be processed by the game, so it's better to kill the process. + if (paused || embedded_process->is_embedding_in_progress()) { // Call deferred to prevent the _stop_pressed callback to be executed before the wrapper window // actually closes. callable_mp(EditorRunBar::get_singleton(), &EditorRunBar::stop_playing).call_deferred(); @@ -795,6 +808,20 @@ void GameView::_window_close_request() { } } +void GameView::_debugger_breaked(bool p_breaked, bool p_can_debug) { + if (p_breaked == paused) { + return; + } + + paused = p_breaked; + + if (paused) { + size_paused = embedded_process->get_screen_embedded_window_rect().size; + } + + _update_embed_window_size(); +} + GameView::GameView(Ref p_debugger, WindowWrapper *p_wrapper) { singleton = this; @@ -984,6 +1011,8 @@ GameView::GameView(Ref p_debugger, WindowWrapper *p_wrapper) { p_wrapper->set_override_close_request(true); p_wrapper->connect("window_close_requested", callable_mp(this, &GameView::_window_close_request)); p_wrapper->connect("window_size_changed", callable_mp(this, &GameView::_update_floating_window_settings)); + + EditorDebuggerNode::get_singleton()->connect("breaked", callable_mp(this, &GameView::_debugger_breaked)); } /////// @@ -1053,15 +1082,18 @@ void GameViewPlugin::_window_visibility_changed(bool p_visible) { } void GameViewPlugin::_save_last_editor(const String &p_editor) { - if (p_editor != get_name()) { + if (p_editor != get_plugin_name()) { last_editor = p_editor; } } void GameViewPlugin::_focus_another_editor() { if (window_wrapper->get_window_enabled()) { - ERR_FAIL_COND(last_editor.is_empty()); - EditorInterface::get_singleton()->set_main_screen_editor(last_editor); + if (last_editor.is_empty()) { + EditorNode::get_singleton()->get_editor_main_screen()->select(EditorMainScreen::EDITOR_2D); + } else { + EditorInterface::get_singleton()->set_main_screen_editor(last_editor); + } } } diff --git a/editor/plugins/game_view_plugin.h b/editor/plugins/game_view_plugin.h index 7402b270e3c0..dd384280b5fb 100644 --- a/editor/plugins/game_view_plugin.h +++ b/editor/plugins/game_view_plugin.h @@ -122,6 +122,8 @@ class GameView : public VBoxContainer { bool embed_on_play = true; bool make_floating_on_play = true; EmbedSizeMode embed_size_mode = SIZE_MODE_FIXED; + bool paused = false; + Size2 size_paused; Rect2i floating_window_rect; int floating_window_screen = -1; @@ -186,6 +188,8 @@ class GameView : public VBoxContainer { void _detach_script_debugger(); void _remote_window_title_changed(String title); + void _debugger_breaked(bool p_breaked, bool p_can_debug); + protected: void _notification(int p_what); From 7a85b19e5a073dee817f06eaa072f71175a42902 Mon Sep 17 00:00:00 2001 From: kobewi Date: Wed, 22 Jan 2025 21:22:31 +0100 Subject: [PATCH 27/91] Fix ProgressDialog in single window mode --- editor/progress_dialog.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/editor/progress_dialog.cpp b/editor/progress_dialog.cpp index ae06116797ff..dae7578a4eb9 100644 --- a/editor/progress_dialog.cpp +++ b/editor/progress_dialog.cpp @@ -166,11 +166,7 @@ void ProgressDialog::_popup() { center_panel->set_custom_minimum_size(ms); - Window *current_window = Window::get_from_id(DisplayServer::get_singleton()->get_focused_window()); - if (!current_window) { - current_window = get_tree()->get_root(); - } - + Window *current_window = get_last_exclusive_window(); reparent(current_window); // Ensures that events are properly released before the dialog blocks input. From a525e30c27b18b869a090dae31e243d6fef0faa4 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Mon, 27 Jan 2025 16:48:29 -0800 Subject: [PATCH 28/91] Avoid flipping normal based on facing direction when calculation SDF. This shader runs for multiple directions, so the flip direction won't be accurate and just creates bad normals --- .../shaders/forward_clustered/scene_forward_clustered.glsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl index 096e099391b1..242d29d047be 100644 --- a/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl +++ b/servers/rendering/renderer_rd/shaders/forward_clustered/scene_forward_clustered.glsl @@ -2603,7 +2603,7 @@ void fragment_shader(in SceneData scene_data) { vec3(0, -1, 0), vec3(0, 0, -1)); - vec3 cam_normal = mat3(scene_data.inv_view_matrix) * geo_normal; + vec3 cam_normal = mat3(scene_data.inv_view_matrix) * normalize(normal_interp); float closest_dist = -1e20; From 60913170c696aa8714f009b84cf7106ed9d730a0 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Mon, 27 Jan 2025 09:03:51 -0500 Subject: [PATCH 29/91] Add check for float texture linear filtering support Co-authored-by: Clay John --- drivers/gles3/storage/config.cpp | 2 + drivers/gles3/storage/config.h | 1 + drivers/gles3/storage/texture_storage.cpp | 76 ++++++++++++++++++----- 3 files changed, 64 insertions(+), 15 deletions(-) diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp index fb45fdeaca7b..8e1d08274f4f 100644 --- a/drivers/gles3/storage/config.cpp +++ b/drivers/gles3/storage/config.cpp @@ -84,12 +84,14 @@ Config::Config() { if (RasterizerGLES3::is_gles_over_gl()) { float_texture_supported = true; + float_texture_linear_supported = true; etc2_supported = false; s3tc_supported = true; rgtc_supported = true; //RGTC - core since OpenGL version 3.0 srgb_framebuffer_supported = true; } else { float_texture_supported = extensions.has("GL_EXT_color_buffer_float"); + float_texture_linear_supported = extensions.has("GL_OES_texture_float_linear"); etc2_supported = true; #if defined(ANDROID_ENABLED) || defined(IOS_ENABLED) // Some Android devices report support for S3TC but we don't expect that and don't export the textures. diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h index e4dfe6a35ee9..36fae084b0e6 100644 --- a/drivers/gles3/storage/config.h +++ b/drivers/gles3/storage/config.h @@ -72,6 +72,7 @@ class Config { HashSet extensions; bool float_texture_supported = false; + bool float_texture_linear_supported = false; bool s3tc_supported = false; bool rgtc_supported = false; bool bptc_supported = false; diff --git a/drivers/gles3/storage/texture_storage.cpp b/drivers/gles3/storage/texture_storage.cpp index c1b2784bfc05..de5938176857 100644 --- a/drivers/gles3/storage/texture_storage.cpp +++ b/drivers/gles3/storage/texture_storage.cpp @@ -334,7 +334,9 @@ void TextureStorage::canvas_texture_set_texture_repeat(RID p_canvas_texture, RS: /* Texture API */ -static inline Error _get_gl_uncompressed_format(Image::Format p_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type) { +static inline Error _get_gl_uncompressed_format(const Ref &p_image, Image::Format p_format, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type) { + Config *config = Config::get_singleton(); + switch (p_format) { case Image::FORMAT_L8: { if (RasterizerGLES3::is_gles_over_gl()) { @@ -389,24 +391,68 @@ static inline Error _get_gl_uncompressed_format(Image::Format p_format, GLenum & r_gl_type = GL_UNSIGNED_SHORT_5_6_5; } break; case Image::FORMAT_RF: { - r_gl_internal_format = GL_R32F; - r_gl_format = GL_RED; - r_gl_type = GL_FLOAT; + if (config->float_texture_linear_supported) { + r_gl_internal_format = GL_R32F; + r_gl_format = GL_RED; + r_gl_type = GL_FLOAT; + } else { + ERR_PRINT("R32 float texture not supported, converting to R16."); + if (p_image.is_valid()) { + p_image->convert(Image::FORMAT_RH); + } + r_real_format = Image::FORMAT_RH; + r_gl_internal_format = GL_R16F; + r_gl_format = GL_RED; + r_gl_type = GL_HALF_FLOAT; + } } break; case Image::FORMAT_RGF: { - r_gl_internal_format = GL_RG32F; - r_gl_format = GL_RG; - r_gl_type = GL_FLOAT; + if (config->float_texture_linear_supported) { + r_gl_internal_format = GL_RG32F; + r_gl_format = GL_RG; + r_gl_type = GL_FLOAT; + } else { + ERR_PRINT("RG32 float texture not supported, converting to RG16."); + if (p_image.is_valid()) { + p_image->convert(Image::FORMAT_RGH); + } + r_real_format = Image::FORMAT_RGH; + r_gl_internal_format = GL_RG16F; + r_gl_format = GL_RG; + r_gl_type = GL_HALF_FLOAT; + } } break; case Image::FORMAT_RGBF: { - r_gl_internal_format = GL_RGB32F; - r_gl_format = GL_RGB; - r_gl_type = GL_FLOAT; + if (config->float_texture_linear_supported) { + r_gl_internal_format = GL_RGB32F; + r_gl_format = GL_RGB; + r_gl_type = GL_FLOAT; + } else { + ERR_PRINT("RGB32 float texture not supported, converting to RGB16."); + if (p_image.is_valid()) { + p_image->convert(Image::FORMAT_RGBH); + } + r_real_format = Image::FORMAT_RGBH; + r_gl_internal_format = GL_RGB16F; + r_gl_format = GL_RGB; + r_gl_type = GL_HALF_FLOAT; + } } break; case Image::FORMAT_RGBAF: { - r_gl_internal_format = GL_RGBA32F; - r_gl_format = GL_RGBA; - r_gl_type = GL_FLOAT; + if (config->float_texture_linear_supported) { + r_gl_internal_format = GL_RGBA32F; + r_gl_format = GL_RGBA; + r_gl_type = GL_FLOAT; + } else { + ERR_PRINT("RGBA32 float texture not supported, converting to RGBA16."); + if (p_image.is_valid()) { + p_image->convert(Image::FORMAT_RGBAH); + } + r_real_format = Image::FORMAT_RGBAH; + r_gl_internal_format = GL_RGBA16F; + r_gl_format = GL_RGBA; + r_gl_type = GL_HALF_FLOAT; + } } break; case Image::FORMAT_RH: { r_gl_internal_format = GL_R16F; @@ -449,7 +495,7 @@ Ref TextureStorage::_get_gl_image_and_format(const Ref &p_image, I r_real_format = p_format; if (!Image::is_format_compressed(p_format)) { - Error err = _get_gl_uncompressed_format(p_format, r_gl_format, r_gl_internal_format, r_gl_type); + Error err = _get_gl_uncompressed_format(p_image, p_format, r_real_format, r_gl_format, r_gl_internal_format, r_gl_type); ERR_FAIL_COND_V_MSG(err != OK, Ref(), vformat("The image format %d is not supported by the Compatibility renderer.", p_format)); return p_image; } @@ -694,7 +740,7 @@ Ref TextureStorage::_get_gl_image_and_format(const Ref &p_image, I image->convert(Image::FORMAT_RG8); } - Error err = _get_gl_uncompressed_format(image->get_format(), r_gl_format, r_gl_internal_format, r_gl_type); + Error err = _get_gl_uncompressed_format(image, image->get_format(), r_real_format, r_gl_format, r_gl_internal_format, r_gl_type); ERR_FAIL_COND_V_MSG(err != OK, Ref(), vformat("The image format %d is not supported by the Compatibility renderer.", image->get_format())); r_real_format = image->get_format(); From c7fd0bb740c250b1fd8ccccfd47a33649b555ccc Mon Sep 17 00:00:00 2001 From: Robert Yevdokimov <105675984+ryevdokimov@users.noreply.github.com> Date: Mon, 27 Jan 2025 05:50:27 +0400 Subject: [PATCH 30/91] Make save confirmation a child of last exclusive window of EditorNode before popup --- editor/editor_node.cpp | 5 +++++ editor/editor_node.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4b7abdf2b072..06c32ba77e9e 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -5701,6 +5701,10 @@ void EditorNode::_cancel_close_scene_tab() { } } +void EditorNode::_prepare_save_confirmation_popup() { + save_confirmation->reparent(get_last_exclusive_window()); +} + void EditorNode::_toggle_distraction_free_mode() { if (EDITOR_GET("interface/editor/separate_distraction_mode")) { int screen = editor_main_screen->get_selected_index(); @@ -7697,6 +7701,7 @@ EditorNode::EditorNode() { save_confirmation->connect(SceneStringName(confirmed), callable_mp(this, &EditorNode::_menu_confirm_current)); save_confirmation->connect("custom_action", callable_mp(this, &EditorNode::_discard_changes)); save_confirmation->connect("canceled", callable_mp(this, &EditorNode::_cancel_close_scene_tab)); + save_confirmation->connect("about_to_popup", callable_mp(this, &EditorNode::_prepare_save_confirmation_popup)); gradle_build_manage_templates = memnew(ConfirmationDialog); gradle_build_manage_templates->set_text(TTR("Android build template is missing, please install relevant templates.")); diff --git a/editor/editor_node.h b/editor/editor_node.h index b77f6553fe96..e56ecbe45310 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -566,6 +566,8 @@ class EditorNode : public Node { void _scene_tab_closed(int p_tab); void _cancel_close_scene_tab(); + void _prepare_save_confirmation_popup(); + void _inherit_request(String p_file); void _instantiate_request(const Vector &p_files); From 24b502b13aec4d33cb011c72342497f20a7cbe15 Mon Sep 17 00:00:00 2001 From: kleonc <9283098+kleonc@users.noreply.github.com> Date: Tue, 28 Jan 2025 14:21:36 +0100 Subject: [PATCH 31/91] Fix Y-sorted root item having modulation applied twice --- servers/rendering/renderer_canvas_cull.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index c9175466104f..9f420bb756b1 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -434,7 +434,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 child_items = (Item **)alloca(child_item_count * sizeof(Item *)); ci->ysort_xform = Transform2D(); - ci->ysort_modulate = Color(1, 1, 1, 1); + ci->ysort_modulate = Color(1, 1, 1, 1) / ci->modulate; ci->ysort_index = 0; ci->ysort_parent_abs_z_index = parent_z; child_items[0] = ci; From 655e98b2ea99f4a8bfe2548c1ce93a9a28627c38 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 28 Jan 2025 10:24:46 -0300 Subject: [PATCH 32/91] Fix default SDFGI variant not being compiled in time. --- .../forward_clustered/render_forward_clustered.cpp | 8 ++++++++ .../forward_clustered/scene_shader_forward_clustered.cpp | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) 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 70b3a89c4a68..34d372252c68 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -3764,6 +3764,14 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te uniforms.push_back(u); } + if (scene_shader.default_shader_sdfgi_rd.is_null()) { + // The variant for SDF from the default material should only be retrieved when SDFGI is required. + ERR_FAIL_NULL_V(scene_shader.default_material_shader_ptr, RID()); + scene_shader.enable_advanced_shader_group(); + scene_shader.default_shader_sdfgi_rd = scene_shader.default_material_shader_ptr->get_shader_variant(SceneShaderForwardClustered::PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, 0, false); + ERR_FAIL_COND_V(scene_shader.default_shader_sdfgi_rd.is_null(), RID()); + } + return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_sdfgi_rd, RENDER_PASS_UNIFORM_SET, uniforms); } diff --git a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp index 102d15206fe0..5debecb134d4 100644 --- a/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp @@ -805,7 +805,6 @@ void fragment() { MaterialData *md = static_cast(material_storage->material_get_data(default_material, RendererRD::MaterialStorage::SHADER_TYPE_3D)); default_shader_rd = md->shader_data->get_shader_variant(PIPELINE_VERSION_COLOR_PASS, 0, false); - default_shader_sdfgi_rd = md->shader_data->get_shader_variant(PIPELINE_VERSION_DEPTH_PASS_WITH_SDF, 0, false); default_material_shader_ptr = md->shader_data; default_material_uniform_set = md->uniform_set; From d0c29faa1547a261254d7721d2e7bcad002a9204 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 28 Jan 2025 11:40:05 -0300 Subject: [PATCH 33/91] Mark pipeline compilation of ubershaders as high priority. --- .../forward_clustered/render_forward_clustered.cpp | 2 +- .../renderer_rd/forward_mobile/render_forward_mobile.cpp | 2 +- servers/rendering/renderer_rd/pipeline_hash_map_rd.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) 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 70b3a89c4a68..97fc9b2202d8 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -4427,7 +4427,7 @@ void RenderForwardClustered::_mesh_compile_pipeline_for_surface(SceneShaderForwa r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, pipeline_motion_vectors); r_pipeline_key.ubershader = p_ubershader; - p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source); + p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source, p_ubershader); if (r_pipeline_pairs != nullptr) { r_pipeline_pairs->push_back({ p_shader, r_pipeline_key }); diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 1651e82276dd..1d438e591eb5 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -2987,7 +2987,7 @@ void RenderForwardMobile::_mesh_compile_pipeline_for_surface(SceneShaderForwardM uint64_t input_mask = p_shader->get_vertex_input_mask(r_pipeline_key.version, true); r_pipeline_key.vertex_format_id = mesh_storage->mesh_surface_get_vertex_format(p_mesh_surface, input_mask, p_instanced_surface, false); r_pipeline_key.ubershader = true; - p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source); + p_shader->pipeline_hash_map.compile_pipeline(r_pipeline_key, r_pipeline_key.hash(), p_source, r_pipeline_key.ubershader); if (r_pipeline_pairs != nullptr) { r_pipeline_pairs->push_back({ p_shader, r_pipeline_key }); diff --git a/servers/rendering/renderer_rd/pipeline_hash_map_rd.h b/servers/rendering/renderer_rd/pipeline_hash_map_rd.h index cdd06accf28b..e569ed13b973 100644 --- a/servers/rendering/renderer_rd/pipeline_hash_map_rd.h +++ b/servers/rendering/renderer_rd/pipeline_hash_map_rd.h @@ -92,7 +92,7 @@ class PipelineHashMapRD { } // Start compilation of a pipeline ahead of time in the background. Returns true if the compilation was started, false if it wasn't required. Source is only used for collecting statistics. - void compile_pipeline(const Key &p_key, uint32_t p_key_hash, RS::PipelineSource p_source) { + void compile_pipeline(const Key &p_key, uint32_t p_key_hash, RS::PipelineSource p_source, bool p_high_priority) { DEV_ASSERT((creation_object != nullptr) && (creation_function != nullptr) && "Creation object and function was not set before attempting to compile a pipeline."); MutexLock local_lock(local_mutex); @@ -133,7 +133,7 @@ class PipelineHashMapRD { #endif // Queue a background compilation task. - WorkerThreadPool::TaskID task_id = WorkerThreadPool::get_singleton()->add_template_task(creation_object, creation_function, p_key, false, "PipelineCompilation"); + WorkerThreadPool::TaskID task_id = WorkerThreadPool::get_singleton()->add_template_task(creation_object, creation_function, p_key, p_high_priority, "PipelineCompilation"); compilation_tasks.insert(p_key_hash, task_id); } @@ -165,7 +165,7 @@ class PipelineHashMapRD { if (e == nullptr) { // Request compilation. The method will ignore the request if it's already being compiled. - compile_pipeline(p_key, p_key_hash, p_source); + compile_pipeline(p_key, p_key_hash, p_source, p_wait_for_compilation); if (p_wait_for_compilation) { wait_for_pipeline(p_key_hash); From a2f5eb9cf095a8d942d9518a2ef5848cd47ce8f1 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Tue, 28 Jan 2025 16:09:48 +0100 Subject: [PATCH 34/91] [WS] Fix wslay multi-frame message parsing (again) We incorrectly assumed that the `payload_length` in the recv start callback of wslay was the final message size, but according to the WebSocket protocol, the payload length always refers to the current frame's payload size. The protocol, in fact, do not include a "message payload" length on purpose to allow sending messages of unknown size without forcing the sender to buffer the whole message (RFC6455 Section 5.4). This means a receiving peer has no way to know beforehand how long a message will be, and needs instead to keep track of the length of each frame until the FIN one is received to properly reconstruct the message at the end. --- modules/websocket/wsl_peer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/websocket/wsl_peer.cpp b/modules/websocket/wsl_peer.cpp index f50b4c480652..1a1f52a8a06b 100644 --- a/modules/websocket/wsl_peer.cpp +++ b/modules/websocket/wsl_peer.cpp @@ -598,7 +598,6 @@ void WSLPeer::_wsl_recv_start_callback(wslay_event_context_ptr ctx, const struct // Get ready to process a data package. PendingMessage &pm = peer->pending_message; pm.opcode = op; - pm.payload_size = arg->payload_length; } } @@ -608,6 +607,7 @@ void WSLPeer::_wsl_frame_recv_chunk_callback(wslay_event_context_ptr ctx, const if (pm.opcode != 0) { // Only write the payload. peer->in_buffer.write_packet(arg->data, arg->data_length, nullptr); + pm.payload_size += arg->data_length; } } From 47f553ae0bc59faa98b4b8b137a47ed05cb99de5 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Wed, 22 Jan 2025 10:44:50 -0500 Subject: [PATCH 35/91] Delegate to the DisplayServer the task of handling mouse_mode - Add `MOUSE_MODE_MAX` and various index checks --- core/input/input.cpp | 53 +++++++----------- core/input/input.h | 14 +++-- doc/classes/DisplayServer.xml | 3 ++ doc/classes/Input.xml | 3 ++ platform/android/display_server_android.cpp | 45 ++++++++++++++-- platform/android/display_server_android.h | 8 +++ .../wayland/display_server_wayland.cpp | 48 +++++++++++++++-- .../linuxbsd/wayland/display_server_wayland.h | 8 +++ platform/linuxbsd/x11/display_server_x11.cpp | 46 ++++++++++++++-- platform/linuxbsd/x11/display_server_x11.h | 9 ++++ platform/macos/display_server_macos.h | 8 +++ platform/macos/display_server_macos.mm | 54 ++++++++++++++++--- platform/web/display_server_web.cpp | 50 ++++++++++++++--- platform/web/display_server_web.h | 10 ++++ platform/windows/display_server_windows.cpp | 46 ++++++++++++++-- platform/windows/display_server_windows.h | 8 +++ servers/display_server.cpp | 37 +++++++++++++ servers/display_server.h | 19 +++++-- servers/display_server_headless.h | 2 + 19 files changed, 394 insertions(+), 77 deletions(-) diff --git a/core/input/input.cpp b/core/input/input.cpp index 4413c426cf09..b705968b87ed 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -77,6 +77,10 @@ Input *Input::singleton = nullptr; void (*Input::set_mouse_mode_func)(Input::MouseMode) = nullptr; Input::MouseMode (*Input::get_mouse_mode_func)() = nullptr; +void (*Input::set_mouse_mode_override_func)(Input::MouseMode) = nullptr; +Input::MouseMode (*Input::get_mouse_mode_override_func)() = nullptr; +void (*Input::set_mouse_mode_override_enabled_func)(bool) = nullptr; +bool (*Input::is_mouse_mode_override_enabled_func)() = nullptr; void (*Input::warp_mouse_func)(const Vector2 &p_position) = nullptr; Input::CursorShape (*Input::get_current_cursor_shape_func)() = nullptr; void (*Input::set_custom_mouse_cursor_func)(const Ref &, Input::CursorShape, const Vector2 &) = nullptr; @@ -86,51 +90,29 @@ Input *Input::get_singleton() { } void Input::set_mouse_mode(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 5); - - if (p_mode == mouse_mode) { - return; - } - - // Allow to be set even if overridden, to see if the platform allows the mode. + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); set_mouse_mode_func(p_mode); - mouse_mode = get_mouse_mode_func(); - - if (mouse_mode_override_enabled) { - set_mouse_mode_func(mouse_mode_override); - } } Input::MouseMode Input::get_mouse_mode() const { - return mouse_mode; + return get_mouse_mode_func(); } -void Input::set_mouse_mode_override_enabled(bool p_enabled) { - if (p_enabled == mouse_mode_override_enabled) { - return; - } - - mouse_mode_override_enabled = p_enabled; - - if (p_enabled) { - set_mouse_mode_func(mouse_mode_override); - mouse_mode_override = get_mouse_mode_func(); - } else { - set_mouse_mode_func(mouse_mode); - } +void Input::set_mouse_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + set_mouse_mode_override_func(p_mode); } -void Input::set_mouse_mode_override(MouseMode p_mode) { - ERR_FAIL_INDEX((int)p_mode, 5); +Input::MouseMode Input::get_mouse_mode_override() const { + return get_mouse_mode_override_func(); +} - if (p_mode == mouse_mode_override) { - return; - } +void Input::set_mouse_mode_override_enabled(bool p_override_enabled) { + set_mouse_mode_override_enabled_func(p_override_enabled); +} - if (mouse_mode_override_enabled) { - set_mouse_mode_func(p_mode); - mouse_mode_override = get_mouse_mode_func(); - } +bool Input::is_mouse_mode_override_enabled() { + return is_mouse_mode_override_enabled_func(); } void Input::_bind_methods() { @@ -199,6 +181,7 @@ void Input::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_MAX); BIND_ENUM_CONSTANT(CURSOR_ARROW); BIND_ENUM_CONSTANT(CURSOR_IBEAM); diff --git a/core/input/input.h b/core/input/input.h index 6893c4b997b4..bbe185de3cbc 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -47,12 +47,14 @@ class Input : public Object { static constexpr uint64_t MAX_EVENT = 32; public: + // Keep synced with "DisplayServer::MouseMode" enum. enum MouseMode { MOUSE_MODE_VISIBLE, MOUSE_MODE_HIDDEN, MOUSE_MODE_CAPTURED, MOUSE_MODE_CONFINED, MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_MAX, }; #undef CursorShape @@ -105,10 +107,6 @@ class Input : public Object { bool legacy_just_pressed_behavior = false; bool disable_input = false; - MouseMode mouse_mode = MOUSE_MODE_VISIBLE; - bool mouse_mode_override_enabled = false; - MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; - struct ActionState { uint64_t pressed_physics_frame = UINT64_MAX; uint64_t pressed_process_frame = UINT64_MAX; @@ -268,6 +266,10 @@ class Input : public Object { static void (*set_mouse_mode_func)(MouseMode); static MouseMode (*get_mouse_mode_func)(); + static void (*set_mouse_mode_override_func)(MouseMode); + static MouseMode (*get_mouse_mode_override_func)(); + static void (*set_mouse_mode_override_enabled_func)(bool); + static bool (*is_mouse_mode_override_enabled_func)(); static void (*warp_mouse_func)(const Vector2 &p_position); static CursorShape (*get_current_cursor_shape_func)(); @@ -286,8 +288,10 @@ class Input : public Object { public: void set_mouse_mode(MouseMode p_mode); MouseMode get_mouse_mode() const; - void set_mouse_mode_override_enabled(bool p_enabled); void set_mouse_mode_override(MouseMode p_mode); + MouseMode get_mouse_mode_override() const; + void set_mouse_mode_override_enabled(bool p_override_enabled); + bool is_mouse_mode_override_enabled(); #ifdef TOOLS_ENABLED void get_argument_options(const StringName &p_function, int p_idx, List *r_options) const override; diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index 8c9855fa9180..6089f85bc774 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1968,6 +1968,9 @@ Confines the mouse cursor to the game window, and make it hidden. + + Max value of the [enum MouseMode]. + Represents the screen containing the mouse pointer. [b]Note:[/b] On Linux (Wayland), this constant always represents the screen at index [code]0[/code]. diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 2e12015e5f98..e0d8be915778 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -464,6 +464,9 @@ Confines the mouse cursor to the game window, and make it hidden. + + Max value of the [enum MouseMode]. + Arrow cursor. Standard, default pointing cursor. diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index 06973f289c5c..f8d960f2b701 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -771,33 +771,68 @@ void DisplayServerAndroid::process_gyroscope(const Vector3 &p_gyroscope) { Input::get_singleton()->set_gyroscope(p_gyroscope); } -void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) { +void DisplayServerAndroid::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + if (!OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_update_pointer_icon() || !OS_Android::get_singleton()->get_godot_java()->get_godot_view()->can_capture_pointer()) { return; } - if (mouse_mode == p_mode) { + if (mouse_mode == wanted_mouse_mode) { return; } - if (p_mode == MouseMode::MOUSE_MODE_HIDDEN) { + if (wanted_mouse_mode == MouseMode::MOUSE_MODE_HIDDEN) { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->set_pointer_icon(CURSOR_TYPE_NULL); } else { cursor_set_shape(cursor_shape); } - if (p_mode == MouseMode::MOUSE_MODE_CAPTURED) { + if (wanted_mouse_mode == MouseMode::MOUSE_MODE_CAPTURED) { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->request_pointer_capture(); } else { OS_Android::get_singleton()->get_godot_java()->get_godot_view()->release_pointer_capture(); } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; +} + +void DisplayServerAndroid::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode() const { return mouse_mode; } +void DisplayServerAndroid::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerAndroid::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerAndroid::mouse_set_mode_override_enabled(bool p_override_enabled) { + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerAndroid::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + Point2i DisplayServerAndroid::mouse_get_position() const { return Input::get_singleton()->get_mouse_position(); } diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 0d2caa07b7c7..587d8731a10f 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -66,6 +66,10 @@ class DisplayServerAndroid : public DisplayServer { }; const int CURSOR_TYPE_NULL = 0; MouseMode mouse_mode = MouseMode::MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MouseMode::MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MouseMode::MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); bool keep_screen_on; bool swap_buffers_flag; @@ -228,6 +232,10 @@ class DisplayServerAndroid : public DisplayServer { virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, DisplayServer::VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Context p_context, int64_t p_parent_window, Error &r_error); static Vector get_rendering_drivers_func(); diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp index 532eaa6bcf49..19123875b2cb 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.cpp +++ b/platform/linuxbsd/wayland/display_server_wayland.cpp @@ -325,20 +325,24 @@ void DisplayServerWayland::beep() const { wayland_thread.beep(); } -void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { - if (p_mode == mouse_mode) { +void DisplayServerWayland::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } MutexLock mutex_lock(wayland_thread.mutex); - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); wayland_thread.cursor_set_visible(show_cursor); WaylandThread::PointerConstraint constraint = WaylandThread::PointerConstraint::NONE; - switch (p_mode) { + switch (wanted_mouse_mode) { case DisplayServer::MOUSE_MODE_CAPTURED: { constraint = WaylandThread::PointerConstraint::LOCKED; } break; @@ -354,13 +358,47 @@ void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { wayland_thread.pointer_set_constraint(constraint); - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; +} + +void DisplayServerWayland::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode() const { return mouse_mode; } +void DisplayServerWayland::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServerWayland::MouseMode DisplayServerWayland::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWayland::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWayland::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + // NOTE: This is hacked together (and not guaranteed to work in the first place) // as for some reason the there's no proper way to ask the compositor to warp // the pointer, although, at the time of writing, there's a proposal for a diff --git a/platform/linuxbsd/wayland/display_server_wayland.h b/platform/linuxbsd/wayland/display_server_wayland.h index 8c3bac9c7e3b..97a07194a6ab 100644 --- a/platform/linuxbsd/wayland/display_server_wayland.h +++ b/platform/linuxbsd/wayland/display_server_wayland.h @@ -113,6 +113,10 @@ class DisplayServerWayland : public DisplayServer { CursorShape cursor_shape = CURSOR_ARROW; DisplayServer::MouseMode mouse_mode = DisplayServer::MOUSE_MODE_VISIBLE; + DisplayServer::MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + DisplayServer::MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); HashMap custom_cursors; @@ -191,6 +195,10 @@ class DisplayServerWayland : public DisplayServer { virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_to) override; virtual Point2i mouse_get_position() const override; diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index b1945eb47a2e..9dbf4dda597d 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -417,10 +417,14 @@ void DisplayServerX11::beep() const { XBell(x11_display, 0); } -void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { +void DisplayServerX11::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (p_mode == mouse_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } @@ -429,7 +433,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { } // The only modes that show a cursor are VISIBLE and CONFINED - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED); if (show_cursor && !previously_shown) { @@ -450,7 +454,7 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { XDefineCursor(x11_display, E.value.x11_window, null_cursor); // hide cursor } } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { //flush pending motion events @@ -484,10 +488,44 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { XFlush(x11_display); } +void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServerX11::MouseMode DisplayServerX11::mouse_get_mode() const { return mouse_mode; } +void DisplayServerX11::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServerX11::MouseMode DisplayServerX11::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerX11::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerX11::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + void DisplayServerX11::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index e0a84db4b627..166b2cb57b5c 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -297,6 +297,11 @@ class DisplayServerX11 : public DisplayServer { void _flush_mouse_motion(); MouseMode mouse_mode = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); + Point2i center; void _handle_key_event(WindowID p_window, XKeyEvent *p_event, LocalVector &p_events, uint32_t &p_event_index, bool p_echo = false); @@ -424,6 +429,10 @@ class DisplayServerX11 : public DisplayServer { virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_position) override; virtual Point2i mouse_get_position() const override; diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 32ab1fc478de..eb536f9894c3 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -169,6 +169,10 @@ class DisplayServerMacOS : public DisplayServer { CGEventSourceRef event_source; MouseMode mouse_mode = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); bool drop_events = false; bool in_dispatch_input_event = false; @@ -306,6 +310,10 @@ class DisplayServerMacOS : public DisplayServer { virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; bool update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp); virtual void warp_mouse(const Point2i &p_position) override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 174e28310ef1..dd351bcad793 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -1264,10 +1264,14 @@ return OK; } -void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { +void DisplayServerMacOS::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (p_mode == mouse_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (wanted_mouse_mode == mouse_mode) { return; } @@ -1277,7 +1281,7 @@ } WindowData &wd = windows[window_id]; - bool show_cursor = (p_mode == MOUSE_MODE_VISIBLE || p_mode == MOUSE_MODE_CONFINED); + bool show_cursor = (wanted_mouse_mode == MOUSE_MODE_VISIBLE || wanted_mouse_mode == MOUSE_MODE_CONFINED); bool previously_shown = (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED); if (show_cursor && !previously_shown) { @@ -1285,7 +1289,7 @@ mouse_enter_window(window_id); } - if (p_mode == MOUSE_MODE_CAPTURED) { + if (wanted_mouse_mode == MOUSE_MODE_CAPTURED) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." // https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html @@ -1299,17 +1303,17 @@ NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin; CGPoint lMouseWarpPos = { pointOnScreen.x, CGDisplayBounds(CGMainDisplayID()).size.height - pointOnScreen.y }; CGWarpMouseCursorPosition(lMouseWarpPos); - } else if (p_mode == MOUSE_MODE_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_HIDDEN) { if (previously_shown) { CGDisplayHideCursor(kCGDirectMainDisplay); } [wd.window_object setMovable:YES]; CGAssociateMouseAndMouseCursorPosition(true); - } else if (p_mode == MOUSE_MODE_CONFINED) { + } else if (wanted_mouse_mode == MOUSE_MODE_CONFINED) { CGDisplayShowCursor(kCGDirectMainDisplay); [wd.window_object setMovable:NO]; CGAssociateMouseAndMouseCursorPosition(false); - } else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { if (previously_shown) { CGDisplayHideCursor(kCGDirectMainDisplay); } @@ -1324,17 +1328,51 @@ last_warp = [[NSProcessInfo processInfo] systemUptime]; ignore_warp = true; warp_events.clear(); - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; if (show_cursor) { cursor_update_shape(); } } +void DisplayServerMacOS::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode() const { return mouse_mode; } +void DisplayServerMacOS::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerMacOS::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerMacOS::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerMacOS::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + bool DisplayServerMacOS::update_mouse_wrap(WindowData &p_wd, NSPoint &r_delta, NSPoint &r_mpos, NSTimeInterval p_timestamp) { _THREAD_SAFE_METHOD_ diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index 8b4a733a0889..89cc6339d28b 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -550,26 +550,39 @@ void DisplayServerWeb::cursor_set_custom_image(const Ref &p_cursor, Cu } // Mouse mode -void DisplayServerWeb::mouse_set_mode(MouseMode p_mode) { - ERR_FAIL_COND_MSG(p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the Web platform."); - if (p_mode == mouse_get_mode()) { +void DisplayServerWeb::_mouse_update_mode() { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + ERR_FAIL_COND_MSG(wanted_mouse_mode == MOUSE_MODE_CONFINED || wanted_mouse_mode == MOUSE_MODE_CONFINED_HIDDEN, "MOUSE_MODE_CONFINED is not supported for the Web platform."); + if (wanted_mouse_mode == mouse_get_mode()) { return; } - if (p_mode == MOUSE_MODE_VISIBLE) { + if (wanted_mouse_mode == MOUSE_MODE_VISIBLE) { godot_js_display_cursor_set_visible(1); godot_js_display_cursor_lock_set(0); - } else if (p_mode == MOUSE_MODE_HIDDEN) { + } else if (wanted_mouse_mode == MOUSE_MODE_HIDDEN) { godot_js_display_cursor_set_visible(0); godot_js_display_cursor_lock_set(0); - } else if (p_mode == MOUSE_MODE_CAPTURED) { + } else if (wanted_mouse_mode == MOUSE_MODE_CAPTURED) { godot_js_display_cursor_set_visible(1); godot_js_display_cursor_lock_set(1); } } +void DisplayServerWeb::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); +} + DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode() const { if (godot_js_display_cursor_is_hidden()) { return MOUSE_MODE_HIDDEN; @@ -581,6 +594,31 @@ DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } +void DisplayServerWeb::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerWeb::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWeb::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWeb::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + Point2i DisplayServerWeb::mouse_get_position() const { return Input::get_singleton()->get_mouse_position(); } diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index de0eb93238cc..2d0d13c19a30 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -106,6 +106,11 @@ class DisplayServerWeb : public DisplayServer { bool tts = false; NativeMenu *native_menu = nullptr; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); + // utilities static void dom2godot_mod(Ref ev, int p_mod, Key p_keycode); static const char *godot2dom_cursor(DisplayServer::CursorShape p_shape); @@ -184,6 +189,11 @@ class DisplayServerWeb : public DisplayServer { // mouse virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; + virtual Point2i mouse_get_position() const override; // ime diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 1d3a6f0ca4f2..ab91b2398d9f 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -796,23 +796,61 @@ void DisplayServerWindows::beep() const { MessageBeep(MB_OK); } -void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { +void DisplayServerWindows::_mouse_update_mode() { _THREAD_SAFE_METHOD_ - if (mouse_mode == p_mode) { + MouseMode wanted_mouse_mode = mouse_mode_override_enabled + ? mouse_mode_override + : mouse_mode_base; + + if (mouse_mode == wanted_mouse_mode) { // Already in the same mode; do nothing. return; } - mouse_mode = p_mode; + mouse_mode = wanted_mouse_mode; - _set_mouse_mode_impl(p_mode); + _set_mouse_mode_impl(wanted_mouse_mode); +} + +void DisplayServerWindows::mouse_set_mode(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_base) { + return; + } + mouse_mode_base = p_mode; + _mouse_update_mode(); } DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const { return mouse_mode; } +void DisplayServerWindows::mouse_set_mode_override(MouseMode p_mode) { + ERR_FAIL_INDEX(p_mode, MouseMode::MOUSE_MODE_MAX); + if (p_mode == mouse_mode_override) { + return; + } + mouse_mode_override = p_mode; + _mouse_update_mode(); +} + +DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode_override() const { + return mouse_mode_override; +} + +void DisplayServerWindows::mouse_set_mode_override_enabled(bool p_override_enabled) { + if (p_override_enabled == mouse_mode_override_enabled) { + return; + } + mouse_mode_override_enabled = p_override_enabled; + _mouse_update_mode(); +} + +bool DisplayServerWindows::mouse_is_mode_override_enabled() const { + return mouse_mode_override_enabled; +} + void DisplayServerWindows::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index b85394366e87..71de7a73769e 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -620,6 +620,10 @@ class DisplayServerWindows : public DisplayServer { void _get_window_style(bool p_main_window, bool p_initialized, bool p_fullscreen, bool p_multiwindow_fs, bool p_borderless, bool p_resizable, bool p_minimized, bool p_maximized, bool p_maximized_fs, bool p_no_activate_focus, bool p_embed_child, DWORD &r_style, DWORD &r_style_ex); MouseMode mouse_mode; + MouseMode mouse_mode_base = MOUSE_MODE_VISIBLE; + MouseMode mouse_mode_override = MOUSE_MODE_VISIBLE; + bool mouse_mode_override_enabled = false; + void _mouse_update_mode(); int restore_mouse_trails = 0; bool use_raw_input = false; @@ -715,6 +719,10 @@ class DisplayServerWindows : public DisplayServer { virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; + virtual void mouse_set_mode_override(MouseMode p_mode) override; + virtual MouseMode mouse_get_mode_override() const override; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled) override; + virtual bool mouse_is_mode_override_enabled() const override; virtual void warp_mouse(const Point2i &p_position) override; virtual Point2i mouse_get_position() const override; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index dc3402bdf88b..bf3d428420a7 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -501,6 +501,22 @@ DisplayServer::MouseMode DisplayServer::mouse_get_mode() const { return MOUSE_MODE_VISIBLE; } +void DisplayServer::mouse_set_mode_override(MouseMode p_mode) { + WARN_PRINT("Mouse is not supported by this display server."); +} + +DisplayServer::MouseMode DisplayServer::mouse_get_mode_override() const { + return MOUSE_MODE_VISIBLE; +} + +void DisplayServer::mouse_set_mode_override_enabled(bool p_override_enabled) { + WARN_PRINT("Mouse is not supported by this display server."); +} + +bool DisplayServer::mouse_is_mode_override_enabled() const { + return false; +} + void DisplayServer::warp_mouse(const Point2i &p_position) { } @@ -1098,6 +1114,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(MOUSE_MODE_CAPTURED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED); BIND_ENUM_CONSTANT(MOUSE_MODE_CONFINED_HIDDEN); + BIND_ENUM_CONSTANT(MOUSE_MODE_MAX); BIND_CONSTANT(SCREEN_WITH_MOUSE_FOCUS); BIND_CONSTANT(SCREEN_WITH_KEYBOARD_FOCUS); @@ -1266,6 +1283,22 @@ Input::MouseMode DisplayServer::_input_get_mouse_mode() { return Input::MouseMode(singleton->mouse_get_mode()); } +void DisplayServer::_input_set_mouse_mode_override(Input::MouseMode p_mode) { + singleton->mouse_set_mode_override(MouseMode(p_mode)); +} + +Input::MouseMode DisplayServer::_input_get_mouse_mode_override() { + return Input::MouseMode(singleton->mouse_get_mode_override()); +} + +void DisplayServer::_input_set_mouse_mode_override_enabled(bool p_enabled) { + singleton->mouse_set_mode_override_enabled(p_enabled); +} + +bool DisplayServer::_input_is_mouse_mode_override_enabled() { + return singleton->mouse_is_mode_override_enabled(); +} + void DisplayServer::_input_warp(const Vector2 &p_to_pos) { singleton->warp_mouse(p_to_pos); } @@ -1347,6 +1380,10 @@ DisplayServer::DisplayServer() { singleton = this; Input::set_mouse_mode_func = _input_set_mouse_mode; Input::get_mouse_mode_func = _input_get_mouse_mode; + Input::set_mouse_mode_override_func = _input_set_mouse_mode_override; + Input::get_mouse_mode_override_func = _input_get_mouse_mode_override; + Input::set_mouse_mode_override_enabled_func = _input_set_mouse_mode_override_enabled; + Input::is_mouse_mode_override_enabled_func = _input_is_mouse_mode_override_enabled; Input::warp_mouse_func = _input_warp; Input::get_current_cursor_shape_func = _input_get_current_cursor_shape; Input::set_custom_mouse_cursor_func = _input_set_custom_mouse_cursor_func; diff --git a/servers/display_server.h b/servers/display_server.h index 562c2bf5abe0..30bb533a5d39 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -98,6 +98,10 @@ class DisplayServer : public Object { private: static void _input_set_mouse_mode(Input::MouseMode p_mode); static Input::MouseMode _input_get_mouse_mode(); + static void _input_set_mouse_mode_override(Input::MouseMode p_mode); + static Input::MouseMode _input_get_mouse_mode_override(); + static void _input_set_mouse_mode_override_enabled(bool p_enabled); + static bool _input_is_mouse_mode_override_enabled(); static void _input_warp(const Vector2 &p_to_pos); static Input::CursorShape _input_get_current_cursor_shape(); static void _input_set_custom_mouse_cursor_func(const Ref &, Input::CursorShape, const Vector2 &p_hotspot); @@ -275,15 +279,20 @@ class DisplayServer : public Object { static void set_early_window_clear_color_override(bool p_enabled, Color p_color = Color(0, 0, 0, 0)); enum MouseMode { - MOUSE_MODE_VISIBLE, - MOUSE_MODE_HIDDEN, - MOUSE_MODE_CAPTURED, - MOUSE_MODE_CONFINED, - MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_VISIBLE = Input::MOUSE_MODE_VISIBLE, + MOUSE_MODE_HIDDEN = Input::MOUSE_MODE_HIDDEN, + MOUSE_MODE_CAPTURED = Input::MOUSE_MODE_CAPTURED, + MOUSE_MODE_CONFINED = Input::MOUSE_MODE_CONFINED, + MOUSE_MODE_CONFINED_HIDDEN = Input::MOUSE_MODE_CONFINED_HIDDEN, + MOUSE_MODE_MAX = Input::MOUSE_MODE_MAX, }; virtual void mouse_set_mode(MouseMode p_mode); virtual MouseMode mouse_get_mode() const; + virtual void mouse_set_mode_override(MouseMode p_mode); + virtual MouseMode mouse_get_mode_override() const; + virtual void mouse_set_mode_override_enabled(bool p_override_enabled); + virtual bool mouse_is_mode_override_enabled() const; virtual void warp_mouse(const Point2i &p_position); virtual Point2i mouse_get_position() const; diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h index 12c174ae2b05..7bd8cbf07520 100644 --- a/servers/display_server_headless.h +++ b/servers/display_server_headless.h @@ -170,6 +170,8 @@ class DisplayServerHeadless : public DisplayServer { void tts_stop() override {} void mouse_set_mode(MouseMode p_mode) override {} + void mouse_set_mode_override(MouseMode p_mode) override {} + void mouse_set_mode_override_enabled(bool p_override_enabled) override {} Point2i mouse_get_position() const override { return Point2i(); } void clipboard_set(const String &p_text) override {} void clipboard_set_primary(const String &p_text) override {} From e904c0c014a09548f9058261cd09ddfb8fc2cc24 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Tue, 28 Jan 2025 10:53:43 -0600 Subject: [PATCH 36/91] Fix memory leak when `ClassDB::bind_method_custom()` fails --- core/object/class_db.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/object/class_db.cpp b/core/object/class_db.cpp index ffd796de9cff..e6536fe8e98a 100644 --- a/core/object/class_db.cpp +++ b/core/object/class_db.cpp @@ -1866,9 +1866,12 @@ void ClassDB::_bind_compatibility(ClassInfo *type, MethodBind *p_method) { void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_method, bool p_compatibility) { OBJTYPE_WLOCK; + StringName method_name = p_method->get_name(); + ClassInfo *type = classes.getptr(p_class); if (!type) { - ERR_FAIL_MSG(vformat("Couldn't bind custom method '%s' for instance '%s'.", p_method->get_name(), p_class)); + memdelete(p_method); + ERR_FAIL_MSG(vformat("Couldn't bind custom method '%s' for instance '%s'.", method_name, p_class)); } if (p_compatibility) { @@ -1876,16 +1879,17 @@ void ClassDB::_bind_method_custom(const StringName &p_class, MethodBind *p_metho return; } - if (type->method_map.has(p_method->get_name())) { + if (type->method_map.has(method_name)) { // overloading not supported - ERR_FAIL_MSG(vformat("Method already bound '%s::%s'.", p_class, p_method->get_name())); + memdelete(p_method); + ERR_FAIL_MSG(vformat("Method already bound '%s::%s'.", p_class, method_name)); } #ifdef DEBUG_METHODS_ENABLED - type->method_order.push_back(p_method->get_name()); + type->method_order.push_back(method_name); #endif - type->method_map[p_method->get_name()] = p_method; + type->method_map[method_name] = p_method; } MethodBind *ClassDB::_bind_vararg_method(MethodBind *p_bind, const StringName &p_name, const Vector &p_default_args, bool p_compatibility) { From 5c7fd16eea72f40bfb2ea8504d308d84dc328cbe Mon Sep 17 00:00:00 2001 From: DarioSamo Date: Tue, 28 Jan 2025 14:22:30 -0300 Subject: [PATCH 37/91] Fix framebuffer clear for particle collider heightfield. --- .../renderer_rd/forward_clustered/render_forward_clustered.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 70b3a89c4a68..53229ddfddb3 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -2862,7 +2862,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con { //regular forward for now RenderListParameters render_list_params(render_list[RENDER_LIST_SECONDARY].elements.ptr(), render_list[RENDER_LIST_SECONDARY].element_info.ptr(), render_list[RENDER_LIST_SECONDARY].elements.size(), false, pass_mode, 0, true, false, rp_uniform_set); - _render_list_with_draw_list(&render_list_params, p_fb); + _render_list_with_draw_list(&render_list_params, p_fb, RD::DRAW_CLEAR_ALL); } RD::get_singleton()->draw_command_end_label(); } From 2710c359d6bf9f170040b00035bf32586f4b0c3f Mon Sep 17 00:00:00 2001 From: ChildLearningClub Date: Sun, 26 Jan 2025 06:52:40 +0900 Subject: [PATCH 38/91] Changed if false to if true "Emoji and Symbols" menu is enabled. --- doc/classes/LineEdit.xml | 2 +- doc/classes/TextEdit.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index dd0d6ed4117e..c6cdacb6ec25 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -277,7 +277,7 @@ If [code]false[/code], existing text cannot be modified and new text cannot be added. - If [code]false[/code], "Emoji and Symbols" menu is enabled. + If [code]true[/code], "Emoji and Symbols" menu is enabled. If [code]true[/code], the [LineEdit] width will increase to stay longer than the [member text]. It will [b]not[/b] compress if the [member text] is shortened. diff --git a/doc/classes/TextEdit.xml b/doc/classes/TextEdit.xml index 89e2a2017af1..3b6f81aebc62 100644 --- a/doc/classes/TextEdit.xml +++ b/doc/classes/TextEdit.xml @@ -1300,7 +1300,7 @@ If [code]false[/code], existing text cannot be modified and new text cannot be added. - If [code]false[/code], "Emoji and Symbols" menu is enabled. + If [code]true[/code], "Emoji and Symbols" menu is enabled. If [code]true[/code], copying or cutting without a selection is performed on all lines with a caret. Otherwise, copy and cut require a selection. From d9bba033926d5b97d508fdc8be5fce4dbc9f5506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Tue, 28 Jan 2025 20:12:33 +0200 Subject: [PATCH 39/91] [Windows] Remove unused code from `godot_windows.cpp`. --- platform/windows/godot_windows.cpp | 84 ------------------------------ 1 file changed, 84 deletions(-) diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp index 486c3120fcad..8c5df46595ca 100644 --- a/platform/windows/godot_windows.cpp +++ b/platform/windows/godot_windows.cpp @@ -57,90 +57,6 @@ static const char dummy[8] __attribute__((section("pck"), used)) = { 0 }; #endif #endif -PCHAR * -CommandLineToArgvA( - PCHAR CmdLine, - int *_argc) { - PCHAR *argv; - PCHAR _argv; - ULONG len; - ULONG argc; - CHAR a; - ULONG i, j; - - BOOLEAN in_QM; - BOOLEAN in_TEXT; - BOOLEAN in_SPACE; - - len = strlen(CmdLine); - i = ((len + 2) / 2) * sizeof(PVOID) + sizeof(PVOID); - - argv = (PCHAR *)GlobalAlloc(GMEM_FIXED, - i + (len + 2) * sizeof(CHAR)); - - _argv = (PCHAR)(((PUCHAR)argv) + i); - - argc = 0; - argv[argc] = _argv; - in_QM = FALSE; - in_TEXT = FALSE; - in_SPACE = TRUE; - i = 0; - j = 0; - - a = CmdLine[i]; - while (a) { - if (in_QM) { - if (a == '\"') { - in_QM = FALSE; - } else { - _argv[j] = a; - j++; - } - } else { - switch (a) { - case '\"': - in_QM = TRUE; - in_TEXT = TRUE; - if (in_SPACE) { - argv[argc] = _argv + j; - argc++; - } - in_SPACE = FALSE; - break; - case ' ': - case '\t': - case '\n': - case '\r': - if (in_TEXT) { - _argv[j] = '\0'; - j++; - } - in_TEXT = FALSE; - in_SPACE = TRUE; - break; - default: - in_TEXT = TRUE; - if (in_SPACE) { - argv[argc] = _argv + j; - argc++; - } - _argv[j] = a; - j++; - in_SPACE = FALSE; - break; - } - } - i++; - a = CmdLine[i]; - } - _argv[j] = '\0'; - argv[argc] = nullptr; - - (*_argc) = argc; - return argv; -} - char *wc_to_utf8(const wchar_t *wc) { int ulen = WideCharToMultiByte(CP_UTF8, 0, wc, -1, nullptr, 0, nullptr, nullptr); char *ubuf = new char[ulen + 1]; From 964cd6525e7292c73784cfd89c419021160305d5 Mon Sep 17 00:00:00 2001 From: MathdudeMan Date: Tue, 28 Jan 2025 20:56:55 -0500 Subject: [PATCH 40/91] Fix: Mass property particle shader error --- drivers/gles3/shaders/particles.glsl | 2 +- drivers/gles3/storage/material_storage.cpp | 2 +- servers/rendering/renderer_rd/shaders/particles.glsl | 2 +- servers/rendering/renderer_rd/storage_rd/particles_storage.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index bdc28e292e2d..03c94e566390 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -342,7 +342,7 @@ void main() { mediump float attractor_attenuation = attractors[i].attenuation; amount = pow(amount, attractor_attenuation); dir = safe_normalize(mix(dir, attractors[i].transform[2].xyz, attractors[i].directionality)); - attractor_force -= amount * dir * attractors[i].strength; + attractor_force -= mass * amount * dir * attractors[i].strength; } float particle_size = particle_size; diff --git a/drivers/gles3/storage/material_storage.cpp b/drivers/gles3/storage/material_storage.cpp index abaa507453e7..67dd9bcb4ee4 100644 --- a/drivers/gles3/storage/material_storage.cpp +++ b/drivers/gles3/storage/material_storage.cpp @@ -1392,7 +1392,7 @@ MaterialStorage::MaterialStorage() { actions.renames["COLOR"] = "out_color"; actions.renames["VELOCITY"] = "out_velocity_flags.xyz"; - //actions.renames["MASS"] = "mass"; ? + actions.renames["MASS"] = "mass"; actions.renames["ACTIVE"] = "particle_active"; actions.renames["RESTART"] = "restart"; actions.renames["CUSTOM"] = "out_custom"; diff --git a/servers/rendering/renderer_rd/shaders/particles.glsl b/servers/rendering/renderer_rd/shaders/particles.glsl index a8f27ba726ee..20aa6c208454 100644 --- a/servers/rendering/renderer_rd/shaders/particles.glsl +++ b/servers/rendering/renderer_rd/shaders/particles.glsl @@ -488,7 +488,7 @@ void main() { } amount = pow(amount, FRAME.attractors[i].attenuation); dir = safe_normalize(mix(dir, FRAME.attractors[i].transform[2].xyz, FRAME.attractors[i].directionality)); - attractor_force -= amount * dir * FRAME.attractors[i].strength; + attractor_force -= mass * amount * dir * FRAME.attractors[i].strength; } float particle_size = FRAME.particle_size; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index b5954132571c..6bb7eff83cf2 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -68,7 +68,7 @@ ParticlesStorage::ParticlesStorage() { actions.renames["COLOR"] = "PARTICLE.color"; actions.renames["VELOCITY"] = "PARTICLE.velocity"; - //actions.renames["MASS"] = "mass"; ? + actions.renames["MASS"] = "mass"; actions.renames["ACTIVE"] = "particle_active"; actions.renames["RESTART"] = "restart"; actions.renames["CUSTOM"] = "PARTICLE.custom"; From 318af42020cd349c5c9c3e4c88aa87249ca224b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Wed, 8 Jan 2025 13:21:47 +0100 Subject: [PATCH 41/91] Include more attributes in the global class names cache --- core/config/project_settings.cpp | 4 +- core/object/script_language.cpp | 33 +++- core/object/script_language.h | 8 +- core/object/script_language_extension.h | 8 +- editor/create_dialog.cpp | 10 +- editor/editor_file_system.cpp | 152 ++++++++---------- editor/editor_file_system.h | 50 +++--- modules/gdscript/gdscript.cpp | 8 +- modules/gdscript/gdscript.h | 2 +- .../gdscript/tests/gdscript_test_runner.cpp | 6 +- modules/gdscript/tests/test_gdscript.cpp | 4 +- modules/mono/csharp_script.cpp | 4 +- modules/mono/csharp_script.h | 2 +- .../Core/Bridge/ManagedCallbacks.cs | 2 +- .../Core/Bridge/ScriptManagerBridge.cs | 12 +- modules/mono/mono_gd/gd_mono_cache.h | 2 +- 16 files changed, 174 insertions(+), 133 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index fdcd4f9b6064..a12b89683118 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1263,10 +1263,10 @@ void ProjectSettings::refresh_global_class_list() { Array script_classes = get_global_class_list(); for (int i = 0; i < script_classes.size(); i++) { Dictionary c = script_classes[i]; - if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { + if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base") || !c.has("is_abstract") || !c.has("is_tool")) { continue; } - ScriptServer::add_global_class(c["class"], c["base"], c["language"], c["path"]); + ScriptServer::add_global_class(c["class"], c["base"], c["language"], c["path"], c["is_abstract"], c["is_tool"]); } } diff --git a/core/object/script_language.cpp b/core/object/script_language.cpp index 4ef53dba1dff..33bf7ab48a0f 100644 --- a/core/object/script_language.cpp +++ b/core/object/script_language.cpp @@ -269,10 +269,10 @@ void ScriptServer::init_languages() { for (const Variant &script_class : script_classes) { Dictionary c = script_class; - if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { + if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base") || !c.has("is_abstract") || !c.has("is_tool")) { continue; } - add_global_class(c["class"], c["base"], c["language"], c["path"]); + add_global_class(c["class"], c["base"], c["language"], c["path"], c["is_abstract"], c["is_tool"]); } ProjectSettings::get_singleton()->clear("_global_script_classes"); } @@ -281,10 +281,10 @@ void ScriptServer::init_languages() { Array script_classes = ProjectSettings::get_singleton()->get_global_class_list(); for (const Variant &script_class : script_classes) { Dictionary c = script_class; - if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base")) { + if (!c.has("class") || !c.has("language") || !c.has("path") || !c.has("base") || !c.has("is_abstract") || !c.has("is_tool")) { continue; } - add_global_class(c["class"], c["base"], c["language"], c["path"]); + add_global_class(c["class"], c["base"], c["language"], c["path"], c["is_abstract"], c["is_tool"]); } } @@ -390,7 +390,7 @@ void ScriptServer::global_classes_clear() { inheriters_cache.clear(); } -void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path) { +void ScriptServer::add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path, bool p_is_abstract, bool p_is_tool) { ERR_FAIL_COND_MSG(p_class == p_base || (global_classes.has(p_base) && get_global_class_native_base(p_base) == p_class), "Cyclic inheritance in script class."); GlobalScriptClass *existing = global_classes.getptr(p_class); if (existing) { @@ -399,6 +399,8 @@ void ScriptServer::add_global_class(const StringName &p_class, const StringName existing->base = p_base; existing->path = p_path; existing->language = p_language; + existing->is_abstract = p_is_abstract; + existing->is_tool = p_is_tool; inheriters_cache_dirty = true; } } else { @@ -407,6 +409,8 @@ void ScriptServer::add_global_class(const StringName &p_class, const StringName g.language = p_language; g.path = p_path; g.base = p_base; + g.is_abstract = p_is_abstract; + g.is_tool = p_is_tool; global_classes[p_class] = g; inheriters_cache_dirty = true; } @@ -480,6 +484,16 @@ StringName ScriptServer::get_global_class_native_base(const String &p_class) { return base; } +bool ScriptServer::is_global_class_abstract(const String &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), false); + return global_classes[p_class].is_abstract; +} + +bool ScriptServer::is_global_class_tool(const String &p_class) { + ERR_FAIL_COND_V(!global_classes.has(p_class), false); + return global_classes[p_class].is_tool; +} + void ScriptServer::get_global_class_list(List *r_global_classes) { List classes; for (const KeyValue &E : global_classes) { @@ -507,12 +521,15 @@ void ScriptServer::save_global_classes() { get_global_class_list(&gc); Array gcarr; for (const StringName &E : gc) { + const GlobalScriptClass &global_class = global_classes[E]; Dictionary d; d["class"] = E; - d["language"] = global_classes[E].language; - d["path"] = global_classes[E].path; - d["base"] = global_classes[E].base; + d["language"] = global_class.language; + d["path"] = global_class.path; + d["base"] = global_class.base; d["icon"] = class_icons.get(E, ""); + d["is_abstract"] = global_class.is_abstract; + d["is_tool"] = global_class.is_tool; gcarr.push_back(d); } ProjectSettings::get_singleton()->store_global_class_list(gcarr); diff --git a/core/object/script_language.h b/core/object/script_language.h index 6ceeb4287512..8158d633ae14 100644 --- a/core/object/script_language.h +++ b/core/object/script_language.h @@ -62,6 +62,8 @@ class ScriptServer { StringName language; String path; StringName base; + bool is_abstract = false; + bool is_tool = false; }; static HashMap global_classes; @@ -86,7 +88,7 @@ class ScriptServer { static void thread_exit(); static void global_classes_clear(); - static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path); + static void add_global_class(const StringName &p_class, const StringName &p_base, const StringName &p_language, const String &p_path, bool p_is_abstract, bool p_is_tool); static void remove_global_class(const StringName &p_class); static void remove_global_class_by_path(const String &p_path); static bool is_global_class(const StringName &p_class); @@ -94,6 +96,8 @@ class ScriptServer { static String get_global_class_path(const String &p_class); static StringName get_global_class_base(const String &p_class); static StringName get_global_class_native_base(const String &p_class); + static bool is_global_class_abstract(const String &p_class); + static bool is_global_class_tool(const String &p_class); static void get_global_class_list(List *r_global_classes); static void get_inheriters_list(const StringName &p_base_type, List *r_classes); static void save_global_classes(); @@ -443,7 +447,7 @@ class ScriptLanguage : public Object { virtual void frame(); virtual bool handles_global_class_type(const String &p_type) const { return false; } - virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const { return String(); } + virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr, bool *r_is_abstract = nullptr, bool *r_is_tool = nullptr) const { return String(); } virtual ~ScriptLanguage() {} }; diff --git a/core/object/script_language_extension.h b/core/object/script_language_extension.h index 09c395e71e8d..715ec43fb35a 100644 --- a/core/object/script_language_extension.h +++ b/core/object/script_language_extension.h @@ -672,7 +672,7 @@ class ScriptLanguageExtension : public ScriptLanguage { GDVIRTUAL1RC_REQUIRED(Dictionary, _get_global_class_name, const String &) - virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr) const override { + virtual String get_global_class_name(const String &p_path, String *r_base_type = nullptr, String *r_icon_path = nullptr, bool *r_is_abstract = nullptr, bool *r_is_tool = nullptr) const override { Dictionary ret; GDVIRTUAL_CALL(_get_global_class_name, p_path, ret); if (!ret.has("name")) { @@ -684,6 +684,12 @@ class ScriptLanguageExtension : public ScriptLanguage { if (r_icon_path != nullptr && ret.has("icon_path")) { *r_icon_path = ret["icon_path"]; } + if (r_is_abstract != nullptr && ret.has("is_abstract")) { + *r_is_abstract = ret["is_abstract"]; + } + if (r_is_tool != nullptr && ret.has("is_tool")) { + *r_is_tool = ret["is_tool"]; + } return ret["name"]; } }; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 7f1670bcb648..f0b2ed6e4691 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -315,18 +315,14 @@ void CreateDialog::_configure_search_option_item(TreeItem *r_item, const StringN r_item->set_metadata(0, p_type); r_item->set_text(0, p_type); - String script_path = ScriptServer::get_global_class_path(p_type); - Ref