Lua向C#逻辑迁移 一期 #13

将整个插件代码上传
This commit is contained in:
2025-10-26 21:48:39 +08:00
parent 56994b3927
commit 648386cd73
785 changed files with 53683 additions and 2 deletions

View File

@ -0,0 +1,381 @@
#include "CSAssembly.h"
#include "UnrealSharpCore.h"
#include "Misc/Paths.h"
#include "CSManager.h"
#include "CSUnrealSharpSettings.h"
#include "Logging/StructuredLog.h"
#include "TypeGenerator/CSClass.h"
#include "TypeGenerator/CSEnum.h"
#include "TypeGenerator/CSInterface.h"
#include "TypeGenerator/CSScriptStruct.h"
#include "TypeGenerator/Register/MetaData/CSClassMetaData.h"
#include "TypeGenerator/Register/MetaData/CSDelegateMetaData.h"
#include "TypeGenerator/Register/MetaData/CSEnumMetaData.h"
#include "TypeGenerator/Register/MetaData/CSInterfaceMetaData.h"
#include "TypeGenerator/Register/MetaData/CSStructMetaData.h"
#include "TypeGenerator/Register/TypeInfo/CSClassInfo.h"
#include "Utils/CSClassUtilities.h"
void UCSAssembly::SetAssemblyPath(const FStringView InAssemblyPath)
{
if (!AssemblyPath.IsEmpty())
{
return;
}
AssemblyPath = FPaths::ConvertRelativePathToFull(InAssemblyPath.GetData());
#if defined(_WIN32)
// Replace forward slashes with backslashes
AssemblyPath.ReplaceInline(TEXT("/"), TEXT("\\"));
#endif
AssemblyName = *FPaths::GetBaseFilename(AssemblyPath);
}
bool UCSAssembly::LoadAssembly(bool bisCollectible)
{
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString(TEXT("UCSAssembly::LoadAssembly: " + AssemblyName.ToString())));
if (IsValidAssembly())
{
UE_LOG(LogUnrealSharp, Display, TEXT("%s is already loaded"), *AssemblyPath);
return true;
}
if (!FPaths::FileExists(AssemblyPath))
{
UE_LOG(LogUnrealSharp, Display, TEXT("%s doesn't exist"), *AssemblyPath);
return false;
}
bIsLoading = true;
FGCHandle NewHandle = UCSManager::Get().GetManagedPluginsCallbacks().LoadPlugin(*AssemblyPath, bisCollectible);
NewHandle.Type = GCHandleType::WeakHandle;
if (NewHandle.IsNull())
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to load: %s"), *AssemblyPath);
return false;
}
ManagedAssemblyHandle = MakeShared<FGCHandle>(NewHandle);
FModuleManager::Get().OnModulesChanged().AddUObject(this, &UCSAssembly::OnModulesChanged);
if (ProcessTypeMetadata())
{
for (const TPair<FCSFieldName, TSharedPtr<FCSManagedTypeInfo>>& NameToTypeInfo : AllTypes)
{
NameToTypeInfo.Value->StartBuildingManagedType();
}
}
bIsLoading = false;
UCSManager::Get().OnManagedAssemblyLoadedEvent().Broadcast(AssemblyName);
return true;
}
template <typename T, typename MetaDataType>
void RegisterMetaData(UCSAssembly* OwningAssembly, const TSharedPtr<FJsonValue>& MetaData,
TMap<FCSFieldName,
TSharedPtr<FCSManagedTypeInfo>>& Map,
UClass* FieldType,
TFunction<void(TSharedPtr<FCSManagedTypeInfo>)> OnRebuild = nullptr)
{
const TSharedPtr<FJsonObject>& MetaDataObject = MetaData->AsObject();
const FString Name= MetaDataObject->GetStringField(TEXT("Name"));
const FString Namespace = MetaDataObject->GetStringField(TEXT("Namespace"));
const FCSFieldName FullName(*Name, *Namespace);
TSharedPtr<FCSManagedTypeInfo> ExistingValue = Map.FindRef(FullName);
if (ExistingValue.IsValid())
{
// Parse fresh metadata and update the existing info
MetaDataType NewMeta;
NewMeta.SerializeFromJson(MetaDataObject);
if (ExistingValue->GetStructureState() == HasChangedStructure || NewMeta != *ExistingValue->GetTypeMetaData<MetaDataType>())
{
TSharedPtr<MetaDataType> MetaDataPtr = MakeShared<MetaDataType>(NewMeta);
ExistingValue->SetTypeMetaData(MetaDataPtr);
ExistingValue->SetStructureState(HasChangedStructure);
if (OnRebuild)
{
OnRebuild(ExistingValue);
}
}
}
else
{
TSharedPtr<MetaDataType> ParsedMeta = MakeShared<MetaDataType>();
ParsedMeta->SerializeFromJson(MetaDataObject);
TSharedPtr<T> NewValue = MakeShared<T>(ParsedMeta, OwningAssembly, FieldType);
Map.Add(FullName, NewValue);
}
}
bool UCSAssembly::ProcessTypeMetadata()
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::ProcessTypeMetadata);
const FString MetadataPath = FPaths::ChangeExtension(AssemblyPath, "metadata.json");
if (!FPaths::FileExists(MetadataPath))
{
return true;
}
FString JsonString;
if (!FFileHelper::LoadFileToString(JsonString, *MetadataPath))
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to load MetaDataPath at: %s"), *MetadataPath);
return false;
}
TSharedPtr<FJsonObject> JsonObject;
if (!FJsonSerializer::Deserialize(TJsonReaderFactory<>::Create(JsonString), JsonObject) || !JsonObject.IsValid())
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to parse JSON at: %s"), *MetadataPath);
return false;
}
UCSManager& Manager = UCSManager::Get();
const TArray<TSharedPtr<FJsonValue>>& StructMetaData = JsonObject->GetArrayField(TEXT("StructMetaData"));
for (const TSharedPtr<FJsonValue>& MetaData : StructMetaData)
{
RegisterMetaData<FCSManagedTypeInfo, FCSStructMetaData>(this, MetaData, AllTypes, UCSScriptStruct::StaticClass());
}
const TArray<TSharedPtr<FJsonValue>>& EnumMetaData = JsonObject->GetArrayField(TEXT("EnumMetaData"));
for (const TSharedPtr<FJsonValue>& MetaData : EnumMetaData)
{
RegisterMetaData<FCSManagedTypeInfo, FCSEnumMetaData>(this, MetaData, AllTypes, UCSEnum::StaticClass());
}
const TArray<TSharedPtr<FJsonValue>>& InterfacesMetaData = JsonObject->GetArrayField(TEXT("InterfacesMetaData"));
for (const TSharedPtr<FJsonValue>& MetaData : InterfacesMetaData)
{
RegisterMetaData<FCSManagedTypeInfo, FCSInterfaceMetaData>(this, MetaData, AllTypes, UCSInterface::StaticClass());
}
const TArray<TSharedPtr<FJsonValue>>& DelegatesMetaData = JsonObject->GetArrayField(TEXT("DelegateMetaData"));
for (const TSharedPtr<FJsonValue>& MetaData : DelegatesMetaData)
{
RegisterMetaData<FCSManagedTypeInfo, FCSDelegateMetaData>(this, MetaData, AllTypes, UDelegateFunction::StaticClass());
}
const TArray<TSharedPtr<FJsonValue>>& ClassesMetaData = JsonObject->GetArrayField(TEXT("ClassMetaData"));
for (const TSharedPtr<FJsonValue>& MetaData : ClassesMetaData)
{
RegisterMetaData<FCSClassInfo, FCSClassMetaData>(this, MetaData, AllTypes, UCSClass::StaticClass(),
[&Manager](const TSharedPtr<FCSManagedTypeInfo>& ClassInfo)
{
// Structure has been changed. We must trigger full reload on all managed classes that derive from this class.
TArray<UClass*> DerivedClasses;
GetDerivedClasses(ClassInfo->GetFieldChecked<UClass>(), DerivedClasses);
for (UClass* DerivedClass : DerivedClasses)
{
if (!Manager.IsManagedType(DerivedClass))
{
continue;
}
UCSClass* ManagedClass = static_cast<UCSClass*>(DerivedClass);
TSharedPtr<FCSClassInfo> ChildClassInfo = ManagedClass->GetManagedTypeInfo<FCSClassInfo>();
ChildClassInfo->SetStructureState(HasChangedStructure);
}
});
}
return true;
}
bool UCSAssembly::UnloadAssembly()
{
if (!IsValidAssembly())
{
// Assembly is already unloaded.
UE_LOGFMT(LogUnrealSharp, Display, "{0} is already unloaded", *AssemblyName.ToString());
return true;
}
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*FString(TEXT("UCSAssembly::UnloadAssembly: " + AssemblyName.ToString())));
FGCHandleIntPtr AssemblyHandle = ManagedAssemblyHandle->GetHandle();
for (TSharedPtr<FGCHandle>& Handle : AllocatedManagedHandles)
{
Handle->Dispose(AssemblyHandle);
Handle.Reset();
}
ManagedClassHandles.Reset();
AllocatedManagedHandles.Reset();
// Don't need the assembly handle anymore, we use the path to unload the assembly.
ManagedAssemblyHandle->Dispose(ManagedAssemblyHandle->GetHandle());
ManagedAssemblyHandle.Reset();
UCSManager::Get().OnManagedAssemblyUnloadedEvent().Broadcast(AssemblyName);
return UCSManager::Get().GetManagedPluginsCallbacks().UnloadPlugin(*AssemblyPath);
}
TSharedPtr<FGCHandle> UCSAssembly::TryFindTypeHandle(const FCSFieldName& FieldName)
{
if (!IsValidAssembly())
{
return nullptr;
}
if (TSharedPtr<FGCHandle>* Handle = ManagedClassHandles.Find(FieldName))
{
return *Handle;
}
FString FullName = FieldName.GetFullName().ToString();
uint8* TypeHandle = FCSManagedCallbacks::ManagedCallbacks.LookupManagedType(ManagedAssemblyHandle->GetPointer(), *FullName);
if (!TypeHandle)
{
return nullptr;
}
TSharedPtr<FGCHandle> AllocatedHandle = MakeShared<FGCHandle>(TypeHandle, GCHandleType::WeakHandle);
AllocatedManagedHandles.Add(AllocatedHandle);
ManagedClassHandles.Add(FieldName, AllocatedHandle);
return AllocatedHandle;
}
TSharedPtr<FGCHandle> UCSAssembly::GetManagedMethod(const TSharedPtr<FGCHandle>& TypeHandle, const FString& MethodName)
{
if (!TypeHandle.IsValid())
{
UE_LOGFMT(LogUnrealSharp, Error, "Type handle is invalid for method %s", *MethodName);
return nullptr;
}
uint8* MethodHandle = FCSManagedCallbacks::ManagedCallbacks.LookupManagedMethod(TypeHandle->GetPointer(), *MethodName);
if (MethodHandle == nullptr)
{
UE_LOG(LogUnrealSharp, Error, TEXT("Failed to find managed method for %s"), *MethodName);
return nullptr;
}
TSharedPtr<FGCHandle> AllocatedHandle = MakeShared<FGCHandle>(MethodHandle, GCHandleType::WeakHandle);
AllocatedManagedHandles.Add(AllocatedHandle);
return AllocatedHandle;
}
TSharedPtr<FGCHandle> UCSAssembly::CreateManagedObject(const UObject* Object)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::CreateManagedObject);
// Only managed/native classes have a C# counterpart.
UClass* Class = FCSClassUtilities::GetFirstNonBlueprintClass(Object->GetClass());
TSharedPtr<FCSManagedTypeInfo> TypeInfo = FindOrAddTypeInfo(Class);
TSharedPtr<FGCHandle> TypeHandle = TypeInfo->GetManagedTypeHandle();
TCHAR* Error = nullptr;
FGCHandle NewManagedObject = FCSManagedCallbacks::ManagedCallbacks.CreateNewManagedObject(Object, TypeHandle->GetPointer(), &Error);
NewManagedObject.Type = GCHandleType::StrongHandle;
if (NewManagedObject.IsNull())
{
// This should never happen. Potential issues: IL errors, typehandle is invalid.
UE_LOGFMT(LogUnrealSharp, Fatal, "Failed to create managed counterpart for {0}:\n{1}", *Object->GetName(), Error);
return nullptr;
}
TSharedPtr<FGCHandle> Handle = MakeShared<FGCHandle>(NewManagedObject);
AllocatedManagedHandles.Add(Handle);
uint32 ObjectID = Object->GetUniqueID();
UCSManager::Get().ManagedObjectHandles.AddByHash(ObjectID, ObjectID, Handle);
return Handle;
}
TSharedPtr<FGCHandle> UCSAssembly::FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* InterfaceClass)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::FindOrCreateManagedInterfaceWrapper);
UClass* NonBlueprintClass = FCSClassUtilities::GetFirstNonBlueprintClass(InterfaceClass);
TSharedPtr<FCSManagedTypeInfo> ClassInfo = FindOrAddTypeInfo(NonBlueprintClass);
TSharedPtr<FGCHandle> TypeHandle = ClassInfo->GetManagedTypeHandle();
uint32 ObjectID = Object->GetUniqueID();
TMap<uint32, TSharedPtr<FGCHandle>>& TypeMap = UCSManager::Get().ManagedInterfaceWrappers.FindOrAddByHash(ObjectID, ObjectID);
uint32 TypeId = InterfaceClass->GetUniqueID();
if (TSharedPtr<FGCHandle>* Existing = TypeMap.FindByHash(TypeId, TypeId))
{
return *Existing;
}
TSharedPtr<FGCHandle>* ObjectHandle = UCSManager::Get().ManagedObjectHandles.FindByHash(ObjectID, ObjectID);
if (ObjectHandle == nullptr)
{
return nullptr;
}
FGCHandle NewManagedObjectWrapper = FCSManagedCallbacks::ManagedCallbacks.CreateNewManagedObjectWrapper((*ObjectHandle)->GetPointer(), TypeHandle->GetPointer());
NewManagedObjectWrapper.Type = GCHandleType::StrongHandle;
if (NewManagedObjectWrapper.IsNull())
{
// This should never happen. Potential issues: IL errors, typehandle is invalid.
UE_LOGFMT(LogUnrealSharp, Fatal, "Failed to create managed counterpart for {0}", *Object->GetName());
return nullptr;
}
TSharedPtr<FGCHandle> Handle = MakeShared<FGCHandle>(NewManagedObjectWrapper);
AllocatedManagedHandles.Add(Handle);
TypeMap.AddByHash(TypeId, TypeId, Handle);
return Handle;
}
void UCSAssembly::AddPendingClass(const FCSTypeReferenceMetaData& ParentClass, FCSClassInfo* NewClass)
{
TSet<FCSClassInfo*>& PendingClass = PendingClasses.FindOrAdd(ParentClass);
PendingClass.Add(NewClass);
}
void UCSAssembly::OnModulesChanged(FName InModuleName, EModuleChangeReason InModuleChangeReason)
{
if (InModuleChangeReason != EModuleChangeReason::ModuleLoaded)
{
return;
}
int32 NumPendingClasses = PendingClasses.Num();
for (auto Itr = PendingClasses.CreateIterator(); Itr; ++Itr)
{
UClass* Class = Itr.Key().GetOwningClass();
if (!Class)
{
// Class still not loaded from this module.
continue;
}
for (FCSClassInfo* PendingClass : Itr.Value())
{
PendingClass->StartBuildingManagedType();
}
Itr.RemoveCurrent();
}
#if WITH_EDITOR
if (NumPendingClasses != PendingClasses.Num())
{
UCSManager::Get().OnProcessedPendingClassesEvent().Broadcast();
}
#endif
}

View File

