---@class W_CenterScrollBox_C:UUserWidget ---@field ScrollBox_Target UScrollBox --Edit Below-- ---@type W_CenterScrollBox_C local W_CenterScrollBox = { bInitDoOnce = false; bTickEnable = false; ---@param ScrollSizeY float 滚动框高度 ScrollSizeY = 0.; ---@param HideWidgetNum int 计算后需要的高度与Item相同的隐藏Widget的个数 HideWidgetNum = 0; ---@param InitScroll float 计算后所得的初始中心滚动位置 InitScroll = 0.; ---@param ItemSizeY float Item的高度,需在外部写死 ItemSizeY = 100; ---@param bSelecting bool 是否正在滚动选择 bSelecting = false; ---@param ScrollStopWaitTime float 延迟触发暂停滚动,自动滚动到就近的Item中心位置 ScrollStopWaitTime = 0.2; ---@param ScrollStopWaitHandle TimerHandle 暂停滚动的Handle ScrollStopWaitHandle = nil; ---@param TargetScroll float 目标滚动的位置 TargetScroll = 0.; ---@param ScrollInterpSpeed float 滚动结束自动过渡时的速度 ScrollInterpSpeed = 10.; ---@param SelectIndex int 当前选择中的Index SelectIndex = -1; ---@param ItemClass UUserWidget ItemClass = nil; ---@param NumItem int Item个数 NumItem = 0; ---@param ItemInitFuncName string Item初始化函数名 ItemInitFuncName = nil; ---@param ItemSelectFuncName string Item被选择函数名 ItemSelectFuncName = nil; ---@param ClickSelectBtnName string Item点击选中Button名 ClickSelectBtnName = nil; }; function W_CenterScrollBox:Construct() --Test --UGCEventSystem.SetTimer( -- self, -- function() -- self:Init( -- UE.LoadClass(UGCGameSystem.GetUGCResourcesFullPath('Asset/UI/W_SelectWeapon_Item2.W_SelectWeapon_Item2_C')), -- 130., -- "InitSelectInfo", -- "SetSelect" -- ) -- local ItemParams = {} -- for k, WeaponTypeInfo in pairs(Tables.WeaponAndProps_V2.WeaponTypeInfos) do -- UGCLogSystem.Log("[W_CenterScrollBox_Construct] k:%d , WeaponType:%s", k, WeaponTypeInfo.Name) -- local ItemParam = {Enum.SelectWeapon.SelectWeaponType, false, WeaponTypeInfo.Icon, WeaponTypeInfo.Name, k} -- ItemParams[#ItemParams + 1] = ItemParam -- end -- self:UpdateItemInfo(ItemParams) -- -- end, -- 2. --) -- Tick 函数判断是否触发 UGCEventSystem.SetTimer( self, function() if self.bTickEnable == false then -- 踏马的Tick不调 local LastTime = KismetSystemLibrary.GetGameTimeInSeconds(self) UGCEventSystem.SetTimerLoop( self, function() local NowTime = KismetSystemLibrary.GetGameTimeInSeconds(self) self:Tick(nil, NowTime - LastTime) LastTime = NowTime end, 0.01 ) end end, 0.1 ) end function W_CenterScrollBox:Tick(MyGeometry, InDeltaTime) self.bTickEnable = true -- UGCLogSystem.Log("[W_CenterScrollBox_Tick]") if self.bSelecting == false then -- UGCLogSystem.Log("[W_CenterScrollBox_Tick] Begin") local NowOffset = self.ScrollBox_Target:GetScrollOffset() local SetOffset = KismetMathLibrary.FInterpTo(NowOffset, self.TargetScroll, InDeltaTime, self.ScrollInterpSpeed) self.ScrollBox_Target:SetScrollOffset(SetOffset) -- UGCLogSystem.Log("[W_CenterScrollBox_Tick] Finish") end end -- function W_CenterScrollBox:Destruct() -- end function W_CenterScrollBox:GetScrollBoxSizeY() local CanvasSlot = WidgetLayoutLibrary.SlotAsCanvasSlot(self) return CanvasSlot:GetSize().Y end --- 初始化函数 ---@param ItemClass UUserWidget ---@param ItemSizeY float Item的高度 ---@param ItemInitFuncName string Item初始化函数名 ---@param ItemSelectFuncName string Item设置选择函数名 ---@param ClickSelectBtnName string Item点击选中Button名 function W_CenterScrollBox:Init(ItemClass, ItemSizeY, ItemInitFuncName, ItemSelectFuncName, ClickSelectBtnName) self.ItemClass = ItemClass self.ItemSizeY = ItemSizeY self.ItemInitFuncName = ItemInitFuncName self.ItemSelectFuncName = ItemSelectFuncName self.ClickSelectBtnName = ClickSelectBtnName self.ScrollSizeY = self:GetScrollBoxSizeY() UGCLogSystem.Log("[W_CenterScrollBox_Init] ScrollSizeY: %f", self.ScrollSizeY) -- SetInitScroll --self.InitScroll = self.ItemSizeY * (0.5 + math.ceil((self.ScrollSizeY / 2. - self.ItemSizeY / 2.) / self.ItemSizeY)) - self.ScrollSizeY / 2. --UGCLogSystem.Log("[W_CenterScrollBox_Init] InitScroll: %f", self.InitScroll) -- SetHideWidgetNum -- self.HideWidgetNum = math.ceil(self.InitScroll / self.ItemSizeY + 0.5) self.HideWidgetNum = math.ceil((self.ScrollSizeY - self.ItemSizeY) / 2 / self.ItemSizeY) UGCLogSystem.Log("[W_CenterScrollBox_Init] HideWidgetNum: %d", self.HideWidgetNum) self.InitScroll = self.HideWidgetNum * self.ItemSizeY + self.ItemSizeY / 2 - self.ScrollSizeY / 2. UGCLogSystem.Log("[W_CenterScrollBox_Init] InitScroll: %f", self.InitScroll) self.ScrollBox_Target.OnUserScrolled:Add(self.BoxScroll, self) end --- 绑定滚动到新的Item委托 ---@param Func function Item:UUserWidget*, SelectIndex:int function W_CenterScrollBox:BindUpdateSelectItem(Func, Obj) self.UpdateSelectDelegation = {Func = Func, Obj = Obj} end function W_CenterScrollBox:ExeUpdateSelectItemDelegation(Item) if self.UpdateSelectDelegation then if self.UpdateSelectDelegation.Obj then self.UpdateSelectDelegation.Func(self.UpdateSelectDelegation.Obj, Item, self.SelectIndex) else self.UpdateSelectDelegation.Func(Item, self.SelectIndex) end end end function W_CenterScrollBox:BoxScroll() self.bSelecting = true if self.ScrollStopWaitHandle ~= nil then UGCEventSystem.StopTimer(self.ScrollStopWaitHandle) self.ScrollStopWaitHandle = nil end self:UpdateSelect() self.ScrollStopWaitHandle = UGCEventSystem.SetTimer( self, function () self:UpdateSelect() self.bSelecting = false self.ScrollStopWaitHandle = nil end, self.ScrollStopWaitTime ) end function W_CenterScrollBox:GetItemIndex(Item) for i = 0, self.ScrollBox_Target:GetChildrenCount() - 1 do if self.ScrollBox_Target:GetChildAt(i) == Item then return i - self.HideWidgetNum end end end --- 更新滚动表数据 ---@param ItemInitParams table Item初始化的参数 function W_CenterScrollBox:UpdateItemInfo(ItemInitParams) self.NumItem = #ItemInitParams while self.ScrollBox_Target:GetChildrenCount() < (self.NumItem + self.HideWidgetNum * 2) do local ItemInst = UserWidget.NewWidgetObjectBP(UGCSystemLibrary.GetLocalPlayerController(), self.ItemClass) self.ScrollBox_Target:AddChild(ItemInst) if ItemInst[self.ClickSelectBtnName] then ItemInst[self.ClickSelectBtnName].OnClicked:Add(function() self:UpdateSelect(self:GetItemIndex(ItemInst)) end) end end UGCLogSystem.Log("[W_CenterScrollBox_UpdateItemInfo] NumItem:%d , ChildrenCount:%d", self.NumItem, self.ScrollBox_Target:GetChildrenCount()) for i = 0, self.ScrollBox_Target:GetChildrenCount() - 1 do local TempItem = self.ScrollBox_Target:GetChildAt(i) if i >= (self.NumItem + self.HideWidgetNum * 2) then TempItem:SetVisibility(ESlateVisibility.Collapsed) elseif (i < self.HideWidgetNum) or (i >= (self.NumItem + self.HideWidgetNum))then TempItem:SetVisibility(ESlateVisibility.Hidden) else TempItem:SetVisibility(ESlateVisibility.SelfHitTestInvisible) TempItem[self.ItemInitFuncName](TempItem, table.unpack(ItemInitParams[i + 1 - self.HideWidgetNum])) end end self:UpdateSelect(0) UGCLogSystem.Log("[W_CenterScrollBox_UpdateItemInfo] Finish") end --- 获取Item function W_CenterScrollBox:GetScrollItem(Index) return self.ScrollBox_Target:GetChildAt(Index + self.HideWidgetNum) end --- 获取启用的Item数量 function W_CenterScrollBox:GetEnableItemNum() return self.NumItem end function W_CenterScrollBox:SetItemSelect(Index, IsSelect) if self.ItemSelectFuncName then local Item = self:GetScrollItem(Index) if Item then Item[self.ItemSelectFuncName](Item, IsSelect) end end end --- 滚动到中间 function W_CenterScrollBox:ScrollToMidItem() local ScrollNum = math.floor(self.NumItem / 2) - (self.NumItem % 2 == 0 and 1 or 0) self:UpdateSelect(ScrollNum) end --- 刷新滚动的位置 function W_CenterScrollBox:UpdateSelect(SelectIndex) -- GetTargetScorll local ScrollOffset = self.ScrollBox_Target:GetScrollOffset() local MustBeUpdated = false if SelectIndex == nil then SelectIndex = math.clamp(KismetMathLibrary.Round((ScrollOffset - self.InitScroll) / self.ItemSizeY), 0, self.NumItem - 1) else MustBeUpdated = true end local SelectItem = self:GetScrollItem(SelectIndex) UGCLogSystem.Log("[W_CenterScrollBox_UpdateSelect] SelectItem:%s", tostring(UE.IsValid(SelectItem))) -- SetTargetScroll self.TargetScroll = SelectIndex * self.ItemSizeY + self.InitScroll UGCLogSystem.Log("[W_CenterScrollBox_UpdateSelect] TargetScroll:%f ScrollOffset:%f", self.TargetScroll, ScrollOffset) UGCLogSystem.Log("[W_CenterScrollBox_UpdateSelect] SelectIndex:%d, self.SelectIndex:%d", SelectIndex, self.SelectIndex) if SelectItem and ((SelectIndex ~= self.SelectIndex) or MustBeUpdated) then -- 隐藏上次被选中的Item self:SetItemSelect(self.SelectIndex, false) self.SelectIndex = SelectIndex -- 显示现在选中的Item self:SetItemSelect(self.SelectIndex, true) self:ExeUpdateSelectItemDelegation(SelectItem) else UGCLogSystem.LogError("[W_CenterScrollBox_UpdateSelect] SelectItem is nil, SelectIndex:%d", SelectIndex) end end return W_CenterScrollBox;