290 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			290 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								#include "CSCompilerContext.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "BlueprintActionDatabase.h"
							 | 
						||
| 
								 | 
							
								#include "ISettingsModule.h"
							 | 
						||
| 
								 | 
							
								#include "BehaviorTree/Tasks/BTTask_BlueprintBase.h"
							 | 
						||
| 
								 | 
							
								#include "Blueprint/StateTreeTaskBlueprintBase.h"
							 | 
						||
| 
								 | 
							
								#include "Engine/SCS_Node.h"
							 | 
						||
| 
								 | 
							
								#include "Engine/SimpleConstructionScript.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/CSBlueprint.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/CSClass.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/CSSkeletonClass.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Factories/CSFunctionFactory.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Factories/CSPropertyFactory.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Factories/PropertyGenerators/CSPropertyGenerator.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Register/CSGeneratedClassBuilder.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Register/CSMetaDataUtils.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Register/CSSimpleConstructionScriptBuilder.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Register/MetaData/CSClassMetaData.h"
							 | 
						||
| 
								 | 
							
								#include "TypeGenerator/Register/TypeInfo/CSClassInfo.h"
							 | 
						||
| 
								 | 
							
								#include "UnrealSharpEditor/CSUnrealSharpEditorSettings.h"
							 | 
						||
| 
								 | 
							
								#include "UnrealSharpUtilities/UnrealSharpUtils.h"
							 | 
						||
| 
								 | 
							
								#include "Utils/CSClassUtilities.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								FCSCompilerContext::FCSCompilerContext(UCSBlueprint* Blueprint, FCompilerResultsLog& InMessageLog, const FKismetCompilerOptions& InCompilerOptions):
							 | 
						||
| 
								 | 
							
									FKismetCompilerContext(Blueprint, InMessageLog, InCompilerOptions)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::FinishCompilingClass(UClass* Class)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									bool bIsSkeletonClass = FCSClassUtilities::IsSkeletonType(Class);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									if (!bIsSkeletonClass)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// The skeleton class shouldn't be using the managed constructor since it's not tied to an assembly
							 | 
						||
| 
								 | 
							
										Class->ClassConstructor = &UCSGeneratedClassBuilder::ManagedObjectConstructor;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Super::FinishCompilingClass(Class);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									TSharedPtr<FCSClassMetaData> TypeMetaData = GetClassInfo()->GetTypeMetaData<FCSClassMetaData>();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Super call overrides the class flags, so we need to set after that
							 | 
						||
| 
								 | 
							
									Class->ClassFlags |= TypeMetaData->ClassFlags;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									if (NeedsToFakeNativeClass(Class) && !bIsSkeletonClass)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										// There are systems in Unreal (BehaviorTree, StateTree) which uses the AssetRegistry to find BP classes, since our C# classes are not assets,
							 | 
						||
| 
								 | 
							
										// we need to fake that they're native classes in editor in order to be able to find them. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// The functions that are used to find classes are:
							 | 
						||
| 
								 | 
							
										// FGraphNodeClassHelper::BuildClassGraph()
							 | 
						||
| 
								 | 
							
										// FStateTreeNodeClassCache::CacheClasses()
							 | 
						||
| 
								 | 
							
										Class->ClassFlags |= CLASS_Native;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									UCSGeneratedClassBuilder::SetConfigName(Class, TypeMetaData);
							 | 
						||
| 
								 | 
							
									TryInitializeAsDeveloperSettings(Class);
							 | 
						||
| 
								 | 
							
									ApplyMetaData();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::OnPostCDOCompiled(const UObject::FPostCDOCompiledContext& Context)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									FKismetCompilerContext::OnPostCDOCompiled(Context);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									UCSGeneratedClassBuilder::SetupDefaultTickSettings(NewClass->GetDefaultObject(), NewClass);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									UCSClass* Class = GetMainClass();
							 | 
						||
| 
								 | 
							
									if (Class == NewClass)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										UCSGeneratedClassBuilder::TryRegisterDynamicSubsystem(Class);
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										if (GEditor)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											FBlueprintActionDatabase::Get().RefreshClassActions(Class);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::CreateClassVariablesFromBlueprint()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									TSharedPtr<FCSClassInfo> ClassInfo = GetMainClass()->GetManagedTypeInfo<FCSClassInfo>();
							 | 
						||
| 
								 | 
							
									const TArray<FCSPropertyMetaData>& Properties = ClassInfo->GetTypeMetaData<FCSClassMetaData>()->Properties;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									NewClass->PropertyGuids.Empty(Properties.Num());
							 | 
						||