@ -0,0 +1,173 @@
#pragma once
#include "CSManagedGCHandle.h"
#include "UnrealSharpCore.h"
#include "Logging/StructuredLog.h"
#include "TypeGenerator/Register/MetaData/CSTypeReferenceMetaData.h"
#include "Utils/CSClassUtilities.h"
#include "CSAssembly.generated.h"
#if !defined(_WIN32)
#define __stdcall
#endif
struct FCSClassInfo;
struct FCSManagedMethod;
class UCSClass;
/**
* Represents a managed assembly.
* This class is responsible for loading and unloading the assembly, as well as managing all types that are defined in the C# assembly.
*/
UCLASS()
class UCSAssembly : public UObject
{
GENERATED_BODY()
public:
void SetAssemblyPath(const FStringView InAssemblyPath);
UNREALSHARPCORE_API bool LoadAssembly(bool bIsCollectible = true);
UNREALSHARPCORE_API bool UnloadAssembly();
UNREALSHARPCORE_API bool IsValidAssembly() const { return ManagedAssemblyHandle.IsValid() && !ManagedAssemblyHandle->IsNull(); }
FName GetAssemblyName() const { return AssemblyName; }
const FString& GetAssemblyPath() const { return AssemblyPath; }
bool IsLoading() const { return bIsLoading; }
TSharedPtr<FGCHandle> TryFindTypeHandle(const FCSFieldName& FieldName);
TSharedPtr<FGCHandle> GetManagedMethod(const TSharedPtr<FGCHandle>& TypeHandle, const FString& MethodName);
template<typename T = FCSManagedTypeInfo>
TSharedPtr<T> FindOrAddTypeInfo(UClass* Field)
{
if (ICSManagedTypeInterface* ManagedClass = FCSClassUtilities::GetManagedType(Field))
{
return ManagedClass->GetManagedTypeInfo<T>();
}
FCSFieldName FieldName(Field);
return FindOrAddTypeInfo<T>(FieldName);
}
template<typename T = FCSManagedTypeInfo>
TSharedPtr<T> FindOrAddTypeInfo(const FCSFieldName& ClassName)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::FindOrAddClassInfo);
TSharedPtr<FCSManagedTypeInfo>& TypeInfo = AllTypes.FindOrAdd(ClassName);
// Native types are populated on the go when they are needed for managed code execution.
if (!TypeInfo.IsValid())
{
UField* Field = TryFindField(ClassName);
if (!IsValid(Field))
{
UE_LOGFMT(LogUnrealSharp, Error, "Failed to find native class: {0}", *ClassName.GetName());
return nullptr;
}
TypeInfo = MakeShared<FCSManagedTypeInfo>(Field, this);
}
if constexpr (std::is_same_v<T, FCSManagedTypeInfo>)
{
return TypeInfo;
}
else
{
return StaticCastSharedPtr<T>(TypeInfo);
}
}
template<typename T = FCSManagedTypeInfo>
TSharedPtr<T> FindTypeInfo(const FCSFieldName& FieldName) const
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::FindClassInfo);
static_assert(TIsDerivedFrom<T, FCSManagedTypeInfo>::Value, "T must be a FCSManagedTypeInfo-derived type.");
const TSharedPtr<FCSManagedTypeInfo>* TypeInfo = AllTypes.Find(FieldName);
if (TypeInfo && TypeInfo->IsValid())
{
return StaticCastSharedPtr<T>(*TypeInfo);
}
return nullptr;
}
template<typename T = UField>
T* FindType(const FCSFieldName& FieldName) const
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSAssembly::FindType);
static_assert(TIsDerivedFrom<T, UField>::Value, "T must be a UField-derived type.");
TSharedPtr<FCSManagedTypeInfo> TypeInfo = AllTypes.FindRef(FieldName);
if (TypeInfo.IsValid())
{
return Cast<T>(TypeInfo->StartBuildingManagedType());
}
return TryFindField<T>(FieldName);
}
// Creates a C# counterpart for the given UObject.
TSharedPtr<FGCHandle> CreateManagedObject(const UObject* Object);
TSharedPtr<FGCHandle> FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* InterfaceClass);
// Add a class that is waiting for its parent class to be loaded before it can be created.
void AddPendingClass(const FCSTypeReferenceMetaData& ParentClass, FCSClassInfo* NewClass);
TSharedPtr<const FGCHandle> GetManagedAssemblyHandle() const { return ManagedAssemblyHandle; }
private:
bool ProcessTypeMetadata();
void OnModulesChanged(FName InModuleName, EModuleChangeReason InModuleChangeReason);
template<typename T = UField>
T* TryFindField(const FCSFieldName FieldName) const
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::TryFindField);
static_assert(TIsDerivedFrom<T, UObject>::Value, "T must be a UObject-derived type.");
if (!FieldName.IsValid())
{
UE_LOGFMT(LogUnrealSharp, Warning, "Invalid field name: {0}", *FieldName.GetName());
return nullptr;
}
UPackage* Package = FieldName.GetPackage();
if (!IsValid(Package))
{
UE_LOGFMT(LogUnrealSharp, Warning, "Failed to find package for field: {0}", *FieldName.GetName());
return nullptr;
}
return FindObject<T>(Package, *FieldName.GetName());
}
// All Unreal types that are defined in this assembly.
TMap<FCSFieldName, TSharedPtr<FCSManagedTypeInfo>> AllTypes;
// All handles allocated by this assembly. Handles to types, methods, objects.
TArray<TSharedPtr<FGCHandle>> AllocatedManagedHandles;
// Handles to all allocated UTypes (UClass/UStruct, etc) that are defined in this assembly.
TMap<FCSFieldName, TSharedPtr<FGCHandle>> ManagedClassHandles;
// Pending classes that are waiting for their parent class to be loaded by the engine.
TMap<FCSTypeReferenceMetaData, TSet<FCSClassInfo*>> PendingClasses;
// Handle to the Assembly object in C#.
TSharedPtr<FGCHandle> ManagedAssemblyHandle;
// Full path to the assembly file.
FString AssemblyPath;
// Assembly file name without the path.
FName AssemblyName;
bool bIsLoading = false;
};

View File

@ -0,0 +1,14 @@
#include "CSFieldName.h"
#include "UnrealSharpUtilities/UnrealSharpUtils.h"
#include "Utils/CSClassUtilities.h"
FCSFieldName::FCSFieldName(UField* Field)
{
if (UClass* Class = Cast<UClass>(Field))
{
Field = FCSClassUtilities::GetFirstNativeClass(Class);
}
Name = Field->GetFName();
Namespace = FCSUnrealSharpUtils::GetNamespace(Field);
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "CSNamespace.h"
struct UNREALSHARPCORE_API FCSFieldName
{
FCSFieldName() = default;
FCSFieldName(FName Name, FName Namespace) : Name(Name), Namespace(Namespace) {}
FCSFieldName(UField* Field);
FName GetFName() const { return Name; }
FString GetName() const { return Name.ToString(); }
bool IsValid() const { return Name != NAME_None; }
FCSNamespace GetNamespace() const { return Namespace; }
UPackage* GetPackage() const { return Namespace.GetPackage(); }
FName GetPackageName() const { return Namespace.GetPackageName(); }
FName GetFullName() const
{
return *FString::Printf(TEXT("%s.%s"), *Namespace.GetName(), *Name.ToString());
}
bool operator == (const FCSFieldName& Other) const
{
return Name == Other.Name && Namespace == Other.Namespace;
}
friend uint32 GetTypeHash(const FCSFieldName& Field)
{
return GetTypeHash(Field.Name) ^ GetTypeHash(Field.Namespace);
}
private:
FName Name;
FCSNamespace Namespace;
};

View File

@ -0,0 +1,50 @@
#pragma once
#if !defined(_WIN32)
#define __stdcall
#endif
struct FScopedGCHandle;
struct FInvokeManagedMethodData;
struct FGCHandleIntPtr;
struct FGCHandle;
class UNREALSHARPCORE_API FCSManagedCallbacks
{
public:
struct FManagedCallbacks
{
using ManagedCallbacks_CreateNewManagedObject = FGCHandleIntPtr(__stdcall*)(const void*, void*, TCHAR**);
using ManagedCallbacks_CreateNewManagedObjectWrapper = FGCHandleIntPtr(__stdcall*)(void*, void*);
using ManagedCallbacks_InvokeManagedEvent = int(__stdcall*)(void*, void*, void*, void*, void*);
using ManagedCallbacks_InvokeDelegate = int(__stdcall*)(FGCHandleIntPtr);
using ManagedCallbacks_LookupMethod = uint8*(__stdcall*)(void*, const TCHAR*);
using ManagedCallbacks_LookupType = uint8*(__stdcall*)(uint8*, const TCHAR*);
using ManagedCallbacks_Dispose = void(__stdcall*)(FGCHandleIntPtr, FGCHandleIntPtr);
using ManagedCallbacks_FreeHandle = void(__stdcall*)(FGCHandleIntPtr);
ManagedCallbacks_CreateNewManagedObject CreateNewManagedObject;
ManagedCallbacks_CreateNewManagedObjectWrapper CreateNewManagedObjectWrapper;
ManagedCallbacks_InvokeManagedEvent InvokeManagedMethod;
ManagedCallbacks_InvokeDelegate InvokeDelegate;
ManagedCallbacks_LookupMethod LookupManagedMethod;
ManagedCallbacks_LookupType LookupManagedType;
private:
//Only call these from GCHandles.
friend FGCHandle;
friend FScopedGCHandle;
ManagedCallbacks_Dispose Dispose;
ManagedCallbacks_FreeHandle FreeHandle;
};
static inline FManagedCallbacks ManagedCallbacks;
};

View File

@ -0,0 +1,26 @@
#include "CSManagedDelegate.h"
#include "CSManager.h"
void FCSManagedDelegate::Invoke(UObject* WorldContextObject, bool bDispose)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FCSManagedDelegate::Invoke);
if (CallbackHandle.IsNull())
{
UE_LOGFMT(LogUnrealSharp, Warning, "FCSManagedDelegate::Invoke: CallbackHandle is null");
return;
}
if (IsValid(WorldContextObject))
{
UCSManager::Get().SetCurrentWorldContext(WorldContextObject);
}
FCSManagedCallbacks::ManagedCallbacks.InvokeDelegate(CallbackHandle.GetHandle());
if (bDispose)
{
Dispose();
}
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "CSManagedGCHandle.h"
struct UNREALSHARPCORE_API FCSManagedDelegate
{
FCSManagedDelegate(const FGCHandle& ManagedDelegate)
: CallbackHandle(ManagedDelegate)
{
}
FCSManagedDelegate()
{
}
void Invoke(UObject* WorldContextObject = nullptr, bool bDispose = true);
void Dispose() { CallbackHandle.Dispose(); }
private:
FGCHandle CallbackHandle;
};

View File

@ -0,0 +1,124 @@
#pragma once
#include "CSManagedCallbacksCache.h"
#include "CSManagedGCHandle.generated.h"
enum class GCHandleType : char
{
Null,
StrongHandle,
WeakHandle,
PinnedHandle,
};
struct FGCHandleIntPtr
{
bool operator == (const FGCHandleIntPtr& Other) const
{
return IntPtr == Other.IntPtr;
}
bool operator != (const FGCHandleIntPtr& Other) const
{
return IntPtr != Other.IntPtr;
}
// Pointer to the managed object in C#
uint8* IntPtr = nullptr;
};
static_assert(sizeof(FGCHandleIntPtr) == sizeof(void *));
struct FGCHandle
{
FGCHandleIntPtr Handle;
GCHandleType Type = GCHandleType::Null;
static FGCHandle Null() { return FGCHandle(nullptr, GCHandleType::Null); }
bool IsNull() const { return !Handle.IntPtr; }
bool IsWeakPointer() const { return Type == GCHandleType::WeakHandle; }
FGCHandleIntPtr GetHandle() const { return Handle; }
uint8* GetPointer() const { return Handle.IntPtr; };
void Dispose(FGCHandleIntPtr AssemblyHandle = FGCHandleIntPtr())
{
if (!Handle.IntPtr || Type == GCHandleType::Null)
{
return;
}
FCSManagedCallbacks::ManagedCallbacks.Dispose(Handle, AssemblyHandle);
Handle.IntPtr = nullptr;
Type = GCHandleType::Null;
}
void operator = (const FGCHandle& Other)
{
Handle = Other.Handle;
Type = Other.Type;
}
operator void*() const
{
return Handle.IntPtr;
}
FGCHandle(){}
FGCHandle(const FGCHandleIntPtr InHandle, const GCHandleType InType) : Handle(InHandle), Type(InType) {}
FGCHandle(uint8* InHandle, const GCHandleType InType) : Type(InType)
{
Handle.IntPtr = InHandle;
}
FGCHandle(const FGCHandleIntPtr InHandle) : Handle(InHandle)
{
Type = GCHandleType::Null;
}
};
struct FScopedGCHandle
{
FGCHandleIntPtr Handle;
explicit FScopedGCHandle(FGCHandleIntPtr InHandle) : Handle(InHandle) {}
FScopedGCHandle(const FScopedGCHandle&) = delete;
FScopedGCHandle(FScopedGCHandle&&) = delete;
~FScopedGCHandle()
{
if (Handle.IntPtr != nullptr)
{
FCSManagedCallbacks::ManagedCallbacks.FreeHandle(Handle);
}
}
FScopedGCHandle& operator=(const FScopedGCHandle&) = delete;
FScopedGCHandle& operator=(FScopedGCHandle&&) = delete;
};
USTRUCT()
struct FSharedGCHandle
{
GENERATED_BODY()
FSharedGCHandle() = default;
explicit FSharedGCHandle(FGCHandleIntPtr InHandle) : Handle(MakeShared<FScopedGCHandle>(InHandle)) {}
FGCHandleIntPtr GetHandle() const
{
if (Handle == nullptr)
{
return FGCHandleIntPtr();
}
return Handle->Handle;
}
private:
TSharedPtr<FScopedGCHandle> Handle;
};

View File

