vault backup: 2024-10-12 17:19:45

This commit is contained in:
2024-10-12 17:19:46 +08:00
parent ff94ddca61
commit 244c0c52f6
960 changed files with 31348 additions and 10 deletions

View File

@@ -0,0 +1,9 @@
# DisallowedAssetDataTags
- **功能描述:** 在UObject*属性上指定Tags来进行过滤必须没有拥有该Tags才可以被选择。
- **使用位置:** UPROPERTY
- **引擎模块:** Asset Property
- **元数据类型:** strings="a=bc=de=f"
- **限制类型:** UObject*
- **关联项:** [RequiredAssetDataTags](RequiredAssetDataTags/RequiredAssetDataTags.md), [AssetRegistrySearchable](../../Specifier/UPROPERTY/Asset/AssetRegistrySearchable/AssetRegistrySearchable.md)
- **常用程度:** ★★

View File

@@ -0,0 +1,59 @@
# ForceShowEngineContent
- **功能描述:** 指定UObject*属性的资源可选列表里强制可选引擎的内建资源
- **使用位置:** UPROPERTY
- **引擎模块:** Asset Property
- **元数据类型:** bool
- **限制类型:** UObject*
- **关联项:** [ForceShowPluginContent](ForceShowPluginContent.md)
- **常用程度:** ★★
指定UObject*属性的资源可选列表里强制可选引擎的内建资源。
## 测试代码:
```cpp
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyProperty_ShowContent :public UDataAsset
{
public:
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
TObjectPtr<UObject> MyAsset_Default;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object, meta = (ForceShowEngineContent))
TObjectPtr<UObject> MyAsset_ForceShowEngineContent;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object, meta = (ForceShowPluginContent))
TObjectPtr<UObject> MyAsset_ForceShowPluginContent;
};
```
## 测试结果:
可见MyAsset_Default默认是只包含本项目的资源。
MyAsset_ForceShowEngineContent的作用其实就是在选项卡里勾选ShowEngineContent因此结果上会发现多了非常多的可选资源。
MyAsset_ForceShowPluginContent的作用同样是在选项卡里勾选ShowPluginContent可以选择别的插件里的资源。
![Untitled](Untitled.png)
## 原理:
在属性的资源选择器里会尝试寻找ForceShowEngineContent和ForceShowPluginContent然后设置到AssetPickerConfig里从而改变资源的可选类型。
```cpp
void SPropertyMenuAssetPicker::Construct( const FArguments& InArgs )
{
const bool bForceShowEngineContent = PropertyHandle ? PropertyHandle->HasMetaData(TEXT("ForceShowEngineContent")) : false;
const bool bForceShowPluginContent = PropertyHandle ? PropertyHandle->HasMetaData(TEXT("ForceShowPluginContent")) : false;
FAssetPickerConfig AssetPickerConfig;
// Force show engine content if meta data says so
AssetPickerConfig.bForceShowEngineContent = bForceShowEngineContent;
// Force show plugin content if meta data says so
AssetPickerConfig.bForceShowPluginContent = bForceShowPluginContent;
}
```

View File

