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

431 lines
10 KiB
Lua

local redDotConfigFile = require_ex("UI/RedDot/RedDotConfig")
local RegisterEventToCS = CS.Beyond.EventManager.AddLuaListenGlobal;
local RED_DOT_TYPE = UIConst.RED_DOT_TYPE
local RED_DOT_TYPE_MAX = UIConst.RED_DOT_TYPE_MAX
RedDotManager = HL.Class('RedDotManager')
RedDotManager.m_activeMsgs = HL.Field(HL.Table)
RedDotManager.m_activeRedDots = HL.Field(HL.Table)
RedDotManager.m_redDotInstanceMap = HL.Field(HL.Table)
RedDotManager.m_nexActiveRedDotId = HL.Field(HL.Number) << 1
RedDotManager.configs = HL.Field(HL.Table)
RedDotManager.RedDotManager = HL.Constructor() << function(self)
self.m_activeMsgs = {}
self.m_activeRedDots = {}
self.m_redDotInstanceMap = {}
self:UpdateConfigs()
end
RedDotManager.UpdateConfigs = HL.Method() << function(self)
logger.info(ELogChannel.RedDot, "RedDotManager.UpdateConfigs")
local redDotConfig = {}
for k, v in pairs(redDotConfigFile) do
if v.Check and v.needArg == nil then
logger.error("红点配置不合法,没有标注 needArg", k, inspect(v))
end
if v.readLike == nil then
logger.error("红点配置不合法,没有标注 readLike", k, inspect(v))
end
local redDot = {
name = k,
config = v,
}
setmetatable(redDot, { __index = v })
redDotConfig[k] = redDot
end
for k, v in pairs(redDotConfig) do
if v.sons then
for sonName, resultDependency in pairs(v.sons) do
local son = redDotConfig[sonName]
if son then
if not son.fathers then
son.fathers = {}
end
son.fathers[k] = resultDependency
else
logger.error("No son", k, sonName)
end
end
end
end
self.configs = redDotConfig
local activeMsgs = {}
for name, _ in pairs(self.m_activeRedDots) do
local redDot = redDotConfig[name]
if redDot.msgs then
for _, v in ipairs(redDot.msgs) do
local redDots = activeMsgs[v]
if not redDots then
redDots = {}
activeMsgs[v] = redDots
RegisterEventToCS(MessageConst.getMsgName(v))
end
redDots[name] = true
end
end
end
self.m_activeMsgs = activeMsgs
end
RedDotManager.AddFatherSon = HL.Method(HL.String, HL.String) << function(self, fatherName, sonName)
logger.info(ELogChannel.RedDot, "RedDotManager.AddFatherSon", fatherName, sonName)
local redDot = self.configs[fatherName]
if not redDot then
logger.error("No RedDot", fatherName)
return
end
local sonRedDot = self.configs[sonName]
if not sonRedDot then
logger.error("No RedDot", sonName)
return
end
if not redDot.sons then
redDot.sons = {}
end
redDot.sons[sonName] = true
if not sonRedDot.fathers then
sonRedDot.fathers = {}
end
sonRedDot.fathers[fatherName] = true
end
RedDotManager.OnMessage = HL.Method(HL.Number) << function(self, msgId)
local redDots = self.m_activeMsgs[msgId]
if not redDots then
return
end
logger.info(ELogChannel.RedDot, "RedDotManager.OnMessage", MessageConst.getMsgName(msgId))
for name, _ in pairs(redDots) do
self:TriggerUpdate(name)
end
end
RedDotManager.GetRedDotState = HL.Method(HL.String, HL.Opt(HL.Any, HL.Number)).Return(HL.Boolean, HL.Opt(HL.Number, HL.Number)) <<
function(self, name, arg, penetrateLevel)
logger.info(ELogChannel.RedDot, "RedDotManager.GetRedDotState", name, inspect(arg), penetrateLevel)
local redDot = self.configs[name]
if not redDot then
logger.error("No RedDot", name)
return false
end
local result, redDotType = false
local expireTs = 0
if redDot.Check then
local succ
succ, result, redDotType, expireTs = xpcall(redDot.Check, debug.traceback, arg)
if not succ then
logger.error("redDot.Check() error", name, result)
return false
end
if result and not redDotType then
redDotType = RED_DOT_TYPE.Normal
end
if redDotType == RED_DOT_TYPE_MAX then
return result, redDotType, expireTs
end
end
if redDot.sons then
penetrateLevel = penetrateLevel or redDot.penetrateLevel or UIConst.RED_DOT_DEFAULT_PENETRATE
local sonResult, sonRedDotType
for sonName, v in pairs(redDot.sons) do
if v then
sonResult, sonRedDotType, expireTs = self:GetRedDotState(sonName, arg, penetrateLevel)
if sonResult and sonRedDotType >= penetrateLevel then
if sonRedDotType == RED_DOT_TYPE_MAX then
return sonResult, sonRedDotType, expireTs
end
if not result or redDotType < sonRedDotType then
result, redDotType = sonResult, sonRedDotType
end
end
end
end
end
return result, redDotType, expireTs
end
RedDotManager.TriggerUpdate = HL.Method(HL.String) << function(self, name)
local redDot = self.configs and self.configs[name]
if not redDot then
logger.error("No RedDot", name)
return
end
local redDotInstanceList = self.m_activeRedDots[name]
if not redDotInstanceList then
return
end
logger.info(ELogChannel.RedDot, "RedDotManager.TriggerUpdate", name)
local count = #redDotInstanceList
if count > 0 then
local result, redDotType, expireTs
local list = {}
for k, v in ipairs(redDotInstanceList) do
list[k] = v
end
for _, v in ipairs(list) do
local isActive = true
if v.uiWidget then
isActive = v.uiWidget:GetActiveState()
end
if isActive then
if redDot.needArg then
v.onUpdate()
else
if result == nil then
result, redDotType, expireTs = self:GetRedDotState(name)
end
v.onUpdate(result, redDotType, expireTs)
end
else
v.uiWidget.needUpdateOnActive = true
end
end
end
if redDot.fathers then
for k, _ in pairs(redDot.fathers) do
self:TriggerUpdate(k)
end
end
end
RedDotManager.AddRedDotInstance = HL.Method(HL.String, HL.Function, HL.Forward('RedDot')).Return(HL.Opt(HL.Number)) <<
function(self, name, onUpdate, uiWidget)
logger.info(ELogChannel.RedDot, "RedDotManager.AddRedDotInstance", name)
local redDot = self.configs[name]
if not redDot then
logger.error("No RedDot", name)
return
end
local key = self.m_nexActiveRedDotId
self.m_nexActiveRedDotId = self.m_nexActiveRedDotId + 1
local redDotInstance = {
redDotName = name,
onUpdate = onUpdate,
key = key,
uiWidget = uiWidget,
}
self.m_redDotInstanceMap[key] = redDotInstance
local redDotInstanceList = self:_ActiveRedDot(name)
table.insert(redDotInstanceList, redDotInstance)
return key
end
RedDotManager.RemoveRedDotInstance = HL.Method(HL.Number).Return(HL.Number) << function(self, key)
logger.info(ELogChannel.RedDot, "RedDotManager.RemoveRedDotInstance", key)
local redDotInstance = self.m_redDotInstanceMap[key]
if not redDotInstance then
return -1
end
self.m_redDotInstanceMap[key] = nil
local name = redDotInstance.redDotName
local redDotInstanceList = self.m_activeRedDots[name]
lume.remove(redDotInstanceList, redDotInstance)
self:_TryDeactiveRedDot(name)
return -1
end
RedDotManager._ActiveRedDot = HL.Method(HL.String).Return(HL.Opt(HL.Table)) << function(self, name)
local redDot = self.configs[name]
if not redDot then
logger.error("No RedDot", name)
return
end
local activeRedDots = self.m_activeRedDots
if activeRedDots[name] then
return activeRedDots[name]
end
logger.info(ELogChannel.RedDot, "RedDotManager._ActiveRedDot", name)
activeRedDots[name] = {}
if redDot.msgs then
local activeMsgs = self.m_activeMsgs
for _, v in ipairs(redDot.msgs) do
local redDots = activeMsgs[v]
if not redDots then
redDots = {}
activeMsgs[v] = redDots
RegisterEventToCS(MessageConst.getMsgName(v))
end
redDots[name] = true
end
end
if redDot.sons then
for k, _ in pairs(redDot.sons) do
self:_ActiveRedDot(k)
end
end
return activeRedDots[name]
end
RedDotManager._TryDeactiveRedDot = HL.Method(HL.String) << function(self, name)
local activeRedDots = self.m_activeRedDots
if not activeRedDots[name] then
return
end
if #activeRedDots[name] > 0 then
return
end
local redDot = self.configs[name]
if not redDot then
logger.error("No RedDot", name)
return
end
if redDot.fathers then
for k, _ in pairs(redDot.fathers) do
if activeRedDots[k] then
return
end
end
end
logger.info(ELogChannel.RedDot, "RedDotManager DeactiveRedDot ", name)
if redDot.msgs then
local activeMsgs = self.m_activeMsgs
for _, msgId in ipairs(redDot.msgs) do
activeMsgs[msgId][name] = nil
if not next(activeMsgs[msgId]) then
activeMsgs[msgId] = nil
end
end
end
activeRedDots[name] = nil
if redDot.sons then
for k, _ in pairs(redDot.sons) do
self:_TryDeactiveRedDot(k)
end
end
end
HL.Commit(RedDotManager)
return RedDotManager