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,112 @@
# DefaultToInstanced
- **功能描述:** 指定该类的所有实例属性都默认是UPROPERTY(instanced),即都默认创建新的实例,而不是对对象的引用。
- **引擎模块:** Instance
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中添加[CLASS_DefaultToInstanced](../../../../Flags/EClassFlags/CLASS_DefaultToInstanced.md)
- **常用程度:★★★★**
指定该类的所有实例属性都默认是UPROPERTY(instanced),即都默认创建新的实例,而不是对对象的引用。
UPROPERTY(instanced)的含义是造成Property的CPF_InstancedReference即为该属性创建对象实例。
所谓实例指的是为该UObject指针创建一个对象而不是默认的去找到引擎内已有的对象的来引用。
也常常和EditInlineNew配合使用以便在细节面板中可以创建对象实例。
UActorComponent本身就是带有DefaultToInstanced的。
## 示例代码:
```cpp
UCLASS(Blueprintable)
class INSIDER_API UMyClass_NotDefaultToInstanced :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
// ClassFlags: CLASS_MatchedSerializers | CLASS_Native | CLASS_RequiredAPI | CLASS_DefaultToInstanced | CLASS_TokenStreamAssembled | CLASS_Intrinsic | CLASS_Constructed
UCLASS(Blueprintable, DefaultToInstanced)
class INSIDER_API UMyClass_DefaultToInstanced :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
// ClassFlags: CLASS_MatchedSerializers | CLASS_Native | CLASS_EditInlineNew | CLASS_RequiredAPI | CLASS_DefaultToInstanced | CLASS_TokenStreamAssembled | CLASS_Intrinsic | CLASS_Constructed
UCLASS(Blueprintable, DefaultToInstanced, EditInlineNew)
class INSIDER_API UMyClass_DefaultToInstanced_EditInlineNew :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
UCLASS(Blueprintable, EditInlineNew)
class INSIDER_API UMyClass_NotDefaultToInstanced_EditInlineNew :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyClass_DefaultToInstanced_Test :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NormalProperty")
UMyClass_NotDefaultToInstanced* MyObject_NotDefaultToInstanced;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "NormalProperty")
UMyClass_DefaultToInstanced* MyObject_DefaultToInstanced;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "NormalProperty | Instanced")
UMyClass_NotDefaultToInstanced* MyObject_NotDefaultToInstanced_Instanced;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "NormalProperty | Instanced")
UMyClass_DefaultToInstanced* MyObject_DefaultToInstanced_Instanced;
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EditInlineNew")
UMyClass_NotDefaultToInstanced_EditInlineNew* MyObject_NotDefaultToInstanced_EditInlineNew;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "EditInlineNew")
UMyClass_DefaultToInstanced_EditInlineNew* MyObject_DefaultToInstanced_EditInlineNew;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "EditInlineNew | Instanced")
UMyClass_NotDefaultToInstanced_EditInlineNew* MyObject_NotDefaultToInstanced_EditInlineNew_Instanced;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = "EditInlineNew | Instanced")
UMyClass_DefaultToInstanced_EditInlineNew* MyObject_DefaultToInstanced_EditInlineNew_Instanced;
};
```
## 示例效果:
- MyObject_NotDefaultToInstanced和MyObject_NotDefaultToInstanced_EditInlineNew因为属性没有instanced的标记因此打开是一个选择对象引用的列表。
- MyObject_DefaultToInstanced因为类上有DefaultToInstanced因此该属性是Instanced。当然我们也可以手动给属性加上Instanced标记正如MyObject_NotDefaultToInstanced_Instanced和MyObject_DefaultToInstanced_Instanced。出现了创建实例的窗口但是还不能创建在细节面板里直接创建对象。
- MyObject_DefaultToInstanced_EditInlineNewMyObject_NotDefaultToInstanced_EditInlineNew_InstancedMyObject_DefaultToInstanced_EditInlineNew_Instanced这3个都可以直接在细节面板创建对象实例。是因为这个类本身要有EditInlineNew另外这个属性要有Instanced要嘛在该类上设置DefaultToInstanced以此该类的所有属性都自动是Instanced或者在属性上单个设置Instanced
![image](image.png)
## 原理:
```cpp
UObject* FObjectInstancingGraph::InstancePropertyValue(UObject* SubObjectTemplate, UObject* CurrentValue, UObject* Owner, EInstancePropertyValueFlags Flags)
{
if (CurrentValue->GetClass()->HasAnyClassFlags(CLASS_DefaultToInstanced))
{
bCausesInstancing = true; // these are always instanced no matter what
}
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

View File

@@ -0,0 +1,80 @@
# EditInlineNew
- **功能描述:** 指定该类的对象可以在属性细节面板里直接内联创建要和属性的Instanced配合。
- **引擎模块:** Instance
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中添加[CLASS_EditInlineNew](../../../../Flags/EClassFlags/CLASS_EditInlineNew.md)
- **关联项:** NotEditInlineNew (NotEditInlineNew.md)
- **常用程度:★★★★★**
指定该类的对象可以在属性细节面板里直接内联创建。
如果想在细节面板里直接创建对象属性上也必须先标记Instanced或ShowInnerProperties。
EditInlineNew主要是用在UObject的子类上一般不标EditInlineNew的是用在Actor或资产的引用上。注意EditInlineNew是表明增加从属性细节面板里直接创建对象实例的能力而非限制只能在属性细节面板里创建当然也可以自己手动NewObject再赋值给对象引用属性。
这个跟UPROPERTY上的Instanced能力是独立的。如果UCLASS上不加EditInlineNew但是属性上加上Instanced则在手动NewObject赋值该属性后该属性也会展开内部属性来提供编辑功能。因为Instanced的属性会自动的在property上加上EditInline的meta。
此说明符会传播到所有子类;子类可通过 NotEditInlineNew 说明符覆盖它。
## 示例代码:
```cpp
UCLASS(Blueprintable, EditInlineNew)
class INSIDER_API UMyClass_EditInlineNew :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
UCLASS(Blueprintable, NotEditInlineNew)
class INSIDER_API UMyClass_NotEditInlineNew :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty;
};
UCLASS(Blueprintable, BlueprintType)
class INSIDER_API UMyClass_Edit_Test :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = InstancedProperty)
UMyClass_EditInlineNew* MyEditInlineNew;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Instanced, Category = InstancedProperty)
UMyClass_NotEditInlineNew* MyNotEditInlineNew;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NormalProperty)
UMyClass_EditInlineNew* MyEditInlineNew_NotInstanced;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = NormalProperty)
UMyClass_NotEditInlineNew* MyNotEditInlineNew_NotInstanced;
};
```
## 示例效果:
EditInlineNew支持直接C++或BP子类创建对象实例然后在上面编辑实例。
而NotEditInlineNew的属性则无法找到支持的类来创建对象。
如果属性上没有Instanced则只能尝试去引用找不到对象
![image](image.png)
## 原理:
判断该类是否有CLASS_EditInlineNew来决定是否可内联创建编辑。
```cpp
template <typename TClass, typename TIsChildOfFunction>
bool FPropertyEditorInlineClassFilter::IsClassAllowedHelper(TClass InClass, TIsChildOfFunction IsClassChildOf, TSharedRef< FClassViewerFilterFuncs > InFilterFuncs)
{
const bool bMatchesFlags = InClass->HasAnyClassFlags(CLASS_EditInlineNew) &&
!InClass->HasAnyClassFlags(CLASS_Hidden | CLASS_HideDropDown | CLASS_Deprecated) &&
(bAllowAbstract || !InClass->HasAnyClassFlags(CLASS_Abstract));
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

View File

@@ -0,0 +1,8 @@
# NotEditInlineNew
- **功能描述:** 不能通过EditInline按钮创建
- **引擎模块:** Instance
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中移除[CLASS_EditInlineNew](../../../Flags/EClassFlags/CLASS_EditInlineNew.md)
- **关联项:** EditInlineNew (EditInlineNew.md)
- **常用程度:★**

View File

@@ -0,0 +1,70 @@
# Within
- **功能描述:** 指定对象创建的时候必须依赖于OuterClassName的对象作为Outer。
- **引擎模块:** Instance
- **元数据类型:** string="abc"
- **作用机制:** 保存在UClass* UClass::ClassWithin=XXX的XXX中
- **常用程度:★★★**
指定对象创建的时候必须依赖于OuterClassName的对象作为Outer。
此类的对象无法在OuterClassName对象的实例之外存在。这意味着要创建此类的对象需要提供OuterClassName的一个实例作为其Outer对象。
本类在这种情况一般是用来当做子对象来使用的。
## 示例代码:
```cpp
UCLASS(Within= MyClass_Within_Outer)
class INSIDER_API UMyClass_Within :public UObject
{
GENERATED_BODY()
};
UCLASS()
class INSIDER_API UMyClass_Within_Outer :public UObject
{
GENERATED_BODY()
public:
};
```
## 示例结果:
```cpp
//错误Fatal error: Object MyClass_Within None created in Package instead of MyClass_Within_Outer
UMyClass_Within* obj=NewObject<UMyClass_Within>();
//正确:
UMyClass_Within_Outer* objOuter = NewObject<UMyClass_Within_Outer>();
UMyClass_Within* obj=NewObject<UMyClass_Within>(objOuter);
```
## 原理:
生成的UClass的字段UClass* ClassWithin会保存这个信息然后在创建的时候StaticAllocateObject会测试 check(bCreatingCDO || !InOuter || InOuter->IsA(InClass->ClassWithin))。因此需要先创建Within的对象。
```cpp
bool StaticAllocateObjectErrorTests( const UClass* InClass, UObject* InOuter, FName InName, EObjectFlags InFlags)
{
if ( (InFlags & (RF_ClassDefaultObject|RF_ArchetypeObject)) == 0 )
{
if ( InOuter != NULL && !InOuter->IsA(InClass->ClassWithin) )
{
UE_LOG(LogUObjectGlobals, Fatal, TEXT("%s"), *FString::Printf( TEXT("Object %s %s created in %s instead of %s"), *InClass->GetName(), *InName.ToString(), *InOuter->GetClass()->GetName(), *InClass->ClassWithin->GetName()) );
return true;
}
}
}
```
在源码里可以搜索到很多Within的用法
UCLASS(Within=Engine, config=Engine, transient)
class ENGINE_API ULocalPlayer
UCLASS(Abstract, DefaultToInstanced, Within=UserWidget)
class UMG_API UUserWidgetExtension : public UObject
{