UITool = UITool or {} if not UE_SERVER then --- 设置 ---@param widget UUserWidget ---@param offset float function UITool.SetWidgetToRightBorder(widget, offset) if not widget then return end local slot = WidgetLayoutLibrary.SlotAsCanvasSlot(widget) slot:SetAnchors({ Minimum = { X = 1, Y = 0 }, Maximum = { X = 1, Y = 0 } }) slot:SetAlignment({ X = 1, Y = 0 }) local offsets = slot:GetOffsets() slot:SetOffsets({ Left = offset, Right = offsets.Right, Bottom = offsets.Bottom, Top = offsets.Top }) end --- 为防止被清除做出的全局处理 function UITool.BindButtonClicked(TargetButton, Func, Obj) TargetButton.OnClicked:Add(Func, Obj) end --- 直接绑定按键点击打开WidgetManager的页面 function UITool.ButtonOnClickShowPanel(TargetButton, UIType) TargetButton.OnClicked:Add(function() if WidgetManager:IsVisiblePanel(UIType) then WidgetManager:ClosePanel(UIType); else WidgetManager:ShowPanel(UIType, false); end end) end ---@param InVec table 这是一个3-4个元素的数组 function UITool.MakeSlateColor(InVec) return { SpecifiedColor = VectorHelper.ArrToColor(InVec), ColorUseRule = 0 } end --- 绑定UI文本 function UITool.TextBlockBindingPropertyText(TargetTextBlock, Func, Obj) TargetTextBlock:BindingProperty("Text", Func, Obj) end function UITool.TextBlockBindingProperty(TargetWidget, PropertyName, Func, Obj) TargetWidget:BindingProperty(PropertyName, Func, Obj) end function UITool.SetBrushFromTexture(InImage, InIcon) InImage:SetBrushFromTexture(InIcon); end UITool.CachedImage = {}; ---@field IsSucceedFun fun(Texture:UTexture2DDynamic) ---@field FailedFun fun() function UITool.DownloadImage(ImageURL, IsSucceedFun, FailedFun) if ImageURL == nil or string.len(ImageURL) == 0 then return ; end if UITool.CachedImage[ImageURL] then IsSucceedFun(UITool.CachedImage[ImageURL]); return ; end local Func = function(Texture) UITool.CachedImage[ImageURL] = Texture; IsSucceedFun(Texture); end local ResHandle = AsyncTaskDownloadImage.DownloadImage(ImageURL) ResHandle.OnSuccess:Add(Func) if FailedFun ~= nil and type(FailedFun) == 'function' then ResHandle.OnFail:Add(FailedFun); end end --- 异步加载图片,成功后设置到UIImageObj,若该UIImageObj重复加载,则会判断设置时间决定是否设置 ---@param UIImageObj UImage ---@param ResPath string function UITool.AsyncLoadTextureToUIImage(UIImageObj, ResPath) if UITool.ImageObjUpdateTime == nil then -- {Obj = float, ...} UITool.ImageObjUpdateTime = {} end local BeginLoadTime = KismetSystemLibrary.GetGameTimeInSeconds(UGCGameSystem.GameState) local CallBackFunc = function(TextureObj) if UE.IsValid(TextureObj) then if UITool.ImageObjUpdateTime[UIImageObj] == nil or UITool.ImageObjUpdateTime[UIImageObj] < BeginLoadTime then UITool.ImageObjUpdateTime[UIImageObj] = BeginLoadTime UIImageObj:SetBrushFromTexture(TextureObj); end end end FileTool.AsyncLoadAsset(ResPath, CallBackFunc, nil, true) end function UITool.ButtonOnClickShowPanel(TargetButton, UIType, IsShow) TargetButton.OnClicked:Add(function() if IsShow then WidgetManager:ShowPanel(UIType, false) else WidgetManager:ClosePanel(UIType) end end) end --- 添加一个 继承自 PanelWidget 的控件的子类 ---@param InBox UPanelWidget ---@param InClas UClass* ---@param InOwner UObject* ---@return UUserWidget* function UITool.AddWidgetItem(InBox, InClas, InOwner) if InOwner == nil then InOwner = UGCGameSystem.GameState end local Item = UserWidget.NewWidgetObjectBP(InOwner, InClas); InBox:AddChild(Item); return Item; end -- PanelWidget 中从后面逐个隐藏 Item 的操作 function UITool.HideWidgetItem(InBox, InCount) if InBox == nil then return ; end local Count = InBox:GetChildrenCount(); if InCount == nil or InCount > Count then InCount = Count; end -- 从后往前逐个隐藏 for i = 1, InCount do local Item = InBox:GetChildAt(Count - i); Item:SetVisibility(ESlateVisibility.Collapsed); end end function UITool.SliderOnValueChanged(Slider, Func, Obj) Slider.OnValueChanged:Add(Func, Obj) end UITool.ClearSpectateButtonTimer = nil; -- 将观战页面退出按钮进行隐藏(否则点击到了直接退出就麻烦了) function UITool.HideSpectate(InPC) if not UE.IsValid(InPC) then return ; end self.ClearSpectateButtonTimer = UGCEventSystem.SetTimerLoop(InPC, function() InPC:CastUIMsg("UIMsg_HideQuitWatch", ""); UGCEventSystem.SetTimer(InPC, function() if UE.IsValid(self.ClearSpectateButtonTimer) then UGCEventSystem.StopTimer(self.ClearSpectateButtonTimer); end end, 10) end, 0.3) end --- 在滚动视图中的按钮可以被 handle 的方法 function UITool.EnableButtonScroll(InButton) InButton:SetTouchMethod(EButtonTouchMethod.PreciseTap) end function UITool.ButtonSetEnable(InButton, IsEnable) InButton:SetIsEnabled(IsEnable); end ---@param Button UButton function UITool.BindButtonToShare(Button) Button.OnClicked:Add(function() UGCWidgetManagerSystem.Share(); end); end --- 绑定按钮到添加朋友 ---@param Button UNewButton ---@param InPlayerKey PlayerKey function UITool.BindButtonAddFriend(Button, InPlayerKey) if LocalPlayerKey ~= InPlayerKey then local UID = UE.GetPlayerUID(InPlayerKey) if UID then UITool.BindButtonClicked(Button, function() UGCGameSystem.AddFriend(UID); end) end Button:SetVisibility(ESlateVisibility.Visible); else Button:SetVisibility(ESlateVisibility.Hidden); end end function UITool.GetChildrenCount(InBox) return InBox:GetChildrenCount(); end function UITool.GetChildAt(InBox, InIndex) return InBox:GetChildAt(InIndex); end --- 遍历所有子项 ---@param InBox UPanelWidget ---@param InFunc fun(index: int32, Widget: UUserWidget) function UITool.ForeachAllChildren(InBox, InFunc) if type(InFunc) ~= 'function' then return ; end for i = 1, InBox:GetChildrenCount() do local Item = InBox:GetChildAt(i - 1); InFunc(i, Item); end end ---@param InBox UPanelWidget ---@param InFunc fun(Widget: UUserWidget): boolean ---@return UUserWidget function UITool.FindItem(InBox, InFunc) for i = 1, InBox:GetChildrenCount() do local Item = InBox:GetChildAt(i - 1); if InFunc(Item) then return Item; end end return nil; end ---@return MainControlBaseUI_C function UITool.MainControlPanel() ---@type MainControlPanelTochButton_C local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); ---@type MainControlBaseUI_C local MainControlBaseUI = MainControlPanel.MainControlBaseUI; return MainControlPanel; end ---@return MainControlPanelTochButton_C function UITool.MainControlBaseUI() local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); return MainControlPanel.MainControlBaseUI; end --- 隐藏所有子项 ---@param InBox UPanelWidget function UITool.HideAllChildren(InBox) UITool.ForeachAllChildren(InBox, function(index, Widget) Widget:SetVisibility(ESlateVisibility.Collapsed); end) end function UITool.SetItemInfo(InBox, FuncName, Info) UITool.ForeachAllChildren(InBox, function(index, Widget) if Info[index] then table.func(Widget, FuncName, index, Info[index]); Widget:SetVisibility(ESlateVisibility.SelfHitTestInvisible); else Widget:SetVisibility(ESlateVisibility.Collapsed); end end) end --- 自动适配数量 ---@param InBox UPanelWidget ---@param InCount int32 ---@param InClass UClass ---@param Func fun(Widget:UUserWidget, Index:int32) function UITool.AdaptChildren(InBox, InCount, InClass, Func, ...) local Count = UITool.GetChildrenCount(InBox) local TargetCount = InCount - Count; if TargetCount == 0 then elseif TargetCount < 0 then -- 说明当前多了 for i = Count, InCount + 1, -1 do local Item = InBox:GetChildAt(i - 1); Item:SetVisibility(ESlateVisibility.Collapsed); end else for i = Count + 1, InCount, 1 do UITool.AddWidgetItem(InBox, InClass, InBox); end end local Params = { ... }; UITool.ForeachAllChildren(InBox, function(index, Widget) if Func and type(Func) == 'function' then Func(Widget, index, table.unpackTable(Params)); end end) end --- 隐藏起来观战退出按钮,直接调用即可 function UITool.HideReturnToLobbyButton() UGCLogSystem.Log("[WidgetManager.HideReturnToLobbyButton] 执行") local InGameMgr = GameFrontendHUD:GetLogicManagerByName("ingame"); local WatchGameUIObj_InGameMgr = GameBusinessManager.GetWidgetFromName(InGameMgr, "WatchGame_UIBP_C"); if WatchGameUIObj_InGameMgr then WatchGameUIObj_InGameMgr.Button_BackToLobby:SetVisibility(ESlateVisibility.Collapsed); end local BattleResultMgr = GameFrontendHUD:GetLogicManagerByName("bp_battleresult"); local ObserveMgr = GameFrontendHUD:GetLogicManagerByName("observe"); local ObserveMgrInst = GameBusinessManager.GetLuaObject(ObserveMgr); UGCLogSystem.Log("[WidgetManager.HideReturnToLobbyButton] ObserveMgrInst = %s", tostring(ObserveMgrInst)) local WatchGameUI = GetUIObject(bp_battleresult, "WatchGame_UIBP_C"); if WatchGameUI then UGCLogSystem.Log("[WidgetManager.HideReturnToLobbyButton] 隐藏起来") WatchGameUI.Button_BackToLobby:SetVisibility(ESlateVisibility.Collapsed); WatchGameUI.GridPanel_1:SetVisibility(ESlateVisibility.Hidden); end local WatchGame_UIBPG = UGCWidgetManagerSystem.GetGlobalOBUI(); if WatchGame_UIBPG then WatchGame_UIBPG.Button_BackToLobby:SetVisibility(ESlateVisibility.Collapsed); end for k, v in pairs(GameFrontendHUD.LogicManagerList) do local UI = GameBusinessManager.GetWidgetFromName(v, "WatchGame_UIBP"); if UI ~= nil then UGCLogSystem.Log("[Watch] WatchGame_UIBP in Manager ====== :%s", UE.GetName(v)); end end local GameBusinessManagerInst = GameBusinessManager.GetLuaObject(BattleResultMgr); UGCLogSystem.Log("[Watch] GameBusinessManagerInst ====%s", tostring(GameBusinessManagerInst)); if GameBusinessManagerInst then UGCLogSystem.LogTree("[Watch] GameBusinessManagerInst", GameBusinessManagerInst); end end function UITool.HidePickUpPanel() ---@type MainControlPanelTochButton_C local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); ---@type MainControlBaseUI_C local MainControlBaseUI = MainControlPanel.MainControlBaseUI; local BackPackPickUpPanel = MainControlBaseUI.BackPackPickUpPanel_BP_0 local PickUpListPanel = BackPackPickUpPanel.PickUpListPanel_BP local CustomizePickUpPanel_BP = PickUpListPanel.CustomizePickUpPanel_BP; local Canvas_PickUp = CustomizePickUpPanel_BP.Canvas_PickUp UGCLogSystem.Log("[UITool.HidePickUpPanel] 执行") Canvas_PickUp:SetVisibility(ESlateVisibility.Hidden); end ---@param Fmt string function UITool.ShowTips(Fmt, ...) UGCWidgetManagerSystem.ShowTipsUI(string.format(Fmt, ...)); end function UITool.ShowTips1(ShowTime, Color, fmt, ...) WidgetManager:ShowPanel(WidgetConfig.EUIType.Tips1, false, ShowTime, Color, fmt, ...); end function UITool.CreateWidget(Class, InOwner) if InOwner == nil then InOwner = UGCGameSystem.GameState end local Item = UserWidget.NewWidgetObjectBP(InOwner, Class); return Item; end ---@param ui UWidget ---@param show bool function UITool.ShowUI(show, ...) local Params = { ... } if table.isEmpty(Params) then return end for i, ui in pairs(Params) do ui:SetVisibility(show and ESlateVisibility.SelfHitTestInvisible or ESlateVisibility.Collapsed); end end --- 显示距离游戏结束还有多长时间 function UITool.ShowGameEndCountDown(fmt, ...) ---@type MainControlPanelTochButton_C local MainControlPanel = GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); local MainControlBaseUI = MainControlPanel.MainControlBaseUI; MainControlBaseUI.CanvasPanel_TimeDown:SetVisibility(ESlateVisibility.SelfHitTestInvisible) MainControlBaseUI.TextBlock_TimeDown:SetText(string.format(fmt, ...)); UGCEventSystem.SetTimer(UGCGameSystem.GameState, function() MainControlBaseUI.CanvasPanel_TimeDown:SetVisibility(ESlateVisibility.Collapsed) end, 2.5); end ---@param Widget UWidget ---@return FVector2D function UITool.GetChildWidgetSize(Widget) local WidgetGeo = Widget:GetCachedGeometry(); return SlateBlueprintLibrary.GetLocalSize(WidgetGeo); end ---@param Widget UWidget 子控件 ---@param Parent UUserWidget 父控件 ---@return FVector2D function UITool.GetChildLeftUpPos(Widget, Parent) UGCLogSystem.Log("[UITool.GetChildLeftUpPos] 执行") local WidgetGeo = Widget:GetCachedGeometry(); local ParentGeo = Parent:GetCachedGeometry(); local WidgetAbsoPos = SlateBlueprintLibrary.GetAbsolutePosition(WidgetGeo); --return WidgetAbsoPos; return SlateBlueprintLibrary.AbsoluteToLocal(ParentGeo, WidgetAbsoPos); end --- 获取中心点坐标 ---@param Widget UWidget 子控件 ---@param Parent UUserWidget 父控件 ---@return FVector2D function UITool.GetChildCenterPos(Widget, Parent) local WidgetGeo = Widget:GetCachedGeometry(); local ParentGeo = Parent:GetCachedGeometry(); local WidgetSize = UITool.GetChildWidgetSize(Widget) local WidgetAbsoPos = SlateBlueprintLibrary.GetAbsolutePosition(WidgetGeo); return VectorHelper.Add2D(SlateBlueprintLibrary.AbsoluteToLocal(Parent, WidgetAbsoPos), VectorHelper.MulNumber(WidgetSize, 0.5)); end --- 切换是否显示 ---@param InWidget UWidget function UITool.TurnVisible(InWidget) if InWidget:IsVisible() then InWidget:SetVisibility(ESlateVisibility.Collapsed); else InWidget:SetVisibility(ESlateVisibility.SelfHitTestInvisible); end end ---@return MainControlPanelTochButton_C function UITool.GetMainControlPanel() return GameBusinessManager.GetWidgetFromName(ingame, "MainControlPanelTochButton_C"); end function UITool.OpenSettings() local MainControlPanel = UITool.GetMainControlPanel(); for i = 1, 2 do MainControlPanel.MainControlBaseUI:OpenSettingPanel(); end end end