Skip to content
This repository has been archived by the owner on Oct 19, 2020. It is now read-only.

Commit

Permalink
Support for latent actions (UGameplayTask, UOnlineBlueprintCallProxyB…
Browse files Browse the repository at this point in the history
…ase, UBlueprintAsyncActionBase)
  • Loading branch information
pixeltris committed Jun 22, 2019
1 parent 99ef8f5 commit 3c4fee5
Show file tree
Hide file tree
Showing 66 changed files with 2,992 additions and 237 deletions.
2 changes: 1 addition & 1 deletion Managed/CodeGenerator.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2
3

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using UnrealEngine.Runtime.Native;

namespace UnrealEngine.Runtime
{
/// <summary>
/// Templated version of FScriptInterface, which provides accessors and operators for referencing the interface portion of a UObject that implements a native interface.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct TScriptInterface<T> : IEquatable<TScriptInterface<T>> where T : class, IInterface
{
public FScriptInterface Base;

public TScriptInterface(T value)
{
IntPtr interfaceClass = UClass.GetInterfaceClassAddress<T>();
if (interfaceClass == IntPtr.Zero)
{
Base = default(FScriptInterface);
return;
}

IntPtr objectPointer = value.GetAddress();
if (objectPointer == IntPtr.Zero)
{
Base = default(FScriptInterface);
return;
}

IntPtr interfacePointer = Native_UObjectBaseUtility.GetNativeInterfaceAddress(objectPointer, interfaceClass);
if (interfacePointer == IntPtr.Zero)
{
Base = default(FScriptInterface);
return;
}

Base = new FScriptInterface(objectPointer, interfacePointer);
}

public UObject GetObject()
{
return Base.GetObject();
}

public T GetInterface()
{
return Base.GetInterface<T>();
}

public static bool operator ==(TScriptInterface<T> a, TScriptInterface<T> b)
{
return a.Equals(b);
}

public static bool operator !=(TScriptInterface<T> a, TScriptInterface<T> b)
{
return !a.Equals(b);
}

public override bool Equals(object obj)
{
if (obj is TScriptInterface<T>)
{
return Equals((TScriptInterface<T>)obj);
}
return false;
}

public bool Equals(TScriptInterface<T> other)
{
return Base == other.Base;
}

public override int GetHashCode()
{
return Base.GetHashCode();
}
}

/// <summary>
/// This utility class stores the UProperty data for a native interface property.
/// ObjectPointer and InterfacePointer point to different locations in the same UObject.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct FScriptInterface : IEquatable<FScriptInterface>
{
/// <summary>
/// A pointer to a UObject that implements a native interface.
/// </summary>
public IntPtr ObjectPointer;

/// <summary>
/// Pointer to the location of the interface object within the UObject referenced by ObjectPointer.
/// </summary>
public IntPtr InterfacePointer;

public FScriptInterface(IntPtr objectPointer, IntPtr interfacePointer)
{
ObjectPointer = objectPointer;
InterfacePointer = interfacePointer;
}

/// <summary>
/// Returns the ObjectPointer contained by this FScriptInterface
/// </summary>
public UObject GetObject()
{
return GCHelper.Find(ObjectPointer);
}

/// <summary>
/// Returns the interface
/// </summary>
public T GetInterface<T>() where T : class, IInterface
{
UObject obj = GetObject();
if (obj != null)
{
return obj.GetInterface<T>();
}
return null;
}

public static bool operator ==(FScriptInterface a, FScriptInterface b)
{
return a.Equals(b);
}

public static bool operator !=(FScriptInterface a, FScriptInterface b)
{
return !a.Equals(b);
}

public override bool Equals(object obj)
{
if (obj is FScriptInterface)
{
return Equals((FScriptInterface)obj);
}
return false;
}

public bool Equals(FScriptInterface other)
{
return ObjectPointer == other.ObjectPointer && InterfacePointer == other.InterfacePointer;
}

public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + ObjectPointer.GetHashCode();
hash = hash * 23 + InterfacePointer.GetHashCode();
return hash;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace UnrealEngine.Runtime
/// This class will redirect an object load to another object, so if an object is renamed
/// to a different package or group, external references to the object can be found
/// </summary>
[UClass(Flags=(ClassFlags)0x104000A0, Config="Engine"), UMetaPath("/Script/CoreUObject.ObjectRedirector")]
[UClass(Flags=(ClassFlags)0x104000A0), UMetaPath("/Script/CoreUObject.ObjectRedirector")]
public class UObjectRedirector : UObject
{
public UObject DestinationObject
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ public void RemoveActionsForObject(TWeakObject<UObject> obj)
public void AddNewAction(UObject actionObject, int uuid, FUSharpLatentAction newAction)
{
GCHandle handle = GCHandle.Alloc(newAction, GCHandleType.Normal);
IntPtr address = Native_FLatentActionManager.AddNewAction(Address, actionObject.Address, uuid, GCHandle.ToIntPtr(handle),
newAction.UpdateOperationFunc, newAction.NotifyObjectDestroyedFunc, newAction.NotifyActionAbortedFunc,
newAction.GetDescriptionFunc, newAction.DestructorFunc);
IntPtr address = Native_FLatentActionManager.AddNewAction(Address, actionObject.Address, uuid,
GCHandle.ToIntPtr(handle), newAction.CallbackFunc);
Debug.Assert(address != IntPtr.Zero);
newAction.Address = address;
newAction.Handle = handle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public struct FLatentResponse
{
public IntPtr Address;

internal FLatentResponse(IntPtr address)
{
Address = address;
}

public FLatentResponse DoneIf(bool condition)
{
Native_FLatentResponse.DoneIf(Address, condition);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@

namespace UnrealEngine.Engine
{
public class FUSharpLatentAction
// K2_NodeCallFunction handles latent functions
// Engine\Source\Editor\BlueprintGraph\Private\K2Node_CallFunction.cpp

// Engine\Source\Runtime\Engine\Classes\Engine\LatentActionManager.h

public unsafe class FUSharpLatentAction
{
public IntPtr Address { get; internal set; }
public bool Destroyed { get; private set; }
Expand All @@ -20,29 +25,48 @@ public class FUSharpLatentAction
private int index;
internal static List<FUSharpLatentAction> latentActions = new List<FUSharpLatentAction>();

public delegate void UpdateOperationDel(FLatentResponse response);
public delegate void NotifyDel();
public delegate void GetDescriptionDel(ref FScriptArray str);

// Cache the delegate as otherwise they will get GCed
internal UpdateOperationDel UpdateOperationFunc;
internal NotifyDel NotifyObjectDestroyedFunc;
internal NotifyDel NotifyActionAbortedFunc;
internal GetDescriptionDel GetDescriptionFunc;
internal NotifyDel DestructorFunc;
// Cache the delegate as otherwise it will get GCed
internal ManagedLatentCallbackDel CallbackFunc;

public FUSharpLatentAction()
{
UpdateOperationFunc = UpdateOperation;
NotifyObjectDestroyedFunc = NotifyObjectDestroyed;
NotifyActionAbortedFunc = NotifyActionAborted;
GetDescriptionFunc = GetDescriptionInternal;
DestructorFunc = Destructor;
CallbackFunc = Callback;

latentActions.Add(this);
index = latentActions.Count - 1;
}

private void Callback(ManagedLatentCallbackType callbackType, IntPtr thisPtr, IntPtr data)
{
try
{
switch (callbackType)
{
case ManagedLatentCallbackType.FUSharpLatentAction_UpdateOperation:
UpdateOperation(new FLatentResponse(data));
break;
case ManagedLatentCallbackType.FUSharpLatentAction_NotifyObjectDestroyed:
NotifyObjectDestroyed();
break;
case ManagedLatentCallbackType.FUSharpLatentAction_NotifyActionAborted:
NotifyActionAborted();
break;
case ManagedLatentCallbackType.FUSharpLatentAction_GetDescription:
GetDescriptionInternal(data);
break;
case ManagedLatentCallbackType.FUSharpLatentAction_Destructor:
Destructor();
break;
default:
throw new NotImplementedException();
}
}
catch (Exception e)
{
FMessage.LogException(e);
}
}

internal static void OnUnload()
{
foreach (FUSharpLatentAction action in latentActions)
Expand Down Expand Up @@ -99,11 +123,9 @@ public virtual void NotifyActionAborted()
{
}

private void GetDescriptionInternal(ref FScriptArray str)
private void GetDescriptionInternal(IntPtr str)
{
FStringUnsafe stringUnsafe = new FStringUnsafe(str);
stringUnsafe.Value = GetDescription();
str = stringUnsafe.Array;
FStringMarshaler.ToNative(str, GetDescription());
}

public virtual string GetDescription()
Expand Down
Loading

0 comments on commit 3c4fee5

Please sign in to comment.