Skip to content

Commit

Permalink
Replace All C# Array to ReadOnlySpan, including params
Browse files Browse the repository at this point in the history
  • Loading branch information
Delsin-Yu committed Aug 31, 2024
1 parent 988114c commit 2fad8dd
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 186 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ private static IEnumerable<BuildDiagnostic> ReadDiagnosticsFromFile(string csvFi

while (!file.EofReached())
{
string[] csvColumns = file.GetCsvLine();
ReadOnlySpan<string> csvColumns = file.GetCsvLine();

if (csvColumns.Length == 1 && string.IsNullOrEmpty(csvColumns[0]))
yield break;
Expand Down
10 changes: 5 additions & 5 deletions modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ private static bool ProjectContainsDotNet()
return File.Exists(GodotSharpDirs.ProjectSlnPath);
}

public override string[] _GetExportFeatures(EditorExportPlatform platform, bool debug)
public override ReadOnlySpan<string> _GetExportFeatures(EditorExportPlatform platform, bool debug)
{
if (!ProjectContainsDotNet())
return Array.Empty<string>();
Expand Down Expand Up @@ -78,7 +78,7 @@ public override string[] _GetExportFeatures(EditorExportPlatform platform, bool
private string? _maybeLastExportError;

// With this method we can override how a file is exported in the PCK
public override void _ExportFile(string path, string type, string[] features)
public override void _ExportFile(string path, string type, ReadOnlySpan<string> features)
{
base._ExportFile(path, type, features);

Expand Down Expand Up @@ -114,7 +114,7 @@ public override void _ExportFile(string path, string type, string[] features)
}
}

public override void _ExportBegin(string[] features, bool isDebug, string path, uint flags)
public override void _ExportBegin(ReadOnlySpan<string> features, bool isDebug, string path, uint flags)
{
base._ExportBegin(features, isDebug, path, flags);

Expand All @@ -137,7 +137,7 @@ public override void _ExportBegin(string[] features, bool isDebug, string path,
}
}

private void _ExportBeginImpl(string[] features, bool isDebug, string path, long flags)
private void _ExportBeginImpl(ReadOnlySpan<string> features, bool isDebug, string path, long flags)
{
_ = flags; // Unused.

Expand Down Expand Up @@ -459,7 +459,7 @@ public override void _ExportEnd()
}
}

private static bool DeterminePlatformFromFeatures(IEnumerable<string> features, [NotNullWhen(true)] out string? platform)
private static bool DeterminePlatformFromFeatures(ReadOnlySpan<string> features, [NotNullWhen(true)] out string? platform)
{
foreach (var feature in features)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public static string[] CodeCompletionRequest(CodeCompletionRequest.CompletionKin
using godot_string scriptFileIn = Marshaling.ConvertStringToNative(scriptFile);
godot_icall_Internal_CodeCompletionRequest((int)kind, scriptFileIn, out godot_packed_string_array res);
using (res)
return Marshaling.ConvertNativePackedStringArrayToSystemArray(res);
return Marshaling.ConvertNativePackedStringArrayToSystemArray(res).ToArray();
}

#region Internal
Expand Down
94 changes: 55 additions & 39 deletions modules/mono/editor/bindings_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ void BindingsGenerator::TypeInterface::postsetup_enum_type(BindingsGenerator::Ty
// any of the changes done here to the 'uint32_t' type interface as well.

r_enum_itype.cs_type = r_enum_itype.proxy_name;
r_enum_itype.cs_type_generic_alternative = r_enum_itype.proxy_name;
r_enum_itype.cs_in_expr = "(int)%0";
r_enum_itype.cs_out = "%5return (%2)%0(%1);";

Expand Down Expand Up @@ -2802,6 +2803,7 @@ Error BindingsGenerator::_generate_cs_method(const BindingsGenerator::TypeInterf

// Collect caller name for MethodBind
if (p_imethod.is_vararg) {
arguments_sig += " = default";
icall_params += ", (godot_string_name)MethodName." + p_imethod.proxy_name + ".NativeValue";
}

Expand Down Expand Up @@ -3400,7 +3402,7 @@ const String BindingsGenerator::_get_generic_type_parameters(const TypeInterface
" Core API cannot have dependencies on the editor API.");
}

params += param_itype->cs_type;
params += param_itype->cs_type_generic_alternative;
if (i < p_generic_type_parameters.size() - 1) {
params += ", ";
}
Expand Down Expand Up @@ -3632,6 +3634,7 @@ bool BindingsGenerator::_populate_object_type_interfaces() {
itype.c_out += itype.is_ref_counted ? "(%1.Reference);\n" : "(%1);\n";

itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;

itype.cs_in_expr = "GodotObject." CS_STATIC_METHOD_GETINSTANCE "(%0)";

Expand Down Expand Up @@ -4252,8 +4255,7 @@ bool BindingsGenerator::_arg_default_value_from_variant(const Variant &p_val, Ar
case Variant::PACKED_VECTOR3_ARRAY:
case Variant::PACKED_VECTOR4_ARRAY:
case Variant::PACKED_COLOR_ARRAY:
r_iarg.default_argument = "Array.Empty<%s>()";
r_iarg.def_param_mode = ArgumentInterface::NULLABLE_REF;
r_iarg.default_argument = "default";
break;
case Variant::TRANSFORM2D: {
Transform2D transform = p_val.operator Transform2D();
Expand Down Expand Up @@ -4413,6 +4415,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "float";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
{
// The expected type for 'float' in ptrcall is 'double'
itype.c_in = "%5%0 %1_in = %1;\n";
Expand All @@ -4431,6 +4434,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "double";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_type = "double";
itype.c_arg_in = "&%s";
itype.c_type_in = itype.proxy_name;
Expand All @@ -4445,6 +4449,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "string";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_in = "%5using %0 %1_in = " C_METHOD_MONOSTR_TO_GODOT "(%1);\n";
itype.c_out = "%5return " C_METHOD_MONOSTR_FROM_GODOT "(%1);\n";
itype.c_arg_in = "&%s_in";
Expand All @@ -4461,6 +4466,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "StringName";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)";
// Cannot pass null StringName to ptrcall
itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
Expand All @@ -4479,6 +4485,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "NodePath";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.cs_in_expr = "(%1)(%0?.NativeValue ?? default)";
// Cannot pass null NodePath to ptrcall
itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
Expand All @@ -4496,6 +4503,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "Rid";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_arg_in = "&%s";
itype.c_type = itype.cs_type;
itype.c_type_in = itype.c_type;
Expand All @@ -4508,6 +4516,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "Variant";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_in = "%5%0 %1_in = (%0)%1.NativeVar;\n";
itype.c_out = "%5return Variant.CreateTakingOwnershipOfDisposableValue(%1);\n";
itype.c_arg_in = "&%s_in";
Expand Down Expand Up @@ -4536,6 +4545,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = "Signal";
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.cs_in_expr = "%0";
itype.c_in = "%5using %0 %1_in = " C_METHOD_MANAGED_TO_SIGNAL "(in %1);\n";
itype.c_out = "%5return " C_METHOD_MANAGED_FROM_SIGNAL "(in %1);\n";
Expand All @@ -4550,47 +4560,50 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype = TypeInterface();
itype.name = "VarArg";
itype.cname = itype.name;
itype.proxy_name = "Variant[]";
itype.cs_type = "params Variant[]";
itype.cs_in_expr = "%0 ?? Array.Empty<Variant>()";
itype.proxy_name = "ReadOnlySpan<Variant>";
itype.cs_type = "ReadOnlySpan<Variant>";
itype.cs_type_generic_alternative = "ReadOnlySpan<Variant>";
// c_type, c_in and c_arg_in are hard-coded in the generator.
// c_out and c_type_out are not applicable to VarArg.
itype.c_arg_in = "&%s_in";
itype.c_type_in = "Variant[]";
itype.c_type_in = "ReadOnlySpan<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_proxy_t_capitalized) \
{ \
itype = TypeInterface(); \
itype.name = #m_name; \
itype.cname = itype.name; \
itype.proxy_name = "ReadOnlySpan<" #m_proxy_t ">"; \
itype.cs_type = itype.proxy_name; \
itype.cs_type_generic_alternative = #m_proxy_t "[]"; \
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; \
itype.cs_managed_to_variant = "VariantUtils.CreateFromSpan(%0)"; \
itype.cs_variant_to_managed = "VariantUtils.ConvertTo" #m_proxy_t_capitalized "Span(%0)"; \
builtin_types.insert(itype.name, itype); \
}

#define INSERT_ARRAY(m_type, m_managed_type, m_proxy_t, m_proxy_t_capitalized) INSERT_ARRAY_FULL(m_type, m_type, m_managed_type, m_proxy_t, m_proxy_t_capitalized)

INSERT_ARRAY(PackedInt32Array, godot_packed_int32_array, int, Int);
INSERT_ARRAY(PackedInt64Array, godot_packed_int64_array, long, Long);
INSERT_ARRAY_FULL(PackedByteArray, PackedByteArray, godot_packed_byte_array, byte, Byte);

INSERT_ARRAY(PackedFloat32Array, godot_packed_float32_array, float, Float);
INSERT_ARRAY(PackedFloat64Array, godot_packed_float64_array, double, Double);

INSERT_ARRAY(PackedStringArray, godot_packed_string_array, string, String);

INSERT_ARRAY(PackedColorArray, godot_packed_color_array, Color, Color);
INSERT_ARRAY(PackedVector2Array, godot_packed_vector2_array, Vector2, Vector2);
INSERT_ARRAY(PackedVector3Array, godot_packed_vector3_array, Vector3, Vector3);
INSERT_ARRAY(PackedVector4Array, godot_packed_vector4_array, Vector4, Vector4);

#undef INSERT_ARRAY

Expand All @@ -4601,6 +4614,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.proxy_name = itype.name;
itype.type_parameter_count = 1;
itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_type_generic_alternative = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue";
itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
itype.c_arg_in = "&%s";
Expand Down Expand Up @@ -4628,6 +4642,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.proxy_name = itype.name;
itype.type_parameter_count = 2;
itype.cs_type = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_type_generic_alternative = BINDINGS_NAMESPACE_COLLECTIONS "." + itype.proxy_name;
itype.cs_in_expr = "(%1)(%0 ?? new()).NativeValue";
itype.c_out = "%5return %0.CreateTakingOwnershipOfDisposableValue(%1);\n";
itype.c_arg_in = "&%s";
Expand All @@ -4654,6 +4669,7 @@ void BindingsGenerator::_populate_builtin_type_interfaces() {
itype.cname = itype.name;
itype.proxy_name = itype.name;
itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_type = itype.proxy_name;
itype.c_type_in = itype.c_type;
itype.c_type_out = itype.c_type;
Expand Down
7 changes: 7 additions & 0 deletions modules/mono/editor/bindings_generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,12 @@ class BindingsGenerator {
*/
String cs_type;

/**
* Type declaration used for generic argument substitution; generally, it should be equal to [cs_type].
* This property is here to handle the case where ReadOnlySpan<T> cannot be used as a generic type argument where we have to fall back to T[].
*/
String cs_type_generic_alternative;

/**
* Formatting elements:
* %0: input expression of type `in godot_variant`
Expand Down Expand Up @@ -537,6 +543,7 @@ class BindingsGenerator {
}

itype.cs_type = itype.proxy_name;
itype.cs_type_generic_alternative = itype.proxy_name;
itype.c_type = itype.cs_type;
itype.c_type_in = itype.cs_type + "*";
itype.c_type_out = itype.cs_type;
Expand Down
12 changes: 6 additions & 6 deletions modules/mono/glue/GodotSharp/GodotSharp/Compat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ partial class Geometry3D
{
/// <inheritdoc cref="SegmentIntersectsConvex(Vector3, Vector3, Godot.Collections.Array{Plane})"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public static Vector3[] SegmentIntersectsConvex(Vector3 from, Vector3 to, Godot.Collections.Array planes)
public static ReadOnlySpan<Vector3> SegmentIntersectsConvex(Vector3 from, Vector3 to, Godot.Collections.Array planes)
{
return SegmentIntersectsConvex(from, to, new Godot.Collections.Array<Plane>(planes));
}
Expand Down Expand Up @@ -170,9 +170,9 @@ public void LookAtFromPosition(Vector3 position, Vector3 target, Nullable<Vector

partial class RenderingDevice
{
/// <inheritdoc cref="DrawListBegin(Rid, InitialAction, FinalAction, InitialAction, FinalAction, Color[], float, uint, Nullable{Rect2}, Godot.Collections.Array{Rid})"/>
/// <inheritdoc cref="DrawListBegin(Godot.Rid,Godot.RenderingDevice.InitialAction,Godot.RenderingDevice.FinalAction,Godot.RenderingDevice.InitialAction,Godot.RenderingDevice.FinalAction,System.ReadOnlySpan{Godot.Color},float,uint,System.Nullable{Godot.Rect2},Godot.Collections.Array{Rid})"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public long DrawListBegin(Rid framebuffer, InitialAction initialColorAction, FinalAction finalColorAction, InitialAction initialDepthAction, FinalAction finalDepthAction, Color[] clearColorValues, float clearDepth, uint clearStencil, Nullable<Rect2> region, Godot.Collections.Array storageTextures)
public long DrawListBegin(Rid framebuffer, InitialAction initialColorAction, FinalAction finalColorAction, InitialAction initialDepthAction, FinalAction finalDepthAction, ReadOnlySpan<Color> clearColorValues, float clearDepth, uint clearStencil, Nullable<Rect2> region, Godot.Collections.Array storageTextures)
{
return DrawListBegin(framebuffer, initialColorAction, finalColorAction, initialDepthAction, finalDepthAction, clearColorValues, clearDepth, clearStencil, region, new Godot.Collections.Array<Rid>(storageTextures));
}
Expand All @@ -187,7 +187,7 @@ public void PushList(int level, ListType type, bool capitalize)
PushList(level, type, capitalize, bullet: "•");
}

/// <inheritdoc cref="PushParagraph(HorizontalAlignment, TextDirection, string, TextServer.StructuredTextParser, TextServer.JustificationFlag, float[])"/>
/// <inheritdoc cref="PushParagraph(Godot.HorizontalAlignment,Godot.Control.TextDirection,string,Godot.TextServer.StructuredTextParser,Godot.TextServer.JustificationFlag,ReadOnlySpan{float})"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public void PushParagraph(HorizontalAlignment alignment, TextDirection baseDirection, string language, TextServer.StructuredTextParser stParser)
{
Expand All @@ -197,9 +197,9 @@ public void PushParagraph(HorizontalAlignment alignment, TextDirection baseDirec

partial class SurfaceTool
{
/// <inheritdoc cref="AddTriangleFan(Vector3[], Vector2[], Color[], Vector2[], Vector3[], Godot.Collections.Array{Plane})"/>
/// <inheritdoc cref="AddTriangleFan(System.ReadOnlySpan{Godot.Vector3},System.ReadOnlySpan{Godot.Vector2},System.ReadOnlySpan{Godot.Color},System.ReadOnlySpan{Godot.Vector2},System.ReadOnlySpan{Godot.Vector3},Godot.Collections.Array)"/>
[EditorBrowsable(EditorBrowsableState.Never)]
public void AddTriangleFan(Vector3[] vertices, Vector2[] uvs, Color[] colors, Vector2[] uv2S, Vector3[] normals, Godot.Collections.Array tangents)
public void AddTriangleFan(ReadOnlySpan<Vector3> vertices, ReadOnlySpan<Vector2> uvs, ReadOnlySpan<Color> colors, ReadOnlySpan<Vector2> uv2S, ReadOnlySpan<Vector3> normals, Godot.Collections.Array tangents)
{
AddTriangleFan(vertices, uvs, colors, uv2S, normals, new Godot.Collections.Array<Plane>(tangents));
}
Expand Down
Loading

0 comments on commit 2fad8dd

Please sign in to comment.