From cdb99af956e664a14377934d5355af34f1e12c19 Mon Sep 17 00:00:00 2001 From: Emmanuel AYME Date: Wed, 11 Mar 2026 08:10:32 +0100 Subject: [PATCH] Transferred widgets methods to another lib --- libs/UEngine/UETools.cpp | 326 --------------------------------------- 1 file changed, 326 deletions(-) diff --git a/libs/UEngine/UETools.cpp b/libs/UEngine/UETools.cpp index cb0c5ef..d1994b2 100644 --- a/libs/UEngine/UETools.cpp +++ b/libs/UEngine/UETools.cpp @@ -76,330 +76,4 @@ void ReactivateDevConsole(std::shared_ptr logger) { return; } }).detach(); -} -// --- HUD & UI methods --- -void ApplyPositionOffset(SDK::UUserWidget* Widget, float offset, SDK::FVector2D Alignment) { - if (!Widget) return; - if (Widget->Slot && Widget->Slot->IsA(SDK::UCanvasPanelSlot::StaticClass())) { - auto* canvasSlot = static_cast(Widget->Slot); - - canvasSlot->SetPosition(SDK::FVector2D(offset, 0)); - canvasSlot->SetAlignment(Alignment); - } -} - -void ApplyTransformOffset(SDK::UWidget* Widget, float OffsetX, float OffsetY) { - if (!Widget) return; - SDK::FWidgetTransform Transform = Widget->RenderTransform; - Transform.Translation.X = OffsetX; // Horizontal shifting - Transform.Translation.Y = OffsetY; // Vertical shifting (optional) - Widget->SetRenderTransform(Transform); -} - -float ApplyOffsetsSmart_Internal(SDK::UWidget* Widget, float Left, float Right, int Depth = 0, int MaxDepth = 1) { - if (!Widget) return 0; - static float leftApplied = 0; - // Apply if CanvasSlot - if (Widget->Slot && Widget->Slot->IsA(SDK::UCanvasPanelSlot::StaticClass())) { - if (Depth <= MaxDepth) { - auto* Slot = static_cast(Widget->Slot); - - SDK::FMargin Offsets = Slot->GetOffsets(); - SDK::FAnchors Anchors = Slot->GetAnchors(); - - float MinX = Anchors.Minimum.X; - float MaxX = Anchors.Maximum.X; - #ifdef MY_VERBOSE_LOGS - std::string indent(Depth * 2, ' '); // 2 espaces par niveau - if (g_logger) g_logger->debug("{}CanvasPanelSlot: {} {} - Slot: {} {} - Offets: {} {} {} {} - Anchors: {} {} {} {}",indent, - Widget->GetName(), Widget->Class->GetName(), - Slot->GetName(), Slot->Class->GetName(), - Offsets.Left, Offsets.Top, Offsets.Right, Offsets.Bottom, - Anchors.Minimum.X, Anchors.Minimum.Y, Anchors.Maximum.X, Anchors.Maximum.Y); - #endif - if (MinX == 0.f && MaxX == 1.f) return 0; // Ignore stretch - if (MinX == 0.5f && MaxX == 0.5f) return 0; // Ignore centered - - if (MinX == 0.f && MaxX == 0.f) // Modify only pure left - leftApplied = Offsets.Left = Left; - else if (MinX == 1.f && MaxX == 1.f) // Modify only pure right - Offsets.Left = -Right; - - Slot->SetOffsets(Offsets); - } - } - - // Stop to max depth - if (Depth >= MaxDepth) return leftApplied; - - // Browse the children - if (Widget->IsA(SDK::UPanelWidget::StaticClass())) { - auto* Panel = static_cast(Widget); - - for (int i = 0; i < Panel->GetChildrenCount(); ++i) - ApplyOffsetsSmart_Internal(Panel->GetChildAt(i), Left, Right, Depth + 1, MaxDepth); - } - - if (Widget->IsA(SDK::UUserWidget::StaticClass())) { - auto* UW = static_cast(Widget); - - if (UW->WidgetTree && UW->WidgetTree->RootWidget) - ApplyOffsetsSmart_Internal(UW->WidgetTree->RootWidget, Left, Right, Depth + 1, MaxDepth); - } - return leftApplied; -} - -float ApplyOffsetsSmart(SDK::UWidget* Widget, float Left, float Right, int MaxDepth) { - float leftApplied = ApplyOffsetsSmart_Internal(Widget, Left, Right, 0, MaxDepth); - return leftApplied; -} - -static void ApplyOffsetsRecursive_Internal(SDK::UWidget* Widget, float Left, float Right, - const std::vector& ExcludeObjects, const std::vector& ExcludeClass, - int CurrentDepth, int MaxDepth) { - if (!Widget || CurrentDepth > MaxDepth) return; - - // Apply offsets according to Slot type - for (const auto& ExcludeObject : ExcludeObjects) { - if (ExcludeObject == Widget) return; - } - - std::string widgetName; - std::string className; - - widgetName = Widget->GetName(); - if (Widget->Class) className = Widget->Class->GetName(); - for (const auto& pattern : ExcludeClass) { - if (widgetName.find(pattern) != std::string::npos || className.find(pattern) != std::string::npos) - return; - } - - if (Widget->Slot) { - if (Widget->Slot->IsA(SDK::UCanvasPanelSlot::StaticClass())) { - auto* Slot = static_cast(Widget->Slot); - SDK::FMargin Offsets = Slot->GetOffsets(); - #ifdef MY_VERBOSE_LOGS - SDK::FAnchors anchors = Slot->GetAnchors(); - if (g_logger) g_logger->debug("CanvasPanelSlot: {} {} - Slot: {} {} - Offets: {} {} {} {} - Anchors: {} {} {} {}", \ - Widget->GetName(), Widget->Class->GetName(), \ - Slot->GetName(), Slot->Class->GetName(), \ - Offsets.Left, Offsets.Top, Offsets.Right, Offsets.Bottom, \ - anchors.Minimum.X, anchors.Minimum.Y, anchors.Maximum.X, anchors.Maximum.Y); - #endif - Offsets.Left = Left; - Offsets.Right = Right; - Slot->SetOffsets(Offsets); - } - else if (Widget->Slot->IsA(SDK::UVerticalBoxSlot::StaticClass())) { - auto* Slot = static_cast(Widget->Slot); - SDK::FMargin Margin = Slot->Padding; - #ifdef MY_VERBOSE_LOGS - if (g_logger) g_logger->debug("VerticalBox Slot: {} {} - Slot: {} {} - Margins: {} {} {} {}", \ - Widget->GetName(), Widget->Class->GetName(), \ - Slot->GetName(), Slot->Class->GetName(), \ - Margin.Left, Margin.Top, Margin.Right, Margin.Bottom); - #endif - Margin.Left = Left; - Margin.Right = Right; - Slot->SetPadding(Margin); - } - } - // Go deeper in children if we got a Panel - if (Widget->IsA(SDK::UPanelWidget::StaticClass()) && CurrentDepth < MaxDepth) { - auto* Panel = static_cast(Widget); - int childrenCount = Panel->GetChildrenCount(); - for (int i = 0; i < childrenCount; ++i) { - ApplyOffsetsRecursive_Internal(Panel->GetChildAt(i), Left, Right, ExcludeObjects, ExcludeClass, CurrentDepth + 1, MaxDepth); - } - } - // Go deeper if the widget is an UserWidget - if (Widget->IsA(SDK::UUserWidget::StaticClass())) { - auto* ChildWidget = static_cast(Widget); - if (ChildWidget->WidgetTree && ChildWidget->WidgetTree->RootWidget) { - ApplyOffsetsRecursive_Internal(ChildWidget->WidgetTree->RootWidget, Left, Right, ExcludeObjects, ExcludeClass, CurrentDepth + 1, MaxDepth); - } - } -} - -void ApplyOffsetsRecursive(SDK::UWidget* Widget, float Left, float Right, - const std::vector& ExcludeObjects, const std::vector& ExcludeClass, int MaxDepth) { - ApplyOffsetsRecursive_Internal(Widget, Left, Right, ExcludeObjects, ExcludeClass, 0, MaxDepth); -} - -static void ApplyOverlayOffsetRecursive_Internal(SDK::UWidget* Widget, float left, float right, SDK::EHorizontalAlignment alignment, - const std::vector& ExcludeNames, int CurrentDepth, int MaxDepth) { - if (!Widget || CurrentDepth > MaxDepth) return; - - auto IsExcluded = [&](SDK::UWidget* widget) -> bool { - for (const auto& name : ExcludeNames) { - if (widget->GetName().contains(name)) - return true; - } - return false; - }; - - auto AdjustOverlaySlot = [&](SDK::UOverlaySlot* Slot) { - if (!Slot || IsExcluded(Widget)) return; - - SDK::FMargin Padding = Slot->Padding; - - if (Slot->HorizontalAlignment == alignment) { - Padding.Left = left; - Padding.Right = right; - } - Slot->SetPadding(Padding); - }; - - if (Widget->Slot && Widget->Slot->IsA(SDK::UOverlaySlot::StaticClass())) - AdjustOverlaySlot((SDK::UOverlaySlot*)Widget->Slot); - - if (Widget->IsA(SDK::UPanelWidget::StaticClass()) && CurrentDepth < MaxDepth) { - SDK::UPanelWidget* Panel = (SDK::UPanelWidget*)Widget; - int childrenCount = Panel->GetChildrenCount(); - for (int i = 0; i < childrenCount; ++i) { - ApplyOverlayOffsetRecursive_Internal(Panel->GetChildAt(i), left, right, alignment, ExcludeNames, CurrentDepth + 1, MaxDepth); - } - } -} - -void ApplyOverlayOffsetRecursive(SDK::UWidget* Widget, float left, float right, SDK::EHorizontalAlignment alignment, - const std::vector& ExcludeNames, int MaxDepth) { - ApplyOverlayOffsetRecursive_Internal(Widget, left, right, alignment, ExcludeNames, 0, MaxDepth); -} - -// -- Tracking && dumping widgets for debugging -- -void FindAndApplyCanvasRecursive(SDK::UWidget* widget, float offset, int MaxDepth, int currentDepth) { - if (!widget || currentDepth > MaxDepth) return; - - // Applying straight if it's a CanvasPanel - if (widget->IsA(SDK::UCanvasPanel::StaticClass())) { - ApplyOffsetsRecursive(widget, offset, offset); - } - - // We go deeper if - if (widget->IsA(SDK::UPanelWidget::StaticClass())) { - auto* panel = static_cast(widget); - int childrenCount = panel->GetChildrenCount(); - for (int i = 0; i < childrenCount; ++i) { - FindAndApplyCanvasRecursive(panel->GetChildAt(i), offset, MaxDepth, currentDepth + 1); - } - } -} - -void TrackWidgetConstruct(SDK::UUserWidget* widget) { - if (!widget || !widget->Class) return; - - std::string className = widget->Class->GetName(); - auto& info = g_WidgetTracker[className]; - - info.ClassName = className; - info.ConstructCount++; - - if (info.ConstructCount == 1) - info.FirstSeen = std::chrono::steady_clock::now(); - - if (widget->IsInViewport()) - info.WasInViewport = true; - - if (widget->Outer && widget->Outer->Class) - info.OuterClass = widget->Outer->Class->GetName(); - - if (widget->WidgetTree && widget->WidgetTree->RootWidget) { - auto* root = widget->WidgetTree->RootWidget; - if (root && root->Class) - info.RootWidgetClass = root->Class->GetName(); - } -} - -void TrackWidgetDestruct(SDK::UUserWidget* widget) { - if (!widget || !widget->Class) return; - - std::string className = widget->Class->GetName(); - - if (g_WidgetTracker.contains(className)) - g_WidgetTracker[className].DestructCount++; -} - -static std::string ClassifyWidget(const WidgetTrackInfo& info) { - bool persistent = info.ConstructCount > info.DestructCount; - - if (info.WasInViewport && persistent && info.OuterClass.find("PlayerController") != std::string::npos) - return "HUD Candidate"; - - if (info.WasInViewport && (info.ClassName.find("Menu") != std::string::npos)) - return "Menu UI"; - - if (info.WasInViewport && (info.ClassName.find("Settings") != std::string::npos)) - return "Settings UI"; - - if (info.WasInViewport && (info.ClassName.find("Save") != std::string::npos || - info.ClassName.find("Load") != std::string::npos)) - return "Save/Load UI"; - - if (!persistent) - return "Temporary Widget"; - - return "Unclassified"; -} - -void DumpUIAnalysis(std::shared_ptr logger) { - if (!logger) return; - - logger->info("========== UI ANALYSIS =========="); - - for (auto& [name, info] : g_WidgetTracker) { - std::string type = ClassifyWidget(info); - bool persistent = info.ConstructCount > info.DestructCount; - - logger->info("Class: {}", name); - logger->info(" Type : {}", type); - logger->info(" Root Type : {}", info.RootWidgetClass.empty() ? "Unknown" : info.RootWidgetClass); - logger->info(" Construct : {}", info.ConstructCount); - logger->info(" Destruct : {}", info.DestructCount); - logger->info(" Persistent : {}", persistent ? "Yes" : "No"); - logger->info(" InViewport : {}", info.WasInViewport ? "Yes" : "No"); - logger->info(" Outer : {}", info.OuterClass.empty() ? "Unknown" : info.OuterClass); - logger->info(" "); - } - - logger->info("================================="); -} - -void ClearWidgetTracking() { - g_WidgetTracker.clear(); -} - -void DumpWidgetRecursive(SDK::UWidget* Widget, int Depth, int MaxDepth) { - if (!Widget || Depth > MaxDepth) return; - - std::string indent(Depth * 2, ' '); - std::string className = Widget->Class ? Widget->Class->GetName() : "UnknownClass"; - std::string widgetName = Widget->GetName(); - if (g_logger) - g_logger->debug("{}Widget: {} [{}]", indent, widgetName, className); - - // Slot info si disponible - if (Widget->Slot) { - std::string slotClass = Widget->Slot->Class ? Widget->Slot->Class->GetName() : "UnknownSlot"; - if (g_logger) - g_logger->debug("{} Slot class: {}", indent, slotClass); - } - - // Descendre dans les enfants si c'est un panel et qu'on est encore sous MaxDepth - if (Depth < MaxDepth) { - if (Widget->IsA(SDK::UPanelWidget::StaticClass())) { - auto* panel = static_cast(Widget); - int count = panel->GetChildrenCount(); - for (int i = 0; i < count; ++i) { - DumpWidgetRecursive(panel->GetChildAt(i), Depth + 1, MaxDepth); - } - } - - if (Widget->IsA(SDK::UUserWidget::StaticClass())) { - auto* userWidget = static_cast(Widget); - if (userWidget->WidgetTree && userWidget->WidgetTree->RootWidget) { - DumpWidgetRecursive(userWidget->WidgetTree->RootWidget, Depth + 1, MaxDepth); - } - } - } } \ No newline at end of file