diff options
24 files changed, 315 insertions, 16 deletions
diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 295b477080..1afd59e99c 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -542,7 +542,7 @@ void EditorExportPlatform::_edit_filter_list(Set<String> &r_list, const String & filters.push_back(f); } - DirAccess *da = DirAccess::open("res://"); + DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES); ERR_FAIL_NULL(da); _edit_files_with_filter(da, filters, r_list, exclude); memdelete(da); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 3cad600002..0a8d35aff1 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -645,7 +645,7 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ // To support custom Android builds, we install the Java source code and buildsystem // from android_source.zip to the project's res://android folder. - DirAccessRef da = DirAccess::open("res://"); + DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); // Make res://android dir (if it does not exist). diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b41123c0dd..e8a2a46dd2 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -396,12 +396,25 @@ void FileSystemDock::_notification(int p_what) { } } else if ((String(dd["type"]) == "files") || (String(dd["type"]) == "files_and_dirs") || (String(dd["type"]) == "resource")) { tree->set_drop_mode_flags(Tree::DROP_MODE_ON_ITEM | Tree::DROP_MODE_INBETWEEN); + } else if ((String(dd["type"]) == "nodes")) { + holding_branch = true; + TreeItem *item = tree->get_next_selected(tree->get_root()); + while (item) { + tree_items_selected_on_drag_begin.push_back(item); + item = tree->get_next_selected(item); + } + list_items_selected_on_drag_begin = files->get_selected_items(); } } } break; case NOTIFICATION_DRAG_END: { tree->set_drop_mode_flags(0); + + if (holding_branch) { + holding_branch = false; + _reselect_items_selected_on_drag_begin(true); + } } break; case NOTIFICATION_THEME_CHANGED: { @@ -512,7 +525,7 @@ void FileSystemDock::_navigate_to_path(const String &p_path, bool p_select_in_fa if (target_path.ends_with("/")) { target_path = target_path.substr(0, target_path.length() - 1); } - DirAccess *dirAccess = DirAccess::open("res://"); + DirAccess *dirAccess = DirAccess::create(DirAccess::ACCESS_RESOURCES); if (dirAccess->file_exists(p_path)) { path = target_path; } else if (dirAccess->dir_exists(p_path)) { @@ -2647,8 +2660,79 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) { call_deferred(SNAME("_update_import_dock")); } +void FileSystemDock::_tree_mouse_exited() { + if (holding_branch) { + _reselect_items_selected_on_drag_begin(); + } +} + +void FileSystemDock::_reselect_items_selected_on_drag_begin(bool reset) { + TreeItem *selected_item = tree->get_next_selected(tree->get_root()); + if (selected_item) { + selected_item->deselect(0); + } + if (!tree_items_selected_on_drag_begin.is_empty()) { + bool reselected = false; + for (TreeItem *item : tree_items_selected_on_drag_begin) { + if (item->get_tree()) { + item->select(0); + reselected = true; + } + } + + if (reset) { + tree_items_selected_on_drag_begin.clear(); + } + + if (!reselected) { + // If couldn't reselect the items selected on drag begin, select the "res://" item. + tree->get_root()->get_child(1)->select(0); + } + } + + files->deselect_all(); + if (!list_items_selected_on_drag_begin.is_empty()) { + for (const int idx : list_items_selected_on_drag_begin) { + files->select(idx, false); + } + + if (reset) { + list_items_selected_on_drag_begin.clear(); + } + } +} + void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> key = p_event; + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid()) { + TreeItem *item = tree->get_item_at_position(mm->get_position()); + if (item && holding_branch) { + String fpath = item->get_metadata(0); + while (!fpath.ends_with("/") && fpath != "res://" && item->get_parent()) { // Find the parent folder tree item. + item = item->get_parent(); + fpath = item->get_metadata(0); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + item->select(0); + + if (display_mode == DisplayMode::DISPLAY_MODE_SPLIT) { + files->deselect_all(); + // Try to select the corresponding file list item. + const int files_item_idx = files->find_metadata(fpath); + if (files_item_idx != -1) { + files->select(files_item_idx); + } + } + } + } + if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { _tree_rmb_option(FILE_DUPLICATE); @@ -2669,6 +2753,43 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) { } void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) { + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && holding_branch) { + const int item_idx = files->get_item_at_position(mm->get_position()); + if (item_idx != -1) { + files->deselect_all(); + String fpath = files->get_item_metadata(item_idx); + if (fpath.ends_with("/") || fpath == "res://") { + files->select(item_idx); + } + + TreeItem *deselect_item = tree->get_next_selected(tree->get_root()); + while (deselect_item) { + deselect_item->deselect(0); + deselect_item = tree->get_next_selected(deselect_item); + } + + // Try to select the corresponding tree item. + TreeItem *tree_item = tree->get_item_with_text(files->get_item_text(item_idx)); + if (tree_item) { + tree_item->select(0); + } else { + // Find parent folder. + fpath = fpath.substr(0, fpath.rfind("/") + 1); + if (fpath.size() > String("res://").size()) { + fpath = fpath.left(fpath.size() - 2); // Remove last '/'. + const int slash_idx = fpath.rfind("/"); + fpath = fpath.substr(slash_idx + 1, fpath.size() - slash_idx - 1); + } + + tree_item = tree->get_item_with_text(fpath); + if (tree_item) { + tree_item->select(0); + } + } + } + } + Ref<InputEventKey> key = p_event; if (key.is_valid() && key->is_pressed() && !key->is_echo()) { if (ED_IS_SHORTCUT("filesystem_dock/duplicate", p_event)) { @@ -2932,6 +3053,7 @@ FileSystemDock::FileSystemDock() { tree->connect("empty_rmb", callable_mp(this, &FileSystemDock::_tree_rmb_empty)); tree->connect("nothing_selected", callable_mp(this, &FileSystemDock::_tree_empty_selected)); tree->connect("gui_input", callable_mp(this, &FileSystemDock::_tree_gui_input)); + tree->connect("mouse_exited", callable_mp(this, &FileSystemDock::_tree_mouse_exited)); file_list_vb = memnew(VBoxContainer); file_list_vb->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/filesystem_dock.h b/editor/filesystem_dock.h index 21c50beeb2..d457c6acd4 100644 --- a/editor/filesystem_dock.h +++ b/editor/filesystem_dock.h @@ -185,6 +185,13 @@ private: ItemList *files; bool import_dock_needs_update; + bool holding_branch = false; + Vector<TreeItem *> tree_items_selected_on_drag_begin; + PackedInt32Array list_items_selected_on_drag_begin; + + void _tree_mouse_exited(); + void _reselect_items_selected_on_drag_begin(bool reset = false); + Ref<Texture2D> _get_tree_item_icon(bool p_is_valid, String p_file_type); bool _create_tree(TreeItem *p_parent, EditorFileSystemDirectory *p_dir, Vector<String> &uncollapsed_paths, bool p_select_in_favorites, bool p_unfold_path = false); Vector<String> _compute_uncollapsed_paths(); diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 3ff8b2b91a..547fd1cfd5 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1139,7 +1139,7 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * #endif // TOOLS_ENABLED } - if (p_function->identifier->name == "_init") { + if (p_function->identifier->name == GDScriptLanguage::get_singleton()->strings._init) { // Constructor. GDScriptParser::DataType return_type = parser->current_class->get_datatype(); return_type.is_meta_type = false; @@ -1153,6 +1153,57 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode * } else { GDScriptParser::DataType return_type = resolve_datatype(p_function->return_type); p_function->set_datatype(return_type); + +#ifdef DEBUG_ENABLED + // Check if the function signature matches the parent. If not it's an error since it breaks polymorphism. + // Not for the constructor which can vary in signature. + GDScriptParser::DataType base_type = parser->current_class->base_type; + GDScriptParser::DataType parent_return_type; + List<GDScriptParser::DataType> parameters_types; + int default_par_count = 0; + bool is_static = false; + bool is_vararg = false; + if (get_function_signature(p_function, false, base_type, p_function->identifier->name, parent_return_type, parameters_types, default_par_count, is_static, is_vararg)) { + bool valid = p_function->is_static == is_static; + valid = valid && parent_return_type == p_function->get_datatype(); + + int par_count_diff = p_function->parameters.size() - parameters_types.size(); + valid = valid && par_count_diff >= 0; + valid = valid && p_function->default_arg_values.size() >= default_par_count + par_count_diff; + + int i = 0; + for (const GDScriptParser::DataType &par_type : parameters_types) { + valid = valid && par_type == p_function->parameters[i++]->get_datatype(); + } + + if (!valid) { + // Compute parent signature as a string to show in the error message. + String parent_signature = parent_return_type.is_hard_type() ? parent_return_type.to_string() : "Variant"; + if (parent_signature == "null") { + parent_signature = "void"; + } + parent_signature += " " + p_function->identifier->name.operator String() + "("; + int j = 0; + for (const GDScriptParser::DataType &par_type : parameters_types) { + if (j > 0) { + parent_signature += ", "; + } + String parameter = par_type.to_string(); + if (parameter == "null") { + parameter = "Variant"; + } + parent_signature += parameter; + if (j == parameters_types.size() - default_par_count) { + parent_signature += " = default"; + } + + j++; + } + parent_signature += ")"; + push_error(vformat(R"(The function signature doesn't match the parent. Parent signature is "%s".)", parent_signature), p_function); + } + } +#endif } parser->current_function = previous_function; @@ -2416,7 +2467,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a GDScriptParser::DataType return_type; List<GDScriptParser::DataType> par_types; - if (get_function_signature(p_call, base_type, p_call->function_name, return_type, par_types, default_arg_count, is_static, is_vararg)) { + bool is_constructor = (base_type.is_meta_type || (p_call->callee && p_call->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_call->function_name == SNAME("new"); + + if (get_function_signature(p_call, is_constructor, base_type, p_call->function_name, return_type, par_types, default_arg_count, is_static, is_vararg)) { // If the function require typed arrays we must make literals be typed. for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) { int index = E.key; @@ -3576,7 +3629,7 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo return result; } -bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) { +bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg) { r_static = false; r_vararg = false; r_default_arg_count = 0; @@ -3616,8 +3669,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source return false; } - bool is_constructor = (p_base_type.is_meta_type || (p_source->callee && p_source->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_function == StaticCString::create("new"); - if (is_constructor) { + if (p_is_constructor) { function_name = "_init"; r_static = true; } @@ -3638,7 +3690,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } if (found_function != nullptr) { - r_static = is_constructor || found_function->is_static; + r_static = p_is_constructor || found_function->is_static; for (int i = 0; i < found_function->parameters.size(); i++) { r_par_types.push_back(found_function->parameters[i]->get_datatype()); if (found_function->parameters[i]->default_value != nullptr) { @@ -3664,7 +3716,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } // If the base is a script, it might be trying to access members of the Script class itself. - if (p_base_type.is_meta_type && !is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) { + if (p_base_type.is_meta_type && !p_is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) { MethodInfo info; StringName script_class = p_base_type.kind == GDScriptParser::DataType::SCRIPT ? p_base_type.script_type->get_class_name() : StringName(GDScript::get_class_static()); @@ -3684,7 +3736,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::CallNode *p_source } #endif - if (is_constructor) { + if (p_is_constructor) { // Native types always have a default constructor. r_return_type = p_base_type; r_return_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; diff --git a/modules/gdscript/gdscript_analyzer.h b/modules/gdscript/gdscript_analyzer.h index 2697a6ec2b..7b8883e1d3 100644 --- a/modules/gdscript/gdscript_analyzer.h +++ b/modules/gdscript/gdscript_analyzer.h @@ -105,7 +105,7 @@ class GDScriptAnalyzer { GDScriptParser::DataType type_from_metatype(const GDScriptParser::DataType &p_meta_type) const; GDScriptParser::DataType type_from_property(const PropertyInfo &p_property) const; GDScriptParser::DataType make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source); - bool get_function_signature(GDScriptParser::CallNode *p_source, GDScriptParser::DataType base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); + bool get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); bool function_signature_from_info(const MethodInfo &p_info, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, bool &r_static, bool &r_vararg); bool validate_call_arg(const List<GDScriptParser::DataType> &p_par_types, int p_default_args_count, bool p_is_vararg, const GDScriptParser::CallNode *p_call); bool validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call); diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd new file mode 100644 index 0000000000..435711fcaf --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function() -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_less.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd new file mode 100644 index 0000000000..2bd392e8f8 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function(_pary1: int, _par2: int) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_count_more.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd new file mode 100644 index 0000000000..49ec82ce2d --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int = 0) -> int: + return 0 + +class Child extends Parent: + func my_function(_par1: int) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out new file mode 100644 index 0000000000..665c229339 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_default_values.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int = default)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd new file mode 100644 index 0000000000..4a17a7831f --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function(_par1: int) -> int: + return 0 + +class Child extends Parent: + func my_function(_par1: Vector2) -> int: + return 0 diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out new file mode 100644 index 0000000000..3baeb17066 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_parameter_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function(int)". diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd new file mode 100644 index 0000000000..b205ec96ef --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.gd @@ -0,0 +1,10 @@ +func test(): + print("Shouldn't reach this") + +class Parent: + func my_function() -> int: + return 0 + +class Child extends Parent: + func my_function() -> Vector2: + return Vector2() diff --git a/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out new file mode 100644 index 0000000000..5b22739a93 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/function_dont_match_parent_signature_return_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +The function signature doesn't match the parent. Parent signature is "int my_function()". diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd new file mode 100644 index 0000000000..d678f3acfc --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.gd @@ -0,0 +1,17 @@ +func test(): + var instance := Parent.new() + var result := instance.my_function(1) + print(result) + assert(result == 1) + instance = Child.new() + result = instance.my_function(2) + print(result) + assert(result == 0) + +class Parent: + func my_function(par1: int) -> int: + return par1 + +class Child extends Parent: + func my_function(_par1: int, par2: int = 0) -> int: + return par2 diff --git a/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out new file mode 100644 index 0000000000..fc5315a501 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/function_match_parent_signature_with_extra_parameters.out @@ -0,0 +1,3 @@ +GDTEST_OK +1 +0 diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index 8679f28132..ee218cb1f8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -81,6 +81,15 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y) + { + x = this.x; + y = this.y; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index 9b51de5c8c..412a885daa 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -82,6 +82,15 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y) + { + x = this.x; + y = this.y; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 1e60fb9523..45e5287610 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -96,6 +96,16 @@ namespace Godot } } + /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out real_t x, out real_t y, out real_t z) + { + x = this.x; + y = this.y; + z = this.z; + } + internal void Normalize() { real_t lengthsq = LengthSquared(); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index eb06d2b87e..abfd2ae720 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -97,6 +97,16 @@ namespace Godot } /// <summary> + /// Helper method for deconstruction into a tuple. + /// </summary> + public void Deconstruct(out int x, out int y, out int z) + { + x = this.x; + y = this.y; + z = this.z; + } + + /// <summary> /// Returns a new vector with all components in absolute values (i.e. positive). /// </summary> /// <returns>A vector with <see cref="Mathf.Abs(int)"/> called on each component.</returns> diff --git a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp index 6d46f6074e..06f035a506 100644 --- a/servers/physics_2d/godot_broad_phase_2d_bvh.cpp +++ b/servers/physics_2d/godot_broad_phase_2d_bvh.cpp @@ -33,7 +33,7 @@ GodotBroadPhase2D::ID GodotBroadPhase2DBVH::create(GodotCollisionObject2D *p_object, int p_subindex, const Rect2 &p_aabb, bool p_static) { uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; - uint32_t tree_collision_mask = p_static ? 0 : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); + uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care? return oid + 1; } @@ -44,7 +44,7 @@ void GodotBroadPhase2DBVH::move(ID p_id, const Rect2 &p_aabb) { void GodotBroadPhase2DBVH::set_static(ID p_id, bool p_static) { uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; - uint32_t tree_collision_mask = p_static ? 0 : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); + uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false); } diff --git a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp index d947892751..ecdf74fd41 100644 --- a/servers/physics_3d/godot_broad_phase_3d_bvh.cpp +++ b/servers/physics_3d/godot_broad_phase_3d_bvh.cpp @@ -34,7 +34,7 @@ GodotBroadPhase3DBVH::ID GodotBroadPhase3DBVH::create(GodotCollisionObject3D *p_object, int p_subindex, const AABB &p_aabb, bool p_static) { uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; - uint32_t tree_collision_mask = p_static ? 0 : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); + uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); ID oid = bvh.create(p_object, true, tree_id, tree_collision_mask, p_aabb, p_subindex); // Pair everything, don't care? return oid + 1; } @@ -45,7 +45,7 @@ void GodotBroadPhase3DBVH::move(ID p_id, const AABB &p_aabb) { void GodotBroadPhase3DBVH::set_static(ID p_id, bool p_static) { uint32_t tree_id = p_static ? TREE_STATIC : TREE_DYNAMIC; - uint32_t tree_collision_mask = p_static ? 0 : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); + uint32_t tree_collision_mask = p_static ? TREE_FLAG_DYNAMIC : (TREE_FLAG_STATIC | TREE_FLAG_DYNAMIC); bvh.set_tree(p_id - 1, tree_id, tree_collision_mask, false); } |