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,58 @@
# Config
- **功能描述:** 指定配置文件的名字把该对象的值保存到ini配置文件中。
- **引擎模块:** Config
- **元数据类型:** string="abc"
- **作用机制:** Config文件名存在FName UClass::ClassConfigName这个参数里
- **关联项:** [PerObjectConfig](PerObjectConfig.md)、[ConfigDoNotCheckDefaults](ConfigDoNotCheckDefaults.md)、[DefaultConfig](DefaultConfig/DefaultConfig.md)、[GlobalUserConfig](GlobalUserConfig/GlobalUserConfig.md)、[ProjectUserConfig](ProjectUserConfig/ProjectUserConfig.md)
- **常用程度:★★★★★**
指定配置文件的名字把该对象的值保存到ini配置文件中。
- 一整个类在ini中只有一个节的值因此一般是保存的CDO对象但也可以用普通对象。
- Config文件名称的元数据值保存在FName UClass::ClassConfigName。
- 默认是保存在Saved/XXX.ini的Local文件中。
- 此说明符会传播到所有子类并且无法使此说明符无效但是子类可通过重新声明config说明符并提供不同的ConfigName来更改配置文件。
- 常见的ConfigName值是“Engine”、“Editor”、“Input”和“Game”。
- 可以自己手动调用SaveConfig和LoadConfig来读写配置值。CDO的值会被引擎自己的从配置中读取而更新。
- 想保存到配置文件里的属性要相应的用UPROPERTY(config)修饰。
## 示例代码:
```cpp
UCLASS(Config = Game)
class INSIDER_API UMyClass_Config :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
};
//测试代码
UMyClass_Config* testObject = NewObject<UMyClass_Config>(GetTransientPackage(),TEXT("testObject"));
testObject->SaveConfig();
//生成
\Hello\Saved\Config\WindowsEditor\Game.ini
[/Script/Insider.MyClass_Config]
MyPropertyWithConfig=123
```
## 原理:
在引擎启动的时候UObjectLoadAllCompiledInDefaultProperties会加载所有Class的CDO在多个调用链条之后会自动的调用CDO的LoadConfig来初始化CDO的值。
```cpp
static void UObjectLoadAllCompiledInDefaultProperties(TArray<UClass*>& OutAllNewClasses)
{
for (UClass* Class : NewClasses)
{
UE_LOG(LogUObjectBootstrap, Verbose, TEXT("GetDefaultObject Begin %s %s"), *Class->GetOutermost()->GetName(), *Class->GetName());
Class->GetDefaultObject();
UE_LOG(LogUObjectBootstrap, Verbose, TEXT("GetDefaultObject End %s %s"), *Class->GetOutermost()->GetName(), *Class->GetName());
}
}
```

View File

