Implement .NET 7 runtime support and bindings generation

This commit is contained in:
2022-11-17 19:49:39 +02:00
parent fe943ca010
commit 96dc279ebd
89 changed files with 6009 additions and 503 deletions

View File

@@ -3,6 +3,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace FlaxEngine
{
@@ -44,6 +45,7 @@ namespace FlaxEngine
/// The node evaluation context structure.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
[NativeMarshalling(typeof(ContextMarshaler))]
public struct Context
{
/// <summary>
@@ -92,6 +94,61 @@ namespace FlaxEngine
public AnimatedModel Instance;
}
[CustomMarshaller(typeof(Context), MarshalMode.Default, typeof(ContextMarshaler))]
internal static class ContextMarshaler
{
[StructLayout(LayoutKind.Sequential)]
public struct ContextNative
{
public IntPtr Graph;
public IntPtr GraphExecutor;
public IntPtr Node;
public uint NodeId;
public int BoxId;
public float DeltaTime;
public ulong CurrentFrameIndex;
public IntPtr BaseModel;
public IntPtr Instance;
}
internal static Context ConvertToManaged(ContextNative unmanaged) => ToManaged(unmanaged);
internal static ContextNative ConvertToUnmanaged(Context managed) => ToNative(managed);
internal static Context ToManaged(ContextNative managed)
{
return new Context()
{
Graph = managed.Graph,
GraphExecutor = managed.GraphExecutor,
Node = managed.Node,
NodeId = managed.NodeId,
BoxId = managed.BoxId,
DeltaTime = managed.DeltaTime,
CurrentFrameIndex = managed.CurrentFrameIndex,
BaseModel = SkinnedModelMarshaller.ConvertToManaged(managed.BaseModel),
Instance = AnimatedModelMarshaller.ConvertToManaged(managed.Instance),
};
}
internal static ContextNative ToNative(Context managed)
{
return new ContextNative()
{
Graph = managed.Graph,
GraphExecutor = managed.GraphExecutor,
Node = managed.Node,
NodeId = managed.NodeId,
BoxId = managed.BoxId,
DeltaTime = managed.DeltaTime,
CurrentFrameIndex = managed.CurrentFrameIndex,
BaseModel = SkinnedModelMarshaller.ConvertToUnmanaged(managed.BaseModel),
Instance = AnimatedModelMarshaller.ConvertToUnmanaged(managed.Instance),
};
}
internal static void Free(ContextNative unmanaged)
{
}
}
/// <summary>
/// The animation graph 'impulse' connections data container (the actual transfer is done via pointer as it gives better performance).
/// Container for skeleton nodes transformation hierarchy and any other required data.
@@ -203,14 +260,16 @@ namespace FlaxEngine
#region Internal Calls
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool Internal_HasConnection(ref CustomNode.Context context, int boxId);
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_HasConnection")]
[return: MarshalAs(UnmanagedType.U1)]
internal static partial bool Internal_HasConnection(ref AnimationGraph.CustomNode.Context context, int boxId);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object Internal_GetInputValue(ref CustomNode.Context context, int boxId);
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_GetInputValue")]
[return: MarshalUsing(typeof(FlaxEngine.GCHandleMarshaller))]
internal static partial object Internal_GetInputValue(ref AnimationGraph.CustomNode.Context context, int boxId);
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern IntPtr Internal_GetOutputImpulseData(ref CustomNode.Context context);
[LibraryImport("FlaxEngine", EntryPoint = "FlaxEngine.AnimationGraph::Internal_GetOutputImpulseData")]
internal static partial IntPtr Internal_GetOutputImpulseData(ref AnimationGraph.CustomNode.Context context);
#endregion
}

View File

@@ -13,8 +13,8 @@
#include "Engine/Content/Assets/SkinnedModel.h"
#if USE_MONO
#include <ThirdParty/mono-2.0/mono/metadata/appdomain.h>
#endif
struct InternalInitData
{
@@ -52,6 +52,7 @@ namespace AnimGraphInternal
{
bool HasConnection(InternalContext* context, int32 boxId)
{
SCRIPTING_EXPORT("FlaxEngine.AnimationGraph::Internal_HasConnection")
const auto box = context->Node->TryGetBox(boxId);
if (box == nullptr)
DebugLog::ThrowArgumentOutOfRange("boxId");
@@ -60,6 +61,7 @@ namespace AnimGraphInternal
MonoObject* GetInputValue(InternalContext* context, int32 boxId)
{
SCRIPTING_EXPORT("FlaxEngine.AnimationGraph::Internal_GetInputValue")
const auto box = context->Node->TryGetBox(boxId);
if (box == nullptr)
DebugLog::ThrowArgumentOutOfRange("boxId");
@@ -77,14 +79,13 @@ namespace AnimGraphInternal
AnimGraphImpulse* GetOutputImpulseData(InternalContext* context)
{
SCRIPTING_EXPORT("FlaxEngine.AnimationGraph::Internal_GetOutputImpulseData")
const auto nodes = context->Node->GetNodes(context->GraphExecutor);
context->GraphExecutor->InitNodes(nodes);
return nodes;
}
}
#endif
void AnimGraphExecutor::initRuntime()
{
#if USE_MONO
@@ -122,7 +123,7 @@ void AnimGraphExecutor::ProcessGroupCustom(Box* boxBase, Node* nodeBase, Value&
internalContext.Instance = context.Data->Object ? context.Data->Object->GetOrCreateManagedInstance() : nullptr;
// Peek managed object
const auto obj = mono_gchandle_get_target(data.Handle);
const auto obj = MUtils::GetGCHandleTarget(data.Handle);
if (obj == nullptr)
{
LOG(Warning, "Custom node instance is null.");
@@ -166,7 +167,7 @@ void AnimGraph::ClearCustomNode(Node* node)
if (data.Handle)
{
#if USE_MONO
mono_gchandle_free(data.Handle);
MUtils::FreeGCHandle(data.Handle);
#endif
data.Handle = 0;
}
@@ -216,7 +217,7 @@ bool AnimGraph::InitCustomNode(Node* node)
// Allocate managed node object (create GC handle to prevent destruction)
const auto obj = type->CreateInstance();
const auto handleGC = mono_gchandle_new(obj, false);
const auto handleGC = MUtils::NewGCHandle(obj, false);
// Initialize node
InternalInitData initData;
@@ -228,7 +229,7 @@ bool AnimGraph::InitCustomNode(Node* node)
load->Invoke(obj, params, &exception);
if (exception)
{
mono_gchandle_free(handleGC);
MUtils::FreeGCHandle(handleGC);
MException ex(exception);
ex.Log(LogType::Warning, TEXT("AnimGraph"));

View File

@@ -516,7 +516,7 @@ public:
/// <summary>
/// The GC handle to the managed instance of the node object.
/// </summary>
uint32 Handle;
gchandle Handle;
};
struct CurveData