#pragma once #include "CoreMinimal.h" #include "Dom/JsonObject.h" #include "EdGraph/EdGraph.h" #include "EdGraph/EdGraphPin.h" #include "Materials/MaterialInstanceConstant.h" #include "MaterialTypes.h" class UBlueprint; class UEdGraphNode; class UEdGraphPin; class UMaterial; class UMaterialInstance; class UMaterialFunction; class UMaterialExpression; struct FEdGraphSchemaAction; class UAnimationStateMachineGraph; class UAnimStateNode; class UAnimStateTransitionNode; class UActorComponent; class UWorld; class UStaticMesh; class USkeletalMesh; class UAnimSequence; class UBlendSpace; class UTexture; class UScriptStruct; class UEnum; class USCS_Node; struct FMemberReference; struct FBPVariableDescription; // Stateless utility functions used by MCP handlers and the MCP server. // This is effectively a namespace — all methods are static. class WingUtils { public: //////////////////////////////////////////////////////// // // Name Formatting // // The goal here is to centralize the code that outputs // names, and have everybody use it, so that names are // used consistently. The secondary goal is to choose // names that are as uniquely-identifying as is practical. // It's not always 100% possible to get perfectly unique // names, though, so our code needs to check for ambiguity. // //////////////////////////////////////////////////////// static FString FormatName(const UWorld *World); static FString FormatName(const UBlueprint *BP); static FString FormatName(const UActorComponent *C); static FString FormatName(const USCS_Node *Node); static FString FormatName(const UEdGraph *Graph); static FString FormatName(const UEdGraphNode* Node); static FString FormatName(const UEdGraphPin *Pin); static FString FormatName(const FMemberReference &Ref); static FString FormatName(const FBPVariableDescription &Var); static FString FormatName(const UStruct *Struct); static FString FormatName(const UMaterial *Material); static FString FormatName(const UMaterialInstance *MaterialInstance); static FString FormatName(const UMaterialFunction *MaterialFunction); static FString FormatName(const UMaterialExpression *Expression); static FString FormatName(const UStaticMesh *Mesh); static FString FormatName(const USkeletalMesh *Mesh); static FString FormatName(const UAnimSequence *Anim); static FString FormatName(const UBlendSpace *BlendSpace); static FString FormatName(const UTexture *Texture); static FString FormatName(const UScriptStruct *Struct); static FString FormatName(const UEnum *Enum); static FString FormatName(const FProperty *Prop); //////////////////////////////////////////////////////// // // Identifies // // Return true if the name identifies the object. The // FormatName functions, above, always return names that // identify the object. However, there may be other // names that also identify the object. Identifying names // aren't 100% guaranteed to be unique, but very likely. // //////////////////////////////////////////////////////// template static bool Identifies(const FString &Name, T&& Obj) { return FormatName(std::forward(Obj)).Equals(Name, ESearchCase::IgnoreCase); } // UEdGraphNode also matches by GUID. static bool Identifies(const FString &Name, const UEdGraphNode* Node); //////////////////////////////////////////////////////// static void SanitizeNameInPlace(FString& Name); static FString SanitizeName(const FString& Name); static FString SanitizeName(FName Name); static FString FormatNodeTitle(const UEdGraphNode *Node); // ----- Enum helpers ----- static FString EnumToString(UEnum* Enum, int64 Value, const FString& Prefix = FString()); static bool StringToEnum(UEnum* Enum, const FString& Str, int64& OutValue, const FString& Prefix = FString()); template static FString EnumToString(TEnumAsByte Value, const FString& Prefix = FString()) { return EnumToString(StaticEnum(), (int64)Value, Prefix); } template static FString EnumToString(T Value, const FString& Prefix = FString()) { return EnumToString(StaticEnum(), (int64)Value, Prefix); } template static bool StringToEnum(const FString& Str, T& OutValue, const FString& Prefix = FString()) { int64 V; if (!StringToEnum(StaticEnum(), Str, V, Prefix)) return false; OutValue = (T)V; return true; } // ----- Blueprint helpers ----- static TArray AllGraphs(UBlueprint* BP); static TArray AllGraphsNamed(UBlueprint* BP, const FString& Name); static TArray AllNodes(UBlueprint* BP); template static TArray AllNodes(UBlueprint* BP) { TArray Result; for (UEdGraph* Graph : AllGraphs(BP)) for (UEdGraphNode* Node : Graph->Nodes) if (T* Typed = Cast(Node)) Result.Add(Typed); return Result; } template static TArray AllNodes(UEdGraph* Graph) { TArray Result; for (UEdGraphNode* Node : Graph->Nodes) if (T* Typed = Cast(Node)) Result.Add(Typed); return Result; } static bool SaveBlueprintPackage(UBlueprint* BP); static UClass* FindClassByName(const FString& ClassName); // ----- Material helpers ----- static void EnsureMaterialGraph(UMaterial* Material); static bool SaveGenericPackage(UObject* Asset); // If the material editor has a transient preview copy of this material, // return that copy (which is what the editor is actually working on). // Otherwise return the original. static UMaterial* ReplaceMaterialWithTransientCopy(UMaterial* Material); // ----- Anim blueprint helpers ----- static UAnimationStateMachineGraph* FindStateMachineGraph(UBlueprint* BP, const FString& GraphName); static UAnimStateNode* FindStateByName(UAnimationStateMachineGraph* SMGraph, const FString& StateName); static UAnimStateTransitionNode* FindTransition(UAnimationStateMachineGraph* SMGraph, const FString& FromStateName, const FString& ToStateName); // ----- Graph actions (node spawning) ----- static FString ActionFullName(const TSharedPtr& Action); static TArray> SearchGraphActions(UEdGraph* Graph, const FString& Query, int32 MaxResults = 0, bool ExactMatch = false); // ----- Editable template ----- static TArray SearchProperties(UObject* Obj, const FString& Query, EPropertyFlags Flags, bool bLocal); static FProperty* FindPropertyByName(UObject* Obj, const FString& Name); static FString GetPropertyValueText(UObject* Container, FProperty* Prop); static bool SetPropertyValueText(UObject* Container, FProperty* Prop, const FString& Value); static bool SetPropertyValueText(void* Container, FProperty* Prop, const FString& Value, UObject* Owner); // ----- Text formatting ----- static FString WrapText(const FString& Text, int32 ColLimit, const FString& Prefix); // ----- Handler discovery ----- static TArray CollectHandlerClasses(); static FString GetHandlerName(UClass* HandlerClass); static FString GetHandlerGroup(UClass* HandlerClass); static void FormatCommandHelp(UClass* HandlerClass); private: static void AppendNumericSuffix(FString &Name, int32 N); };