| 
								 | 
							
									TryValidateSimpleConstructionScript(ClassInfo);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									FCSPropertyFactory::CreateAndAssignProperties(NewClass, Properties, [this](const FProperty* NewProperty)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										FName PropertyName = NewProperty->GetFName();
							 | 
						||
| 
								 | 
							
										FGuid PropertyGuid = FCSUnrealSharpUtils::ConstructGUIDFromName(PropertyName);
							 | 
						||
| 
								 | 
							
										NewClass->PropertyGuids.Add(PropertyName, PropertyGuid);
							 | 
						||
| 
								 | 
							
									});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Create dummy variables for the blueprint.
							 | 
						||
| 
								 | 
							
									// They should not get compiled, just there for metadata for different Unreal modules.
							 | 
						||
| 
								 | 
							
									CreateDummyBlueprintVariables(Properties);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::CleanAndSanitizeClass(UBlueprintGeneratedClass* ClassToClean, UObject*& InOldCDO)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									FKismetCompilerContext::CleanAndSanitizeClass(ClassToClean, InOldCDO);
							 | 
						||
| 
								 | 
							
									NewClass->FieldNotifies.Reset();
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									TryDeinitializeAsDeveloperSettings(InOldCDO);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Too late to generate functions in CreateFunctionList for child blueprints
							 | 
						||
| 
								 | 
							
									GenerateFunctions();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::SpawnNewClass(const FString& NewClassName)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									UCSClass* MainClass = GetMainClass();
							 | 
						||
| 
								 | 
							
									UCSSkeletonClass* NewSkeletonClass = NewObject<UCSSkeletonClass>(Blueprint->GetOutermost(), FName(*NewClassName), RF_Public | RF_Transactional);
							 | 
						||
| 
								 | 
							
									NewSkeletonClass->SetGeneratedClass(MainClass);
							 | 
						||
| 
								 | 
							
									NewClass = NewSkeletonClass;
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									// Skeleton class doesn't generate functions on the first pass.
							 | 
						||
| 
								 | 
							
									// It's done in CleanAndSanitizeClass which doesn't run when the skeleton class is created
							 | 
						||
| 
								 | 
							
									GenerateFunctions();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::AddInterfacesFromBlueprint(UClass* Class)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									UCSGeneratedClassBuilder::ImplementInterfaces(Class, GetTypeMetaData()->Interfaces);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::TryValidateSimpleConstructionScript(const TSharedPtr<const FCSClassInfo>& ClassInfo) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									const TArray<FCSPropertyMetaData>& Properties = GetTypeMetaData()->Properties;
							 | 
						||
| 
								 | 
							
									FCSSimpleConstructionScriptBuilder::BuildSimpleConstructionScript(Blueprint->GeneratedClass, &Blueprint->SimpleConstructionScript, Properties);
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									if (!Blueprint->SimpleConstructionScript)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									TArray<USCS_Node*> Nodes;
							 | 
						||
| 
								 | 
							
									for (const FCSPropertyMetaData& Property : Properties)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (Property.Type->PropertyType != ECSPropertyType::DefaultComponent)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											continue;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
										USimpleConstructionScript* SCS = Blueprint->SimpleConstructionScript;
							 | 
						||
| 
								 | 
							
										USCS_Node* Node = SCS->FindSCSNode(Property.Name);
							 | 
						||
| 
								 | 
							
										Nodes.Add(Node);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Remove all nodes that are not part of the class anymore.
							 | 
						||
| 
								 | 
							
									int32 NumNodes = Blueprint->SimpleConstructionScript->GetAllNodes().Num();
							 | 
						||
| 
								 | 
							
									TArray<USCS_Node*> AllNodes = Blueprint->SimpleConstructionScript->GetAllNodes();
							 | 
						||
| 
								 | 
							
									for (int32 i = NumNodes - 1; i >= 0; --i)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										USCS_Node* Node = AllNodes[i];
							 | 
						||
| 
								 | 
							
										if (!Nodes.Contains(Node))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											Blueprint->SimpleConstructionScript->RemoveNode(Node);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Blueprint->SimpleConstructionScript->ValidateNodeTemplates(MessageLog);
							 | 
						||
| 
								 | 
							
									Blueprint->SimpleConstructionScript->ValidateNodeVariableNames(MessageLog);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::GenerateFunctions() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									TSharedPtr<const FCSClassMetaData> TypeMetaData = GetTypeMetaData();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (TypeMetaData->VirtualFunctions.IsEmpty() && TypeMetaData->Functions.IsEmpty())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									
							 | 
						||
