vault backup: 2024-10-12 17:19:45
@@ -0,0 +1,104 @@
|
||||
# DataTablePin
|
||||
|
||||
- **功能描述:** 指定一个函数参数为DataTable或CurveTable类型,以便为FName的其他参数提供RowNameList的选择。
|
||||
- **使用位置:** UFUNCTION
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** string="abc"
|
||||
- **限制类型:** DataTable,CurveTable
|
||||
- **常用程度:** ★★
|
||||
|
||||
指定一个函数参数为UDataTable类型,这样就可以加载根据DataTable里的数据,为RowName提供一个List来选择,而不是手填。支持的类型是DataTable和CurveTable
|
||||
|
||||
如果是DataTablePin,则会采用UK2Node_CallDataTableFunction来生成蓝图节点,以便在DataTable Pin连接参数改变的时候,触发RowNameList的刷新。
|
||||
|
||||
UK2Node_GetDataTableRow也是一个单独的蓝图节点。
|
||||
|
||||
但是发现RowName并没有用meta指定?但是有判断函数的参数如果类型是FName,就会把它当作RowName来看待。(这么简单粗糙的判断,也是因为其并不打算把这个Meta给用户使用)。因此实际上函数里可以有多个FName的参数,都会被自动的赋予RowNameList
|
||||
|
||||
在源码中用的地方只有UDataTableFunctionLibrary
|
||||
|
||||
```cpp
|
||||
UFUNCTION(BlueprintCallable, Category = "DataTable", meta = (ExpandEnumAsExecs="OutResult", DataTablePin="CurveTable"))
|
||||
static ENGINE_API void EvaluateCurveTableRow(UCurveTable* CurveTable, FName RowName, float InXY, TEnumAsByte<EEvaluateCurveTableResult::Type>& OutResult, float& OutXY,const FString& ContextString);
|
||||
```
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UFUNCTION(BlueprintCallable, meta = (DataTablePin="CurveTable"))
|
||||
static void GetMyCurveTableRow(UCurveTable* CurveTable, FName MyRowName, float InXY, float& OutXY,const FString& ContextString){}
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (DataTablePin="TargetTable"))
|
||||
static bool HasMyDataTableRow(UDataTable* TargetTable, FName MyRowName,FName OtherRowName){return false;}
|
||||
```
|
||||
|
||||
## 蓝图效果:
|
||||
|
||||
左侧为自己定义的函数节点,可以看见左侧的蓝图节点上的Name都变成了CurveTable和DataTable里的RowNameList,即使这些FName参数并没有什么特殊指定,但是蓝图系统里自动识别到FName类型并改变了实际的Pin Widget.
|
||||
|
||||

|
||||
|
||||
## 原理:
|
||||
|
||||
如果发现FName节点,会去尝试找DataTablePin,然后根据DataTablePin的类型来改变FName类型的Pin类型。
|
||||
|
||||
```cpp
|
||||
TSharedPtr<class SGraphPin> FBlueprintGraphPanelPinFactory::CreatePin(class UEdGraphPin* InPin) const
|
||||
{
|
||||
if (InPin->PinType.PinCategory == UEdGraphSchema_K2::PC_Name)
|
||||
{
|
||||
UObject* Outer = InPin->GetOuter();
|
||||
|
||||
// Create drop down combo boxes for DataTable and CurveTable RowName pins
|
||||
const UEdGraphPin* DataTablePin = nullptr;
|
||||
if (Outer->IsA(UK2Node_CallFunction::StaticClass()))
|
||||
{
|
||||
const UK2Node_CallFunction* CallFunctionNode = CastChecked<UK2Node_CallFunction>(Outer);
|
||||
if (CallFunctionNode)
|
||||
{
|
||||
const UFunction* FunctionToCall = CallFunctionNode->GetTargetFunction();
|
||||
if (FunctionToCall)
|
||||
{
|
||||
const FString& DataTablePinName = FunctionToCall->GetMetaData(FBlueprintMetadata::MD_DataTablePin);
|
||||
DataTablePin = CallFunctionNode->FindPin(DataTablePinName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Outer->IsA(UK2Node_GetDataTableRow::StaticClass()))
|
||||
{
|
||||
const UK2Node_GetDataTableRow* GetDataTableRowNode = CastChecked<UK2Node_GetDataTableRow>(Outer);
|
||||
DataTablePin = GetDataTableRowNode->GetDataTablePin();
|
||||
}
|
||||
|
||||
if (DataTablePin)
|
||||
{
|
||||
if (DataTablePin->DefaultObject != nullptr && DataTablePin->LinkedTo.Num() == 0)
|
||||
{
|
||||
if (auto DataTable = Cast<UDataTable>(DataTablePin->DefaultObject))
|
||||
{
|
||||
return SNew(SGraphPinDataTableRowName, InPin, DataTable);
|
||||
}
|
||||
if (DataTablePin->DefaultObject->IsA(UCurveTable::StaticClass()))
|
||||
{
|
||||
UCurveTable* CurveTable = (UCurveTable*)DataTablePin->DefaultObject;
|
||||
if (CurveTable)
|
||||
{
|
||||
TArray<TSharedPtr<FName>> RowNames;
|
||||
/** Extract all the row names from the RowMap */
|
||||
for (TMap<FName, FRealCurve*>::TConstIterator Iterator(CurveTable->GetRowMap()); Iterator; ++Iterator)
|
||||
{
|
||||
/** Create a simple array of the row names */
|
||||
TSharedPtr<FName> RowNameItem = MakeShareable(new FName(Iterator.Key()));
|
||||
RowNames.Add(RowNameItem);
|
||||
}
|
||||
return SNew(SGraphPinNameList, InPin, RowNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
```
|
After Width: | Height: | Size: 110 KiB |
@@ -0,0 +1,43 @@
|
||||
# DisableSplitPin
|
||||
|
||||
- **功能描述:** 禁用Struct的split功能
|
||||
- **使用位置:** USTRUCT
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** bool
|
||||
- **常用程度:** ★★
|
||||
|
||||
对于某些Struct,特别是只有一个成员变量的结构,有时候如果按照默认的展开则会显得很怪。这个时候就希望能够禁用掉这个功能。但是注意依然可以手动在蓝图里Break来访问成员变量。如果在蓝图里也不想暴露成员变量访问,那应该在UPROPERTY上不能加BlueprintReadWrite/BlueprintReadOnly
|
||||
|
||||
在源码里搜索,如FGameplayTag,FPostProcessSettings,FSlatePostSettings
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
USTRUCT(BlueprintType, meta = (DisableSplitPin))
|
||||
struct INSIDER_API FMyStruct_DisableSplitPin
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float MyFloat;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString MyString;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct INSIDER_API FMyStruct_WithSplitPin
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float MyFloat;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString MyString;
|
||||
};
|
||||
```
|
||||
|
||||

|
||||
|
||||
允许的对比
|
||||
|
||||

|
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1,42 @@
|
||||
# HiddenByDefault
|
||||
|
||||
- **功能描述:** Struct的Make Struct和Break Struct节点中的引脚默认为隐藏状态
|
||||
- **使用位置:** USTRUCT
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** bool
|
||||
- **常用程度:** ★
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
//(BlueprintType = true, HiddenByDefault = , ModuleRelativePath = Struct/MyStruct_HiddenByDefault.h)
|
||||
USTRUCT(BlueprintType, meta = (HiddenByDefault))
|
||||
struct INSIDER_API FMyStruct_HiddenByDefault
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float MyFloat;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString MyString;
|
||||
};
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct INSIDER_API FMyStruct_NotHidden
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
float MyFloat;
|
||||
UPROPERTY(BlueprintReadWrite, EditAnywhere)
|
||||
FString MyString;
|
||||
};
|
||||
```
|
||||
|
||||
## 蓝图结果:
|
||||
|
||||

|
||||
|
||||
所谓隐藏,指的是在节点的细节面板里需要手动选择某些属性。而不是像默认的一样一开始就全部自动打开。
|
||||
|
||||

|
After Width: | Height: | Size: 52 KiB |
After Width: | Height: | Size: 84 KiB |
@@ -0,0 +1,170 @@
|
||||
# HidePin
|
||||
|
||||
- **功能描述:** 用在函数调用上,指定要隐藏的参数名称,也可以隐藏返回值。可以隐藏多个参数
|
||||
- **使用位置:** UFUNCTION
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** strings="a,b,c"
|
||||
- **关联项:** [InternalUseParam](../InternalUseParam/InternalUseParam.md)
|
||||
- **常用程度:** ★★
|
||||
|
||||
源码里倒是经常发现和DefaultToSelf比较合同。既隐藏的同时,又有默认值。一起合并的效果是把一个静态函数调用,限制在一个参数直接为外部调用环境对象。
|
||||
|
||||
HidePin的值也经常是WorldContextObject,
|
||||
|
||||
meta = (HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject")
|
||||
|
||||
## C++测试代码:
|
||||
|
||||
```cpp
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class INSIDER_API AMyFunction_HidePinfTest :public AActor
|
||||
{
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
int MyFunc_Default(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (HidePin = "options"))
|
||||
int MyFunc_HidePin(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment"))
|
||||
int MyFunc_HidePin2(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options"))
|
||||
int MyFunc_InternalUseParam(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (HidePin = "ReturnValue"))
|
||||
int MyFunc_HideReturn(FName name, float value, FString options, FString& otherReturn) { return 0; }
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintPure)
|
||||
int MyPure_Default(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (HidePin = "options"))
|
||||
int MyPure_HidePin(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (InternalUseParam = "options"))
|
||||
int MyPure_InternalUseParam(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (HidePin = "ReturnValue"))
|
||||
int MyPure_HideReturn(FName name, float value, FString options, FString& otherReturn) { return 0; }
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment"))
|
||||
int MyFunc_InternalUseParams2(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment,ReturnValue"))
|
||||
int MyFunc_InternalUseParams3(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
## 蓝图测试结果:
|
||||
|
||||

|
||||
|
||||
可以看出BlueprintCallable和BlueprintPure其实都可以。另外ReturnValue是默认的返回值的名字,也可以通过这个来隐藏掉。
|
||||
|
||||
## 原理:
|
||||
|
||||
在源码里搜索,唯一用到的是:
|
||||
|
||||
可以发现以下这些情况的Pin会自动被隐藏:
|
||||
|
||||
- LatentInfo=”ParametertName”
|
||||
- HidePin=”ParametertName”
|
||||
- InternalUseParam=”ParametertName1, ParametertName2”,可以多个
|
||||
- ExpandEnumAsExecs或ExpandBoolAsExecs里面指定的PinNames
|
||||
- WorldContext=”ParametertName”,成员函数被调用,且C++基类有实现GetWorld,这时WorldContext可以自动被赋予正确的World值,就不需要显示出来了。
|
||||
|
||||
这个函数是被CreatePinsForFunctionCall所调用,用来对Function的内部Property进行筛选,也就是Params+ReturnValue,因此是HidePin是不能用来隐藏Target这种Pin的,这种需求应该是HideSelfPin。
|
||||
|
||||
```cpp
|
||||
// Gets a list of pins that should hidden for a given function
|
||||
void FBlueprintEditorUtils::GetHiddenPinsForFunction(UEdGraph const* Graph, UFunction const* Function, TSet<FName>& HiddenPins, TSet<FName>* OutInternalPins)
|
||||
{
|
||||
check(Function != nullptr);
|
||||
TMap<FName, FString>* MetaData = UMetaData::GetMapForObject(Function);
|
||||
if (MetaData != nullptr)
|
||||
{
|
||||
for (TMap<FName, FString>::TConstIterator It(*MetaData); It; ++It)
|
||||
{
|
||||
const FName& Key = It.Key();
|
||||
|
||||
if (Key == FBlueprintMetadata::MD_LatentInfo)
|
||||
{
|
||||
HiddenPins.Add(*It.Value());
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_HidePin)
|
||||
{
|
||||
TArray<FString> HiddenPinNames;
|
||||
It.Value().ParseIntoArray(HiddenPinNames, TEXT(","));
|
||||
for (FString& HiddenPinName : HiddenPinNames)
|
||||
{
|
||||
HiddenPinName.TrimStartAndEndInline();
|
||||
HiddenPins.Add(*HiddenPinName);
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_ExpandEnumAsExecs ||
|
||||
Key == FBlueprintMetadata::MD_ExpandBoolAsExecs)
|
||||
{
|
||||
TArray<FName> EnumPinNames;
|
||||
UK2Node_CallFunction::GetExpandEnumPinNames(Function, EnumPinNames);
|
||||
|
||||
for (const FName& EnumName : EnumPinNames)
|
||||
{
|
||||
HiddenPins.Add(EnumName);
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_InternalUseParam)
|
||||
{
|
||||
TArray<FString> HiddenPinNames;
|
||||
It.Value().ParseIntoArray(HiddenPinNames, TEXT(","));
|
||||
for (FString& HiddenPinName : HiddenPinNames)
|
||||
{
|
||||
HiddenPinName.TrimStartAndEndInline();
|
||||
|
||||
FName HiddenPinFName(*HiddenPinName);
|
||||
HiddenPins.Add(HiddenPinFName);
|
||||
|
||||
if (OutInternalPins)
|
||||
{
|
||||
OutInternalPins->Add(HiddenPinFName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_WorldContext)
|
||||
{
|
||||
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
if(!K2Schema->IsStaticFunctionGraph(Graph))
|
||||
{
|
||||
bool bHasIntrinsicWorldContext = false;
|
||||
|
||||
UBlueprint const* CallingContext = FindBlueprintForGraph(Graph);
|
||||
if (CallingContext && CallingContext->ParentClass)
|
||||
{
|
||||
UClass* NativeOwner = CallingContext->ParentClass;
|
||||
while(NativeOwner && !NativeOwner->IsNative())
|
||||
{
|
||||
NativeOwner = NativeOwner->GetSuperClass();
|
||||
}
|
||||
|
||||
if(NativeOwner)
|
||||
{
|
||||
bHasIntrinsicWorldContext = NativeOwner->GetDefaultObject()->ImplementsGetWorld();
|
||||
}
|
||||
}
|
||||
|
||||
// if the blueprint has world context that we can lookup with "self",
|
||||
// then we can hide this pin (and default it to self)
|
||||
if (bHasIntrinsicWorldContext)
|
||||
{
|
||||
HiddenPins.Add(*It.Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
After Width: | Height: | Size: 214 KiB |
@@ -0,0 +1,99 @@
|
||||
# HideSelfPin
|
||||
|
||||
- **功能描述:** 用在函数调用上,隐藏默认的SelfPin,也就是Target,导致该函数只能在OwnerClass内调用。
|
||||
- **使用位置:** UFUNCTION
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** bool
|
||||
- **常用程度:** ★★
|
||||
|
||||
用在函数调用上,隐藏默认的SelfPin,也就是Target,导致该函数只能在OwnerClass内调用。
|
||||
|
||||
注释里说通常与 DefaultToSelf 说明符共用。但是实际上在源码里没找到例子。
|
||||
|
||||
和HidePin以及InternalUseParam比较类似,不过后者可以隐藏其他参数,HideSelfPin只能隐藏SelfPin
|
||||
|
||||
## 逻辑代码:
|
||||
|
||||
可以看出SelfPin的bHidden 与否,受到一些情况的影响:
|
||||
|
||||
1. 如果是Static 函数(蓝图函数库里的函数,或者C++里的静态函数),因为默认不需要Target来调用,则默认就隐藏起SelfPin.
|
||||
2. 如果函数上带有HideSelfPin标记,则默认也隐藏且不可在外部连接,导致该函数只能在本类内调用。
|
||||
3. 如果函数是BlueprintPure函数,且当前是在OwnerClass内调用,则不需要显示SelfPin。
|
||||
4. 在源码里只找到这一个地方的判断和应用。因此可以认为HidleSelfPin只隐藏Self,意思是只隐藏类成员函数被调用时候的This指针(就是Self,也就是Target),但不会隐藏Static函数被调用时候的参数,哪怕这个参数被DefaultToSelf标识。被DefaultToSelf标志只意味着这个参数的默认值为外部调用环境的Self值,并不是指这个函数节点上的SelfPin,静态函数的SelfPin总是隐藏的。被DefaultToSelf标识的那个参数虽然值等于Self,但并不是SelfPin.
|
||||
|
||||
```cpp
|
||||
bool UK2Node_CallFunction::CreatePinsForFunctionCall(const UFunction* Function)
|
||||
{
|
||||
//...
|
||||
if (bIsStaticFunc)
|
||||
{
|
||||
// For static methods, wire up the self to the CDO of the class if it's not us
|
||||
if (!bIsFunctionCompatibleWithSelf)
|
||||
{
|
||||
UClass* AuthoritativeClass = FunctionOwnerClass->GetAuthoritativeClass();
|
||||
SelfPin->DefaultObject = AuthoritativeClass->GetDefaultObject();
|
||||
}
|
||||
|
||||
// Purity doesn't matter with a static function, we can always hide the self pin since we know how to call the method
|
||||
SelfPin->bHidden = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Function->GetBoolMetaData(FBlueprintMetadata::MD_HideSelfPin))
|
||||
{
|
||||
SelfPin->bHidden = true;
|
||||
SelfPin->bNotConnectable = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide the self pin if the function is compatible with the blueprint class and pure (the !bIsConstFunc portion should be going away soon too hopefully)
|
||||
SelfPin->bHidden = (bIsFunctionCompatibleWithSelf && bIsPureFunc && !bIsConstFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## C++测试代码:
|
||||
|
||||
```cpp
|
||||
UCLASS()
|
||||
class INSIDER_API UMyFunctionLibrary_SelfPinTest :public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UFUNCTION(BlueprintPure,meta=(DefaultToSelf="myOwner",hidePin="myOwner"))
|
||||
static FString PrintProperty_HasDefaultToSelf_ButHide(UObject* myOwner,FName propertyName);
|
||||
|
||||
UFUNCTION(BlueprintPure,meta=(DefaultToSelf="myOwner",HideSelfPin="true"))
|
||||
static FString PrintProperty_HasDefaultToSelf_AndHideSelf(UObject* myOwner,FName propertyName);
|
||||
|
||||
UFUNCTION(BlueprintPure,meta=(DefaultToSelf="myOwner",InternalUseParam="myOwner"))
|
||||
static FString PrintProperty_HasDefaultToSelf_ButInternal(UObject* myOwner,FName propertyName);
|
||||
};
|
||||
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class INSIDER_API AMyFunction_HideSelfTest :public AActor
|
||||
{
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
void MyFunc_Default(int value){}
|
||||
|
||||
UFUNCTION(BlueprintCallable,meta=(HideSelfPin="true"))
|
||||
void MyFunc_HideSelfPin(int value){}
|
||||
};
|
||||
```
|
||||
|
||||
## 蓝图里测试效果:
|
||||
|
||||
从第一个图可以看到,HideSelfPin用在Static函数并无效果。而InternalUseParam可以隐藏引脚。
|
||||
|
||||

|
||||
|
||||
而对于类成员函数的测试结果可以看出:
|
||||
|
||||
- 在类内部调用的时候,self可以被隐藏起来,但都可以调用。二者的区别是,MyFunc_Default这个默认的版本,也可以接受同类型的AMyFunction_HideSelfTest 不同对象实例来调用。而MyFunc_HideSelfPin只能被当前的对象来调用。
|
||||
- 而在左侧关卡蓝图中,通过一个AMyFunction_HideSelfTest 对象尝试调用这两个函数,可以发现MyFunc_Default可以调用,而MyFunc_HideSelfPin这个函数节点就无法被创建出来。就算用复制粘贴的方法硬创造出来,也因为失去了Self这个Target Pin而无法连接,从而无法调用。
|
||||
|
||||

|
After Width: | Height: | Size: 144 KiB |
After Width: | Height: | Size: 63 KiB |
@@ -0,0 +1,156 @@
|
||||
# InternalUseParam
|
||||
|
||||
- **功能描述:** 用在函数调用上,指定要隐藏的参数名称,也可以隐藏返回值。可以隐藏多个参数
|
||||
- **使用位置:** UFUNCTION
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** strings="a,b,c"
|
||||
- **关联项:** [HidePin](../HidePin/HidePin.md)
|
||||
- **常用程度:** ★★
|
||||
|
||||
该元数据和HidePin是等价的。
|
||||
|
||||
## C++测试代码:
|
||||
|
||||
```cpp
|
||||
UCLASS(Blueprintable, BlueprintType)
|
||||
class INSIDER_API AMyFunction_HidePinfTest :public AActor
|
||||
{
|
||||
public:
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
int MyFunc_Default(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (HidePin = "options"))
|
||||
int MyFunc_HidePin(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment"))
|
||||
int MyFunc_HidePin2(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options"))
|
||||
int MyFunc_InternalUseParam(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (HidePin = "ReturnValue"))
|
||||
int MyFunc_HideReturn(FName name, float value, FString options, FString& otherReturn) { return 0; }
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintPure)
|
||||
int MyPure_Default(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (HidePin = "options"))
|
||||
int MyPure_HidePin(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (InternalUseParam = "options"))
|
||||
int MyPure_InternalUseParam(FName name, float value, FString options) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintPure, meta = (HidePin = "ReturnValue"))
|
||||
int MyPure_HideReturn(FName name, float value, FString options, FString& otherReturn) { return 0; }
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment"))
|
||||
int MyFunc_InternalUseParams2(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (InternalUseParam = "options,comment,ReturnValue"))
|
||||
int MyFunc_InternalUseParams3(FName name, float value, FString options,FString comment) { return 0; }
|
||||
|
||||
};
|
||||
```
|
||||
|
||||
## 蓝图测试结果:
|
||||
|
||||

|
||||
|
||||
可以看出BlueprintCallable和BlueprintPure其实都可以。另外ReturnValue是默认的返回值的名字,也可以通过这个来隐藏掉。
|
||||
|
||||
## 原理:
|
||||
|
||||
可见MD_InternalUseParam的使用也是在隐藏引脚。
|
||||
|
||||
```cpp
|
||||
// Gets a list of pins that should hidden for a given function
|
||||
void FBlueprintEditorUtils::GetHiddenPinsForFunction(UEdGraph const* Graph, UFunction const* Function, TSet<FName>& HiddenPins, TSet<FName>* OutInternalPins)
|
||||
{
|
||||
check(Function != nullptr);
|
||||
TMap<FName, FString>* MetaData = UMetaData::GetMapForObject(Function);
|
||||
if (MetaData != nullptr)
|
||||
{
|
||||
for (TMap<FName, FString>::TConstIterator It(*MetaData); It; ++It)
|
||||
{
|
||||
const FName& Key = It.Key();
|
||||
|
||||
if (Key == FBlueprintMetadata::MD_LatentInfo)
|
||||
{
|
||||
HiddenPins.Add(*It.Value());
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_HidePin)
|
||||
{
|
||||
TArray<FString> HiddenPinNames;
|
||||
It.Value().ParseIntoArray(HiddenPinNames, TEXT(","));
|
||||
for (FString& HiddenPinName : HiddenPinNames)
|
||||
{
|
||||
HiddenPinName.TrimStartAndEndInline();
|
||||
HiddenPins.Add(*HiddenPinName);
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_ExpandEnumAsExecs ||
|
||||
Key == FBlueprintMetadata::MD_ExpandBoolAsExecs)
|
||||
{
|
||||
TArray<FName> EnumPinNames;
|
||||
UK2Node_CallFunction::GetExpandEnumPinNames(Function, EnumPinNames);
|
||||
|
||||
for (const FName& EnumName : EnumPinNames)
|
||||
{
|
||||
HiddenPins.Add(EnumName);
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_InternalUseParam)
|
||||
{
|
||||
TArray<FString> HiddenPinNames;
|
||||
It.Value().ParseIntoArray(HiddenPinNames, TEXT(","));
|
||||
for (FString& HiddenPinName : HiddenPinNames)
|
||||
{
|
||||
HiddenPinName.TrimStartAndEndInline();
|
||||
|
||||
FName HiddenPinFName(*HiddenPinName);
|
||||
HiddenPins.Add(HiddenPinFName);
|
||||
|
||||
if (OutInternalPins)
|
||||
{
|
||||
OutInternalPins->Add(HiddenPinFName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (Key == FBlueprintMetadata::MD_WorldContext)
|
||||
{
|
||||
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
||||
if(!K2Schema->IsStaticFunctionGraph(Graph))
|
||||
{
|
||||
bool bHasIntrinsicWorldContext = false;
|
||||
|
||||
UBlueprint const* CallingContext = FindBlueprintForGraph(Graph);
|
||||
if (CallingContext && CallingContext->ParentClass)
|
||||
{
|
||||
UClass* NativeOwner = CallingContext->ParentClass;
|
||||
while(NativeOwner && !NativeOwner->IsNative())
|
||||
{
|
||||
NativeOwner = NativeOwner->GetSuperClass();
|
||||
}
|
||||
|
||||
if(NativeOwner)
|
||||
{
|
||||
bHasIntrinsicWorldContext = NativeOwner->GetDefaultObject()->ImplementsGetWorld();
|
||||
}
|
||||
}
|
||||
|
||||
// if the blueprint has world context that we can lookup with "self",
|
||||
// then we can hide this pin (and default it to self)
|
||||
if (bHasIntrinsicWorldContext)
|
||||
{
|
||||
HiddenPins.Add(*It.Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
After Width: | Height: | Size: 41 KiB |
@@ -0,0 +1,77 @@
|
||||
# PinHiddenByDefault
|
||||
|
||||
- **功能描述:** 使得这个结构里的属性在蓝图里作为引脚时默认是隐藏的。
|
||||
- **使用位置:** UPROPERTY
|
||||
- **引擎模块:** Pin
|
||||
- **元数据类型:** bool
|
||||
- **限制类型:** struct member property
|
||||
- **常用程度:** ★★
|
||||
|
||||
使得这个结构里的属性在蓝图里作为引脚时默认是隐藏的。
|
||||
|
||||
需要注意的是这个meta只作用于结构的成员属性,且只作用在蓝图里的节点。在有些时候一个结构里拥有多个属性,但不是希望一下子暴露所有属性来让用户编辑,有些属性可能是高级属性需要一开始隐藏起来。
|
||||
|
||||
该标记也可以在动画蓝图中,让动画节点的某些属性不暴露成引脚。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
USTRUCT(BlueprintType)
|
||||
struct FMyPinHiddenTestStruct
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category=PinHiddenByDefaultTest)
|
||||
int32 MyInt_NotHidden = 123;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite,Category=PinHiddenByDefaultTest, meta = (PinHiddenByDefault))
|
||||
int32 MyInt_PinHiddenByDefault = 123;
|
||||
};
|
||||
|
||||
UFUNCTION(BlueprintCallable)
|
||||
static FMyPinHiddenTestStruct MyHiddenPinTestFunc(FMyPinHiddenTestStruct Input);
|
||||
```
|
||||
|
||||
## 测试结果:
|
||||
|
||||
可以发现MakeStruct和BreakStruct的节点,默认只有MyInt_NotHidden。当选择该蓝图节点时,可以在右侧细节面板看到MyInt_PinHiddenByDefault 的显示默认没有选中,这就是区别。
|
||||
|
||||
同样的,当该结构当作函数输入和输出参数的时候,当用SplitStuctPin展开结构节点,会发现MyInt_PinHiddenByDefault 也被隐藏了起来。
|
||||
|
||||

|
||||
|
||||
## 原理:
|
||||
|
||||
通过源码可以发现,FStructOperationOptionalPinManager 里使用了该meta,然后FMakeStructPinManager 和FBreakStructPinManager 继承了,从而使得PinHiddenByDefault的Pin一开始不显示。
|
||||
|
||||
```cpp
|
||||
struct FStructOperationOptionalPinManager : public FOptionalPinManager
|
||||
{
|
||||
//~ Begin FOptionalPinsUpdater Interface
|
||||
virtual void GetRecordDefaults(FProperty* TestProperty, FOptionalPinFromProperty& Record) const override
|
||||
{
|
||||
Record.bCanToggleVisibility = true;
|
||||
Record.bShowPin = true;
|
||||
if (TestProperty)
|
||||
{
|
||||
Record.bShowPin = !TestProperty->HasMetaData(TEXT("PinHiddenByDefault"));
|
||||
if (Record.bShowPin)
|
||||
{
|
||||
if (UStruct* OwnerStruct = TestProperty->GetOwnerStruct())
|
||||
{
|
||||
Record.bShowPin = !OwnerStruct->HasMetaData(TEXT("HiddenByDefault"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void CustomizePinData(UEdGraphPin* Pin, FName SourcePropertyName, int32 ArrayIndex, FProperty* Property) const override;
|
||||
// End of FOptionalPinsUpdater interfac
|
||||
};
|
||||
|
||||
struct FMakeStructPinManager : public FStructOperationOptionalPinManager
|
||||
{}
|
||||
struct FBreakStructPinManager : public FStructOperationOptionalPinManager
|
||||
{}
|
||||
|
||||
```
|
After Width: | Height: | Size: 100 KiB |