@ -0,0 +1,678 @@
#include "CSManager.h"
#include "CSManagedGCHandle.h"
#include "CSAssembly.h"
#include "UnrealSharpCore.h"
#include "TypeGenerator/CSClass.h"
#include "Misc/Paths.h"
#include "Misc/App.h"
#include "UObject/Object.h"
#include "Misc/MessageDialog.h"
#include "Engine/Blueprint.h"
#include "UnrealSharpProcHelper/CSProcHelper.h"
#include <vector>
#include "CSBindsManager.h"
#include "CSNamespace.h"
#include "CSUnrealSharpSettings.h"
#include "Engine/UserDefinedEnum.h"
#include "Logging/StructuredLog.h"
#include "StructUtils/UserDefinedStruct.h"
#include "TypeGenerator/CSInterface.h"
#include "TypeGenerator/Factories/CSPropertyFactory.h"
#include "TypeGenerator/Register/CSBuilderManager.h"
#include "TypeGenerator/Register/TypeInfo/CSClassInfo.h"
#include "Utils/CSClassUtilities.h"
#ifdef _WIN32
#define PLATFORM_STRING(string) string
#elif defined(__unix__)
#define PLATFORM_STRING(string) TCHAR_TO_ANSI(string)
#elif defined(__APPLE__)
#define PLATFORM_STRING(string) TCHAR_TO_ANSI(string)
#endif
#ifdef __clang__
#pragma clang diagnostic ignored "-Wdangling-assignment"
#endif
UCSManager* UCSManager::Instance = nullptr;
UPackage* UCSManager::FindOrAddManagedPackage(const FCSNamespace Namespace)
{
if (UPackage* NativePackage = Namespace.TryGetAsNativePackage())
{
return NativePackage;
}
FCSNamespace CurrentNamespace = Namespace;
TArray<FCSNamespace> ParentNamespaces;
while (true)
{
ParentNamespaces.Add(CurrentNamespace);
if (!CurrentNamespace.GetParentNamespace(CurrentNamespace))
{
break;
}
}
UPackage* ParentPackage = nullptr;
for (int32 i = ParentNamespaces.Num() - 1; i >= 0; i--)
{
FCSNamespace ParentNamespace = ParentNamespaces[i];
FName PackageName = ParentNamespace.GetPackageName();
for (UPackage* Package : AllPackages)
{
if (PackageName == Package->GetFName())
{
ParentPackage = Package;
break;
}
}
if (!ParentPackage)
{
ParentPackage = NewObject<UPackage>(nullptr, PackageName, RF_Public);
ParentPackage->SetPackageFlags(PKG_CompiledIn);
AllPackages.Add(ParentPackage);
}
}
return ParentPackage;
}
void UCSManager::ForEachManagedField(const TFunction<void(UObject*)>& Callback) const
{
for (UPackage* Package : AllPackages)
{
ForEachObjectWithPackage(Package, [&Callback](UObject* Object)
{
Callback(Object);
return true;
}, false);
}
}
UPackage* UCSManager::GetPackage(const FCSNamespace Namespace)
{
UPackage* FoundPackage;
if (GetDefault<UCSUnrealSharpSettings>()->HasNamespaceSupport())
{
FoundPackage = FindOrAddManagedPackage(Namespace);
}
else
{
FoundPackage = GetGlobalManagedPackage();
}
return FoundPackage;
}
bool UCSManager::IsLoadingAnyAssembly() const
{
for (const TPair<FName, TObjectPtr<UCSAssembly>>& LoadedAssembly : LoadedAssemblies)
{
UCSAssembly* AssemblyPtr = LoadedAssembly.Value;
if (IsValid(AssemblyPtr) && AssemblyPtr->IsLoading())
{
return true;
}
}
return false;
}
void UCSManager::AddDynamicSubsystemClass(TSubclassOf<UDynamicSubsystem> SubsystemClass)
{
if (!IsValid(SubsystemClass))
{
UE_LOG(LogUnrealSharp, Warning, TEXT("Tried to add an invalid dynamic subsystem class"));
return;
}
if (!PendingDynamicSubsystemClasses.Contains(SubsystemClass))
{
PendingDynamicSubsystemClasses.Add(SubsystemClass);
}
TryInitializeDynamicSubsystems();
}
void UCSManager::Initialize()
{
#if WITH_EDITOR
FString DotNetInstallationPath = FCSProcHelper::GetDotNetDirectory();
if (DotNetInstallationPath.IsEmpty())
{
FString DialogText = FString::Printf(TEXT("UnrealSharp can't be initialized. An installation of .NET %s SDK can't be found on your system."), TEXT(DOTNET_MAJOR_VERSION));
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(DialogText));
return;
}
FString UnrealSharpLibraryPath = FCSProcHelper::GetUnrealSharpPluginsPath();
if (!FPaths::FileExists(UnrealSharpLibraryPath))
{
FString FullPath = FPaths::ConvertRelativePathToFull(UnrealSharpLibraryPath);
FString DialogText = FString::Printf(TEXT(
"The bindings library could not be found at the following location:\n%s\n\n"
"Most likely, the bindings library failed to build due to invalid generated glue."
), *FullPath);
FMessageDialog::Open(EAppMsgType::Ok, FText::FromString(DialogText));
return;
}
TArray<FString> ProjectPaths;
FCSProcHelper::GetAllProjectPaths(ProjectPaths);
// Compile the C# project for any changes done outside the editor.
if (!ProjectPaths.IsEmpty() && !FApp::IsUnattended() && !FCSProcHelper::InvokeUnrealSharpBuildTool(BUILD_ACTION_BUILD_WEAVE))
{
Initialize();
return;
}
// Remove this listener when the engine is shutting down.
// Otherwise, we'll get a crash when the GC cleans up all the UObject.
FCoreDelegates::OnPreExit.AddUObject(this, &UCSManager::OnEnginePreExit);
#endif
TypeBuilderManager = NewObject<UCSTypeBuilderManager>(this);
TypeBuilderManager->Initialize();
GUObjectArray.AddUObjectDeleteListener(this);
// Initialize the C# runtime.
if (!InitializeDotNetRuntime())
{
return;
}
GlobalManagedPackage = FindOrAddManagedPackage(FCSNamespace(TEXT("UnrealSharp")));
// Initialize the property factory. This is used to create properties for managed structs/classes/functions.
FCSPropertyFactory::Initialize();
// Try to load the user assembly. Can be empty if the user hasn't created any csproj yet.
LoadAllUserAssemblies();
FModuleManager::Get().OnModulesChanged().AddUObject(this, &UCSManager::OnModulesChanged);
}
bool UCSManager::InitializeDotNetRuntime()
{
if (!LoadRuntimeHost())
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to load Runtime Host"));
return false;
}
load_assembly_and_get_function_pointer_fn LoadAssemblyAndGetFunctionPointer = InitializeNativeHost();
if (!LoadAssemblyAndGetFunctionPointer)
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to initialize Runtime Host. Check logs for more details."));
return false;
}
const FString EntryPointClassName = TEXT("UnrealSharp.Plugins.Main, UnrealSharp.Plugins");
const FString EntryPointFunctionName = TEXT("InitializeUnrealSharp");
const FString UnrealSharpLibraryAssembly = FPaths::ConvertRelativePathToFull(FCSProcHelper::GetUnrealSharpPluginsPath());
const FString UserWorkingDirectory = FPaths::ConvertRelativePathToFull(FCSProcHelper::GetUserAssemblyDirectory());
FInitializeRuntimeHost InitializeUnrealSharp = nullptr;
const int32 ErrorCode = LoadAssemblyAndGetFunctionPointer(PLATFORM_STRING(*UnrealSharpLibraryAssembly),
PLATFORM_STRING(*EntryPointClassName),
PLATFORM_STRING(*EntryPointFunctionName),
UNMANAGEDCALLERSONLY_METHOD,
nullptr,
reinterpret_cast<void**>(&InitializeUnrealSharp));
if (ErrorCode != 0)
{
UE_LOGFMT(LogUnrealSharp, Fatal, "Failed to load assembly: {0}", ErrorCode);
return false;
}
// Entry point to C# to initialize UnrealSharp
if (!InitializeUnrealSharp(*UserWorkingDirectory,
*UnrealSharpLibraryAssembly,
&ManagedPluginsCallbacks,
(const void*)&FCSBindsManager::GetBoundFunction,
&FCSManagedCallbacks::ManagedCallbacks))
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to initialize UnrealSharp!"));
return false;
}
return true;
}
bool UCSManager::LoadRuntimeHost()
{
const FString RuntimeHostPath = FCSProcHelper::GetRuntimeHostPath();
if (!FPaths::FileExists(RuntimeHostPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("Couldn't find Hostfxr.dll"));
return false;
}
RuntimeHost = FPlatformProcess::GetDllHandle(*RuntimeHostPath);
if (RuntimeHost == nullptr)
{
UE_LOG(LogUnrealSharp, Fatal, TEXT("Failed to get the RuntimeHost DLL handle!"));
return false;
}
#if defined(_WIN32)
void* DLLHandle = FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_initialize_for_dotnet_command_line"));
Hostfxr_Initialize_For_Dotnet_Command_Line = static_cast<hostfxr_initialize_for_dotnet_command_line_fn>(DLLHandle);
DLLHandle = FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_initialize_for_runtime_config"));
Hostfxr_Initialize_For_Runtime_Config = static_cast<hostfxr_initialize_for_runtime_config_fn>(DLLHandle);
DLLHandle = FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_get_runtime_delegate"));
Hostfxr_Get_Runtime_Delegate = static_cast<hostfxr_get_runtime_delegate_fn>(DLLHandle);
DLLHandle = FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_close"));
Hostfxr_Close = static_cast<hostfxr_close_fn>(DLLHandle);
#else
Hostfxr_Initialize_For_Dotnet_Command_Line = (hostfxr_initialize_for_dotnet_command_line_fn)FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_initialize_for_dotnet_command_line"));
Hostfxr_Initialize_For_Runtime_Config = (hostfxr_initialize_for_runtime_config_fn)FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_initialize_for_runtime_config"));
Hostfxr_Get_Runtime_Delegate = (hostfxr_get_runtime_delegate_fn)FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_get_runtime_delegate"));
Hostfxr_Close = (hostfxr_close_fn)FPlatformProcess::GetDllExport(RuntimeHost, TEXT("hostfxr_close"));
#endif
return Hostfxr_Initialize_For_Dotnet_Command_Line && Hostfxr_Get_Runtime_Delegate && Hostfxr_Close && Hostfxr_Initialize_For_Runtime_Config;
}
bool UCSManager::LoadAllUserAssemblies()
{
TArray<FString> UserAssemblyPaths;
FCSProcHelper::GetAssemblyPathsByLoadOrder(UserAssemblyPaths, true);
if (UserAssemblyPaths.IsEmpty())
{
return true;
}
for (const FString& UserAssemblyPath : UserAssemblyPaths)
{
LoadAssemblyByPath(UserAssemblyPath);
}
OnAssembliesLoaded.Broadcast();
return true;
}
void UCSManager::NotifyUObjectDeleted(const UObjectBase* Object, int32 Index)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::NotifyUObjectDeleted);
TSharedPtr<FGCHandle> Handle;
if (!ManagedObjectHandles.RemoveAndCopyValueByHash(Index, Index, Handle))
{
return;
}
UCSAssembly* Assembly = FindOwningAssembly(Object->GetClass());
if (!IsValid(Assembly))
{
FString ObjectName = Object->GetFName().ToString();
FString ClassName = Object->GetClass()->GetFName().ToString();
UE_LOG(LogUnrealSharp, Error, TEXT("Failed to find owning assembly for object %s with class %s. Will cause managed memory leak."), *ObjectName, *ClassName);
return;
}
TSharedPtr<const FGCHandle> AssemblyHandle = Assembly->GetManagedAssemblyHandle();
Handle->Dispose(AssemblyHandle->GetHandle());
TMap<uint32, TSharedPtr<FGCHandle>>* FoundHandles = ManagedInterfaceWrappers.FindByHash(Index, Index);
if (FoundHandles == nullptr)
{
return;
}
for (auto &[Key, Value] : *FoundHandles)
{
Value->Dispose(AssemblyHandle->GetHandle());
}
FoundHandles->Empty();
ManagedInterfaceWrappers.Remove(Index);
}
void UCSManager::OnModulesChanged(FName InModuleName, EModuleChangeReason InModuleChangeReason)
{
if (InModuleChangeReason != EModuleChangeReason::ModuleLoaded)
{
return;
}
TryInitializeDynamicSubsystems();
}
void UCSManager::TryInitializeDynamicSubsystems()
{
// Try to activate Editor/EngineSubsystems
for (int32 i = PendingDynamicSubsystemClasses.Num() - 1; i >= 0; --i)
{
TSubclassOf<UDynamicSubsystem> SubsystemClass = PendingDynamicSubsystemClasses[i];
if (!IsValid(SubsystemClass))
{
UE_LOG(LogUnrealSharp, Warning, TEXT("Tried to activate an invalid dynamic subsystem class"));
PendingDynamicSubsystemClasses.RemoveAt(i);
continue;
}
FSubsystemCollectionBase::ActivateExternalSubsystem(SubsystemClass);
// Unfortunately no better way to check if the subsystems actually registered.
{
if (SubsystemClass->IsChildOf(UEngineSubsystem::StaticClass()))
{
if (IsValid(GEngine) && GEngine->GetEngineSubsystemBase(SubsystemClass.Get()))
{
PendingDynamicSubsystemClasses.RemoveAt(i);
}
}
#if WITH_EDITOR
else if (SubsystemClass->IsChildOf(UEditorSubsystem::StaticClass()))
{
if (IsValid(GEditor) && GEditor->GetEditorSubsystemBase(SubsystemClass.Get()))
{
PendingDynamicSubsystemClasses.RemoveAt(i);
}
}
#endif
}
}
}
load_assembly_and_get_function_pointer_fn UCSManager::InitializeNativeHost() const
{
#if WITH_EDITOR
FString DotNetPath = FCSProcHelper::GetDotNetDirectory();
#else
FString DotNetPath = FCSProcHelper::GetPluginAssembliesPath();
#endif
if (!FPaths::DirectoryExists(DotNetPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("Dotnet directory does not exist at: %s"), *DotNetPath);
return nullptr;
}
FString RuntimeHostPath = FCSProcHelper::GetRuntimeHostPath();
if (!FPaths::FileExists(RuntimeHostPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("Runtime host path does not exist at: %s"), *RuntimeHostPath);
return nullptr;
}
UE_LOG(LogUnrealSharp, Log, TEXT("DotNetPath: %s"), *DotNetPath);
UE_LOG(LogUnrealSharp, Log, TEXT("RuntimeHostPath: %s"), *RuntimeHostPath);
hostfxr_initialize_parameters InitializeParameters;
InitializeParameters.dotnet_root = PLATFORM_STRING(*DotNetPath);
InitializeParameters.host_path = PLATFORM_STRING(*RuntimeHostPath);
InitializeParameters.size = sizeof(hostfxr_initialize_parameters);
hostfxr_handle HostFXR_Handle = nullptr;
int32 ErrorCode = 0;
#if WITH_EDITOR
FString RuntimeConfigPath = FCSProcHelper::GetRuntimeConfigPath();
if (!FPaths::FileExists(RuntimeConfigPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("No runtime config found"));
return nullptr;
}
#if defined(_WIN32)
ErrorCode = Hostfxr_Initialize_For_Runtime_Config(PLATFORM_STRING(*RuntimeConfigPath), &InitializeParameters, &HostFXR_Handle);
#else
ErrorCode = Hostfxr_Initialize_For_Runtime_Config(PLATFORM_STRING(*RuntimeConfigPath), nullptr, &HostFXR_Handle);
#endif
#else
FString PluginAssemblyPath = FCSProcHelper::GetUnrealSharpPluginsPath();
if (!FPaths::FileExists(PluginAssemblyPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("UnrealSharp.Plugins.dll does not exist at: %s"), *PluginAssemblyPath);
return nullptr;
}
std::vector Args { PLATFORM_STRING(*PluginAssemblyPath) };
#if defined(_WIN32)
ErrorCode = Hostfxr_Initialize_For_Dotnet_Command_Line(Args.size(), Args.data(), &InitializeParameters, &HostFXR_Handle);
#else
ErrorCode = Hostfxr_Initialize_For_Dotnet_Command_Line(Args.size(), const_cast<const char**>(Args.data()), &InitializeParameters, &HostFXR_Handle);
#endif
#endif
if (ErrorCode != 0)
{
UE_LOG(LogUnrealSharp, Error, TEXT("hostfxr_initialize_for_runtime_config failed with code: %d"), ErrorCode);
return nullptr;
}
void* LoadAssemblyAndGetFunctionPointer = nullptr;
ErrorCode = Hostfxr_Get_Runtime_Delegate(HostFXR_Handle, hdt_load_assembly_and_get_function_pointer, &LoadAssemblyAndGetFunctionPointer);
Hostfxr_Close(HostFXR_Handle);
if (ErrorCode != 0 || !LoadAssemblyAndGetFunctionPointer)
{
UE_LOG(LogUnrealSharp, Error, TEXT("hostfxr_get_runtime_delegate failed with code: %d"), ErrorCode);
return nullptr;
}
return (load_assembly_and_get_function_pointer_fn)LoadAssemblyAndGetFunctionPointer;
}
UCSAssembly* UCSManager::LoadAssemblyByPath(const FString& AssemblyPath, bool bIsCollectible)
{
if (!FPaths::FileExists(AssemblyPath))
{
UE_LOG(LogUnrealSharp, Error, TEXT("Assembly path does not exist: %s"), *AssemblyPath);
return nullptr;
}
FString AssemblyName = FPaths::GetBaseFilename(AssemblyPath);
UCSAssembly* ExistingAssembly = FindAssembly(FName(*AssemblyName));
if (IsValid(ExistingAssembly) && ExistingAssembly->IsValidAssembly())
{
UE_LOGFMT(LogUnrealSharp, Display, "Assembly {AssemblyName} is already loaded.", *AssemblyName);
return ExistingAssembly;
}
UCSAssembly* NewAssembly = NewObject<UCSAssembly>(this, *AssemblyName);
NewAssembly->SetAssemblyPath(AssemblyPath);
LoadedAssemblies.Add(NewAssembly->GetAssemblyName(), NewAssembly);
if (!NewAssembly->LoadAssembly(bIsCollectible))
{
return nullptr;
}
OnManagedAssemblyLoaded.Broadcast(NewAssembly->GetAssemblyName());
UE_LOGFMT(LogUnrealSharp, Display, "Successfully loaded AssemblyHandle with path {AssemblyPath}.", *AssemblyPath);
return NewAssembly;
}
UCSAssembly* UCSManager::LoadUserAssemblyByName(const FName AssemblyName, bool bIsCollectible)
{
FString AssemblyPath = FPaths::Combine(FCSProcHelper::GetUserAssemblyDirectory(), AssemblyName.ToString() + ".dll");
return LoadAssemblyByPath(AssemblyPath, bIsCollectible);
}
UCSAssembly* UCSManager::LoadPluginAssemblyByName(const FName AssemblyName, bool bIsCollectible)
{
FString AssemblyPath = FPaths::Combine(FCSProcHelper::GetPluginAssembliesPath(), AssemblyName.ToString() + ".dll");
return LoadAssemblyByPath(AssemblyPath, bIsCollectible);
}
UCSAssembly* UCSManager::FindOwningAssembly(UClass* Class)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::FindOwningAssembly);
if (ICSManagedTypeInterface* ManagedType = FCSClassUtilities::GetManagedType(Class))
{
// Fast access to the owning assembly for managed types.
return ManagedType->GetOwningAssembly();
}
Class = FCSClassUtilities::GetFirstNativeClass(Class);
uint32 ClassID = Class->GetUniqueID();
TObjectPtr<UCSAssembly> Assembly = NativeClassToAssemblyMap.FindOrAddByHash(ClassID, ClassID);
if (IsValid(Assembly))
{
return Assembly;
}
return FindOwningAssemblySlow(Class);
}
UCSAssembly * UCSManager::FindOwningAssembly(UScriptStruct* Struct)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::FindOwningAssembly);
if (const ICSManagedTypeInterface* ManagedType = Cast<ICSManagedTypeInterface>(Struct); ManagedType != nullptr)
{
// Fast access to the owning assembly for managed types.
return ManagedType->GetOwningAssembly();
}
if (const UUserDefinedStruct* UserStruct = Cast<UUserDefinedStruct>(Struct); UserStruct != nullptr)
{
// This is a Blueprint Struct and we can't use it
return nullptr;
}
uint32 ClassID = Struct->GetUniqueID();
TObjectPtr<UCSAssembly> Assembly = NativeClassToAssemblyMap.FindOrAddByHash(ClassID, ClassID);
if (IsValid(Assembly))
{
return Assembly;
}
return FindOwningAssemblySlow(Struct);
}
UCSAssembly* UCSManager::FindOwningAssembly(UEnum* Enum)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::FindOwningAssembly);
if (const ICSManagedTypeInterface* ManagedType = Cast<ICSManagedTypeInterface>(Enum); ManagedType != nullptr)
{
// Fast access to the owning assembly for managed types.
return ManagedType->GetOwningAssembly();
}
if (const UUserDefinedEnum* UserEnum = Cast<UUserDefinedEnum>(Enum); UserEnum != nullptr)
{
// This is a Blueprint Enum and we can't use it
return nullptr;
}
uint32 ClassID = Enum->GetUniqueID();
TObjectPtr<UCSAssembly> Assembly = NativeClassToAssemblyMap.FindOrAddByHash(ClassID, ClassID);
if (IsValid(Assembly))
{
return Assembly;
}
return FindOwningAssemblySlow(Enum);
}
UCSAssembly* UCSManager::FindOwningAssemblySlow(UField *Field)
{
// Slow path for native classes. This runs once per new native class.
const FCSFieldName ClassName = FCSFieldName(Field);
for (TPair<FName, TObjectPtr<UCSAssembly>>& LoadedAssembly : LoadedAssemblies)
{
if (TSharedPtr<FGCHandle> TypeHandle = LoadedAssembly.Value->TryFindTypeHandle(ClassName); !TypeHandle.IsValid() || TypeHandle->IsNull())
{
continue;
}
uint32 FieldID = Field->GetUniqueID();
NativeClassToAssemblyMap.AddByHash(FieldID, FieldID, LoadedAssembly.Value);
return LoadedAssembly.Value;
}
return nullptr;
}
FGCHandle UCSManager::FindManagedObject(const UObject* Object)
{
TRACE_CPUPROFILER_EVENT_SCOPE(UCSManager::FindManagedObject);
if (!IsValid(Object))
{
return FGCHandle::Null();
}
uint32 ObjectID = Object->GetUniqueID();
if (TSharedPtr<FGCHandle>* FoundHandle = ManagedObjectHandles.FindByHash(ObjectID, ObjectID))
{
#if WITH_EDITOR
// During full hot reload only the managed objects are GCd as we reload the assemblies.
// So the C# counterpart can be invalid even if the handle can be found, so we need to create a new one.
TSharedPtr<FGCHandle> HandlePtr = *FoundHandle;
if (HandlePtr.IsValid() && !HandlePtr->IsNull())
{
return *HandlePtr;
}
#else
return **FoundHandle;
#endif
}
// No existing handle found, we need to create a new managed object.
UCSAssembly* OwningAssembly = FindOwningAssembly(Object->GetClass());
if (!IsValid(OwningAssembly))
{
UE_LOGFMT(LogUnrealSharp, Error, "Failed to find assembly for {0}", *Object->GetName());
return FGCHandle::Null();
}
return *OwningAssembly->CreateManagedObject(Object);
}
FGCHandle UCSManager::FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* InterfaceClass)
{
if (!Object->GetClass()->ImplementsInterface(InterfaceClass))
{
return FGCHandle::Null();
}
// No existing handle found, we need to create a new managed object.
UCSAssembly* OwningAssembly = FindOwningAssembly(InterfaceClass);
if (!IsValid(OwningAssembly))
{
UE_LOGFMT(LogUnrealSharp, Error, "Failed to find assembly for {0}", *InterfaceClass->GetName());
return FGCHandle::Null();
}
TSharedPtr<FGCHandle> FoundHandle = OwningAssembly->FindOrCreateManagedInterfaceWrapper(Object, InterfaceClass);
if (!FoundHandle.IsValid())
{
return FGCHandle::Null();
}
return *FoundHandle;
}

