Lots more progress on the name overhaul
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
#include "WingHandler.h"
|
#include "WingHandler.h"
|
||||||
#include "WingFetcher.h"
|
#include "WingFetcher.h"
|
||||||
#include "WingUtils.h"
|
#include "WingUtils.h"
|
||||||
|
#include "WingTypes.h"
|
||||||
#include "WingServer.h"
|
#include "WingServer.h"
|
||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
@@ -41,11 +42,26 @@ public:
|
|||||||
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
UBlueprint* BP = F.Asset(Blueprint).Cast<UBlueprint>();
|
||||||
if (!BP) return;
|
if (!BP) return;
|
||||||
|
|
||||||
// Find the interface by name
|
// Resolve the interface name to a UClass*
|
||||||
FBPInterfaceDescription *IFaceDesc =
|
UWingTypes::Requirements Req;
|
||||||
WingUtils::FindExactlyOneNamed(Interface, BP->ImplementedInterfaces, TEXT("Interface"));
|
Req.BlueprintType = false;
|
||||||
if (!IFaceDesc) return;
|
Req.Blueprintable = false;
|
||||||
UClass* FoundInterface = IFaceDesc->Interface;
|
Req.AllowContainer = false;
|
||||||
|
UClass* FoundInterface = UWingTypes::TextToOneInterfaceType(Interface, Req);
|
||||||
|
if (!FoundInterface) return;
|
||||||
|
|
||||||
|
// Verify this blueprint actually implements it
|
||||||
|
bool Found = false;
|
||||||
|
for (const FBPInterfaceDescription& Desc : BP->ImplementedInterfaces)
|
||||||
|
{
|
||||||
|
if (Desc.Interface == FoundInterface) { Found = true; break; }
|
||||||
|
}
|
||||||
|
if (!Found)
|
||||||
|
{
|
||||||
|
UWingServer::Printf(TEXT("ERROR: Blueprint %s does not implement interface %s\n"),
|
||||||
|
*WingUtils::FormatName(BP), *WingUtils::FormatName(FoundInterface));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
FTopLevelAssetPath InterfacePath = FoundInterface->GetClassPathName();
|
FTopLevelAssetPath InterfacePath = FoundInterface->GetClassPathName();
|
||||||
FBlueprintEditorUtils::RemoveInterface(BP, InterfacePath, PreserveFunctions);
|
FBlueprintEditorUtils::RemoveInterface(BP, InterfacePath, PreserveFunctions);
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "CoreMinimal.h"
|
|
||||||
#include "WingServer.h"
|
|
||||||
#include "WingHandler.h"
|
|
||||||
#include "WingFetcher.h"
|
|
||||||
#include "WingUtils.h"
|
|
||||||
#include "EdGraph/EdGraph.h"
|
|
||||||
#include "EdGraph/EdGraphNode.h"
|
|
||||||
#include "EdGraph/EdGraphPin.h"
|
|
||||||
#include "GraphNode_Duplicate.generated.h"
|
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
UCLASS()
|
|
||||||
class UWing_GraphNode_Duplicate : public UObject, public IWingHandler
|
|
||||||
{
|
|
||||||
GENERATED_BODY()
|
|
||||||
|
|
||||||
public:
|
|
||||||
UPROPERTY(meta=(Description="Target graph"))
|
|
||||||
FString Graph;
|
|
||||||
|
|
||||||
UPROPERTY(meta=(Description="Array of node names to duplicate (as returned by FormatName)"))
|
|
||||||
FWingJsonArray Nodes;
|
|
||||||
|
|
||||||
UPROPERTY(meta=(Optional, Description="X offset for duplicated nodes"))
|
|
||||||
int32 OffsetX = 50;
|
|
||||||
|
|
||||||
UPROPERTY(meta=(Optional, Description="Y offset for duplicated nodes"))
|
|
||||||
int32 OffsetY = 50;
|
|
||||||
|
|
||||||
virtual FString GetDescription() const override
|
|
||||||
{
|
|
||||||
return TEXT("Duplicate one or more nodes in a Blueprint graph. "
|
|
||||||
"Creates copies offset from the originals with new GUIDs. "
|
|
||||||
"Connections are not preserved on the duplicates.");
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Handle() override
|
|
||||||
{
|
|
||||||
WingFetcher F;
|
|
||||||
UEdGraph* TargetGraph = F.Walk(Graph).Cast<UEdGraph>();
|
|
||||||
if (!TargetGraph) return;
|
|
||||||
|
|
||||||
if (Nodes.Array.Num() == 0)
|
|
||||||
{
|
|
||||||
UWingServer::Print(TEXT("ERROR: Nodes array is empty\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all source nodes by name
|
|
||||||
TArray<UEdGraphNode*> SourceNodes;
|
|
||||||
for (const TSharedPtr<FJsonValue>& IdVal : Nodes.Array)
|
|
||||||
{
|
|
||||||
FString Name = IdVal->AsString();
|
|
||||||
UEdGraphNode* Found = nullptr;
|
|
||||||
for (UEdGraphNode* Node : TargetGraph->Nodes)
|
|
||||||
{
|
|
||||||
if (WingUtils::Identifies(Name, Node))
|
|
||||||
{
|
|
||||||
Found = Node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!Found)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Node '%s' not found in graph\n"), *Name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SourceNodes.Add(Found);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SourceNodes.Num() == 0) return;
|
|
||||||
|
|
||||||
// Duplicate each node
|
|
||||||
for (UEdGraphNode* SourceNode : SourceNodes)
|
|
||||||
{
|
|
||||||
UEdGraphNode* NewNode = DuplicateObject<UEdGraphNode>(SourceNode, TargetGraph);
|
|
||||||
if (!NewNode)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Failed to duplicate %s\n"), *WingUtils::FormatName(SourceNode));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewNode->CreateNewGuid();
|
|
||||||
NewNode->NodePosX += OffsetX;
|
|
||||||
NewNode->NodePosY += OffsetY;
|
|
||||||
|
|
||||||
for (UEdGraphPin* Pin : NewNode->Pins)
|
|
||||||
{
|
|
||||||
if (Pin)
|
|
||||||
Pin->LinkedTo.Empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
TargetGraph->AddNode(NewNode, false, false);
|
|
||||||
UWingServer::Printf(TEXT("Duplicated: %s -> %s\n"), *WingUtils::FormatName(SourceNode), *WingUtils::FormatName(NewNode));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -92,12 +92,12 @@ public:
|
|||||||
if (!Node) return;
|
if (!Node) return;
|
||||||
|
|
||||||
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Node, CPF_Edit);
|
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Node, CPF_Edit);
|
||||||
FWingProperty P = FWingProperty::FindOneExactMatch(All, Entry.Name);
|
FWingProperty *P = WingUtils::FindOneWithExternalID(Entry.Name, All, TEXT("Property"));
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
|
|
||||||
UWingServer::AddTouchedObject(Node);
|
UWingServer::AddTouchedObject(Node);
|
||||||
|
|
||||||
if (!P.SetText(Entry.Value))
|
if (!P->SetText(Entry.Value))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ public:
|
|||||||
if (!Obj) return;
|
if (!Obj) return;
|
||||||
|
|
||||||
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
TArray<FWingProperty> All = FWingProperty::GetDetailsMutable(Obj, CPF_Edit);
|
||||||
FWingProperty P = FWingProperty::FindOneExactMatch(All, Property);
|
FWingProperty *P = WingUtils::FindOneWithExternalID(Property, All, TEXT("Property"));
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
|
|
||||||
UWingServer::Print(P.GetText());
|
UWingServer::Print(P->GetText());
|
||||||
UWingServer::Print(TEXT("\n"));
|
UWingServer::Print(TEXT("\n"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,15 +48,15 @@ public:
|
|||||||
// Validation pass — resolve all properties and values before modifying anything.
|
// Validation pass — resolve all properties and values before modifying anything.
|
||||||
for (const auto& Pair : Properties.Json->Values)
|
for (const auto& Pair : Properties.Json->Values)
|
||||||
{
|
{
|
||||||
FWingProperty P = FWingProperty::FindOneExactMatch(All, Pair.Key);
|
FWingProperty *P = WingUtils::FindOneWithExternalID(Pair.Key, All, TEXT("Property"));
|
||||||
if (!P) return;
|
if (!P) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assignment Pass - store the values.
|
// Assignment Pass - store the values.
|
||||||
for (const auto& Pair : Properties.Json->Values)
|
for (const auto& Pair : Properties.Json->Values)
|
||||||
{
|
{
|
||||||
FWingProperty P = FWingProperty::FindOneExactMatch(All, Pair.Key);
|
FWingProperty *P = WingUtils::FindOneWithExternalID(Pair.Key, All, TEXT("Property"));
|
||||||
if (P.SetJson(Pair.Value)) SuccessCount++;
|
if (P && P->SetJson(Pair.Value)) SuccessCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
UWingServer::Printf(TEXT("Set %d/%d properties.\n"), SuccessCount, Properties.Json->Values.Num());
|
UWingServer::Printf(TEXT("Set %d/%d properties.\n"), SuccessCount, Properties.Json->Values.Num());
|
||||||
|
|||||||
@@ -336,27 +336,6 @@ TArray<FWingProperty> FWingProperty::FindAllSubstring(const TArray<FWingProperty
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FWingProperty FWingProperty::FindOneExactMatch(const TArray<FWingProperty>& Props, const FString& Name)
|
|
||||||
{
|
|
||||||
TArray<FWingProperty> Matches;
|
|
||||||
for (const FWingProperty& P : Props)
|
|
||||||
{
|
|
||||||
if (WingUtils::Identifies(Name, P.Prop))
|
|
||||||
Matches.Add(P);
|
|
||||||
}
|
|
||||||
if (Matches.Num() == 0)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Property '%s' not found\n"), *Name);
|
|
||||||
return FWingProperty();
|
|
||||||
}
|
|
||||||
if (Matches.Num() > 1)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Ambiguous property '%s'\n"), *Name);
|
|
||||||
return FWingProperty();
|
|
||||||
}
|
|
||||||
return Matches[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FWingProperty::PopulateFromJson(FWingProperty& P, const FJsonObject* Json, bool AllOptional)
|
bool FWingProperty::PopulateFromJson(FWingProperty& P, const FJsonObject* Json, bool AllOptional)
|
||||||
{
|
{
|
||||||
FString JsonKey = WingUtils::FormatName(P.Prop);
|
FString JsonKey = WingUtils::FormatName(P.Prop);
|
||||||
|
|||||||
@@ -311,3 +311,14 @@ FString WingTokenizer::CheckInternalizeID(const FString &ExternalID)
|
|||||||
}
|
}
|
||||||
return InternalID;
|
return InternalID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString WingTokenizer::SimplifyID(const FString &ID)
|
||||||
|
{
|
||||||
|
TStringBuilder<512> Result;
|
||||||
|
for (TCHAR Ch : ID)
|
||||||
|
{
|
||||||
|
if (WingCharacterClasses::GetCat(Ch) == Cat::Identifier)
|
||||||
|
Result.AppendChar(Ch);
|
||||||
|
}
|
||||||
|
return Result.ToString();
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "WingUtils.h"
|
#include "WingUtils.h"
|
||||||
#include "WingServer.h"
|
#include "WingServer.h"
|
||||||
#include "WingManual.h"
|
#include "WingManual.h"
|
||||||
|
#include "WingTokenizer.h"
|
||||||
#include "Editor.h"
|
#include "Editor.h"
|
||||||
#include "EdGraphSchema_K2.h"
|
#include "EdGraphSchema_K2.h"
|
||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
@@ -161,15 +162,17 @@ FString UWingTypes::NewShortName(const FString &Path, FName PinCategory, const U
|
|||||||
// Verify that the path is not already associated.
|
// Verify that the path is not already associated.
|
||||||
check(!PathToShort.Find(Path));
|
check(!PathToShort.Find(Path));
|
||||||
|
|
||||||
// Derive the name proposal from the path.
|
// Derive the name proposal from the path. Names used by
|
||||||
|
// the type system are always simple ids that require no
|
||||||
|
// escaping when emitted.
|
||||||
int32 DotIndex;
|
int32 DotIndex;
|
||||||
check(Path.FindLastChar('.', DotIndex));
|
check(Path.FindLastChar('.', DotIndex));
|
||||||
FString Proposal = Path.Mid(DotIndex + 1);
|
FString Proposal = Path.Mid(DotIndex + 1);
|
||||||
if ((PinCategory == UEdGraphSchema_K2::PC_Object || PinCategory == UEdGraphSchema_K2::PC_Interface)
|
if ((PinCategory == UEdGraphSchema_K2::PC_Object || PinCategory == UEdGraphSchema_K2::PC_Interface)
|
||||||
&& IsUserDefined && Proposal.EndsWith(TEXT("_C")))
|
&& IsUserDefined && Proposal.EndsWith(TEXT("_C")))
|
||||||
Proposal.LeftChopInline(2);
|
Proposal.LeftChopInline(2);
|
||||||
Proposal = WingUtils::ExternalizeID(Proposal);
|
Proposal = WingTokenizer::SimplifyID(Proposal);
|
||||||
check(!Proposal.IsEmpty());
|
if (Proposal.IsEmpty()) Proposal = "Unknown";
|
||||||
|
|
||||||
// Construct the Info struct.
|
// Construct the Info struct.
|
||||||
Info TypeInfo;
|
Info TypeInfo;
|
||||||
|
|||||||
@@ -55,10 +55,7 @@
|
|||||||
// Name sanitization
|
// Name sanitization
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
FString WingUtils::ExternalizeID(const FString &InName)
|
FName WingUtils::GetFName(const FWingProperty &Prop) { return Prop.Prop->GetFName(); }
|
||||||
{
|
|
||||||
return WingTokenizer::ExternalizeID(InName);
|
|
||||||
}
|
|
||||||
|
|
||||||
FString WingUtils::ExternalizeID(FName Name)
|
FString WingUtils::ExternalizeID(FName Name)
|
||||||
{
|
{
|
||||||
@@ -126,7 +123,7 @@ FString WingUtils::FormatName(const UBlueprint *BP)
|
|||||||
|
|
||||||
FString WingUtils::FormatName(const UActorComponent *C)
|
FString WingUtils::FormatName(const UActorComponent *C)
|
||||||
{
|
{
|
||||||
return ExternalizeID(C->GetName());
|
return ExternalizeID(C->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const USCS_Node *Node)
|
FString WingUtils::FormatName(const USCS_Node *Node)
|
||||||
@@ -136,22 +133,22 @@ FString WingUtils::FormatName(const USCS_Node *Node)
|
|||||||
|
|
||||||
FString WingUtils::FormatName(const UEdGraph *Graph)
|
FString WingUtils::FormatName(const UEdGraph *Graph)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Graph->GetName());
|
return ExternalizeID(Graph->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const TObjectPtr<UEdGraph> &Graph)
|
FString WingUtils::FormatName(const TObjectPtr<UEdGraph> &Graph)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Graph->GetName());
|
return ExternalizeID(Graph->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const UEdGraphNode* Node)
|
FString WingUtils::FormatName(const UEdGraphNode* Node)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Node->GetName());
|
return ExternalizeID(Node->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const UEdGraphPin *Pin)
|
FString WingUtils::FormatName(const UEdGraphPin *Pin)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Pin->GetName());
|
return ExternalizeID(Pin->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const FMemberReference &Ref)
|
FString WingUtils::FormatName(const FMemberReference &Ref)
|
||||||
@@ -168,7 +165,7 @@ FString WingUtils::FormatName(const UStruct *Struct)
|
|||||||
{
|
{
|
||||||
if (Cast<UScriptStruct>(Struct) || Cast<UClass>(Struct))
|
if (Cast<UScriptStruct>(Struct) || Cast<UClass>(Struct))
|
||||||
return UWingTypes::TypeToTextOrDie(Struct);
|
return UWingTypes::TypeToTextOrDie(Struct);
|
||||||
return ExternalizeID(Struct->GetName());
|
return ExternalizeID(Struct->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const UClass *Class)
|
FString WingUtils::FormatName(const UClass *Class)
|
||||||
@@ -193,7 +190,7 @@ FString WingUtils::FormatName(const UMaterialFunction *MaterialFunction)
|
|||||||
|
|
||||||
FString WingUtils::FormatName(const UMaterialExpression *Expression)
|
FString WingUtils::FormatName(const UMaterialExpression *Expression)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Expression->GetName());
|
return ExternalizeID(Expression->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const UStaticMesh *Mesh)
|
FString WingUtils::FormatName(const UStaticMesh *Mesh)
|
||||||
@@ -233,7 +230,7 @@ FString WingUtils::FormatName(const UEnum *Enum)
|
|||||||
|
|
||||||
FString WingUtils::FormatName(const FProperty *Prop)
|
FString WingUtils::FormatName(const FProperty *Prop)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Prop->GetName());
|
return ExternalizeID(Prop->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FString WingUtils::FormatName(const FUserPinInfo &Pin)
|
FString WingUtils::FormatName(const FUserPinInfo &Pin)
|
||||||
@@ -253,7 +250,7 @@ FString WingUtils::FormatName(const UWingComponentReference *Ref)
|
|||||||
|
|
||||||
FString WingUtils::FormatName(const UWidget *Widget)
|
FString WingUtils::FormatName(const UWidget *Widget)
|
||||||
{
|
{
|
||||||
return ExternalizeID(Widget->GetName());
|
return ExternalizeID(Widget->GetFName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ struct FWingProperty
|
|||||||
// Functions to find items by name in an array of properties.
|
// Functions to find items by name in an array of properties.
|
||||||
//
|
//
|
||||||
static TArray<FWingProperty> FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring);
|
static TArray<FWingProperty> FindAllSubstring(const TArray<FWingProperty>& Props, const FString& Substring);
|
||||||
static FWingProperty FindOneExactMatch(const TArray<FWingProperty>& Props, const FString& Name);
|
|
||||||
static void Remove(TArray<FWingProperty>& Props, const FString& Name);
|
static void Remove(TArray<FWingProperty>& Props, const FString& Name);
|
||||||
static void Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, const FString &Name);
|
static void Move(TArray<FWingProperty> &Out, TArray<FWingProperty> &In, const FString &Name);
|
||||||
|
|
||||||
|
|||||||
@@ -150,6 +150,13 @@ struct WingTokenizer
|
|||||||
// string.
|
// string.
|
||||||
static FString CheckInternalizeID(const FString &ExternalID);
|
static FString CheckInternalizeID(const FString &ExternalID);
|
||||||
|
|
||||||
|
// Simplify an ID. This removes any non-identifier
|
||||||
|
// characters from the ID. Be careful! This could
|
||||||
|
// remove the whole identifier! So obviously this
|
||||||
|
// should only be used in certain rare contexts where
|
||||||
|
// that's OK.
|
||||||
|
static FString SimplifyID(const FString &ID);
|
||||||
|
|
||||||
// Print all tokens to the log for debugging.
|
// Print all tokens to the log for debugging.
|
||||||
void PrintEverything() const;
|
void PrintEverything() const;
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class UAnimStateTransitionNode;
|
|||||||
class UScriptStruct;
|
class UScriptStruct;
|
||||||
class UEnum;
|
class UEnum;
|
||||||
struct FBPInterfaceDescription;
|
struct FBPInterfaceDescription;
|
||||||
|
struct FWingProperty;
|
||||||
|
|
||||||
#include "Engine/World.h"
|
#include "Engine/World.h"
|
||||||
#include "Materials/Material.h"
|
#include "Materials/Material.h"
|
||||||
@@ -37,21 +38,14 @@ struct FBPInterfaceDescription;
|
|||||||
class WingUtils
|
class WingUtils
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Given an array and a reference to an element of the array, return
|
|
||||||
// a pointer to the element, or if the element is already a pointer, the element.
|
|
||||||
template<class T> static const T* EltAsPtr(const TArray<T> &A, const T &Elt) { return &Elt; }
|
|
||||||
template<class T> static T* EltAsPtr(TArray<T> &A, T &Elt) { return &Elt; }
|
|
||||||
template<class T> static T* EltAsPtr(const TArray<T*> &A, T* &Elt) { return Elt; }
|
|
||||||
template<class T> static T* EltAsPtr(TArray<T*> &A, T* &Elt) { return Elt; }
|
|
||||||
template<class T> static const T* EltAsPtr(const TArray<const T*> &A, const T* &Elt) { return Elt; }
|
|
||||||
template<class T> static const T* EltAsPtr(TArray<const T*> &A, const T* &Elt) { return Elt; }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// GetFName
|
// GetFName
|
||||||
//
|
//
|
||||||
// For objects whose FormatName uses ExternalizeID,
|
// Get the FName of anything that has an FName. This
|
||||||
// GetFName returns the raw internal FName.
|
// is here because having a consistent way to get the FName
|
||||||
|
// of something makes it possible to write search templates
|
||||||
|
// that work on any of these types.
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -64,10 +58,45 @@ public:
|
|||||||
static FName GetFName(const FBPVariableDescription &Var) { return Var.VarName; }
|
static FName GetFName(const FBPVariableDescription &Var) { return Var.VarName; }
|
||||||
static FName GetFName(const UMaterialExpression *Expression) { return Expression->GetFName(); }
|
static FName GetFName(const UMaterialExpression *Expression) { return Expression->GetFName(); }
|
||||||
static FName GetFName(const FProperty *Prop) { return Prop->GetFName(); }
|
static FName GetFName(const FProperty *Prop) { return Prop->GetFName(); }
|
||||||
|
static FName GetFName(const FWingProperty &Prop);
|
||||||
static FName GetFName(const FUserPinInfo &Pin) { return Pin.PinName; }
|
static FName GetFName(const FUserPinInfo &Pin) { return Pin.PinName; }
|
||||||
static FName GetFName(const UWingComponentReference *Ref) { return Ref->VariableName; }
|
static FName GetFName(const UWingComponentReference *Ref) { return Ref->VariableName; }
|
||||||
static FName GetFName(const UWidget *Widget) { return Widget->GetFName(); }
|
static FName GetFName(const UWidget *Widget) { return Widget->GetFName(); }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// When searching an array of structs, you want to
|
||||||
|
// return a pointer to one of the structs. When
|
||||||
|
// searching an array of pointers, you want to return
|
||||||
|
// one of the pointers. These helpers make it easy for
|
||||||
|
// the search templates below to do that.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template<class T> static const T* EltAsPtr(const TArray<T> &A, const T &Elt) { return &Elt; }
|
||||||
|
template<class T> static T* EltAsPtr(TArray<T> &A, T &Elt) { return &Elt; }
|
||||||
|
template<class T> static T* EltAsPtr(const TArray<T*> &A, T* &Elt) { return Elt; }
|
||||||
|
template<class T> static T* EltAsPtr(TArray<T*> &A, T* &Elt) { return Elt; }
|
||||||
|
template<class T> static const T* EltAsPtr(const TArray<const T*> &A, const T* &Elt) { return Elt; }
|
||||||
|
template<class T> static const T* EltAsPtr(TArray<const T*> &A, const T* &Elt) { return Elt; }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Search Templates. Search an array for an item with a
|
||||||
|
// given name. Works correctly no matter how a name is
|
||||||
|
// expressed: eg, "A+B" finds the same results as
|
||||||
|
// "A+B". Handles failure cases correctly: two
|
||||||
|
// items with the same name, no such item, and malformed
|
||||||
|
// names. In case of failure, sends readable and
|
||||||
|
// informative error messages to the AI Agent.
|
||||||
|
//
|
||||||
|
// Try to direct all searching through these templates,
|
||||||
|
// given the amount of care that was put into ensuring
|
||||||
|
// their correctness and the quality of their error
|
||||||
|
// reporting.
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<typename ArrayType>
|
template<typename ArrayType>
|
||||||
static auto FindOneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind)
|
static auto FindOneWithInternalID(FName InternalID, ArrayType &&Array, const TCHAR *Kind)
|
||||||
{
|
{
|
||||||
@@ -103,32 +132,13 @@ public:
|
|||||||
return FindNoneWithInternalID(InternalID, Array, Kind);
|
return FindNoneWithInternalID(InternalID, Array, Kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// GetPathName
|
|
||||||
//
|
|
||||||
// For objects whose FormatName returns a path name,
|
|
||||||
// GetPathName returns the raw path.
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static FString GetPathName(const UWorld *World) { return World->GetPathName(); }
|
|
||||||
static FString GetPathName(const UMaterial *Material) { return Material->GetPathName(); }
|
|
||||||
static FString GetPathName(const UMaterialInstance *MI) { return MI->GetPathName(); }
|
|
||||||
static FString GetPathName(const UMaterialFunction *MF) { return MF->GetPathName(); }
|
|
||||||
static FString GetPathName(const UStaticMesh *Mesh) { return Mesh->GetPathName(); }
|
|
||||||
static FString GetPathName(const USkeletalMesh *Mesh) { return Mesh->GetPathName(); }
|
|
||||||
static FString GetPathName(const UAnimSequence *Anim) { return Anim->GetPathName(); }
|
|
||||||
static FString GetPathName(const UTexture *Texture) { return Texture->GetPathName(); }
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Name Formatting
|
// Name Formatting
|
||||||
//
|
//
|
||||||
// The goal here is to centralize the code that outputs
|
// Get the name of something, and format it for transmission
|
||||||
// names, and have everybody use it, so that names are
|
// to the AI Agent. These correctly handle all escaping and
|
||||||
// used consistently. When an identifier is output by
|
// quoting.
|
||||||
// FormatName, it's always an ExternalID.
|
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -161,54 +171,9 @@ public:
|
|||||||
static FString FormatName(const UWingComponentReference *Ref);
|
static FString FormatName(const UWingComponentReference *Ref);
|
||||||
static FString FormatName(const UWidget *Widget);
|
static FString FormatName(const UWidget *Widget);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
// Identifies
|
|
||||||
//
|
|
||||||
// Return true if the name matches the formatted name
|
|
||||||
// of the object, using the formatname routines above.
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static bool Identifies(const FString &ExternalID, T&& Obj)
|
|
||||||
{
|
|
||||||
return FormatName(std::forward<T>(Obj)).Equals(ExternalID, ESearchCase::IgnoreCase);
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
|
// static FString ExternalizeID(const FString& InternalID);
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static T* FindExactlyOneNamed(const FString &Name, const TArray<T*> &Array, const TCHAR *Kind)
|
|
||||||
{
|
|
||||||
int Count = 0;
|
|
||||||
T* Result = nullptr;
|
|
||||||
for (T* Elt : Array) if (Identifies(Name, Elt)) { Count++; Result = Elt; }
|
|
||||||
if (!CheckExactlyOneNamed(Count, Kind, Name)) return nullptr;
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename = std::enable_if_t<!std::is_pointer_v<T>>>
|
|
||||||
static T* FindExactlyOneNamed(const FString &Name, TArray<T> &Array, const TCHAR *Kind)
|
|
||||||
{
|
|
||||||
int Count = 0;
|
|
||||||
T* Result = nullptr;
|
|
||||||
for (T& Elt : Array) if (Identifies(Name, Elt)) { Count++; Result = &Elt; }
|
|
||||||
if (!CheckExactlyOneNamed(Count, Kind, Name)) return nullptr;
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static bool FindExactlyNoneNamed(const FString &Name, const TArray<T> &Array, const TCHAR *Kind)
|
|
||||||
{
|
|
||||||
for (const T& Elt: Array) if (Identifies(Name, Elt))
|
|
||||||
{
|
|
||||||
return CheckExactlyNoneNamed(1, Kind, Name);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
|
||||||
static FString ExternalizeID(const FString& InternalID);
|
|
||||||
static FString ExternalizeID(FName Name);
|
static FString ExternalizeID(FName Name);
|
||||||
|
|
||||||
static FName CheckInternalizeID(const FString &ExternalID);
|
static FName CheckInternalizeID(const FString &ExternalID);
|
||||||
|
|||||||
Reference in New Issue
Block a user