feat: updated engine version to 4.4-rc1

This commit is contained in:
Sara 2025-02-23 14:38:14 +01:00
parent ee00efde1f
commit 21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions

View file

@ -1,11 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10</LangVersion>
<Nullable>enable</Nullable>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.10.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" PrivateAssets="all" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
</ItemGroup>
</Project>

View file

@ -172,7 +172,7 @@ using Godot.NativeInterop;
{
var parameter = callback.Parameters[i];
AppendRefKind(source, parameter.RefKind);
AppendRefKind(source, parameter.RefKind, parameter.ScopedKind);
source.Append(' ');
source.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
source.Append(' ');
@ -208,7 +208,7 @@ using Godot.NativeInterop;
{
// If it's a by-ref param and we can't get the pointer
// just pass it by-ref and let it be pinned.
AppendRefKind(methodCallArguments, parameter.RefKind)
AppendRefKind(methodCallArguments, parameter.RefKind, parameter.ScopedKind)
.Append(' ')
.Append(parameter.Name);
}
@ -346,7 +346,7 @@ using Godot.NativeInterop;
{
// If it's a by-ref param and we can't get the pointer
// just pass it by-ref and let it be pinned.
AppendRefKind(source, parameter.RefKind)
AppendRefKind(source, parameter.RefKind, parameter.ScopedKind)
.Append(' ')
.Append(parameter.Type.FullQualifiedNameIncludeGlobal());
}
@ -392,14 +392,18 @@ using Godot.NativeInterop;
private static bool IsByRefParameter(IParameterSymbol parameter) =>
parameter.RefKind is RefKind.In or RefKind.Out or RefKind.Ref;
private static StringBuilder AppendRefKind(StringBuilder source, RefKind refKind) =>
refKind switch
private static StringBuilder AppendRefKind(StringBuilder source, RefKind refKind, ScopedKind scopedKind)
{
return (refKind, scopedKind) switch
{
RefKind.In => source.Append("in"),
RefKind.Out => source.Append("out"),
RefKind.Ref => source.Append("ref"),
(RefKind.Out, _) => source.Append("out"),
(RefKind.In, ScopedKind.ScopedRef) => source.Append("scoped in"),
(RefKind.In, _) => source.Append("in"),
(RefKind.Ref, ScopedKind.ScopedRef) => source.Append("scoped ref"),
(RefKind.Ref, _) => source.Append("ref"),
_ => source,
};
}
private static void AppendPointerType(StringBuilder source, ITypeSymbol type)
{

View file

@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<LangVersion>10</LangVersion>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

View file

@ -314,13 +314,20 @@ namespace Godot
/// <returns>A vector representing the support.</returns>
public readonly Vector3 GetSupport(Vector3 dir)
{
Vector3 halfExtents = _size * 0.5f;
Vector3 ofs = _position + halfExtents;
return ofs + new Vector3(
dir.X > 0f ? halfExtents.X : -halfExtents.X,
dir.Y > 0f ? halfExtents.Y : -halfExtents.Y,
dir.Z > 0f ? halfExtents.Z : -halfExtents.Z);
Vector3 support = _position;
if (dir.X > 0.0f)
{
support.X += _size.X;
}
if (dir.Y > 0.0f)
{
support.Y += _size.Y;
}
if (dir.Z > 0.0f)
{
support.Z += _size.Z;
}
return support;
}
/// <summary>

View file

@ -50,8 +50,7 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(IEnumerable<Variant> collection) : this()
{
if (collection == null)
throw new ArgumentNullException(nameof(collection));
ArgumentNullException.ThrowIfNull(collection);
foreach (Variant element in collection)
Add(element);
@ -67,8 +66,7 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(Variant[] array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
ArgumentNullException.ThrowIfNull(array);
NativeValue = (godot_array.movable)NativeFuncs.godotsharp_array_new();
_weakReferenceToSelf = DisposablesTracker.RegisterDisposable(this);
@ -1046,6 +1044,8 @@ namespace Godot.Collections
[DebuggerTypeProxy(typeof(ArrayDebugView<>))]
[DebuggerDisplay("Count = {Count}")]
[SuppressMessage("ReSharper", "RedundantExtendsListEntry")]
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
Justification = "Known issue. Requires explicit refcount management to not dispose untyped collections.")]
[SuppressMessage("Naming", "CA1710", MessageId = "Identifiers should have correct suffix")]
public sealed class Array<[MustBeVariant] T> :
IList<T>,
@ -1054,16 +1054,32 @@ namespace Godot.Collections
IEnumerable<T>,
IGenericGodotArray
{
private static godot_variant ToVariantFunc(in Array<T> godotArray) =>
private static godot_variant ToVariantFunc(scoped in Array<T> godotArray) =>
VariantUtils.CreateFromArray(godotArray);
private static Array<T> FromVariantFunc(in godot_variant variant) =>
VariantUtils.ConvertToArray<T>(variant);
private void SetTypedForUnderlyingArray()
{
Marshaling.GetTypedCollectionParameterInfo<T>(out var elemVariantType, out var elemClassName, out var elemScriptRef);
var self = (godot_array)NativeValue;
using (elemScriptRef)
{
NativeFuncs.godotsharp_array_set_typed(
ref self,
(uint)elemVariantType,
elemClassName,
elemScriptRef);
}
}
static unsafe Array()
{
VariantUtils.GenericConversion<Array<T>>.ToVariantCb = &ToVariantFunc;
VariantUtils.GenericConversion<Array<T>>.FromVariantCb = &FromVariantFunc;
VariantUtils.GenericConversion<Array<T>>.ToVariantCb = ToVariantFunc;
VariantUtils.GenericConversion<Array<T>>.FromVariantCb = FromVariantFunc;
}
private readonly Array _underlyingArray;
@ -1083,6 +1099,7 @@ namespace Godot.Collections
public Array()
{
_underlyingArray = new Array();
SetTypedForUnderlyingArray();
}
/// <summary>
@ -1095,10 +1112,10 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(IEnumerable<T> collection)
{
if (collection == null)
throw new ArgumentNullException(nameof(collection));
ArgumentNullException.ThrowIfNull(collection);
_underlyingArray = new Array();
SetTypedForUnderlyingArray();
foreach (T element in collection)
Add(element);
@ -1114,10 +1131,10 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(T[] array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
ArgumentNullException.ThrowIfNull(array);
_underlyingArray = new Array();
SetTypedForUnderlyingArray();
foreach (T element in array)
Add(element);
@ -1133,8 +1150,7 @@ namespace Godot.Collections
/// <returns>A new Godot Array.</returns>
public Array(Array array)
{
if (array == null)
throw new ArgumentNullException(nameof(array));
ArgumentNullException.ThrowIfNull(array);
_underlyingArray = array;
}

View file

@ -0,0 +1,33 @@
using System;
#nullable enable
namespace Godot
{
/// <summary>
/// Exports the annotated <see cref="Callable"/> as a clickable button.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public sealed class ExportToolButtonAttribute : Attribute
{
/// <summary>
/// The label of the button.
/// </summary>
public string Text { get; }
/// <summary>
/// If defined, used to fetch an icon for the button via <see cref="Control.GetThemeIcon"/>,
/// from the <code>EditorIcons</code> theme type.
/// </summary>
public string? Icon { get; init; }
/// <summary>
/// Exports the annotated <see cref="Callable"/> as a clickable button.
/// </summary>
/// <param name="text">The label of the button.</param>
public ExportToolButtonAttribute(string text)
{
Text = text;
}
}
}

View file

@ -19,7 +19,7 @@ namespace Godot.Bridge
public delegate* unmanaged<godot_string_name*, IntPtr, IntPtr> ScriptManagerBridge_CreateManagedForGodotObjectBinding;
public delegate* unmanaged<IntPtr, IntPtr, godot_variant**, int, godot_bool> ScriptManagerBridge_CreateManagedForGodotObjectScriptInstance;
public delegate* unmanaged<IntPtr, godot_string_name*, void> ScriptManagerBridge_GetScriptNativeName;
public delegate* unmanaged<godot_string*, godot_string*, godot_string*, godot_string*, void> ScriptManagerBridge_GetGlobalClassName;
public delegate* unmanaged<godot_string*, godot_string*, godot_string*, godot_bool*, godot_bool*, godot_string*, void> ScriptManagerBridge_GetGlobalClassName;
public delegate* unmanaged<IntPtr, IntPtr, void> ScriptManagerBridge_SetGodotObjectPtr;
public delegate* unmanaged<IntPtr, godot_string_name*, godot_variant**, int, godot_bool*, void> ScriptManagerBridge_RaiseEventSignal;
public delegate* unmanaged<IntPtr, IntPtr, godot_bool> ScriptManagerBridge_ScriptIsOrInherits;

View file

@ -90,30 +90,17 @@ namespace Godot.Bridge
}
[UnmanagedCallersOnly]
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName,
IntPtr godotObject)
internal static unsafe IntPtr CreateManagedForGodotObjectBinding(godot_string_name* nativeTypeName, IntPtr godotObject)
{
// TODO: Optimize with source generators and delegate pointers.
try
{
using var stringName = StringName.CreateTakingOwnershipOfDisposableValue(
NativeFuncs.godotsharp_string_name_new_copy(CustomUnsafe.AsRef(nativeTypeName)));
string nativeTypeNameStr = stringName.ToString();
Type nativeType = TypeGetProxyClass(nativeTypeNameStr) ?? throw new InvalidOperationException(
"Wrapper class not found for type: " + nativeTypeNameStr);
var obj = (GodotObject)FormatterServices.GetUninitializedObject(nativeType);
var instance = Constructors.Invoke(nativeTypeNameStr, godotObject);
var ctor = nativeType.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null, Type.EmptyTypes, null);
obj.NativePtr = godotObject;
_ = ctor!.Invoke(obj, null);
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(obj));
return GCHandle.ToIntPtr(CustomGCHandle.AllocStrong(instance));
}
catch (Exception e)
{
@ -155,7 +142,7 @@ namespace Godot.Bridge
}
}
var obj = (GodotObject)FormatterServices.GetUninitializedObject(scriptType);
var obj = (GodotObject)RuntimeHelpers.GetUninitializedObject(scriptType);
var parameters = ctor.GetParameters();
int paramCount = parameters.Length;
@ -194,18 +181,7 @@ namespace Godot.Bridge
return;
}
var native = GodotObject.InternalGetClassNativeBase(scriptType);
var field = native.GetField("NativeName", BindingFlags.DeclaredOnly | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic);
if (field == null)
{
*outRes = default;
return;
}
var nativeName = (StringName?)field.GetValue(null);
var nativeName = GodotObject.InternalGetClassNativeBaseName(scriptType);
if (nativeName == null)
{
@ -223,7 +199,7 @@ namespace Godot.Bridge
}
[UnmanagedCallersOnly]
internal static unsafe void GetGlobalClassName(godot_string* scriptPath, godot_string* outBaseType, godot_string* outIconPath, godot_string* outClassName)
internal static unsafe void GetGlobalClassName(godot_string* scriptPath, godot_string* outBaseType, godot_string* outIconPath, godot_bool* outIsAbstract, godot_bool* outIsTool, godot_string* outClassName)
{
// This method must always return the outBaseType for every script, even if the script is
// not a global class. But if the script is not a global class it must return an empty
@ -241,11 +217,17 @@ namespace Godot.Bridge
if (outIconPath != null)
{
var iconAttr = scriptType.GetCustomAttributes(inherit: false)
IconAttribute? iconAttr = scriptType.GetCustomAttributes(inherit: false)
.OfType<IconAttribute>()
.FirstOrDefault();
*outIconPath = Marshaling.ConvertStringToNative(iconAttr?.Path);
if (!string.IsNullOrEmpty(iconAttr?.Path))
{
string iconPath = iconAttr.Path.IsAbsolutePath()
? iconAttr.Path.SimplifyPath()
: scriptPathStr.GetBaseDir().PathJoin(iconAttr.Path).SimplifyPath();
*outIconPath = Marshaling.ConvertStringToNative(iconPath);
}
}
if (outBaseType != null)
@ -272,6 +254,16 @@ namespace Godot.Bridge
}
}
if (outIsAbstract != null)
{
*outIsAbstract = scriptType.IsAbstract.ToGodotBool();
}
if (outIsTool != null)
{
*outIsTool = Attribute.IsDefined(scriptType, typeof(ToolAttribute)).ToGodotBool();
}
if (!IsGlobalClass(scriptType))
{
// Scripts that are not global classes should not have a name.
@ -302,66 +294,6 @@ namespace Godot.Bridge
}
}
private static Type? TypeGetProxyClass(string nativeTypeNameStr)
{
// Performance is not critical here as this will be replaced with a generated dictionary.
if (nativeTypeNameStr[0] == '_')
nativeTypeNameStr = nativeTypeNameStr.Substring(1);
Type? wrapperType = typeof(GodotObject).Assembly.GetType("Godot." + nativeTypeNameStr);
if (wrapperType == null)
{
wrapperType = GetTypeByGodotClassAttr(typeof(GodotObject).Assembly, nativeTypeNameStr);
}
if (wrapperType == null)
{
var editorAssembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name == "GodotSharpEditor");
if (editorAssembly != null)
{
wrapperType = editorAssembly.GetType("Godot." + nativeTypeNameStr);
if (wrapperType == null)
{
wrapperType = GetTypeByGodotClassAttr(editorAssembly, nativeTypeNameStr);
}
}
}
static Type? GetTypeByGodotClassAttr(Assembly assembly, string nativeTypeNameStr)
{
var types = assembly.GetTypes();
foreach (var type in types)
{
var attr = type.GetCustomAttribute<GodotClassNameAttribute>();
if (attr?.Name == nativeTypeNameStr)
{
return type;
}
}
return null;
}
static bool IsStatic(Type type) => type.IsAbstract && type.IsSealed;
if (wrapperType != null && IsStatic(wrapperType))
{
// A static class means this is a Godot singleton class. Try to get the Instance proxy type.
wrapperType = TypeGetProxyClass($"{wrapperType.Name}Instance");
if (wrapperType == null)
{
// Otherwise, fallback to GodotObject.
return typeof(GodotObject);
}
}
return wrapperType;
}
// Called from GodotPlugins
// ReSharper disable once UnusedMember.Local
public static void LookupScriptsInAssembly(Assembly assembly)
@ -499,16 +431,29 @@ namespace Godot.Bridge
private static unsafe bool AddScriptBridgeCore(IntPtr scriptPtr, string scriptPath)
{
lock (_scriptTypeBiMap.ReadWriteLock)
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
try
{
if (!_scriptTypeBiMap.IsScriptRegistered(scriptPtr))
{
if (!_pathTypeBiMap.TryGetScriptType(scriptPath, out Type? scriptType))
return false;
_scriptTypeBiMap.Add(scriptPtr, scriptType);
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
try
{
_scriptTypeBiMap.Add(scriptPtr, scriptType);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
}
}
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
}
return true;
}
@ -531,7 +476,8 @@ namespace Godot.Bridge
private static unsafe void GetOrCreateScriptBridgeForType(Type scriptType, godot_ref* outScript)
{
lock (_scriptTypeBiMap.ReadWriteLock)
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
try
{
if (_scriptTypeBiMap.TryGetScriptPtr(scriptType, out IntPtr scriptPtr))
{
@ -543,6 +489,10 @@ namespace Godot.Bridge
// This path is slower, but it's only executed for the first instantiation of the type
CreateScriptBridgeForType(scriptType, outScript);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
}
}
internal static unsafe void GetOrLoadOrCreateScriptForType(Type scriptType, godot_ref* outScript)
@ -550,7 +500,8 @@ namespace Godot.Bridge
static bool GetPathOtherwiseGetOrCreateScript(Type scriptType, godot_ref* outScript,
[MaybeNullWhen(false)] out string scriptPath)
{
lock (_scriptTypeBiMap.ReadWriteLock)
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
try
{
if (_scriptTypeBiMap.TryGetScriptPtr(scriptType, out IntPtr scriptPtr))
{
@ -578,6 +529,10 @@ namespace Godot.Bridge
scriptPath = null;
return false;
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
}
}
static string GetVirtualConstructedGenericTypeScriptPath(Type scriptType, string scriptPath)
@ -607,7 +562,16 @@ namespace Godot.Bridge
// IMPORTANT: The virtual path must be added to _pathTypeBiMap before the first
// load of the script, otherwise the loaded script won't be added to _scriptTypeBiMap.
scriptPath = GetVirtualConstructedGenericTypeScriptPath(scriptType, scriptPath);
_pathTypeBiMap.Add(scriptPath, scriptType);
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
try
{
_pathTypeBiMap.Add(scriptPath, scriptType);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
}
}
// This must be done outside the read-write lock, as the script resource loading can lock it
@ -637,104 +601,119 @@ namespace Godot.Bridge
{
Debug.Assert(!scriptType.IsGenericTypeDefinition, $"Script type must be a constructed generic type or not generic at all. Type: {scriptType}.");
NativeFuncs.godotsharp_internal_new_csharp_script(outScript);
IntPtr scriptPtr = outScript->Reference;
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
try
{
NativeFuncs.godotsharp_internal_new_csharp_script(outScript);
IntPtr scriptPtr = outScript->Reference;
// Caller takes care of locking
_scriptTypeBiMap.Add(scriptPtr, scriptType);
_scriptTypeBiMap.Add(scriptPtr, scriptType);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
}
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
NativeFuncs.godotsharp_internal_reload_registered_script(outScript->Reference);
}
[UnmanagedCallersOnly]
internal static void RemoveScriptBridge(IntPtr scriptPtr)
{
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
try
{
lock (_scriptTypeBiMap.ReadWriteLock)
{
_scriptTypeBiMap.Remove(scriptPtr);
}
_scriptTypeBiMap.Remove(scriptPtr);
}
catch (Exception e)
{
ExceptionUtils.LogException(e);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
}
}
[UnmanagedCallersOnly]
internal static godot_bool TryReloadRegisteredScriptWithClass(IntPtr scriptPtr)
{
_scriptTypeBiMap.ReadWriteLock.EnterUpgradeableReadLock();
try
{
lock (_scriptTypeBiMap.ReadWriteLock)
if (_scriptTypeBiMap.TryGetScriptType(scriptPtr, out _))
{
if (_scriptTypeBiMap.TryGetScriptType(scriptPtr, out _))
{
// NOTE:
// Currently, we reload all scripts, not only the ones from the unloaded ALC.
// As such, we need to handle this case instead of treating it as an error.
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
return godot_bool.True;
}
if (!_scriptDataForReload.TryGetValue(scriptPtr, out var dataForReload))
{
GD.PushError("Missing class qualified name for reloading script");
return godot_bool.False;
}
_ = _scriptDataForReload.TryRemove(scriptPtr, out _);
if (dataForReload.assemblyName == null)
{
GD.PushError(
$"Missing assembly name of class '{dataForReload.classFullName}' for reloading script");
return godot_bool.False;
}
var scriptType = ReflectionUtils.FindTypeInLoadedAssemblies(dataForReload.assemblyName,
dataForReload.classFullName);
if (scriptType == null)
{
// The class was removed, can't reload
return godot_bool.False;
}
if (!typeof(GodotObject).IsAssignableFrom(scriptType))
{
// The class no longer inherits GodotObject, can't reload
return godot_bool.False;
}
_scriptTypeBiMap.Add(scriptPtr, scriptType);
// NOTE:
// Currently, we reload all scripts, not only the ones from the unloaded ALC.
// As such, we need to handle this case instead of treating it as an error.
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
return godot_bool.True;
}
if (!_scriptDataForReload.TryGetValue(scriptPtr, out var dataForReload))
{
GD.PushError("Missing class qualified name for reloading script");
return godot_bool.False;
}
_ = _scriptDataForReload.TryRemove(scriptPtr, out _);
if (dataForReload.assemblyName == null)
{
GD.PushError(
$"Missing assembly name of class '{dataForReload.classFullName}' for reloading script");
return godot_bool.False;
}
var scriptType = ReflectionUtils.FindTypeInLoadedAssemblies(dataForReload.assemblyName,
dataForReload.classFullName);
if (scriptType == null)
{
// The class was removed, can't reload
return godot_bool.False;
}
if (!typeof(GodotObject).IsAssignableFrom(scriptType))
{
// The class no longer inherits GodotObject, can't reload
return godot_bool.False;
}
_scriptTypeBiMap.ReadWriteLock.EnterWriteLock();
try
{
_scriptTypeBiMap.Add(scriptPtr, scriptType);
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitWriteLock();
}
NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr);
return godot_bool.True;
}
catch (Exception e)
{
ExceptionUtils.LogException(e);
return godot_bool.False;
}
finally
{
_scriptTypeBiMap.ReadWriteLock.ExitUpgradeableReadLock();
}
}
private static unsafe void GetScriptTypeInfo(Type scriptType, godot_csharp_type_info* outTypeInfo)
{
Type native = GodotObject.InternalGetClassNativeBase(scriptType);
godot_string className = Marshaling.ConvertStringToNative(ReflectionUtils.ConstructTypeName(scriptType));
string typeName = scriptType.Name;
if (scriptType.IsGenericType)
{
var sb = new StringBuilder();
AppendTypeName(sb, scriptType);
typeName = sb.ToString();
}
StringName? nativeBase = GodotObject.InternalGetClassNativeBaseName(scriptType);
godot_string className = Marshaling.ConvertStringToNative(typeName);
godot_string_name nativeBaseName = nativeBase != null
? NativeFuncs.godotsharp_string_name_new_copy((godot_string_name)nativeBase.NativeValue)
: default;
bool isTool = scriptType.IsDefined(typeof(ToolAttribute), inherit: false);
@ -760,6 +739,7 @@ namespace Godot.Bridge
godot_string iconPath = Marshaling.ConvertStringToNative(iconAttr?.Path);
outTypeInfo->ClassName = className;
outTypeInfo->NativeBaseName = nativeBaseName;
outTypeInfo->IconPath = iconPath;
outTypeInfo->IsTool = isTool.ToGodotBool();
outTypeInfo->IsGlobalClass = isGlobalClass.ToGodotBool();
@ -767,24 +747,6 @@ namespace Godot.Bridge
outTypeInfo->IsGenericTypeDefinition = scriptType.IsGenericTypeDefinition.ToGodotBool();
outTypeInfo->IsConstructedGenericType = scriptType.IsConstructedGenericType.ToGodotBool();
static void AppendTypeName(StringBuilder sb, Type type)
{
sb.Append(type.Name);
if (type.IsGenericType)
{
sb.Append('<');
for (int i = 0; i < type.GenericTypeArguments.Length; i++)
{
Type typeArg = type.GenericTypeArguments[i];
AppendTypeName(sb, typeArg);
if (i != type.GenericTypeArguments.Length - 1)
{
sb.Append(", ");
}
}
sb.Append('>');
}
}
}
[UnmanagedCallersOnly]
@ -1098,7 +1060,7 @@ namespace Godot.Bridge
interopProperties[i] = interopProperty;
}
using godot_string currentClassName = Marshaling.ConvertStringToNative(type.Name);
using godot_string currentClassName = Marshaling.ConvertStringToNative(ReflectionUtils.ConstructTypeName(type));
addPropInfoFunc(scriptPtr, &currentClassName, interopProperties, length);

