vault backup: 2024-10-12 17:19:45
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
# RestrictedToClasses
|
||||
|
||||
- **功能描述:** 限制蓝图函数库下的函数只能在RestrictedToClasses指定的类蓝图中右键创建出来
|
||||
- **使用位置:** UCLASS
|
||||
- **引擎模块:** Blueprint
|
||||
- **元数据类型:** strings="a,b,c"
|
||||
- **限制类型:** BlueprintFunctionLibrary
|
||||
- **常用程度:** ★★★
|
||||
|
||||
在蓝图函数库上使用,指定该函数库中的函数只能用在RestrictedToClasses指定的类的蓝图中,不能在别的蓝图类中被右键出来。
|
||||
|
||||
## 测试代码:
|
||||
|
||||
```cpp
|
||||
UCLASS(Blueprintable)
|
||||
class INSIDER_API UMyClass_RestrictedToClasses :public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UPROPERTY(BlueprintReadWrite,EditAnywhere)
|
||||
float MyFloat;
|
||||
};
|
||||
|
||||
UCLASS(meta=(RestrictedToClasses="MyClass_RestrictedToClasses"))
|
||||
class INSIDER_API UMyClass_RestrictedToClassesLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
GENERATED_BODY()
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable)
|
||||
static float GetMyClassRestrictedFloat(UMyClass_RestrictedToClasses* myObject) {return myObject->MyFloat;}
|
||||
};
|
||||
```
|
||||
|
||||
在UMyClass_RestrictedToClasses 的子类蓝图中测试效果:
|
||||
|
||||

|
||||
|
||||
在别的地方,比如关卡蓝图中测试效果:
|
||||
|
||||
因此右键创建不出来,但是直接粘贴节点其实还是可以调用的。
|
||||
|
||||

|
||||
|
||||
## 源码中的例子:
|
||||
|
||||
指定UBTFunctionLibrary中的节点,只能在BTNode中使用,否则没有意义。
|
||||
|
||||
```cpp
|
||||
UCLASS(meta=(RestrictedToClasses="BTNode"), MinimalAPI)
|
||||
class UBTFunctionLibrary : public UBlueprintFunctionLibrary
|
||||
{
|
||||
UFUNCTION(BlueprintPure, Category="AI|BehaviorTree", Meta=(HidePin="NodeOwner", DefaultToSelf="NodeOwner"))
|
||||
static AIMODULE_API UBlackboardComponent* GetOwnersBlackboard(UBTNode* NodeOwner);
|
||||
//....
|
||||
}
|
||||
```
|
||||
|
||||
## 原理:
|
||||
|
||||
```cpp
|
||||
static bool BlueprintActionFilterImpl::IsRestrictedClassMember(FBlueprintActionFilter const& Filter, FBlueprintActionInfo& BlueprintAction)
|
||||
{
|
||||
bool bIsFilteredOut = false;
|
||||
FBlueprintActionContext const& FilterContext = Filter.Context;
|
||||
|
||||
if (UClass const* ActionClass = BlueprintAction.GetOwnerClass())
|
||||
{
|
||||
if (ActionClass->HasMetaData(FBlueprintMetadata::MD_RestrictedToClasses))
|
||||
{
|
||||
FString const& ClassRestrictions = ActionClass->GetMetaData(FBlueprintMetadata::MD_RestrictedToClasses);
|
||||
|
||||
// Parse the the metadata into an array that is delimited by ',' and trim whitespace
|
||||
TArray<FString> ParsedClassRestrictions;
|
||||
ClassRestrictions.ParseIntoArray(ParsedClassRestrictions, TEXT(","));
|
||||
for (FString& ValidClassName : ParsedClassRestrictions)
|
||||
{
|
||||
ValidClassName = ValidClassName.TrimStartAndEnd();
|
||||
}
|
||||
|
||||
for (UBlueprint const* TargetContext : FilterContext.Blueprints)
|
||||
{
|
||||
UClass* TargetClass = TargetContext->GeneratedClass;
|
||||
if(!TargetClass)
|
||||
{
|
||||
// Skip possible null classes (e.g. macros, etc)
|
||||
continue;
|
||||
}
|
||||
|
||||
bool bIsClassListed = false;
|
||||
|
||||
UClass const* QueryClass = TargetClass;
|
||||
// walk the class inheritance chain to see if this class is one
|
||||
// of the allowed
|
||||
while (!bIsClassListed && (QueryClass != nullptr))
|
||||
{
|
||||
FString const ClassName = QueryClass->GetName();
|
||||
// If this class is on the list of valid classes
|
||||
for (const FString& ValidClassName : ParsedClassRestrictions)
|
||||
{
|
||||
bIsClassListed = (ClassName == ValidClassName);
|
||||
if (bIsClassListed)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QueryClass = QueryClass->GetSuperClass();
|
||||
}
|
||||
|
||||
// if the blueprint class wasn't listed as one of the few
|
||||
// classes that this can be accessed from, then filter it out
|
||||
if (!bIsClassListed)
|
||||
{
|
||||
bIsFilteredOut = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bIsFilteredOut;
|
||||
}
|
||||
```
|
Binary file not shown.
After Width: | Height: | Size: 63 KiB |
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
Reference in New Issue
Block a user