View File

@ -0,0 +1,208 @@
#pragma once
#include <coreclr_delegates.h>
#include <hostfxr.h>
#include "CSAssembly.h"
#include "CSManagedCallbacksCache.h"
#include "CSManager.generated.h"
class UCSTypeBuilderManager;
class UCSInterface;
class UCSEnum;
class UCSScriptStruct;
class FUnrealSharpCoreModule;
class UFunctionsExporter;
struct FCSNamespace;
struct FCSTypeReferenceMetaData;
struct FCSManagedPluginCallbacks
{
using LoadPluginCallback = FGCHandleIntPtr(__stdcall*)(const TCHAR*, bool);
using UnloadPluginCallback = bool(__stdcall*)(const TCHAR*);
LoadPluginCallback LoadPlugin = nullptr;
UnloadPluginCallback UnloadPlugin = nullptr;
};
using FInitializeRuntimeHost = bool (*)(const TCHAR*, const TCHAR*, FCSManagedPluginCallbacks*, const void*, FCSManagedCallbacks::FManagedCallbacks*);
DECLARE_MULTICAST_DELEGATE_OneParam(FOnManagedAssemblyLoaded, const FName&);
DECLARE_MULTICAST_DELEGATE_OneParam(FOnManagedAssemblyUnloaded, const FName&);
DECLARE_MULTICAST_DELEGATE(FOnAssembliesReloaded);
DECLARE_MULTICAST_DELEGATE_OneParam(FCSClassEvent, UCSClass*);
DECLARE_MULTICAST_DELEGATE_OneParam(FCSStructEvent, UCSScriptStruct*);
DECLARE_MULTICAST_DELEGATE_OneParam(FCSInterfaceEvent, UCSInterface*);
DECLARE_MULTICAST_DELEGATE_OneParam(FCSEnumEvent, UCSEnum*);
UCLASS()
class UNREALSHARPCORE_API UCSManager : public UObject, public FUObjectArray::FUObjectDeleteListener
{
GENERATED_BODY()
public:
static UCSManager& GetOrCreate()
{
if (!Instance)
{
Instance = NewObject<UCSManager>(GetTransientPackage(), TEXT("CSManager"), RF_Public | RF_MarkAsRootSet);
}
return *Instance;
}
static UCSManager& Get() { return *Instance; }
// The outermost package for all managed packages. If namespace support is off, this is the only package that will be used.
UPackage* GetGlobalManagedPackage() const { return GlobalManagedPackage; }
UPackage* FindOrAddManagedPackage(FCSNamespace Namespace);
UCSAssembly* LoadAssemblyByPath(const FString& AssemblyPath, bool bIsCollectible = true);
// Load an assembly by name that exists in the ProjectRoot/Binaries/Managed folder
UCSAssembly* LoadUserAssemblyByName(const FName AssemblyName, bool bIsCollectible = true);
// Load an assembly by name that exists in the UnrealSharp/Binaries/Managed folder
UCSAssembly* LoadPluginAssemblyByName(const FName AssemblyName, bool bIsCollectible = true);
UCSAssembly* FindOwningAssembly(UClass* Class);
UCSAssembly* FindOwningAssembly(UScriptStruct* Struct);
UCSAssembly* FindOwningAssembly(UEnum* Enum);
UCSAssembly* FindAssembly(FName AssemblyName) const
{
return LoadedAssemblies.FindRef(AssemblyName);
}
UCSAssembly* FindOrLoadAssembly(FName AssemblyName)
{
if (UCSAssembly* Assembly = FindAssembly(AssemblyName))
{
return Assembly;
}
return LoadUserAssemblyByName(AssemblyName);
}
FGCHandle FindManagedObject(const UObject* Object);
FGCHandle FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* InterfaceClass);
void SetCurrentWorldContext(UObject* WorldContext) { CurrentWorldContext = WorldContext; }
UObject* GetCurrentWorldContext() const { return CurrentWorldContext.Get(); }
const FCSManagedPluginCallbacks& GetManagedPluginsCallbacks() const { return ManagedPluginsCallbacks; }
FOnManagedAssemblyLoaded& OnManagedAssemblyLoadedEvent() { return OnManagedAssemblyLoaded; }
FOnManagedAssemblyUnloaded& OnManagedAssemblyUnloadedEvent() { return OnManagedAssemblyUnloaded; }
FOnAssembliesReloaded& OnAssembliesLoadedEvent() { return OnAssembliesLoaded; }
#if WITH_EDITOR
FCSClassEvent& OnNewClassEvent() { return OnNewClass; }
FCSStructEvent& OnNewStructEvent() { return OnNewStruct; }
FCSInterfaceEvent& OnNewInterfaceEvent() { return OnNewInterface; }
FCSEnumEvent& OnNewEnumEvent() { return OnNewEnum; }
FSimpleMulticastDelegate& OnProcessedPendingClassesEvent() { return OnProcessedPendingClasses; }
#endif
void ForEachManagedPackage(const TFunction<void(UPackage*)>& Callback) const
{
for (UPackage* Package : AllPackages)
{
Callback(Package);
}
}
void ForEachManagedField(const TFunction<void(UObject*)>& Callback) const;
bool IsManagedPackage(const UPackage* Package) const { return AllPackages.Contains(Package); }
UPackage* GetPackage(const FCSNamespace Namespace);
bool IsManagedType(const UObject* Field) const { return IsManagedPackage(Field->GetOutermost()); }
bool IsLoadingAnyAssembly() const;
void AddDynamicSubsystemClass(TSubclassOf<UDynamicSubsystem> SubsystemClass);
UCSTypeBuilderManager* GetTypeBuilderManager() const { return TypeBuilderManager; }
private:
friend UCSAssembly;
friend FUnrealSharpCoreModule;
void Initialize();
static void Shutdown() { Instance = nullptr; }
load_assembly_and_get_function_pointer_fn InitializeNativeHost() const;
bool LoadRuntimeHost();
bool InitializeDotNetRuntime();
bool LoadAllUserAssemblies();
// UObjectArray listener interface
virtual void NotifyUObjectDeleted(const UObjectBase* Object, int32 Index) override;
virtual void OnUObjectArrayShutdown() override { GUObjectArray.RemoveUObjectDeleteListener(this); }
void OnEnginePreExit() { GUObjectArray.RemoveUObjectDeleteListener(this); }
// End of interface
void OnModulesChanged(FName InModuleName, EModuleChangeReason InModuleChangeReason);
void TryInitializeDynamicSubsystems();
UCSAssembly* FindOwningAssemblySlow(UField* Field);
static UCSManager* Instance;
UPROPERTY()
TArray<TObjectPtr<UPackage>> AllPackages;
UPROPERTY()
TObjectPtr<UPackage> GlobalManagedPackage;
UPROPERTY(Transient)
TArray<TSubclassOf<UDynamicSubsystem>> PendingDynamicSubsystemClasses;
UPROPERTY(Transient)
TObjectPtr<UCSTypeBuilderManager> TypeBuilderManager;
// Handles to all active UObjects that has a C# counterpart. The key is the unique ID of the UObject.
TMap<uint32, TSharedPtr<FGCHandle>> ManagedObjectHandles;
// Handles all active UObjects that have interface wrappers in C#. The primary key is the unique ID of the UObject.
// The second key is the unique ID of the interface class.
TMap<uint32, TMap<uint32, TSharedPtr<FGCHandle>>> ManagedInterfaceWrappers;
// Map to cache assemblies that native classes are associated with, for quick lookup.
UPROPERTY()
TMap<uint32, TObjectPtr<UCSAssembly>> NativeClassToAssemblyMap;
UPROPERTY()
TMap<FName, TObjectPtr<UCSAssembly>> LoadedAssemblies;
TWeakObjectPtr<UObject> CurrentWorldContext;
FOnManagedAssemblyLoaded OnManagedAssemblyLoaded;
FOnManagedAssemblyUnloaded OnManagedAssemblyUnloaded;
FOnAssembliesReloaded OnAssembliesLoaded;
#if WITH_EDITORONLY_DATA
FCSClassEvent OnNewClass;
FCSStructEvent OnNewStruct;
FCSInterfaceEvent OnNewInterface;
FCSEnumEvent OnNewEnum;
FSimpleMulticastDelegate OnProcessedPendingClasses;
#endif
FCSManagedPluginCallbacks ManagedPluginsCallbacks;
//.NET Core Host API
hostfxr_initialize_for_dotnet_command_line_fn Hostfxr_Initialize_For_Dotnet_Command_Line = nullptr;
hostfxr_initialize_for_runtime_config_fn Hostfxr_Initialize_For_Runtime_Config = nullptr;
hostfxr_get_runtime_delegate_fn Hostfxr_Get_Runtime_Delegate = nullptr;
hostfxr_close_fn Hostfxr_Close = nullptr;
void* RuntimeHost = nullptr;
//End
};

View File

@ -0,0 +1,35 @@
#include "CSNamespace.h"
#include "CSManager.h"
FString FCSNamespace::GetLastNamespace() const
{
FString NamespaceString = Namespace.ToString();
int32 LastDotIndex = NamespaceString.Find(TEXT("."), ESearchCase::CaseSensitive, ESearchDir::FromEnd);
if (LastDotIndex == INDEX_NONE)
{
return NamespaceString;
}
return NamespaceString.Right(NamespaceString.Len() - LastDotIndex - 1);
}
bool FCSNamespace::GetParentNamespace(FCSNamespace& OutParent) const
{
FString NamespaceString = Namespace.ToString();
int32 LastDotIndex = NamespaceString.Find(".", ESearchCase::CaseSensitive, ESearchDir::FromEnd);
if (LastDotIndex == INDEX_NONE)
{
return false;
}
FString ParentNamespace = NamespaceString.Left(LastDotIndex);
OutParent = FCSNamespace(*ParentNamespace);
return true;
}
UPackage* FCSNamespace::GetPackage() const
{
return UCSManager::Get().FindOrAddManagedPackage(*this);
}

View File

@ -0,0 +1,47 @@
#pragma once
struct FCSNamespace
{
FCSNamespace(FName InNamespace = NAME_None) : Namespace(InNamespace)
{
}
// Get the namespace as a FName
FName GetFName() const { return Namespace; }
// Get the namespace as a string
FString GetName() const { return Namespace.ToString(); }
// Gets the name of the last part of the namespace. For example, if the namespace is "UnrealSharp.Core", this will return "Core".
FString GetLastNamespace() const;
bool GetParentNamespace(FCSNamespace& OutParent) const;
bool IsValid() const { return Namespace != NAME_None; }
UPackage* GetPackage() const;
UPackage* TryGetAsNativePackage() const
{
FString NativePackageName = FString::Printf(TEXT("/Script/%s"), *GetLastNamespace());
return FindPackage(nullptr, *NativePackageName);
}
FName GetPackageName() const { return *FString::Printf(TEXT("/Script/%s"), *Namespace.ToString()); }
static FCSNamespace Invalid() { return FCSNamespace(); }
bool operator == (const FCSNamespace& Other) const
{
return Namespace == Other.Namespace;
}
friend uint32 GetTypeHash(const FCSNamespace& InNamespace)
{
return GetTypeHash(InNamespace.Namespace);
}
private:
FName Namespace;
};

View File

