diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index b26f6d1bbf97..9bc48b8f7226 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2221,9 +2221,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str int method_bind_count = 0; for (const MethodInterface &imethod : itype.methods) { - Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output); + Error method_err = _generate_cs_method(itype, imethod, method_bind_count, output, false); ERR_FAIL_COND_V_MSG(method_err != OK, method_err, "Failed to generate method '" + imethod.name + "' for class '" + itype.name + "'."); + + method_err = _generate_cs_method(itype, imethod, method_bind_count, output, true); + ERR_FAIL_COND_V_MSG(method_err != OK, method_err, + "Failed to generate span overload method '" + imethod.name + "' for class '" + itype.name + "'."); } // Signals @@ -2649,7 +2653,7 @@ Error BindingsGenerator::_generate_cs_property(const BindingsGenerator::TypeInte return OK; } -Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output) { +Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, const bool p_use_span) { const TypeInterface *return_type = _get_type_or_singleton_or_null(p_imethod.return_type); ERR_FAIL_NULL_V(return_type, ERR_BUG); // Return type not found @@ -2662,6 +2666,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf "' from the editor API. Core API cannot have dependencies on the editor API."); } + if (p_imethod.is_virtual && p_use_span) + return OK; + String method_bind_field = CS_STATIC_FIELD_METHOD_BIND_PREFIX + itos(p_method_bind_count); String arguments_sig; @@ -2686,6 +2693,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf StringBuilder default_args_doc; + bool has_span_argument = false; + // Retrieve information from the arguments const ArgumentInterface &first = p_imethod.arguments.front()->get(); for (const ArgumentInterface &iarg : p_imethod.arguments) { @@ -2708,6 +2717,8 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf String arg_cs_type = arg_type->cs_type + _get_generic_type_parameters(*arg_type, iarg.type.generic_type_parameters); + bool use_span_for_arg = p_use_span && arg_type->is_span_compatible; + // Add the current arguments to the signature // If the argument has a default value which is not a constant, we will make it Nullable { @@ -2719,7 +2730,12 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf arguments_sig += "Nullable<"; } - arguments_sig += arg_cs_type; + if (use_span_for_arg) { + arguments_sig += "ReadOnlySpan<" + arg_type->span_substitution_name + ">"; + has_span_argument = true; + } else { + arguments_sig += arg_cs_type; + } if (iarg.def_param_mode == ArgumentInterface::NULLABLE_VAL) { arguments_sig += "> "; @@ -2731,7 +2747,11 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf if (!p_imethod.is_compat && iarg.default_argument.size()) { if (iarg.def_param_mode != ArgumentInterface::CONSTANT) { - arguments_sig += " = null"; + if (use_span_for_arg) { + arguments_sig += " = default"; + } else { + arguments_sig += " = null"; + } } else { arguments_sig += " = " + sformat(iarg.default_argument, arg_type->cs_type); } @@ -2740,7 +2760,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf icall_params += ", "; - if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT) { + if (iarg.default_argument.size() && iarg.def_param_mode != ArgumentInterface::CONSTANT && !use_span_for_arg) { // The default value of an argument must be constant. Otherwise we make it Nullable and do the following: // Type arg_in = arg.HasValue ? arg.Value : ; String arg_or_defval_local = iarg.name; @@ -2800,6 +2820,9 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf cs_in_expr_is_unsafe |= arg_type->cs_in_expr_is_unsafe; } + if (p_use_span && !has_span_argument) + return OK; + // Collect caller name for MethodBind if (p_imethod.is_vararg) { icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue"; @@ -4559,38 +4582,40 @@ void BindingsGenerator::_populate_builtin_type_interfaces() { itype.c_type_in = "Variant[]"; builtin_types.insert(itype.cname, itype); -#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t) \ - { \ - itype = TypeInterface(); \ - itype.name = #m_name; \ - itype.cname = itype.name; \ - itype.proxy_name = #m_proxy_t "[]"; \ - itype.cs_type = itype.proxy_name; \ - itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \ - itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \ - itype.c_arg_in = "&%s_in"; \ - itype.c_type = #m_managed_type; \ - itype.c_type_in = itype.proxy_name; \ - itype.c_type_out = itype.proxy_name; \ - itype.c_type_is_disposable_struct = true; \ - builtin_types.insert(itype.name, itype); \ - } - -#define INSERT_ARRAY(m_type, m_managed_type, m_proxy_t) INSERT_ARRAY_FULL(m_type, m_type, m_managed_type, m_proxy_t) - - INSERT_ARRAY(PackedInt32Array, godot_packed_int32_array, int); - INSERT_ARRAY(PackedInt64Array, godot_packed_int64_array, long); - INSERT_ARRAY_FULL(PackedByteArray, PackedByteArray, godot_packed_byte_array, byte); - - INSERT_ARRAY(PackedFloat32Array, godot_packed_float32_array, float); - INSERT_ARRAY(PackedFloat64Array, godot_packed_float64_array, double); - - INSERT_ARRAY(PackedStringArray, godot_packed_string_array, string); - - INSERT_ARRAY(PackedColorArray, godot_packed_color_array, Color); - INSERT_ARRAY(PackedVector2Array, godot_packed_vector2_array, Vector2); - INSERT_ARRAY(PackedVector3Array, godot_packed_vector3_array, Vector3); - INSERT_ARRAY(PackedVector4Array, godot_packed_vector4_array, Vector4); +#define INSERT_ARRAY_FULL(m_name, m_type, m_managed_type, m_proxy_t, m_is_span_compatible) \ + { \ + itype = TypeInterface(); \ + itype.name = #m_name; \ + itype.cname = itype.name; \ + itype.proxy_name = #m_proxy_t "[]"; \ + itype.cs_type = itype.proxy_name; \ + itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOARRAY_TO(m_type) "(%1);\n"; \ + itype.c_out = "%5return " C_METHOD_MONOARRAY_FROM(m_type) "(%1);\n"; \ + itype.c_arg_in = "&%s_in"; \ + itype.c_type = #m_managed_type; \ + itype.c_type_in = "ReadOnlySpan<" #m_proxy_t ">"; \ + itype.c_type_out = itype.proxy_name; \ + itype.c_type_is_disposable_struct = true; \ + itype.is_span_compatible = m_is_span_compatible; \ + itype.span_substitution_name = #m_proxy_t; \ + builtin_types.insert(itype.name, itype); \ + } + +#define INSERT_ARRAY(m_type, m_managed_type, m_proxy_t, m_is_span_compatible) INSERT_ARRAY_FULL(m_type, m_type, m_managed_type, m_proxy_t, m_is_span_compatible) + + INSERT_ARRAY(PackedInt32Array, godot_packed_int32_array, int, true); + INSERT_ARRAY(PackedInt64Array, godot_packed_int64_array, long, true); + INSERT_ARRAY_FULL(PackedByteArray, PackedByteArray, godot_packed_byte_array, byte, true); + + INSERT_ARRAY(PackedFloat32Array, godot_packed_float32_array, float, true); + INSERT_ARRAY(PackedFloat64Array, godot_packed_float64_array, double, true); + + INSERT_ARRAY(PackedStringArray, godot_packed_string_array, string, false); + + INSERT_ARRAY(PackedColorArray, godot_packed_color_array, Color, true); + INSERT_ARRAY(PackedVector2Array, godot_packed_vector2_array, Vector2, true); + INSERT_ARRAY(PackedVector3Array, godot_packed_vector3_array, Vector3, true); + INSERT_ARRAY(PackedVector4Array, godot_packed_vector4_array, Vector4, true); #undef INSERT_ARRAY diff --git a/modules/mono/editor/bindings_generator.h b/modules/mono/editor/bindings_generator.h index 556d287af4ef..b6fae6a08fc9 100644 --- a/modules/mono/editor/bindings_generator.h +++ b/modules/mono/editor/bindings_generator.h @@ -258,6 +258,11 @@ class BindingsGenerator { */ String proxy_name; + /** + * Name to be used in the ReadOnlySpan when [is_span_compatible] evaluates to true. + */ + String span_substitution_name; + ClassDB::APIType api_type = ClassDB::API_NONE; bool is_enum = false; @@ -265,6 +270,7 @@ class BindingsGenerator { bool is_singleton = false; bool is_singleton_instance = false; bool is_ref_counted = false; + bool is_span_compatible = false; /** * Class is a singleton, but can't be declared as a static class as that would @@ -840,7 +846,7 @@ class BindingsGenerator { Error _generate_cs_type(const TypeInterface &itype, const String &p_output_file); Error _generate_cs_property(const TypeInterface &p_itype, const PropertyInterface &p_iprop, StringBuilder &p_output); - Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output); + Error _generate_cs_method(const TypeInterface &p_itype, const MethodInterface &p_imethod, int &p_method_bind_count, StringBuilder &p_output, bool p_use_span); Error _generate_cs_signal(const BindingsGenerator::TypeInterface &p_itype, const BindingsGenerator::SignalInterface &p_isignal, StringBuilder &p_output); Error _generate_cs_native_calls(const InternalCall &p_icall, StringBuilder &r_output); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs b/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs index 4e80afc4a595..90fd6f9fbb96 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Compat.cs @@ -176,6 +176,13 @@ public long DrawListBegin(Rid framebuffer, InitialAction initialColorAction, Fin { return DrawListBegin(framebuffer, initialColorAction, finalColorAction, initialDepthAction, finalDepthAction, clearColorValues, clearDepth, clearStencil, region, new Godot.Collections.Array(storageTextures)); } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public long DrawListBegin(Rid framebuffer, InitialAction initialColorAction, FinalAction finalColorAction, InitialAction initialDepthAction, FinalAction finalDepthAction, ReadOnlySpan clearColorValues, float clearDepth, uint clearStencil, Nullable region, Godot.Collections.Array storageTextures) + { + return DrawListBegin(framebuffer, initialColorAction, finalColorAction, initialDepthAction, finalDepthAction, clearColorValues, clearDepth, clearStencil, region, new Godot.Collections.Array(storageTextures)); + } } partial class RichTextLabel @@ -187,11 +194,11 @@ public void PushList(int level, ListType type, bool capitalize) PushList(level, type, capitalize, bullet: "•"); } - /// + /// [EditorBrowsable(EditorBrowsableState.Never)] public void PushParagraph(HorizontalAlignment alignment, TextDirection baseDirection, string language, TextServer.StructuredTextParser stParser) { - PushParagraph(alignment, baseDirection, language, stParser, TextServer.JustificationFlag.WordBound | TextServer.JustificationFlag.Kashida | TextServer.JustificationFlag.SkipLastLine | TextServer.JustificationFlag.DoNotSkipSingleLine); + PushParagraph(alignment, baseDirection, language, stParser, TextServer.JustificationFlag.WordBound | TextServer.JustificationFlag.Kashida | TextServer.JustificationFlag.SkipLastLine | TextServer.JustificationFlag.DoNotSkipSingleLine, Array.Empty()); } } @@ -204,6 +211,13 @@ public void AddTriangleFan(Vector3[] vertices, Vector2[] uvs, Color[] colors, Ve AddTriangleFan(vertices, uvs, colors, uv2S, normals, new Godot.Collections.Array(tangents)); } + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public void AddTriangleFan(ReadOnlySpan vertices, ReadOnlySpan uvs, ReadOnlySpan colors, ReadOnlySpan uv2S, ReadOnlySpan normals, Godot.Collections.Array tangents) + { + AddTriangleFan(vertices, uvs, colors, uv2S, normals, new Godot.Collections.Array(tangents)); + } + /// [EditorBrowsable(EditorBrowsableState.Never)] public ArrayMesh Commit(ArrayMesh existing, uint flags) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs index 15b7ce7c73f4..3b32b1de8a40 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/Marshaling.cs @@ -394,7 +394,7 @@ public static unsafe byte[] ConvertNativePackedByteArrayToSystemArray(in godot_p return array; } - public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span p_array) + public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_byte_array(); @@ -417,7 +417,7 @@ public static unsafe int[] ConvertNativePackedInt32ArrayToSystemArray(godot_pack return array; } - public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span p_array) + public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_int32_array(); @@ -440,7 +440,7 @@ public static unsafe long[] ConvertNativePackedInt64ArrayToSystemArray(godot_pac return array; } - public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span p_array) + public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_int64_array(); @@ -464,7 +464,7 @@ public static unsafe float[] ConvertNativePackedFloat32ArrayToSystemArray(godot_ } public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_float32_array(); @@ -488,7 +488,7 @@ public static unsafe double[] ConvertNativePackedFloat64ArrayToSystemArray(godot } public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_float64_array(); @@ -510,7 +510,7 @@ public static unsafe string[] ConvertNativePackedStringArrayToSystemArray(godot_ return array; } - public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span p_array) + public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(ReadOnlySpan p_array) { godot_packed_string_array dest = new godot_packed_string_array(); @@ -545,7 +545,7 @@ public static unsafe Vector2[] ConvertNativePackedVector2ArrayToSystemArray(godo } public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector2_array(); @@ -569,7 +569,7 @@ public static unsafe Vector3[] ConvertNativePackedVector3ArrayToSystemArray(godo } public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector3_array(); @@ -593,7 +593,7 @@ public static unsafe Vector4[] ConvertNativePackedVector4ArrayToSystemArray(godo } public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array( - Span p_array) + ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_vector4_array(); @@ -616,7 +616,7 @@ public static unsafe Color[] ConvertNativePackedColorArrayToSystemArray(godot_pa return array; } - public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span p_array) + public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(ReadOnlySpan p_array) { if (p_array.IsEmpty) return new godot_packed_color_array();