Added WingActorComponent
This commit is contained in:
@@ -73,22 +73,8 @@ public:
|
|||||||
USCS_Node* ParentSCSNode = nullptr;
|
USCS_Node* ParentSCSNode = nullptr;
|
||||||
if (!Parent.IsEmpty())
|
if (!Parent.IsEmpty())
|
||||||
{
|
{
|
||||||
for (USCS_Node* Node : Existing)
|
ParentSCSNode = WingUtils::FindExactlyOneNamed(Parent, Existing);
|
||||||
{
|
if (!ParentSCSNode) return;
|
||||||
if (Node && Node->ComponentTemplate &&
|
|
||||||
WingUtils::Identifies(Parent, Node->ComponentTemplate))
|
|
||||||
{
|
|
||||||
ParentSCSNode = Node;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ParentSCSNode)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT("ERROR: Parent component '%s' not found in Blueprint '%s'\n"),
|
|
||||||
*Parent, *WingUtils::FormatName(BP));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the SCS node
|
// Create the SCS node
|
||||||
|
|||||||
@@ -9,10 +9,7 @@
|
|||||||
#include "Engine/Blueprint.h"
|
#include "Engine/Blueprint.h"
|
||||||
#include "Animation/AnimBlueprint.h"
|
#include "Animation/AnimBlueprint.h"
|
||||||
#include "Animation/Skeleton.h"
|
#include "Animation/Skeleton.h"
|
||||||
#include "Engine/SimpleConstructionScript.h"
|
#include "WingActorComponent.h"
|
||||||
#include "Engine/SCS_Node.h"
|
|
||||||
#include "Components/SceneComponent.h"
|
|
||||||
#include "GameFramework/Actor.h"
|
|
||||||
#include "WingFunctionArgs.h"
|
#include "WingFunctionArgs.h"
|
||||||
#include "Kismet2/BlueprintEditorUtils.h"
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
#include "AnimationGraph.h"
|
#include "AnimationGraph.h"
|
||||||
@@ -82,34 +79,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Components
|
// Components
|
||||||
bool bHasAny = false;
|
TArray<FWingActorComponent> Components = FWingActorComponent::GetAll(BP);
|
||||||
if (UClass* GenClass = BP->GeneratedClass)
|
if (!Components.IsEmpty())
|
||||||
{
|
{
|
||||||
// Native components first.
|
UWingServer::Print(TEXT("\nComponents:\n"));
|
||||||
if (AActor* CDO = Cast<AActor>(GenClass->GetDefaultObject()))
|
for (const FWingActorComponent& Comp : Components)
|
||||||
{
|
{
|
||||||
TArray<UActorComponent*> NativeComponents;
|
UWingServer::Printf(TEXT(" %s %s"), *Comp.GetClassName(), *Comp.GetName());
|
||||||
CDO->GetComponents(NativeComponents);
|
FString ParentName = Comp.GetParentName();
|
||||||
for (UActorComponent* Comp : NativeComponents)
|
if (!ParentName.IsEmpty())
|
||||||
{
|
UWingServer::Printf(TEXT(" [parent: %s]"), *ParentName);
|
||||||
if (!bHasAny) { UWingServer::Print(TEXT("\nComponents:\n")); bHasAny = true; }
|
if (Comp.IsNative())
|
||||||
PrintComponent(Comp, TEXT("native"));
|
UWingServer::Print(TEXT(" [native]"));
|
||||||
}
|
else if (!Comp.IsOwnedBy(BP))
|
||||||
}
|
UWingServer::Print(TEXT(" [inherited]"));
|
||||||
|
UWingServer::Print(TEXT("\n"));
|
||||||
// Blueprint SCS components (this blueprint and parents)
|
|
||||||
TArray<UBlueprint*> Hierarchy;
|
|
||||||
UBlueprint::GetBlueprintHierarchyFromClass(GenClass, Hierarchy);
|
|
||||||
for (int32 i = Hierarchy.Num() - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
UBlueprint* WalkBP = Hierarchy[i];
|
|
||||||
if (!WalkBP->SimpleConstructionScript) continue;
|
|
||||||
const TCHAR* Annotation = (WalkBP == BP) ? nullptr : TEXT("inherited");
|
|
||||||
for (USCS_Node* Node : WalkBP->SimpleConstructionScript->GetAllNodes())
|
|
||||||
{
|
|
||||||
if (!bHasAny) { UWingServer::Print(TEXT("\nComponents:\n")); bHasAny = true; }
|
|
||||||
PrintComponent(Node, Annotation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,34 +187,6 @@ private:
|
|||||||
UWingServer::Printf(TEXT(" %s(%s)\n"), *WingUtils::FormatName(Graph), *Args);
|
UWingServer::Printf(TEXT(" %s(%s)\n"), *WingUtils::FormatName(Graph), *Args);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintComponent(USCS_Node* Node, const TCHAR* Annotation = nullptr)
|
|
||||||
{
|
|
||||||
FString ClassName = Node->ComponentClass
|
|
||||||
? WingUtils::FormatName(Node->ComponentClass)
|
|
||||||
: TEXT("None");
|
|
||||||
UWingServer::Printf(TEXT(" %s %s"),
|
|
||||||
*ClassName,
|
|
||||||
*WingUtils::FormatName(Node));
|
|
||||||
if (Node->ParentComponentOrVariableName != NAME_None)
|
|
||||||
UWingServer::Printf(TEXT(" [parent: %s]"), *Node->ParentComponentOrVariableName.ToString());
|
|
||||||
if (Annotation)
|
|
||||||
UWingServer::Printf(TEXT(" [%s]"), Annotation);
|
|
||||||
UWingServer::Print(TEXT("\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintComponent(UActorComponent* Comp, const TCHAR* Annotation = nullptr)
|
|
||||||
{
|
|
||||||
UWingServer::Printf(TEXT(" %s %s"),
|
|
||||||
*WingUtils::FormatName(Comp->GetClass()),
|
|
||||||
*Comp->GetName());
|
|
||||||
if (USceneComponent* Scene = Cast<USceneComponent>(Comp))
|
|
||||||
if (USceneComponent* Parent = Scene->GetAttachParent())
|
|
||||||
UWingServer::Printf(TEXT(" [parent: %s]"), *Parent->GetName());
|
|
||||||
if (Annotation)
|
|
||||||
UWingServer::Printf(TEXT(" [%s]"), Annotation);
|
|
||||||
UWingServer::Print(TEXT("\n"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintGraph(UEdGraph* Graph, const TCHAR* Type, UClass* Interface = nullptr)
|
void PrintGraph(UEdGraph* Graph, const TCHAR* Type, UClass* Interface = nullptr)
|
||||||
{
|
{
|
||||||
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
TWeakObjectPtr<UK2Node_EditablePinBase> EntryNode;
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#include "WingActorComponent.h"
|
||||||
|
#include "WingUtils.h"
|
||||||
|
#include "Engine/Blueprint.h"
|
||||||
|
#include "Engine/SCS_Node.h"
|
||||||
|
#include "Engine/SimpleConstructionScript.h"
|
||||||
|
#include "Components/ActorComponent.h"
|
||||||
|
#include "Components/SceneComponent.h"
|
||||||
|
#include "GameFramework/Actor.h"
|
||||||
|
#include "Kismet2/BlueprintEditorUtils.h"
|
||||||
|
|
||||||
|
FString FWingActorComponent::GetName() const
|
||||||
|
{
|
||||||
|
if (SCSNode) return WingUtils::FormatName(SCSNode);
|
||||||
|
if (NativeComponent) return WingUtils::FormatName(NativeComponent);
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
|
||||||
|
FString FWingActorComponent::GetClassName() const
|
||||||
|
{
|
||||||
|
if (SCSNode)
|
||||||
|
return SCSNode->ComponentClass ? WingUtils::FormatName(SCSNode->ComponentClass) : TEXT("None");
|
||||||
|
if (NativeComponent)
|
||||||
|
return WingUtils::FormatName(NativeComponent->GetClass());
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
|
||||||
|
FString FWingActorComponent::GetParentName() const
|
||||||
|
{
|
||||||
|
if (SCSNode)
|
||||||
|
{
|
||||||
|
if (SCSNode->ParentComponentOrVariableName != NAME_None)
|
||||||
|
return WingUtils::SanitizeName(SCSNode->ParentComponentOrVariableName);
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
if (NativeComponent)
|
||||||
|
{
|
||||||
|
if (USceneComponent* Scene = Cast<USceneComponent>(NativeComponent))
|
||||||
|
if (USceneComponent* Parent = Scene->GetAttachParent())
|
||||||
|
return WingUtils::FormatName(Parent);
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
return FString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FWingActorComponent::IsOwnedBy(const UBlueprint* BP) const
|
||||||
|
{
|
||||||
|
return BP && BP->GeneratedClass == Owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<FWingActorComponent> FWingActorComponent::GetAll(UBlueprint* BP)
|
||||||
|
{
|
||||||
|
TArray<FWingActorComponent> Result;
|
||||||
|
if (!BP) return Result;
|
||||||
|
|
||||||
|
UClass* GenClass = BP->GeneratedClass;
|
||||||
|
if (!GenClass) return Result;
|
||||||
|
|
||||||
|
// Native components from CDO
|
||||||
|
if (AActor* CDO = Cast<AActor>(GenClass->GetDefaultObject()))
|
||||||
|
{
|
||||||
|
UClass* NativeClass = FBlueprintEditorUtils::FindFirstNativeClass(GenClass);
|
||||||
|
TArray<UActorComponent*> NativeComponents;
|
||||||
|
CDO->GetComponents(NativeComponents);
|
||||||
|
for (UActorComponent* Comp : NativeComponents)
|
||||||
|
Result.Emplace(Comp, NativeClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCS nodes, walking hierarchy from oldest ancestor to current BP
|
||||||
|
TArray<UBlueprint*> Hierarchy;
|
||||||
|
UBlueprint::GetBlueprintHierarchyFromClass(GenClass, Hierarchy);
|
||||||
|
for (int32 i = Hierarchy.Num() - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
UBlueprint* WalkBP = Hierarchy[i];
|
||||||
|
if (!WalkBP->SimpleConstructionScript) continue;
|
||||||
|
UClass* OwnerClass = WalkBP->GeneratedClass;
|
||||||
|
for (USCS_Node* Node : WalkBP->SimpleConstructionScript->GetAllNodes())
|
||||||
|
Result.Emplace(Node, OwnerClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "WingUtils.h"
|
#include "WingUtils.h"
|
||||||
|
#include "WingActorComponent.h"
|
||||||
#include "WingJson.h"
|
#include "WingJson.h"
|
||||||
#include "WingTypes.h"
|
#include "WingTypes.h"
|
||||||
#include "WingServer.h"
|
#include "WingServer.h"
|
||||||
@@ -215,6 +216,11 @@ FString WingUtils::FormatName(const FBPInterfaceDescription &IFace)
|
|||||||
return FormatName(IFace.Interface);
|
return FormatName(IFace.Interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString WingUtils::FormatName(const FWingActorComponent &Comp)
|
||||||
|
{
|
||||||
|
return Comp.GetName();
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Formatting other things
|
// Formatting other things
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
||||||
|
class UBlueprint;
|
||||||
|
class USCS_Node;
|
||||||
|
class UActorComponent;
|
||||||
|
|
||||||
|
struct FWingActorComponent
|
||||||
|
{
|
||||||
|
USCS_Node* SCSNode = nullptr;
|
||||||
|
UActorComponent* NativeComponent = nullptr;
|
||||||
|
UClass* Owner = nullptr;
|
||||||
|
|
||||||
|
FWingActorComponent() = default;
|
||||||
|
FWingActorComponent(USCS_Node* InSCSNode, UClass* InOwner) : SCSNode(InSCSNode), Owner(InOwner) {}
|
||||||
|
FWingActorComponent(UActorComponent* InNative, UClass* InOwner) : NativeComponent(InNative), Owner(InOwner) {}
|
||||||
|
|
||||||
|
explicit operator bool() const { return SCSNode || NativeComponent; }
|
||||||
|
|
||||||
|
FString GetName() const;
|
||||||
|
FString GetClassName() const;
|
||||||
|
FString GetParentName() const;
|
||||||
|
bool IsNative() const { return NativeComponent != nullptr; }
|
||||||
|
bool IsOwnedBy(const UBlueprint* BP) const;
|
||||||
|
|
||||||
|
// Collect all components: native from CDO first, then SCS nodes
|
||||||
|
// walking the hierarchy from oldest ancestor to current blueprint.
|
||||||
|
static TArray<FWingActorComponent> GetAll(UBlueprint* BP);
|
||||||
|
};
|
||||||
@@ -32,6 +32,7 @@ struct FMemberReference;
|
|||||||
struct FBPVariableDescription;
|
struct FBPVariableDescription;
|
||||||
struct FUserPinInfo;
|
struct FUserPinInfo;
|
||||||
struct FBPInterfaceDescription;
|
struct FBPInterfaceDescription;
|
||||||
|
struct FWingActorComponent;
|
||||||
|
|
||||||
// Stateless utility functions used by MCP handlers and the MCP server.
|
// Stateless utility functions used by MCP handlers and the MCP server.
|
||||||
// This is effectively a namespace — all methods are static.
|
// This is effectively a namespace — all methods are static.
|
||||||
@@ -76,6 +77,7 @@ public:
|
|||||||
static FString FormatName(const FProperty *Prop);
|
static FString FormatName(const FProperty *Prop);
|
||||||
static FString FormatName(const FUserPinInfo &Pin);
|
static FString FormatName(const FUserPinInfo &Pin);
|
||||||
static FString FormatName(const FBPInterfaceDescription &IFace);
|
static FString FormatName(const FBPInterfaceDescription &IFace);
|
||||||
|
static FString FormatName(const FWingActorComponent &Comp);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user