Added WingActorComponent
This commit is contained in:
@@ -73,22 +73,8 @@ public:
|
||||
USCS_Node* ParentSCSNode = nullptr;
|
||||
if (!Parent.IsEmpty())
|
||||
{
|
||||
for (USCS_Node* Node : Existing)
|
||||
{
|
||||
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;
|
||||
}
|
||||
ParentSCSNode = WingUtils::FindExactlyOneNamed(Parent, Existing);
|
||||
if (!ParentSCSNode) return;
|
||||
}
|
||||
|
||||
// Create the SCS node
|
||||
|
||||
@@ -9,10 +9,7 @@
|
||||
#include "Engine/Blueprint.h"
|
||||
#include "Animation/AnimBlueprint.h"
|
||||
#include "Animation/Skeleton.h"
|
||||
#include "Engine/SimpleConstructionScript.h"
|
||||
#include "Engine/SCS_Node.h"
|
||||
#include "Components/SceneComponent.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
#include "WingActorComponent.h"
|
||||
#include "WingFunctionArgs.h"
|
||||
#include "Kismet2/BlueprintEditorUtils.h"
|
||||
#include "AnimationGraph.h"
|
||||
@@ -82,34 +79,21 @@ public:
|
||||
}
|
||||
|
||||
// Components
|
||||
bool bHasAny = false;
|
||||
if (UClass* GenClass = BP->GeneratedClass)
|
||||
TArray<FWingActorComponent> Components = FWingActorComponent::GetAll(BP);
|
||||
if (!Components.IsEmpty())
|
||||
{
|
||||
// Native components first.
|
||||
if (AActor* CDO = Cast<AActor>(GenClass->GetDefaultObject()))
|
||||
UWingServer::Print(TEXT("\nComponents:\n"));
|
||||
for (const FWingActorComponent& Comp : Components)
|
||||
{
|
||||
TArray<UActorComponent*> NativeComponents;
|
||||
CDO->GetComponents(NativeComponents);
|
||||
for (UActorComponent* Comp : NativeComponents)
|
||||
{
|
||||
if (!bHasAny) { UWingServer::Print(TEXT("\nComponents:\n")); bHasAny = true; }
|
||||
PrintComponent(Comp, TEXT("native"));
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
UWingServer::Printf(TEXT(" %s %s"), *Comp.GetClassName(), *Comp.GetName());
|
||||
FString ParentName = Comp.GetParentName();
|
||||
if (!ParentName.IsEmpty())
|
||||
UWingServer::Printf(TEXT(" [parent: %s]"), *ParentName);
|
||||
if (Comp.IsNative())
|
||||
UWingServer::Print(TEXT(" [native]"));
|
||||
else if (!Comp.IsOwnedBy(BP))
|
||||
UWingServer::Print(TEXT(" [inherited]"));
|
||||
UWingServer::Print(TEXT("\n"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,34 +187,6 @@ private:
|
||||
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)
|
||||
{
|
||||
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 "WingActorComponent.h"
|
||||
#include "WingJson.h"
|
||||
#include "WingTypes.h"
|
||||
#include "WingServer.h"
|
||||
@@ -215,6 +216,11 @@ FString WingUtils::FormatName(const FBPInterfaceDescription &IFace)
|
||||
return FormatName(IFace.Interface);
|
||||
}
|
||||
|
||||
FString WingUtils::FormatName(const FWingActorComponent &Comp)
|
||||
{
|
||||
return Comp.GetName();
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// 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 FUserPinInfo;
|
||||
struct FBPInterfaceDescription;
|
||||
struct FWingActorComponent;
|
||||
|
||||
// Stateless utility functions used by MCP handlers and the MCP server.
|
||||
// This is effectively a namespace — all methods are static.
|
||||
@@ -76,6 +77,7 @@ public:
|
||||
static FString FormatName(const FProperty *Prop);
|
||||
static FString FormatName(const FUserPinInfo &Pin);
|
||||
static FString FormatName(const FBPInterfaceDescription &IFace);
|
||||
static FString FormatName(const FWingActorComponent &Comp);
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user