Ensures the `push_nupkgs_local` argument in build_assemblies.py is an
absolute path so the argument can be
given as a relative path and it will be converted.
- Creates a `Godot.Offline.Config` file to configurate NuGet with
Godot's fallback folder. This is easier because now we can assume we can
override the entire file since user config will likely be in the default
`NuGet.Config` file or an additional `*.config` file.
- Ensure the NuGet fallback folder is created at the same time it is
added to the NuGet configuration so future builds don't fail.
- Add `GodotSharp` and `GodotSharpEditor` packages to the fallback folder.
- Add `.nupkg.metadata` file to packages in fallback folder.
- Refer to `Godot.SourceGenerators` using the specific non-floating version
since floating versions don't seem to work with fallbackPackageFolders.
We want to replace libnethost as it gives us issues with some compilers.
Our implementation tries to mimic libnethost's hostfxr_resolver search
logic. We try to use the same function names for easier comparing in
case we need to update this in the future.
Scripts that are instantiated at some point will always be recreated
if they ever become placeholders to prevent non-tool scripts
instantiated manually by users to become placeholders, if they
do become placeholders due to errors that prevent instantiation
(such as a missing parameterless constructor) these scripts
will also be recreated replacing the temporary placeholder.
If a script is marked as a tool but becomes a non-tool script
in a rebuild, the script will become a placeholder and will
no longer be considered applicable to be replaced by an instance
since the user explicitly removed the Tool attribute.
Since the list of signals in `CSharpScript::event_signals` retrieved
from calling `ScriptManagerBridge.UpdateScriptClassInfo` already
includes the signals from base scripts there is no need to iterate the
hierarchy again on `CSharpInstance::connect_event_signals`.
When the C# bindings generator finds a type without meta assume the type
refers to the 64-bit version of the type:
- `float` is converted to `double`
- `int` is converted to `long`
Vector4 and Vector4i were implemented incorrectly in godot_variant.
They were also missing their respective Variant conversion callbacks
(used for generic collections).
Took the chance to remove unnecessary native calls for creating
Variant from Vector4, as now it can be done from C# (which is faster).
- Use different syntax for object printing to avoid confusion with arrays.
- Print null as `<null>` to avoid confusion with a string `"null"`.
- Display `<empty>` in editor resource pickers to avoid confusion
with array-based properties.
- Fix platform detection after Linux OS name was renamed from `LinuxBSD`
to `Linux`
- Fix arch detection after renaming `64` to `x86_64`
- Fix typo in `find_hostfxr`
- Replace `IndexOutOfRangeException` with `ArgumentOutOfRangeException`
- Replace `Exception` with a more specific exception
- Add the parameter name to argument exception
- Update documentation for methods that throw exceptions
- Use `StringBuilder` to build exception messages
- Ensure exception messages end with a period
`libnethost.a` detection failed on my Linux system (Mageia 9, using Fedora 36
dotnet repos), because it used the first match which isn't the one matching
the rest of the SDK:
```
$ dotnet --list-runtimes
Microsoft.AspNetCore.App 3.1.28 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.8 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 3.1.28 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.5 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.8 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
```
No idea why I still have 6.0.5 installed but it should pick the highest I guess.
- Remove event as a valid target of `SignalAttribute`
- Stop adding the `[Signal]` attribute to events in bindings_generator
- Make bindings_generator use the `EventHandler` suffix to be consistent with the C# source generator
- Remove obsolete comment about the signal's delegate name
- MustBeVariant attribute can be used to enforce that generic types must
be a marshable from/to Variant.
- Also renames all diagnostic ids to be valid unicode identifiers.
Node methods in C# extended to use generics
now have the optional parameter `includeInternal`
like their non-generic equivalents.
Also, fixed a typo in the `Node.get_child` documentation.
- In cases where both `Xform`/`XformInv` and the `*` operator were
implemented the `Xform`/`XformInv` methods were removed in favor of the
`*` operator.
- In cases where the `Xform`/`XformInv` existed but not the `*` operator,
the `Xform`/`XformInv` methods were replaced with the `*` operator.
- In cases where no method existed, a new `*` operator has been
implemented to support the same operations that are supported in GDScript.
- Fixes the `Transform.Xform` and `Transform.XformInv` with `Rect2`
implementation to use a zero `Rect2` size to start expanding from
(which is how it's implemented in C++).
If the project assembly does not exist, return `false` directly instead
of trying to load it.
This prevents the `System.InvalidOperationException` thrown for failing
to locate managed application.
- Moves interop functions to UnmanagedCallbacks struct that
contains the function pointers and is passed to C#.
- Implements UnmanagedCallbacksGenerator, a C# source generator that
generates the UnmanagedCallbacks struct in C# and the body for the
NativeFuncs methods (their implementation just calls the function
pointer in the UnmanagedCallbacks). The generated methods are needed
because .NET pins byref parameters of native calls, even if they are
'ref struct's, which don't need pinning. The generated methods use
`Unsafe.AsPointer` so that we can benefit from byref parameters
without suffering overhead of pinning.
Co-authored-by: Raul Santos <raulsntos@gmail.com>
We were using it to workaround a limitation of `Unsafe.AsPointer` and
`ref struct`s. However, we can get the same result with some tricks,
since we have control over the declaration of these structs.
The setting is initially assigned the name of the Godot project,
but it's kept freezed to prevent issues when renaming the Godot
project.
The user can always rename the C# project and solution manually and
change the setting to the new name.
This new version does not support the following type arguments:
- Generic types
- Array of Godot Object (Godot.Object[]) or derived types
The new implementation uses delegate pointers to call the Variant
conversion methods. We do type checking only once in the static
constructor to get the conversion delegates.
Now, we no longer need to do type checking every time, and we no
longer have to box value types.
This is the best implementation I could come up with, as C# generics
don't support anything similar to C++ template specializations.
- Array and Dictionary now store `Variant` instead of `System.Object`.
- Removed generic Array and Dictionary.
They cause too much issues, heavily relying on reflection and
very limited by the lack of a generic specialization.
- Removed support for non-Godot collections.
Support for them also relied heavily on reflection for marshaling.
Support for them will likely be re-introduced in the future, but
it will have to rely on source generators instead of reflection.
- Reduced our use of reflection.
The remaining usages will be moved to source generators soon.
The only usage that I'm not sure yet how to replace is dynamic
invocation of delegates.
Changed the signal declaration signal to:
```
// The following generates a MySignal event
[Signal] public delegate void MySignalEventHandler(int param);
```
In the past, the Godot editor distributed the API assemblies and
copied them to project directories for projects to reference them.
This changed with the move to .NET 5/6. Godot no longer copies the
assemblies to project directories. However, the project Sdk still
tried to reference them from the same location.
From now on, the GodotSharp API is distributed as a NuGet package,
which the Sdk can reference.
Added an option to `build_assemblies.py` to copy all Godot NuGet
packages to an existing local NuGet source. This will be needed
during development, while packages are not published to a remote
NuGet repository.
This option also makes sure to remove packages of the same version
installed (~/.nuget/packages). Very useful during development, when
packages change, to make sure the package being used by a project is
the same we just built and not one from a previous build.
A local NuGet source can be created like this:
```
mkdir ~/MyLocalNuGetSource && \
dotnet nuget add source ~/MyLocalNuGetSource/ -n MyLocalNuGetSource
```
Previously, we added source generators for invoking/accessing methods,
properties and fields in scripts. This freed us from the overhead of
reflection. However, the generated code still used our dynamic
marshaling functions, which do runtime type checking and box value
types.
This commit changes the bindings and source generators to include
'static' marshaling. Based on the types known at compile time, now
we generate the appropriate marshaling call for each type.
Previously, for each scripts class instance that was created from code
rather than by the engine, we were constructing, configuring and
assigning a new CSharpScript.
This has changed now and we make sure there's only one CSharpScript
associated to each type.
The editor no longer needs to create temporary instances to get the
default values. The initializer values of the exported properties are
still evaluated at runtime. For example, in the following example,
`GetInitialValue()` will be called when first looks for default values:
```
[Export] int MyValue = GetInitialValue();
```
Exporting fields with a non-supported type now results in a compiler
error rather than a runtime error when the script is used.
This base implementation is still very barebones but it defines the path
for how exporting will work (at least when embedding the .NET runtime).
Many manual steps are still needed, which should be automatized in the
future. For example, in addition to the API assemblies, now you also
need to copy the GodotPlugins assembly to each game project.
Finalizers are longer guaranteed to be called on exit now that
we switched to .NET Core. This results in native instances leaking.
The only solution I can think of so far is to keep a list of all
instances alive to dispose when the AssemblyLoadContext.Unloading
event is raised.
This replaces the way we invoke methods and set/get properties.
This first iteration rids us of runtime type checking in those
cases, as it's now done at compile time.
Later it will also stop needing the use of reflection. After that,
we will only depend on reflection for generic Godot Array and
Dictionary. We're stuck with reflection in generic collections
for now as C# doesn't support generic/template specialization.
This is only the initial implementation. Further iterations are
coming, specially once we switch to the native extension system
which completely changes the way members are accessed/invoked.
For example, with the native extension system we will likely need
to create `UnmanagedCallersOnly` invoke wrapper methods and return
function pointers to the engine.
Other kind of members, like event signals will be receiving the
same treatment in the future.
Some Linux distros use their distro name as the RID for directory names.
If the .NET Host directory cannot be found with the generic RID,
try to get the rid from `dotnet --info`.
The generic RID should still be the first choice. Some platforms like
Windows 10 define the RID as `win10-x64` but still use the generic
`win-x64` for directory names.
Co-authored-by: Lewis James <lewiji+github@gmail.com>
We're targeting .NET 5 for now to make development easier while
.NET 6 is not yet released.
TEMPORARY REGRESSIONS
---------------------
Assembly unloading is not implemented yet. As such, many Godot
resources are leaked at exit. This will be re-implemented later
together with assembly hot-reloading.