Files
Endfield-Data/LuaScripts/UI/Panels/ActivityCenter/ActivityCenterCtrl.lua
2025-12-02 20:37:18 +07:00

536 lines
14 KiB
Lua

local uiCtrl = require_ex('UI/Panels/Base/UICtrl')
local PANEL_ID = PanelId.ActivityCenter
local PHASE_ID = PhaseId.ActivityCenter
ActivityCenterCtrl = HL.Class('ActivityCenterCtrl', uiCtrl.UICtrl)
ActivityCenterCtrl.s_messages = HL.StaticField(HL.Table) << {
[MessageConst.ON_ACTIVITY_UPDATED] = 'OnActivityUpdated',
[MessageConst.ON_ACTIVITY_CENTER_REFRESH] = 'OnActivityCenterRefresh',
}
ActivityCenterCtrl.m_selectedPanel = HL.Field(HL.Any)
ActivityCenterCtrl.m_fromDialog = HL.Field(HL.Boolean) << false
ActivityCenterCtrl.m_allActivities = HL.Field(HL.Table)
ActivityCenterCtrl.m_selectedTabIndex = HL.Field(HL.Number) << 0
ActivityCenterCtrl.m_activityDict = HL.Field(HL.Table)
ActivityCenterCtrl.m_tabCells = HL.Field(HL.Any)
ActivityCenterCtrl.m_cells = HL.Field(HL.Any)
ActivityCenterCtrl.m_activityId = HL.Field(HL.String) << ""
ActivityCenterCtrl.m_initialActivityId = HL.Field(HL.String) << ""
ActivityCenterCtrl.m_enterType = HL.Field(HL.String) << ""
local WAIT_FOR_ANIM_TIME = 0.2
local CLOSE_WAIT_TIME = 0.5
ActivityCenterCtrl.OnCreate = HL.Override(HL.Any) << function(self, arg)
self:_InitInfoAndButtons(arg)
self:_RefreshTabList()
self:_InitController()
self:_Debug()
self:GoToActivity(self.m_initialActivityId)
self:_InitDecoArrow()
end
ActivityCenterCtrl._InitDecoArrow = HL.Method() << function(self)
self:_StartCoroutine(function()
while true do
coroutine.step()
local _,final = self:_GetShowingCellStartEnd()
self.view.decoArrow.gameObject:SetActive(final < #self.m_allActivities)
local moreActivityData = {}
for i = final + 1, #self.m_allActivities do
table.insert(moreActivityData, self.m_allActivities[i].activityData)
end
self.view.redDotArrow:InitRedDot("ActivityTableMore", moreActivityData)
end
end)
end
ActivityCenterCtrl._InitInfoAndButtons = HL.Method(HL.Table) << function(self, arg)
self.view.btnClose.onClick:AddListener(function()
self:_Close()
end)
self.view.doubleF7CloseBtn.onClick:AddListener(function()
self:_Close()
end)
self.m_tabCells = UIUtils.genCellCache(self.view.tabCell)
self.m_initialActivityId = (arg and arg.gotoCenter) and arg.activityId or ""
self.m_enterType = arg and arg.openFrom or "SomewhereElse"
end
ActivityCenterCtrl._InitController = HL.Method() << function(self)
if DeviceInfo.usingController then
if #self.m_allActivities > 0 and not self.m_initialActivityId then
self:_SetNaviTarget(1)
end
end
end
ActivityCenterCtrl._Debug = HL.Method() << function(self)
if BEYOND_DEBUG_COMMAND then
UIUtils.bindInputEvent(CS.Beyond.Input.KeyboardKeyCode.Z, function()
UIManager:Open(PanelId.StaminaPotion,"item_ap_feed_in")
end, nil, nil, self.view.inputGroup.groupId)
UIUtils.bindInputEvent(CS.Beyond.Input.KeyboardKeyCode.X, function()
PhaseManager:OpenPhase(PhaseId.CheckInCBT3)
end, nil, nil, self.view.inputGroup.groupId)
UIUtils.bindInputEvent(CS.Beyond.Input.KeyboardKeyCode.C, function()
local start, final = self:_GetShowingCellStartEnd()
logger.error(start, final)
end, nil, nil, self.view.inputGroup.groupId)
end
end
ActivityCenterCtrl._RefreshTabList = HL.Method() << function(self)
local lastCount = 0
local lastActivityId
if self.m_allActivities then
lastCount = #self.m_allActivities
if lastCount > 0 then
lastActivityId = self.m_allActivities[self.m_selectedTabIndex].id
end
end
self.m_allActivities = {}
local activities = GameInstance.player.activitySystem:GetAllActivities()
for _, activity in cs_pairs(activities) do
local _, activityData = Tables.activityTable:TryGetValue(activity.id)
if activityData then
table.insert(self.m_allActivities, {
id = activity.id,
sortId = -activityData.sortId,
activity = activity,
activityData = activityData,
completed = activity.isCompleted and 1 or 0,
type = activityData.type,
status = activity.status,
})
end
end
if #self.m_allActivities == 0 then
Notify(MessageConst.SHOW_TOAST,Language.LUA_ACTIVITY_NONE_ACTIVITY_EXIST)
self:_StartCoroutine(function()
coroutine.wait(CLOSE_WAIT_TIME)
self:_Close()
end)
end
table.sort(self.m_allActivities, Utils.genSortFunction({"completed","sortId", "id"}, true))
self.m_activityDict = {}
for index = 1,#self.m_allActivities do
local activity = self.m_allActivities[index]
self.m_activityDict[activity.id] = {
type = activity.type,
index = index,
}
end
self.m_cells = {}
self.m_tabCells:Refresh(#self.m_allActivities, function(cell, index)
self:_OnUpdateCell(cell, index)
end)
if self.m_selectedTabIndex == 0 then
if #self.m_allActivities > 0 then
ActivityUtils.GameEventLogActivityEnter(self.m_enterType, not string.isEmpty(self.m_initialActivityId) and self.m_initialActivityId or self.m_allActivities[1].id)
self:_OnTabClicked(1)
end
else
self:GoToActivity(lastActivityId)
end
end
ActivityCenterCtrl._OnUpdateCell = HL.Method(HL.Any, HL.Number) << function(self, cell, index)
self.m_cells[index] = cell
cell.button.onClick:RemoveAllListeners()
cell.button.onClick:AddListener(function()
self:_OnTabClicked(index)
end)
self:_SetTabCellSelected(cell, index == self.m_selectedTabIndex)
local activityData = self.m_allActivities[index].activityData
local nodes = {
cell.selectNode,
cell.normalNode,
}
for i = 1, #nodes do
local innerCell = nodes[i]
innerCell.txtName.text = activityData.name
if activityData.tabImg ~= "" then
if activityData.tabImgGender then
local suffix = Utils.getPlayerGender() == CS.Proto.GENDER.GenMale and "_boy" or "_girl"
innerCell.tabImg:LoadSprite(UIConst.UI_SPRITE_ACTIVITY,activityData.tabImg .. suffix)
else
innerCell.tabImg:LoadSprite(UIConst.UI_SPRITE_ACTIVITY,activityData.tabImg)
end
end
if activityData.tabImgColor then
local suc, color = CS.UnityEngine.ColorUtility.TryParseHtmlString(activityData.tabImgColor)
if suc then
innerCell.selectedBg.color = color
innerCell.decoLine.color = color
innerCell.decoArrow.color = color
end
end
if ActivityConst.ACTIVITY_TABLE[activityData.type] and ActivityConst.ACTIVITY_TABLE[activityData.type].redDot then
local redDotName = ActivityConst.ACTIVITY_TABLE[activityData.type].redDot
innerCell.redDot:InitRedDot(redDotName,activityData.id)
end
local activity = GameInstance.player.activitySystem:GetActivity(activityData.id)
innerCell.completedIconNode.gameObject:SetActive(activity.isCompleted)
end
end
ActivityCenterCtrl._OnTabClicked = HL.Method(HL.Number, HL.Opt(HL.Boolean)) << function(self, index, forceRefresh)
if #self.m_allActivities == 0 then
self:_OnActivityDisabled()
return
end
if self.m_selectedTabIndex == index and not forceRefresh then
return
end
local lastSelectedCell = self:_GetCell(self.m_selectedTabIndex)
if lastSelectedCell then
self:_SetTabCellSelected(lastSelectedCell, false)
end
self.m_selectedTabIndex = index
local selectedCell = self:_GetCell(index)
if selectedCell then
self:_SetTabCellSelected(selectedCell, true)
end
local id = self.m_allActivities[index].id
ActivityUtils.GameEventLogActivityVisit(id, "ActivityTabCellButton", "visit_center")
if ActivityUtils.isNewActivity(id) then
ActivityUtils.setFalseNewActivity(id)
end
if ActivityUtils.isNewUnlockActivity(id) then
ActivityUtils.setFalseNewUnlockActivity(id)
end
if ActivityUtils.isNewActivityBubble(id) and self.m_allActivities[index].activity.isUnlocked then
ActivityUtils.setFalseNewActivityBubble(id)
end
if self.m_activityId == id then
return
end
self.m_activityId = id
Notify(MessageConst.SHOW_ACTIVITY_PANEL, {
activityId = id,
controllerHintPlaceholder = self.view.controllerHintPlaceholder,
groupId = self.view.inputBindingGroupMonoTarget.groupId,
naviGroup = self.view.tabScrollRectSelectableNaviGroup,
getReturnTargetFunc = function()
return self:_GetCell(self.m_activityDict[id].index).button
end,
btnClose = self.view.btnClose,
})
end
ActivityCenterCtrl.GoToActivity = HL.Method(HL.Any, HL.Opt(HL.Boolean)) << function(self, activityId, forceRefresh)
if not activityId then
return
end
local index
if self.m_activityDict[activityId] then
index = self.m_activityDict[activityId].index or 1
else
index = 1
end
self:_OnTabClicked(index, forceRefresh)
self:_StartCoroutine(function()
coroutine.wait(WAIT_FOR_ANIM_TIME)
local _,final = self:_GetShowingCellStartEnd()
local normalizedPosition = 1 - (index - final) / (#self.m_allActivities - final)
self.view.tabScrollRect.verticalNormalizedPosition = lume.clamp(normalizedPosition, 0, 1)
self:_SetNaviTarget(index)
end)
end
ActivityCenterCtrl._GetShowingCellStartEnd = HL.Method().Return(HL.Number,HL.Number) << function(self)
local redDotSize = self.view.tabCell.selectNode.redDot.rectTransform.rect.height
local totalCount = #self.m_allActivities
local low, high = 1, totalCount
local start = totalCount
while low <= high do
local mid = math.floor((low + high) / 2)
local cell = self:_GetCell(mid)
local top = -self.view.contentRectTransform.anchoredPosition.y - cell.gameObject:GetComponent("RectTransform").anchoredPosition.y - self.view.tabCellRectTransform.rect.height / 2 - redDotSize / 2
local bottom = top + redDotSize
if bottom > 0 then
start = mid
high = mid - 1
else
low = mid + 1
end
end
low, high = 1, totalCount
local final = 1
while low <= high do
local mid = math.floor((low + high) / 2)
local cell = self:_GetCell(mid)
local top = -self.view.contentRectTransform.anchoredPosition.y - cell.gameObject:GetComponent("RectTransform").anchoredPosition.y - self.view.tabCellRectTransform.rect.height / 2 - redDotSize / 2
if top < self.view.tabScrollRectRectTransform.rect.height then
final = mid
low = mid + 1
else
high = mid - 1
end
end
return start, final
end
ActivityCenterCtrl._GetCell = HL.Method(HL.Number).Return(HL.Any) << function(self, index)
local target
self.m_tabCells:Refresh(#self.m_allActivities, function(cell, tabIndex)
if index == tabIndex then
target = cell
end
end)
return target
end
ActivityCenterCtrl._SetNaviTarget = HL.Method(HL.Number) << function(self, index)
local cell = self:_GetCell(index)
if DeviceInfo.usingController and cell then
UIUtils.setAsNaviTarget(cell.button)
end
end
ActivityCenterCtrl._SetTabCellSelected = HL.Method(HL.Table, HL.Boolean) << function(self, tabCell, isSelected)
tabCell.stateController:SetState(isSelected and "selected" or "normal")
end
ActivityCenterCtrl._Close = HL.Method() << function(self)
PhaseManager:PopPhase(PHASE_ID)
end
ActivityCenterCtrl.OnActivityUpdated = HL.Method(HL.Any) << function(self, arg)
local id = unpack(arg)
local activity = GameInstance.player.activitySystem:GetActivity(id)
if not activity then
self:_OnActivityDisabled()
return
end
if not self.m_activityDict[id] then
self:_RefreshTabList()
return
end
if activity.status ~= self.m_allActivities[self.m_activityDict[id].index].status then
self:_RefreshTabCompleteState()
return
end
end
ActivityCenterCtrl._RefreshTabCompleteState = HL.Method() << function(self)
self.m_tabCells:Refresh(#self.m_allActivities, function(cell, index)
local activityData = self.m_allActivities[index].activityData
local activity = GameInstance.player.activitySystem:GetActivity(activityData.id)
cell.selectNode.completedIconNode.gameObject:SetActive(activity.isCompleted)
cell.normalNode.completedIconNode.gameObject:SetActive(activity.isCompleted)
end)
end
ActivityCenterCtrl._IsActivityChanged = HL.Method().Return(HL.Boolean) << function(self)
local old = self.m_activityDict
local new = {}
local activities = GameInstance.player.activitySystem:GetAllActivities()
for _, activity in cs_pairs(activities) do
new[activity.id] = true
end
for key, _ in pairs(new) do
if old[key] == nil then
return true
end
end
for key, _ in pairs(old) do
if new[key] == nil then
return true
end
end
return false
end
ActivityCenterCtrl._OnActivityDisabled = HL.Method() << function(self)
GameInstance.player.guide:OnActivityDisabled()
Notify(MessageConst.SHOW_POP_UP,{
content = Language.LUA_ACTIVITY_MODIFY_QUIT_TO_MENU,
hideCancel = true,
onConfirm = function()
PhaseManager:ExitPhaseFastTo(PhaseId.Level, true)
end
})
end
ActivityCenterCtrl.OnActivityCenterRefresh = HL.Method(HL.Table) << function(self, arg)
self:GoToActivity(arg and arg.gotoCenter and arg.activityId, true)
end
HL.Commit(ActivityCenterCtrl)