You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Change 1996384 by Andrew Brown: 322252 - EDITOR: Asset picker displays incorrect text when there are no filter results. Change 1996385 by Andrew Brown: 321858 - CRASH: Assertion failed: (Index >= 0) Function: STransformViewportToolBar::GetLocationGridLabel() STextBlock::CacheDesiredSize() Change 1996977 by Andrew Brown: 309685 - UE4: Adding an event/renaming an event on an event track in Matinee does not update the MatineeActor node in blueprint Change 2034873 by Jaroslaw Palczynski: More robust VS installation detection. Change 2039693 by Jaroslaw Palczynski: 327268 - RocketGDC: POSTLAUNCH: DEV: Make engine more robust against bad Visual Studio environment variables Change 1978978 by Jaroslaw Surowiec: - Removed obsolete AllowEliminatingReferences from the FArchive Change 2020326 by Maciej Mroz: pretest BP K2Node: RemovePinsFromOldPins function moved from K2Node to RemovePinsFromOldPins Change 2017608 by Maciej Mroz: pretest Some changes in SFortMissionEventSelector caused by FPinTypeTreeInfo Change 2017463 by Maciej Mroz: PinTypeSelector can lins unloaded UDStructs Change 2019979 by Maciej Mroz: pretest BP: Crash when performing Diff against Depot with blueprints containing Format Text nodes Change 2024469 by Maciej Mroz: MemberReference variable added to PinType. It's necessary for delegate's signature. Change 2024049 by Maciej Mroz: HasExternalBlueprintDependencies added to UK2Node_DynamicCast Change 2024586 by Maciej Mroz: FillSimpleMemberReference fix Change 2024472 by Maciej Mroz: workaround for delegates signature in pintype removed. Change 2023997 by Maciej Mroz: BP, UDStruc: Class UserDefinedStructEditorData added. It fixes many problems with undo/redo. Change 2021934 by Maciej Mroz: typo in a comment Change 2020355 by Maciej Mroz: Back out changelist 2020342 Change 2022178 by Maciej Mroz: CRASH: PRETEST: EDITOR: UDS: Crash when undo then redo new variable in struct that is used by blueprint Change 2021958 by Maciej Mroz: CRASH: PRETEST: EDITOR: UDS: Crash using variable of a type of copied struct in blueprint Change 1986247 by Maciej Mroz: User Defined Structures: circle dependency fixed. Early version. Change 1985107 by Maciej Mroz: UserDefinedStruct cannot have a field of a non-native type Change 1986278 by Maciej Mroz: pretest ensureMsgf in Struct::link Change 1986250 by Maciej Mroz: User Defined Struct: Non native classes are accepted types od values in structures. Change 1980955 by Maciej Mroz: Using AssetPtr and LazyPtr as UFunction parameter (intput or return) is explicitly disallowed. Change 2041215 by Maciej Mroz: ttp331249 BLOCKER: PRETEST: UI: Survive the Storm is missing the Mission HUD. Change 1984316 by Maciej Mroz: New User Defined Structure. WIP - there are still problems with circular dependencies. Change 2011616 by Maciej Mroz: UserDefinedStructures - various problems fixed. Change 2011609 by Maciej Mroz: more robust HasExternalBlueprintDependencies implementation Change 2016697 by Maciej Mroz: pretest BP: UDStruct - default value propagation in cooked build Change 2016288 by Maciej Mroz: pretest BP: UDStruct: Renaming variables wont break links from make/break nodes Change 1987637 by Maciej Mroz: CustomStruct icons placeholders Change 1987422 by Maciej Mroz: Better tooltips for variables in MyBlueprint Change 1991387 by Maciej Mroz: UDStructures fixes: Change 2029165 by Maciej Mroz: BP: better comment for incomatible pins Change2030016by Maciej Mroz: 8PRETEST: EDITOR: UDS: Defaults values aren't updated in struct type variables in blueprints Change 2030017 by Maciej Mroz: Unused UDStructure code removed (PPF_UseDefaultsForUDStructures) Change 2028856 by Maciej Mroz: BP: Pins with PC_Struct type are compatible only with exactly the same structure. (No derived structures are not handled as compatible). Change 2026701 by Maciej Mroz: k2: odd error on an add item node within a function (see attached image in details) Change 2028160 by Maciej Mroz: PRETEST: EDITOR: UDS: When deleting structures just after creating there is always some references in the memory Change 2028165 by Maciej Mroz: BP: BreakHitResult function has proper icon. Change 2033340 by Maciej Mroz: ttp330786 PRETEST: EDITOR: UDS: Changes of default values aren't apllied to breeak nodes for text type of variables Change 2034255 by Maciej Mroz: EDITOR: UDS: Changes of default values aren't apllied to make nodes for text type of variables ttp#330620 Change 2037682 by Maciej Mroz: ttp331309 BLOCKER: PRETEST: CRASH: EDITOR: Crash occurs when performing Diff Against Depot on any Blueprint Change 2033142 by Maciej Mroz: CreateDelegate Node uses internally FMemberReference. Refactor. Change 2032329 by Maciej Mroz: ttp330608 CRASH: PRETEST: EDITOR: UDS: Crash when trying to use struct named 'Color' in blueprint Change 2032420 by Maciej Mroz: ttp330620 PRETEST: EDITOR: UDS: Changes of default values aren't apllied to make nodes for text type of variables Change 2033139 by Maciej Mroz: Functions generated from CustomEvents can be also identified by GUID Change 2026631 by Maciej Mroz: BP. UDStruct: Invalid structs are handled better. Change 2025344 by Maciej Mroz: UDStruct enabled by default Change 2026672 by Maciej Mroz: EDITOR: BP: Can't easily remove 'pass-by-reference' pins on ReturnNodes Change 2026411 by Maciej Mroz: ExposeOnSpawn updated, it supports UDStructs, custom native Structs, and it throws compiler error. Change 2025342 by Maciej Mroz: GenerateBlueprintSkeleton moved from BLueprint::Serialize to RegenerateBlueprintClass, because SkeletonClass compilation requires all external dependencies to be loaded and linked. Change 2025570 by Steve Robb: Moved dependency processing to its own function. Change 2033235 by Steve Robb: String improvements Change 2035830 by Steve Robb: Workaround for FriendsAndChat crash in Fortnite. Change 2035115 by Steve Robb: UBT build time regression fixes. Change 2034162 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere Change2034181by Steve Robb: Removal of any references to .generated.inl Change 2020165 by Steve Robb: BuildPublicAndPrivateUObjectHeaders factored out into its own function. Change 2020187 by Steve Robb: CreateModuleCompileEnvironment function factored out. Change 2020055 by Steve Robb: Refactoring of Unity.cs to remove complex and duplicate iteration. Change 2020083 by Steve Robb: Another use of dictionary utilities. Change 2031049 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere Change 2025728 by Steve Robb: Refactored the application of a shared PCH file to multiple file into a single ApplySharedPCH function. Change 2020068 by Steve Robb: A couple of helpful utility functions for populating dictionaries. Change 2032307 by Steve Robb: 312775: UObject improvement: Ensure that *.generated.inl is included somewhere [CL 2054495 by Robert Manuszewski in Main branch]
317 lines
12 KiB
C++
317 lines
12 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "BlueprintGraphPrivatePCH.h"
|
|
#include "CompilerResultsLog.h"
|
|
#include "KismetCompiler.h"
|
|
|
|
#define LOCTEXT_NAMESPACE "K2Node_DelegateSet"
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// FKCHandler_BindToMulticastDelegate
|
|
|
|
class FKCHandler_BindToMulticastDelegate : public FNodeHandlingFunctor
|
|
{
|
|
protected:
|
|
TMap<UEdGraphNode*, FBPTerminal*> LocalDelegateMap;
|
|
|
|
public:
|
|
FKCHandler_BindToMulticastDelegate(FKismetCompilerContext& InCompilerContext)
|
|
: FNodeHandlingFunctor(InCompilerContext)
|
|
{
|
|
}
|
|
|
|
virtual void RegisterNets(FKismetFunctionContext& Context, UEdGraphNode* Node) OVERRIDE
|
|
{
|
|
UK2Node_DelegateSet* DelegateNode = Cast<UK2Node_DelegateSet>(Node);
|
|
if( DelegateNode )
|
|
{
|
|
CompilerContext.MessageLog.Warning(*FString(*LOCTEXT("DeprecatedDelegateSet_Warning", "DelegateSet node @@ is Deprecated. It should be replaced by an EventCaller Bind node").ToString()), DelegateNode);
|
|
|
|
// Create a term to store the locally created delegate that we'll use to add to the MC delegate
|
|
FBPTerminal* DelegateTerm = new (Context.IsEventGraph() ? Context.EventGraphLocals : Context.Locals) FBPTerminal();
|
|
DelegateTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Delegate;
|
|
FMemberReference::FillSimpleMemberReference<UFunction>(DelegateNode->GetDelegateSignature(), DelegateTerm->Type.PinSubCategoryMemberReference);
|
|
DelegateTerm->Source = Node;
|
|
DelegateTerm->Name = Context.NetNameMap->MakeValidName(Node) + TEXT("_TempBindingDelegate");
|
|
DelegateTerm->bIsLocal = true;
|
|
LocalDelegateMap.Add(Node, DelegateTerm);
|
|
|
|
// The only net we need to register for this node is the delegate's target (self) pin, since the others are expanded to their own event node
|
|
RegisterDelegateNet(Context, DelegateNode);
|
|
}
|
|
}
|
|
|
|
void RegisterDelegateNet(FKismetFunctionContext& Context, UK2Node_DelegateSet* DelegateNode)
|
|
{
|
|
check(DelegateNode);
|
|
|
|
UEdGraphPin* DelegatePin = DelegateNode->GetDelegateOwner();
|
|
check(DelegatePin);
|
|
|
|
// Find the property on the specified scope
|
|
UProperty* BoundProperty = NULL;
|
|
for (TFieldIterator<UProperty> It(DelegateNode->DelegatePropertyClass, EFieldIteratorFlags::IncludeSuper); It; ++It)
|
|
{
|
|
UProperty* Prop = *It;
|
|
if( Prop->GetFName() == DelegateNode->DelegatePropertyName )
|
|
{
|
|
check(Prop->HasAllPropertyFlags(CPF_BlueprintAssignable));
|
|
BoundProperty = Prop;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Create a term for this property
|
|
if( BoundProperty != NULL )
|
|
{
|
|
FBPTerminal* Term = new(Context.VariableReferences) FBPTerminal();
|
|
Term->CopyFromPin(DelegatePin, DelegatePin->PinName);
|
|
Term->AssociatedVarProperty = BoundProperty;
|
|
|
|
Context.NetMap.Add(DelegatePin, Term);
|
|
|
|
// Find the context for this term (the object owning the delegate property)
|
|
FBPTerminal** pContextTerm = Context.NetMap.Find(FEdGraphUtilities::GetNetFromPin(DelegatePin));
|
|
if( pContextTerm )
|
|
{
|
|
Term->Context = *pContextTerm;
|
|
}
|
|
else
|
|
{
|
|
CompilerContext.MessageLog.Error(*FString(*LOCTEXT("FindDynamicallyBoundDelegate_Error", "Couldn't find target for dynamically bound delegate node @@").ToString()), DelegateNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void Compile(FKismetFunctionContext& Context, UEdGraphNode* Node) OVERRIDE
|
|
{
|
|
const UK2Node_DelegateSet* DelegateNode = Cast<UK2Node_DelegateSet>(Node);
|
|
check(DelegateNode);
|
|
|
|
// Verify that the event has a darget to be bound to
|
|
UEdGraphPin* DelegateOwnerPin = DelegateNode->GetDelegateOwner();
|
|
|
|
if( DelegateOwnerPin->LinkedTo.Num() == 0 )
|
|
{
|
|
CompilerContext.MessageLog.Error(*FString(*LOCTEXT("FindDynamicallyBoundDelegate_Error", "Couldn't find target for dynamically bound delegate node @@").ToString()), DelegateNode);
|
|
return;
|
|
}
|
|
|
|
FBPTerminal** pDelegateOwnerTerm = DelegateOwnerPin ? Context.NetMap.Find(DelegateOwnerPin) : NULL;
|
|
|
|
// Create a delegate name term
|
|
FBPTerminal* DelegateNameTerm = new (Context.IsEventGraph() ? Context.EventGraphLocals : Context.Locals) FBPTerminal();
|
|
DelegateNameTerm->Type.PinCategory = CompilerContext.GetSchema()->PC_Name;
|
|
DelegateNameTerm->Name = DelegateNode->GetDelegateTargetEntryPointName().ToString();
|
|
DelegateNameTerm->bIsLiteral = true;
|
|
|
|
// Create a local delegate, which we can then add to the multicast delegate
|
|
FBPTerminal* LocalDelegate = *LocalDelegateMap.Find(Node);
|
|
FBlueprintCompiledStatement& Statement = Context.AppendStatementForNode(Node);
|
|
Statement.Type = KCST_Assignment;
|
|
Statement.LHS = LocalDelegate;
|
|
Statement.RHS.Add(DelegateNameTerm);
|
|
|
|
// Add the local delegate to the MC delegate
|
|
FBlueprintCompiledStatement& AddStatement = Context.AppendStatementForNode(Node);
|
|
AddStatement.Type = KCST_AddMulticastDelegate;
|
|
AddStatement.LHS = *pDelegateOwnerTerm;
|
|
AddStatement.RHS.Add(LocalDelegate);
|
|
|
|
GenerateSimpleThenGoto(Context, *Node, DelegateNode->FindPin(CompilerContext.GetSchema()->PN_Then));
|
|
|
|
FNodeHandlingFunctor::Compile(Context, Node);
|
|
}
|
|
};
|
|
|
|
UK2Node_DelegateSet::UK2Node_DelegateSet(const class FPostConstructInitializeProperties& PCIP)
|
|
: Super(PCIP)
|
|
{
|
|
}
|
|
|
|
void UK2Node_DelegateSet::AllocateDefaultPins()
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
// Cache off the delegate signature, which will update the DelegatePropertyName as well, if it's been redirected
|
|
UFunction* DelegateSignature = GetDelegateSignature();
|
|
|
|
CreatePin(EGPD_Input, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_Execute);
|
|
CreatePin(EGPD_Input, K2Schema->PC_Object, TEXT(""), DelegatePropertyClass, false, false, DelegatePropertyName.ToString());
|
|
|
|
CreatePin(EGPD_Output, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_Then);
|
|
CreatePin(EGPD_Output, K2Schema->PC_Exec, TEXT(""), NULL, false, false, K2Schema->PN_DelegateEntry);
|
|
|
|
CreatePinsForFunctionEntryExit(DelegateSignature, true);
|
|
|
|
Super::AllocateDefaultPins();
|
|
}
|
|
|
|
FString UK2Node_DelegateSet::GetTooltip() const
|
|
{
|
|
FString Tooltip = FString::Printf(*NSLOCTEXT("K2Node", "CreateEventForDelegate", "Create an event tied to the delegate %s").ToString(), *DelegatePropertyName.ToString());
|
|
if (UFunction* Function = GetDelegateSignature())
|
|
{
|
|
const FString SignatureTooltip = Function->GetToolTipText().ToString();
|
|
|
|
if (!SignatureTooltip.IsEmpty())
|
|
{
|
|
Tooltip += FString(TEXT("\n")) + SignatureTooltip;
|
|
}
|
|
}
|
|
return Tooltip;
|
|
}
|
|
|
|
FText UK2Node_DelegateSet::GetNodeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
FFormatNamedArguments Args;
|
|
Args.Add(TEXT("DelegatePropertyName"), FText::FromName(DelegatePropertyName));
|
|
return FText::Format(NSLOCTEXT("K2Node", "Assign_Name", "Assign {DelegatePropertyName}"), Args);
|
|
}
|
|
|
|
FString UK2Node_DelegateSet::GetNodeNativeTitle(ENodeTitleType::Type TitleType) const
|
|
{
|
|
// Do not setup this function for localization, intentionally left unlocalized!
|
|
return FString::Printf(TEXT("Assign %s"), *DelegatePropertyName.ToString());
|
|
}
|
|
|
|
UEdGraphPin* UK2Node_DelegateSet::GetDelegateOwner() const
|
|
{
|
|
const UEdGraphSchema_K2* K2Schema = GetDefault<UEdGraphSchema_K2>();
|
|
|
|
UEdGraphPin* Pin = FindPin(DelegatePropertyName.ToString());
|
|
check(Pin != NULL);
|
|
check(Pin->Direction == EGPD_Input);
|
|
return Pin;
|
|
}
|
|
|
|
UFunction* UK2Node_DelegateSet::GetDelegateSignature()
|
|
{
|
|
UMulticastDelegateProperty* DelegateProperty = FindField<UMulticastDelegateProperty>(DelegatePropertyClass, DelegatePropertyName);
|
|
|
|
if( !DelegateProperty )
|
|
{
|
|
// Attempt to find a remapped delegate property
|
|
UMulticastDelegateProperty* NewProperty = Cast<UMulticastDelegateProperty>(FindRemappedField(DelegatePropertyClass, DelegatePropertyName));
|
|
if( NewProperty )
|
|
{
|
|
// Found a remapped property, update the node
|
|
DelegateProperty = NewProperty;
|
|
DelegatePropertyName = NewProperty->GetFName();
|
|
DelegatePropertyClass = Cast<UClass>(NewProperty->GetOuter());
|
|
}
|
|
}
|
|
|
|
return (DelegateProperty != NULL) ? DelegateProperty->SignatureFunction : NULL;
|
|
}
|
|
|
|
UFunction* UK2Node_DelegateSet::GetDelegateSignature() const
|
|
{
|
|
UMulticastDelegateProperty* DelegateProperty = FindField<UMulticastDelegateProperty>(DelegatePropertyClass, DelegatePropertyName);
|
|
|
|
if( !DelegateProperty )
|
|
{
|
|
// Attempt to find a remapped delegate property
|
|
DelegateProperty = Cast<UMulticastDelegateProperty>(FindRemappedField(DelegatePropertyClass, DelegatePropertyName));
|
|
}
|
|
|
|
return (DelegateProperty != NULL) ? DelegateProperty->SignatureFunction : NULL;
|
|
}
|
|
|
|
void UK2Node_DelegateSet::ValidateNodeDuringCompilation(class FCompilerResultsLog& MessageLog) const
|
|
{
|
|
Super::ValidateNodeDuringCompilation(MessageLog);
|
|
|
|
// If we are overriding a function, but we can;t find the function we are overriding, that is a compile error
|
|
if(GetDelegateSignature() == NULL)
|
|
{
|
|
MessageLog.Error(*FString::Printf(*NSLOCTEXT("KismetCompiler", "MissingDelegateSig_Error", "Unable to find delegate '%s' for @@").ToString(), *DelegatePropertyName.ToString()), this);
|
|
}
|
|
}
|
|
|
|
FNodeHandlingFunctor* UK2Node_DelegateSet::CreateNodeHandler(FKismetCompilerContext& CompilerContext) const
|
|
{
|
|
return new FKCHandler_BindToMulticastDelegate(CompilerContext);
|
|
}
|
|
|
|
|
|
UK2Node::ERedirectType UK2Node_DelegateSet::DoPinsMatchForReconstruction(const UEdGraphPin* NewPin, int32 NewPinIndex, const UEdGraphPin* OldPin, int32 OldPinIndex) const
|
|
{
|
|
ERedirectType OrginalResult = Super::DoPinsMatchForReconstruction(NewPin, NewPinIndex, OldPin, OldPinIndex);
|
|
const UEdGraphSchema_K2* K2Schema = Cast<const UEdGraphSchema_K2>(GetSchema());
|
|
if ((ERedirectType::ERedirectType_None == OrginalResult) && K2Schema && NewPin && OldPin)
|
|
{
|
|
bool const bOldPinIsObj = (OldPin->PinType.PinCategory == K2Schema->PC_Object) || (OldPin->PinType.PinCategory == K2Schema->PC_Interface);
|
|
bool const bNewPinIsObj = (OldPin->PinType.PinCategory == K2Schema->PC_Object) || (OldPin->PinType.PinCategory == K2Schema->PC_Interface);
|
|
|
|
if ((NewPin->Direction == EGPD_Input && OldPin->Direction == EGPD_Input) &&
|
|
bOldPinIsObj && bNewPinIsObj)
|
|
{
|
|
return ERedirectType_Name;
|
|
}
|
|
}
|
|
return OrginalResult;
|
|
}
|
|
|
|
void UK2Node_DelegateSet::ExpandNode(class FKismetCompilerContext& CompilerContext, UEdGraph* SourceGraph)
|
|
{
|
|
Super::ExpandNode(CompilerContext, SourceGraph);
|
|
|
|
if (SourceGraph != CompilerContext.ConsolidatedEventGraph)
|
|
{
|
|
CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("KismetCompiler", "InvalidNodeOutsideUbergraph_Error", "Unexpected node @@ found outside ubergraph.").ToString()), this);
|
|
}
|
|
else if (CompilerContext.bIsFullCompile)
|
|
{
|
|
UFunction* TargetFunction = GetDelegateSignature();
|
|
if(TargetFunction != NULL)
|
|
{
|
|
const UEdGraphSchema_K2* Schema = CompilerContext.GetSchema();
|
|
|
|
// First, create an event node matching the delegate signature
|
|
UK2Node_Event* DelegateEvent = CompilerContext.SpawnIntermediateNode<UK2Node_Event>(this, SourceGraph);
|
|
DelegateEvent->EventSignatureClass = Cast<UClass>(TargetFunction->GetOuter());
|
|
DelegateEvent->EventSignatureName = TargetFunction->GetFName();
|
|
DelegateEvent->CustomFunctionName = GetDelegateTargetEntryPointName();
|
|
DelegateEvent->bInternalEvent = true;
|
|
DelegateEvent->AllocateDefaultPins();
|
|
|
|
// Move the pins over to the newly created event node
|
|
for( TArray<UEdGraphPin*>::TIterator PinIt(DelegateEvent->Pins); PinIt; ++PinIt )
|
|
{
|
|
UEdGraphPin* CurrentPin = *PinIt;
|
|
check(CurrentPin);
|
|
|
|
if( CurrentPin->Direction == EGPD_Output )
|
|
{
|
|
if( CurrentPin->PinType.PinCategory == Schema->PC_Exec )
|
|
{
|
|
// Hook up the exec pin specially, since it has a different name on the dynamic delegate node
|
|
UEdGraphPin* OldExecPin = FindPin(Schema->PN_DelegateEntry);
|
|
check(OldExecPin);
|
|
CompilerContext.MovePinLinksToIntermediate(*OldExecPin, *CurrentPin);
|
|
}
|
|
else if( CurrentPin->PinName != UK2Node_Event::DelegateOutputName )
|
|
{
|
|
// Hook up all other pins, EXCEPT the delegate output pin, which isn't needed in this case
|
|
UEdGraphPin* OldPin = FindPin(CurrentPin->PinName);
|
|
if( !OldPin )
|
|
{
|
|
// If we couldn't find the old pin, the function signature is out of date. Tell them to reconstruct
|
|
CompilerContext.MessageLog.Error(*FString::Printf(*NSLOCTEXT("KismetCompiler", "EventNodeOutOfDate_Error", "Event node @@ is out-of-date. Please refresh it.").ToString()), this);
|
|
return;
|
|
}
|
|
|
|
CompilerContext.MovePinLinksToIntermediate(*OldPin, *CurrentPin);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CompilerContext.MessageLog.Error(*FString::Printf(*LOCTEXT("DelegateSigNotFound_Error", "Set Delegate node @@ unable to find function.").ToString()), this);
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef LOCTEXT_NAMESPACE |