@ -0,0 +1,59 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include <array>
#include "CoreMinimal.h"
#include "CSUnmanagedDataStore.generated.h"
USTRUCT()
struct FUnmanagedDataStore
{
GENERATED_BODY()
private:
static constexpr size_t SmallStorageSize = 56;
using FSmallStorage = std::array<std::byte, SmallStorageSize>;
struct FLargeStorageDeleter
{
void operator()(void* Ptr) const
{
FMemory::Free(Ptr);
}
};
public:
FUnmanagedDataStore() = default;
void CopyDataIn(const void* InData, const size_t Size)
{
if (Size <= SmallStorageSize)
{
Data.Emplace<FSmallStorage>();
FMemory::Memcpy(Data.Get<FSmallStorage>().data(), InData, Size);
}
else
{
Data.Emplace<TSharedPtr<void>>(FMemory::Malloc(Size), FLargeStorageDeleter());
FMemory::Memcpy(Data.Get<TSharedPtr<void>>().Get(), InData, Size);
}
}
void CopyDataOut(void* OutData, const size_t Size) const
{
if (Size <= SmallStorageSize)
{
FMemory::Memcpy(OutData, Data.Get<FSmallStorage>().data(), Size);
}
else
{
FMemory::Memcpy(OutData, Data.Get<TSharedPtr<void>>().Get(), Size);
}
}
private:
TVariant<FSmallStorage, TSharedPtr<void>> Data;
};

View File

@ -0,0 +1,55 @@
#include "CSUnrealSharpSettings.h"
UCSUnrealSharpSettings::UCSUnrealSharpSettings()
{
CategoryName = "Plugins";
}
#if WITH_EDITOR
void UCSUnrealSharpSettings::PreEditChange(FProperty* PropertyAboutToChange)
{
Super::PreEditChange(PropertyAboutToChange);
if (PropertyAboutToChange->GetFName() == GET_MEMBER_NAME_CHECKED(UCSUnrealSharpSettings, bEnableNamespaceSupport))
{
OldValueOfNamespaceSupport = bEnableNamespaceSupport;
}
}
void UCSUnrealSharpSettings::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
if (PropertyChangedEvent.Property)
{
const FName PropertyName = PropertyChangedEvent.Property->GetFName();
if (PropertyName == GET_MEMBER_NAME_CHECKED(UCSUnrealSharpSettings, bEnableNamespaceSupport))
{
bRecentlyChangedNamespaceSupport = true;
FText Message = FText::FromString(
TEXT("Namespace support settings have been updated. A restart is required for the changes to take effect.\n\n"
"WARNING: This experimental feature will break existing Blueprints derived from C# classes due to changes in the outermost package when restarting the engine.\n\n"
"Press 'Cancel' to revert these changes.")
);
if (FMessageDialog::Open(EAppMsgType::OkCancel, Message) == EAppReturnType::Cancel)
{
bEnableNamespaceSupport = OldValueOfNamespaceSupport;
bRecentlyChangedNamespaceSupport = false;
}
}
}
}
#endif
bool UCSUnrealSharpSettings::HasNamespaceSupport() const
{
if (bRecentlyChangedNamespaceSupport)
{
// Keep returning the old value until we have restarted the editor
return OldValueOfNamespaceSupport;
}
return bEnableNamespaceSupport;
}

View File

@ -0,0 +1,39 @@
#pragma once
#include "CoreMinimal.h"
#include "Engine/DeveloperSettings.h"
#include "CSUnrealSharpSettings.generated.h"
UCLASS(config = UnrealSharp, defaultconfig, meta = (DisplayName = "UnrealSharp Settings"))
class UNREALSHARPCORE_API UCSUnrealSharpSettings : public UDeveloperSettings
{
GENERATED_BODY()
public:
UCSUnrealSharpSettings();
#if WITH_EDITOR
// UObject interface
virtual void PreEditChange(FProperty* PropertyAboutToChange) override;
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
// End of UObject interface
#endif
// Should we exit PIE when an exception is thrown in C#?
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Debugging")
bool bCrashOnException = true;
bool HasNamespaceSupport() const;
protected:
// Should we enable namespace support for generated types?
// If false, all types will be generated in the global package and all types need to have unique names.
// Currently destructive to the project if changed after BPs of C# types have been created.
UPROPERTY(EditDefaultsOnly, config, Category = "UnrealSharp | Namespace", Experimental)
bool bEnableNamespaceSupport = false;
bool bRecentlyChangedNamespaceSupport = false;
bool OldValueOfNamespaceSupport = false;
};

View File

@ -0,0 +1,23 @@
#include "AsyncExporter.h"
#include "CSManagedDelegate.h"
void UAsyncExporter::RunOnThread(TWeakObjectPtr<UObject> WorldContextObject, ENamedThreads::Type Thread, FGCHandleIntPtr DelegateHandle)
{
AsyncTask(Thread, [WorldContextObject, DelegateHandle]()
{
FCSManagedDelegate ManagedDelegate = FGCHandle(DelegateHandle, GCHandleType::StrongHandle);
if (!WorldContextObject.IsValid())
{
ManagedDelegate.Dispose();
return;
}
ManagedDelegate.Invoke(WorldContextObject.Get());
});
}
int UAsyncExporter::GetCurrentNamedThread()
{
return FTaskGraphInterface::Get().GetCurrentThreadIfKnown();
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "Async/Async.h"
#include "CSManagedGCHandle.h"
#include "AsyncExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UAsyncExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void RunOnThread(TWeakObjectPtr<UObject> WorldContextObject, ENamedThreads::Type Thread, FGCHandleIntPtr DelegateHandle);
UNREALSHARP_FUNCTION()
static int GetCurrentNamedThread();
};

View File

@ -0,0 +1,11 @@
#include "CSTimerExtensions.h"
void UCSTimerExtensions::SetTimerForNextTick(FNextTickEvent NextTickEvent)
{
#if WITH_EDITOR
FFunctionGraphTask::CreateAndDispatchWhenReady([NextTickEvent]
{
GEditor->GetTimerManager()->SetTimerForNextTick(FTimerDelegate::CreateLambda(NextTickEvent));
}, TStatId(), nullptr, ENamedThreads::GameThread);
#endif
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "CSTimerExtensions.generated.h"
using FNextTickEvent = void(*)();
UCLASS()
class UNREALSHARPCORE_API UCSTimerExtensions : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void SetTimerForNextTick(FNextTickEvent NextTickEvent);
};

View File

@ -0,0 +1,43 @@
#include "FArrayPropertyExporter.h"
void UFArrayPropertyExporter::InitializeArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int Length)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.EmptyAndAddValues(Length);
}
void UFArrayPropertyExporter::EmptyArray(FArrayProperty* ArrayProperty, const void* ScriptArray)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.EmptyValues();
}
void UFArrayPropertyExporter::AddToArray(FArrayProperty* ArrayProperty, const void* ScriptArray)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.AddValue();
}
void UFArrayPropertyExporter::InsertInArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int index)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.InsertValues(index);
}
void UFArrayPropertyExporter::RemoveFromArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int index)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.RemoveValues(index);
}
void UFArrayPropertyExporter::ResizeArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int Length)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.Resize(Length);
}
void UFArrayPropertyExporter::SwapValues(FArrayProperty* ArrayProperty, const void* ScriptArray, int indexA, int indexB)
{
FScriptArrayHelper Helper(ArrayProperty, ScriptArray);
Helper.SwapValues(indexA, indexB);
}

View File

@ -0,0 +1,37 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FArrayPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFArrayPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void InitializeArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int Length);
UNREALSHARP_FUNCTION()
static void EmptyArray(FArrayProperty* ArrayProperty, const void* ScriptArray);
UNREALSHARP_FUNCTION()
static void AddToArray(FArrayProperty* ArrayProperty, const void* ScriptArray);
UNREALSHARP_FUNCTION()
static void InsertInArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int index);
UNREALSHARP_FUNCTION()
static void RemoveFromArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int index);
UNREALSHARP_FUNCTION()
static void ResizeArray(FArrayProperty* ArrayProperty, const void* ScriptArray, int Length);
UNREALSHARP_FUNCTION()
static void SwapValues(FArrayProperty* ArrayProperty, const void* ScriptArray, int indexA, int indexB);
};

View File

@ -0,0 +1,21 @@
#include "FBoolPropertyExporter.h"
bool UFBoolPropertyExporter::GetBitfieldValueFromProperty(uint8* NativeBuffer, FProperty* Property, int32 Offset)
{
// NativeBuffer won't necessarily correspond to a UObject. It might be the beginning of a native struct, for example.
check(NativeBuffer);
uint8* OffsetPointer = NativeBuffer + Offset;
check(OffsetPointer == Property->ContainerPtrToValuePtr<uint8>(NativeBuffer));
FBoolProperty* BoolProperty = CastFieldChecked<FBoolProperty>(Property);
return BoolProperty->GetPropertyValue(OffsetPointer);
}
void UFBoolPropertyExporter::SetBitfieldValueForProperty(uint8* NativeObject, FProperty* Property, int32 Offset, bool Value)
{
// NativeBuffer won't necessarily correspond to a UObject. It might be the beginning of a native struct, for example.
check(NativeObject);
uint8* OffsetPointer = NativeObject + Offset;
check(OffsetPointer == Property->ContainerPtrToValuePtr<uint8>(NativeObject));
const FBoolProperty* BoolProperty = CastFieldChecked<FBoolProperty>(Property);
BoolProperty->SetPropertyValue(OffsetPointer, Value);
}

View File

@ -0,0 +1,21 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FBoolPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFBoolPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static bool GetBitfieldValueFromProperty(uint8* NativeBuffer, FProperty* Property, int32 Offset);
UNREALSHARP_FUNCTION()
static void SetBitfieldValueForProperty(uint8* NativeObject, FProperty* Property, int32 Offset, bool Value);
};

View File

@ -0,0 +1,7 @@
#include "FCSManagedCallbacksExporter.h"
#include "CSManagedCallbacksCache.h"
FCSManagedCallbacks::FManagedCallbacks* UFCSManagedCallbacksExporter::GetManagedCallbacks()
{
return &FCSManagedCallbacks::ManagedCallbacks;
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "CSManagedCallbacksCache.h"
#include "UObject/Object.h"
#include "FCSManagedCallbacksExporter.generated.h"
class FCSManagedCallbacks;
UCLASS()
class UNREALSHARPCORE_API UFCSManagedCallbacksExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static FCSManagedCallbacks::FManagedCallbacks* GetManagedCallbacks();
};

View File

@ -0,0 +1,23 @@
#include "FCSManagerExporter.h"
#include "UnrealSharpCore/CSManager.h"
void* UFCSManagerExporter::FindManagedObject(UObject* Object)
{
return UCSManager::Get().FindManagedObject(Object);
}
void* UFCSManagerExporter::FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* NativeClass)
{
return UCSManager::Get().FindOrCreateManagedInterfaceWrapper(Object, NativeClass);
}
void* UFCSManagerExporter::GetCurrentWorldContext()
{
return UCSManager::Get().GetCurrentWorldContext();
}
void* UFCSManagerExporter::GetCurrentWorldPtr()
{
UObject* WorldContext = UCSManager::Get().GetCurrentWorldContext();
return GEngine->GetWorldFromContextObject(WorldContext, EGetWorldErrorMode::ReturnNull);
}

View File

@ -0,0 +1,28 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FCSManagerExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFCSManagerExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* FindManagedObject(UObject* Object);
UNREALSHARP_FUNCTION()
static void* FindOrCreateManagedInterfaceWrapper(UObject* Object, UClass* NativeClass);
UNREALSHARP_FUNCTION()
static void* GetCurrentWorldContext();
UNREALSHARP_FUNCTION()
static void* GetCurrentWorldPtr();
};

View File

@ -0,0 +1,6 @@
#include "FCSTypeRegistryExporter.h"
void UFCSTypeRegistryExporter::RegisterClassToFilePath(const UTF16CHAR* ClassName, const UTF16CHAR* FilePath)
{
//FCSTypeRegistry::Get().RegisterClassToFilePath(ClassName, FilePath);
}

View File

@ -0,0 +1,19 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FCSTypeRegistryExporter.generated.h"
UCLASS()
class UFCSTypeRegistryExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void RegisterClassToFilePath(const UTF16CHAR* ClassName, const UTF16CHAR* FilePath);
};

View File

@ -0,0 +1,30 @@
#include "FEditorDelegatesExporter.h"
void UFEditorDelegatesExporter::BindEndPIE(FPIEEvent Delegate, FDelegateHandle* DelegateHandle)
{
#if WITH_EDITOR
*DelegateHandle = FEditorDelegates::EndPIE.AddLambda(Delegate);
#endif
}
void UFEditorDelegatesExporter::BindStartPIE(FPIEEvent Delegate, FDelegateHandle* DelegateHandle)
{
#if WITH_EDITOR
*DelegateHandle = FEditorDelegates::BeginPIE.AddLambda(Delegate);
#endif
}
void UFEditorDelegatesExporter::UnbindStartPIE(FDelegateHandle DelegateHandle)
{
#if WITH_EDITOR
FEditorDelegates::BeginPIE.Remove(DelegateHandle);
#endif
}
void UFEditorDelegatesExporter::UnbindEndPIE(FDelegateHandle DelegateHandle)
{
#if WITH_EDITOR
FEditorDelegates::EndPIE.Remove(DelegateHandle);
#endif
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FEditorDelegatesExporter.generated.h"
using FPIEEvent = void(*)(bool);
UCLASS()
class UNREALSHARPCORE_API UFEditorDelegatesExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void BindEndPIE(FPIEEvent Delegate, FDelegateHandle* DelegateHandle);
UNREALSHARP_FUNCTION()
static void BindStartPIE(FPIEEvent Delegate, FDelegateHandle* DelegateHandle);
UNREALSHARP_FUNCTION()
static void UnbindEndPIE(FDelegateHandle DelegateHandle);
UNREALSHARP_FUNCTION()
static void UnbindStartPIE(FDelegateHandle DelegateHandle);
};

View File

@ -0,0 +1,31 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FFieldPathExporter.h"
bool UFFieldPathExporter::IsValid(const TFieldPath<FField>& FieldPath)
{
return FieldPath != nullptr;
}
bool UFFieldPathExporter::IsStale(const FFieldPath& FieldPath)
{
return FieldPath.IsStale();
}
void UFFieldPathExporter::FieldPathToString(const FFieldPath& FieldPath, FString* OutString)
{
*OutString = FieldPath.ToString();
}
bool UFFieldPathExporter::FieldPathsEqual(const FFieldPath& A, const FFieldPath& B)
{
return A == B;
}
int32 UFFieldPathExporter::GetFieldPathHashCode(const FFieldPath& FieldPath)
{
// GetHashCode returns a signed integer in C#, but GetTypeHash returns an unsigned integer, thus
// the cast is necessary
return static_cast<int32>(GetTypeHash(FieldPath));
}

View File

@ -0,0 +1,30 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FFieldPathExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFFieldPathExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static bool IsValid(const TFieldPath<FField>& FieldPath);
UNREALSHARP_FUNCTION()
static bool IsStale(const FFieldPath& FieldPath);
UNREALSHARP_FUNCTION()
static void FieldPathToString(const FFieldPath& FieldPath, FString* OutString);
UNREALSHARP_FUNCTION()
static bool FieldPathsEqual(const FFieldPath& A, const FFieldPath& B);
UNREALSHARP_FUNCTION()
static int32 GetFieldPathHashCode(const FFieldPath& FieldPath);
};

View File

@ -0,0 +1,38 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FInstancedStructExporter.h"
#include "StructUtils/InstancedStruct.h"
const UScriptStruct* UFInstancedStructExporter::GetNativeStruct(const FInstancedStruct& Struct)
{
check(&Struct != nullptr);
return Struct.GetScriptStruct();
}
void UFInstancedStructExporter::NativeInit(FInstancedStruct& Struct)
{
std::construct_at(&Struct);
}
void UFInstancedStructExporter::NativeCopy(FInstancedStruct& Dest, const FInstancedStruct& Src)
{
std::construct_at(&Dest, Src);
}
void UFInstancedStructExporter::NativeDestroy(FInstancedStruct& Struct)
{
std::destroy_at(&Struct);
}
void UFInstancedStructExporter::InitializeAs(FInstancedStruct& Struct, const UScriptStruct* ScriptStruct, const uint8* StructData)
{
check(ScriptStruct != nullptr);
Struct.InitializeAs(ScriptStruct, StructData);
}
const uint8* UFInstancedStructExporter::GetMemory(const FInstancedStruct& Struct)
{
return Struct.GetMemory();
}

View File

