diff options
Diffstat (limited to 'modules/mono')
11 files changed, 174 insertions, 67 deletions
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs index 813bdf1e9f..47a4516948 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotPluginsInitializerGenerator.cs @@ -48,7 +48,7 @@ namespace GodotPlugins.Game } catch (Exception e) { - Console.Error.WriteLine(e); + global::System.Console.Error.WriteLine(e); return false.ToGodotBool(); } } diff --git a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs index 019504ad66..70b48b0e3a 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Export/ExportPlugin.cs @@ -185,7 +185,9 @@ namespace GodotTools.Export foreach (string file in Directory.GetFiles(publishOutputTempDir, "*", SearchOption.AllDirectories)) { - AddSharedObject(file, tags: null, projectDataDirName); + AddSharedObject(file, tags: null, + Path.Join(projectDataDirName, + Path.GetRelativePath(publishOutputTempDir, Path.GetDirectoryName(file)))); } } } diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs index 344b76a202..02d0226e90 100644 --- a/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs +++ b/modules/mono/glue/GodotSharp/GodotPlugins/PluginLoadContext.cs @@ -21,6 +21,26 @@ namespace GodotPlugins _resolver = new AssemblyDependencyResolver(pluginPath); _sharedAssemblies = sharedAssemblies; _mainLoadContext = mainLoadContext; + + if (string.IsNullOrEmpty(AppContext.BaseDirectory)) + { + // See https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs#L17-L35 + // but Assembly.Location is unavailable, because we load assemblies from memory. + string? baseDirectory = Path.GetDirectoryName(pluginPath); + if (baseDirectory != null) + { + if (!Path.EndsInDirectorySeparator(baseDirectory)) + baseDirectory += Path.PathSeparator; + // This SetData call effectively sets AppContext.BaseDirectory + // See https://github.com/dotnet/runtime/blob/v6.0.0/src/libraries/System.Private.CoreLib/src/System/AppContext.cs#L21-L25 + AppDomain.CurrentDomain.SetData("APP_CONTEXT_BASE_DIRECTORY", baseDirectory); + } + else + { + // TODO: How to log from GodotPlugins? (delegate pointer?) + Console.Error.WriteLine("Failed to set AppContext.BaseDirectory. Dynamic loading of libraries may fail."); + } + } } protected override Assembly? Load(AssemblyName assemblyName) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs index 8463403096..4610761bdb 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Extensions/PackedSceneExtensions.cs @@ -7,7 +7,7 @@ namespace Godot /// <summary> /// Instantiates the scene's node hierarchy, erroring on failure. /// Triggers child scene instantiation(s). Triggers a - /// <see cref="Node.NotificationInstanced"/> notification on the root node. + /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node. /// </summary> /// <seealso cref="InstantiateOrNull{T}(GenEditState)"/> /// <exception cref="InvalidCastException"> @@ -23,7 +23,7 @@ namespace Godot /// <summary> /// Instantiates the scene's node hierarchy, returning <see langword="null"/> on failure. /// Triggers child scene instantiation(s). Triggers a - /// <see cref="Node.NotificationInstanced"/> notification on the root node. + /// <see cref="Node.NotificationSceneInstantiated"/> notification on the root node. /// </summary> /// <seealso cref="Instantiate{T}(GenEditState)"/> /// <typeparam name="T">The type to cast to. Should be a descendant of <see cref="Node"/>.</typeparam> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index ac1d8d3465..3d72ee0036 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -482,6 +482,10 @@ namespace Godot.NativeInterop public static partial godot_bool godotsharp_node_path_is_absolute(in godot_node_path p_self); + public static partial godot_bool godotsharp_node_path_equals(in godot_node_path p_self, in godot_node_path p_other); + + public static partial int godotsharp_node_path_hash(in godot_node_path p_self); + // GD, etc internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs index b02bd167a1..f216fb7ea3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NodePath.cs @@ -39,7 +39,7 @@ namespace Godot /// new NodePath("/root/MyAutoload"); // If you have an autoloaded node or scene. /// </code> /// </example> - public sealed class NodePath : IDisposable + public sealed class NodePath : IDisposable, IEquatable<NodePath> { internal godot_node_path.movable NativeValue; @@ -288,5 +288,37 @@ namespace Godot /// </summary> /// <returns>If the <see cref="NodePath"/> is empty.</returns> public bool IsEmpty => NativeValue.DangerousSelfRef.IsEmpty; + + public static bool operator ==(NodePath left, NodePath right) + { + if (left is null) + return right is null; + return left.Equals(right); + } + + public static bool operator !=(NodePath left, NodePath right) + { + return !(left == right); + } + + public bool Equals(NodePath other) + { + if (other is null) + return false; + var self = (godot_node_path)NativeValue; + var otherNative = (godot_node_path)other.NativeValue; + return NativeFuncs.godotsharp_node_path_equals(self, otherNative).ToBool(); + } + + public override bool Equals(object obj) + { + return ReferenceEquals(this, obj) || (obj is NodePath other && Equals(other)); + } + + public override int GetHashCode() + { + var self = (godot_node_path)NativeValue; + return NativeFuncs.godotsharp_node_path_hash(self); + } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs index 150eb98fc7..350626389b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rid.cs @@ -6,13 +6,17 @@ using Godot.NativeInterop; namespace Godot { /// <summary> - /// The Rid type is used to access the unique integer ID of a resource. - /// They are opaque, which means they do not grant access to the associated - /// resource by themselves. They are used by and with the low-level Server - /// classes such as <see cref="RenderingServer"/>. + /// The RID type is used to access a low-level resource by its unique ID. + /// RIDs are opaque, which means they do not grant access to the resource + /// by themselves. They are used by the low-level server classes, such as + /// <see cref="DisplayServer"/>, <see cref="RenderingServer"/>, + /// <see cref="TextServer"/>, etc. + /// + /// A low-level resource may correspond to a high-level <see cref="Resource"/>, + /// such as <see cref="Texture"/> or <see cref="Mesh"/> /// </summary> [StructLayout(LayoutKind.Sequential)] - public readonly struct Rid + public readonly struct Rid : IEquatable<Rid> { private readonly ulong _id; // Default is 0 @@ -28,15 +32,73 @@ namespace Godot => _id = from is Resource res ? res.GetRid()._id : default; /// <summary> - /// Returns the ID of the referenced resource. + /// Returns the ID of the referenced low-level resource. /// </summary> /// <returns>The ID of the referenced resource.</returns> public ulong Id => _id; /// <summary> + /// Returns <see langword="true"/> if the <see cref="Rid"/> is not <c>0</c>. + /// </summary> + /// <returns>Whether or not the ID is valid.</returns> + public bool IsValid => _id != 0; + + /// <summary> + /// Returns <see langword="true"/> if both <see cref="Rid"/>s are equal, + /// which means they both refer to the same low-level resource. + /// </summary> + /// <param name="left">The left RID.</param> + /// <param name="right">The right RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public static bool operator ==(Rid left, Rid right) + { + return left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if the <see cref="Rid"/>s are not equal. + /// </summary> + /// <param name="left">The left RID.</param> + /// <param name="right">The right RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public static bool operator !=(Rid left, Rid right) + { + return !left.Equals(right); + } + + /// <summary> + /// Returns <see langword="true"/> if this RID and <paramref name="obj"/> are equal. + /// </summary> + /// <param name="obj">The other object to compare.</param> + /// <returns>Whether or not the color and the other object are equal.</returns> + public override readonly bool Equals(object obj) + { + return obj is Rid other && Equals(other); + } + + /// <summary> + /// Returns <see langword="true"/> if the RIDs are equal. + /// </summary> + /// <param name="other">The other RID.</param> + /// <returns>Whether or not the RIDs are equal.</returns> + public readonly bool Equals(Rid other) + { + return _id == other.Id; + } + + /// <summary> + /// Serves as the hash function for <see cref="Rid"/>. + /// </summary> + /// <returns>A hash code for this RID.</returns> + public override readonly int GetHashCode() + { + return HashCode.Combine(_id); + } + + /// <summary> /// Converts this <see cref="Rid"/> to a string. /// </summary> /// <returns>A string representation of this Rid.</returns> - public override string ToString() => $"Rid({Id})"; + public override string ToString() => $"RID({Id})"; } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs index b9ee0bc278..97d28f9ee9 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringName.cs @@ -10,7 +10,7 @@ namespace Godot /// Comparing them is much faster than with regular strings, because only the pointers are compared, /// not the whole strings. /// </summary> - public sealed class StringName : IDisposable + public sealed class StringName : IDisposable, IEquatable<StringName> { internal godot_string_name.movable NativeValue; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index e939396926..d7392dbda8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -50,6 +50,18 @@ namespace Godot } /// <summary> + /// Returns the transform's skew (in radians). + /// </summary> + public readonly real_t Skew + { + get + { + real_t detSign = Mathf.Sign(BasisDeterminant()); + return Mathf.Acos(X.Normalized().Dot(detSign * Y.Normalized())) - Mathf.Pi * 0.5f; + } + } + + /// <summary> /// Access whole columns in the form of <see cref="Vector2"/>. /// The third column is the <see cref="Origin"/> vector. /// </summary> @@ -190,48 +202,13 @@ namespace Godot /// <returns>The interpolated transform.</returns> public readonly Transform2D InterpolateWith(Transform2D transform, real_t weight) { - real_t r1 = Rotation; - real_t r2 = transform.Rotation; - - Vector2 s1 = Scale; - Vector2 s2 = transform.Scale; - - // Slerp rotation - (real_t sin1, real_t cos1) = Mathf.SinCos(r1); - (real_t sin2, real_t cos2) = Mathf.SinCos(r2); - var v1 = new Vector2(cos1, sin1); - var v2 = new Vector2(cos2, sin2); - - real_t dot = v1.Dot(v2); - - dot = Mathf.Clamp(dot, -1.0f, 1.0f); - - Vector2 v; - - if (dot > 0.9995f) - { - // Linearly interpolate to avoid numerical precision issues - v = v1.Lerp(v2, weight).Normalized(); - } - else - { - real_t angle = weight * Mathf.Acos(dot); - Vector2 v3 = (v2 - (v1 * dot)).Normalized(); - (real_t sine, real_t cos) = Mathf.SinCos(angle); - v = (v1 * sine) + (v3 * cos); - } - - // Extract parameters - Vector2 p1 = Origin; - Vector2 p2 = transform.Origin; - - // Construct matrix - var res = new Transform2D(Mathf.Atan2(v.Y, v.X), p1.Lerp(p2, weight)); - Vector2 scale = s1.Lerp(s2, weight); - res.X *= scale; - res.Y *= scale; - - return res; + return new Transform2D + ( + Mathf.LerpAngle(Rotation, transform.Rotation, weight), + Scale.Lerp(transform.Scale, weight), + Mathf.LerpAngle(Skew, transform.Skew, weight), + Origin.Lerp(transform.Origin, weight) + ); } /// <summary> @@ -270,19 +247,19 @@ namespace Godot /// <returns>The orthonormalized transform.</returns> public readonly Transform2D Orthonormalized() { - Transform2D on = this; + Transform2D ortho = this; - Vector2 onX = on.X; - Vector2 onY = on.Y; + Vector2 orthoX = ortho.X; + Vector2 orthoY = ortho.Y; - onX.Normalize(); - onY = onY - (onX * onX.Dot(onY)); - onY.Normalize(); + orthoX.Normalize(); + orthoY = orthoY - orthoX * orthoX.Dot(orthoY); + orthoY.Normalize(); - on.X = onX; - on.Y = onY; + ortho.X = orthoX; + ortho.Y = orthoY; - return on; + return ortho; } /// <summary> @@ -294,7 +271,7 @@ namespace Godot /// <returns>The rotated transformation matrix.</returns> public readonly Transform2D Rotated(real_t angle) { - return this * new Transform2D(angle, new Vector2()); + return new Transform2D(angle, new Vector2()) * this; } /// <summary> @@ -306,7 +283,7 @@ namespace Godot /// <returns>The rotated transformation matrix.</returns> public readonly Transform2D RotatedLocal(real_t angle) { - return new Transform2D(angle, new Vector2()) * this; + return this * new Transform2D(angle, new Vector2()); } /// <summary> diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index c46503df95..306ac333eb 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -1209,6 +1209,14 @@ bool godotsharp_node_path_is_absolute(const NodePath *p_self) { return p_self->is_absolute(); } +bool godotsharp_node_path_equals(const NodePath *p_self, const NodePath *p_other) { + return *p_self == *p_other; +} + +int godotsharp_node_path_hash(const NodePath *p_self) { + return p_self->hash(); +} + void godotsharp_randomize() { Math::randomize(); } @@ -1556,6 +1564,8 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_node_path_get_subname, (void *)godotsharp_node_path_get_subname_count, (void *)godotsharp_node_path_is_absolute, + (void *)godotsharp_node_path_equals, + (void *)godotsharp_node_path_hash, (void *)godotsharp_bytes_to_var, (void *)godotsharp_convert, (void *)godotsharp_hash, diff --git a/modules/mono/utils/naming_utils.cpp b/modules/mono/utils/naming_utils.cpp index dc9bc3485a..62fbf815f8 100644 --- a/modules/mono/utils/naming_utils.cpp +++ b/modules/mono/utils/naming_utils.cpp @@ -109,7 +109,7 @@ Vector<String> _split_pascal_case(const String &p_identifier) { if (!is_digit(p_identifier[i])) { // These conditions only apply when the separator is not a digit. if (i - current_part_start == 1) { - // Upper character was only the beggining of a word. + // Upper character was only the beginning of a word. prev_was_upper = false; continue; } |