//////////////////////////////////////////////////////////// // // RootCanvas.cpp // //////////////////////////////////////////////////////////// #include "RootCanvas.h" #include "Common.h" #include "Blueprint/UserWidget.h" UlxRootCanvasSlot::UlxRootCanvasSlot(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) { // Children of the root canvas default to filling the parent, // matching the viewport's "stretch" behavior. Individual widgets // can still override anchors/offsets after being added. SetAnchors(FAnchors(0.0f, 0.0f, 1.0f, 1.0f)); SetOffsets(FMargin(0.0f, 0.0f, 0.0f, 0.0f)); } UClass* UlxRootCanvasPanel::GetSlotClass() const { return UlxRootCanvasSlot::StaticClass(); } UlxRootCanvasSlot *UlxRootCanvasPanel::GetRootCanvasSlot(UUserWidget *Widget, ElxSuccessOrWrongType &Result) { if (IsValid(Widget)) { if (UlxRootCanvasSlot *Slot = Cast(Widget->Slot)) { Result = ElxSuccessOrWrongType::Success; return Slot; } } Result = ElxSuccessOrWrongType::WrongType; return nullptr; } UlxRootCanvasSlot* UlxRootCanvasPanel::AddChildToRootCanvas(UWidget* Content) { return Cast(Super::AddChild(Content)); } int32 UlxRootCanvasPanel::GetMaxZOrder() const { int32 MaxZOrder = 0; for (UPanelSlot *PanelSlot : Slots) { UlxRootCanvasSlot *TypedSlot = Cast(PanelSlot); check(TypedSlot); MaxZOrder = FMath::Max(MaxZOrder, TypedSlot->GetZOrder()); } return MaxZOrder; } void UlxRootCanvasPanel::PropagateZOrderToSlate() { if (!MustPropagateZOrderToSlate) return; MustPropagateZOrderToSlate = false; for (UPanelSlot *PanelSlot : Slots) { UlxRootCanvasSlot *TypedSlot = Cast(PanelSlot); check(TypedSlot); TypedSlot->SetZOrder(TypedSlot->GetZOrder()); } } TArray UlxRootCanvasPanel::GetSortedUserWidgets() { TArray Result; Result.Reserve(Slots.Num()); for (UPanelSlot *PanelSlot : Slots) { UlxRootCanvasSlot *TypedSlot = Cast(PanelSlot); check(TypedSlot); if (Cast(TypedSlot->Content) == nullptr) continue; Result.Add(TypedSlot); } Result.StableSort([](const UlxRootCanvasSlot &A, const UlxRootCanvasSlot &B) { return A.GetZOrder() > B.GetZOrder(); }); return Result; } void UlxRootCanvasPanel::SetWidgetWindowManagement(class UUserWidget *Widget, bool ShowPointer, bool BlockInput, bool EnableEnhancedInput, bool BringToFront, UWidget *DesiredFocusWidget) { if (!IsValid(Widget)) { UE_LOG(LogLuprexIntegration, Error, TEXT("ManageRootWidget called with an invalid widget.")); return; } UlxRootCanvasSlot *Slot = Cast(Widget->Slot); if (Slot == nullptr) { UE_LOG(LogLuprexIntegration, Error, TEXT("Widget is not yet a root widget, use 'AddWidgetToRoot' first")); return; } UlxRootCanvasPanel *Panel = Cast(Slot->Parent); check(Panel); Slot->ShowPointer = ShowPointer; Slot->BlockInput = BlockInput; Slot->EnableEnhancedInput = EnableEnhancedInput; Widget->SetDesiredFocusWidget(DesiredFocusWidget); if (BringToFront) { // Write the int32 ZOrder UPROPERTY directly and defer the // Slate-side push to PropagateZOrderToSlate. Going through SetZOrder // here is unsafe when called from Event Construct: the FSlot // has been Exposed but its Owner isn't set yet, which fires // an ensure in SConstraintCanvas::FSlot::SetZOrder. PRAGMA_DISABLE_DEPRECATION_WARNINGS Slot->ZOrder = Panel->GetMaxZOrder() + 1; PRAGMA_ENABLE_DEPRECATION_WARNINGS Panel->MustPropagateZOrderToSlate = true; } }