@ -0,0 +1,37 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FInstancedStructExporter.generated.h"
struct FInstancedStruct;
/**
*
*/
UCLASS()
class UNREALSHARPCORE_API UFInstancedStructExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static const UScriptStruct* GetNativeStruct(const FInstancedStruct& Struct);
UNREALSHARP_FUNCTION()
static void NativeInit(FInstancedStruct& Struct);
UNREALSHARP_FUNCTION()
static void NativeCopy(FInstancedStruct& Dest, const FInstancedStruct& Src);
UNREALSHARP_FUNCTION()
static void NativeDestroy(FInstancedStruct& Struct);
UNREALSHARP_FUNCTION()
static void InitializeAs(FInstancedStruct& Struct, const UScriptStruct* ScriptStruct, const uint8* StructData);
UNREALSHARP_FUNCTION()
static const uint8* GetMemory(const FInstancedStruct& Struct);
};

View File

@ -0,0 +1,11 @@
#include "FMapPropertyExporter.h"
void* UFMapPropertyExporter::GetKey(FMapProperty* MapProperty)
{
return MapProperty->KeyProp;
}
void* UFMapPropertyExporter::GetValue(FMapProperty* MapProperty)
{
return MapProperty->ValueProp;
}

View File

@ -0,0 +1,20 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FMapPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFMapPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetKey(FMapProperty* MapProperty);
UNREALSHARP_FUNCTION()
static void* GetValue(FMapProperty* MapProperty);
};

View File

@ -0,0 +1,6 @@
#include "FMatrixExporter.h"
void UFMatrixExporter::FromRotator(FMatrix* Matrix, const FRotator Rotator)
{
*Matrix = Rotator.Quaternion().ToMatrix();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FMatrixExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFMatrixExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void FromRotator(FMatrix* Matrix, const FRotator Rotator);
};

View File

@ -0,0 +1,9 @@
#include "FMsgExporter.h"
void UFMsgExporter::Log(const UTF16CHAR* ManagedCategoryName, ELogVerbosity::Type Verbosity, const UTF16CHAR* ManagedMessage)
{
FString Message = FString(ManagedMessage);
FName CategoryName = FName(ManagedCategoryName);
FMsg::Logf(nullptr, 0, CategoryName, Verbosity, TEXT("%s"), *Message);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FMsgExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFMsgExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void Log(const UTF16CHAR* ManagedCategoryName, ELogVerbosity::Type Verbosity, const UTF16CHAR* ManagedMessage);
};

View File

@ -0,0 +1,64 @@
#include "FMulticastDelegatePropertyExporter.h"
void UFMulticastDelegatePropertyExporter::AddDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName)
{
FScriptDelegate NewScriptDelegate = MakeScriptDelegate(Target, FunctionName);
DelegateProperty->AddDelegate(NewScriptDelegate, nullptr, Delegate);
}
bool UFMulticastDelegatePropertyExporter::IsBound(FMulticastScriptDelegate* Delegate)
{
return Delegate->IsBound();
}
void UFMulticastDelegatePropertyExporter::ToString(FMulticastScriptDelegate* Delegate, FString* OutString)
{
*OutString = Delegate->ToString<UObject>();
}
void UFMulticastDelegatePropertyExporter::RemoveDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName)
{
FScriptDelegate NewScriptDelegate = MakeScriptDelegate(Target, FunctionName);
DelegateProperty->RemoveDelegate(NewScriptDelegate, nullptr, Delegate);
}
void UFMulticastDelegatePropertyExporter::ClearDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate)
{
DelegateProperty->ClearDelegate(nullptr, Delegate);
}
void UFMulticastDelegatePropertyExporter::BroadcastDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate, void* Parameters)
{
Delegate = TryGetSparseMulticastDelegate(DelegateProperty, Delegate);
Delegate->ProcessMulticastDelegate<UObject>(Parameters);
}
bool UFMulticastDelegatePropertyExporter::ContainsDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName)
{
FScriptDelegate NewScriptDelegate = MakeScriptDelegate(Target, FunctionName);
Delegate = TryGetSparseMulticastDelegate(DelegateProperty, Delegate);
return Delegate->Contains(NewScriptDelegate);
}
void* UFMulticastDelegatePropertyExporter::GetSignatureFunction(FMulticastDelegateProperty* DelegateProperty)
{
return DelegateProperty->SignatureFunction;
}
FScriptDelegate UFMulticastDelegatePropertyExporter::MakeScriptDelegate(UObject* Target, const char* FunctionName)
{
FScriptDelegate NewDelegate;
NewDelegate.BindUFunction(Target, FunctionName);
return NewDelegate;
}
const FMulticastScriptDelegate* UFMulticastDelegatePropertyExporter::TryGetSparseMulticastDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate)
{
// If the delegate is a sparse delegate, we need to get the multicast delegate from FSparseDelegate wrapper.
if (DelegateProperty->IsA<FMulticastSparseDelegateProperty>())
{
Delegate = DelegateProperty->GetMulticastDelegate(Delegate);
}
return Delegate;
}

View File

@ -0,0 +1,58 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FMulticastDelegatePropertyExporter.generated.h"
struct Interop_FScriptDelegate
{
UObject* Object;
FName Name;
FScriptDelegate ToFScriptDelegate() const
{
FScriptDelegate NewScriptDelegate;
NewScriptDelegate.BindUFunction(Object, Name);
return NewScriptDelegate;
}
};
UCLASS()
class UNREALSHARPCORE_API UFMulticastDelegatePropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void AddDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName);
UNREALSHARP_FUNCTION()
static bool IsBound(FMulticastScriptDelegate* Delegate);
UNREALSHARP_FUNCTION()
static void ToString(FMulticastScriptDelegate* Delegate, FString* OutString);
UNREALSHARP_FUNCTION()
static void RemoveDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName);
UNREALSHARP_FUNCTION()
static void ClearDelegate(FMulticastDelegateProperty* DelegateProperty, FMulticastScriptDelegate* Delegate);
UNREALSHARP_FUNCTION()
static void BroadcastDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate, void* Parameters);
UNREALSHARP_FUNCTION()
static bool ContainsDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate, UObject* Target, const char* FunctionName);
UNREALSHARP_FUNCTION()
static void* GetSignatureFunction(FMulticastDelegateProperty* DelegateProperty);
UNREALSHARP_FUNCTION()
static FScriptDelegate MakeScriptDelegate(UObject* Target, const char* FunctionName);
UNREALSHARP_FUNCTION()
static const FMulticastScriptDelegate* TryGetSparseMulticastDelegate(FMulticastDelegateProperty* DelegateProperty, const FMulticastScriptDelegate* Delegate);
};

View File

@ -0,0 +1,17 @@
#include "FNameExporter.h"
void UFNameExporter::NameToString(FName Name, FString* OutString)
{
Name.ToString(*OutString);
}
void UFNameExporter::StringToName(FName* Name, const UTF16CHAR* String, int32 Length)
{
*Name = FName(TStringView(String, Length));
}
bool UFNameExporter::IsValid(FName Name)
{
bool bIsValid = Name.IsValid();
return bIsValid;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FNameExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFNameExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void NameToString(FName Name, FString* OutString);
UNREALSHARP_FUNCTION()
static void StringToName(FName* Name, const UTF16CHAR* String, int32 Length);
UNREALSHARP_FUNCTION()
static bool IsValid(FName Name);
};

View File

@ -0,0 +1,62 @@
#include "FOptionalPropertyExporter.h"
#include "UObject/PropertyOptional.h"
bool UFOptionalPropertyExporter::IsSet(const FOptionalProperty* OptionalProperty, const void* ScriptValue)
{
return OptionalProperty->IsSet(ScriptValue);
}
void* UFOptionalPropertyExporter::MarkSetAndGetInitializedValuePointerToReplace(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->MarkSetAndGetInitializedValuePointerToReplace(Data);
}
void UFOptionalPropertyExporter::MarkUnset(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->MarkUnset(Data);
}
const void* UFOptionalPropertyExporter::GetValuePointerForRead(const FOptionalProperty* OptionalProperty, const void* Data)
{
return OptionalProperty->GetValuePointerForRead(Data);
}
void* UFOptionalPropertyExporter::GetValuePointerForReplace(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->GetValuePointerForReplace(Data);
}
const void* UFOptionalPropertyExporter::GetValuePointerForReadIfSet(const FOptionalProperty* OptionalProperty, const void* Data)
{
return OptionalProperty->GetValuePointerForReadIfSet(Data);
}
void* UFOptionalPropertyExporter::GetValuePointerForReplaceIfSet(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->GetValuePointerForReplaceIfSet(Data);
}
void* UFOptionalPropertyExporter::GetValuePointerForReadOrReplace(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->GetValuePointerForReadOrReplace(Data);
}
void* UFOptionalPropertyExporter::GetValuePointerForReadOrReplaceIfSet(const FOptionalProperty* OptionalProperty, void* Data)
{
return OptionalProperty->GetValuePointerForReadOrReplaceIfSet(Data);
}
int32 UFOptionalPropertyExporter::CalcSize(const FOptionalProperty* OptionalProperty)
{
#if ENGINE_MINOR_VERSION >= 5
// Do we really need this? StaticLink should do this.
return OptionalProperty->CalcSize();
#else
return OptionalProperty->GetSize();
#endif
}
void UFOptionalPropertyExporter::DestructInstance(const FOptionalProperty* OptionalProperty, void* Data)
{
OptionalProperty->DestroyValueInternal(Data);
}

View File

@ -0,0 +1,47 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FOptionalPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFOptionalPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static bool IsSet(const FOptionalProperty* OptionalProperty, const void* ScriptValue);
UNREALSHARP_FUNCTION()
static void* MarkSetAndGetInitializedValuePointerToReplace(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static void MarkUnset(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static const void* GetValuePointerForRead(const FOptionalProperty* OptionalProperty, const void* Data);
UNREALSHARP_FUNCTION()
static void* GetValuePointerForReplace(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static const void* GetValuePointerForReadIfSet(const FOptionalProperty* OptionalProperty, const void* Data);
UNREALSHARP_FUNCTION()
static void* GetValuePointerForReplaceIfSet(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static void* GetValuePointerForReadOrReplace(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static void* GetValuePointerForReadOrReplaceIfSet(const FOptionalProperty* OptionalProperty, void* Data);
UNREALSHARP_FUNCTION()
static int32 CalcSize(const FOptionalProperty* OptionalProperty);
UNREALSHARP_FUNCTION()
static void DestructInstance(const FOptionalProperty* OptionalProperty, void* Data);
};

View File

@ -0,0 +1,106 @@
#include "FPropertyExporter.h"
FProperty* UFPropertyExporter::GetNativePropertyFromName(UStruct* Struct, const char* PropertyName)
{
FProperty* Property = FindFProperty<FProperty>(Struct, PropertyName);
return Property;
}
int32 UFPropertyExporter::GetPropertyOffset(FProperty* Property)
{
return Property->GetOffset_ForInternal();
}
int32 UFPropertyExporter::GetSize(FProperty* Property)
{
return Property->GetSize();
}
int32 UFPropertyExporter::GetArrayDim(FProperty* Property)
{
return Property->ArrayDim;
}
void UFPropertyExporter::DestroyValue(FProperty* Property, void* Value)
{
Property->DestroyValue(Value);
}
void UFPropertyExporter::DestroyValue_InContainer(FProperty* Property, void* Value)
{
Property->DestroyValue_InContainer(Value);
}
void UFPropertyExporter::InitializeValue(FProperty* Property, void* Value)
{
Property->InitializeValue(Value);
}
bool UFPropertyExporter::Identical(const FProperty* Property, void* ValueA, void* ValueB)
{
bool bIsIdentical = Property->Identical(ValueA, ValueB);
return bIsIdentical;
}
void UFPropertyExporter::GetInnerFields(FProperty* SetProperty, TArray<FField*>* OutFields)
{
SetProperty->GetInnerFields(*OutFields);
}
uint32 UFPropertyExporter::GetValueTypeHash(FProperty* Property, void* Source)
{
return Property->GetValueTypeHash(Source);
}
bool UFPropertyExporter::HasAnyPropertyFlags(FProperty* Property, EPropertyFlags FlagsToCheck)
{
return Property->HasAnyPropertyFlags(FlagsToCheck);
}
bool UFPropertyExporter::HasAllPropertyFlags(FProperty* Property, EPropertyFlags FlagsToCheck)
{
return Property->HasAllPropertyFlags(FlagsToCheck);
}
void UFPropertyExporter::CopySingleValue(FProperty* Property, void* Dest, void* Src)
{
Property->CopySingleValue(Dest, Src);
}
void UFPropertyExporter::GetValue_InContainer(FProperty* Property, void* Container, void* OutValue)
{
Property->GetValue_InContainer(Container, OutValue);
}
void UFPropertyExporter::SetValue_InContainer(FProperty* Property, void* Container, void* Value)
{
Property->SetValue_InContainer(Container, Value);
}
uint8 UFPropertyExporter::GetBoolPropertyFieldMaskFromName(UStruct* InStruct, const char* InPropertyName)
{
FBoolProperty* Property = FindFProperty<FBoolProperty>(InStruct, InPropertyName);
if (!Property)
{
return 0;
}
return Property->GetFieldMask();
}
int32 UFPropertyExporter::GetPropertyOffsetFromName(UStruct* InStruct, const char* InPropertyName)
{
FProperty* FoundProperty = GetNativePropertyFromName(InStruct, InPropertyName);
if (!FoundProperty)
{
return -1;
}
return GetPropertyOffset(FoundProperty);
}
int32 UFPropertyExporter::GetPropertyArrayDimFromName(UStruct* InStruct, const char* PropertyName)
{
FProperty* Property = GetNativePropertyFromName(InStruct, PropertyName);
return GetArrayDim(Property);
}

View File

@ -0,0 +1,69 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static FProperty* GetNativePropertyFromName(UStruct* Struct, const char* PropertyName);
UNREALSHARP_FUNCTION()
static int32 GetPropertyOffsetFromName(UStruct* InStruct, const char* InPropertyName);
UNREALSHARP_FUNCTION()
static int32 GetPropertyArrayDimFromName(UStruct* InStruct, const char* PropertyName);
UNREALSHARP_FUNCTION()
static int32 GetPropertyOffset(FProperty* Property);
UNREALSHARP_FUNCTION()
static int32 GetSize(FProperty* Property);
UNREALSHARP_FUNCTION()
static int32 GetArrayDim(FProperty* Property);
UNREALSHARP_FUNCTION()
static void DestroyValue(FProperty* Property, void* Value);
UNREALSHARP_FUNCTION()
static void DestroyValue_InContainer(FProperty* Property, void* Value);
UNREALSHARP_FUNCTION()
static void InitializeValue(FProperty* Property, void* Value);
UNREALSHARP_FUNCTION()
static bool Identical(const FProperty* Property, void* ValueA, void* ValueB);
UNREALSHARP_FUNCTION()
static void GetInnerFields(FProperty* SetProperty, TArray<FField*>* OutFields);
UNREALSHARP_FUNCTION()
static uint32 GetValueTypeHash(FProperty* Property, void* Source);
UNREALSHARP_FUNCTION()
static bool HasAnyPropertyFlags(FProperty* Property, EPropertyFlags FlagsToCheck);
UNREALSHARP_FUNCTION()
static bool HasAllPropertyFlags(FProperty* Property, EPropertyFlags FlagsToCheck);
UNREALSHARP_FUNCTION()
static void CopySingleValue(FProperty* Property, void* Dest, void* Src);
UNREALSHARP_FUNCTION()
static void GetValue_InContainer(FProperty* Property, void* Container, void* OutValue);
UNREALSHARP_FUNCTION()
static void SetValue_InContainer(FProperty* Property, void* Container, void* Value);
UNREALSHARP_FUNCTION()
static uint8 GetBoolPropertyFieldMaskFromName(UStruct* InStruct, const char* InPropertyName);
};

View File

@ -0,0 +1,37 @@
#include "FRandomStreamExporter.h"
void UFRandomStreamExporter::GenerateNewSeed(FRandomStream* RandomStream)
{
RandomStream->GenerateNewSeed();
}
float UFRandomStreamExporter::GetFraction(FRandomStream* RandomStream)
{
return RandomStream->GetFraction();
}
uint32 UFRandomStreamExporter::GetUnsignedInt(FRandomStream* RandomStream)
{
return RandomStream->GetUnsignedInt();
}
FVector UFRandomStreamExporter::GetUnitVector(FRandomStream* RandomStream)
{
return RandomStream->GetUnitVector();
}
int UFRandomStreamExporter::RandRange(FRandomStream* RandomStream, int32 Min, int32 Max)
{
return RandomStream->RandRange(Min, Max);
}
FVector UFRandomStreamExporter::VRandCone(FRandomStream* RandomStream, FVector Dir, float ConeHalfAngleRad)
{
return RandomStream->VRandCone(Dir, ConeHalfAngleRad);
}
FVector UFRandomStreamExporter::VRandCone2(FRandomStream* RandomStream, FVector Dir, float HorizontalConeHalfAngleRad, float VerticalConeHalfAngleRad)
{
return RandomStream->VRandCone(Dir, HorizontalConeHalfAngleRad, VerticalConeHalfAngleRad);
}

View File

@ -0,0 +1,35 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FRandomStreamExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFRandomStreamExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void GenerateNewSeed(FRandomStream* RandomStream);
UNREALSHARP_FUNCTION()
static float GetFraction(FRandomStream* RandomStream);
UNREALSHARP_FUNCTION()
static uint32 GetUnsignedInt(FRandomStream* RandomStream);
UNREALSHARP_FUNCTION()
static FVector GetUnitVector(FRandomStream* RandomStream);
UNREALSHARP_FUNCTION()
static int RandRange(FRandomStream* RandomStream, int32 Min, int32 Max);
UNREALSHARP_FUNCTION()
static FVector VRandCone(FRandomStream* RandomStream, FVector Dir, float ConeHalfAngleRad);
UNREALSHARP_FUNCTION()
static FVector VRandCone2(FRandomStream* RandomStream, FVector Dir, float HorizontalConeHalfAngleRad, float VerticalConeHalfAngleRad);
};

View File

@ -0,0 +1,8 @@
#include "FRotatorExporter.h"
void UFRotatorExporter::FromMatrix(FRotator* Rotator, const FMatrix& Matrix)
{
*Rotator = Matrix.Rotator();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FRotatorExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFRotatorExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void FromMatrix(FRotator* Rotator, const FMatrix& Matrix);
};

View File

@ -0,0 +1,21 @@
#include "FScriptArrayExporter.h"
void* UFScriptArrayExporter::GetData(FScriptArray* Instance)
{
return Instance->GetData();
}
bool UFScriptArrayExporter::IsValidIndex(FScriptArray* Instance, int32 i)
{
return Instance->IsValidIndex(i);
}
int UFScriptArrayExporter::Num(FScriptArray* Instance)
{
return Instance->Num();
}
void UFScriptArrayExporter::Destroy(FScriptArray* Instance)
{
Instance->~FScriptArray();
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FScriptArrayExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFScriptArrayExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetData(FScriptArray* Instance);
UNREALSHARP_FUNCTION()
static bool IsValidIndex(FScriptArray* Instance, int32 i);
UNREALSHARP_FUNCTION()
static int Num(FScriptArray* Instance);
UNREALSHARP_FUNCTION()
static void Destroy(FScriptArray* Instance);
};

View File

@ -0,0 +1,11 @@
#include "FScriptDelegateExporter.h"
void UFScriptDelegateExporter::BroadcastDelegate(FScriptDelegate* Delegate, void* Params)
{
Delegate->ProcessDelegate<UObject>(Params);
}
bool UFScriptDelegateExporter::IsBound(FScriptDelegate* Delegate)
{
return Delegate->IsBound();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FScriptDelegateExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFScriptDelegateExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void BroadcastDelegate(FScriptDelegate* Delegate, void* Params);
UNREALSHARP_FUNCTION()
static bool IsBound(FScriptDelegate* Delegate);
};

View File

@ -0,0 +1,65 @@
#include "FScriptMapHelperExporter.h"
void UFScriptMapHelperExporter::AddPair(FMapProperty* MapProperty, const void* Address, const void* Key, const void* Value)
{
FScriptMapHelper Helper(MapProperty, Address);
Helper.AddPair(Key, Value);
}
void* UFScriptMapHelperExporter::FindOrAdd(FMapProperty* MapProperty, const void* Address, const void* Key)
{
FScriptMapHelper Helper(MapProperty, Address);
return Helper.FindOrAdd(Key);
}
int UFScriptMapHelperExporter::Num(FMapProperty* MapProperty, const void* Address)
{
FScriptMapHelper Helper(MapProperty, Address);
return Helper.Num();
}
int UFScriptMapHelperExporter::FindMapPairIndexFromHash(FMapProperty* MapProperty, const void* Address, const void* Key)
{
FScriptMapHelper Helper(MapProperty, Address);
#if ENGINE_MINOR_VERSION >= 4
return Helper.FindMapPairIndexFromHash(Key);
#else
return Helper.FindMapIndexWithKey(Key);
#endif
}
void UFScriptMapHelperExporter::RemoveIndex(FMapProperty* MapProperty, const void* Address, int Index)
{
FScriptMapHelper Helper(MapProperty, Address);
Helper.RemoveAt(Index);
}
void UFScriptMapHelperExporter::EmptyValues(FMapProperty* MapProperty, const void* Address)
{
FScriptMapHelper Helper(MapProperty, Address);
Helper.EmptyValues();
}
void UFScriptMapHelperExporter::Remove(FMapProperty* MapProperty, const void* Address, const void* Key)
{
FScriptMapHelper Helper(MapProperty, Address);
Helper.RemovePair(Key);
}
bool UFScriptMapHelperExporter::IsValidIndex(FMapProperty* MapProperty, const void* Address, int Index)
{
FScriptMapHelper Helper(MapProperty, Address);
return Helper.IsValidIndex(Index);
}
int UFScriptMapHelperExporter::GetMaxIndex(FMapProperty* MapProperty, const void* Address)
{
FScriptMapHelper Helper(MapProperty, Address);
return Helper.GetMaxIndex();
}
void* UFScriptMapHelperExporter::GetPairPtr(FMapProperty* MapProperty, const void* Address, int Index)
{
FScriptMapHelper Helper(MapProperty, Address);
return Helper.GetPairPtr(Index);
}

View File

@ -0,0 +1,44 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FScriptMapHelperExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFScriptMapHelperExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void AddPair(FMapProperty* MapProperty, const void* Address, const void* Key, const void* Value);
UNREALSHARP_FUNCTION()
static void* FindOrAdd(FMapProperty* MapProperty, const void* Address, const void* Key);
UNREALSHARP_FUNCTION()
static int Num(FMapProperty* MapProperty, const void* Address);
UNREALSHARP_FUNCTION()
static int FindMapPairIndexFromHash(FMapProperty* MapProperty, const void* Address, const void* Key);
UNREALSHARP_FUNCTION()
static void RemoveIndex(FMapProperty* MapProperty, const void* Address, int Index);
UNREALSHARP_FUNCTION()
static void EmptyValues(FMapProperty* MapProperty, const void* Address);
UNREALSHARP_FUNCTION()
static void Remove(FMapProperty* MapProperty, const void* Address, const void* Key);
UNREALSHARP_FUNCTION()
static bool IsValidIndex(FMapProperty* MapProperty, const void* Address, int Index);
UNREALSHARP_FUNCTION()
static int GetMaxIndex(FMapProperty* MapProperty, const void* Address);
UNREALSHARP_FUNCTION()
static void* GetPairPtr(FMapProperty* MapProperty, const void* Address, int Index);
};

View File

@ -0,0 +1,52 @@
#include "FScriptSetExporter.h"
bool UFScriptSetExporter::IsValidIndex(FScriptSet* ScriptSet, int32 Index)
{
return ScriptSet->IsValidIndex(Index);
}
int UFScriptSetExporter::Num(FScriptSet* ScriptSet)
{
int Num = ScriptSet->Num();
return Num;
}
int UFScriptSetExporter::GetMaxIndex(FScriptSet* ScriptSet)
{
return ScriptSet->GetMaxIndex();
}
void* UFScriptSetExporter::GetData(int Index, FScriptSet* ScriptSet, FSetProperty* Property)
{
return ScriptSet->GetData(Index, Property->SetLayout);
}
void UFScriptSetExporter::Empty(int Slack, FScriptSet* ScriptSet, FSetProperty* Property)
{
return ScriptSet->Empty(Slack, Property->SetLayout);
}
void UFScriptSetExporter::RemoveAt(int Index, FScriptSet* ScriptSet, FSetProperty* Property)
{
return ScriptSet->RemoveAt(Index, Property->SetLayout);
}
int UFScriptSetExporter::AddUninitialized(FScriptSet* ScriptSet, FSetProperty* Property)
{
return ScriptSet->AddUninitialized(Property->SetLayout);
}
void UFScriptSetExporter::Add(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element,FGetKeyHash GetKeyHash, FEqualityFn EqualityFn, FConstructFn ConstructFn, FDestructFn DestructFn)
{
ScriptSet->Add(Element, Property->SetLayout, GetKeyHash, EqualityFn, ConstructFn, DestructFn);
}
int32 UFScriptSetExporter::FindOrAdd(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element, FGetKeyHash GetKeyHash, FEqualityFn EqualityFn, FConstructFn ConstructFn)
{
return ScriptSet->FindOrAdd(Element, Property->SetLayout, GetKeyHash, EqualityFn, ConstructFn);
}
int UFScriptSetExporter::FindIndex(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element, FGetKeyHash GetKeyHash, FEqualityFn EqualityFn)
{
return ScriptSet->FindIndex(Element, Property->SetLayout, GetKeyHash, EqualityFn);
}

View File

@ -0,0 +1,50 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FScriptSetExporter.generated.h"
using FGetKeyHash = uint32(*)(const void*);
using FEqualityFn = bool(*)(const void*, const void*);
using FConstructFn = void(*)(void*);
using FDestructFn = void(*)(void*);
UCLASS()
class UNREALSHARPCORE_API UFScriptSetExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static bool IsValidIndex(FScriptSet* ScriptSet, int32 Index);
UNREALSHARP_FUNCTION()
static int Num(FScriptSet* ScriptSet);
UNREALSHARP_FUNCTION()
static int GetMaxIndex(FScriptSet* ScriptSet);
UNREALSHARP_FUNCTION()
static void* GetData(int Index, FScriptSet* ScriptSet, FSetProperty* Property);
UNREALSHARP_FUNCTION()
static void Empty(int Slack, FScriptSet* ScriptSet, FSetProperty* Property);
UNREALSHARP_FUNCTION()
static void RemoveAt(int Index, FScriptSet* ScriptSet, FSetProperty* Property);
UNREALSHARP_FUNCTION()
static int AddUninitialized(FScriptSet* ScriptSet, FSetProperty* Property);
UNREALSHARP_FUNCTION()
static void Add(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element, FGetKeyHash GetKeyHash, FEqualityFn EqualityFn, FConstructFn ConstructFn, FDestructFn DestructFn);
UNREALSHARP_FUNCTION()
static int32 FindOrAdd(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element, FGetKeyHash GetKeyHash, FEqualityFn EqualityFn, FConstructFn ConstructFn);
UNREALSHARP_FUNCTION()
static int FindIndex(FScriptSet* ScriptSet, FSetProperty* Property, const void* Element, FGetKeyHash GetKeyHash, FEqualityFn EqualityFn);
};

View File

@ -0,0 +1,6 @@
#include "FSetPropertyExporter.h"
void* UFSetPropertyExporter::GetElement(FSetProperty* Property)
{
return Property->ElementProp;
}

View File

@ -0,0 +1,17 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FSetPropertyExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFSetPropertyExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetElement(FSetProperty* Property);
};

View File

@ -0,0 +1,13 @@
#include "FSoftObjectPtrExporter.h"
#include "UnrealSharpCore/CSManager.h"
void* UFSoftObjectPtrExporter::LoadSynchronous(const TSoftObjectPtr<UObject>* SoftObjectPtr)
{
if (SoftObjectPtr->IsNull())
{
return nullptr;
}
UObject* LoadedObject = SoftObjectPtr->LoadSynchronous();
return UCSManager::Get().FindManagedObject(LoadedObject);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FSoftObjectPtrExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFSoftObjectPtrExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* LoadSynchronous(const TSoftObjectPtr<UObject>* SoftObjectPtr);
};

View File

@ -0,0 +1,6 @@
#include "FStringExporter.h"
void UFStringExporter::MarshalToNativeString(FString* String, TCHAR* ManagedString)
{
*String = ManagedString;
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FStringExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFStringExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void MarshalToNativeString(FString* String, TCHAR* ManagedString);
};

View File

@ -0,0 +1,9 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FSubsystemCollectionBaseRefExporter.h"
USubsystem* UFSubsystemCollectionBaseRefExporter::InitializeDependency(FSubsystemCollectionBase* Collection, UClass* SubsystemClass)
{
return Collection->InitializeDependency(SubsystemClass);
}

View File

@ -0,0 +1,21 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "FSubsystemCollectionBaseRefExporter.generated.h"
/**
*
*/
UCLASS()
class UNREALSHARPCORE_API UFSubsystemCollectionBaseRefExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static USubsystem* InitializeDependency(FSubsystemCollectionBase* Collection, UClass* SubsystemClass);
};

View File

@ -0,0 +1,66 @@
#include "FTextExporter.h"
const TCHAR* UFTextExporter::ToString(FText* Text)
{
if (!Text)
{
return nullptr;
}
return *Text->ToString();
}
void UFTextExporter::ToStringView(FText* Text, const TCHAR*& OutString, int32& OutLength)
{
if (!Text)
{
OutString = nullptr;
OutLength = 0;
return;
}
const FString& AsString = Text->ToString();
OutString = *AsString;
OutLength = AsString.Len();
}
void UFTextExporter::FromString(FText* Text, const char* String)
{
if (!Text)
{
return;
}
*Text = Text->FromString(String);
}
void UFTextExporter::FromStringView(FText* Text, const TCHAR* String, int32 Length)
{
if (!Text)
{
return;
}
*Text = Text->FromStringView(FStringView(String, Length));
}
void UFTextExporter::FromName(FText* Text, FName Name)
{
if (!Text)
{
return;
}
*Text = Text->FromName(Name);
}
void UFTextExporter::CreateEmptyText(FText* Text)
{
if (!Text)
{
return;
}
*Text = FText::GetEmpty();
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FTextExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFTextExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static const TCHAR* ToString(FText* Text);
UNREALSHARP_FUNCTION()
static void ToStringView(FText* Text, const TCHAR*& OutString, int32& OutLength);
UNREALSHARP_FUNCTION()
static void FromString(FText* Text, const char* String);
UNREALSHARP_FUNCTION()
static void FromStringView(FText* Text, const TCHAR* String, int32 Length);
UNREALSHARP_FUNCTION()
static void FromName(FText* Text, FName Name);
UNREALSHARP_FUNCTION()
static void CreateEmptyText(FText* Text);
};

View File

@ -0,0 +1,6 @@
#include "FVectorExporter.h"
FVector UFVectorExporter::FromRotator(const FRotator& Rotator)
{
return Rotator.Vector();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FVectorExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFVectorExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static FVector FromRotator(const FRotator& Rotator);
};

View File

@ -0,0 +1,35 @@
#include "FWeakObjectPtrExporter.h"
#include "UnrealSharpCore/CSManager.h"
void UFWeakObjectPtrExporter::SetObject(TWeakObjectPtr<UObject>& WeakObject, UObject* Object)
{
WeakObject = Object;
}
void* UFWeakObjectPtrExporter::GetObject(TWeakObjectPtr<UObject> WeakObjectPtr)
{
if (!WeakObjectPtr.IsValid())
{
return nullptr;
}
UObject* Object = WeakObjectPtr.Get();
return UCSManager::Get().FindManagedObject(Object);
}
bool UFWeakObjectPtrExporter::IsValid(TWeakObjectPtr<UObject> WeakObjectPtr)
{
return WeakObjectPtr.IsValid();
}
bool UFWeakObjectPtrExporter::IsStale(TWeakObjectPtr<UObject> WeakObjectPtr)
{
return WeakObjectPtr.IsStale();
}
bool UFWeakObjectPtrExporter::NativeEquals(TWeakObjectPtr<UObject> A, TWeakObjectPtr<UObject> B)
{
return A == B;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FWeakObjectPtrExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UFWeakObjectPtrExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void SetObject(TWeakObjectPtr<UObject>& WeakObject, UObject* Object);
UNREALSHARP_FUNCTION()
static void* GetObject(TWeakObjectPtr<UObject> WeakObjectPtr);
UNREALSHARP_FUNCTION()
static bool IsValid(TWeakObjectPtr<UObject> WeakObjectPtr);
UNREALSHARP_FUNCTION()
static bool IsStale(TWeakObjectPtr<UObject> WeakObjectPtr);
UNREALSHARP_FUNCTION()
static bool NativeEquals(TWeakObjectPtr<UObject> A, TWeakObjectPtr<UObject> B);
};

