381
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSAssembly.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										381
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSAssembly.cpp
									
									
									
									
									
										Normal 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 | ||||
| } | ||||
							
								
								
									
										173
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSAssembly.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSAssembly.h
									
									
									
									
									
										Normal 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; | ||||
| }; | ||||
							
								
								
									
										14
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSFieldName.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSFieldName.cpp
									
									
									
									
									
										Normal 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); | ||||
| } | ||||
							
								
								
									
										37
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSFieldName.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSFieldName.h
									
									
									
									
									
										Normal 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; | ||||
| }; | ||||
| @ -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; | ||||
| 	 | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @ -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(); | ||||
| 	} | ||||
| } | ||||
| @ -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; | ||||
| }; | ||||
							
								
								
									
										124
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManagedGCHandle.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManagedGCHandle.h
									
									
									
									
									
										Normal 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; | ||||
| }; | ||||
							
								
								
									
										678
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										678
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManager.cpp
									
									
									
									
									
										Normal 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; | ||||
| } | ||||
							
								
								
									
										208
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSManager.h
									
									
									
									
									
										Normal 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 | ||||
| }; | ||||
							
								
								
									
										35
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSNamespace.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSNamespace.cpp
									
									
									
									
									
										Normal 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); | ||||
| } | ||||
							
								
								
									
										47
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSNamespace.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								Plugins/UnrealSharp/Source/UnrealSharpCore/CSNamespace.h
									
									
									
									
									
										Normal 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; | ||||
| }; | ||||
|  | ||||
| @ -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; | ||||
|      | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
| @ -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; | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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(); | ||||
| 	 | ||||
| }; | ||||
| @ -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 | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -0,0 +1,7 @@ | ||||
| #include "FCSManagedCallbacksExporter.h" | ||||
| #include "CSManagedCallbacksCache.h" | ||||
|  | ||||
| FCSManagedCallbacks::FManagedCallbacks* UFCSManagedCallbacksExporter::GetManagedCallbacks() | ||||
| { | ||||
| 	return &FCSManagedCallbacks::ManagedCallbacks; | ||||
| } | ||||
| @ -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(); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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(); | ||||
| 	 | ||||
| }; | ||||
| @ -0,0 +1,6 @@ | ||||
| #include "FCSTypeRegistryExporter.h" | ||||
|  | ||||
| void UFCSTypeRegistryExporter::RegisterClassToFilePath(const UTF16CHAR* ClassName, const UTF16CHAR* FilePath) | ||||
| { | ||||
| 	//FCSTypeRegistry::Get().RegisterClassToFilePath(ClassName, FilePath); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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 | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| }; | ||||
| @ -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)); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -0,0 +1,11 @@ | ||||
| #include "FMapPropertyExporter.h" | ||||
|  | ||||
| void* UFMapPropertyExporter::GetKey(FMapProperty* MapProperty) | ||||
| { | ||||
| 	return MapProperty->KeyProp; | ||||
| } | ||||
|  | ||||
| void* UFMapPropertyExporter::GetValue(FMapProperty* MapProperty) | ||||
| { | ||||
| 	return MapProperty->ValueProp; | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -0,0 +1,6 @@ | ||||
| #include "FMatrixExporter.h" | ||||
|  | ||||
| void UFMatrixExporter::FromRotator(FMatrix* Matrix, const FRotator Rotator) | ||||
| { | ||||
| 	*Matrix = Rotator.Quaternion().ToMatrix(); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -0,0 +1,8 @@ | ||||
| #include "FRotatorExporter.h" | ||||
|  | ||||
| void UFRotatorExporter::FromMatrix(FRotator* Rotator, const FMatrix& Matrix) | ||||
| { | ||||
| 	*Rotator = Matrix.Rotator(); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| 	 | ||||
| }; | ||||
| @ -0,0 +1,6 @@ | ||||
| #include "FSetPropertyExporter.h" | ||||
|  | ||||
| void* UFSetPropertyExporter::GetElement(FSetProperty* Property) | ||||
| { | ||||
| 	return Property->ElementProp; | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -0,0 +1,6 @@ | ||||
| #include "FStringExporter.h" | ||||
|  | ||||
| void UFStringExporter::MarshalToNativeString(FString* String, TCHAR* ManagedString) | ||||
| { | ||||
| 	*String = ManagedString; | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| }; | ||||
| @ -0,0 +1,6 @@ | ||||
| #include "FVectorExporter.h" | ||||
|  | ||||
| FVector UFVectorExporter::FromRotator(const FRotator& Rotator) | ||||
| { | ||||
| 	return Rotator.Vector(); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -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); | ||||
| }; | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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 | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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(); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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(); | ||||
| 	 | ||||
| }; | ||||
| @ -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); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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; | ||||
| } | ||||
| @ -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); | ||||
| }; | ||||
| @ -0,0 +1,11 @@ | ||||
| #include "UDataTableExporter.h" | ||||
|  | ||||
| uint8* UUDataTableExporter::GetRow(const UDataTable* DataTable, FName RowName) | ||||
| { | ||||
| 	if (!IsValid(DataTable)) | ||||
| 	{ | ||||
| 		return nullptr; | ||||
| 	} | ||||
|  | ||||
| 	return DataTable->FindRowUnchecked(RowName); | ||||
| } | ||||
| @ -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); | ||||
| 	 | ||||
| }; | ||||
| @ -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
		Reference in New Issue
	
	Block a user