@@ -0,0 +1,8 @@
# ForceShowPluginContent
- **功能描述:** 指定UObject*属性的资源可选列表里强制可选其他插件里的内建资源
- **使用位置:** UPROPERTY
- **引擎模块:** Asset Property
- **元数据类型:** bool
- **限制类型:** UObject*
- **关联项:** [ForceShowEngineContent](ForceShowEngineContent.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

View File

@@ -0,0 +1,77 @@
# GetAssetFilter
- **功能描述:** 指定一个UFUNCTION来对UObject*属性的可选资源进行排除过滤。
- **使用位置:** UPROPERTY
- **引擎模块:** Asset Property
- **元数据类型:** string="abc"
- **限制类型:** UObject*
- **常用程度:** ★★★
指定一个UFUNCTION来对UObject*属性的可选资源进行排除过滤。
- 指定的函数名字必须是UFUNCTION在本类中定义。
- 函数的原型是bool FuncName(const FAssetData& AssetData) const;返回true来排除掉该资产。
- 这是一种让用户自定义资产过滤的方式。
## 测试代码:
```cpp
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyProperty_GetAssetFilter :public UDataAsset
{
public:
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UObject* MyAsset_Default;
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (GetAssetFilter = "IsShouldFilterAsset"))
UObject* MyAsset_GetAssetFilter;
public:
UFUNCTION()
bool IsShouldFilterAsset(const FAssetData& AssetData)
{
return !AssetData.IsInstanceOf<UDataAsset>();
}
};
```
## 测试效果:
可以见到MyAsset_GetAssetFilter进行过滤后只允许DataAsset类型的资产。
![Untitled](Untitled.png)
## 原理:
在SPropertyEditorAsset对应UObject类型属性中有判断GetAssetFilter的meta得到函数并附加到资产排除的回调里去。
```cpp
void SPropertyEditorAsset::Construct(const FArguments& InArgs, const TSharedPtr<FPropertyEditor>& InPropertyEditor)
{
if (Property && Property->GetOwnerProperty()->HasMetaData("GetAssetFilter"))
{
// Add MetaData asset filter
const FString GetAssetFilterFunctionName = Property->GetOwnerProperty()->GetMetaData("GetAssetFilter");
if (!GetAssetFilterFunctionName.IsEmpty())
{
TArray<UObject*> ObjectList;
if (PropertyEditor.IsValid())
{
PropertyEditor->GetPropertyHandle()->GetOuterObjects(ObjectList);
}
else if (PropertyHandle.IsValid())
{
PropertyHandle->GetOuterObjects(ObjectList);
}
for (UObject* Object : ObjectList)
{
const UFunction* GetAssetFilterFunction = Object ? Object->FindFunction(*GetAssetFilterFunctionName) : nullptr;
if (GetAssetFilterFunction)
{
AppendOnShouldFilterAssetCallback(FOnShouldFilterAsset::CreateUFunction(Object, GetAssetFilterFunction->GetFName()));
}
}
}
}
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

View File

@@ -0,0 +1,208 @@
# RequiredAssetDataTags
- **功能描述:** 在UObject*属性上指定Tags来进行过滤必须拥有该Tags才可以被选择。
- **使用位置:** UPROPERTY
- **引擎模块:** Asset Property
- **元数据类型:** strings="a=bc=de=f"
- **限制类型:** UObject*
- **关联项:** [DisallowedAssetDataTags](../DisallowedAssetDataTags.md), [AssetRegistrySearchable](../../../Specifier/UPROPERTY/Asset/AssetRegistrySearchable/AssetRegistrySearchable.md)
- **常用程度:** ★★
在UObject*属性上指定Tags来进行过滤必须拥有该Tags才可以被选择。
相关联的可参考AssetRegistrySearchable标识符和GetAssetRegistryTags 方法。
## 测试代码:
```cpp
USTRUCT(BlueprintType)
struct INSIDER_API FMyTableRow_Required :public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
int32 MyInt = 123;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
FString MyString;
};
USTRUCT(BlueprintType)
struct INSIDER_API FMyTableRow_Disallowed :public FTableRowBase
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere)
float MyFloat = 123.f;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
UTexture2D* MyTexture;
};
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyProperty_AssetDataTags :public UDataAsset
{
public:
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object)
TObjectPtr<UObject> MyAsset_Default;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object, meta = (RequiredAssetDataTags = "MyIdForSearch=MyId456"))
TObjectPtr<UObject> MyAsset_RequiredAssetDataTags;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Object, meta = (DisallowedAssetDataTags = "MyOtherId=MyOtherId789"))
TObjectPtr<UObject> MyAsset_DisallowedAssetDataTags;
public:
UPROPERTY(EditAnywhere, Category = DataTable)
TObjectPtr<class UDataTable> MyDataTable_Default;
UPROPERTY(EditAnywhere, Category = DataTable, meta = (RequiredAssetDataTags = "RowStructure=/Script/Insider.MyTableRow_Required"))
TObjectPtr<class UDataTable> MyDataTable_RequiredAssetDataTags;
UPROPERTY(EditAnywhere, Category = DataTable, meta = (DisallowedAssetDataTags = "RowStructure=/Script/Insider.MyTableRow_Disallowed"))
TObjectPtr<class UDataTable> MyDataTable_DisallowedAssetDataTags;
};
```
## 测试效果:
如上面代码所见定义了两个不同类型的FTableRowBase并且也创建了两个DataTable。同时也有两个DataAssetAssetRegistrySearchable的例子里定义的结构都有MyIdForSearch和MyOtherId的Tag但是有不同的值以此来进行区分。
- MyAsset_Default可以筛选出所有的对象图中示例有730个。
- MyAsset_RequiredAssetDataTags因为加了RequiredAssetDataTags 只有DA_MyPropertySearch符合因为MyIdForSearch=MyId456。
- MyAsset_DisallowedAssetDataTags把DA_MyPropertySearch_Disallowed过滤掉了因为我配置的MyOtherId=MyOtherId789因此只剩下729个。
- 关于DataTable也是同理。MyDataTable_Default可以获取所有的DataTable有3个而MyDataTable_RequiredAssetDataTags限制了RowStructure只能是FMyTableRow_Required 因此只能筛选出一个。MyDataTable_DisallowedAssetDataTags排除掉一个RowStructure为FMyTableRow_Disallowed 的因此就剩下2个。
![Untitled](Untitled.png)
## 源码中例子:
```cpp
UPROPERTY(Category="StateTree", EditAnywhere, meta=(RequiredAssetDataTags="Schema=/Script/MassAIBehavior.MassStateTreeSchema"))
TObjectPtr<UStateTree> StateTree;
UPROPERTY(EditAnywhere, Category=Appearance, meta = (RequiredAssetDataTags = "RowStructure=/Script/UMG.RichImageRow"))
TObjectPtr<class UDataTable> ImageSet;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=Compositing, meta = (AllowPrivateAccess, RequiredAssetDataTags = "IsSourceValid=True"), Setter = SetCompositeTexture, Getter = GetCompositeTexture)
TObjectPtr<class UTexture> CompositeTexture;
```
## 原理:
在UObject*属性上RequiredAssetDataTags和DisallowedAssetDataTags的配置会在这个属性的编辑器SPropertyEditorAsset初始化的时候解析提取到其成员变量RequiredAssetDataTags和DisallowedAssetDataTags里本质就是个键值对。而后续在进行Asset过滤的时候IsAssetFiltered的调用就会开始把FAssetData里的Tags去匹配该属性的Tags需求。Disallowed的出现就排除掉Required的必须拥有才不会被过滤最终实现了过滤效果。
关于FAssetData里的Tags可以参考AssetRegistrySearchable标识符和GetAssetRegistryTags 方法的调用和实现简单来说就是在对象上会有个方式主动提供Tags给AssetRegistry。
关于DataTable为何可以通过RowStructure过滤通过查看DataTable里的GetAssetRegistryTags方法就可以知道它主动提供了RowStructure的Tags注册。
```cpp
FAssetDataTagMapBase=TSortedMap<FName, FString, FDefaultAllocator, FNameFastLess>;
SPropertyEditorAsset::
/** Tags (and eventually values) that can NOT be used with this property */
TSharedPtr<FAssetDataTagMap> DisallowedAssetDataTags;
**/** Tags and values that must be present for an asset to be used with this property */
TSharedPtr<FAssetDataTagMap> RequiredAssetDataTags;
void SPropertyEditorAsset::InitializeAssetDataTags(const FProperty* Property)
{
if (Property == nullptr)
{
return;
}
const FProperty* MetadataProperty = GetActualMetadataProperty(Property);
const FString DisallowedAssetDataTagsFilterString = MetadataProperty->GetMetaData("DisallowedAssetDataTags");
if (!DisallowedAssetDataTagsFilterString.IsEmpty())
{
TArray<FString> DisallowedAssetDataTagsAndValues;
DisallowedAssetDataTagsFilterString.ParseIntoArray(DisallowedAssetDataTagsAndValues, TEXT(","), true);
for (const FString& TagAndOptionalValueString : DisallowedAssetDataTagsAndValues)
{
TArray<FString> TagAndOptionalValue;
TagAndOptionalValueString.ParseIntoArray(TagAndOptionalValue, TEXT("="), true);
size_t NumStrings = TagAndOptionalValue.Num();
check((NumStrings == 1) || (NumStrings == 2)); // there should be a single '=' within a tag/value pair
if (!DisallowedAssetDataTags.IsValid())
{
DisallowedAssetDataTags = MakeShared<FAssetDataTagMap>();
}
DisallowedAssetDataTags->Add(FName(*TagAndOptionalValue[0]), (NumStrings > 1) ? TagAndOptionalValue[1] : FString());
}
}
const FString RequiredAssetDataTagsFilterString = MetadataProperty->GetMetaData("RequiredAssetDataTags");
if (!RequiredAssetDataTagsFilterString.IsEmpty())
{
TArray<FString> RequiredAssetDataTagsAndValues;
RequiredAssetDataTagsFilterString.ParseIntoArray(RequiredAssetDataTagsAndValues, TEXT(","), true);
for (const FString& TagAndOptionalValueString : RequiredAssetDataTagsAndValues)
{
TArray<FString> TagAndOptionalValue;
TagAndOptionalValueString.ParseIntoArray(TagAndOptionalValue, TEXT("="), true);
size_t NumStrings = TagAndOptionalValue.Num();
check((NumStrings == 1) || (NumStrings == 2)); // there should be a single '=' within a tag/value pair
if (!RequiredAssetDataTags.IsValid())
{
RequiredAssetDataTags = MakeShared<FAssetDataTagMap>();
}
RequiredAssetDataTags->Add(FName(*TagAndOptionalValue[0]), (NumStrings > 1) ? TagAndOptionalValue[1] : FString());
}
}
}
bool SPropertyEditorAsset::IsAssetFiltered(const FAssetData& InAssetData)
{
//判断只要包含就不符合
if (DisallowedAssetDataTags.IsValid())
{
for (const auto& DisallowedTagAndValue : *DisallowedAssetDataTags.Get())
{
if (InAssetData.TagsAndValues.ContainsKeyValue(DisallowedTagAndValue.Key, DisallowedTagAndValue.Value))
{
return true;
}
}
}
//判断必须包含才不会被过滤掉
if (RequiredAssetDataTags.IsValid())
{
for (const auto& RequiredTagAndValue : *RequiredAssetDataTags.Get())
{
if (!InAssetData.TagsAndValues.ContainsKeyValue(RequiredTagAndValue.Key, RequiredTagAndValue.Value))
{
// For backwards compatibility compare against short name version of the tag value.
if (!FPackageName::IsShortPackageName(RequiredTagAndValue.Value) &&
InAssetData.TagsAndValues.ContainsKeyValue(RequiredTagAndValue.Key, FPackageName::ObjectPathToObjectName(RequiredTagAndValue.Value)))
{
continue;
}
return true;
}
}
}
return false;
}
void UDataTable::GetAssetRegistryTags(FAssetRegistryTagsContext Context) const
{
if (AssetImportData)
{
Context.AddTag( FAssetRegistryTag(SourceFileTagName(), AssetImportData->GetSourceData().ToJson(), FAssetRegistryTag::TT_Hidden) );
}
// Add the row structure tag
{
static const FName RowStructureTag = "RowStructure";
Context.AddTag( FAssetRegistryTag(RowStructureTag, GetRowStructPathName().ToString(), FAssetRegistryTag::TT_Alphabetical) );
}
Super::GetAssetRegistryTags(Context);
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 KiB