View File

@ -0,0 +1,11 @@
#include "FWorldDelegatesExporter.h"
void UFWorldDelegatesExporter::BindOnWorldCleanup(FWorldCleanupEventDelegate Delegate, FDelegateHandle* Handle)
{
*Handle = FWorldDelegates::OnWorldCleanup.AddLambda(Delegate);
}
void UFWorldDelegatesExporter::UnbindOnWorldCleanup(const FDelegateHandle Handle)
{
FWorldDelegates::OnWorldCleanup.Remove(Handle);
}

View File

@ -0,0 +1,23 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "FWorldDelegatesExporter.generated.h"
using FWorldCleanupEventDelegate = void(*)(UWorld*, bool, bool);
UCLASS()
class UNREALSHARPCORE_API UFWorldDelegatesExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void BindOnWorldCleanup(FWorldCleanupEventDelegate Delegate, FDelegateHandle* Handle);
UNREALSHARP_FUNCTION()
static void UnbindOnWorldCleanup(FDelegateHandle Handle);
};

View File

@ -0,0 +1,18 @@
#include "GEditorExporter.h"
#include "CSManager.h"
#if WITH_EDITOR
#include "Editor.h"
#include "EditorSubsystem.h"
#endif
void* UGEditorExporter::GetEditorSubsystem(UClass* SubsystemClass)
{
#if WITH_EDITOR
const UEditorSubsystem* EditorSubsystem = GEditor->GetEditorSubsystemBase(SubsystemClass);
return UCSManager::Get().FindManagedObject(EditorSubsystem);
#else
return nullptr;
#endif
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "GEditorExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UGEditorExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetEditorSubsystem(UClass* SubsystemClass);
};

View File

@ -0,0 +1,9 @@
#include "GEngineExporter.h"
#include "Engine/Engine.h"
#include "UnrealSharpCore/CSManager.h"
void* UGEngineExporter::GetEngineSubsystem(UClass* SubsystemClass)
{
UEngineSubsystem* EngineSubsystem = GEngine->GetEngineSubsystemBase(SubsystemClass);
return UCSManager::Get().FindManagedObject(EngineSubsystem);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "GEngineExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UGEngineExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetEngineSubsystem(UClass* SubsystemClass);
};

View File

@ -0,0 +1,34 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "IRefCountedObjectExporter.h"
uint32 UIRefCountedObjectExporter::GetRefCount(const IRefCountedObject* Object)
{
if (!Object || Object->GetRefCount() == 0)
{
return 0;
}
return Object->GetRefCount();
}
uint32 UIRefCountedObjectExporter::AddRef(const IRefCountedObject* Object)
{
if (!Object || Object->GetRefCount() == 0)
{
return 0;
}
return Object->AddRef();
}
uint32 UIRefCountedObjectExporter::Release(const IRefCountedObject* Object)
{
if (!Object || Object->GetRefCount() == 0)
{
return 0;
}
return Object->Release();
}

View File

@ -0,0 +1,23 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "IRefCountedObjectExporter.generated.h"
UCLASS()
class UIRefCountedObjectExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static uint32 GetRefCount(const IRefCountedObject* Object);
UNREALSHARP_FUNCTION()
static uint32 AddRef(const IRefCountedObject* Object);
UNREALSHARP_FUNCTION()
static uint32 Release(const IRefCountedObject* Object);
};

View File

@ -0,0 +1,26 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "ManagedHandleExporter.h"
void UManagedHandleExporter::StoreManagedHandle(const FGCHandleIntPtr Handle, FSharedGCHandle& Destination)
{
Destination = FSharedGCHandle(Handle);
}
FGCHandleIntPtr UManagedHandleExporter::LoadManagedHandle(const FSharedGCHandle& Source)
{
return Source.GetHandle();
}
void UManagedHandleExporter::StoreUnmanagedMemory(const void* Source, FUnmanagedDataStore& Destination, const int32 Size)
{
check(Size > 0)
Destination.CopyDataIn(Source, Size);
}
void UManagedHandleExporter::LoadUnmanagedMemory(const FUnmanagedDataStore& Source, void* Destination, const int32 Size)
{
check(Size > 0)
Source.CopyDataOut(Destination, Size);
}

View File

@ -0,0 +1,32 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "CSManagedGCHandle.h"
#include "CSUnmanagedDataStore.h"
#include "UObject/Object.h"
#include "ManagedHandleExporter.generated.h"
/**
*
*/
UCLASS()
class UNREALSHARPCORE_API UManagedHandleExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void StoreManagedHandle(FGCHandleIntPtr Handle, FSharedGCHandle& Destination);
UNREALSHARP_FUNCTION()
static FGCHandleIntPtr LoadManagedHandle(const FSharedGCHandle& Source);
UNREALSHARP_FUNCTION()
static void StoreUnmanagedMemory(const void* Source, FUnmanagedDataStore& Destination, const int32 Size);
UNREALSHARP_FUNCTION()
static void LoadUnmanagedMemory(const FUnmanagedDataStore& Source, void* Destination, const int32 Size);
};

View File

@ -0,0 +1,29 @@
#include "TPersistentObjectPtrExporter.h"
#include "UnrealSharpCore/CSManager.h"
void UTPersistentObjectPtrExporter::FromObject(TPersistentObjectPtr<FSoftObjectPath>* Path, UObject* InObject)
{
*Path = InObject;
}
void UTPersistentObjectPtrExporter::FromSoftObjectPath(TPersistentObjectPtr<FSoftObjectPath>* Path, const FSoftObjectPath* SoftObjectPath)
{
*Path = *SoftObjectPath;
}
void* UTPersistentObjectPtrExporter::Get(TPersistentObjectPtr<FSoftObjectPath>* Path)
{
UObject* Object = Path->Get();
return UCSManager::Get().FindManagedObject(Object);
}
void* UTPersistentObjectPtrExporter::GetNativePointer(TPersistentObjectPtr<FSoftObjectPath>* Path)
{
return Path->Get();
}
void* UTPersistentObjectPtrExporter::GetUniqueID(TPersistentObjectPtr<FSoftObjectPath>* Path)
{
return &Path->GetUniqueID();
}

View File

@ -0,0 +1,31 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "TPersistentObjectPtrExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UTPersistentObjectPtrExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void FromObject(TPersistentObjectPtr<FSoftObjectPath>* Path, UObject* Object);
UNREALSHARP_FUNCTION()
static void FromSoftObjectPath(TPersistentObjectPtr<FSoftObjectPath>* Path, const FSoftObjectPath* SoftObjectPath);
UNREALSHARP_FUNCTION()
static void* Get(TPersistentObjectPtr<FSoftObjectPath>* Path);
UNREALSHARP_FUNCTION()
static void* GetNativePointer(TPersistentObjectPtr<FSoftObjectPath>* Path);
UNREALSHARP_FUNCTION()
static void* GetUniqueID(TPersistentObjectPtr<FSoftObjectPath>* Path);
};

View File

@ -0,0 +1,21 @@
#include "TSharedPtrExporter.h"
void UTSharedPtrExporter::AddSharedReference(SharedPointerInternals::TReferenceControllerBase<ESPMode::ThreadSafe>* ReferenceController)
{
if (!ReferenceController)
{
return;
}
ReferenceController->AddSharedReference();
}
void UTSharedPtrExporter::ReleaseSharedReference(SharedPointerInternals::TReferenceControllerBase<ESPMode::ThreadSafe>* ReferenceController)
{
if (!ReferenceController)
{
return;
}
ReferenceController->ReleaseSharedReference();
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "TSharedPtrExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UTSharedPtrExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void AddSharedReference(SharedPointerInternals::TReferenceControllerBase<ESPMode::ThreadSafe>* ReferenceController);
UNREALSHARP_FUNCTION()
static void ReleaseSharedReference(SharedPointerInternals::TReferenceControllerBase<ESPMode::ThreadSafe>* ReferenceController);
};

View File

@ -0,0 +1,18 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "TStrongObjectPtrExporter.h"
void UTStrongObjectPtrExporter::ConstructStrongObjectPtr(TStrongObjectPtr<UObject>* Ptr, UObject* Object)
{
static_assert(sizeof(TStrongObjectPtr<UObject>) == sizeof(UObject*), "TStrongObjectPtr<UObject> must be the same size as UObject*");
check(Ptr != nullptr);
std::construct_at(Ptr, Object);
}
void UTStrongObjectPtrExporter::DestroyStrongObjectPtr(TStrongObjectPtr<UObject>* Ptr)
{
static_assert(sizeof(TStrongObjectPtr<UObject>) == sizeof(UObject*), "TStrongObjectPtr<UObject> must be the same size as UObject*");
check(Ptr != nullptr);
std::destroy_at(Ptr);
}

View File

@ -0,0 +1,24 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UObject/Object.h"
#include "TStrongObjectPtrExporter.generated.h"
/**
*
*/
UCLASS()
class UNREALSHARPCORE_API UTStrongObjectPtrExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void ConstructStrongObjectPtr(TStrongObjectPtr<UObject>* Ptr, UObject* Object);
UNREALSHARP_FUNCTION()
static void DestroyStrongObjectPtr(TStrongObjectPtr<UObject>* Ptr);
};

View File

@ -0,0 +1,9 @@
#include "UAssetManagerExporter.h"
#include "CSManager.h"
#include "Engine/AssetManager.h"
void* UUAssetManagerExporter::GetAssetManager()
{
UAssetManager& AssetManager = UAssetManager::Get();
return UCSManager::Get().FindManagedObject(&AssetManager);
}

View File

@ -0,0 +1,19 @@
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UAssetManagerExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UUAssetManagerExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static void* GetAssetManager();
};

View File

@ -0,0 +1,64 @@
#include "UClassExporter.h"
#include "CSManager.h"
#include "UnrealSharpCore/TypeGenerator/Register/TypeInfo/CSClassInfo.h"
#include "UnrealSharpCore/UnrealSharpCore.h"
UFunction* UUClassExporter::GetNativeFunctionFromClassAndName(const UClass* Class, const char* FunctionName)
{
UFunction* Function = Class->FindFunctionByName(FunctionName);
if (!Function)
{
UE_LOG(LogUnrealSharp, Warning, TEXT("Failed to get NativeFunction. FunctionName: %hs"), FunctionName)
return nullptr;
}
return Function;
}
UFunction* UUClassExporter::GetNativeFunctionFromInstanceAndName(const UObject* NativeObject, const char* FunctionName)
{
if (!IsValid(NativeObject))
{
UE_LOG(LogUnrealSharp, Warning, TEXT("Failed to get NativeFunction. NativeObject is not valid."))
return nullptr;
}
return NativeObject->FindFunctionChecked(FunctionName);
}
void* UUClassExporter::GetDefaultFromName(const char* AssemblyName, const char* Namespace, const char* ClassName)
{
UCSAssembly* Assembly = UCSManager::Get().FindOrLoadAssembly(AssemblyName);
FCSFieldName FieldName(ClassName, Namespace);
UClass* Class = Assembly->FindType<UClass>(FieldName);
if (!IsValid(Class))
{
UE_LOGFMT(LogUnrealSharp, Warning, "Failed to get default object. ClassName: {0}", *FieldName.GetName());
return nullptr;
}
return UCSManager::Get().FindManagedObject(Class->GetDefaultObject());
}
void* UUClassExporter::GetDefaultFromInstance(UObject* Object)
{
if (!IsValid(Object))
{
return nullptr;
}
UObject* CDO;
if (UClass* Class = Cast<UClass>(Object))
{
CDO = Class->GetDefaultObject();
}
else
{
CDO = Object->GetClass()->GetDefaultObject();
}
return UCSManager::Get().FindManagedObject(CDO);
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UClassExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UUClassExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static UFunction* GetNativeFunctionFromClassAndName(const UClass* Class, const char* FunctionName);
UNREALSHARP_FUNCTION()
static UFunction* GetNativeFunctionFromInstanceAndName(const UObject* NativeObject, const char* FunctionName);
UNREALSHARP_FUNCTION()
static void* GetDefaultFromName(const char* AssemblyName, const char* Namespace, const char* ClassName);
UNREALSHARP_FUNCTION()
static void* GetDefaultFromInstance(UObject* Object);
};

View File

@ -0,0 +1,29 @@
#include "UCoreUObjectExporter.h"
#include "CSAssembly.h"
#include "CSManager.h"
#include "TypeGenerator/Register/TypeInfo/CSClassInfo.h"
UClass* UUCoreUObjectExporter::GetNativeClassFromName(const char* InAssemblyName, const char* InNamespace, const char* InClassName)
{
// This gets called by the static constructor of the class, so we can cache the class info of native classes here.
UCSAssembly* Assembly = UCSManager::Get().FindOrLoadAssembly(InAssemblyName);
FCSFieldName FieldName(InClassName, InNamespace);
TSharedPtr<FCSClassInfo> ClassInfo = Assembly->FindOrAddTypeInfo<FCSClassInfo>(FieldName);
return ClassInfo->GetFieldChecked<UClass>();
}
UClass* UUCoreUObjectExporter::GetNativeInterfaceFromName(const char* InAssemblyName, const char* InNamespace, const char* InInterfaceName)
{
UCSAssembly* Assembly = UCSManager::Get().FindOrLoadAssembly(InAssemblyName);
FCSFieldName FieldName(InInterfaceName, InNamespace);
return Assembly->FindType<UClass>(FieldName);
}
UScriptStruct* UUCoreUObjectExporter::GetNativeStructFromName(const char* InAssemblyName, const char* InNamespace, const char* InStructName)
{
UCSAssembly* Assembly = UCSManager::Get().FindOrLoadAssembly(InAssemblyName);
FCSFieldName FieldName(InStructName, InNamespace);
UScriptStruct* ScriptStruct = Assembly->FindType<UScriptStruct>(FieldName);
return ScriptStruct;
}

View File

@ -0,0 +1,22 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UCoreUObjectExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UUCoreUObjectExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static UClass* GetNativeClassFromName(const char* InAssemblyName, const char* InNamespace, const char* InClassName);
UNREALSHARP_FUNCTION()
static UClass* GetNativeInterfaceFromName(const char* InAssemblyName, const char* InNamespace, const char* InInterfaceName);
UNREALSHARP_FUNCTION()
static UScriptStruct* GetNativeStructFromName(const char* InAssemblyName, const char* InNamespace, const char* InStructName);
};

View File

@ -0,0 +1,11 @@
#include "UDataTableExporter.h"
uint8* UUDataTableExporter::GetRow(const UDataTable* DataTable, FName RowName)
{
if (!IsValid(DataTable))
{
return nullptr;
}
return DataTable->FindRowUnchecked(RowName);
}

View File

@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "CSBindsManager.h"
#include "UDataTableExporter.generated.h"
UCLASS()
class UNREALSHARPCORE_API UUDataTableExporter : public UObject
{
GENERATED_BODY()
public:
UNREALSHARP_FUNCTION()
static uint8* GetRow(const UDataTable* DataTable, FName RowName);
};

View File

@ -0,0 +1,22 @@
#include "UEnhancedInputComponentExporter.h"
#include "EnhancedInputComponent.h"
bool UUEnhancedInputComponentExporter::BindAction(UEnhancedInputComponent* InputComponent, UInputAction* InputAction, ETriggerEvent TriggerEvent, UObject* Object, const FName FunctionName, uint32* OutHandle)
{
if (!IsValid(InputComponent) || !IsValid(InputAction))
{
return false;
}
*OutHandle = InputComponent->BindAction(InputAction, TriggerEvent, Object, FunctionName).GetHandle();
return true;
}
bool UUEnhancedInputComponentExporter::RemoveBindingByHandle(UEnhancedInputComponent* InputComponent, const uint32 Handle)
{
if (!IsValid(InputComponent))
{
return false;
}
return InputComponent->RemoveBindingByHandle(Handle);
}

Some files were not shown because too many files have changed in this diff Show More