@@ -0,0 +1,93 @@
# ConfigDoNotCheckDefaults
- **功能描述:** 指定在保存配置值的时候忽略上一级的配置值的一致性检查。
- **引擎模块:** Config
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中增加[CLASS_ConfigDoNotCheckDefaults](../../../Flags/EClassFlags/CLASS_ConfigDoNotCheckDefaults.md)
- **关联项:** [Config](Config.md)
- **常用程度:★**
指定在保存配置值的时候忽略上一级的配置值的一致性检查。
- 在保存配置的时候决定是否要先根据Base或Default的配置来检查属性是否一致如果一致就不用序列化写入下来。但加上这个标志后即使同上一个层级的配置值相同也无论如何都要保存下来。
UCLASS(config=XXX,configdonotcheckdefaults)表示这个类对应的配置文件不会检查XXX层级上层的DefaultXXX配置文件是否有该信息后面会解释层级就直接存储到Saved目录下。
## 示例代码:
```cpp
UCLASS(Config = Game)
class INSIDER_API UMyClass_Config :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
};
UCLASS(Config = Game,configdonotcheckdefaults)
class INSIDER_API UMyClass_ConfigDoNotCheckDefaults :public UMyClass_Config
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfigSub = 123;
};
UCLASS(Config = Game)
class INSIDER_API UMyClass_ConfigDefaultChild :public UMyClass_Config
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfigSub = 123;
};
```
## 示例效果:
```cpp
void UMyClass_Config_Test::TestConfigCheckDefaultSave()
{
auto* testObject = NewObject<UMyClass_ConfigDoNotCheckDefaults>(GetTransientPackage(), TEXT("testObjectCheckDefault"));
auto* testObject2 = NewObject<UMyClass_ConfigDefaultChild>(GetTransientPackage(), TEXT("testObjectDefaultChild"));
testObject->SaveConfig();
testObject2->SaveConfig();
}
生成:
[/Script/Insider.MyClass_Config]
MyPropertyWithConfig=777
[/Script/Insider.MyClass_ConfigDoNotCheckDefaults]
MyPropertyWithConfigSub=123
MyPropertyWithConfig=777
[/Script/Insider.MyClass_ConfigDefaultChild]
MyPropertyWithConfigSub=123
```
由此可见MyClass_ConfigDoNotCheckDefaults中的MyPropertyWithConfig的值默认跟UMyClass_Config中的777值一致但是依然会写入进来。在MyClass_ConfigDefaultChild类中MyPropertyWithConfig的值因为没有改变就会被略过。
在源码里搜configdonotcheckdefaults的时候发现常常和defaultconfig配合使用。什么时候应该使用configdonotcheckdefaults感觉是为了保持自己的完整性无论如何都要全部写入进去。在defaultConfig的时候就可以不管Base里的值都写入一份到Default配置里这样在编辑上更加的完整。
## 原理:
```cpp
const bool bShouldCheckIfIdenticalBeforeAdding = !GetClass()->HasAnyClassFlags(CLASS_ConfigDoNotCheckDefaults) && !bPerObject && bIsPropertyInherited;
//简单的示例判断
if (!bPropDeprecated && (!bShouldCheckIfIdenticalBeforeAdding || !Property->Identical_InContainer(this, SuperClassDefaultObject, Index)))
{
FString Value;
Property->ExportText_InContainer( Index, Value, this, this, this, PortFlags );
Config->SetString( *Section, *Key, *Value, PropFileName );
}
else
{
// If we are not writing it to config above, we should make sure that this property isn't stagnant in the cache.
Config->RemoveKey( *Section, *Key, PropFileName );
}
```

View File