| 
								 | 
							
									FCSFunctionFactory::GenerateVirtualFunctions(NewClass, TypeMetaData);
							 | 
						||
| 
								 | 
							
									FCSFunctionFactory::GenerateFunctions(NewClass, TypeMetaData->Functions);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								UCSClass* FCSCompilerContext::GetMainClass() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return CastChecked<UCSClass>(Blueprint->GeneratedClass);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TSharedPtr<const FCSClassInfo> FCSCompilerContext::GetClassInfo() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return GetMainClass()->GetManagedTypeInfo<FCSClassInfo>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TSharedPtr<const FCSClassMetaData> FCSCompilerContext::GetTypeMetaData() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return GetClassInfo()->GetTypeMetaData<FCSClassMetaData>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool FCSCompilerContext::IsDeveloperSettings() const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									return Blueprint->GeneratedClass == NewClass && NewClass->IsChildOf<UDeveloperSettings>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::TryInitializeAsDeveloperSettings(const UClass* Class) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!IsDeveloperSettings())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									UDeveloperSettings* Settings = static_cast<UDeveloperSettings*>(Class->GetDefaultObject());
							 | 
						||
| 
								 | 
							
									ISettingsModule& SettingsModule = FModuleManager::GetModuleChecked<ISettingsModule>("Settings");
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
									SettingsModule.RegisterSettings(Settings->GetContainerName(), Settings->GetCategoryName(), Settings->GetSectionName(),
							 | 
						||
| 
								 | 
							
										Settings->GetSectionText(),
							 | 
						||
| 
								 | 
							
										Settings->GetSectionDescription(),
							 | 
						||
| 
								 | 
							
										Settings);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									Settings->LoadConfig();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::TryDeinitializeAsDeveloperSettings(UObject* Settings) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									if (!IsValid(Settings) || !IsDeveloperSettings())
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										return;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ISettingsModule& SettingsModule = FModuleManager::GetModuleChecked<ISettingsModule>("Settings");
							 | 
						||
| 
								 | 
							
									UDeveloperSettings* DeveloperSettings = static_cast<UDeveloperSettings*>(Settings);
							 | 
						||
| 
								 | 
							
									SettingsModule.UnregisterSettings(DeveloperSettings->GetContainerName(), DeveloperSettings->GetCategoryName(), DeveloperSettings->GetSectionName());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::ApplyMetaData()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									TSharedPtr<const FCSClassMetaData> TypeMetaData = GetTypeMetaData();
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
									static FString DisplayNameKey = TEXT("DisplayName");
							 | 
						||
| 
								 | 
							
									if (!NewClass->HasMetaData(*DisplayNameKey))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										NewClass->SetMetaData(*DisplayNameKey, *Blueprint->GetName());
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
										
							 | 
						||
| 
								 | 
							
									if (GetDefault<UCSUnrealSharpEditorSettings>()->bSuffixGeneratedTypes)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										FString DisplayName = NewClass->GetMetaData(*DisplayNameKey);
							 | 
						||
| 
								 | 
							
										DisplayName += TEXT(" (C#)");
							 | 
						||
| 
								 | 
							
										NewClass->SetMetaData(*DisplayNameKey, *DisplayName);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									FCSMetaDataUtils::ApplyMetaData(TypeMetaData->MetaData, NewClass);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool FCSCompilerContext::NeedsToFakeNativeClass(UClass* Class)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									static TArray ParentClasses =
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										UBTTask_BlueprintBase::StaticClass(),
							 | 
						||
| 
								 | 
							
										UStateTreeTaskBlueprintBase::StaticClass(),
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (UClass* ParentClass  : ParentClasses)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										if (Class->IsChildOf(ParentClass))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void FCSCompilerContext::CreateDummyBlueprintVariables(const TArray<FCSPropertyMetaData>& Properties) const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									Blueprint->NewVariables.Empty(Properties.Num());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									for (const FCSPropertyMetaData& PropertyMetaData : Properties)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										FBPVariableDescription VariableDescription;
							 | 
						||
| 
								 | 
							
										VariableDescription.FriendlyName = PropertyMetaData.Name.ToString();
							 | 
						||
| 
								 | 
							
										VariableDescription.VarName = PropertyMetaData.Name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (const TTuple<FString, FString>& MetaData : PropertyMetaData.MetaData)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											VariableDescription.SetMetaData(*MetaData.Key, MetaData.Value);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										Blueprint->NewVariables.Add(VariableDescription);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#undef LOCTEXT_NAMESPACE
							 |