“初始化俯视角工程,带puerts,未编过”

This commit is contained in:
2024-12-01 02:11:25 +08:00
parent 04698dd585
commit 850d76173c
1491 changed files with 271579 additions and 0 deletions
@@ -0,0 +1,141 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "FileSystemOperation.h"
#include "Misc/Paths.h"
#include "Misc/FileHelper.h"
#include "Misc/EngineVersionComparison.h"
#if UE_VERSION_OLDER_THAN(5, 0, 0)
#include "HAL/PlatformFilemanager.h"
#else
#include "HAL/PlatformFileManager.h"
#endif
#include "PuertsModule.h"
#include "Misc/SecureHash.h"
#ifdef PUERTS_WITH_SOURCE_CONTROL
#include "SourceControlHelpers.h"
#endif
bool UFileSystemOperation::ReadFile(FString Path, FString& Data)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
IFileHandle* FileHandle = PlatformFile.OpenRead(*Path);
if (FileHandle)
{
int len = FileHandle->Size();
TArray<uint8> Content;
Content.Reset(len + 2);
Content.AddUninitialized(len);
const bool Success = FileHandle->Read(Content.GetData(), len);
delete FileHandle;
if (Success)
{
FFileHelper::BufferToString(Data, Content.GetData(), Content.Num());
}
return Success;
}
return false;
}
void UFileSystemOperation::WriteFile(FString Path, FString Data)
{
#ifdef PUERTS_WITH_SOURCE_CONTROL
PuertsSourceControlUtils::CheckoutSourceControlFile(Path);
#endif
FFileHelper::SaveStringToFile(Data, *Path, FFileHelper::EEncodingOptions::ForceUTF8WithoutBOM);
}
FString UFileSystemOperation::ResolvePath(FString Path)
{
return IFileManager::Get().ConvertToAbsolutePathForExternalAppForRead(*Path);
}
bool UFileSystemOperation::FileExists(FString Path)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
return PlatformFile.FileExists(*Path);
}
bool UFileSystemOperation::DirectoryExists(FString Path)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
return PlatformFile.DirectoryExists(*Path);
}
void UFileSystemOperation::CreateDirectory(FString Path)
{
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
PlatformFile.CreateDirectory(*Path);
}
FString UFileSystemOperation::GetCurrentDirectory()
{
return FPaths::ConvertRelativePathToFull(FPaths::ProjectDir());
}
TArray<FString> UFileSystemOperation::GetDirectories(FString Path)
{
IFileManager& FileManager = IFileManager::Get();
TArray<FString> Dirs;
if (!Path.EndsWith(TEXT("/")))
Path = Path + TEXT("/");
Path = Path + "*";
FileManager.FindFiles(Dirs, *Path, false, true);
return Dirs;
}
TArray<FString> UFileSystemOperation::GetFiles(FString Path)
{
IFileManager& FileManager = IFileManager::Get();
TArray<FString> Dirs;
if (!Path.EndsWith(TEXT("/")))
Path = Path + TEXT("/");
Path = Path + "*";
FileManager.FindFiles(Dirs, *Path, true, false);
return Dirs;
}
void UFileSystemOperation::PuertsNotifyChange(FString Path, FString Source)
{
IPuertsModule::Get().ReloadModule(*Path, Source);
}
FString UFileSystemOperation::FileMD5Hash(FString Path)
{
FMD5Hash Hash = FMD5Hash::HashFile(*Path);
return LexToString(Hash);
}
// TArray<FString> UFileSystemOperation::ReadDirectory(FString Path, TArray<FString> Extensions, TArray<FString> exclude, int32
// Depth)
//{
//
//}
#ifdef PUERTS_WITH_SOURCE_CONTROL
namespace PuertsSourceControlUtils
{
bool MakeSourceControlFileWritable(const FString& InFileToMakeWritable)
{
if (SourceControlHelpers::IsAvailable() && FPlatformFileManager::Get().GetPlatformFile().FileExists(*InFileToMakeWritable))
{
return FPlatformFileManager::Get().GetPlatformFile().SetReadOnly(*InFileToMakeWritable, false);
}
return true;
}
bool CheckoutSourceControlFile(const FString& InFileToCheckout)
{
if (SourceControlHelpers::IsAvailable())
{
const FSourceControlState FileState = SourceControlHelpers::QueryFileState(InFileToCheckout);
if (FileState.bIsValid && FileState.bIsSourceControlled && !FileState.bCanEdit)
{
return SourceControlHelpers::CheckOutFile(InFileToCheckout);
}
}
return true;
}
} // namespace PuertsSourceControlUtils
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,659 @@
#include "PEBlueprintMetaData.h"
#include "Algo/AnyOf.h"
#include "K2Node_FunctionEntry.h"
#include "UObject/MetaData.h"
#include "Engine/Blueprint.h"
#include "GameFramework/Actor.h"
#include "UECompatible.h"
const TCHAR* UPEClassMetaData::NAME_HideCategories{TEXT("HideCategories")};
const TCHAR* UPEClassMetaData::NAME_ShowCategories{TEXT("ShowCategories")};
const TCHAR* UPEClassMetaData::NAME_HideFunctions{TEXT("HideFunctions")};
const TCHAR* UPEClassMetaData::NAME_AutoExpandCategories{TEXT("AutoExpandCategories")};
const TCHAR* UPEClassMetaData::NAME_AutoCollapseCategories{TEXT("AutoCollapseCategories")};
const TCHAR* UPEClassMetaData::NAME_ClassGroupNames{TEXT("ClassGroupNames")};
const TCHAR* UPEClassMetaData::NAME_SparseClassDataTypes{TEXT("SparseClassDataTypes")};
FPEMetaDataUtils::TFormatValidator<class FFieldVariant> FPEMetaDataUtils::ValidateFormat;
bool FPEMetaDataUtils::AddMetaData(UField* InField, TMap<FName, FString>& InMetaData)
{
// check if meta data changed
const bool bChanged = Algo::AnyOf(InMetaData, [InField](const TPair<FName, FString>& InNewData)
{ return !InField->HasMetaData(InNewData.Key) || InField->GetMetaData(InNewData.Key) != InNewData.Value; });
// set the metadata for this field, since blueprint compilation will handle parent issue, we set meta data directly
UMetaData* MetaData = InField->GetOutermost()->GetMetaData();
MetaData->SetObjectValues(InField, MoveTemp(InMetaData));
return bChanged;
}
void UPEClassMetaData::SetClassFlags(int32 InFlags, bool bInPlaceable)
{
ClassFlags = static_cast<EClassFlags>(InFlags);
bWantsToBePlaceable = bInPlaceable;
}
void UPEClassMetaData::SetMetaData(const FString& InName, const FString& InValue)
{
MetaData.FindOrAdd(*InName) = InValue;
}
void UPEClassMetaData::SetClassWithIn(const FString& InClassName)
{
ClassWithIn = InClassName;
}
void UPEClassMetaData::SetConfig(const FString& InConfigName)
{
ConfigName = InConfigName;
}
void UPEClassMetaData::AddHideCategory(const FString& InCategory)
{
HideCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddShowCategory(const FString& InCategory)
{
ShowCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddShowSubCategory(const FString& InCategory)
{
ShowSubCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddHideFunction(const FString& InFunctionName)
{
HideFunctions.AddUnique(InFunctionName);
}
void UPEClassMetaData::AddShowFunction(const FString& InFunctionName)
{
ShowFunctions.AddUnique(InFunctionName);
}
void UPEClassMetaData::AddAutoExpandCategory(const FString& InCategory)
{
AutoExpandCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddAutoCollapseCategory(const FString& InCategory)
{
AutoCollapseCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddDontAutoCollapseCategory(const FString& InCategory)
{
DontAutoCollapseCategories.AddUnique(InCategory);
}
void UPEClassMetaData::AddClassGroup(const FString& InGroupName)
{
ClassGroupNames.AddUnique(InGroupName);
}
void UPEClassMetaData::AddSparseDataType(const FString& InType)
{
SparseClassDataTypes.AddUnique(InType);
}
bool UPEClassMetaData::Apply(UClass* InClass, UBlueprint* InBlueprint)
{
MergeClassCategories(InClass);
const bool bFlagsChanged = MergeAndValidateClassFlags(InClass);
const bool bMetaDataChanged = SetClassMetaData(InClass);
const bool bBlueprintMetaDataChange = SyncClassToBlueprint(InClass, InBlueprint);
return bFlagsChanged || bMetaDataChanged || bBlueprintMetaDataChange;
}
void UPEClassMetaData::MergeClassCategories(UClass* InParentClass)
{
if (!IsValid(InParentClass))
{
return;
}
TArray<FString> ParentShowCategories = GetClassMetaDataValues(InParentClass, NAME_ShowCategories);
TArray<FString> ParentHideFunctions = GetClassMetaDataValues(InParentClass, NAME_HideFunctions);
TArray<FString> ParentAutoExpandCategories = GetClassMetaDataValues(InParentClass, NAME_AutoExpandCategories);
TArray<FString> ParentAutoCollapseCategories = GetClassMetaDataValues(InParentClass, NAME_AutoCollapseCategories);
// add parent categories
ShowSubCategories.Append(MoveTemp(ParentShowCategories));
HideFunctions.Append(MoveTemp(ParentHideFunctions));
// If metadata is collected from ts
FString* ExistingValue = MetaData.Find(NAME_HideCategories);
if (ExistingValue)
{
ExistingValue->ParseIntoArray(HideCategories, TEXT(" "), true);
}
// for show categories
for (const FString& Value : ShowCategories)
{
// if we didn't find this specific category path in the HideCategories metadata
if (HideCategories.RemoveSwap(Value) != 0)
{
continue;
}
TArray<FString> SubCategoryList;
Value.ParseIntoArray(SubCategoryList, TEXT("|"), true);
FString SubCategoryPath;
// look to see if any of the parent paths are excluded in the HideCategories list
for (int32 CategoryPathIndex = 0; CategoryPathIndex < SubCategoryList.Num() - 1; ++CategoryPathIndex)
{
SubCategoryPath += SubCategoryList[CategoryPathIndex];
// if we're hiding a parent category, then we need to flag this sub category for show
if (HideCategories.Contains(SubCategoryPath))
{
ShowSubCategories.AddUnique(Value);
break;
}
SubCategoryPath += "|";
}
}
// Once the categories have been merged, empty the array as we will no longer need it nor should we use it
ShowCategories.Empty();
// Merge ShowFunctions and HideFunctions
for (const FString& Value : ShowFunctions)
{
HideFunctions.RemoveSwap(Value);
}
ShowFunctions.Empty();
// Merge DontAutoCollapseCategories and AutoCollapseCategories
for (const FString& Value : DontAutoCollapseCategories)
{
AutoCollapseCategories.RemoveSwap(Value);
}
DontAutoCollapseCategories.Empty();
// Merge ShowFunctions and HideFunctions
for (const FString& Value : ShowFunctions)
{
HideFunctions.RemoveSwap(Value);
}
ShowFunctions.Empty();
// Merge AutoExpandCategories and AutoCollapseCategories (we still want to keep AutoExpandCategories though!)
for (const FString& Value : AutoExpandCategories)
{
AutoCollapseCategories.RemoveSwap(Value);
ParentAutoCollapseCategories.RemoveSwap(Value);
}
// Do the same as above but the other way around
for (const FString& Value : AutoCollapseCategories)
{
AutoExpandCategories.RemoveSwap(Value);
ParentAutoExpandCategories.RemoveSwap(Value);
}
// Once AutoExpandCategories and AutoCollapseCategories for THIS class have been parsed, add the parent inherited categories
AutoCollapseCategories.Append(MoveTemp(ParentAutoCollapseCategories));
AutoExpandCategories.Append(MoveTemp(ParentAutoExpandCategories));
// add the categories to the meta data
if (ClassGroupNames.Num() > 0)
{
MetaData.Add(NAME_ClassGroupNames, FString::Join(ClassGroupNames, TEXT(" ")));
}
if (AutoExpandCategories.Num() > 0)
{
MetaData.Add(NAME_AutoExpandCategories, FString::Join(AutoExpandCategories, TEXT(" ")));
}
if (ShowSubCategories.Num() > 0)
{
MetaData.Add(NAME_ShowCategories, FString::Join(ShowSubCategories, TEXT(" ")));
}
if (SparseClassDataTypes.Num() > 0)
{
MetaData.Add(NAME_SparseClassDataTypes, FString::Join(SparseClassDataTypes, TEXT(" ")));
}
if (AutoCollapseCategories.Num() > 0)
{
MetaData.Add(NAME_AutoCollapseCategories, FString::Join(AutoCollapseCategories, TEXT(" ")));
}
}
bool UPEClassMetaData::MergeAndValidateClassFlags(UClass* InClass)
{
if (!IsValid(InClass))
{
return false;
}
const EClassFlags OldFlags = InClass->ClassFlags;
if (bWantsToBePlaceable)
{
if (!(InClass->ClassFlags & CLASS_NotPlaceable))
{
UE_LOG(LogTemp, Error,
TEXT("The 'placeable' specifier is only allowed on classes which have a base class that's marked as not placeable. "
"Classes are assumed to be placeable by default."));
return false;
}
InClass->ClassFlags &= ~CLASS_NotPlaceable;
bWantsToBePlaceable = false;
}
InClass->ClassFlags |= ClassFlags;
const auto OldWithInClass = InClass->ClassWithin;
SetAndValidateWithinClass(InClass);
if (!!(InClass->ClassFlags & CLASS_EditInlineNew) && InClass->IsChildOf(AActor::StaticClass()))
{
UE_LOG(LogTemp, Error, TEXT("Invalid class attribute: Creating actor instances via the property window is not allowed"));
return false;
}
if (InClass->HasAllClassFlags(CLASS_MinimalAPI | CLASS_RequiredAPI))
{
UE_LOG(
LogTemp, Error, TEXT("MinimalAPI cannot be specified when the class is fully exported using a MODULENAME_API macro"));
return false;
}
return OldFlags != InClass->ClassFlags || OldWithInClass != InClass->ClassWithin;
}
bool UPEClassMetaData::SetClassMetaData(UClass* InClass)
{
// Evaluate any key redirects on the passed in pairs
for (TPair<FName, FString>& Pair : MetaData)
{
FName& CurrentKey = Pair.Key;
FName NewKey = UMetaData::GetRemappedKeyName(CurrentKey);
if (NewKey != NAME_None)
{
UE_LOG(LogTemp, Warning, TEXT("Remapping old metadata key '%s' to new key '%s', please update the declaration."),
*CurrentKey.ToString(), *NewKey.ToString());
CurrentKey = NewKey;
}
}
// Finish validating and associate the metadata with the field
for (const auto& Pair : MetaData)
{
FString Message;
if (!FPEMetaDataUtils::ValidateFormat(InClass, Pair.Key, Pair.Value, Message))
{
UE_LOG(LogTemp, Error, TEXT("failed set meta data: %s"), *Message);
return false;
}
}
return FPEMetaDataUtils::AddMetaData(InClass, MetaData);
}
TArray<FString> UPEClassMetaData::GetClassMetaDataValues(
UClass* InClass, const TCHAR* InMetaDataKey, const TCHAR* InDelimiter, bool bInCullEmpty)
{
TArray<FString> Result;
if (!IsValid(InClass))
{
return Result;
}
if (!InClass->HasMetaData(InMetaDataKey))
{
return Result;
}
InClass->GetMetaData(InMetaDataKey).ParseIntoArray(Result, InDelimiter, bInCullEmpty);
return Result;
}
bool UPEClassMetaData::SyncClassToBlueprint(UClass* InClass, UBlueprint* InBlueprint)
{
if (!IsValid(InClass) || !IsValid(InBlueprint))
{
return false;
}
bool onChange = false;
if (InBlueprint->bDeprecate != (bool) (InClass->ClassFlags & CLASS_Deprecated))
{
InBlueprint->bDeprecate = (bool) (InClass->ClassFlags & CLASS_Deprecated);
onChange = true;
}
if (InBlueprint->bGenerateAbstractClass != (bool) (InClass->ClassFlags & CLASS_Abstract))
{
InBlueprint->bGenerateAbstractClass = (bool) (InClass->ClassFlags & CLASS_Abstract);
onChange = true;
}
FString newDescription = InClass->HasMetaData(TEXT("Tooltip")) ? InClass->GetMetaData(TEXT("Tooltip")) : FString{};
if (InBlueprint->BlueprintDescription != newDescription)
{
InBlueprint->BlueprintDescription = newDescription;
onChange = true;
}
FString newDisplayName = InClass->HasMetaData(TEXT("DisplayName")) ? InClass->GetMetaData(TEXT("DisplayName")) : FString{};
if (InBlueprint->BlueprintDisplayName != newDisplayName)
{
InBlueprint->BlueprintDisplayName = newDisplayName;
onChange = true;
}
EBlueprintType newType = (InClass->ClassFlags & CLASS_Const) ? BPTYPE_Const : BPTYPE_Normal;
if (InBlueprint->BlueprintType != newType)
{
InBlueprint->BlueprintType = newType;
onChange = true;
}
FString newCategory = InClass->HasMetaData(TEXT("Category")) ? InClass->GetMetaData(TEXT("Category")) : FString{};
if (InBlueprint->BlueprintCategory != newCategory)
{
InBlueprint->BlueprintCategory = newCategory;
onChange = true;
}
if (InBlueprint->HideCategories != HideCategories)
{
InBlueprint->HideCategories = HideCategories;
onChange = true;
}
return onChange;
}
void UPEClassMetaData::SetAndValidateWithinClass(UClass* InClass)
{
#if ENGINE_MAJOR_VERSION >= 5 && ENGINE_MINOR_VERSION > 2
UClass* ExpectedWithinClass = InClass->GetSuperClass() ? InClass->GetSuperClass()->ClassWithin.Get() : UObject::StaticClass();
#else
UClass* ExpectedWithinClass = InClass->GetSuperClass() ? InClass->GetSuperClass()->ClassWithin : UObject::StaticClass();
#endif
if (ClassWithIn.IsEmpty() == false)
{
UClass* WithinClass = PUERTS_NAMESPACE::FindAnyType<UClass>(ClassWithIn);
if (WithinClass == nullptr)
{
UE_LOG(LogTemp, Error, TEXT("the with in class of %s: %s is not found"), *InClass->GetName(), *ClassWithIn);
return;
}
if (WithinClass->IsChildOf(UInterface::StaticClass()))
{
UE_LOG(LogTemp, Error, TEXT("the with in class of %s: %s should not be interface "), *InClass->GetName(), *ClassWithIn);
return;
}
if (InClass->ClassWithin == nullptr || InClass->ClassWithin == UObject::StaticClass() ||
WithinClass->IsChildOf(InClass->ClassWithin))
{
InClass->ClassWithin = WithinClass;
}
if (InClass->ClassWithin != WithinClass)
{
UE_LOG(LogTemp, Error, TEXT("the with in class of %s: %s is set failed"), *InClass->GetName(), *ClassWithIn);
return;
}
}
else
{
InClass->ClassWithin = ExpectedWithinClass;
}
if (!InClass->ClassWithin->IsChildOf(ExpectedWithinClass))
{
UE_LOG(LogTemp, Error, TEXT("the parent class with in class %s is not consist the with in class of %s: %s"),
*ExpectedWithinClass->GetName(), *InClass->GetName(), *InClass->ClassWithin->GetName());
}
}
void UPEClassMetaData::SetAndValidateConfigName(UClass* InClass)
{
if (ConfigName.IsEmpty() == false)
{
// if the user specified "inherit", we're just going to use the parent class's config filename
// this is not actually necessary but it can be useful for explicitly communicating config-ness
if (ConfigName == TEXT("inherit"))
{
UClass* SuperClass = InClass->GetSuperClass();
if (!SuperClass)
{
UE_LOG(LogTemp, Error, TEXT("Cannot inherit config filename: %s has no super class"), *InClass->GetName());
return;
}
if (SuperClass->ClassConfigName == NAME_None)
{
UE_LOG(LogTemp, Error, TEXT("Cannot inherit config filename: parent class %s is not marked config."),
*SuperClass->GetPathName());
return;
}
}
else
{
// otherwise, set the config name to the parsed identifier
InClass->ClassConfigName = FName(*ConfigName);
}
}
else
{
// Invalidate config name if not specifically declared.
InClass->ClassConfigName = NAME_None;
}
}
void UPEFunctionMetaData::SetFunctionFlags(int32 InHighBits, int32 InLowBits)
{
FunctionFlags =
static_cast<EFunctionFlags>((static_cast<uint64>(static_cast<uint32>(InHighBits)) << 32) + static_cast<uint32>(InLowBits));
}
void UPEFunctionMetaData::SetFunctionExportFlags(int32 InFlags)
{
FunctionExportFlags = InFlags;
}
void UPEFunctionMetaData::SetMetaData(const FString& InName, const FString& InValue)
{
MetaData.FindOrAdd(*InName) = InValue;
}
void UPEFunctionMetaData::SetCppImplName(const FString& InName)
{
CppImplName = InName;
}
void UPEFunctionMetaData::SetCppValidationImplName(const FString& InName)
{
CppValidationImplName = InName;
}
void UPEFunctionMetaData::SetEndpointName(const FString& InEndpointName)
{
EndpointName = InEndpointName;
}
void UPEFunctionMetaData::SetRPCId(int32 InRPCId)
{
RPCId = static_cast<uint16>(InRPCId);
}
void UPEFunctionMetaData::SetRPCResponseId(int32 InRPCResponseId)
{
RPCResponseId = InRPCResponseId;
}
void UPEFunctionMetaData::SetIsSealedEvent(bool bInSealedEvent)
{
bSealedEvent = bInSealedEvent;
}
void UPEFunctionMetaData::SetForceBlueprintImpure(bool bInForceBlueprintImpure)
{
bForceBlueprintImpure = bInForceBlueprintImpure;
}
bool UPEFunctionMetaData::Apply(UK2Node_FunctionEntry* InFunctionEntry) const
{
// a helper function used to update text value, and return if the value is updated by a new value
static const auto UpdateTextMetaData = [](FName InKey, const TMap<FName, FString>& InMetaData, FText& InOutValue) -> bool
{
const FText NewValue = InMetaData.Contains(InKey) ? FText::FromString(InMetaData[InKey]) : FText{};
const bool bChanged = !NewValue.EqualTo(InOutValue);
InOutValue = NewValue;
return bChanged;
};
// a helper function used to update boolean value, and return if the value is updated by the new value
static const auto UpdateBooleanMetaData = [](FName InKey, const TMap<FName, FString>& InMetaData, bool& InOutValue) -> bool
{
const bool NewValue = InMetaData.Contains(InKey) ? true : false;
const bool bChanged = NewValue != InOutValue;
InOutValue = NewValue;
return bChanged;
};
// a helper function sued update string value, return return if the value is updated by the new value
static const auto UpdateStringMetaData = [](FName InKey, const TMap<FName, FString>& InMetaData, FString& InOutValue) -> bool
{
const FString NewValue = InMetaData.Contains(InKey) ? InMetaData[InKey] : FString{};
const bool bChanged = NewValue != InOutValue;
InOutValue = NewValue;
return bChanged;
};
if (!IsValid(InFunctionEntry))
{
return false;
}
// make sure native flags is removed
const auto OldFlags = InFunctionEntry->GetExtraFlags();
InFunctionEntry->SetExtraFlags(InFunctionEntry->GetExtraFlags() | FunctionFlags);
const bool bFlagsChanged = InFunctionEntry->GetExtraFlags() != OldFlags;
bool bMetaDataChanged = false;
auto& MetaDataToSet = InFunctionEntry->MetaData;
bMetaDataChanged = UpdateBooleanMetaData(TEXT("CallInEditor"), MetaData, MetaDataToSet.bCallInEditor) || bMetaDataChanged;
bMetaDataChanged = UpdateTextMetaData(TEXT("Category"), MetaData, MetaDataToSet.Category) || bMetaDataChanged;
bMetaDataChanged = UpdateTextMetaData(TEXT("Keywords"), MetaData, MetaDataToSet.Keywords) || bMetaDataChanged;
bMetaDataChanged = UpdateTextMetaData(TEXT("CompactNodeTitle"), MetaData, MetaDataToSet.CompactNodeTitle) || bMetaDataChanged;
bMetaDataChanged = UpdateTextMetaData(TEXT("ToolTip"), MetaData, MetaDataToSet.ToolTip) || bMetaDataChanged;
#if ENGINE_MINOR_VERSION >= 23 || ENGINE_MAJOR_VERSION > 4
bMetaDataChanged = UpdateBooleanMetaData(TEXT("DeprecatedFunction"), MetaData, MetaDataToSet.bIsDeprecated) || bMetaDataChanged;
bMetaDataChanged =
UpdateStringMetaData(TEXT("DeprecationMessage"), MetaData, MetaDataToSet.DeprecationMessage) || bMetaDataChanged;
#endif
return bFlagsChanged || bMetaDataChanged;
}
bool UPEFunctionMetaData::Apply(UK2Node_CustomEvent* InCustomEvent) const
{
if (!IsValid(InCustomEvent))
{
return false;
}
// the function flags
const auto Oldflags = InCustomEvent->FunctionFlags;
InCustomEvent->FunctionFlags |= FunctionFlags;
const bool bFlagsChanged = Oldflags != InCustomEvent->FunctionFlags;
// add meta data
bool bMetaChanged;
ApplyCustomEventMetaData(bMetaChanged, MetaData, InCustomEvent);
return bFlagsChanged || bMetaChanged;
}
void UPEParamMetaData::SetParamFlags(int32 InHighBits, int32 InLowBits)
{
ParamFlags =
static_cast<EPropertyFlags>((static_cast<uint64>(static_cast<uint32>(InHighBits)) << 32) + static_cast<uint32>(InLowBits));
}
void UPEParamMetaData::SetMetaData(const FString& InName, const FString& InValue)
{
MetaData.FindOrAdd(*InName) = InValue;
}
bool UPEParamMetaData::Apply(FEdGraphPinType& PinType) const
{
// most meta data could not set in blueprint, should have a way to apply on related FProperty after blueprint compilation?
bool bChanged = false;
bChanged = (PinType.bIsConst != !!(ParamFlags & CPF_ConstParm)) || bChanged;
PinType.bIsConst = !!(ParamFlags & CPF_ConstParm);
bChanged = (PinType.bIsReference != !!(ParamFlags & CPF_ReferenceParm)) || bChanged;
PinType.bIsReference = !!(ParamFlags & CPF_ReferenceParm);
return bChanged;
}
void UPEPropertyMetaData::SetPropertyFlags(int32 InHighBits, int32 InLowBits)
{
PropertyFlags =
static_cast<EPropertyFlags>((static_cast<uint64>(static_cast<uint32>(InHighBits)) << 32) + static_cast<uint32>(InLowBits));
}
void UPEPropertyMetaData::SetMetaData(const FString& InName, const FString& InValue)
{
MetaData.FindOrAdd(*InName) = InValue;
}
void UPEPropertyMetaData::SetRepCallbackName(const FString& InName)
{
RepCallbackName = InName;
}
bool UPEPropertyMetaData::Apply(FBPVariableDescription& Element) const
{
// should do more check here?
const auto OldFlags = Element.PropertyFlags;
// set flags, since the default create blueprint variable could not edit instance, so modify it if needed
Element.PropertyFlags |= PropertyFlags;
const bool bFlagsChanged = OldFlags != Element.PropertyFlags;
// set meta data
bool bMetaDataChanged = false;
for (int Index = Element.MetaDataArray.Num() - 1; Index >= 0; --Index)
{
if (!MetaData.Contains(Element.MetaDataArray[Index].DataKey))
{
bMetaDataChanged = true;
Element.MetaDataArray.RemoveAt(Index);
}
}
for (const auto& Pair : MetaData)
{
if (const auto MetaDataEntryPtr = Element.MetaDataArray.FindByPredicate(
[Key = Pair.Key](const FBPVariableMetaDataEntry& InEntry) { return InEntry.DataKey == Key; }))
{
bMetaDataChanged = MetaDataEntryPtr->DataValue != Pair.Value || bMetaDataChanged;
MetaDataEntryPtr->DataValue = Pair.Value;
}
else
{
bMetaDataChanged = true;
Element.MetaDataArray.Emplace(Pair.Key, Pair.Value);
}
}
// if needed set notify function, we don't check the existence of the notify function here
bool bRepFunctionChanged = false;
if (PropertyFlags & CPF_RepNotify)
{
const FName NewRepNotifyFunc =
RepCallbackName.IsEmpty() ? *FString::Printf(TEXT("OnRep_%s"), *Element.VarName.ToString()) : *RepCallbackName;
bRepFunctionChanged = NewRepNotifyFunc != Element.RepNotifyFunc;
Element.RepNotifyFunc = NewRepNotifyFunc;
}
return bFlagsChanged || bMetaDataChanged || bRepFunctionChanged;
}
@@ -0,0 +1,90 @@
// Fill out your copyright notice in the Description page of Project Settings.
#include "PEDirectoryWatcher.h"
#include "DirectoryWatcherModule.h"
#include "Modules/ModuleManager.h"
#include "HAL/FileManager.h"
#include "Misc/SecureHash.h"
UPEDirectoryWatcher::UPEDirectoryWatcher()
{
this->AddToRoot();
}
bool UPEDirectoryWatcher::Watch(const FString& InDirectory)
{
Directory = FPaths::IsRelative(InDirectory) ? FPaths::ConvertRelativePathToFull(InDirectory) : InDirectory;
// UE_LOG(LogTemp, Warning, TEXT("PEDirectoryWatcher::Watch: %s"), *InDirectory);
if (IFileManager::Get().DirectoryExists(*Directory))
{
auto Changed = IDirectoryWatcher::FDirectoryChanged::CreateLambda(
[&](const TArray<FFileChangeData>& FileChanges)
{
TArray<FString> Added;
TArray<FString> Modified;
TArray<FString> Removed;
for (auto Change : FileChanges)
{
//因为要算md5,所有过滤掉不关心的
if (!Change.Filename.EndsWith(TEXT(".ts")) && !Change.Filename.EndsWith(TEXT(".mts")) &&
!Change.Filename.EndsWith(TEXT(".tsx")) && !Change.Filename.EndsWith(TEXT(".json")) &&
!Change.Filename.EndsWith(TEXT(".js")))
{
continue;
}
FPaths::NormalizeFilename(Change.Filename);
Change.Filename = FPaths::ConvertRelativePathToFull(Change.Filename);
switch (Change.Action)
{
case FFileChangeData::FCA_Added:
if (Added.Contains(Change.Filename))
continue;
Added.Add(Change.Filename);
break;
case FFileChangeData::FCA_Modified:
if (Modified.Contains(Change.Filename))
continue;
Modified.Add(Change.Filename);
break;
case FFileChangeData::FCA_Removed:
if (Removed.Contains(Change.Filename))
continue;
Removed.Add(Change.Filename);
break;
default:
continue;
}
}
if (Added.Num() || Modified.Num() || Removed.Num())
{
OnChanged.Broadcast(Added, Modified, Removed);
}
});
FDirectoryWatcherModule& DirectoryWatcherModule =
FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get();
DirectoryWatcher->RegisterDirectoryChangedCallback_Handle(
Directory, Changed, DelegateHandle, IDirectoryWatcher::IncludeDirectoryChanges);
return true;
}
return false;
}
void UPEDirectoryWatcher::UnWatch()
{
if (DelegateHandle.IsValid())
{
FDirectoryWatcherModule& DirectoryWatcherModule =
FModuleManager::Get().LoadModuleChecked<FDirectoryWatcherModule>(TEXT("DirectoryWatcher"));
IDirectoryWatcher* DirectoryWatcher = DirectoryWatcherModule.Get();
DirectoryWatcher->UnregisterDirectoryChangedCallback_Handle(Directory, DelegateHandle);
Directory = TEXT("");
}
}
UPEDirectoryWatcher::~UPEDirectoryWatcher()
{
UnWatch();
}
@@ -0,0 +1,175 @@
/*
* Tencent is pleased to support the open source community by making Puerts available.
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
* which is part of this source code package.
*/
#include "PuertsEditorModule.h"
#include "JsEnv.h"
#include "Editor.h"
#include "Misc/FileHelper.h"
#include "PuertsModule.h"
#include "TypeScriptCompilerContext.h"
#include "TypeScriptBlueprint.h"
#include "SourceFileWatcher.h"
#include "JSLogger.h"
#include "JSModuleLoader.h"
#include "Binding.hpp"
#include "UEDataBinding.hpp"
#include "Object.hpp"
class FPuertsEditorModule : public IPuertsEditorModule
{
/** IModuleInterface implementation */
void StartupModule() override;
void ShutdownModule() override;
void SetCmdImpl(std::function<void(const FString&, const FString&)> Func) override
{
CmdImpl = Func;
}
public:
static void SetCmdCallback(std::function<void(const FString&, const FString&)> Func)
{
Get().SetCmdImpl(Func);
}
private:
//
void PreBeginPIE(bool bIsSimulating);
void EndPIE(bool bIsSimulating);
void OnPostEngineInit();
TSharedPtr<PUERTS_NAMESPACE::FJsEnv> JsEnv;
TSharedPtr<PUERTS_NAMESPACE::FSourceFileWatcher> SourceFileWatcher;
bool Enabled = false;
std::function<void(const FString&, const FString&)> CmdImpl;
TUniquePtr<FAutoConsoleCommand> ConsoleCommand;
};
UsingCppType(FPuertsEditorModule);
struct AutoRegisterForPEM
{
AutoRegisterForPEM()
{
PUERTS_NAMESPACE::DefineClass<FPuertsEditorModule>()
.Function("SetCmdCallback", MakeFunction(&FPuertsEditorModule::SetCmdCallback))
.Register();
}
};
AutoRegisterForPEM _AutoRegisterForPEM__;
IMPLEMENT_MODULE(FPuertsEditorModule, PuertsEditor)
void FPuertsEditorModule::StartupModule()
{
Enabled = IPuertsModule::Get().IsWatchEnabled() && !IsRunningCommandlet();
FEditorDelegates::PreBeginPIE.AddRaw(this, &FPuertsEditorModule::PreBeginPIE);
FEditorDelegates::EndPIE.AddRaw(this, &FPuertsEditorModule::EndPIE);
ConsoleCommand = MakeUnique<FAutoConsoleCommand>(TEXT("Puerts"), TEXT("Puerts action"),
FConsoleCommandWithArgsDelegate::CreateLambda(
[this](const TArray<FString>& Args)
{
if (CmdImpl)
{
FString CmdForJs = TEXT("");
FString ArgsForJs = TEXT("");
if (Args.Num() > 0)
{
CmdForJs = Args[0];
}
if (Args.Num() > 1)
{
ArgsForJs = Args[1];
}
CmdImpl(CmdForJs, ArgsForJs);
}
else
{
UE_LOG(Puerts, Error, TEXT("Puerts command not initialized"));
}
}));
this->OnPostEngineInit();
}
TSharedPtr<FKismetCompilerContext> MakeCompiler(
UBlueprint* InBlueprint, FCompilerResultsLog& InMessageLog, const FKismetCompilerOptions& InCompileOptions)
{
return MakeShared<FTypeScriptCompilerContext>(CastChecked<UTypeScriptBlueprint>(InBlueprint), InMessageLog, InCompileOptions);
}
void FPuertsEditorModule::OnPostEngineInit()
{
if (Enabled)
{
FKismetCompilerContext::RegisterCompilerForBP(UTypeScriptBlueprint::StaticClass(), &MakeCompiler);
SourceFileWatcher = MakeShared<PUERTS_NAMESPACE::FSourceFileWatcher>(
[this](const FString& InPath)
{
if (JsEnv.IsValid())
{
TArray<uint8> Source;
if (FFileHelper::LoadFileToArray(Source, *InPath))
{
JsEnv->ReloadSource(InPath, std::string((const char*) Source.GetData(), Source.Num()));
}
else
{
UE_LOG(Puerts, Error, TEXT("read file fail for %s"), *InPath);
}
}
});
JsEnv = MakeShared<PUERTS_NAMESPACE::FJsEnv>(
std::make_shared<PUERTS_NAMESPACE::DefaultJSModuleLoader>(TEXT("JavaScript")),
std::make_shared<PUERTS_NAMESPACE::FDefaultLogger>(), -1,
[this](const FString& InPath)
{
if (SourceFileWatcher.IsValid())
{
SourceFileWatcher->OnSourceLoaded(InPath);
}
},
TEXT("--max-old-space-size=2048"));
JsEnv->Start("PuertsEditor/CodeAnalyze");
}
}
void FPuertsEditorModule::ShutdownModule()
{
CmdImpl = nullptr;
if (JsEnv.IsValid())
{
JsEnv.Reset();
}
if (SourceFileWatcher.IsValid())
{
SourceFileWatcher.Reset();
}
}
void FPuertsEditorModule::PreBeginPIE(bool bIsSimulating)
{
if (Enabled)
{
}
}
void FPuertsEditorModule::EndPIE(bool bIsSimulating)
{
}
@@ -0,0 +1,41 @@
#include "TypeScriptCompilerContext.h"
#include "TypeScriptGeneratedClass.h"
#include "Kismet2/KismetReinstanceUtilities.h"
#include "KismetCompilerMisc.h"
#include "Runtime/Launch/Resources/Version.h"
FTypeScriptCompilerContext::FTypeScriptCompilerContext(
UBlueprint* SourceSketch, FCompilerResultsLog& MessageLog, const FKismetCompilerOptions& CompilerOptions)
#if (ENGINE_MAJOR_VERSION <= 4) & (ENGINE_MINOR_VERSION <= 21)
: Super(SourceSketch, MessageLog, CompilerOptions, nullptr)
#else
: Super(SourceSketch, MessageLog, CompilerOptions)
#endif
{
}
void FTypeScriptCompilerContext::SpawnNewClass(const FString& NewClassName)
{
if (NewClassName.StartsWith(TEXT("SKEL_")))
{
FKismetCompilerContext::SpawnNewClass(NewClassName);
return;
}
NewClass = FindObject<UTypeScriptGeneratedClass>(Blueprint->GetOutermost(), *NewClassName);
if (NewClass == NULL)
{
// If the class hasn't been found, then spawn a new one
NewClass =
NewObject<UTypeScriptGeneratedClass>(Blueprint->GetOutermost(), FName(*NewClassName), RF_Public | RF_Transactional);
}
else
{
// Already existed, but wasn't linked in the Blueprint yet due to load ordering issues
NewClass->ClassGeneratedBy = Blueprint;
FBlueprintCompileReinstancer::Create(NewClass);
}
}
@@ -0,0 +1,17 @@
#pragma once
#include "CoreMinimal.h"
#include "KismetCompiler.h"
class FTypeScriptCompilerContext final : public FKismetCompilerContext
{
using Super = FKismetCompilerContext;
public:
FTypeScriptCompilerContext(
UBlueprint* SourceSketch, FCompilerResultsLog& MessageLog, const FKismetCompilerOptions& CompilerOptions);
private:
void SpawnNewClass(const FString& NewClassName) override;
};