@@ -0,0 +1,89 @@
# DefaultConfig
- **功能描述:** 指定保存到的配置文件层级是Project/Config/DefaultXXX.ini。
- **引擎模块:** Config
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中增加[CLASS_DefaultConfig](../../../../Flags/EClassFlags/CLASS_DefaultConfig.md)
- **关联项:** [Config](../Config.md)
- **常用程度:★★★**
指定保存到的配置文件层级是Project/Config/DefaultXXX.ini。
- 而不是默认的Saved/XXX.ini
- 一般用在编辑器里把Settings自动保存到Project/Config/DefaultXXX.ini里去
## 示例代码:
```cpp
UCLASS(Config = MyGame,DefaultConfig)
class INSIDER_API UMyClass_DefaultConfig :public UDeveloperSettings
{
GENERATED_BODY()
public:
/** Gets the settings container name for the settings, either Project or Editor */
virtual FName GetContainerName() const override { return TEXT("Project"); }
/** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */
virtual FName GetCategoryName() const override { return TEXT("MyGame"); }
/** The unique name for your section of settings, uses the class's FName. */
virtual FName GetSectionName() const override { return TEXT("MyGame"); }
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
};
//保存的结果:
//Config/DefaultMyGame.ini
[/Script/Insider.MyClass_DefaultConfig]
MyPropertyWithConfig=888
```
## 示例结果:
![Untitled](Untitled.png)
## 原理:
代码里要使用Settings->TryUpdateDefaultConfigFile();但发现TryUpdateDefaultConfigFile不管有没有DefaultConfig都可以调用都可以保存到Default里。因此应该调用哪个SaveConfigTryUpdateDefaultConfigFileUpdateGlobalUserConfigFileUpdateProjectUserConfigFile是可以手动指定的。
但是在编辑器里编辑的时候则可以通过写好的代码来处理好逻辑。如SSettingsEditor.cpp里NotifyPostChange中调用Section->Save();则可以在内部再调用如下代码:
```cpp
bool FSettingsSection::Save()
{
if (ModifiedDelegate.IsBound() && !ModifiedDelegate.Execute())
{
return false;
}
if (SaveDelegate.IsBound())
{
return SaveDelegate.Execute();
}
//更新到正确的文件里
if (SettingsObject.IsValid())
{
if (SettingsObject->GetClass()->HasAnyClassFlags(CLASS_DefaultConfig))
{
SettingsObject->TryUpdateDefaultConfigFile();
}
else if (SettingsObject->GetClass()->HasAnyClassFlags(CLASS_GlobalUserConfig))
{
SettingsObject->UpdateGlobalUserConfigFile();
}
else if (SettingsObject->GetClass()->HasAnyClassFlags(CLASS_ProjectUserConfig))
{
SettingsObject->UpdateProjectUserConfigFile();
}
else
{
SettingsObject->SaveConfig();
}
return true;
}
return false;
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -0,0 +1,70 @@
# EditorConfig
- **功能描述:** 用来在编辑器状态下保存信息。
- **引擎模块:** Config, Editor
- **元数据类型:** string="abc"
- **作用机制:** 在Meta中增加[EditorConfig](../../../../Meta/Config/EditorConfig.md)
- **常用程度:★**
用来在编辑器状态下保存信息。
一般用在EditorTarget的Module里用于配置相应编辑器的信息比如列宽收藏夹之类的用json保存。
保存在C:\Users\{user name}\AppData\Local\UnrealEngine\Editor。当前有
![Untitled](Untitled.png)
在源码里搜索后,使用的时候必须继承于基类:
```cpp
/** Inherit from this class to simplify saving and loading properties from editor configs. */
UCLASS()
class EDITORCONFIG_API UEditorConfigBase : public UObject
{
GENERATED_BODY()
public:
/** Load any properties of this class into properties marked with metadata tag "EditorConfig" from the class's EditorConfig */
bool LoadEditorConfig();
/** Save any properties of this class in properties marked with metadata tag "EditorConfig" into the class's EditorConfig. */
bool SaveEditorConfig() const;
};
```
## 示例代码:
```cpp
UCLASS(EditorConfig = "MyEditorGame")
class INSIDER_API UMyClass_EditorConfig : public UEditorConfigBase
{
public:
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (EditorConfig))
int32 MyPropertyWithConfig = 123;
};
void UMyClass_EditorConfig_Test::TestConfigSave()
{
//must run after editor initialization
auto* testObject = NewObject<UMyClass_EditorConfig>(GetTransientPackage(), TEXT("testObject_EditorConfig"));
testObject->MyPropertyWithConfig = 777;
testObject->SaveEditorConfig();
}
void UMyClass_EditorConfig_Test::TestConfigLoad()
{
auto* testObject = NewObject<UMyClass_EditorConfig>(GetTransientPackage(), TEXT("testObject_EditorConfig"));
testObject->LoadEditorConfig();
}
//运行Save后的保存结果C:\Users\jack.fu\AppData\Local\UnrealEngine\Editor\MyEditorGame.json
{
"$type": "MyClass_EditorConfig",
"MyPropertyWithConfig": 777
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 128 KiB

View File

@@ -0,0 +1,74 @@
# GlobalUserConfig
- **功能描述:** 指定保存到的配置文件层级是全局用户设置 Engine/Config/UserXXX.ini。
- **引擎模块:** Config
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中增加[CLASS_GlobalUserConfig](../../../../Flags/EClassFlags/CLASS_GlobalUserConfig.md)
- **关联项:** [Config](../Config.md)
- **常用程度:★★★**
指定保存到的配置文件层级是全局用户设置 Engine/Config/UserXXX.ini。
## 示例代码:
属性用Config或者GlobalConfig都是可以的。
```cpp
UCLASS(Config = MyGame, GlobalUserConfig)
class INSIDER_API UMyClass_GlobalUserConfig:public UDeveloperSettings
{
GENERATED_BODY()
public:
/** Gets the settings container name for the settings, either Project or Editor */
virtual FName GetContainerName() const override { return TEXT("Project"); }
/** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */
virtual FName GetCategoryName() const override { return TEXT("MyGame"); }
/** The unique name for your section of settings, uses the class's FName. */
virtual FName GetSectionName() const override { return TEXT("MyGlobalGame"); }
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, GlobalConfig)
int32 MyPropertyWithGlobalConfig = 456;
};
保存到C:\Users\jack.fu\AppData\Local\Unreal Engine\Engine\Config\UserMyGame.ini
[/Script/Insider.UMyClass_GlobalUserConfig]
MyPropertyWithGlobalConfig=999
```
## 示例效果:
![Untitled](Untitled.png)
## 源码例子:
```cpp
UCLASS(config=Engine, globaluserconfig)
class ANDROIDPLATFORMEDITOR_API UAndroidSDKSettings : public UObject
{
public:
GENERATED_UCLASS_BODY()
// Location on disk of the Android SDK (falls back to ANDROID_HOME environment variable if this is left blank)
UPROPERTY(GlobalConfig, EditAnywhere, Category = SDKConfig, Meta = (DisplayName = "Location of Android SDK (the directory usually contains 'android-sdk-')"))
FDirectoryPath SDKPath;
// Location on disk of the Android NDK (falls back to NDKROOT environment variable if this is left blank)
UPROPERTY(GlobalConfig, EditAnywhere, Category = SDKConfig, Meta = (DisplayName = "Location of Android NDK (the directory usually contains 'android-ndk-')"))
FDirectoryPath NDKPath;
// Location on disk of Java (falls back to JAVA_HOME environment variable if this is left blank)
UPROPERTY(GlobalConfig, EditAnywhere, Category = SDKConfig, Meta = (DisplayName = "Location of JAVA (the directory usually contains 'jdk')"))
FDirectoryPath JavaPath;
// Which SDK to package and compile Java with (a specific version or (without quotes) 'latest' for latest version on disk, or 'matchndk' to match the NDK API Level)
UPROPERTY(GlobalConfig, EditAnywhere, Category = SDKConfig, Meta = (DisplayName = "SDK API Level (specific version, 'latest', or 'matchndk' - see tooltip)"))
FString SDKAPILevel;
// Which NDK to compile with (a specific version or (without quotes) 'latest' for latest version on disk). Note that choosing android-21 or later won't run on pre-5.0 devices.
UPROPERTY(GlobalConfig, EditAnywhere, Category = SDKConfig, Meta = (DisplayName = "NDK API Level (specific version or 'latest' - see tooltip)"))
FString NDKAPILevel;
};
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

View File

@@ -0,0 +1,73 @@
# PerObjectConfig
- **功能描述:** 在已经有config配置文件名字的情况下指定应该按每个对象实例来存储值而不是一个类一个存储值。
- **引擎模块:** Config
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中增加[CLASS_PerObjectConfig](../../../Flags/EClassFlags/CLASS_PerObjectConfig.md)
- **关联项:** [Config](Config.md)
- **常用程度:★★★★★**
在已经有config配置文件名字的情况下指定应该按每个对象实例来存储值而不是一个类一个存储值。
- 此类的配置信息将按对象存储,在.ini文件中每个对象都有一个分段根据对象命名格式为[ObjectName ClassName]。
- 此说明符会传播到子类。指定该配置是对每个对象都单独保存。
## 示例代码:
注意ObjectName必须一致
```cpp
UCLASS(Config = Game,PerObjectConfig)
class INSIDER_API UMyClass_PerObjectConfig :public UObject
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 MyProperty = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
};
void UMyClass_Config_Test::TestPerObjectConfigSave()
{
UMyClass_PerObjectConfig* testObject1 = NewObject<UMyClass_PerObjectConfig>(GetTransientPackage(), TEXT("testObject1"));
testObject1->MyPropertyWithConfig = 456;
testObject1->SaveConfig();
UMyClass_PerObjectConfig* testObject2 = NewObject<UMyClass_PerObjectConfig>(GetTransientPackage(), TEXT("testObject2"));
testObject2->MyPropertyWithConfig = 789;
testObject2->SaveConfig();
}
void UMyClass_Config_Test::TestPerObjectConfigLoad()
{
UMyClass_PerObjectConfig* testObject1 = NewObject<UMyClass_PerObjectConfig>(GetTransientPackage(), TEXT("testObject1"));
//testObject1->LoadConfig(); //不需要显式调用LoadConfig
UMyClass_PerObjectConfig* testObject2 = NewObject<UMyClass_PerObjectConfig>(GetTransientPackage(), TEXT("testObject2"));
//testObject2->LoadConfig();
}
//\Saved\Config\WindowsEditor\Game.ini
[testObject1 MyClass_PerObjectConfig]
MyPropertyWithConfig=456
[testObject2 MyClass_PerObjectConfig]
MyPropertyWithConfig=789
```
## 原理:
对象构造的末期会尝试去读取配置。
```cpp
void FObjectInitializer::PostConstructInit()
{
//在NewObject构造中后面会调用
if (bIsCDO || Class->HasAnyClassFlags(CLASS_PerObjectConfig))
{
Obj->LoadConfig(NULL, NULL, bIsCDO ? UE::LCPF_ReadParentSections : UE::LCPF_None);
}
}
```

View File

@@ -0,0 +1,53 @@
# ProjectUserConfig
- **功能描述:** 指定保存到的配置文件层级是项目用户设置 Project/Config/UserXXX.ini。
- **引擎模块:** Config
- **元数据类型:** bool
- **作用机制:** 在ClassFlags中增加[CLASS_ProjectUserConfig](../../../../Flags/EClassFlags/CLASS_ProjectUserConfig.md)
- **关联项:** [Config](../Config.md)
- **常用程度:★★★**
指定保存到的配置文件层级是项目用户设置 Project/Config/UserXXX.ini。
## 示例代码:
保存的目录是\Hello\Config\UserMyGame.ini
```cpp
UCLASS(Config = MyGame, ProjectUserConfig)
class INSIDER_API UMyClass_ProjectUserConfig :public UDeveloperSettings
{
GENERATED_BODY()
public:
/** Gets the settings container name for the settings, either Project or Editor */
virtual FName GetContainerName() const override { return TEXT("Project"); }
/** Gets the category for the settings, some high level grouping like, Editor, Engine, Game...etc. */
virtual FName GetCategoryName() const override { return TEXT("MyGame"); }
/** The unique name for your section of settings, uses the class's FName. */
virtual FName GetSectionName() const override { return TEXT("MyProjectGame"); }
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Config)
int32 MyPropertyWithConfig = 123;
UPROPERTY(EditAnywhere, BlueprintReadWrite, GlobalConfig)
int32 MyPropertyWithGlobalConfig = 456;
};
//结果:\Hello\Config\UserMyGame.ini
[/Script/Insider.MyClass_ProjectUserConfig]
MyPropertyWithConfig=777
MyPropertyWithGlobalConfig=888
```
## 示例效果:
![Untitled](Untitled.png)
## 在源码中搜索:
```cpp
UCLASS(config = Engine, projectuserconfig, meta = (DisplayName = "Rendering Overrides (Local)"))
class ENGINE_API URendererOverrideSettings : public UDeveloperSettings
{
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB