Files
integration/Plugins/UEWingman/Source/UEWingman/Handlers/Widget_Reparent.h
2026-04-04 01:45:25 -04:00

83 lines
2.5 KiB
C++

#pragma once
#include "CoreMinimal.h"
#include "WingServer.h"
#include "WingHandler.h"
#include "WingFetcher.h"
#include "WingUtils.h"
#include "WingWidgets.h"
#include "WidgetBlueprint.h"
#include "Blueprint/WidgetTree.h"
#include "Components/PanelWidget.h"
#include "Widget_Reparent.generated.h"
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
UCLASS()
class UWing_Widget_Reparent : public UWingHandler
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere, meta=(Description="Path to the widget, eg /Game/Widgets/WB_Test,widget:MyButton"))
FString Widget;
UPROPERTY(EditAnywhere, meta=(Description="Name of the new parent widget. Must be a panel."))
FString Parent;
virtual void Register() override
{
UWingServer::AddHandler(this,
TEXT("Move a widget to a different parent in a Widget Blueprint's widget tree."));
}
virtual void Handle() override
{
// Walk to the widget.
WingFetcher F(WingOut::Stdout);
UWidget* TargetWidget = F.Walk(Widget).Cast<UWidget>();
if (!TargetWidget) return;
// Get the widget blueprint from the widget's outer chain.
UWidgetBlueprint* BP = TargetWidget->GetTypedOuter<UWidgetBlueprint>();
if (!BP)
{
WingOut::Stdout.Printf(TEXT("ERROR: Could not find owning WidgetBlueprint\n"));
return;
}
UWidgetTree* Tree = BP->WidgetTree;
// Get all widgets for name lookup.
TArray<UWidget*> AllWidgets;
Tree->GetAllWidgets(AllWidgets);
FString WidgetName = WingUtils::FormatName(TargetWidget);
// Find the new parent and verify it's a panel with room.
UWidget* ParentWidget = WingUtils::FindOneWithExternalID(Parent, AllWidgets, TEXT("Widget"), WingOut::Stdout);
if (!ParentWidget) return;
if (!WingWidgets::CheckCanBeParent(ParentWidget, WingOut::Stdout)) return;
UPanelWidget* ParentPanel = Cast<UPanelWidget>(ParentWidget);
// Check for circular reparenting.
for (UPanelWidget* Ancestor = ParentPanel; Ancestor != nullptr; Ancestor = Ancestor->GetParent())
{
if (Ancestor == TargetWidget)
{
WingOut::Stdout.Printf(TEXT("ERROR: Cannot reparent '%s' under itself\n"), *WidgetName);
return;
}
}
// Remove from current location.
Tree->RemoveWidget(TargetWidget);
// Add to new parent.
ParentPanel->AddChild(TargetWidget);
WingOut::Stdout.Printf(TEXT("Reparented '%s' under '%s'\n"), *WidgetName, *Parent);
}
};