265 lines
10 KiB
Lua
Raw Normal View History

2025-01-04 23:00:19 +08:00
---@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;