View file

@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Godot.Bridge;
@ -11,9 +12,11 @@ namespace Godot.Bridge;
public static partial class ScriptManagerBridge
{
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
Justification = "Not applicable. The class functions as a persistent singleton.")]
private class ScriptTypeBiMap
{
public readonly object ReadWriteLock = new();
public readonly ReaderWriterLockSlim ReadWriteLock = new(LockRecursionPolicy.SupportsRecursion);
private System.Collections.Generic.Dictionary<IntPtr, Type> _scriptTypeMap = new();
private System.Collections.Generic.Dictionary<Type, IntPtr> _typeScriptMap = new();
@ -65,7 +68,7 @@ public static partial class ScriptManagerBridge
private System.Collections.Generic.Dictionary<string, Type> _pathTypeMap = new();
private System.Collections.Generic.Dictionary<Type, string> _typePathMap = new();
public IReadOnlyCollection<string> Paths => _pathTypeMap.Keys;
public System.Collections.Generic.Dictionary<string, Type>.KeyCollection Paths => _pathTypeMap.Keys;
public void Add(string scriptPath, Type scriptType)
{

View file

@ -193,6 +193,51 @@ namespace Godot
}
}
/// <summary>
/// The OKHSL hue of this color, on the range 0 to 1.
/// </summary>
public float OkHslH
{
readonly get
{
return NativeFuncs.godotsharp_color_get_ok_hsl_h(this);
}
set
{
this = FromOkHsl(value, OkHslS, OkHslL, A);
}
}
/// <summary>
/// The OKHSL saturation of this color, on the range 0 to 1.
/// </summary>
public float OkHslS
{
readonly get
{
return NativeFuncs.godotsharp_color_get_ok_hsl_s(this);
}
set
{
this = FromOkHsl(OkHslH, value, OkHslL, A);
}
}
/// <summary>
/// The OKHSL lightness of this color, on the range 0 to 1.
/// </summary>
public float OkHslL
{
readonly get
{
return NativeFuncs.godotsharp_color_get_ok_hsl_l(this);
}
set
{
this = FromOkHsl(OkHslH, OkHslS, value, A);
}
}
/// <summary>
/// Returns the light intensity of the color, as a value between 0.0 and 1.0 (inclusive).
/// This is useful when determining light or dark color. Colors with a luminance smaller

