Files
Endfield-Data/LuaScripts/UI/Widgets/CharFormationList.lua
2025-12-02 20:37:18 +07:00

647 lines
18 KiB
Lua

local UIWidgetBase = require_ex('Common/Core/UIWidgetBase')
CharFormationList = HL.Class('CharFormationList', UIWidgetBase)
local ActionOnSetNaviTarget = CS.Beyond.Input.ActionOnSetNaviTarget
CharFormationList.info = HL.Field(HL.Table)
CharFormationList.m_selectNum = HL.Field(HL.Number) << -1
CharFormationList.m_mode = HL.Field(HL.Number) << -1
CharFormationList.m_charNum = HL.Field(HL.Number) << 0
CharFormationList.m_originSingleSelect = HL.Field(HL.Number) << 0
CharFormationList.curSingleSelect = HL.Field(HL.Number) << 0
CharFormationList.cell2Select = HL.Field(HL.Table)
CharFormationList.m_select2Cell = HL.Field(HL.Table)
CharFormationList.m_charItems = HL.Field(HL.Table)
CharFormationList.m_onCharListChanged = HL.Field(HL.Function)
CharFormationList.GetCell = HL.Field(HL.Function)
CharFormationList.m_clickFunc = HL.Field(HL.Function)
CharFormationList.m_updateFunc = HL.Field(HL.Function)
CharFormationList.m_ignoreDead = HL.Field(HL.Boolean) << false
CharFormationList.m_naviTargetInitialized = HL.Field(HL.Boolean) << false
CharFormationList._OnFirstTimeInit = HL.Override() << function(self)
self.view.sortNode:InitSortNode(UIConst.CHAR_FORMATION_LIST_SORT_OPTION, function(optData, isIncremental)
self:_OnSortChanged(optData, isIncremental)
end, nil, false)
self.GetCell = UIUtils.genCachedCellFunction(self.view.charScrollList)
self.view.charScrollList.onSelectedCell:AddListener(function(obj, csIndex)
local cellIndex = LuaIndex(csIndex)
if self.m_mode == UIConst.CharListMode.Single then
self:OnClickItem(cellIndex)
end
end)
self.view.charScrollList.getCurSelectedIndex = function()
return CSIndex(self.curSingleSelect)
end
self.view.charScrollList.onUpdateCell:AddListener(function(object, index)
self:OnUpdateCell(object, LuaIndex(index))
if self.m_updateFunc then
self.m_updateFunc(object, LuaIndex(index))
end
end)
self.view.charScrollList.onGraduallyShowFinish:AddListener(function()
if DeviceInfo.usingController then
local targetIndex = 1
if self.m_mode == UIConst.CharListMode.Single and self.curSingleSelect > 0 then
targetIndex = self.curSingleSelect
end
self.view.charScrollList:ScrollToIndex(targetIndex, true)
local cell = self:GetCellByIndex(targetIndex)
if cell then
UIUtils.setAsNaviTarget(cell.view.button)
end
end
end)
self.view.naviGroup.onSetLayerSelectedTarget:AddListener(function(selectable)
local cell = self.GetCell(selectable.gameObject)
InputManagerInst:SetBindingText(cell.view.button.hoverConfirmBindingId, cell.info.selectIndex and
Language.LUA_CHAR_FORMATION_CONTROLLER_OUT_TEAM or Language.LUA_CHAR_FORMATION_CONTROLLER_IN_TEAM)
end)
end
CharFormationList.InitCharFormationList = HL.Method(HL.Table, HL.Opt(HL.Function, HL.Boolean)) << function(self, info, onCharListChanged , ignoreDead)
self:_FirstTimeInit()
self.m_ignoreDead = ignoreDead == true
self:_InitData(info)
self.m_onCharListChanged = onCharListChanged
end
CharFormationList._InitData = HL.Method(HL.Table) << function(self, info)
self.info = info or {}
self.m_selectNum = info.selectNum or 1
if self.m_selectNum > 1 then
self.m_mode = UIConst.CharListMode.MultiSelect
else
self.m_mode = UIConst.CharListMode.Single
end
self.m_charNum = 0
self.cell2Select = {}
self.m_select2Cell = {}
self.m_charItems = {}
self.m_originSingleSelect = 0
self.curSingleSelect = 0
self.m_mode = info.mode or UIConst.CharListMode.MultiSelect
self.m_naviTargetInitialized = false
end
CharFormationList._GetCharIndex = HL.Method(HL.Any).Return(HL.Number) << function(self, charInstId)
for index = 1, #self.m_charItems do
local charItem = self.m_charItems[index]
if charItem.instId == charInstId then
return index
end
end
return -1;
end
CharFormationList._OnSortChanged = HL.Method(HL.Table, HL.Boolean) << function(self, optData, isIncremental)
if self.m_charItems then
local tmpTable = {}
local tmpSingleInstId = 0
local scrollToIndex = 1
if self.m_mode == UIConst.CharListMode.Single then
local cell = self:GetCellByIndex(self.curSingleSelect)
if cell then
tmpSingleInstId = cell.charInfo.instId
end
else
for selectIndex, cellIndex in pairs(self.m_select2Cell) do
local charItem = self.m_charItems[cellIndex]
local instId = charItem.instId
tmpTable[instId] = selectIndex
end
end
local keys = isIncremental and optData.keys or optData.reverseKeys
self:_SortData(keys, isIncremental)
self.m_select2Cell = {}
self.cell2Select = {}
for cellIndex, info in pairs(self.m_charItems) do
local cellInstId = info.instId
local selectIndex = tmpTable[cellInstId]
if selectIndex then
self.m_select2Cell[selectIndex] = cellIndex
self.cell2Select[cellIndex] = selectIndex
end
if tmpSingleInstId > 0 and tmpSingleInstId == cellInstId then
self.curSingleSelect = cellIndex
scrollToIndex = cellIndex
end
end
if DeviceInfo.usingController then
UIUtils.setAsNaviTarget(nil)
end
self:_RefreshCharList(scrollToIndex)
end
end
CharFormationList._SortData = HL.Method(HL.Table, HL.Boolean) << function(self, keys, isIncremental)
if self.m_charItems then
table.sort(self.m_charItems, Utils.genSortFunction(keys, isIncremental))
end
end
CharFormationList._RefreshCharList = HL.Method(HL.Opt(HL.Number)) << function(self, scrollToIndex)
if not scrollToIndex then
scrollToIndex = 0
end
local count = #self.m_charItems
self.view.charScrollList:UpdateCount(count, CSIndex(scrollToIndex))
if self.m_onCharListChanged then
self.m_onCharListChanged(self.m_charItems)
end
end
CharFormationList._ShowMultiChars = HL.Method(HL.Opt(HL.Boolean)) << function(self, playAnim)
for cellIndex = 1, self.view.charScrollList.count do
local cell = self:GetCellByIndex(cellIndex)
if cell then
cell:SetMultiSelect(self.cell2Select[cellIndex], playAnim)
end
end
end
CharFormationList._ShowSingleChars = HL.Method(HL.Opt(HL.Boolean)) << function(self, playAnim)
for cellIndex = 1, self.view.charScrollList.count do
local cell = self:GetCellByIndex(cellIndex)
if cell then
cell:SetSingleModeSelected(true, playAnim)
end
end
end
CharFormationList._UpdateMultiSelect = HL.Method(HL.Opt(HL.Boolean)).Return(HL.Table, HL.Table) << function(self, playAnim)
local result = {}
local charItemList = {}
local charInfoList = {}
for _, cellIndex in pairs(self.m_select2Cell) do
table.insert(result, cellIndex)
end
self.cell2Select = {}
self.m_select2Cell = {}
for index, cellIndex in pairs(result) do
local cell = self:GetCellByIndex(cellIndex)
self.cell2Select[cellIndex] = index
self.m_select2Cell[index] = cellIndex
if cell then
cell:SetMultiSelect(index, playAnim)
end
local charItem = self.m_charItems[cellIndex]
self:_UpdateSlotIndex(charItem, index)
table.insert(charItemList, charItem)
local charInfo = {
charId = charItem.templateId,
charInstId = charItem.instId,
isLocked = charItem.isLocked,
isTrail = charItem.isTrail,
isReplaceable = charItem.isReplaceable
}
table.insert(charInfoList, charInfo)
end
return charItemList, charInfoList
end
CharFormationList._GetNextIndex = HL.Method().Return(HL.Number) << function(self)
for index = 1, self.m_selectNum do
if not Utils.isInclude(self.cell2Select, index) then
return index
end
end
return -1
end
CharFormationList._RefreshMode = HL.Method() << function(self)
local singleSelected = self.m_mode == UIConst.CharListMode.Single
for cellIndex, _ in pairs(self.cell2Select) do
local cell = self:GetCellByIndex(cellIndex)
if cell then
cell:SetSingleModeSelected(singleSelected)
end
end
if self.m_mode == UIConst.CharListMode.Single then
local cell = self:GetCellByIndex(self.curSingleSelect)
if cell then
cell:SetSingleSelect(true)
UIUtils.setAsNaviTarget(cell.view.button)
end
end
end
CharFormationList.SetUpdateCellFunc = HL.Method(HL.Opt(HL.Function, HL.Function)) << function(self, updateFunc, clickFunc)
self.m_updateFunc = updateFunc
self.m_clickFunc = clickFunc
end
CharFormationList.OnUpdateCell = HL.Method(HL.Userdata, HL.Number, HL.Opt(HL.Function)) << function(self, object, index)
local cell = self:GetCellByIndex(index)
local item = self.m_charItems[index]
cell:InitCharFormationHeadCell(item, function(arg)
self:OnClickItem(index)
end, self.m_ignoreDead)
cell:RefreshExInfo(self.info)
if self.m_mode == UIConst.CharListMode.Single then
cell.view.button:ChangeActionOnSetNaviTarget(ActionOnSetNaviTarget.AutoTriggerOnClick)
cell:SetSingleModeSelected(true, false)
cell:SetSingleSelect(self.curSingleSelect == index)
local selectedCharInfo = self.info.selectedCharInfo
local isUnavailable = false
if selectedCharInfo and selectedCharInfo.isLocked then
if (not selectedCharInfo.isReplaceable or item.templateId ~= selectedCharInfo.charId) and
selectedCharInfo.charInstId ~= item.instId then
isUnavailable = true
end
else
if self.info.lockedTeamData then
for _, char in pairs(self.info.lockedTeamData.chars) do
if char.isLocked and char.charId == item.templateId and char.charInstId ~= item.instId then
isUnavailable = true
break
end
end
end
end
cell:SetUnavailable(isUnavailable)
else
cell.view.button:ChangeActionOnSetNaviTarget(ActionOnSetNaviTarget.PressConfirmTriggerOnClick)
cell:SetMultiSelect(self.cell2Select[index], false)
local isUnavailable = false
if self.info.lockedTeamData then
for _, char in pairs(self.info.lockedTeamData.chars) do
if char.isLocked and not char.isReplaceable and
char.charId == item.templateId and char.charInstId ~= item.instId then
isUnavailable = true
break
end
end
end
cell:SetUnavailable(isUnavailable)
end
end
CharFormationList.GetCellByIndex = HL.Method(HL.Number).Return(HL.Forward("CharFormationHeadCell")) << function(self, cellIndex)
local go = self.view.charScrollList:Get(CSIndex(cellIndex))
local cell = nil
if go then
cell = self.GetCell(go)
end
return cell
end
CharFormationList.ShowSelectChars = HL.Method(HL.Table, HL.Opt(HL.Boolean)) << function(self, m_charItems, playAnim)
self.cell2Select = {}
self.m_select2Cell = {}
self.m_charNum = #m_charItems
for index, charItem in pairs(m_charItems) do
local cellIndex = self:_GetCharIndex(charItem.instId)
self.cell2Select[cellIndex] = index
self.m_select2Cell[index] = cellIndex
end
if self.m_mode == UIConst.UIConst.CharListMode.MultiSelect then
self:_ShowMultiChars(playAnim)
else
self:_ShowSingleChars(playAnim)
end
end
CharFormationList.SetMode = HL.Method(HL.Any, HL.Any) << function(self, mode, charInstId)
self.m_naviTargetInitialized = false
self.m_mode = mode
self.curSingleSelect = self:_GetCharIndex(charInstId)
self.m_originSingleSelect = self.curSingleSelect
self:_RefreshMode()
end
CharFormationList.GetEmpty = HL.Method().Return(HL.Boolean) << function(self)
local empty
if self.m_mode == UIConst.UIConst.CharListMode.MultiSelect then
empty = self.m_charNum <= 0
else
empty = self.curSingleSelect <= 0
end
return empty
end
CharFormationList.UpdateCharItems = HL.Method(HL.Table) << function(self, items)
self.m_charItems = lume.deepCopy(items)
self.view.sortNode:SortCurData()
end
CharFormationList._GetCellSelectIndex = HL.Method(HL.Number).Return(HL.Number) << function(self, cellIndex)
if self.cell2Select[cellIndex] ~= nil and self.cell2Select[cellIndex] > 0 then
return self.cell2Select[cellIndex]
else
return -1
end
end
CharFormationList._RefreshSingleSelect = HL.Method(HL.Number) << function(self, cellIndex)
if self.curSingleSelect > 0 then
local oldCell = self:GetCellByIndex(self.curSingleSelect)
if oldCell then
oldCell:SetSingleSelect(false)
end
end
local cell = self:GetCellByIndex(cellIndex)
cell:SetSingleSelect(true)
self.curSingleSelect = cellIndex
end
CharFormationList.OnClickItem = HL.Method(HL.Number, HL.Opt(HL.Function, HL.Boolean)) << function(self, cellIndex, playAnim)
local cell = self:GetCellByIndex(cellIndex)
local cellSelectIndex = self:_GetCellSelectIndex(cellIndex)
if cell.isUnavailable then
Notify(MessageConst.SHOW_TOAST, Language.LUA_TEAM_FORMATION_CAN_NOT_REPLACE)
return
end
if self.m_mode == UIConst.CharListMode.Single then
if self.curSingleSelect == cellIndex then
return
end
self:_RefreshSingleSelect(cellIndex)
if self.m_clickFunc then
self.m_clickFunc(true, cellIndex, cell.info)
end
self.m_charNum = 1
else
if cell.info.isLocked and cellSelectIndex > 0 then
Notify(MessageConst.SHOW_TOAST, Language.LUA_TEAM_FORMATION_CHAR_LOCKED)
return
end
if cell.isDead and cellSelectIndex < 0 then
Notify(MessageConst.SHOW_TOAST, Language.LUA_CHAR_IS_DEAD)
return
end
if cell.info.isLocked and cell.info.isReplaceable then
local replaceSelectedIndex = nil
for selectedIndex, index in pairs(self.m_select2Cell) do
local selectedCharItem = self.m_charItems[index]
if selectedCharItem and selectedCharItem.templateId == cell.info.templateId then
replaceSelectedIndex = selectedIndex
end
end
if replaceSelectedIndex then
Notify(MessageConst.SHOW_POP_UP, {
content = Language.LUA_TEAM_FORMATION_REPLACE_CHAR,
onConfirm = function()
local replaceCell = self:GetCellByIndex(self.m_select2Cell[replaceSelectedIndex])
self.m_select2Cell[replaceSelectedIndex] = cellIndex
self.cell2Select[cellIndex] = replaceSelectedIndex
self.m_charItems[cellIndex].selectIndex = replaceSelectedIndex
if replaceCell then
replaceCell:SetMultiSelect(nil, playAnim)
self:_UpdateSlotIndex(self.m_charItems[cellIndex], nil)
end
local charItemList, charInfoList = self:_UpdateMultiSelect(playAnim)
if self.m_clickFunc then
self.m_clickFunc(false, cellIndex, cell.info, charItemList, charInfoList)
end
end,
})
return
end
end
if self.m_charNum >= self.m_selectNum and self.cell2Select[cellIndex] == nil and replaceIndex == nil then
Notify(MessageConst.SHOW_TOAST, Language.LUA_CHAR_FORMATION_MAX_CHAR)
return
end
if cellSelectIndex > 0 then
local index = self.cell2Select[cellIndex]
self.m_select2Cell[index] = nil
self.cell2Select[cellIndex] = nil
self.m_charItems[cellIndex].selectIndex = nil
self.m_charNum = self.m_charNum - 1
cell:SetMultiSelect(nil, playAnim)
self:_UpdateSlotIndex(self.m_charItems[cellIndex], nil)
InputManagerInst:SetBindingText(cell.view.button.hoverConfirmBindingId, Language.LUA_CHAR_FORMATION_CONTROLLER_IN_TEAM)
elseif self.m_charNum < self.m_selectNum then
local curIndex = self:_GetNextIndex()
self.m_select2Cell[curIndex] = cellIndex
self.cell2Select[cellIndex] = curIndex
self.m_charItems[cellIndex].selectIndex = curIndex
self.m_charNum = curIndex
InputManagerInst:SetBindingText(cell.view.button.hoverConfirmBindingId, Language.LUA_CHAR_FORMATION_CONTROLLER_OUT_TEAM)
end
local charItemList, charInfoList = self:_UpdateMultiSelect(playAnim)
if self.m_clickFunc then
self.m_clickFunc(false, cellIndex, cell.info, charItemList, charInfoList)
end
end
end
CharFormationList._UpdateSlotIndex = HL.Method(HL.Table, HL.Any) << function(self, charItem, selectedIndex)
if selectedIndex then
charItem.slotIndex = selectedIndex
charItem.slotReverseIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM - selectedIndex
else
charItem.slotIndex = Const.BATTLE_SQUAD_MAX_CHAR_NUM + 1
charItem.slotReverseIndex = -1
end
end
HL.Commit(CharFormationList)
return CharFormationList