diff options
32 files changed, 301 insertions, 141 deletions
diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index 9ba653e1a9..9f89f5d8c9 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -1813,3 +1813,24 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo return OK; } + +Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count) { + // We always allocate a new array, and we don't memcpy. + // We also don't consider returning a pointer to the passed vectors when sizeof(real_t) == 4. + // One reason is that we could decide to put a 4th component in Vector3 for SIMD/mobile performance, + // which would cause trouble with these optimizations. + Vector<float> floats; + if (count == 0) { + return floats; + } + floats.resize(count * 3); + float *floats_w = floats.ptrw(); + for (size_t i = 0; i < count; ++i) { + const Vector3 v = vecs[i]; + floats_w[0] = v.x; + floats_w[1] = v.y; + floats_w[2] = v.z; + floats_w += 3; + } + return floats; +} diff --git a/core/io/marshalls.h b/core/io/marshalls.h index fef3a1c2c1..66e2571066 100644 --- a/core/io/marshalls.h +++ b/core/io/marshalls.h @@ -215,4 +215,6 @@ public: Error decode_variant(Variant &r_variant, const uint8_t *p_buffer, int p_len, int *r_len = nullptr, bool p_allow_objects = false, int p_depth = 0); Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bool p_full_objects = false, int p_depth = 0); +Vector<float> vector3_to_float32_array(const Vector3 *vecs, size_t count); + #endif // MARSHALLS_H diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 8dff8e6e7e..a998dece2a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -453,7 +453,10 @@ public: } static _ALWAYS_INLINE_ double wrapf(double value, double min, double max) { double range = max - min; - double result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_zero_approx(range)) { + return min; + } + double result = value - (range * Math::floor((value - min) / range)); if (is_equal_approx(result, max)) { return min; } @@ -461,7 +464,10 @@ public: } static _ALWAYS_INLINE_ float wrapf(float value, float min, float max) { float range = max - min; - float result = is_zero_approx(range) ? min : value - (range * Math::floor((value - min) / range)); + if (is_zero_approx(range)) { + return min; + } + float result = value - (range * Math::floor((value - min) / range)); if (is_equal_approx(result, max)) { return min; } diff --git a/editor/debugger/editor_debugger_tree.cpp b/editor/debugger/editor_debugger_tree.cpp index 8b31781c5e..351af4508f 100644 --- a/editor/debugger/editor_debugger_tree.cpp +++ b/editor/debugger/editor_debugger_tree.cpp @@ -118,6 +118,7 @@ void EditorDebuggerTree::_scene_tree_rmb_selected(const Vector2 &p_position, Mou item_menu->add_icon_item(get_theme_icon(SNAME("CreateNewSceneFrom"), SNAME("EditorIcons")), TTR("Save Branch as Scene"), ITEM_MENU_SAVE_REMOTE_NODE); item_menu->add_icon_item(get_theme_icon(SNAME("CopyNodePath"), SNAME("EditorIcons")), TTR("Copy Node Path"), ITEM_MENU_COPY_NODE_PATH); item_menu->set_position(get_screen_position() + get_local_mouse_position()); + item_menu->reset_size(); item_menu->popup(); } @@ -323,6 +324,8 @@ void EditorDebuggerTree::_item_menu_id_pressed(int p_option) { file_dialog->add_filter("*." + extensions[i], extensions[i].to_upper()); } + String filename = get_selected_path().get_file() + "." + extensions.front()->get().to_lower(); + file_dialog->set_current_path(filename); file_dialog->popup_file_dialog(); } break; case ITEM_MENU_COPY_NODE_PATH: { diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index affb31945d..1f350f1199 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -219,6 +219,7 @@ PluginConfigDialog::PluginConfigDialog() { GridContainer *grid = memnew(GridContainer); grid->set_columns(3); + grid->set_v_size_flags(Control::SIZE_EXPAND_FILL); vbox->add_child(grid); // Plugin Name @@ -234,6 +235,7 @@ PluginConfigDialog::PluginConfigDialog() { name_edit = memnew(LineEdit); name_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed)); name_edit->set_placeholder("MyPlugin"); + name_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid->add_child(name_edit); // Subfolder @@ -248,6 +250,7 @@ PluginConfigDialog::PluginConfigDialog() { subfolder_edit = memnew(LineEdit); subfolder_edit->set_placeholder("\"my_plugin\" -> res://addons/my_plugin"); + subfolder_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); subfolder_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed)); grid->add_child(subfolder_edit); @@ -263,6 +266,8 @@ PluginConfigDialog::PluginConfigDialog() { desc_edit = memnew(TextEdit); desc_edit->set_custom_minimum_size(Size2(400, 80) * EDSCALE); desc_edit->set_line_wrapping_mode(TextEdit::LineWrappingMode::LINE_WRAPPING_BOUNDARY); + desc_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); + desc_edit->set_v_size_flags(Control::SIZE_EXPAND_FILL); grid->add_child(desc_edit); // Author @@ -276,6 +281,7 @@ PluginConfigDialog::PluginConfigDialog() { author_edit = memnew(LineEdit); author_edit->set_placeholder("Godette"); + author_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid->add_child(author_edit); // Version @@ -289,6 +295,7 @@ PluginConfigDialog::PluginConfigDialog() { version_edit = memnew(LineEdit); version_edit->set_placeholder("1.0"); + version_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid->add_child(version_edit); // Language dropdown @@ -326,6 +333,7 @@ PluginConfigDialog::PluginConfigDialog() { script_edit = memnew(LineEdit); script_edit->connect("text_changed", callable_mp(this, &PluginConfigDialog::_on_required_text_changed)); script_edit->set_placeholder("\"plugin.gd\" -> res://addons/my_plugin/plugin.gd"); + script_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL); grid->add_child(script_edit); // Activate now checkbox diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index bb5491fcb5..562eddbc64 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -3003,6 +3003,7 @@ void ScriptEditor::shortcut_input(const Ref<InputEvent> &p_event) { _go_to_tab(script_list->get_item_metadata(next_tab)); _update_script_names(); } + accept_event(); } if (ED_IS_SHORTCUT("script_editor/prev_script", p_event)) { if (script_list->get_item_count() > 1) { @@ -3011,12 +3012,15 @@ void ScriptEditor::shortcut_input(const Ref<InputEvent> &p_event) { _go_to_tab(script_list->get_item_metadata(next_tab)); _update_script_names(); } + accept_event(); } if (ED_IS_SHORTCUT("script_editor/window_move_up", p_event)) { _menu_option(WINDOW_MOVE_UP); + accept_event(); } if (ED_IS_SHORTCUT("script_editor/window_move_down", p_event)) { _menu_option(WINDOW_MOVE_DOWN); + accept_event(); } } diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index c93b0019dc..3d0c1acff8 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -5383,6 +5383,10 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("Binormal", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "binormal", "BINORMAL"), { "binormal" }, VisualShaderNode::PORT_TYPE_VECTOR_3D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("Color", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_and_fragment_shader_modes, "color", "COLOR"), { "color" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Custom0", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom0", "CUSTOM0"), { "custom0" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Custom1", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom1", "CUSTOM1"), { "custom1" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Custom2", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom2", "CUSTOM2"), { "custom2" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("Custom3", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom3", "CUSTOM3"), { "custom3" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InstanceId", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_id", "INSTANCE_ID"), { "instance_id" }, VisualShaderNode::PORT_TYPE_SCALAR_INT, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("InstanceCustom", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "instance_custom", "INSTANCE_CUSTOM"), { "instance_custom" }, VisualShaderNode::PORT_TYPE_VECTOR_4D, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); add_options.push_back(AddOption("ModelViewMatrix", "Input/Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "modelview_matrix", "MODELVIEW_MATRIX"), { "modelview_matrix" }, VisualShaderNode::PORT_TYPE_TRANSFORM, TYPE_FLAGS_VERTEX, Shader::MODE_SPATIAL)); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index f91b571118..60d3925cd6 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -3217,6 +3217,7 @@ List<Node *> SceneTreeDock::paste_nodes() { if (!paste_parent) { paste_parent = dup; owner = dup; + dup->set_scene_file_path(String()); // Make sure the scene path is empty, to avoid accidental references. ur->add_do_method(EditorNode::get_singleton(), "set_edited_scene", dup); } else { ur->add_do_method(paste_parent, "add_child", dup, true); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index 1fe1561559..40bc2beb23 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -629,6 +629,10 @@ void GDScript::_update_doc() { } } + for (KeyValue<StringName, Ref<GDScript>> &E : subclasses) { + E.value->_update_doc(); + } + _add_doc(doc); } #endif diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 05d19863ca..6e2c3193cd 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -937,6 +937,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, const GDScriptParser::EnumNode *prev_enum = current_enum; current_enum = member.m_enum; + Dictionary dictionary; for (int j = 0; j < member.m_enum->values.size(); j++) { GDScriptParser::EnumNode::Value &element = member.m_enum->values.write[j]; @@ -960,11 +961,13 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, } enum_type.enum_values[element.identifier->name] = element.value; + dictionary[String(element.identifier->name)] = element.value; } current_enum = prev_enum; member.m_enum->set_datatype(enum_type); + member.m_enum->dictionary = dictionary; // Apply annotations. for (GDScriptParser::AnnotationNode *&E : member.m_enum->annotations) { @@ -2262,30 +2265,26 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig } p_assignment->set_datatype(op_type); - if (!assignee_type.is_variant() && assigned_value_type.is_hard_type()) { + if (assignee_type.is_hard_type() && !assignee_type.is_variant() && op_type.is_hard_type()) { if (compatible) { compatible = is_type_compatible(assignee_type, op_type, true, p_assignment->assigned_value); if (!compatible) { - if (assignee_type.is_hard_type()) { - // Try reverse test since it can be a masked subtype. - if (!is_type_compatible(op_type, assignee_type, true, p_assignment->assigned_value)) { - push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value); - } else { - // TODO: Add warning. - mark_node_unsafe(p_assignment); - p_assignment->use_conversion_assign = true; - } + // Try reverse test since it can be a masked subtype. + if (!is_type_compatible(op_type, assignee_type, true)) { + push_error(vformat(R"(Cannot assign a value of type "%s" to a target of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value); } else { - // TODO: Warning in this case. + // TODO: Add warning. mark_node_unsafe(p_assignment); + p_assignment->use_conversion_assign = true; } } } else { push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", assignee_type.to_string(), assigned_value_type.to_string()), p_assignment); } - } - - if (assignee_type.has_no_type() || assigned_value_type.is_variant()) { + } else if (assignee_type.is_hard_type() && !assignee_type.is_variant()) { + mark_node_unsafe(p_assignment); + p_assignment->use_conversion_assign = true; + } else { mark_node_unsafe(p_assignment); if (assignee_type.is_hard_type() && !assignee_type.is_variant()) { p_assignment->use_conversion_assign = true; @@ -3143,10 +3142,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT; break; case GDScriptParser::ClassNode::Member::ENUM: - if (p_base != nullptr && p_base->is_constant) { - p_identifier->is_constant = true; - p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT; - } + p_identifier->is_constant = true; + p_identifier->reduced_value = member.m_enum->dictionary; + p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT; break; case GDScriptParser::ClassNode::Member::VARIABLE: p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_VARIABLE; @@ -3200,7 +3198,8 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod return; case GDScriptParser::ClassNode::Member::ENUM: p_identifier->set_datatype(member.get_datatype()); - p_identifier->is_constant = false; + p_identifier->is_constant = true; + p_identifier->reduced_value = member.m_enum->dictionary; return; case GDScriptParser::ClassNode::Member::CLASS: p_identifier->set_datatype(member.get_datatype()); @@ -4177,7 +4176,7 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo r_default_arg_count++; } } - r_return_type = found_function->get_datatype(); + r_return_type = p_is_constructor ? p_base_type : found_function->get_datatype(); r_return_type.is_meta_type = false; r_return_type.is_coroutine = found_function->is_coroutine; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index cf9e734b05..f4b468449b 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -2453,26 +2453,20 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri case GDScriptParser::ClassNode::Member::ENUM: { const GDScriptParser::EnumNode *enum_n = member.m_enum; + StringName name = enum_n->identifier->name; - // TODO: Make enums not be just a dictionary? - Dictionary new_enum; - for (int j = 0; j < enum_n->values.size(); j++) { - // Needs to be string because Variant::get will convert to String. - new_enum[String(enum_n->values[j].identifier->name)] = enum_n->values[j].value; - } - - p_script->constants.insert(enum_n->identifier->name, new_enum); + p_script->constants.insert(name, enum_n->dictionary); #ifdef TOOLS_ENABLED - p_script->member_lines[enum_n->identifier->name] = enum_n->start_line; - p_script->doc_enums[enum_n->identifier->name] = DocData::EnumDoc(); - p_script->doc_enums[enum_n->identifier->name].name = enum_n->identifier->name; - p_script->doc_enums[enum_n->identifier->name].description = enum_n->doc_description; + p_script->member_lines[name] = enum_n->start_line; + p_script->doc_enums[name] = DocData::EnumDoc(); + p_script->doc_enums[name].name = name; + p_script->doc_enums[name].description = enum_n->doc_description; for (int j = 0; j < enum_n->values.size(); j++) { DocData::ConstantDoc const_doc; const_doc.name = enum_n->values[j].identifier->name; const_doc.value = Variant(enum_n->values[j].value).operator String(); const_doc.description = enum_n->values[j].doc_description; - p_script->doc_enums[enum_n->identifier->name].values.push_back(const_doc); + p_script->doc_enums[name].values.push_back(const_doc); } #endif } break; @@ -2642,10 +2636,6 @@ Error GDScriptCompiler::_compile_class(GDScript *p_script, const GDScriptParser: } } -#ifdef TOOLS_ENABLED - p_script->_update_doc(); -#endif - p_script->_init_rpc_methods_properties(); p_script->valid = true; @@ -2730,6 +2720,10 @@ Error GDScriptCompiler::compile(const GDScriptParser *p_parser, GDScript *p_scri return err; } +#ifdef TOOLS_ENABLED + p_script->_update_doc(); +#endif + return GDScriptCache::finish_compiling(main_script->get_path()); } diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 540ef1c561..fd2f7b3288 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -483,6 +483,7 @@ public: IdentifierNode *identifier = nullptr; Vector<Value> values; + Variant dictionary; #ifdef TOOLS_ENABLED String doc_description; #endif // TOOLS_ENABLED diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd new file mode 100644 index 0000000000..251be70088 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.gd @@ -0,0 +1,10 @@ +class A: + func _init(): + pass + +class B extends A: pass +class C extends A: pass + +func test(): + var x := B.new() + print(x is C) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out new file mode 100644 index 0000000000..91d5125ec0 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/constructor_call_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Expression is of type "B" so it can't be of type "C". diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd new file mode 100644 index 0000000000..2ce588373b --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd @@ -0,0 +1,29 @@ +class Outer: + enum OuterEnum { OuterValue = 3 } + const OuterConst := OuterEnum + + class Inner: + enum InnerEnum { InnerValue = 7 } + const InnerConst := InnerEnum + + static func test() -> void: + print(OuterEnum.size()); + print(OuterEnum.OuterValue); + print(OuterConst.size()); + print(OuterConst.OuterValue); + print(Outer.OuterEnum.size()); + print(Outer.OuterEnum.OuterValue); + print(Outer.OuterConst.size()); + print(Outer.OuterConst.OuterValue); + + print(InnerEnum.size()); + print(InnerEnum.InnerValue); + print(InnerConst.size()); + print(InnerConst.InnerValue); + print(Inner.InnerEnum.size()); + print(Inner.InnerEnum.InnerValue); + print(Inner.InnerConst.size()); + print(Inner.InnerConst.InnerValue); + +func test(): + Outer.Inner.test() diff --git a/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out new file mode 100644 index 0000000000..e049f85b6e --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out @@ -0,0 +1,17 @@ +GDTEST_OK +1 +3 +1 +3 +1 +3 +1 +3 +1 +7 +1 +7 +1 +7 +1 +7 diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd new file mode 100644 index 0000000000..22e54cf91c --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.gd @@ -0,0 +1,9 @@ +func test(): + var x: int = 2 + var y = 3.14 + var z := 2.72 + print(typeof(x)) + x = y + print(typeof(x)) + x = z + print(typeof(x)) diff --git a/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out new file mode 100644 index 0000000000..4a268dd8e0 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/typed_assignment.out @@ -0,0 +1,12 @@ +GDTEST_OK +>> WARNING +>> Line: 6 +>> NARROWING_CONVERSION +>> Narrowing conversion (float is converted to int and loses precision). +>> WARNING +>> Line: 8 +>> NARROWING_CONVERSION +>> Narrowing conversion (float is converted to int and loses precision). +2 +2 +2 diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs index fb32f6192f..eae7e41da8 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPathAttributeGenerator.cs @@ -45,8 +45,11 @@ namespace Godot.SourceGenerators return false; }) ) - // Ignore classes whose name is not the same as the file name - .Where(x => Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name) + .Where(x => + // Ignore classes whose name is not the same as the file name + Path.GetFileNameWithoutExtension(x.cds.SyntaxTree.FilePath) == x.symbol.Name && + // Ignore generic classes + !x.symbol.IsGenericType) .GroupBy(x => x.symbol) .ToDictionary(g => g.Key, g => g.Select(x => x.cds)); @@ -150,8 +153,6 @@ namespace Godot.SourceGenerators first = false; sourceBuilder.Append("typeof("); sourceBuilder.Append(qualifiedName); - if (godotClass.Key.IsGenericType) - sourceBuilder.Append($"<{new string(',', godotClass.Key.TypeParameters.Count() - 1)}>"); sourceBuilder.Append(")"); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index e6a8054ae2..dafa83431b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -297,7 +297,7 @@ namespace Godot.Bridge foreach (var type in assembly.GetTypes()) { - if (type.IsNested) + if (type.IsNested || type.IsGenericType) continue; if (!typeOfGodotObject.IsAssignableFrom(type)) @@ -314,9 +314,12 @@ namespace Godot.Bridge if (scriptTypes != null) { - for (int i = 0; i < scriptTypes.Length; i++) + foreach (var type in scriptTypes) { - LookupScriptForClass(scriptTypes[i]); + if (type.IsGenericType) + continue; + + LookupScriptForClass(type); } } } @@ -729,6 +732,7 @@ namespace Godot.Bridge { ExceptionUtils.LogException(e); *outTool = godot_bool.False; + *outMethodsDest = NativeFuncs.godotsharp_array_new(); *outRpcFunctionsDest = NativeFuncs.godotsharp_dictionary_new(); *outEventSignalsDest = NativeFuncs.godotsharp_dictionary_new(); *outBaseScript = default; diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 844b15e9fb..747dcbd76c 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -339,9 +339,6 @@ def configure(env: "Environment"): env.Prepend(CPPPATH=["#platform/linuxbsd"]) if env["x11"]: - if not env["vulkan"]: - print("Error: X11 support requires vulkan=yes") - env.Exit(255) env.Append(CPPDEFINES=["X11_ENABLED"]) env.Append(CPPDEFINES=["UNIX_ENABLED"]) diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index e7864ebac0..f462893112 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -3709,7 +3709,6 @@ WTEnablePtr DisplayServerWindows::wintab_WTEnable = nullptr; // UXTheme API. bool DisplayServerWindows::dark_title_available = false; bool DisplayServerWindows::ux_theme_available = false; -IsDarkModeAllowedForAppPtr DisplayServerWindows::IsDarkModeAllowedForApp = nullptr; ShouldAppsUseDarkModePtr DisplayServerWindows::ShouldAppsUseDarkMode = nullptr; GetImmersiveColorFromColorSetExPtr DisplayServerWindows::GetImmersiveColorFromColorSetEx = nullptr; GetImmersiveColorTypeFromNamePtr DisplayServerWindows::GetImmersiveColorTypeFromName = nullptr; @@ -3727,7 +3726,7 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS { } SHC_PROCESS_DPI_AWARENESS; bool DisplayServerWindows::is_dark_mode_supported() const { - return ux_theme_available && IsDarkModeAllowedForApp(); + return ux_theme_available; } bool DisplayServerWindows::is_dark_mode() const { @@ -3817,13 +3816,12 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win // Load UXTheme. HMODULE ux_theme_lib = LoadLibraryW(L"uxtheme.dll"); if (ux_theme_lib) { - IsDarkModeAllowedForApp = (IsDarkModeAllowedForAppPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(136)); ShouldAppsUseDarkMode = (ShouldAppsUseDarkModePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(132)); GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(95)); GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(96)); GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(98)); - ux_theme_available = IsDarkModeAllowedForApp && ShouldAppsUseDarkMode && GetImmersiveColorFromColorSetEx && GetImmersiveColorTypeFromName && GetImmersiveUserColorSetPreference; + ux_theme_available = ShouldAppsUseDarkMode && GetImmersiveColorFromColorSetEx && GetImmersiveColorTypeFromName && GetImmersiveUserColorSetPreference; if (os_ver.dwBuildNumber >= 22000) { dark_title_available = true; } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 4702bb7765..82894d300f 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -152,7 +152,6 @@ typedef UINT(WINAPI *WTInfoPtr)(UINT p_category, UINT p_index, LPVOID p_output); typedef BOOL(WINAPI *WTPacketPtr)(HANDLE p_ctx, UINT p_param, LPVOID p_packets); typedef BOOL(WINAPI *WTEnablePtr)(HANDLE p_ctx, BOOL p_enable); -typedef bool(WINAPI *IsDarkModeAllowedForAppPtr)(); typedef bool(WINAPI *ShouldAppsUseDarkModePtr)(); typedef DWORD(WINAPI *GetImmersiveColorFromColorSetExPtr)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode); typedef int(WINAPI *GetImmersiveColorTypeFromNamePtr)(const WCHAR *name); @@ -288,7 +287,6 @@ class DisplayServerWindows : public DisplayServer { // UXTheme API static bool dark_title_available; static bool ux_theme_available; - static IsDarkModeAllowedForAppPtr IsDarkModeAllowedForApp; static ShouldAppsUseDarkModePtr ShouldAppsUseDarkMode; static GetImmersiveColorFromColorSetExPtr GetImmersiveColorFromColorSetEx; static GetImmersiveColorTypeFromNamePtr GetImmersiveColorTypeFromName; diff --git a/scene/3d/occluder_instance_3d.cpp b/scene/3d/occluder_instance_3d.cpp index 4e1ed5654a..f150a602b3 100644 --- a/scene/3d/occluder_instance_3d.cpp +++ b/scene/3d/occluder_instance_3d.cpp @@ -32,6 +32,7 @@ #include "core/config/project_settings.h" #include "core/core_string_names.h" +#include "core/io/marshalls.h" #include "core/math/geometry_2d.h" #include "core/math/triangulate.h" #include "scene/3d/importer_mesh_instance_3d.h" @@ -533,11 +534,20 @@ void OccluderInstance3D::_bake_surface(const Transform3D &p_transform, Array p_s } if (!Math::is_zero_approx(p_simplification_dist) && SurfaceTool::simplify_func) { - float error_scale = SurfaceTool::simplify_scale_func((float *)vertices.ptr(), vertices.size(), sizeof(Vector3)); + Vector<float> vertices_f32 = vector3_to_float32_array(vertices.ptr(), vertices.size()); + + float error_scale = SurfaceTool::simplify_scale_func(vertices_f32.ptr(), vertices.size(), sizeof(float) * 3); float target_error = p_simplification_dist / error_scale; float error = -1.0f; int target_index_count = MIN(indices.size(), 36); - uint32_t index_count = SurfaceTool::simplify_func((unsigned int *)indices.ptrw(), (unsigned int *)indices.ptr(), indices.size(), (float *)vertices.ptr(), vertices.size(), sizeof(Vector3), target_index_count, target_error, &error); + + uint32_t index_count = SurfaceTool::simplify_func( + (unsigned int *)indices.ptrw(), + (unsigned int *)indices.ptr(), + indices.size(), + vertices_f32.ptr(), vertices.size(), sizeof(float) * 3, + target_index_count, target_error, &error); + indices.resize(index_count); } diff --git a/scene/gui/tab_bar.cpp b/scene/gui/tab_bar.cpp index f87829cf71..beaffc14b0 100644 --- a/scene/gui/tab_bar.cpp +++ b/scene/gui/tab_bar.cpp @@ -154,7 +154,9 @@ void TabBar::gui_input(const Ref<InputEvent> &p_event) { queue_redraw(); } - _update_hover(); + if (!tabs.is_empty()) { + _update_hover(); + } return; } @@ -362,12 +364,19 @@ void TabBar::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { + bool rtl = is_layout_rtl(); + Vector2 size = get_size(); + if (tabs.is_empty()) { + // Draw the drop indicator where the first tab would be if there are no tabs. + if (dragging_valid_tab) { + int x = rtl ? size.x : 0; + theme_cache.drop_mark_icon->draw(get_canvas_item(), Point2(x - (theme_cache.drop_mark_icon->get_width() / 2), (size.height - theme_cache.drop_mark_icon->get_height()) / 2), theme_cache.drop_mark_color); + } + return; } - bool rtl = is_layout_rtl(); - Vector2 size = get_size(); int limit_minus_buttons = size.width - theme_cache.increment_icon->get_width() - theme_cache.decrement_icon->get_width(); int ofs = tabs[offset].ofs_cache; @@ -1092,7 +1101,8 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) { hover_now += 1; } } else { - hover_now = is_layout_rtl() ^ (p_point.x < get_tab_rect(0).position.x) ? 0 : get_tab_count() - 1; + int x = tabs.is_empty() ? 0 : get_tab_rect(0).position.x; + hover_now = is_layout_rtl() ^ (p_point.x < x) ? 0 : get_tab_count() - 1; } move_tab(tab_from_id, hover_now); @@ -1118,7 +1128,7 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) { hover_now += 1; } } else { - hover_now = is_layout_rtl() ^ (p_point.x < get_tab_rect(0).position.x) ? 0 : get_tab_count(); + hover_now = tabs.is_empty() || (is_layout_rtl() ^ (p_point.x < get_tab_rect(0).position.x)) ? 0 : get_tab_count(); } Tab moving_tab = from_tabs->tabs[tab_from_id]; @@ -1154,10 +1164,13 @@ void TabBar::drop_data(const Point2 &p_point, const Variant &p_data) { int TabBar::get_tab_idx_at_point(const Point2 &p_point) const { int hover_now = -1; - for (int i = offset; i <= max_drawn_tab; i++) { - Rect2 rect = get_tab_rect(i); - if (rect.has_point(p_point)) { - hover_now = i; + + if (!tabs.is_empty()) { + for (int i = offset; i <= max_drawn_tab; i++) { + Rect2 rect = get_tab_rect(i); + if (rect.has_point(p_point)) { + hover_now = i; + } } } diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 584a7e7eac..78b4edfcf7 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -270,24 +270,18 @@ void Font::set_cache_capacity(int p_single_line, int p_multi_line) { } Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - } - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : TextServer::JUSTIFICATION_NONE, TextServer::BREAK_NONE, p_direction, p_orientation); Ref<TextLine> buffer; - if (cache.has(hash)) { - buffer = cache.get(hash); + if (cache.has(key)) { + buffer = cache.get(key); } else { buffer.instantiate(); buffer->set_direction(p_direction); buffer->set_orientation(p_orientation); buffer->add_string(p_text, Ref<Font>(this), p_font_size); - cache.insert(hash, buffer); + cache.insert(key, buffer); } buffer->set_width(p_width); @@ -300,17 +294,11 @@ Size2 Font::get_string_size(const String &p_text, HorizontalAlignment p_alignmen } Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation); Ref<TextParagraph> lines_buffer; - if (cache_wrap.has(hash)) { - lines_buffer = cache_wrap.get(hash); + if (cache_wrap.has(key)) { + lines_buffer = cache_wrap.get(key); } else { lines_buffer.instantiate(); lines_buffer->set_direction(p_direction); @@ -319,7 +307,7 @@ Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment lines_buffer->set_width(p_width); lines_buffer->set_break_flags(p_brk_flags); lines_buffer->set_justification_flags(p_jst_flags); - cache_wrap.insert(hash, lines_buffer); + cache_wrap.insert(key, lines_buffer); } lines_buffer->set_alignment(p_alignment); @@ -329,24 +317,18 @@ Size2 Font::get_multiline_string_size(const String &p_text, HorizontalAlignment } void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - } - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : TextServer::JUSTIFICATION_NONE, TextServer::BREAK_NONE, p_direction, p_orientation); Ref<TextLine> buffer; - if (cache.has(hash)) { - buffer = cache.get(hash); + if (cache.has(key)) { + buffer = cache.get(key); } else { buffer.instantiate(); buffer->set_direction(p_direction); buffer->set_orientation(p_orientation); buffer->add_string(p_text, Ref<Font>(this), p_font_size); - cache.insert(hash, buffer); + cache.insert(key, buffer); } Vector2 ofs = p_pos; @@ -366,17 +348,11 @@ void Font::draw_string(RID p_canvas_item, const Point2 &p_pos, const String &p_t } void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation); Ref<TextParagraph> lines_buffer; - if (cache_wrap.has(hash)) { - lines_buffer = cache_wrap.get(hash); + if (cache_wrap.has(key)) { + lines_buffer = cache_wrap.get(key); } else { lines_buffer.instantiate(); lines_buffer->set_direction(p_direction); @@ -385,7 +361,7 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S lines_buffer->set_width(p_width); lines_buffer->set_break_flags(p_brk_flags); lines_buffer->set_justification_flags(p_jst_flags); - cache_wrap.insert(hash, lines_buffer); + cache_wrap.insert(key, lines_buffer); } Vector2 ofs = p_pos; @@ -402,24 +378,18 @@ void Font::draw_multiline_string(RID p_canvas_item, const Point2 &p_pos, const S } void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_size, const Color &p_modulate, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - if (p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - } - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + bool fill = (p_alignment == HORIZONTAL_ALIGNMENT_FILL); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, fill ? p_width : 0.0, fill ? p_jst_flags : TextServer::JUSTIFICATION_NONE, TextServer::BREAK_NONE, p_direction, p_orientation); Ref<TextLine> buffer; - if (cache.has(hash)) { - buffer = cache.get(hash); + if (cache.has(key)) { + buffer = cache.get(key); } else { buffer.instantiate(); buffer->set_direction(p_direction); buffer->set_orientation(p_orientation); buffer->add_string(p_text, Ref<Font>(this), p_font_size); - cache.insert(hash, buffer); + cache.insert(key, buffer); } Vector2 ofs = p_pos; @@ -439,17 +409,11 @@ void Font::draw_string_outline(RID p_canvas_item, const Point2 &p_pos, const Str } void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, const String &p_text, HorizontalAlignment p_alignment, float p_width, int p_font_size, int p_max_lines, int p_size, const Color &p_modulate, BitField<TextServer::LineBreakFlag> p_brk_flags, BitField<TextServer::JustificationFlag> p_jst_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) const { - uint64_t hash = p_text.hash64(); - hash = hash_djb2_one_64(p_font_size, hash); - hash = hash_djb2_one_64(hash_murmur3_one_float(p_width), hash); - hash = hash_djb2_one_64(p_brk_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_jst_flags.operator int64_t(), hash); - hash = hash_djb2_one_64(p_direction, hash); - hash = hash_djb2_one_64(p_orientation, hash); + ShapedTextKey key = ShapedTextKey(p_text, p_font_size, p_width, p_jst_flags, p_brk_flags, p_direction, p_orientation); Ref<TextParagraph> lines_buffer; - if (cache_wrap.has(hash)) { - lines_buffer = cache_wrap.get(hash); + if (cache_wrap.has(key)) { + lines_buffer = cache_wrap.get(key); } else { lines_buffer.instantiate(); lines_buffer->set_direction(p_direction); @@ -458,7 +422,7 @@ void Font::draw_multiline_string_outline(RID p_canvas_item, const Point2 &p_pos, lines_buffer->set_width(p_width); lines_buffer->set_break_flags(p_brk_flags); lines_buffer->set_justification_flags(p_jst_flags); - cache_wrap.insert(hash, lines_buffer); + cache_wrap.insert(key, lines_buffer); } Vector2 ofs = p_pos; diff --git a/scene/resources/font.h b/scene/resources/font.h index e9f7507652..44198a3111 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -47,9 +47,44 @@ class TextParagraph; class Font : public Resource { GDCLASS(Font, Resource); + struct ShapedTextKey { + String text; + int font_size = 14; + float width = 0.f; + BitField<TextServer::JustificationFlag> jst_flags = TextServer::JUSTIFICATION_NONE; + BitField<TextServer::LineBreakFlag> brk_flags = TextServer::BREAK_MANDATORY; + TextServer::Direction direction = TextServer::DIRECTION_AUTO; + TextServer::Orientation orientation = TextServer::ORIENTATION_HORIZONTAL; + + bool operator==(const ShapedTextKey &p_b) const { + return (font_size == p_b.font_size) && (width == p_b.width) && (jst_flags == p_b.jst_flags) && (brk_flags == p_b.brk_flags) && (direction == p_b.direction) && (orientation == p_b.orientation) && (text == p_b.text); + } + + ShapedTextKey() {} + ShapedTextKey(const String &p_text, int p_font_size, float p_width, BitField<TextServer::JustificationFlag> p_jst_flags, BitField<TextServer::LineBreakFlag> p_brk_flags, TextServer::Direction p_direction, TextServer::Orientation p_orientation) { + text = p_text; + font_size = p_font_size; + width = p_width; + jst_flags = p_jst_flags; + brk_flags = p_brk_flags; + direction = p_direction; + orientation = p_orientation; + } + }; + + struct ShapedTextKeyHasher { + _FORCE_INLINE_ static uint32_t hash(const ShapedTextKey &p_a) { + uint32_t hash = p_a.text.hash(); + hash = hash_murmur3_one_32(p_a.font_size, hash); + hash = hash_murmur3_one_float(p_a.width, hash); + hash = hash_murmur3_one_32(p_a.brk_flags | (p_a.jst_flags << 6) | (p_a.direction << 12) | (p_a.orientation << 15), hash); + return hash_fmix32(hash); + } + }; + // Shaped string cache. - mutable LRUCache<uint64_t, Ref<TextLine>> cache; - mutable LRUCache<uint64_t, Ref<TextParagraph>> cache_wrap; + mutable LRUCache<ShapedTextKey, Ref<TextLine>, ShapedTextKeyHasher> cache; + mutable LRUCache<ShapedTextKey, Ref<TextParagraph>, ShapedTextKeyHasher> cache_wrap; protected: // Output. diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index d1278f9340..b5e02b2f76 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -30,6 +30,7 @@ #include "importer_mesh.h" +#include "core/io/marshalls.h" #include "core/math/random_pcg.h" #include "core/math/static_raycaster.h" #include "scene/resources/surface_tool.h" @@ -424,9 +425,8 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli normal_weights[j] = 2.0; // Give some weight to normal preservation, may be worth exposing as an import setting } - const float max_mesh_error = FLT_MAX; // We don't want to limit by error, just by index target - float scale = SurfaceTool::simplify_scale_func((const float *)merged_vertices_ptr, merged_vertex_count, sizeof(Vector3)); - float mesh_error = 0.0f; + Vector<float> merged_vertices_f32 = vector3_to_float32_array(merged_vertices_ptr, merged_vertex_count); + float scale = SurfaceTool::simplify_scale_func(merged_vertices_f32.ptr(), merged_vertex_count, sizeof(float) * 3); unsigned int index_target = 12; // Start with the smallest target, 4 triangles unsigned int last_index_count = 0; @@ -446,11 +446,25 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli raycaster->commit(); } + const float max_mesh_error = FLT_MAX; // We don't want to limit by error, just by index target + float mesh_error = 0.0f; + while (index_target < index_count) { PackedInt32Array new_indices; new_indices.resize(index_count); - size_t new_index_count = SurfaceTool::simplify_with_attrib_func((unsigned int *)new_indices.ptrw(), (const uint32_t *)merged_indices_ptr, index_count, (const float *)merged_vertices_ptr, merged_vertex_count, sizeof(Vector3), index_target, max_mesh_error, &mesh_error, (float *)merged_normals.ptr(), normal_weights.ptr(), 3); + Vector<float> merged_normals_f32 = vector3_to_float32_array(merged_normals.ptr(), merged_normals.size()); + + size_t new_index_count = SurfaceTool::simplify_with_attrib_func( + (unsigned int *)new_indices.ptrw(), + (const uint32_t *)merged_indices_ptr, index_count, + merged_vertices_f32.ptr(), merged_vertex_count, + sizeof(float) * 3, // Vertex stride + index_target, + max_mesh_error, + &mesh_error, + merged_normals_f32.ptr(), + normal_weights.ptr(), 3); if (new_index_count < last_index_count * 1.5f) { index_target = index_target * 1.5f; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 94967352c8..185cbdc6bf 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -46,7 +46,7 @@ void SurfaceTool::strip_mesh_arrays(PackedVector3Array &r_vertices, PackedInt32A Vector<uint32_t> remap; remap.resize(r_vertices.size()); - uint32_t new_vertex_count = generate_remap_func(remap.ptrw(), (unsigned int *)r_indices.ptr(), r_indices.size(), (float *)r_vertices.ptr(), r_vertices.size(), sizeof(Vector3)); + uint32_t new_vertex_count = generate_remap_func(remap.ptrw(), (unsigned int *)r_indices.ptr(), r_indices.size(), r_vertices.ptr(), r_vertices.size(), sizeof(Vector3)); remap_vertex_func(r_vertices.ptrw(), r_vertices.ptr(), r_vertices.size(), sizeof(Vector3), remap.ptr()); r_vertices.resize(new_vertex_count); remap_index_func((unsigned int *)r_indices.ptrw(), (unsigned int *)r_indices.ptr(), r_indices.size(), remap.ptr()); diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 18915e294e..48eaf98aa3 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -3386,7 +3386,7 @@ RID PlaceholderTexture2D::get_rid() const { void PlaceholderTexture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_size", "size"), &PlaceholderTexture2D::set_size); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size", PROPERTY_HINT_NONE, "suffix:px"), "set_size", "get_size"); } PlaceholderTexture2D::PlaceholderTexture2D() { diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 6b8f8097a8..fc2366a78c 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -2650,6 +2650,10 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "camera_direction_world", "CAMERA_DIRECTION_WORLD" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "camera_visible_layers", "CAMERA_VISIBLE_LAYERS" }, { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_3D, "node_position_view", "NODE_POSITION_VIEW" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom0", "CUSTOM0" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom1", "CUSTOM1" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom2", "CUSTOM2" }, + { Shader::MODE_SPATIAL, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_VECTOR_4D, "custom3", "CUSTOM3" }, // Node3D, Fragment { Shader::MODE_SPATIAL, VisualShader::TYPE_FRAGMENT, VisualShaderNode::PORT_TYPE_VECTOR_4D, "fragcoord", "FRAGCOORD" }, diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index ca76a819ec..47f767425b 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -513,10 +513,6 @@ bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p } bool GodotCollisionSolver3D::solve_distance(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) { - if (p_shape_A->is_concave()) { - return false; - } - if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) { Vector3 a, b; bool col = solve_distance_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, a, b); |