View file

@ -87,8 +87,8 @@ namespace Godot
public void Resize(int size)
{
if (size < 0)
throw new ArgumentOutOfRangeException(nameof(size));
ArgumentOutOfRangeException.ThrowIfNegative(size);
var err = NativeFuncs.godotsharp_stack_info_vector_resize(ref this, size);
if (err != Error.Ok)
throw new InvalidOperationException("Failed to resize vector. Error code is: " + err.ToString());

View file

@ -174,7 +174,7 @@ namespace Godot.Collections
var keys = Array.CreateTakingOwnershipOfDisposableValue(keysArray);
godot_array valuesArray;
NativeFuncs.godotsharp_dictionary_keys(ref self, out valuesArray);
NativeFuncs.godotsharp_dictionary_values(ref self, out valuesArray);
var values = Array.CreateTakingOwnershipOfDisposableValue(valuesArray);
int count = NativeFuncs.godotsharp_dictionary_count(ref self);
@ -485,21 +485,44 @@ namespace Godot.Collections
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
[DebuggerTypeProxy(typeof(DictionaryDebugView<,>))]
[DebuggerDisplay("Count = {Count}")]
[SuppressMessage("Design", "CA1001", MessageId = "Types that own disposable fields should be disposable",
Justification = "Known issue. Requires explicit refcount management to not dispose untyped collections.")]
public class Dictionary<[MustBeVariant] TKey, [MustBeVariant] TValue> :
IDictionary<TKey, TValue>,
IReadOnlyDictionary<TKey, TValue>,
IGenericGodotDictionary
{
private static godot_variant ToVariantFunc(in Dictionary<TKey, TValue> godotDictionary) =>
private static godot_variant ToVariantFunc(scoped in Dictionary<TKey, TValue> godotDictionary) =>
VariantUtils.CreateFromDictionary(godotDictionary);
private static Dictionary<TKey, TValue> FromVariantFunc(in godot_variant variant) =>
VariantUtils.ConvertToDictionary<TKey, TValue>(variant);
private void SetTypedForUnderlyingDictionary()
{
Marshaling.GetTypedCollectionParameterInfo<TKey>(out var keyVariantType, out var keyClassName, out var keyScriptRef);
Marshaling.GetTypedCollectionParameterInfo<TValue>(out var valueVariantType, out var valueClassName, out var valueScriptRef);
var self = (godot_dictionary)NativeValue;
using (keyScriptRef)
using (valueScriptRef)
{
NativeFuncs.godotsharp_dictionary_set_typed(
ref self,
(uint)keyVariantType,
keyClassName,
keyScriptRef,
(uint)valueVariantType,
valueClassName,
valueScriptRef);
}
}
static unsafe Dictionary()
{
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = &ToVariantFunc;
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = &FromVariantFunc;
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.ToVariantCb = ToVariantFunc;
VariantUtils.GenericConversion<Dictionary<TKey, TValue>>.FromVariantCb = FromVariantFunc;
}
private readonly Dictionary _underlyingDict;
@ -519,6 +542,7 @@ namespace Godot.Collections
public Dictionary()
{
_underlyingDict = new Dictionary();
SetTypedForUnderlyingDictionary();
}
/// <summary>
@ -531,10 +555,10 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(IDictionary<TKey, TValue> dictionary)
{
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
ArgumentNullException.ThrowIfNull(dictionary);
_underlyingDict = new Dictionary();
SetTypedForUnderlyingDictionary();
foreach (KeyValuePair<TKey, TValue> entry in dictionary)
Add(entry.Key, entry.Value);
@ -550,8 +574,7 @@ namespace Godot.Collections
/// <returns>A new Godot Dictionary.</returns>
public Dictionary(Dictionary dictionary)
{
if (dictionary == null)
throw new ArgumentNullException(nameof(dictionary));
ArgumentNullException.ThrowIfNull(dictionary);
_underlyingDict = dictionary;
}

View file

@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Godot.NativeInterop;
#nullable enable
@ -51,7 +52,7 @@ namespace Godot
/// </summary>
/// <param name="instance">The instance to check.</param>
/// <returns>If the instance is a valid object.</returns>
public static bool IsInstanceValid(GodotObject? instance)
public static bool IsInstanceValid([NotNullWhen(true)] GodotObject? instance)
{
return instance != null && instance.NativeInstance != IntPtr.Zero;
}

View file

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using Godot.Bridge;
using Godot.NativeInterop;
@ -13,6 +15,8 @@ namespace Godot
private bool _disposed;
private static readonly Type _cachedType = typeof(GodotObject);
private static readonly Dictionary<Type, StringName?> _nativeNames = new Dictionary<Type, StringName?>();
internal IntPtr NativePtr;
private bool _memoryOwn;
@ -29,8 +33,19 @@ namespace Godot
}
}
internal GodotObject(IntPtr nativePtr) : this(false)
{
// NativePtr must be non-zero before calling ConstructAndInitialize to avoid invoking the constructor NativeCtor.
// We don't want to invoke the constructor, because we already have a constructed instance in nativePtr.
NativePtr = nativePtr;
unsafe
{
ConstructAndInitialize(NativeCtor, NativeName, _cachedType, refCounted: false);
}
}
internal unsafe void ConstructAndInitialize(
delegate* unmanaged<IntPtr> nativeCtor,
delegate* unmanaged<godot_bool, IntPtr> nativeCtor,
StringName nativeName,
Type cachedType,
bool refCounted
@ -40,7 +55,8 @@ namespace Godot
{
Debug.Assert(nativeCtor != null);
NativePtr = nativeCtor();
// Need postinitialization.
NativePtr = nativeCtor(godot_bool.True);
InteropUtils.TieManagedToUnmanaged(this, NativePtr,
nativeName, refCounted, GetType(), cachedType);
@ -74,8 +90,7 @@ namespace Godot
// NativePtr is assigned, that would result in UB or crashes when calling
// native functions that receive the pointer, which can happen because the
// debugger calls ToString() and tries to get the value of properties.
if (instance._disposed || instance.NativePtr == IntPtr.Zero)
throw new ObjectDisposedException(instance.GetType().FullName);
ObjectDisposedException.ThrowIf(instance._disposed || instance.NativePtr == IntPtr.Zero, instance);
return instance.NativePtr;
}
@ -179,16 +194,56 @@ namespace Godot
return new SignalAwaiter(source, signal, this);
}
internal static bool IsNativeClass(Type t)
{
if (ReferenceEquals(t.Assembly, typeof(GodotObject).Assembly))
{
return true;
}
if (ReflectionUtils.IsEditorHintCached)
{
return t.Assembly.GetName().Name == "GodotSharpEditor";
}
return false;
}
internal static Type InternalGetClassNativeBase(Type t)
{
var name = t.Assembly.GetName().Name;
while (!IsNativeClass(t))
{
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");
if (name == "GodotSharp" || name == "GodotSharpEditor")
return t;
t = t.BaseType;
}
Debug.Assert(t.BaseType is not null, "Script types must derive from a native Godot type.");
return t;
}
return InternalGetClassNativeBase(t.BaseType);
internal static StringName? InternalGetClassNativeBaseName(Type t)
{
if (_nativeNames.TryGetValue(t, out var name))
{
return name;
}
var baseType = InternalGetClassNativeBase(t);
if (_nativeNames.TryGetValue(baseType, out name))
{
return name;
}
var field = baseType.GetField("NativeName",
BindingFlags.DeclaredOnly | BindingFlags.Static |
BindingFlags.Public | BindingFlags.NonPublic);
name = field?.GetValue(null) as StringName;
_nativeNames[baseType] = name;
return name;
}
// ReSharper disable once VirtualMemberNeverOverridden.Global
@ -260,7 +315,7 @@ namespace Godot
return methodBind;
}
internal static unsafe delegate* unmanaged<IntPtr> ClassDB_get_constructor(StringName type)
internal static unsafe delegate* unmanaged<godot_bool, IntPtr> ClassDB_get_constructor(StringName type)
{
// for some reason the '??' operator doesn't support 'delegate*'
var typeSelf = (godot_string_name)type.NativeValue;

View file

@ -88,7 +88,7 @@ namespace Godot
lock (_tasks)
{
if (_tasks.Any())
if (_tasks.Count > 0)
{
task = _tasks.First.Value;
_tasks.RemoveFirst();

View file

@ -109,6 +109,7 @@ namespace Godot.NativeInterop
public ref struct godot_csharp_type_info
{
private godot_string _className;
private godot_string_name _nativeBaseName;
private godot_string _iconPath;
private godot_bool _isTool;
private godot_bool _isGlobalClass;
@ -122,6 +123,12 @@ namespace Godot.NativeInterop
set => _className = value;
}
public godot_string_name NativeBaseName
{
readonly get => _nativeBaseName;
set => _nativeBaseName = value;
}
public godot_string IconPath
{
readonly get => _iconPath;
@ -167,6 +174,7 @@ namespace Godot.NativeInterop
=> (godot_variant*)Unsafe.AsPointer(ref Unsafe.AsRef(in _typeField));
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
// The native enum actually has no fixed underlying type, so it is only at least 6 bits long.
private int _typeField;
// There's padding here
@ -474,8 +482,10 @@ namespace Godot.NativeInterop
Type = Variant.Type.Nil;
}
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
[StructLayout(LayoutKind.Explicit)]
internal struct movable
#pragma warning restore CS8981
{
// Variant.Type is generated as an enum of type long, so we can't use for the field as it must only take 32-bits.
[FieldOffset(0)] private int _typeField;
@ -581,8 +591,10 @@ namespace Godot.NativeInterop
return _data.GetHashCode();
}
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
[StructLayout(LayoutKind.Sequential)]
internal struct movable
#pragma warning restore CS8981
{
private IntPtr _data;
@ -627,8 +639,10 @@ namespace Godot.NativeInterop
get => _data == IntPtr.Zero;
}
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
[StructLayout(LayoutKind.Sequential)]
internal struct movable
#pragma warning restore CS8981
{
private IntPtr _data;
@ -802,8 +816,10 @@ namespace Godot.NativeInterop
_p = null;
}
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
[StructLayout(LayoutKind.Sequential)]
internal struct movable
#pragma warning restore CS8981
{
private unsafe ArrayPrivate* _p;
@ -869,8 +885,10 @@ namespace Godot.NativeInterop
_p = null;
}
#pragma warning disable CS8981 // The type name only contains lower-cased ascii characters
[StructLayout(LayoutKind.Sequential)]
internal struct movable
#pragma warning restore CS8981
{
private unsafe DictionaryPrivate* _p;

View file

@ -199,6 +199,44 @@ namespace Godot.NativeInterop
return Variant.Type.Nil;
}
internal static void GetTypedCollectionParameterInfo<T>(
out Variant.Type variantType,
out godot_string_name className,
out godot_ref script)
{
variantType = ConvertManagedTypeToVariantType(typeof(T), out _);
if (variantType != Variant.Type.Object)
{
className = default;
script = default;
return;
}
godot_ref scriptRef = default;
if (!GodotObject.IsNativeClass(typeof(T)))
{
unsafe
{
Godot.Bridge.ScriptManagerBridge.GetOrLoadOrCreateScriptForType(typeof(T), &scriptRef);
}
// Don't call GodotObject.InternalGetClassNativeBaseName here!
// godot_dictionary_set_typed and godot_array_set_typed will call CSharpScript::get_instance_base_type
// when a script is passed, because this is better for performance than using reflection to find the
// native base type.
className = default;
}
else
{
StringName? nativeBaseName = GodotObject.InternalGetClassNativeBaseName(typeof(T));
className = nativeBaseName != null ? (godot_string_name)nativeBaseName.NativeValue : default;
}
script = scriptRef;
}
// String
public static unsafe godot_string ConvertStringToNative(string? p_mono_string)
@ -230,7 +268,7 @@ namespace Godot.NativeInterop
// Callable
public static godot_callable ConvertCallableToNative(in Callable p_managed_callable)
public static godot_callable ConvertCallableToNative(scoped in Callable p_managed_callable)
{
if (p_managed_callable.Delegate != null)
{
@ -295,7 +333,7 @@ namespace Godot.NativeInterop
// Signal
public static godot_signal ConvertSignalToNative(in Signal p_managed_signal)
public static godot_signal ConvertSignalToNative(scoped in Signal p_managed_signal)
{
ulong ownerId = p_managed_signal.Owner.GetInstanceId();
godot_string_name name;
@ -394,7 +432,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(Span<byte> p_array)
public static godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(scoped Span<byte> p_array)
{
return ConvertSystemArrayToNativePackedByteArray((ReadOnlySpan<byte>)p_array);
}
public static unsafe godot_packed_byte_array ConvertSystemArrayToNativePackedByteArray(scoped ReadOnlySpan<byte> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_byte_array();
@ -417,7 +460,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(Span<int> p_array)
public static godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(scoped Span<int> p_array)
{
return ConvertSystemArrayToNativePackedInt32Array((ReadOnlySpan<int>)p_array);
}
public static unsafe godot_packed_int32_array ConvertSystemArrayToNativePackedInt32Array(scoped ReadOnlySpan<int> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int32_array();
@ -440,7 +488,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(Span<long> p_array)
public static godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(scoped Span<long> p_array)
{
return ConvertSystemArrayToNativePackedInt64Array((ReadOnlySpan<long>)p_array);
}
public static unsafe godot_packed_int64_array ConvertSystemArrayToNativePackedInt64Array(scoped ReadOnlySpan<long> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_int64_array();
@ -463,8 +516,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(
Span<float> p_array)
public static godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(scoped Span<float> p_array)
{
return ConvertSystemArrayToNativePackedFloat32Array((ReadOnlySpan<float>)p_array);
}
public static unsafe godot_packed_float32_array ConvertSystemArrayToNativePackedFloat32Array(scoped ReadOnlySpan<float> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float32_array();
@ -487,8 +544,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(
Span<double> p_array)
public static godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(scoped Span<double> p_array)
{
return ConvertSystemArrayToNativePackedFloat64Array((ReadOnlySpan<double>)p_array);
}
public static unsafe godot_packed_float64_array ConvertSystemArrayToNativePackedFloat64Array(scoped ReadOnlySpan<double> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_float64_array();
@ -510,7 +571,12 @@ namespace Godot.NativeInterop
return array;
}
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(Span<string> p_array)
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(scoped Span<string> p_array)
{
return ConvertSystemArrayToNativePackedStringArray((ReadOnlySpan<string>)p_array);
}
public static godot_packed_string_array ConvertSystemArrayToNativePackedStringArray(scoped ReadOnlySpan<string> p_array)
{
godot_packed_string_array dest = new godot_packed_string_array();
@ -544,8 +610,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(
Span<Vector2> p_array)
public static godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(scoped Span<Vector2> p_array)
{
return ConvertSystemArrayToNativePackedVector2Array((ReadOnlySpan<Vector2>)p_array);
}
public static unsafe godot_packed_vector2_array ConvertSystemArrayToNativePackedVector2Array(scoped ReadOnlySpan<Vector2> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector2_array();
@ -568,8 +638,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(
Span<Vector3> p_array)
public static godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(scoped Span<Vector3> p_array)
{
return ConvertSystemArrayToNativePackedVector3Array((ReadOnlySpan<Vector3>)p_array);
}
public static unsafe godot_packed_vector3_array ConvertSystemArrayToNativePackedVector3Array(scoped ReadOnlySpan<Vector3> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector3_array();
@ -592,8 +666,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(
Span<Vector4> p_array)
public static godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(scoped Span<Vector4> p_array)
{
return ConvertSystemArrayToNativePackedVector4Array((ReadOnlySpan<Vector4>)p_array);
}
public static unsafe godot_packed_vector4_array ConvertSystemArrayToNativePackedVector4Array(scoped ReadOnlySpan<Vector4> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_vector4_array();
@ -616,7 +694,12 @@ namespace Godot.NativeInterop
return array;
}
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(Span<Color> p_array)
public static godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(scoped Span<Color> p_array)
{
return ConvertSystemArrayToNativePackedColorArray((ReadOnlySpan<Color>)p_array);
}
public static unsafe godot_packed_color_array ConvertSystemArrayToNativePackedColorArray(scoped ReadOnlySpan<Color> p_array)
{
if (p_array.IsEmpty)
return new godot_packed_color_array();

View file

@ -47,7 +47,7 @@ namespace Godot.NativeInterop
public static partial IntPtr godotsharp_method_bind_get_method_with_compatibility(
in godot_string_name p_classname, in godot_string_name p_methodname, ulong p_hash);
public static partial delegate* unmanaged<IntPtr> godotsharp_get_class_constructor(
public static partial delegate* unmanaged<godot_bool, IntPtr> godotsharp_get_class_constructor(
in godot_string_name p_classname);
public static partial IntPtr godotsharp_engine_get_singleton(in godot_string p_name);
@ -101,10 +101,10 @@ namespace Godot.NativeInterop
internal static partial void godotsharp_internal_reload_registered_script(IntPtr scriptPtr);
internal static partial void godotsharp_array_filter_godot_objects_by_native(in godot_string_name p_native_name,
in godot_array p_input, out godot_array r_output);
internal static partial void godotsharp_array_filter_godot_objects_by_native(scoped in godot_string_name p_native_name,
scoped in godot_array p_input, out godot_array r_output);
internal static partial void godotsharp_array_filter_godot_objects_by_non_native(in godot_array p_input,
internal static partial void godotsharp_array_filter_godot_objects_by_non_native(scoped in godot_array p_input,
out godot_array r_output);
public static partial void godotsharp_ref_new_from_ref_counted_ptr(out godot_ref r_dest,
@ -113,15 +113,15 @@ namespace Godot.NativeInterop
public static partial void godotsharp_ref_destroy(ref godot_ref p_instance);
public static partial void godotsharp_string_name_new_from_string(out godot_string_name r_dest,
in godot_string p_name);
scoped in godot_string p_name);
public static partial void godotsharp_node_path_new_from_string(out godot_node_path r_dest,
in godot_string p_name);
scoped in godot_string p_name);
public static partial void
godotsharp_string_name_as_string(out godot_string r_dest, in godot_string_name p_name);
godotsharp_string_name_as_string(out godot_string r_dest, scoped in godot_string_name p_name);
public static partial void godotsharp_node_path_as_string(out godot_string r_dest, in godot_node_path p_np);
public static partial void godotsharp_node_path_as_string(out godot_string r_dest, scoped in godot_node_path p_np);
public static partial godot_packed_byte_array godotsharp_packed_byte_array_new_mem_copy(byte* p_src,
int p_length);
@ -156,10 +156,10 @@ namespace Godot.NativeInterop
public static partial void godotsharp_callable_new_with_delegate(IntPtr p_delegate_handle, IntPtr p_trampoline,
IntPtr p_object, out godot_callable r_callable);
internal static partial godot_bool godotsharp_callable_get_data_for_marshalling(in godot_callable p_callable,
internal static partial godot_bool godotsharp_callable_get_data_for_marshalling(scoped in godot_callable p_callable,
out IntPtr r_delegate_handle, out IntPtr r_trampoline, out IntPtr r_object, out godot_string_name r_name);
internal static partial godot_variant godotsharp_callable_call(in godot_callable p_callable,
internal static partial godot_variant godotsharp_callable_call(scoped in godot_callable p_callable,
godot_variant** p_args, int p_arg_count, out godot_variant_call_error p_call_error);
internal static partial void godotsharp_callable_call_deferred(in godot_callable p_callable,
@ -167,6 +167,12 @@ namespace Godot.NativeInterop
internal static partial Color godotsharp_color_from_ok_hsl(float p_h, float p_s, float p_l, float p_alpha);
internal static partial float godotsharp_color_get_ok_hsl_h(in Color p_self);
internal static partial float godotsharp_color_get_ok_hsl_s(in Color p_self);
internal static partial float godotsharp_color_get_ok_hsl_l(in Color p_self);
// GDNative functions
// gdnative.h
@ -180,140 +186,135 @@ namespace Godot.NativeInterop
// variant.h
public static partial void
godotsharp_variant_new_string_name(out godot_variant r_dest, in godot_string_name p_s);
godotsharp_variant_new_string_name(out godot_variant r_dest, scoped in godot_string_name p_s);
public static partial void godotsharp_variant_new_copy(out godot_variant r_dest, in godot_variant p_src);
public static partial void godotsharp_variant_new_copy(out godot_variant r_dest, scoped in godot_variant p_src);
public static partial void godotsharp_variant_new_node_path(out godot_variant r_dest, in godot_node_path p_np);
public static partial void godotsharp_variant_new_node_path(out godot_variant r_dest, scoped in godot_node_path p_np);
public static partial void godotsharp_variant_new_object(out godot_variant r_dest, IntPtr p_obj);
public static partial void godotsharp_variant_new_transform2d(out godot_variant r_dest, in Transform2D p_t2d);
public static partial void godotsharp_variant_new_transform2d(out godot_variant r_dest, scoped in Transform2D p_t2d);
public static partial void godotsharp_variant_new_basis(out godot_variant r_dest, in Basis p_basis);
public static partial void godotsharp_variant_new_basis(out godot_variant r_dest, scoped in Basis p_basis);
public static partial void godotsharp_variant_new_transform3d(out godot_variant r_dest, in Transform3D p_trans);
public static partial void godotsharp_variant_new_transform3d(out godot_variant r_dest, scoped in Transform3D p_trans);
public static partial void godotsharp_variant_new_projection(out godot_variant r_dest, in Projection p_proj);
public static partial void godotsharp_variant_new_projection(out godot_variant r_dest, scoped in Projection p_proj);
public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, in Aabb p_aabb);
public static partial void godotsharp_variant_new_aabb(out godot_variant r_dest, scoped in Aabb p_aabb);
public static partial void godotsharp_variant_new_dictionary(out godot_variant r_dest,
in godot_dictionary p_dict);
scoped in godot_dictionary p_dict);
public static partial void godotsharp_variant_new_array(out godot_variant r_dest, in godot_array p_arr);
public static partial void godotsharp_variant_new_array(out godot_variant r_dest, scoped in godot_array p_arr);
public static partial void godotsharp_variant_new_packed_byte_array(out godot_variant r_dest,
in godot_packed_byte_array p_pba);
scoped in godot_packed_byte_array p_pba);
public static partial void godotsharp_variant_new_packed_int32_array(out godot_variant r_dest,
in godot_packed_int32_array p_pia);
scoped in godot_packed_int32_array p_pia);
public static partial void godotsharp_variant_new_packed_int64_array(out godot_variant r_dest,
in godot_packed_int64_array p_pia);
scoped in godot_packed_int64_array p_pia);
public static partial void godotsharp_variant_new_packed_float32_array(out godot_variant r_dest,
in godot_packed_float32_array p_pra);
scoped in godot_packed_float32_array p_pra);
public static partial void godotsharp_variant_new_packed_float64_array(out godot_variant r_dest,
in godot_packed_float64_array p_pra);
scoped in godot_packed_float64_array p_pra);
public static partial void godotsharp_variant_new_packed_string_array(out godot_variant r_dest,
in godot_packed_string_array p_psa);
scoped in godot_packed_string_array p_psa);
public static partial void godotsharp_variant_new_packed_vector2_array(out godot_variant r_dest,
in godot_packed_vector2_array p_pv2a);
scoped in godot_packed_vector2_array p_pv2a);
public static partial void godotsharp_variant_new_packed_vector3_array(out godot_variant r_dest,
in godot_packed_vector3_array p_pv3a);
scoped in godot_packed_vector3_array p_pv3a);
public static partial void godotsharp_variant_new_packed_vector4_array(out godot_variant r_dest,
in godot_packed_vector4_array p_pv4a);
scoped in godot_packed_vector4_array p_pv4a);
public static partial void godotsharp_variant_new_packed_color_array(out godot_variant r_dest,
in godot_packed_color_array p_pca);
scoped in godot_packed_color_array p_pca);
public static partial godot_bool godotsharp_variant_as_bool(in godot_variant p_self);
public static partial godot_bool godotsharp_variant_as_bool(scoped in godot_variant p_self);
public static partial Int64 godotsharp_variant_as_int(in godot_variant p_self);
public static partial Int64 godotsharp_variant_as_int(scoped in godot_variant p_self);
public static partial double godotsharp_variant_as_float(in godot_variant p_self);
public static partial double godotsharp_variant_as_float(scoped in godot_variant p_self);
public static partial godot_string godotsharp_variant_as_string(in godot_variant p_self);
public static partial godot_string godotsharp_variant_as_string(scoped in godot_variant p_self);
public static partial Vector2 godotsharp_variant_as_vector2(in godot_variant p_self);
public static partial Vector2 godotsharp_variant_as_vector2(scoped in godot_variant p_self);
public static partial Vector2I godotsharp_variant_as_vector2i(in godot_variant p_self);
public static partial Vector2I godotsharp_variant_as_vector2i(scoped in godot_variant p_self);
public static partial Rect2 godotsharp_variant_as_rect2(in godot_variant p_self);
public static partial Rect2 godotsharp_variant_as_rect2(scoped in godot_variant p_self);
public static partial Rect2I godotsharp_variant_as_rect2i(in godot_variant p_self);
public static partial Rect2I godotsharp_variant_as_rect2i(scoped in godot_variant p_self);
public static partial Vector3 godotsharp_variant_as_vector3(in godot_variant p_self);
public static partial Vector3 godotsharp_variant_as_vector3(scoped in godot_variant p_self);
public static partial Vector3I godotsharp_variant_as_vector3i(in godot_variant p_self);
public static partial Vector3I godotsharp_variant_as_vector3i(scoped in godot_variant p_self);
public static partial Transform2D godotsharp_variant_as_transform2d(in godot_variant p_self);
public static partial Transform2D godotsharp_variant_as_transform2d(scoped in godot_variant p_self);
public static partial Vector4 godotsharp_variant_as_vector4(in godot_variant p_self);
public static partial Vector4 godotsharp_variant_as_vector4(scoped in godot_variant p_self);
public static partial Vector4I godotsharp_variant_as_vector4i(in godot_variant p_self);
public static partial Vector4I godotsharp_variant_as_vector4i(scoped in godot_variant p_self);
public static partial Plane godotsharp_variant_as_plane(in godot_variant p_self);
public static partial Plane godotsharp_variant_as_plane(scoped in godot_variant p_self);
public static partial Quaternion godotsharp_variant_as_quaternion(in godot_variant p_self);
public static partial Quaternion godotsharp_variant_as_quaternion(scoped in godot_variant p_self);
public static partial Aabb godotsharp_variant_as_aabb(in godot_variant p_self);
public static partial Aabb godotsharp_variant_as_aabb(scoped in godot_variant p_self);
public static partial Basis godotsharp_variant_as_basis(in godot_variant p_self);
public static partial Basis godotsharp_variant_as_basis(scoped in godot_variant p_self);
public static partial Transform3D godotsharp_variant_as_transform3d(in godot_variant p_self);
public static partial Transform3D godotsharp_variant_as_transform3d(scoped in godot_variant p_self);
public static partial Projection godotsharp_variant_as_projection(in godot_variant p_self);
public static partial Projection godotsharp_variant_as_projection(scoped in godot_variant p_self);
public static partial Color godotsharp_variant_as_color(in godot_variant p_self);
public static partial Color godotsharp_variant_as_color(scoped in godot_variant p_self);
public static partial godot_string_name godotsharp_variant_as_string_name(in godot_variant p_self);
public static partial godot_string_name godotsharp_variant_as_string_name(scoped in godot_variant p_self);
public static partial godot_node_path godotsharp_variant_as_node_path(in godot_variant p_self);
public static partial godot_node_path godotsharp_variant_as_node_path(scoped in godot_variant p_self);
public static partial Rid godotsharp_variant_as_rid(in godot_variant p_self);
public static partial Rid godotsharp_variant_as_rid(scoped in godot_variant p_self);
public static partial godot_callable godotsharp_variant_as_callable(in godot_variant p_self);
public static partial godot_callable godotsharp_variant_as_callable(scoped in godot_variant p_self);
public static partial godot_signal godotsharp_variant_as_signal(in godot_variant p_self);
public static partial godot_signal godotsharp_variant_as_signal(scoped in godot_variant p_self);
public static partial godot_dictionary godotsharp_variant_as_dictionary(in godot_variant p_self);
public static partial godot_dictionary godotsharp_variant_as_dictionary(scoped in godot_variant p_self);
public static partial godot_array godotsharp_variant_as_array(in godot_variant p_self);
public static partial godot_array godotsharp_variant_as_array(scoped in godot_variant p_self);
public static partial godot_packed_byte_array godotsharp_variant_as_packed_byte_array(in godot_variant p_self);
public static partial godot_packed_byte_array godotsharp_variant_as_packed_byte_array(scoped in godot_variant p_self);
public static partial godot_packed_int32_array godotsharp_variant_as_packed_int32_array(in godot_variant p_self);
public static partial godot_packed_int32_array godotsharp_variant_as_packed_int32_array(scoped in godot_variant p_self);
public static partial godot_packed_int64_array godotsharp_variant_as_packed_int64_array(in godot_variant p_self);
public static partial godot_packed_int64_array godotsharp_variant_as_packed_int64_array(scoped in godot_variant p_self);
public static partial godot_packed_float32_array godotsharp_variant_as_packed_float32_array(
in godot_variant p_self);
public static partial godot_packed_float32_array godotsharp_variant_as_packed_float32_array(scoped in godot_variant p_self);
public static partial godot_packed_float64_array godotsharp_variant_as_packed_float64_array(
in godot_variant p_self);
public static partial godot_packed_float64_array godotsharp_variant_as_packed_float64_array(scoped in godot_variant p_self);
public static partial godot_packed_string_array godotsharp_variant_as_packed_string_array(
in godot_variant p_self);
public static partial godot_packed_string_array godotsharp_variant_as_packed_string_array(scoped in godot_variant p_self);
public static partial godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(
in godot_variant p_self);
public static partial godot_packed_vector2_array godotsharp_variant_as_packed_vector2_array(scoped in godot_variant p_self);
public static partial godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(
in godot_variant p_self);
public static partial godot_packed_vector3_array godotsharp_variant_as_packed_vector3_array(scoped in godot_variant p_self);
public static partial godot_packed_vector4_array godotsharp_variant_as_packed_vector4_array(
in godot_variant p_self);
public static partial godot_packed_color_array godotsharp_variant_as_packed_color_array(in godot_variant p_self);
public static partial godot_packed_color_array godotsharp_variant_as_packed_color_array(scoped in godot_variant p_self);
public static partial godot_bool godotsharp_variant_equals(in godot_variant p_a, in godot_variant p_b);
public static partial godot_bool godotsharp_variant_equals(scoped in godot_variant p_a, scoped in godot_variant p_b);
// string.h
@ -322,17 +323,17 @@ namespace Godot.NativeInterop
// string_name.h
public static partial void godotsharp_string_name_new_copy(out godot_string_name r_dest,
in godot_string_name p_src);
scoped in godot_string_name p_src);
// node_path.h
public static partial void godotsharp_node_path_new_copy(out godot_node_path r_dest, in godot_node_path p_src);
public static partial void godotsharp_node_path_new_copy(out godot_node_path r_dest, scoped in godot_node_path p_src);
// array.h
public static partial void godotsharp_array_new(out godot_array r_dest);
public static partial void godotsharp_array_new_copy(out godot_array r_dest, in godot_array p_src);
public static partial void godotsharp_array_new_copy(out godot_array r_dest, scoped in godot_array p_src);
public static partial godot_variant* godotsharp_array_ptrw(ref godot_array p_self);
@ -341,7 +342,7 @@ namespace Godot.NativeInterop
public static partial void godotsharp_dictionary_new(out godot_dictionary r_dest);
public static partial void godotsharp_dictionary_new_copy(out godot_dictionary r_dest,
in godot_dictionary p_src);
scoped in godot_dictionary p_src);
// destroy functions
@ -389,8 +390,7 @@ namespace Godot.NativeInterop
public static partial int godotsharp_array_binary_search(ref godot_array p_self, int p_index, int p_count, in godot_variant p_value);
public static partial void
godotsharp_array_duplicate(ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
public static partial void godotsharp_array_duplicate(scoped ref godot_array p_self, godot_bool p_deep, out godot_array r_dest);
public static partial void godotsharp_array_fill(ref godot_array p_self, in godot_variant p_value);
@ -402,11 +402,19 @@ namespace Godot.NativeInterop
public static partial void godotsharp_array_make_read_only(ref godot_array p_self);
public static partial void godotsharp_array_max(ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_set_typed(
ref godot_array p_self,
uint p_elem_type,
in godot_string_name p_elem_class_name,
in godot_ref p_elem_script);
public static partial void godotsharp_array_min(ref godot_array p_self, out godot_variant r_value);
public static partial godot_bool godotsharp_array_is_typed(ref godot_array p_self);
public static partial void godotsharp_array_pick_random(ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_max(scoped ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_min(scoped ref godot_array p_self, out godot_variant r_value);
public static partial void godotsharp_array_pick_random(scoped ref godot_array p_self, out godot_variant r_value);
public static partial godot_bool godotsharp_array_recursive_equal(ref godot_array p_self, in godot_array p_other);
@ -418,7 +426,7 @@ namespace Godot.NativeInterop
public static partial void godotsharp_array_shuffle(ref godot_array p_self);
public static partial void godotsharp_array_slice(ref godot_array p_self, int p_start, int p_end,
public static partial void godotsharp_array_slice(scoped ref godot_array p_self, int p_start, int p_end,
int p_step, godot_bool p_deep, out godot_array r_dest);
public static partial void godotsharp_array_sort(ref godot_array p_self);
@ -427,20 +435,20 @@ namespace Godot.NativeInterop
// Dictionary
public static partial godot_bool godotsharp_dictionary_try_get_value(ref godot_dictionary p_self,
in godot_variant p_key,
public static partial godot_bool godotsharp_dictionary_try_get_value(scoped ref godot_dictionary p_self,
scoped in godot_variant p_key,
out godot_variant r_value);
public static partial void godotsharp_dictionary_set_value(ref godot_dictionary p_self, in godot_variant p_key,
in godot_variant p_value);
public static partial void godotsharp_dictionary_keys(ref godot_dictionary p_self, out godot_array r_dest);
public static partial void godotsharp_dictionary_keys(scoped ref godot_dictionary p_self, out godot_array r_dest);
public static partial void godotsharp_dictionary_values(ref godot_dictionary p_self, out godot_array r_dest);
public static partial void godotsharp_dictionary_values(scoped ref godot_dictionary p_self, out godot_array r_dest);
public static partial int godotsharp_dictionary_count(ref godot_dictionary p_self);
public static partial void godotsharp_dictionary_key_value_pair_at(ref godot_dictionary p_self, int p_index,
public static partial void godotsharp_dictionary_key_value_pair_at(scoped ref godot_dictionary p_self, int p_index,
out godot_variant r_key, out godot_variant r_value);
public static partial void godotsharp_dictionary_add(ref godot_dictionary p_self, in godot_variant p_key,
@ -451,7 +459,7 @@ namespace Godot.NativeInterop
public static partial godot_bool godotsharp_dictionary_contains_key(ref godot_dictionary p_self,
in godot_variant p_key);
public static partial void godotsharp_dictionary_duplicate(ref godot_dictionary p_self, godot_bool p_deep,
public static partial void godotsharp_dictionary_duplicate(scoped ref godot_dictionary p_self, godot_bool p_deep,
out godot_dictionary r_dest);
public static partial void godotsharp_dictionary_merge(ref godot_dictionary p_self, in godot_dictionary p_dictionary, godot_bool p_overwrite);
@ -463,20 +471,45 @@ namespace Godot.NativeInterop
public static partial void godotsharp_dictionary_make_read_only(ref godot_dictionary p_self);
public static partial void godotsharp_dictionary_to_string(ref godot_dictionary p_self, out godot_string r_str);
public static partial void godotsharp_dictionary_set_typed(
ref godot_dictionary p_self,
uint p_key_type,
in godot_string_name p_key_class_name,
in godot_ref p_key_script,
uint p_value_type,
in godot_string_name p_value_class_name,
in godot_ref p_value_script);
public static partial godot_bool godotsharp_dictionary_is_typed_key(ref godot_dictionary p_self);
public static partial godot_bool godotsharp_dictionary_is_typed_value(ref godot_dictionary p_self);
public static partial uint godotsharp_dictionary_get_typed_key_builtin(ref godot_dictionary p_self);
public static partial uint godotsharp_dictionary_get_typed_value_builtin(ref godot_dictionary p_self);
public static partial void godotsharp_dictionary_get_typed_key_class_name(ref godot_dictionary p_self, out godot_string_name r_dest);
public static partial void godotsharp_dictionary_get_typed_value_class_name(ref godot_dictionary p_self, out godot_string_name r_dest);
public static partial void godotsharp_dictionary_get_typed_key_script(ref godot_dictionary p_self, out godot_variant r_dest);
public static partial void godotsharp_dictionary_get_typed_value_script(ref godot_dictionary p_self, out godot_variant r_dest);
public static partial void godotsharp_dictionary_to_string(scoped ref godot_dictionary p_self, out godot_string r_str);
// StringExtensions
public static partial void godotsharp_string_simplify_path(in godot_string p_self,
public static partial void godotsharp_string_simplify_path(scoped in godot_string p_self,
out godot_string r_simplified_path);
public static partial void godotsharp_string_to_camel_case(in godot_string p_self,
public static partial void godotsharp_string_to_camel_case(scoped in godot_string p_self,
out godot_string r_camel_case);
public static partial void godotsharp_string_to_pascal_case(in godot_string p_self,
public static partial void godotsharp_string_to_pascal_case(scoped in godot_string p_self,
out godot_string r_pascal_case);
public static partial void godotsharp_string_to_snake_case(in godot_string p_self,
public static partial void godotsharp_string_to_snake_case(scoped in godot_string p_self,
out godot_string r_snake_case);
// NodePath
@ -484,18 +517,18 @@ namespace Godot.NativeInterop
public static partial void godotsharp_node_path_get_as_property_path(in godot_node_path p_self,
ref godot_node_path r_dest);
public static partial void godotsharp_node_path_get_concatenated_names(in godot_node_path p_self,
public static partial void godotsharp_node_path_get_concatenated_names(scoped in godot_node_path p_self,
out godot_string r_names);
public static partial void godotsharp_node_path_get_concatenated_subnames(in godot_node_path p_self,
public static partial void godotsharp_node_path_get_concatenated_subnames(scoped in godot_node_path p_self,
out godot_string r_subnames);
public static partial void godotsharp_node_path_get_name(in godot_node_path p_self, int p_idx,
public static partial void godotsharp_node_path_get_name(scoped in godot_node_path p_self, int p_idx,
out godot_string r_name);
public static partial int godotsharp_node_path_get_name_count(in godot_node_path p_self);
public static partial void godotsharp_node_path_get_subname(in godot_node_path p_self, int p_idx,
public static partial void godotsharp_node_path_get_subname(scoped in godot_node_path p_self, int p_idx,
out godot_string r_subname);
public static partial int godotsharp_node_path_get_subname_count(in godot_node_path p_self);
@ -508,11 +541,11 @@ namespace Godot.NativeInterop
// GD, etc
internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes,
internal static partial void godotsharp_bytes_to_var(scoped in godot_packed_byte_array p_bytes,
godot_bool p_allow_objects,
out godot_variant r_ret);
internal static partial void godotsharp_convert(in godot_variant p_what, int p_type,
internal static partial void godotsharp_convert(scoped in godot_variant p_what, int p_type,
out godot_variant r_ret);
internal static partial int godotsharp_hash(in godot_variant p_var);
@ -549,12 +582,12 @@ namespace Godot.NativeInterop
internal static partial void godotsharp_weakref(IntPtr p_obj, out godot_ref r_weak_ref);
internal static partial void godotsharp_str_to_var(in godot_string p_str, out godot_variant r_ret);
internal static partial void godotsharp_str_to_var(scoped in godot_string p_str, out godot_variant r_ret);
internal static partial void godotsharp_var_to_bytes(in godot_variant p_what, godot_bool p_full_objects,
internal static partial void godotsharp_var_to_bytes(scoped in godot_variant p_what, godot_bool p_full_objects,
out godot_packed_byte_array r_bytes);
internal static partial void godotsharp_var_to_str(in godot_variant p_var, out godot_string r_ret);
internal static partial void godotsharp_var_to_str(scoped in godot_variant p_var, out godot_string r_ret);
internal static partial void godotsharp_err_print_error(in godot_string p_function, in godot_string p_file, int p_line, in godot_string p_error, in godot_string p_message = default, godot_bool p_editor_notify = godot_bool.False, godot_error_handler_type p_type = godot_error_handler_type.ERR_HANDLER_ERROR);

View file

@ -6,7 +6,7 @@ namespace Godot.NativeInterop
{
public static partial class NativeFuncs
{
public static godot_variant godotsharp_variant_new_copy(in godot_variant src)
public static godot_variant godotsharp_variant_new_copy(scoped in godot_variant src)
{
switch (src.Type)
{
@ -48,7 +48,7 @@ namespace Godot.NativeInterop
return ret;
}
public static godot_string_name godotsharp_string_name_new_copy(in godot_string_name src)
public static godot_string_name godotsharp_string_name_new_copy(scoped in godot_string_name src)
{
if (src.IsEmpty)
return default;
@ -56,7 +56,7 @@ namespace Godot.NativeInterop
return ret;
}
public static godot_node_path godotsharp_node_path_new_copy(in godot_node_path src)
public static godot_node_path godotsharp_node_path_new_copy(scoped in godot_node_path src)
{
if (src.IsEmpty)
return default;
@ -70,7 +70,7 @@ namespace Godot.NativeInterop
return ret;
}
public static godot_array godotsharp_array_new_copy(in godot_array src)
public static godot_array godotsharp_array_new_copy(scoped in godot_array src)
{
godotsharp_array_new_copy(out godot_array ret, src);
return ret;
@ -82,7 +82,7 @@ namespace Godot.NativeInterop
return ret;
}
public static godot_dictionary godotsharp_dictionary_new_copy(in godot_dictionary src)
public static godot_dictionary godotsharp_dictionary_new_copy(scoped in godot_dictionary src)
{
godotsharp_dictionary_new_copy(out godot_dictionary ret, src);
return ret;

View file

@ -117,137 +117,137 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromString(string? from)
=> CreateFromStringTakingOwnershipOfDisposableValue(Marshaling.ConvertStringToNative(from));
public static godot_variant CreateFromPackedByteArray(in godot_packed_byte_array from)
public static godot_variant CreateFromPackedByteArray(scoped in godot_packed_byte_array from)
{
NativeFuncs.godotsharp_variant_new_packed_byte_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedInt32Array(in godot_packed_int32_array from)
public static godot_variant CreateFromPackedInt32Array(scoped in godot_packed_int32_array from)
{
NativeFuncs.godotsharp_variant_new_packed_int32_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedInt64Array(in godot_packed_int64_array from)
public static godot_variant CreateFromPackedInt64Array(scoped in godot_packed_int64_array from)
{
NativeFuncs.godotsharp_variant_new_packed_int64_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedFloat32Array(in godot_packed_float32_array from)
public static godot_variant CreateFromPackedFloat32Array(scoped in godot_packed_float32_array from)
{
NativeFuncs.godotsharp_variant_new_packed_float32_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedFloat64Array(in godot_packed_float64_array from)
public static godot_variant CreateFromPackedFloat64Array(scoped in godot_packed_float64_array from)
{
NativeFuncs.godotsharp_variant_new_packed_float64_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedStringArray(in godot_packed_string_array from)
public static godot_variant CreateFromPackedStringArray(scoped in godot_packed_string_array from)
{
NativeFuncs.godotsharp_variant_new_packed_string_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedVector2Array(in godot_packed_vector2_array from)
public static godot_variant CreateFromPackedVector2Array(scoped in godot_packed_vector2_array from)
{
NativeFuncs.godotsharp_variant_new_packed_vector2_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedVector3Array(in godot_packed_vector3_array from)
public static godot_variant CreateFromPackedVector3Array(scoped in godot_packed_vector3_array from)
{
NativeFuncs.godotsharp_variant_new_packed_vector3_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedVector4Array(in godot_packed_vector4_array from)
public static godot_variant CreateFromPackedVector4Array(scoped in godot_packed_vector4_array from)
{
NativeFuncs.godotsharp_variant_new_packed_vector4_array(out godot_variant ret, from);
return ret;
}
public static godot_variant CreateFromPackedColorArray(in godot_packed_color_array from)
public static godot_variant CreateFromPackedColorArray(scoped in godot_packed_color_array from)
{
NativeFuncs.godotsharp_variant_new_packed_color_array(out godot_variant ret, from);
return ret;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedByteArray(Span<byte> from)
public static godot_variant CreateFromPackedByteArray(scoped Span<byte> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedByteArray(from);
return CreateFromPackedByteArray(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt32Array(Span<int> from)
public static godot_variant CreateFromPackedInt32Array(scoped Span<int> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt32Array(from);
return CreateFromPackedInt32Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedInt64Array(Span<long> from)
public static godot_variant CreateFromPackedInt64Array(scoped Span<long> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedInt64Array(from);
return CreateFromPackedInt64Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat32Array(Span<float> from)
public static godot_variant CreateFromPackedFloat32Array(scoped Span<float> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat32Array(from);
return CreateFromPackedFloat32Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedFloat64Array(Span<double> from)
public static godot_variant CreateFromPackedFloat64Array(scoped Span<double> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedFloat64Array(from);
return CreateFromPackedFloat64Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedStringArray(Span<string> from)
public static godot_variant CreateFromPackedStringArray(scoped Span<string> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedStringArray(from);
return CreateFromPackedStringArray(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector2Array(Span<Vector2> from)
public static godot_variant CreateFromPackedVector2Array(scoped Span<Vector2> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector2Array(from);
return CreateFromPackedVector2Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector3Array(Span<Vector3> from)
public static godot_variant CreateFromPackedVector3Array(scoped Span<Vector3> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector3Array(from);
return CreateFromPackedVector3Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedVector4Array(Span<Vector4> from)
public static godot_variant CreateFromPackedVector4Array(scoped Span<Vector4> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedVector4Array(from);
return CreateFromPackedVector4Array(nativePackedArray);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_variant CreateFromPackedColorArray(Span<Color> from)
public static godot_variant CreateFromPackedColorArray(scoped Span<Color> from)
{
using var nativePackedArray = Marshaling.ConvertSystemArrayToNativePackedColorArray(from);
return CreateFromPackedColorArray(nativePackedArray);
}
public static godot_variant CreateFromSystemArrayOfStringName(Span<StringName> from)
public static godot_variant CreateFromSystemArrayOfStringName(scoped Span<StringName> from)
{
if (from == null)
return default;
@ -255,7 +255,7 @@ namespace Godot.NativeInterop
return CreateFromArray((godot_array)fromGodot.NativeValue);
}
public static godot_variant CreateFromSystemArrayOfNodePath(Span<NodePath> from)
public static godot_variant CreateFromSystemArrayOfNodePath(scoped Span<NodePath> from)
{
if (from == null)
return default;
@ -263,7 +263,7 @@ namespace Godot.NativeInterop
return CreateFromArray((godot_array)fromGodot.NativeValue);
}
public static godot_variant CreateFromSystemArrayOfRid(Span<Rid> from)
public static godot_variant CreateFromSystemArrayOfRid(scoped Span<Rid> from)
{
if (from == null)
return default;
@ -279,7 +279,7 @@ namespace Godot.NativeInterop
return CreateFromArray((godot_array)fromGodot.NativeValue);
}
public static godot_variant CreateFromArray(godot_array from)
public static godot_variant CreateFromArray(scoped in godot_array from)
{
NativeFuncs.godotsharp_variant_new_array(out godot_variant ret, from);
return ret;
@ -293,7 +293,7 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromArray<[MustBeVariant] T>(Array<T>? from)
=> from != null ? CreateFromArray((godot_array)((Collections.Array)from).NativeValue) : default;
public static godot_variant CreateFromDictionary(godot_dictionary from)
public static godot_variant CreateFromDictionary(scoped in godot_dictionary from)
{
NativeFuncs.godotsharp_variant_new_dictionary(out godot_variant ret, from);
return ret;
@ -307,7 +307,7 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromDictionary<[MustBeVariant] TKey, [MustBeVariant] TValue>(Dictionary<TKey, TValue>? from)
=> from != null ? CreateFromDictionary((godot_dictionary)((Dictionary)from).NativeValue) : default;
public static godot_variant CreateFromStringName(godot_string_name from)
public static godot_variant CreateFromStringName(scoped in godot_string_name from)
{
NativeFuncs.godotsharp_variant_new_string_name(out godot_variant ret, from);
return ret;
@ -317,7 +317,7 @@ namespace Godot.NativeInterop
public static godot_variant CreateFromStringName(StringName? from)
=> from != null ? CreateFromStringName((godot_string_name)from.NativeValue) : default;
public static godot_variant CreateFromNodePath(godot_node_path from)
public static godot_variant CreateFromNodePath(scoped in godot_node_path from)
{
NativeFuncs.godotsharp_variant_new_node_path(out godot_variant ret, from);
return ret;
@ -510,7 +510,7 @@ namespace Godot.NativeInterop
}
}
public static godot_string_name ConvertToNativeStringName(in godot_variant p_var)
public static godot_string_name ConvertToNativeStringName(scoped in godot_variant p_var)
=> p_var.Type == Variant.Type.StringName ?
NativeFuncs.godotsharp_string_name_new_copy(p_var.StringName) :
NativeFuncs.godotsharp_variant_as_string_name(p_var);
@ -519,7 +519,7 @@ namespace Godot.NativeInterop
public static StringName ConvertToStringName(in godot_variant p_var)
=> StringName.CreateTakingOwnershipOfDisposableValue(ConvertToNativeStringName(p_var));
public static godot_node_path ConvertToNativeNodePath(in godot_variant p_var)
public static godot_node_path ConvertToNativeNodePath(scoped in godot_variant p_var)
=> p_var.Type == Variant.Type.NodePath ?
NativeFuncs.godotsharp_node_path_new_copy(p_var.NodePath) :
NativeFuncs.godotsharp_variant_as_node_path(p_var);
@ -529,22 +529,28 @@ namespace Godot.NativeInterop
=> NodePath.CreateTakingOwnershipOfDisposableValue(ConvertToNativeNodePath(p_var));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_callable ConvertToNativeCallable(in godot_variant p_var)
public static godot_callable ConvertToNativeCallable(scoped in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_callable(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Callable ConvertToCallable(in godot_variant p_var)
=> Marshaling.ConvertCallableToManaged(ConvertToNativeCallable(p_var));
{
using var callable = ConvertToNativeCallable(p_var);
return Marshaling.ConvertCallableToManaged(callable);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static godot_signal ConvertToNativeSignal(in godot_variant p_var)
public static godot_signal ConvertToNativeSignal(scoped in godot_variant p_var)
=> NativeFuncs.godotsharp_variant_as_signal(p_var);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Signal ConvertToSignal(in godot_variant p_var)
=> Marshaling.ConvertSignalToManaged(ConvertToNativeSignal(p_var));
{
using var signal = ConvertToNativeSignal(p_var);
return Marshaling.ConvertSignalToManaged(signal);
}
public static godot_array ConvertToNativeArray(in godot_variant p_var)
public static godot_array ConvertToNativeArray(scoped in godot_variant p_var)
=> p_var.Type == Variant.Type.Array ?
NativeFuncs.godotsharp_array_new_copy(p_var.Array) :
NativeFuncs.godotsharp_variant_as_array(p_var);
@ -557,7 +563,7 @@ namespace Godot.NativeInterop
public static Array<T> ConvertToArray<[MustBeVariant] T>(in godot_variant p_var)
=> Array<T>.CreateTakingOwnershipOfDisposableValue(ConvertToNativeArray(p_var));
public static godot_dictionary ConvertToNativeDictionary(in godot_variant p_var)
public static godot_dictionary ConvertToNativeDictionary(scoped in godot_variant p_var)
=> p_var.Type == Variant.Type.Dictionary ?
NativeFuncs.godotsharp_dictionary_new_copy(p_var.Dictionary) :
NativeFuncs.godotsharp_variant_as_dictionary(p_var);

View file

@ -7,22 +7,23 @@ namespace Godot.NativeInterop;
public partial class VariantUtils
{
private static Exception UnsupportedType<T>() => new InvalidOperationException(
private static InvalidOperationException UnsupportedType<T>() => new InvalidOperationException(
$"The type is not supported for conversion to/from Variant: '{typeof(T).FullName}'");
internal static class GenericConversion<T>
{
public static unsafe godot_variant ToVariant(in T from) =>
ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
internal delegate godot_variant ToVariantConverter(scoped in T from);
internal delegate T FromVariantConverter(in godot_variant from);
public static unsafe godot_variant ToVariant(scoped in T from) =>
ToVariantCb != null ? ToVariantCb(from) : throw UnsupportedType<T>();
public static unsafe T FromVariant(in godot_variant variant) =>
FromVariantCb != null ? FromVariantCb(variant) : throw UnsupportedType<T>();
// ReSharper disable once StaticMemberInGenericType
internal static unsafe delegate*<in T, godot_variant> ToVariantCb;
internal static ToVariantConverter? ToVariantCb;
// ReSharper disable once StaticMemberInGenericType
internal static unsafe delegate*<in godot_variant, T> FromVariantCb;
internal static FromVariantConverter? FromVariantCb;
static GenericConversion()
{
@ -31,10 +32,10 @@ public partial class VariantUtils
}
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
public static godot_variant CreateFrom<[MustBeVariant] T>(in T from)
public static godot_variant CreateFrom<[MustBeVariant] T>(scoped in T from)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(f));
static TTo UnsafeAs<TTo>(in T f) => Unsafe.As<T, TTo>(ref Unsafe.AsRef(in f));
// `typeof(T) == typeof(X)` is optimized away. We cannot cache `typeof(T)` in a local variable, as it's not optimized when done like that.
@ -227,7 +228,7 @@ public partial class VariantUtils
public static T ConvertTo<[MustBeVariant] T>(in godot_variant variant)
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(f));
static T UnsafeAsT<TFrom>(TFrom f) => Unsafe.As<TFrom, T>(ref Unsafe.AsRef(in f));
if (typeof(T) == typeof(bool))
return UnsafeAsT(ConvertToBool(variant));

View file

@ -171,6 +171,26 @@ namespace Godot
return _position + (_size * 0.5f);
}
/// <summary>
/// Returns the support point in a given direction.
/// This is useful for collision detection algorithms.
/// </summary>
/// <param name="direction">The direction to find support for.</param>
/// <returns>A vector representing the support.</returns>
public readonly Vector2 GetSupport(Vector2 direction)
{
Vector2 support = _position;
if (direction.X > 0.0f)
{
support.X += _size.X;
}
if (direction.Y > 0.0f)
{
support.Y += _size.Y;
}
return support;
}
/// <summary>
/// Returns a copy of the <see cref="Rect2"/> grown by the specified amount
/// on all sides.

View file

@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
#nullable enable
@ -7,10 +10,186 @@ namespace Godot;
internal class ReflectionUtils
{
private static readonly HashSet<Type>? _tupleTypeSet;
private static readonly Dictionary<Type, string>? _builtinTypeNameDictionary;
internal static readonly bool IsEditorHintCached;
static ReflectionUtils()
{
IsEditorHintCached = Engine.IsEditorHint();
if (!IsEditorHintCached)
{
return;
}
_tupleTypeSet = new HashSet<Type>
{
// ValueTuple with only one element should be treated as normal generic type.
//typeof(ValueTuple<>),
typeof(ValueTuple<,>),
typeof(ValueTuple<,,>),
typeof(ValueTuple<,,,>),
typeof(ValueTuple<,,,,>),
typeof(ValueTuple<,,,,,>),
typeof(ValueTuple<,,,,,,>),
typeof(ValueTuple<,,,,,,,>),
};
_builtinTypeNameDictionary ??= new Dictionary<Type, string>
{
{ typeof(sbyte), "sbyte" },
{ typeof(byte), "byte" },
{ typeof(short), "short" },
{ typeof(ushort), "ushort" },
{ typeof(int), "int" },
{ typeof(uint), "uint" },
{ typeof(long), "long" },
{ typeof(ulong), "ulong" },
{ typeof(nint), "nint" },
{ typeof(nuint), "nuint" },
{ typeof(float), "float" },
{ typeof(double), "double" },
{ typeof(decimal), "decimal" },
{ typeof(bool), "bool" },
{ typeof(char), "char" },
{ typeof(string), "string" },
{ typeof(object), "object" },
};
}
public static Type? FindTypeInLoadedAssemblies(string assemblyName, string typeFullName)
{
return AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name == assemblyName)?
.GetType(typeFullName);
}
public static string ConstructTypeName(Type type)
{
if (!IsEditorHintCached)
{
return type.Name;
}
if (type is { IsArray: false, IsGenericType: false })
{
return GetSimpleTypeName(type);
}
var typeNameBuilder = new StringBuilder();
AppendType(typeNameBuilder, type);
return typeNameBuilder.ToString();
static void AppendType(StringBuilder sb, Type type)
{
if (type.IsArray)
{
AppendArray(sb, type);
}
else if (type.IsGenericType)
{
AppendGeneric(sb, type);
}
else
{
sb.Append(GetSimpleTypeName(type));
}
}
static void AppendArray(StringBuilder sb, Type type)
{
// Append inner most non-array element.
var elementType = type.GetElementType()!;
while (elementType.IsArray)
{
elementType = elementType.GetElementType()!;
}
AppendType(sb, elementType);
// Append brackets.
AppendArrayBrackets(sb, type);
static void AppendArrayBrackets(StringBuilder sb, Type? type)
{
while (type != null && type.IsArray)
{
int rank = type.GetArrayRank();
sb.Append('[');
sb.Append(',', rank - 1);
sb.Append(']');
type = type.GetElementType();
}
}
}
static void AppendGeneric(StringBuilder sb, Type type)
{
var genericArgs = type.GenericTypeArguments;
var genericDefinition = type.GetGenericTypeDefinition();
// Nullable<T>
if (genericDefinition == typeof(Nullable<>))
{
AppendType(sb, genericArgs[0]);
sb.Append('?');
return;
}
// ValueTuple
Debug.Assert(_tupleTypeSet != null);
if (_tupleTypeSet.Contains(genericDefinition))
{
sb.Append('(');
while (true)
{
// We assume that ValueTuple has 1~8 elements.
// And the 8th element (TRest) is always another ValueTuple.
// This is a hard coded tuple element length check.
if (genericArgs.Length != 8)
{
AppendParamTypes(sb, genericArgs);
break;
}
else
{
AppendParamTypes(sb, genericArgs.AsSpan(0, 7));
sb.Append(", ");
// TRest should be a ValueTuple!
var nextTuple = genericArgs[7];
genericArgs = nextTuple.GenericTypeArguments;
}
}
sb.Append(')');
return;
}
// Normal generic
var typeName = type.Name.AsSpan();
sb.Append(typeName[..typeName.LastIndexOf('`')]);
sb.Append('<');
AppendParamTypes(sb, genericArgs);
sb.Append('>');
static void AppendParamTypes(StringBuilder sb, ReadOnlySpan<Type> genericArgs)
{
int n = genericArgs.Length - 1;
for (int i = 0; i < n; i += 1)
{
AppendType(sb, genericArgs[i]);
sb.Append(", ");
}
AppendType(sb, genericArgs[n]);
}
}
static string GetSimpleTypeName(Type type)
{
Debug.Assert(_builtinTypeNameDictionary != null);
return _builtinTypeNameDictionary.TryGetValue(type, out string? name) ? name : type.Name;
}
}
}

View file

@ -979,7 +979,7 @@ namespace Godot
{
if (instance.Length < 3)
return false;
if (instance[from] != '0' || instance[from + 1] != 'x')
if (instance[from] != '0' || instance[from + 1] != 'x' || instance[from + 1] != 'X')
return false;
from += 2;
}
@ -1581,7 +1581,7 @@ namespace Godot
if (end < 0)
end = len;
if (allowEmpty || end > from)
ret.Add(float.Parse(instance.Substring(from), CultureInfo.InvariantCulture));
ret.Add(float.Parse(instance.AsSpan(from), CultureInfo.InvariantCulture));
if (end == len)
break;

View file

@ -47,7 +47,7 @@ namespace Godot
{
get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
real_t detSign = Mathf.Sign(Determinant());
return new Vector2(X.Length(), detSign * Y.Length());
}
}
@ -59,7 +59,7 @@ namespace Godot
{
get
{
real_t detSign = Mathf.Sign(BasisDeterminant());
real_t detSign = Mathf.Sign(Determinant());
return Mathf.Acos(X.Normalized().Dot(detSign * Y.Normalized())) - Mathf.Pi * 0.5f;
}
}
@ -135,7 +135,7 @@ namespace Godot
/// <returns>The inverse transformation matrix.</returns>
public readonly Transform2D AffineInverse()
{
real_t det = BasisDeterminant();
real_t det = Determinant();
if (det == 0)
throw new InvalidOperationException("Matrix determinant is zero and cannot be inverted.");
@ -157,15 +157,16 @@ namespace Godot
/// <summary>
/// Returns the determinant of the basis matrix. If the basis is
/// uniformly scaled, its determinant is the square of the scale.
/// uniformly scaled, then its determinant equals the square of the
/// scale factor.
///
/// A negative determinant means the Y scale is negative.
/// A zero determinant means the basis isn't invertible,
/// and is usually considered invalid.
/// A negative determinant means the basis was flipped, so one part of
/// the scale is negative. A zero determinant means the basis isn't
/// invertible, and is usually considered invalid.
/// </summary>
/// <returns>The determinant of the basis matrix.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private readonly real_t BasisDeterminant()
public readonly real_t Determinant()
{
return (X.X * Y.Y) - (X.Y * Y.X);
}

View file

@ -468,8 +468,8 @@ namespace Godot
{
for (int j = 0; j < 3; j++)
{
real_t e = transform.Basis[i][j] * min[j];
real_t f = transform.Basis[i][j] * max[j];
real_t e = transform.Basis[j][i] * min[j];
real_t f = transform.Basis[j][i] * max[j];
if (e < f)
{
tmin[i] += e;

View file

@ -692,10 +692,18 @@ namespace Godot
// Zero length vectors have no angle, so the best we can do is either lerp or throw an error.
return Lerp(to, weight);
}
Vector3 axis = Cross(to);
real_t axisLengthSquared = axis.LengthSquared();
if (axisLengthSquared == 0.0)
{
// Colinear vectors have no rotation axis or angle between them, so the best we can do is lerp.
return Lerp(to, weight);
}
axis /= Mathf.Sqrt(axisLengthSquared);
real_t startLength = Mathf.Sqrt(startLengthSquared);
real_t resultLength = Mathf.Lerp(startLength, Mathf.Sqrt(endLengthSquared), weight);
real_t angle = AngleTo(to);
return Rotated(Cross(to).Normalized(), angle * weight) * (resultLength / startLength);
return Rotated(axis, angle * weight) * (resultLength / startLength);
}
/// <summary>

View file

@ -1,23 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{AEBF0036-DA76-4341-B651-A3F2856AB2FA}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<OutputPath>bin/$(Configuration)</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RootNamespace>Godot</RootNamespace>
<TargetFramework>net6.0</TargetFramework>
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
<EnableDefaultItems>false</EnableDefaultItems>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>10</LangVersion>
<AnalysisMode>Recommended</AnalysisMode>
</PropertyGroup>
<PropertyGroup>
<Description>Godot C# Core API.</Description>
<Authors>Godot Engine contributors</Authors>
<PackageId>GodotSharp</PackageId>
<Version>4.3.0</Version>
<Version>4.4.0</Version>
<PackageVersion>$(PackageVersion_GodotSharp)</PackageVersion>
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp/GodotSharp</RepositoryUrl>
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
@ -28,26 +30,32 @@
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>
<ItemGroup>
<!-- SdkPackageVersions.props for easy access -->
<None Include="$(GodotSdkPackageVersionsFilePath)">
<Link>SdkPackageVersions.props</Link>
</None>
</ItemGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);GODOT</DefineConstants>
<DefineConstants Condition=" '$(GodotFloat64)' == 'true' ">REAL_T_IS_DOUBLE;$(DefineConstants)</DefineConstants>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ReflectionAnalyzers" Version="0.1.22-dev" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />
<!--PackageReference Include="IDisposableAnalyzers" Version="3.4.13" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" /-->
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Godot.SourceGenerators.Internal\Godot.SourceGenerators.Internal.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>
<!-- Sources -->
<ItemGroup>
<Compile Include="Core\Aabb.cs" />
<Compile Include="Core\Attributes\ExportToolButtonAttribute.cs" />
<Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
<Compile Include="Core\Bridge\MethodInfo.cs" />
<Compile Include="Core\Callable.generics.cs" />
@ -134,10 +142,12 @@
<Compile Include="GlobalUsings.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<!-- Compat Sources -->
<ItemGroup>
<ItemGroup Condition=" '$(GodotNoDeprecated)' == '' ">
<Compile Include="Compat.cs" />
</ItemGroup>
<!--
We import a props file with auto-generated includes. This works well with Rider.
However, Visual Studio and MonoDevelop won't list them in the solution explorer.

View file

@ -1,21 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ProjectGuid>{8FBEC238-D944-4074-8548-B3B524305905}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12</LangVersion>
<OutputPath>bin/$(Configuration)</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RootNamespace>Godot</RootNamespace>
<TargetFramework>net6.0</TargetFramework>
<DocumentationFile>$(OutputPath)/$(AssemblyName).xml</DocumentationFile>
<EnableDefaultItems>false</EnableDefaultItems>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>10</LangVersion>
</PropertyGroup>
<PropertyGroup>
<Description>Godot C# Editor API.</Description>
<Authors>Godot Engine contributors</Authors>
<PackageId>GodotSharpEditor</PackageId>
<Version>4.3.0</Version>
<Version>4.4.0</Version>
<PackageVersion>$(PackageVersion_GodotSharp)</PackageVersion>
<RepositoryUrl>https://github.com/godotengine/godot/tree/master/modules/mono/glue/GodotSharp/GodotSharpEditor</RepositoryUrl>
<PackageProjectUrl>$(RepositoryUrl)</PackageProjectUrl>
@ -36,7 +36,7 @@
</ProjectReference>
</ItemGroup>
<!-- Compat Sources -->
<ItemGroup>
<ItemGroup Condition=" '$(GodotNoDeprecated)' == '' ">
<Compile Include="Compat.cs" />
</ItemGroup>
<!--