914 lines
27 KiB
C++
914 lines
27 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "PropertyMacros.h"
|
|
#include "Math/UnitConversion.h"
|
|
#include "K2Node_CustomEvent.h"
|
|
#include "K2Node_FunctionEntry.h"
|
|
#include "Engine/Blueprint.h"
|
|
|
|
#include "PEBlueprintMetaData.generated.h"
|
|
|
|
/**
|
|
* @brief since the void_t defined in converter.hpp will introduce v8
|
|
* define a temporary void_t here
|
|
*/
|
|
template <class...>
|
|
using Void_t = void;
|
|
|
|
/**
|
|
* @brief the utility function collection for meta data
|
|
*/
|
|
struct FPEMetaDataUtils
|
|
{
|
|
/**
|
|
* temporary check if a type is defined
|
|
*/
|
|
template <typename T, typename = void>
|
|
struct TFormatValidator
|
|
{
|
|
/**
|
|
* @brief fallback
|
|
* @param ...
|
|
* @return
|
|
*/
|
|
template <typename... Args>
|
|
bool operator()(Args&&...) const
|
|
{
|
|
// if the field variant is not exist, currently don't do further check
|
|
UE_LOG(LogTemp, VeryVerbose, TEXT("FFieldVarient is not implemented in current engine"));
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief if the field variant is defined, we do the check
|
|
* @tparam T
|
|
*/
|
|
template <typename T>
|
|
struct TFormatValidator<T, typename std::enable_if<(sizeof(T) > 0)>::type>
|
|
{
|
|
/**
|
|
* @brief real check
|
|
* @param InField
|
|
* @param InKey
|
|
* @param InValue
|
|
* @param OutMessage
|
|
* @return
|
|
*/
|
|
bool operator()(T InField, FName InKey, const FString& InValue, FString& OutMessage) const
|
|
{
|
|
// name pre define
|
|
static const FName NAME_BlueprintProtected = TEXT("BlueprintProtected");
|
|
static const FName NAME_ClampMax = TEXT("ClampMax");
|
|
static const FName NAME_ClampMin = TEXT("ClampMin");
|
|
static const FName NAME_CommutativeAssociativeBinaryOperator = TEXT("CommutativeAssociativeBinaryOperator");
|
|
static const FName NAME_DevelopmentStatus = TEXT("DevelopmentStatus");
|
|
static const FName NAME_DocumentationPolicy = TEXT("DocumentationPolicy");
|
|
static const FName NAME_ExpandBoolAsExecs = TEXT("ExpandBoolAsExecs");
|
|
static const FName NAME_ExpandEnumAsExecs = TEXT("ExpandEnumAsExecs");
|
|
static const FName NAME_UIMax = TEXT("UIMax");
|
|
static const FName NAME_UIMin = TEXT("UIMin");
|
|
static const FName NAME_Units = TEXT("Units");
|
|
|
|
// a helper function used to check a function is well defined blueprint protected
|
|
static const auto ValidateFunctionBlueprintProtected = [](UFunction* InFunction)
|
|
{
|
|
if (!IsValid(InFunction))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (InFunction->HasAnyFunctionFlags(FUNC_Static))
|
|
{
|
|
// Determine if it's a function library
|
|
UClass* Class = InFunction->GetOuterUClass();
|
|
while (Class != nullptr && Class->GetSuperClass() != UObject::StaticClass())
|
|
{
|
|
Class = Class->GetSuperClass();
|
|
}
|
|
|
|
if (Class != nullptr && Class->GetName() == TEXT("BlueprintFunctionLibrary"))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// a helper function used to check a function is well defined binary operator
|
|
static const auto ValidateFunctionCommutativeAssociativeBinaryOperator = [](UFunction* InFunction)
|
|
{
|
|
if (!IsValid(InFunction))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
bool bGoodParams = (InFunction->NumParms == 3);
|
|
if (bGoodParams)
|
|
{
|
|
PropertyMacro* FirstParam = nullptr;
|
|
PropertyMacro* SecondParam = nullptr;
|
|
PropertyMacro* ReturnValue = nullptr;
|
|
|
|
TFieldIterator<PropertyMacro> It(InFunction);
|
|
|
|
auto GetNextParam = [&]()
|
|
{
|
|
if (It)
|
|
{
|
|
if (It->HasAnyPropertyFlags(CPF_ReturnParm))
|
|
{
|
|
ReturnValue = *It;
|
|
}
|
|
else
|
|
{
|
|
if (FirstParam == nullptr)
|
|
{
|
|
FirstParam = *It;
|
|
}
|
|
else if (SecondParam == nullptr)
|
|
{
|
|
SecondParam = *It;
|
|
}
|
|
}
|
|
++It;
|
|
}
|
|
};
|
|
|
|
GetNextParam();
|
|
GetNextParam();
|
|
GetNextParam();
|
|
ensure(!It);
|
|
|
|
if (ReturnValue == nullptr || SecondParam == nullptr || !SecondParam->SameType(FirstParam))
|
|
{
|
|
bGoodParams = false;
|
|
}
|
|
}
|
|
|
|
return bGoodParams;
|
|
};
|
|
|
|
// a helper function sued to check a function is well defined as execs
|
|
static const auto ValidateFunctionExpandAsExecs = [](UFunction* InFunction, const FString& InValue)
|
|
{
|
|
if (!IsValid(InFunction))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// multiple entry parsing in the same format as eg SetParam.
|
|
TArray<FString> RawGroupings;
|
|
InValue.ParseIntoArray(RawGroupings, TEXT(","), false);
|
|
|
|
PropertyMacro* FirstInput = nullptr;
|
|
for (const FString& RawGroup : RawGroupings)
|
|
{
|
|
TArray<FString> IndividualEntries;
|
|
RawGroup.ParseIntoArray(IndividualEntries, TEXT("|"));
|
|
|
|
for (const FString& Entry : IndividualEntries)
|
|
{
|
|
if (Entry.IsEmpty())
|
|
{
|
|
continue;
|
|
}
|
|
auto FoundField = FindUFieldOrFProperty(InFunction, *Entry);
|
|
if (!FoundField)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (PropertyMacro* Prop = FoundField.Get<PropertyMacro>())
|
|
{
|
|
if (!Prop->HasAnyPropertyFlags(CPF_ReturnParm) &&
|
|
|
|
(!Prop->HasAnyPropertyFlags(CPF_OutParm) || Prop->HasAnyPropertyFlags(CPF_ReferenceParm)))
|
|
{
|
|
if (!FirstInput)
|
|
{
|
|
FirstInput = Prop;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
// function body
|
|
// check numeric keys
|
|
if (InKey == NAME_UIMin || InKey == NAME_UIMax || InKey == NAME_ClampMin || InKey == NAME_ClampMax)
|
|
{
|
|
if (!InValue.IsNumeric())
|
|
{
|
|
OutMessage =
|
|
FString::Printf(TEXT("Metadata value for '%s' is non-numeric : '%s'"), *InKey.ToString(), *InValue);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check blueprint protected function
|
|
if (InKey == NAME_BlueprintProtected)
|
|
{
|
|
if (!ValidateFunctionBlueprintProtected(InField.template Get<UFunction>()))
|
|
{
|
|
OutMessage =
|
|
FString::Printf(TEXT("%s doesn't make sense on static method '%s' in a blueprint function library"),
|
|
*InKey.ToString(), *InField.GetFullName());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check binary operator function
|
|
if (InKey == NAME_CommutativeAssociativeBinaryOperator)
|
|
{
|
|
if (!ValidateFunctionCommutativeAssociativeBinaryOperator(InField.template Get<UFunction>()))
|
|
{
|
|
OutMessage = TEXT(
|
|
"Commutative asssociative binary operators must have exactly 2 parameters of the same type and a return "
|
|
"value.");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// check expand as execs
|
|
if (InKey == NAME_ExpandBoolAsExecs || InKey == NAME_ExpandEnumAsExecs)
|
|
{
|
|
if (!ValidateFunctionExpandAsExecs(InField.template Get<UFunction>(), InValue))
|
|
{
|
|
OutMessage = TEXT("invalid meta data for expand as execs");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check development status
|
|
if (InKey == NAME_DevelopmentStatus)
|
|
{
|
|
const FString EarlyAccessValue(TEXT("EarlyAccess"));
|
|
const FString ExperimentalValue(TEXT("Experimental"));
|
|
if ((InValue != EarlyAccessValue) && (InValue != ExperimentalValue))
|
|
{
|
|
OutMessage = FString::Printf(TEXT("'%s' metadata was '%s' but it must be %s or %s"), *InKey.ToString(),
|
|
*InValue, *ExperimentalValue, *EarlyAccessValue);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check units
|
|
if (InKey == NAME_Units)
|
|
{
|
|
// Check for numeric property
|
|
auto* MaybeProperty = InField.template Get<NumericPropertyMacro>();
|
|
if (MaybeProperty == nullptr && !MaybeProperty->template IsA<StructPropertyMacro>())
|
|
{
|
|
OutMessage = TEXT("'Units' meta data can only be applied to numeric and struct properties");
|
|
return false;
|
|
}
|
|
|
|
if (!FUnitConversion::UnitFromString(*InValue))
|
|
{
|
|
OutMessage = FString::Printf(
|
|
TEXT("Unrecognized units (%s) specified for property '%s'"), *InValue, *InField.GetFullName());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// check documentation policy
|
|
if (InKey == NAME_DocumentationPolicy)
|
|
{
|
|
const TCHAR* StrictValue = TEXT("Strict");
|
|
if (InValue != StrictValue)
|
|
{
|
|
OutMessage =
|
|
FString::Printf(TEXT("'%s' metadata was '%s' but it must be %s"), *InKey.ToString(), *InValue, StrictValue);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief the format validate
|
|
*/
|
|
static TFormatValidator<class FFieldVariant> ValidateFormat;
|
|
|
|
/**
|
|
* @brief add specific meta data to ufield
|
|
* @param InField
|
|
* @param InMetaData
|
|
* @return
|
|
*/
|
|
static bool AddMetaData(UField* InField, TMap<FName, FString>& InMetaData);
|
|
};
|
|
|
|
/**
|
|
* @brief a helper structure used to store the meta data of a class, @see ClassDeclarationMetaData.h/cpp
|
|
* currently, we don't need remove methods, also the caller should ensure the internal data consistence
|
|
* e.g. the show category added should never be added in hide categories...
|
|
*/
|
|
UCLASS()
|
|
class PUERTSEDITOR_API UPEClassMetaData : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
public:
|
|
/**
|
|
* @brief set the class flags, ant notify if placeable specifier is set
|
|
* @param InFlags
|
|
* @param bInPlaceable
|
|
*/
|
|
UFUNCTION()
|
|
void SetClassFlags(int32 InFlags, bool bInPlaceable);
|
|
|
|
/**
|
|
* @brief set the specific meta data
|
|
* @param InName
|
|
* @param InValue
|
|
*/
|
|
UFUNCTION()
|
|
void SetMetaData(const FString& InName, const FString& InValue);
|
|
|
|
/**
|
|
* @brief set the class should be with in
|
|
* @param InClassName
|
|
*/
|
|
UFUNCTION()
|
|
void SetClassWithIn(const FString& InClassName);
|
|
|
|
/**
|
|
* @brief set the configuration name
|
|
* @param InConfigName
|
|
*/
|
|
UFUNCTION()
|
|
void SetConfig(const FString& InConfigName);
|
|
|
|
/**
|
|
* @brief add a category to hide in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddHideCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief add a category to show in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddShowCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief add a sub category to show in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddShowSubCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief add a function to hide in blueprint
|
|
* @param InFunctionName
|
|
*/
|
|
UFUNCTION()
|
|
void AddHideFunction(const FString& InFunctionName);
|
|
|
|
/**
|
|
* @brief add a function to show in blueprint
|
|
* @param InFunctionName
|
|
*/
|
|
UFUNCTION()
|
|
void AddShowFunction(const FString& InFunctionName);
|
|
|
|
/**
|
|
* @brief add a category to auto expand in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddAutoExpandCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief add a category to auto collapse in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddAutoCollapseCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief forbid a category to auto collapse in blueprint
|
|
* @param InCategory
|
|
*/
|
|
UFUNCTION()
|
|
void AddDontAutoCollapseCategory(const FString& InCategory);
|
|
|
|
/**
|
|
* @brief add a class group
|
|
* @param InGroupName
|
|
*/
|
|
UFUNCTION()
|
|
void AddClassGroup(const FString& InGroupName);
|
|
|
|
/**
|
|
* @brief add a sparse data type
|
|
* @param InType
|
|
*/
|
|
UFUNCTION()
|
|
void AddSparseDataType(const FString& InType);
|
|
|
|
public:
|
|
/**
|
|
* @brief apply the meta data to specific class, this should only call at most once
|
|
* since this function will change the internal status of the meta data
|
|
* @param InClass
|
|
* @param InBlueprint
|
|
* @return
|
|
*/
|
|
bool Apply(UClass* InClass, UBlueprint* InBlueprint);
|
|
|
|
private:
|
|
/**
|
|
* @brief the helper function used to get the value array like meta data from the given class
|
|
* @param InClass
|
|
* @param InMetaDataKey
|
|
* @param InDelimiter
|
|
* @param bInCullEmpty
|
|
* @return
|
|
*/
|
|
static TArray<FString> GetClassMetaDataValues(
|
|
UClass* InClass, const TCHAR* InMetaDataKey, const TCHAR* InDelimiter = TEXT(" "), bool bInCullEmpty = true);
|
|
|
|
/**
|
|
* @brief since blueprint compilation will reset class meta data, so make blueprint sync with class
|
|
* @param InClass
|
|
* @param InBlueprint
|
|
*/
|
|
bool SyncClassToBlueprint(UClass* InClass, UBlueprint* InBlueprint);
|
|
|
|
private:
|
|
/**
|
|
* @brief Merges all category properties with the class which at this point only has its parent propagated categories
|
|
* @param InClass
|
|
*/
|
|
void MergeClassCategories(UClass* InClass);
|
|
|
|
/**
|
|
* @brief Merge and validate the class flags, the input class is the class to set meta data
|
|
* @param InClass
|
|
* @return if the class flags is changed
|
|
*/
|
|
bool MergeAndValidateClassFlags(UClass* InClass);
|
|
|
|
/**
|
|
* @brief set the class meta data
|
|
* @param InClass
|
|
* @return
|
|
*/
|
|
bool SetClassMetaData(UClass* InClass);
|
|
|
|
/**
|
|
* @brief set and check with class
|
|
* @param InClass
|
|
*/
|
|
void SetAndValidateWithinClass(UClass* InClass);
|
|
|
|
/**
|
|
* @brief set and check the config name
|
|
* @param InClass
|
|
*/
|
|
void SetAndValidateConfigName(UClass* InClass);
|
|
|
|
public:
|
|
/**
|
|
* @brief the class flags
|
|
*/
|
|
EClassFlags ClassFlags = CLASS_None;
|
|
|
|
/**
|
|
* @brief the meta data
|
|
*/
|
|
TMap<FName, FString> MetaData;
|
|
|
|
/**
|
|
* @brief the class with in
|
|
*/
|
|
FString ClassWithIn;
|
|
|
|
/**
|
|
* @brief the config name, from where the class to read config variables' value
|
|
*/
|
|
FString ConfigName;
|
|
|
|
/**
|
|
* @brief the hide categories in blueprint
|
|
*/
|
|
TArray<FString> HideCategories;
|
|
|
|
/**
|
|
* @brief the show categories in blueprint
|
|
*/
|
|
TArray<FString> ShowCategories;
|
|
|
|
/**
|
|
* @brief the show sub categories in blueprint
|
|
*/
|
|
TArray<FString> ShowSubCategories;
|
|
|
|
/**
|
|
* @brief the hide functions in blueprint
|
|
*/
|
|
TArray<FString> HideFunctions;
|
|
|
|
/**
|
|
* @brief the show functions in blueprint
|
|
*/
|
|
TArray<FString> ShowFunctions;
|
|
|
|
/**
|
|
* @brief the auto expand categories in blueprint
|
|
*/
|
|
TArray<FString> AutoExpandCategories;
|
|
|
|
/**
|
|
* @brief the auto collapse categories in blueprint
|
|
*/
|
|
TArray<FString> AutoCollapseCategories;
|
|
|
|
/**
|
|
* @brief the categories will not auto collapse in blueprint
|
|
*/
|
|
TArray<FString> DontAutoCollapseCategories;
|
|
|
|
/**
|
|
* @brief the class group names
|
|
*/
|
|
TArray<FString> ClassGroupNames;
|
|
|
|
/**
|
|
* @brief the sparse class data types
|
|
*/
|
|
TArray<FString> SparseClassDataTypes;
|
|
|
|
/**
|
|
* @brief a boolean indicate if wants to be placeable
|
|
*/
|
|
bool bWantsToBePlaceable = false;
|
|
|
|
private:
|
|
/**
|
|
* @brief the name of cached category in meta data
|
|
*/
|
|
static const TCHAR* NAME_ClassGroupNames;
|
|
static const TCHAR* NAME_HideCategories;
|
|
static const TCHAR* NAME_ShowCategories;
|
|
static const TCHAR* NAME_SparseClassDataTypes;
|
|
static const TCHAR* NAME_HideFunctions;
|
|
static const TCHAR* NAME_AutoExpandCategories;
|
|
static const TCHAR* NAME_AutoCollapseCategories;
|
|
};
|
|
|
|
/**
|
|
* @brief a helper structure used to store the meta data of a function, @see ParseHelper.h
|
|
*/
|
|
UCLASS()
|
|
class PUERTSEDITOR_API UPEFunctionMetaData : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
private:
|
|
friend class UPEBlueprintAsset;
|
|
|
|
public:
|
|
/**
|
|
* @brief set the function flags, since this will called from js, so divide into high and low parts
|
|
* @param InHighBits
|
|
* @param InLowBits
|
|
*/
|
|
UFUNCTION()
|
|
void SetFunctionFlags(int32 InHighBits, int32 InLowBits);
|
|
|
|
/**
|
|
* @brief set the function export flags
|
|
* @param InFlags
|
|
*/
|
|
UFUNCTION()
|
|
void SetFunctionExportFlags(int32 InFlags);
|
|
|
|
/**
|
|
* @brief set the specific meta data
|
|
* @param InName
|
|
* @param InValue
|
|
*/
|
|
UFUNCTION()
|
|
void SetMetaData(const FString& InName, const FString& InValue);
|
|
|
|
/**
|
|
* @brief set the cpp implementation function, is this meaningful for blueprint function?
|
|
* @param InName
|
|
*/
|
|
UFUNCTION()
|
|
void SetCppImplName(const FString& InName);
|
|
|
|
/**
|
|
* @brief set the cpp implementation validation function
|
|
* @param InName
|
|
*/
|
|
UFUNCTION()
|
|
void SetCppValidationImplName(const FString& InName);
|
|
|
|
/**
|
|
* @brief set the end point name,
|
|
* @param InEndpointName
|
|
*/
|
|
UFUNCTION()
|
|
void SetEndpointName(const FString& InEndpointName);
|
|
|
|
/**
|
|
* @brief set the rpc id
|
|
* @param InRPCId
|
|
*/
|
|
UFUNCTION()
|
|
void SetRPCId(int32 InRPCId);
|
|
|
|
/**
|
|
* @brief set the rpc response id
|
|
* @param InRPCResponseId
|
|
*/
|
|
UFUNCTION()
|
|
void SetRPCResponseId(int32 InRPCResponseId);
|
|
|
|
/**
|
|
* @brief set if the function is sealed event
|
|
* @param bInSealedEvent
|
|
*/
|
|
UFUNCTION()
|
|
void SetIsSealedEvent(bool bInSealedEvent);
|
|
|
|
/**
|
|
* @brief set if the function is force blueprint impure
|
|
* @param bInForceBlueprintImpure
|
|
*/
|
|
UFUNCTION()
|
|
void SetForceBlueprintImpure(bool bInForceBlueprintImpure);
|
|
|
|
public:
|
|
/**
|
|
* @brief apply to a custom event
|
|
* @param InCustomEvent
|
|
*/
|
|
bool Apply(UK2Node_CustomEvent* InCustomEvent) const;
|
|
|
|
/**
|
|
* @brief apply to a normal function
|
|
* @param InFunctionEntry
|
|
*/
|
|
bool Apply(UK2Node_FunctionEntry* InFunctionEntry) const;
|
|
|
|
private:
|
|
/**
|
|
* @brief
|
|
* fallback if the custom event not support the user defined meta data
|
|
* @param bOutChanged
|
|
* @param ...
|
|
*/
|
|
template <typename... Args>
|
|
static void ApplyCustomEventMetaData(bool& bOutChanged, Args&&...)
|
|
{
|
|
bOutChanged = false;
|
|
};
|
|
|
|
/**
|
|
* @brief add user defined meta data for custom event
|
|
* @tparam CustomEvent
|
|
* @param bOutChanged
|
|
* @param InMetaData
|
|
* @param InCustomEvent
|
|
* @return
|
|
*/
|
|
template <typename CustomEvent>
|
|
static auto ApplyCustomEventMetaData(bool& bOutChanged, const TMap<FName, FString>& InMetaData, CustomEvent* InCustomEvent) ->
|
|
typename std::enable_if<true, Void_t<decltype(std::declval<CustomEvent>().GetUserDefinedMetaData())>>::type
|
|
{
|
|
check(IsValid(InCustomEvent));
|
|
|
|
// 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;
|
|
};
|
|
|
|
bool bMetaDataChanged = false;
|
|
auto& MetaDataToSet = InCustomEvent->GetUserDefinedMetaData();
|
|
|
|
bMetaDataChanged = UpdateBooleanMetaData(TEXT("CallInEditor"), InMetaData, MetaDataToSet.bCallInEditor) || bMetaDataChanged;
|
|
bMetaDataChanged = UpdateTextMetaData(TEXT("Category"), InMetaData, MetaDataToSet.Category) || bMetaDataChanged;
|
|
bMetaDataChanged = UpdateTextMetaData(TEXT("Keywords"), InMetaData, MetaDataToSet.Keywords) || bMetaDataChanged;
|
|
bMetaDataChanged =
|
|
UpdateTextMetaData(TEXT("CompactNodeTitle"), InMetaData, MetaDataToSet.CompactNodeTitle) || bMetaDataChanged;
|
|
bMetaDataChanged = UpdateTextMetaData(TEXT("ToolTip"), InMetaData, MetaDataToSet.ToolTip) || bMetaDataChanged;
|
|
bMetaDataChanged =
|
|
UpdateBooleanMetaData(TEXT("DeprecatedFunction"), InMetaData, MetaDataToSet.bIsDeprecated) || bMetaDataChanged;
|
|
bMetaDataChanged =
|
|
UpdateStringMetaData(TEXT("DeprecationMessage"), InMetaData, MetaDataToSet.DeprecationMessage) || bMetaDataChanged;
|
|
|
|
bOutChanged = bMetaDataChanged;
|
|
}
|
|
|
|
public:
|
|
/**
|
|
* @brief the function flags
|
|
*/
|
|
EFunctionFlags FunctionFlags = FUNC_None;
|
|
|
|
/**
|
|
* @brief the function export flags
|
|
*/
|
|
int32 FunctionExportFlags = 0;
|
|
|
|
/**
|
|
* @brief the meta data of the function
|
|
*/
|
|
TMap<FName, FString> MetaData;
|
|
|
|
/**
|
|
* @brief the cpp implementation name, is this ok for blueprint function? or generated function could be a no-blueprint function
|
|
* ?
|
|
*/
|
|
FString CppImplName;
|
|
|
|
/**
|
|
* @brief the cpp validation implementation name,
|
|
*/
|
|
FString CppValidationImplName;
|
|
|
|
/**
|
|
* @brief endpoint name
|
|
*/
|
|
FString EndpointName;
|
|
|
|
/**
|
|
* @brief identifier for an RPC call to a platform service
|
|
*/
|
|
uint16 RPCId = 0;
|
|
|
|
/**
|
|
* @brief identifier for an RPC call expect a response
|
|
*/
|
|
uint16 RPCResponseId = 0;
|
|
|
|
/**
|
|
* @brief whether this function represents a sealed event
|
|
*/
|
|
bool bSealedEvent = false;
|
|
|
|
/**
|
|
* @brief true if the function is being forced to be considered as impure by the user
|
|
*/
|
|
bool bForceBlueprintImpure = false;
|
|
};
|
|
|
|
/**
|
|
* @brief a helper structure used to store the meta data of a function parameter
|
|
*/
|
|
UCLASS()
|
|
class PUERTSEDITOR_API UPEParamMetaData : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
private:
|
|
friend class UPEBlueprintAsset;
|
|
|
|
public:
|
|
/**
|
|
* @brief set the parameter's property flags
|
|
* @param InHighBits
|
|
* @param InLowBits
|
|
*/
|
|
UFUNCTION()
|
|
void SetParamFlags(int32 InHighBits, int32 InLowBits);
|
|
|
|
/**
|
|
* @brief set specific meta data
|
|
* @param InName
|
|
* @param InValue
|
|
*/
|
|
UFUNCTION()
|
|
void SetMetaData(const FString& InName, const FString& InValue);
|
|
|
|
public:
|
|
/**
|
|
* @brief apply to pin type
|
|
* @param PinType
|
|
* @return
|
|
*/
|
|
bool Apply(FEdGraphPinType& PinType) const;
|
|
|
|
private:
|
|
/**
|
|
* @brief the parameter's flags
|
|
*/
|
|
EPropertyFlags ParamFlags;
|
|
|
|
/**
|
|
* @brief the meta data
|
|
*/
|
|
TMap<FName, FString> MetaData;
|
|
};
|
|
|
|
/**
|
|
* @brief a helper function used to store the meta data of a class's member variable
|
|
*/
|
|
UCLASS()
|
|
class PUERTSEDITOR_API UPEPropertyMetaData : public UObject
|
|
{
|
|
GENERATED_BODY()
|
|
|
|
private:
|
|
friend class UPEBlueprintAsset;
|
|
|
|
public:
|
|
/**
|
|
* @brief set the property flags
|
|
* @param InHighBits
|
|
* @param InLowBits
|
|
*/
|
|
UFUNCTION()
|
|
void SetPropertyFlags(int32 InHighBits, int32 InLowBits);
|
|
|
|
/**
|
|
* @brief set the meta data of the property
|
|
* @param InName
|
|
* @param InValue
|
|
*/
|
|
UFUNCTION()
|
|
void SetMetaData(const FString& InName, const FString& InValue);
|
|
|
|
/**
|
|
* @brief set the rep callback name
|
|
* @param InName
|
|
*/
|
|
UFUNCTION()
|
|
void SetRepCallbackName(const FString& InName);
|
|
|
|
public:
|
|
/**
|
|
* @brief apply the meta data to the property
|
|
* @param Element
|
|
*/
|
|
bool Apply(FBPVariableDescription& Element) const;
|
|
|
|
private:
|
|
/**
|
|
* @brief the property's flags
|
|
*/
|
|
EPropertyFlags PropertyFlags;
|
|
|
|
/**
|
|
* @brief the function name for a replicated function
|
|
*/
|
|
FString RepCallbackName;
|
|
|
|
/**
|
|
* @brief the meta data for the property
|
|
*/
|
|
TMap<FName, FString> MetaData;
|
|
};
|