More work on Actor components

This commit is contained in:
2026-03-27 15:21:38 -04:00
parent 490b649dc1
commit df50daca2c
4 changed files with 57 additions and 35 deletions

View File

@@ -1,12 +1,10 @@
#pragma once
#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingHandler.h"
#include "WingFetcher.h"
#include "WingUtils.h"
#include "Engine/SCS_Node.h"
#include "Engine/SimpleConstructionScript.h"
#include "WingServer.h"
#include "WingActorComponent.h"
#include "ActorComponent_Remove.generated.h"
@@ -31,25 +29,11 @@ public:
virtual void Handle() override
{
WingFetcher F;
USCS_Node* Node = F.Walk(Component).Cast<USCS_Node>();
if (!Node) return;
UWingComponentReference* CompRef = F.Walk(Component).Cast<UWingComponentReference>();
if (!CompRef) return;
USimpleConstructionScript* SCS = Node->GetSCS();
if (!SCS) return;
if (!CompRef->DeleteComponent()) return;
// Prevent removing a root component that has children
const TArray<USCS_Node*>& RootNodes = SCS->GetRootNodes();
if (RootNodes.Contains(Node) && Node->GetChildNodes().Num() > 0)
{
UWingServer::Printf(TEXT("ERROR: Cannot remove '%s' — it is a root component with %d children. "
"Remove or re-parent the children first.\n"),
*WingUtils::FormatName(Node),
Node->GetChildNodes().Num());
return;
}
FString RemovedName = WingUtils::FormatName(Node);
SCS->RemoveNodeAndPromoteChildren(Node);
UWingServer::Printf(TEXT("Removed component %s.\n"), *RemovedName);
UWingServer::Printf(TEXT("Removed component.\n"));
}
};

View File

@@ -40,6 +40,16 @@ UWingComponentReference::FoundComponent UWingComponentReference::FindComponent(U
return Result;
}
bool UWingComponentReference::CheckExists(UWingComponentReference::FoundComponent FC)
{
if ((FC.SCS == nullptr) && (FC.Native == nullptr))
{
UWingServer::Printf(TEXT("Cannot find component: %s\n"), *WingUtils::SanitizeName(FC.Name));
return false;
}
return true;
}
bool UWingComponentReference::CheckValidParent(UWingComponentReference::FoundComponent FC)
{
if (FC.SCS && FC.Native)
@@ -74,6 +84,28 @@ bool UWingComponentReference::CheckNoSuchComponent(FoundComponent FC)
return true;
}
bool UWingComponentReference::CheckNotNative(FoundComponent FC, const TCHAR *Action)
{
if (FC.Native != nullptr)
{
UWingServer::Printf(TEXT("Component %s is native, cannot %s native components"),
*WingUtils::SanitizeName(FC.Name), Action);
return false;
}
return true;
}
bool UWingComponentReference::CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP)
{
if ((FC.SCS == nullptr) || (FC.SCS->GetSCS() != BP->SimpleConstructionScript))
{
UWingServer::Printf(TEXT("Component %s belongs to blueprint %s, edit that blueprint instead"),
*WingUtils::SanitizeName(FC.Name), *WingUtils::FormatName(FC.SCS->GetSCS()->GetBlueprint()));
return false;
}
return true;
}
bool UWingComponentReference::CheckValidComponentClass(UClass *Class)
{
if (!Class->IsChildOf(UActorComponent::StaticClass()))
@@ -85,6 +117,7 @@ bool UWingComponentReference::CheckValidComponentClass(UClass *Class)
return true;
}
void UWingComponentReference::AddChildNode(UBlueprint *BP, USCS_Node *NewNode, FoundComponent Parent)
{
if (Parent.SCS)
@@ -131,18 +164,10 @@ bool UWingComponentReference::ReparentComponent(UWingComponentReference *Parent)
FoundComponent ParentComponent = FindComponent(BP, Parent->VariableName);
if (!CheckValidParent(ParentComponent)) return false;
FoundComponent ThisComponent = FindComponent(BP, VariableName);
if (!CheckExists(ThisComponent)) return false;
if (!CheckNotNative(ThisComponent, TEXT("reparent"))) return false;
if (!CheckOwnedByBlueprint(ThisComponent, BP)) return false;
if (ThisComponent.SCS == nullptr)
{
UWingServer::Printf(TEXT("Cannot reparent native components."));
return false;
}
if (ThisComponent.SCS->GetSCS() != BP->SimpleConstructionScript)
{
UWingServer::Printf(TEXT("Component belongs to blueprint %s, edit that blueprint to reparent it."),
*WingUtils::FormatName(ThisComponent.SCS->GetSCS()->GetBlueprint()));
return false;
}
if (ParentComponent.SCS && ParentComponent.SCS->IsChildOf(ThisComponent.SCS))
{
UWingServer::Printf(TEXT("Cannot parent a component to itself or its own child."));
@@ -154,6 +179,16 @@ bool UWingComponentReference::ReparentComponent(UWingComponentReference *Parent)
return true;
}
bool UWingComponentReference::DeleteComponent()
{
FoundComponent ThisComponent = FindComponent(BP, VariableName);
if (!CheckExists(ThisComponent)) return false;
if (!CheckNotNative(ThisComponent, TEXT("delete"))) return false;
if (!CheckOwnedByBlueprint(ThisComponent, BP)) return false;
BP->SimpleConstructionScript->RemoveNodeAndPromoteChildren(ThisComponent.SCS);
return true;
}
TMap<FName, FName> UWingComponentReference::CalculateParentNames(USimpleConstructionScript *Script)
{
TMap<FName, FName> ParentNames;

View File

@@ -60,7 +60,10 @@ private:
static USCS_Node* FindSCSNodeByName(UBlueprint *BP, FName VariableName);
static FoundComponent FindComponent(UBlueprint *BP, FName Name);
static bool CheckValidParent(FoundComponent FC);
static bool CheckExists(FoundComponent FC);
static bool CheckNoSuchComponent(FoundComponent FC);
static bool CheckNotNative(FoundComponent FC, const TCHAR *Action);
static bool CheckOwnedByBlueprint(FoundComponent FC, UBlueprint *BP);
static void AddChildNode(UBlueprint *BP, USCS_Node *Node, FoundComponent Parent);
static TMap<FName, FName> CalculateParentNames(USimpleConstructionScript *Script);
};