Files
Endfield-Data/LuaScripts/Common/Core/UIManager.lua
2026-01-31 21:42:01 +07:00

2285 lines
63 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
local panelConfig = require_ex("UI/Panels/PanelConfig")
local rootConfig = require_ex("UI/Panels/RootConfig")
local luaLoader = require_ex('Common/Utils/LuaResourceLoader')
local PlaneDistance = CS.Beyond.UI.UIConst.SCREEN_SPACE_CAMERA_PANEL_DISTANCE
UIManager = HL.Class('UIManager')
UIManager.ids = HL.Field(HL.Table)
UIManager.cfgs = HL.Field(HL.Table)
UIManager.m_names = HL.Field(HL.Table)
UIManager.persistentInputBindingKey = HL.Field(HL.Number) << -1
UIManager.m_panelConfigs = HL.Field(HL.Table)
UIManager.m_openedPanels = HL.Field(HL.Table)
UIManager.m_hidedPanels = HL.Field(HL.Table)
UIManager.m_selfMaintainOrderPanels = HL.Field(HL.Table)
UIManager.m_nextClearScreenKey = HL.Field(HL.Number) << 1
UIManager.m_clearedPanelReverseInfos = HL.Field(HL.Table)
UIManager.m_clearedPanelInfos = HL.Field(HL.Table)
UIManager.m_autoClearScreenKeys = HL.Field(HL.Table)
UIManager.m_orderManagers = HL.Field(HL.Table)
UIManager.m_panelOrderInterval = HL.Field(HL.Number) << 20
UIManager.m_panelOrderTypeInterval = HL.Field(HL.Number) << 1000
UIManager.m_curBlockKeyboardEventPanelOrder = HL.Field(HL.Number) << -1
UIManager.m_ignoreBlockOrderUpdate = HL.Field(HL.Boolean) << false
UIManager.m_resourceLoader = HL.Field(HL.Forward("LuaResourceLoader"))
UIManager.m_panel2Handle = HL.Field(HL.Table)
UIManager.m_customPreloadInfos = HL.Field(HL.Table)
UIManager.uiCamera = HL.Field(Unity.Camera)
UIManager.uiCanvasRect = HL.Field(Unity.RectTransform)
UIManager.m_uiCanvasScaleHelper = HL.Field(CS.Beyond.UI.UICanvasScaleHelper)
UIManager.uiNode = HL.Field(HL.Table)
UIManager.uiRoot = HL.Field(Unity.Transform)
UIManager.uiInputBindingGroupMonoTarget = HL.Field(CS.Beyond.Input.InputBindingGroupMonoTarget)
UIManager.worldUIRoot = HL.Field(Unity.RectTransform)
UIManager.gyroscopeEffect = HL.Field(CS.Beyond.UI.UIGyroscopeEffect)
UIManager.worldUICanvas = HL.Field(Unity.Canvas)
UIManager.worldObjectRoot = HL.Field(Unity.Transform)
UIManager.m_disabledPanelRoot = HL.Field(Unity.Transform)
UIManager.commonTouchPanel = HL.Field(CS.Beyond.UI.UITouchPanel)
UIManager.m_blockInputKeys = HL.Field(HL.Table)
UIManager.m_mainCameraClosedByUI = HL.Field(HL.Boolean) << false
UIManager.m_showingFullScreenPanel = HL.Field(HL.Table)
UIManager.m_worldUICanvasScaleHelper = HL.Field(CS.Beyond.UI.UICanvasScaleHelper)
UIManager.m_onScreenSizeChangedCallback = HL.Field(HL.Function)
UIManager.m_currentStandardFOV = HL.Field(HL.Number) << 0
UIManager.m_sourceFontFileLoader = HL.Field(HL.Userdata)
UIManager.uiDummyNaviLayerRoot = HL.Field(Unity.Transform)
UIManager.uiDummyNaviLayerAsset = HL.Field(HL.Userdata)
UIManager.UIManager = HL.Constructor() << function(self)
Register(MessageConst.BLOCK_LUA_UI_INPUT, function(arg)
local shouldBlock, key = unpack(arg)
self:_ToggleUIInputBinding(not shouldBlock, key)
end, self)
Register(MessageConst.CLOSE_UI_PANEL, function(arg)
local panelName = unpack(arg)
self:Close(PanelId[panelName])
end, self)
Register(MessageConst.ON_TOGGLE_UI_ACTION, function(arg)
self:OnToggleUiAction(arg)
end, self)
Register(MessageConst.CLOSE_ALL_UI_FOR_SWITCH_LANGUAGE, function()
self:_CloseAllUIForSwitchLanguage()
end, self)
Register(MessageConst.ON_INPUT_DEVICE_TYPE_CHANGED, function()
if DeviceInfo.isMobile then
self:UpdateUICanvasScaleHelpers()
end
end, self)
self.cfgs = {}
self.m_panelConfigs = {}
self.m_openedPanels = setmetatable({}, { __mode = "v" })
self.m_hidedPanels = setmetatable({}, { __mode = "v" })
self.m_selfMaintainOrderPanels = setmetatable({}, { __mode = "v" })
self.m_clearedPanelReverseInfos = {}
self.m_clearedPanelInfos = {}
self.m_autoClearScreenKeys = {}
self.m_orderManagers = {}
self.m_panel2Handle = {}
self.m_customPreloadInfos = {}
self.m_blockInputKeys = {}
self.m_showingFullScreenPanel = {}
self.m_blockObtainWaysJumpKeys = {}
self.m_recentClosedPanelIds = {}
self.m_waitClearPanels = {}
self:InitPanelIds()
local UICtrl = require_ex('UI/Panels/Base/UICtrl').UICtrl
UICtrl.s_useBlackOutPanelIds = {}
Register(MessageConst.TOGGLE_PANEL_USE_BLACK_OUT, function(arg)
local panelName, useBlackOut = unpack(arg)
local panelId = PanelId[panelName]
UICtrl.TogglePanelUseBlackOut(panelId, useBlackOut)
end, self)
self.persistentInputBindingKey = InputManagerInst:CreateGroup(-1)
self.m_resourceLoader = luaLoader.LuaResourceLoader()
self:_InitOrderManagers()
local uiNodeAsset = self.m_resourceLoader:LoadGameObject(UIConst.UI_NODE_PREFAB_PATH)
local uiNodeObj = CSUtils.CreateObject(uiNodeAsset)
self.uiNode = Utils.bindLuaRef(uiNodeObj)
self.uiNode.gameObject.name = UNITY_EDITOR and "+ UINode" or "UINode"
GameObject.DontDestroyOnLoad(self.uiNode.gameObject)
self.uiRoot = self.uiNode.uiRoot.transform
self.uiInputBindingGroupMonoTarget = self.uiNode.transform:GetComponent("InputBindingGroupMonoTarget")
self.m_uiCanvasScaleHelper = self.uiRoot:GetComponent("UICanvasScaleHelper")
self.uiCanvasRect = self.uiNode.dummyCanvas.transform
self.m_uiCanvasScaleHelper:AddCanvas(self.uiNode.dummyCanvas, self.uiNode.dummyCanvas:GetComponent("CanvasScaler"))
self.worldUICanvas = self.uiNode.worldUIRoot
self.worldUIRoot = self.uiNode.worldUIRoot.transform
self.gyroscopeEffect = self.uiNode.worldUIRoot.transform:GetComponent("UIGyroscopeEffect")
self.m_worldUICanvasScaleHelper = self.worldUIRoot:GetComponent("UICanvasScaleHelper")
self.uiDummyNaviLayerRoot = self.uiNode.uiDummyNaviLayerRoot
self.uiDummyNaviLayerAsset = self.m_resourceLoader:LoadGameObject(UIConst.UI_DUMMY_NAVI_LAYER_PREFAB_PATH)
self.m_disabledPanelRoot = self.uiNode.disabledUIRoot
self.m_disabledPanelRoot.gameObject:SetActive(false)
self.worldObjectRoot = GameObject("UICreatedWorldObjects").transform
self.worldObjectRoot.position = Vector3.zero
GameObject.DontDestroyOnLoad(self.worldObjectRoot.gameObject)
local uiCam = CameraManager.uiCamera
self.uiCamera = uiCam
self.m_uiCanvasScaleHelper.uiCamera = uiCam
self.m_worldUICanvasScaleHelper.uiCamera = uiCam
self.worldUICanvas.worldCamera = uiCam
self.uiNode.dummyCanvas.worldCamera = uiCam
self.uiNode.dummyCanvas.planeDistance = PlaneDistance
self.m_currentStandardFOV = self:GetUICameraFOV()
self.m_onScreenSizeChangedCallback = function()
self:_OnScreenSizeChanged()
end
self.m_worldUICanvasScaleHelper.onScreenSizeChanged:AddListener(self.m_onScreenSizeChangedCallback)
CS.TMPro.TMP_Settings.instance.dynamicFontAssetLoader = CS.Beyond.UI.DynamicFontAssetLoader()
addMetaIndex(self.cfgs, function(_, k)
local id = self.ids[k]
if id then
return self.m_panelConfigs[id]
end
end)
if CS.Beyond.BeyondMemoryUtility.IsLowMemoryDevice() then
self.m_panelAssetLRUCapacity = 0
end
end
UIManager.InitPanelIds = HL.Method() << function(self)
self.ids = {}
self.m_names = {}
local nextId = 1
for name, data in pairs(panelConfig.config) do
local id = nextId
nextId = nextId + 1
self.ids[name] = id
self.m_names[id] = name
end
end
UIManager.InitPanelConfigs = HL.Method() << function(self)
for name, data in pairs(panelConfig.config) do
local id = self.ids[name]
local cfg = {
name = name,
id = id
}
local modelPath = string.format(UIConst.UI_PANEL_MODEL_FILE_PATH, name, name)
local modelExist = require_check(modelPath)
if modelExist then
cfg.modelClass = require_ex(modelPath)[name .. "Model"]
else
cfg.modelClass = require_ex("UI/Panels/Base/UIModel").UIModel
end
setmetatable(cfg, { __index = data })
self.m_panelConfigs[id] = cfg
end
local backgroundMessage = require_ex(UIConst.UI_BACKGROUND_MESSAGE_PATH).BackgroundMessage
for ctrlName, msgs in pairs(backgroundMessage.s_messages) do
for msg, funcName in pairs(msgs) do
Register(msg, function(msgArg)
local id = self.ids[ctrlName]
local cfg = self.m_panelConfigs[id]
if not cfg.ctrlClass then
local path = string.format(UIConst.UI_PANEL_CTRL_FILE_PATH, ctrlName, ctrlName)
local ctrlClass = require_ex(path)[ctrlName .. "Ctrl"]
cfg.ctrlClass = ctrlClass
end
local ctrlClass = cfg.ctrlClass
if HL.TryGet(ctrlClass, "s_overrideMessages") then
ctrlClass.s_messages = ctrlClass.s_overrideMessages
else
ctrlClass.s_messages = ctrlClass.s_messages
end
if msgArg == nil then
ctrlClass[funcName]()
else
ctrlClass[funcName](msgArg)
end
end, self)
end
end
self:_InitRoots()
end
UIManager.OpenInitPanels = HL.Method() << function(self)
Input.multiTouchEnabled = true
self:Open(self.ids.Touch)
self:Open(self.ids.CommonDrag)
self.commonTouchPanel = self.cfgs.Touch.ctrl.view.uiTouchPanel
self:Open(self.ids.MouseIconHint)
self:Open(self.ids.CommonTips)
self:Open(self.ids.FullScreenSceneBlur)
Notify(MessageConst.ON_OPEN_INIT_PANELS)
end
UIManager.Open = HL.Method(HL.Number, HL.Opt(HL.Any, HL.Table)).Return(HL.Opt(HL.Forward("UICtrl")))
<< function(self, panelId, arg, callbacks)
if self:IsOpen(panelId) then
logger.error("Panel Already Opened", self.m_names[panelId])
return
end
local cfg = self.m_panelConfigs[panelId]
if not cfg then
logger.error("No Panel Config", panelId)
return
end
logger.info("UIManager.Open", self.m_names[panelId])
LuaProfilerUtils.BeginSample("UIManager.Open." .. self.m_names[panelId])
callbacks = callbacks or {}
Notify(MessageConst.ON_BEFORE_UI_PANEL_OPEN, cfg.name)
self:_TryAttachNaviDummyLayer(panelId)
local asset, assetType = self:_LoadPanelAsset(panelId)
local parent = self:_GetPanelParentTransform(cfg)
local panelObj
if UNITY_EDITOR then
panelObj = CSUtils.CreateObject(asset, self.m_disabledPanelRoot)
panelObj.gameObject:SetActive(false)
panelObj.transform:SetParent(parent)
else
asset.gameObject:SetActive(false)
panelObj = CSUtils.CreateObject(asset, parent)
end
panelObj.name = string.format("%sPanel", cfg.name)
local uiCamera = self.uiCamera
local view = {
curPanelCfg = {}
}
if cfg.clearScreen then
local exceptPanelIds = {}
if cfg.clearScreen ~= true then
for _, v in ipairs(cfg.clearScreen) do
table.insert(exceptPanelIds, self.ids[v])
end
end
self.m_autoClearScreenKeys[panelId] = self:ClearScreen(exceptPanelIds)
end
if cfg.blockObtainWaysJump then
self:ToggleBlockObtainWaysJump(cfg.name, true, true)
end
local refs = panelObj:GetComponent("LuaReference")
refs:BindToLua(view)
view.panelCanvas = view.transform:GetComponent("Canvas")
view.canvasScaler = view.transform:GetComponent("CanvasScaler")
view.luaPanel = view.transform:GetComponent("LuaPanel")
view.raycaster = view.transform:GetComponent("GraphicRaycaster")
view.inputGroup = view.transform:GetComponent("InputBindingGroupMonoTarget")
view.selectableNaviGroup = view.transform:GetComponent("UISelectableNaviGroup")
UIUtils.initLuaCustomConfig(view)
view.panelCanvas.worldCamera = self.uiCamera
if not cfg.isWorldUI then
view.panelCanvas.renderMode = CS.UnityEngine.RenderMode.ScreenSpaceCamera
view.panelCanvas.planeDistance = PlaneDistance
self.m_uiCanvasScaleHelper:AddCanvas(view.panelCanvas, view.canvasScaler)
else
view.rectTransform.localScale = Vector3.one
view.rectTransform.pivot = Vector2.one / 2
view.rectTransform.anchorMin = Vector2.zero
view.rectTransform.anchorMax = Vector2.one
view.rectTransform.offsetMin = Vector2.zero
view.rectTransform.offsetMax = Vector2.zero
view.rectTransform.anchoredPosition3D = Vector3.zero
end
view.luaPanel.panelId = panelId
view.luaPanel.panelName = cfg.name
view.luaPanel.uiCamera = uiCamera
view.luaPanel.planeDistance = PlaneDistance
if cfg.orderType then
view.luaPanel.panelLevel = UIConst.PANEL_ORDER_TO_PANEL_LEVEL[cfg.orderType]
end
view.luaPanel.inited = true
CS.Beyond.UI.LuaPanel.s_openedLuaPanels:Add(cfg.name, view.luaPanel)
if not cfg.ctrlClass then
local name = cfg.name
local path = string.format(UIConst.UI_PANEL_CTRL_FILE_PATH, name, name)
local ctrlClass = require_ex(path)[name .. "Ctrl"]
if HL.TryGet(ctrlClass, "s_overrideMessages") then
ctrlClass.s_messages = ctrlClass.s_overrideMessages
else
ctrlClass.s_messages = ctrlClass.s_messages
end
cfg.ctrlClass = ctrlClass
end
local ctrl = cfg.ctrlClass()
ctrl.panelId = panelId
ctrl.panelCfg = cfg
ctrl.model = cfg.modelClass()
ctrl.view = view
ctrl.loader = luaLoader.LuaResourceLoader()
ctrl.animationWrapper = view.luaPanel.animationWrapper
ctrl.naviGroup = view.transform:GetComponent("UISelectableNaviGroup")
ctrl.uiCamera = uiCamera
ctrl.planeDistance = PlaneDistance
ctrl.isControllerPanel = assetType == UIConst.PANEL_ASSET_TYPES.Controller
ctrl.isPCPanel = assetType == UIConst.PANEL_ASSET_TYPES.PC
ctrl.isDefaultPanel = assetType == UIConst.PANEL_ASSET_TYPES.Default
ctrl.m_updateKeys = {}
cfg.ctrl = ctrl
self.m_openedPanels[panelId] = ctrl
Notify(MessageConst.ON_UI_PANEL_START_OPEN, cfg.name)
view.luaPanel.onAnimationInFinished:AddListener(function()
logger.info("OnAnimationInFinished", cfg.name)
ctrl:OnAnimationInFinished()
Notify(MessageConst.ON_UI_PANEL_OPENED, cfg.name)
local needTrigger = view.luaPanel.animationWrapper == nil or view.luaPanel.animationWrapper.curState ~= CS.Beyond.UI.UIConst.AnimationState.Out
if needTrigger then
CS.Beyond.Gameplay.Conditions.OnUIPanelOpen.Trigger(cfg.name, true, PhaseManager:GetTopPhaseName())
if GameInstance.player then
GameInstance.player.guide:OnUIPanelOpened(cfg.name)
end
end
if callbacks.onAnimationInFinished then
callbacks.onAnimationInFinished()
end
self:TryToggleMainCamera(cfg, true)
end)
if cfg.selfMaintainOrder then
self.m_selfMaintainOrderPanels[panelId] = ctrl
else
self:_AutoSetPanelOrder(cfg, true)
end
panelObj.gameObject:SetActive(true)
for msg, funcName in pairs(cfg.ctrlClass.s_messages) do
Register(msg, function(msgArg)
if ctrl.m_isClosed then
logger.info("UIManager 触发面板监听消息,但是面板已经关闭了,所以无视掉", ctrl.panelCfg.name, MessageConst.getMsgName(msg))
return
end
if msgArg == nil then
ctrl[funcName](ctrl)
else
ctrl[funcName](ctrl, msgArg)
end
end, ctrl)
end
local succ, log = xpcall(function()
ctrl.model:InitModel()
ctrl:OnCreate(arg)
ctrl:OnShow()
end, debug.traceback)
if not succ then
logger.critical(log)
end
ctrl.isFinishedCreation = true
if cfg.selfMaintainOrder then
self:CalcOtherSystemPropertyByPanelOrder()
end
self:_SendEventUISwitch(cfg, true)
CS.Beyond.Gameplay.Conditions.OnUIPanelOpen.Trigger(cfg.name, false, PhaseManager:GetTopPhaseName())
LuaProfilerUtils.EndSample()
return ctrl
end
UIManager.PreloadPanelAsset = HL.Method(HL.Number, HL.Any, HL.Opt(HL.Function)) << function(self, panelId, source, onPreloadComplete)
if BEYOND_DEBUG or BEYOND_DEBUG_COMMAND then
logger.info("UIManager.PreloadPanelAsset.", self.m_names[panelId])
end
local info = self.m_customPreloadInfos[source]
if not info then
info = {}
self.m_customPreloadInfos[source] = info
end
info[panelId] = true
LuaProfilerUtils.BeginSample("UIManager.PreloadPanelAsset." .. self.m_names[panelId])
self:_LoadPanelAsset(panelId, true, onPreloadComplete)
LuaProfilerUtils.EndSample()
end
UIManager.PreloadPersistentPanelAsset = HL.Method(HL.Number, HL.Opt(HL.Function)) << function(self, panelId, onPreloadComplete)
self:PreloadPanelAsset(panelId, "Persistent", onPreloadComplete)
end
UIManager.ClearPreloadAsset = HL.Method(HL.Any) << function(self, source)
local info = self.m_customPreloadInfos[source]
if not info then
return
end
logger.info("UIManager.ClearPreloadAsset", source)
for panelId, _ in pairs(info) do
if not self:IsOpen(panelId) then
local assetInfo = self.m_panel2Handle[panelId]
if assetInfo then
self.m_panel2Handle[panelId] = nil
self.m_resourceLoader:DisposeHandleByKey(assetInfo[1])
logger.info("UIManager.ClearPreloadAsset DisposeHandleByKey", panelId, self.m_names[panelId])
end
end
end
end
UIManager.CheckPanelAssetHadLoaded = HL.Method(HL.Number).Return(HL.Boolean) << function(self, panelId)
local assetInfo = self.m_panel2Handle[panelId]
return assetInfo ~= nil
end
UIManager._LoadPanelAsset = HL.Method(HL.Number, HL.Opt(HL.Boolean, HL.Function)).Return(HL.Opt(GameObject, HL.Number)) << function(self, panelId, isPreload, onPreloadComplete)
logger.info("UIManager._LoadPanelAsset", panelId, self.m_names[panelId], isPreload)
self:_UpdatePanelAssetLRU(panelId, true)
local asset
local assetType = UIConst.PANEL_ASSET_TYPES.Default
local assetInfo = self.m_panel2Handle[panelId]
if not assetInfo then
local cfg = self.m_panelConfigs[panelId]
local path
if DeviceInfo.usingController then
local ctPath = string.format(UIConst.UI_CONTROLLER_PANEL_PREFAB_PATH, cfg.folder, cfg.name)
if BEYOND_DEBUG or BEYOND_DEBUG_COMMAND then
if not ResourceManager.CheckExists(ctPath) then
ctPath = string.format(UIConst.UI_CONTROLLER_PANEL_PREFAB_DEV_PATH, cfg.folder, cfg.name)
end
end
if ResourceManager.CheckExists(ctPath) then
assetType = UIConst.PANEL_ASSET_TYPES.Controller
path = ctPath
end
end
if not path and (DeviceInfo.isPCorConsole or DeviceInfo.usingController) then
local pcPath = string.format(UIConst.UI_PC_PANEL_PREFAB_PATH, cfg.folder, cfg.name)
if BEYOND_DEBUG or BEYOND_DEBUG_COMMAND then
if not ResourceManager.CheckExists(pcPath) then
pcPath = string.format(UIConst.UI_PC_PANEL_PREFAB_DEV_PATH, cfg.folder, cfg.name)
end
end
if ResourceManager.CheckExists(pcPath) then
assetType = UIConst.PANEL_ASSET_TYPES.PC
path = pcPath
end
end
if not path then
path = string.format(UIConst.UI_PANEL_PREFAB_PATH, cfg.folder, cfg.name)
if BEYOND_DEBUG or BEYOND_DEBUG_COMMAND then
if not ResourceManager.CheckExists(path) then
path = string.format(UIConst.UI_PANEL_PREFAB_DEV_PATH, cfg.folder, cfg.name)
end
end
end
if not isPreload then
local assetKey
if not self.m_panel2Handle[panelId] then
asset, assetKey = self.m_resourceLoader:LoadI18NAsset(path, typeof(CS.UnityEngine.GameObject))
self.m_panel2Handle[panelId] = { assetKey, assetType }
end
else
local assetKey
assetKey = self.m_resourceLoader:LoadGameObjectAsync(path, function(loadedAsset)
if not assetKey then
logger.error("预加载面板时异步调用同步返回了", path)
return
end
if self.m_panel2Handle[panelId] then
self.m_resourceLoader:DisposeHandleByKey(assetKey)
else
self.m_panel2Handle[panelId] = { assetKey, assetType }
end
if onPreloadComplete then
onPreloadComplete()
end
end)
return
end
else
if isPreload then
if onPreloadComplete then
onPreloadComplete()
end
return
end
local assetKey = assetInfo[1]
assetType = assetInfo[2]
asset = self.m_resourceLoader:GetGameObjectByKey(assetKey)
end
return asset, assetType
end
UIManager.TryToggleMainCamera = HL.Method(HL.Table, HL.Boolean) << function(self, cfg, tryCloseCamera)
if (not cfg) or (not cfg.hideCamera) then
return
end
if tryCloseCamera then
self.m_showingFullScreenPanel[cfg] = true
else
self.m_showingFullScreenPanel[cfg] = nil
end
local shouldClose = next(self.m_showingFullScreenPanel) ~= nil
if shouldClose == self.m_mainCameraClosedByUI then
return
end
if tryCloseCamera then
CameraManager:AddMainCamCullingMaskConfig("UIManager", UIConst.LAYERS.Nothing)
else
CameraManager:RemoveMainCamCullingMaskConfig("UIManager")
end
self.m_mainCameraClosedByUI = tryCloseCamera
end
UIManager._CheckCanCloseCamera = HL.Method().Return(HL.Boolean) << function(self)
for i, openedPanel in pairs(self.m_openedPanels) do
if self:IsShow(openedPanel.panelId) and openedPanel.panelCfg.hideCamera then
return true
end
end
return false
end
local defaultNoEventOrderTypes = {
[Types.EPanelOrderTypes.Hud] = true,
[Types.EPanelOrderTypes.LowerHud] = true,
[Types.EPanelOrderTypes.BottomScreenEffect] = true,
[Types.EPanelOrderTypes.TopScreenEffect] = true,
[Types.EPanelOrderTypes.Toast] = true,
[Types.EPanelOrderTypes.Debug] = true,
}
UIManager._SendEventUISwitch = HL.Method(HL.Table, HL.Boolean) << function(self, cfg, isEnter)
return
end
UIManager.AutoOpen = HL.Method(HL.Number, HL.Opt(HL.Any, HL.Boolean, HL.Function)).Return(HL.Opt(HL.Forward("UICtrl")))
<< function(self, panelId, arg, forceShow, onShowCallback)
local isOpen, ctrl = self:IsOpen(panelId)
if not isOpen then
return self:Open(panelId, arg)
else
if forceShow or self:IsHide(panelId) then
self:Show(panelId)
end
if onShowCallback then
onShowCallback(ctrl)
end
return ctrl
end
end
UIManager.IsOpen = HL.Method(HL.Number).Return(HL.Boolean, HL.Opt(HL.Forward("UICtrl"))) << function(self, panelId)
local ctrl = self.m_openedPanels[panelId]
return ctrl ~= nil and not ctrl.m_isClosed, ctrl
end
UIManager.Close = HL.Method(HL.Number) << function(self, panelId)
if not self:IsOpen(panelId) then
return
end
local cfg = self.m_panelConfigs[panelId]
local ctrl = cfg.ctrl
CS.Beyond.UI.LuaPanel.s_openedLuaPanels:Remove(cfg.name)
cfg.ctrl = nil
self.m_openedPanels[panelId] = nil
self.m_hidedPanels[panelId] = nil
self.m_waitClearPanels[panelId] = nil
local hideByOthers = self.m_clearedPanelReverseInfos[panelId]
if hideByOthers then
for k, _ in pairs(hideByOthers) do
local panels = self.m_clearedPanelInfos[k]
if panels then
panels[panelId] = nil
end
end
self.m_clearedPanelReverseInfos[panelId] = nil
end
if cfg.selfMaintainOrder then
self.m_selfMaintainOrderPanels[panelId] = nil
else
self:_RemoveFromOrderStack(panelId)
end
logger.info("UIManager.Close", self.m_names[panelId])
LuaProfilerUtils.BeginSample("UIManager.Close." .. cfg.name)
local clearScreenKey = self.m_autoClearScreenKeys[panelId]
self.m_autoClearScreenKeys[panelId] = nil
if not cfg.isWorldUI then
self.m_uiCanvasScaleHelper:RemoveCanvas(ctrl.view.panelCanvas, ctrl.view.canvasScaler)
end
MessageManager:UnregisterAll(ctrl)
local succ, log = xpcall(function()
ctrl:OnClose()
ctrl:Clear()
ctrl.model:OnClose()
end, debug.traceback)
if not succ then
logger.critical(log)
end
local gameObject = ctrl.view.gameObject
local loader = ctrl.loader
CSUtils.ClearUIComponents(gameObject)
ctrl.view.luaPanel.onAnimationInFinished:RemoveAllListeners()
ctrl.view.inputGroup:DeleteGroup()
GameObject.DestroyImmediate(gameObject)
if ENABLE_LUA_LEAK_CHECK then
LuaObjectMemoryLeakChecker:AddDetectLuaObject(ctrl)
end
loader:DisposeAllHandles()
if not cfg.isResidentPanel then
self:_UpdatePanelAssetLRU(panelId, false)
end
if clearScreenKey then
self:RecoverScreen(clearScreenKey)
end
self:CalcOtherSystemPropertyByPanelOrder()
if cfg.blockObtainWaysJump then
self:ToggleBlockObtainWaysJump(cfg.name, false)
end
Notify(MessageConst.ON_UI_PANEL_CLOSED, cfg.name)
CS.Beyond.Gameplay.Conditions.OnUIPanelClose.Trigger(cfg.name)
self:_TryDetachNaviDummyLayer(panelId)
self:_SendEventUISwitch(cfg, false)
self:TryToggleMainCamera(cfg, false)
LuaProfilerUtils.EndSample()
end
UIManager.Show = HL.Method(HL.Number) << function(self, panelId)
if not self:IsOpen(panelId) then
logger.error("Panel Not Open", panelId, self.m_names[panelId])
return
end
if not self.m_hidedPanels[panelId] then
return
end
LuaProfilerUtils.BeginSample("UIManager.Show." .. self.m_names[panelId])
local hideByOthers = self.m_clearedPanelReverseInfos[panelId] ~= nil
self.m_hidedPanels[panelId] = nil
if not hideByOthers then
self:_InternalShow(panelId)
end
LuaProfilerUtils.EndSample()
end
UIManager._InternalShow = HL.Method(HL.Number) << function(self, panelId)
local ctrl = self.m_openedPanels[panelId]
if ctrl == nil then
return
end
if ctrl.panelCfg.useCanvasHide then
ctrl.view.gameObject:SetLayerRecursive(UIConst.UI_LAYER)
ctrl.view.panelCanvas.enabled = true
if ctrl.animationWrapper then
ctrl.animationWrapper.enabled = true
if ctrl.animationWrapper.autoPlay then
ctrl.animationWrapper:PlayInAnimation()
end
end
else
ctrl.view.gameObject:SetActive(true)
end
if IsNull(ctrl.view.gameObject) then
logger.error("UIManager._InternalShow 面板GO已被错误销毁", ctrl.panelCfg.name)
return
end
self:_TryAttachNaviDummyLayer(panelId)
self:CalcOtherSystemPropertyByPanelOrder()
if ctrl.panelCfg.blockObtainWaysJump then
self:ToggleBlockObtainWaysJump(ctrl.panelCfg.name, true, true)
end
ctrl.view.luaPanel:RecoverAllInput()
ctrl:SetGameObjectVisible(true)
ctrl:OnShow()
Notify(MessageConst.ON_UI_PANEL_SHOW, ctrl.panelCfg.name)
self:_SendEventUISwitch(ctrl.panelCfg, true)
CS.Beyond.Gameplay.Conditions.OnUIPanelOpen.Trigger(ctrl.panelCfg.name, false, PhaseManager:GetTopPhaseName())
end
UIManager.IsShow = HL.Method(HL.Number, HL.Opt(HL.Boolean)).Return(HL.Boolean) << function(self, panelId, ignoreClear)
return self:IsOpen(panelId) and not self.m_hidedPanels[panelId] and (ignoreClear or not self.m_clearedPanelReverseInfos[panelId])
end
UIManager.Hide = HL.Method(HL.Number) << function(self, panelId)
if not self:IsOpen(panelId) then
return
end
if self.m_hidedPanels[panelId] then
return
end
self.m_hidedPanels[panelId] = true
if not self.m_clearedPanelReverseInfos[panelId] then
self:_InternalHide(panelId)
end
end
UIManager.HideWithKey = HL.Method(HL.Number, HL.String) << function(self, panelId, key)
if not self:IsOpen(panelId) then
return
end
local isShow = self:IsShow(panelId)
local clearedPanelIds = self.m_clearedPanelInfos[key]
if not clearedPanelIds then
clearedPanelIds = {}
self.m_clearedPanelInfos[key] = clearedPanelIds
end
local clearedByOthers = self.m_clearedPanelReverseInfos[panelId]
if not clearedByOthers then
clearedByOthers = {}
self.m_clearedPanelReverseInfos[panelId] = clearedByOthers
end
clearedPanelIds[panelId] = true
clearedByOthers[key] = true
if isShow then
self:_InternalHide(panelId)
end
end
UIManager.ShowWithKey = HL.Method(HL.Number, HL.String) << function(self, panelId, key)
if not self:IsOpen(panelId) or self:IsShow(panelId) then
return
end
local clearedPanelIds = self.m_clearedPanelInfos[key]
if not clearedPanelIds then
return
end
clearedPanelIds[panelId] = nil
if not next(clearedPanelIds) then
self.m_clearedPanelInfos[key] = nil
end
local clearedByOthers = self.m_clearedPanelReverseInfos[panelId]
if clearedByOthers then
clearedByOthers[key] = nil
if not next(clearedByOthers) then
self.m_clearedPanelReverseInfos[panelId] = nil
end
end
if self:IsShow(panelId) then
self:_InternalShow(panelId)
end
end
UIManager._InternalHide = HL.Method(HL.Number) << function(self, panelId)
local ctrl = self.m_openedPanels[panelId]
if ctrl == nil then
return
end
local cfg = ctrl.panelCfg
ctrl:OnHide()
Notify(MessageConst.ON_UI_PANEL_HIDE, ctrl.panelCfg.name)
ctrl:SetGameObjectVisible(false)
if cfg.useCanvasHide then
ctrl.view.gameObject:SetLayerRecursive(UIConst.HIDE_LAYER)
ctrl.view.panelCanvas.enabled = false
ctrl.view.luaPanel:BlockAllInput()
if ctrl.animationWrapper then
ctrl.animationWrapper.enabled = false
end
else
ctrl.view.gameObject:SetActive(false)
end
if IsNull(ctrl.view.gameObject) then
logger.error("UIManager._InternalHide 面板GO已被错误销毁", ctrl.panelCfg.name)
return
end
self:_TryDetachNaviDummyLayer(panelId)
self:CalcOtherSystemPropertyByPanelOrder()
if cfg.blockObtainWaysJump then
self:ToggleBlockObtainWaysJump(cfg.name, false)
end
self:_SendEventUISwitch(ctrl.panelCfg, false)
self:TryToggleMainCamera(cfg, false)
CS.Beyond.Gameplay.Conditions.OnUIPanelClose.Trigger(cfg.name)
end
UIManager.IsHide = HL.Method(HL.Number).Return(HL.Boolean) << function(self, panelId)
return self:IsOpen(panelId) and not self:IsShow(panelId)
end
UIManager.IsInternalHidden = HL.Method(HL.Number).Return(HL.Boolean) << function(self, panelId)
local ctrl = self.m_openedPanels[panelId]
if ctrl == nil then
return false
end
local cfg = ctrl.panelCfg
if cfg.useCanvasHide then
return not ctrl.view.panelCanvas.enabled
else
return not ctrl.view.gameObject.activeSelf
end
end
UIManager.ClearScreen = HL.Method(HL.Opt(HL.Table)).Return(HL.Opt(HL.Number)) << function(self, exceptPanelIds)
if self.m_inClearScreen then
logger.error("清屏中,不能额外操作")
return
end
local clearScreenKey, panelIds = self:_GetClearScreenTargets(exceptPanelIds)
self.m_ignoreBlockOrderUpdate = true
for _, id in ipairs(panelIds) do
self:_InternalHide(id)
end
self.m_ignoreBlockOrderUpdate = false
self:CalcOtherSystemPropertyByPanelOrder()
logger.info("UIManager.ClearScreen", clearScreenKey)
return clearScreenKey
end
UIManager._GetClearScreenTargets = HL.Method(HL.Opt(HL.Table)).Return(HL.Number, HL.Table) << function(self, exceptPanelIds)
local clearedPanels = {}
local clearScreenKey = self.m_nextClearScreenKey
self.m_nextClearScreenKey = self.m_nextClearScreenKey + 1
self.m_clearedPanelInfos[clearScreenKey] = clearedPanels
local panelIds = {}
for id, ctrl in pairs(self.m_openedPanels) do
if not exceptPanelIds or not lume.find(exceptPanelIds, id) then
if ctrl:GetCurPanelCfg("clearedPanel") then
local isShowing = self:IsShow(id)
clearedPanels[id] = true
local clearedByOthers = self.m_clearedPanelReverseInfos[id]
if not clearedByOthers then
clearedByOthers = {}
self.m_clearedPanelReverseInfos[id] = clearedByOthers
end
clearedByOthers[clearScreenKey] = true
if isShowing then
table.insert(panelIds, id)
end
end
end
end
return clearScreenKey, panelIds
end
UIManager.m_inClearScreen = HL.Field(HL.Boolean) << false
UIManager.m_curClearScreenKey = HL.Field(HL.Number) << -1
UIManager.m_waitClearPanels = HL.Field(HL.Table)
UIManager.ClearScreenWithOutAnimation = HL.Method(HL.Function, HL.Opt(HL.Table)) << function(self, callback, exceptPanelIds)
if self.m_inClearScreen then
logger.error("清屏中,不能额外操作")
callback()
return
end
self.m_inClearScreen = true
local clearScreenKey, panelIds = self:_GetClearScreenTargets(exceptPanelIds)
self.m_curClearScreenKey = clearScreenKey
logger.info("UIManager.ClearScreenWithOutAnimation", clearScreenKey)
self.m_ignoreBlockOrderUpdate = true
local count = #panelIds
if count == 0 then
TimerManager:StartTimer(0, function()
self.m_ignoreBlockOrderUpdate = false
self:CalcOtherSystemPropertyByPanelOrder()
self.m_inClearScreen = false
self.m_curClearScreenKey = -1
callback(clearScreenKey)
end, true, self)
return
end
self.m_waitClearPanels = {}
for _, v in ipairs(panelIds) do
local panelId = v
local uiCtrl = self.m_openedPanels[panelId]
if uiCtrl ~= nil and not uiCtrl:IsPlayingAnimationOut() then
self.m_waitClearPanels[panelId] = true
uiCtrl:PlayAnimationOutWithCallback(function()
self:_InternalHide(panelId)
self.m_waitClearPanels[panelId] = nil
end)
end
end
CoroutineManager:StartCoroutine(function()
while true do
coroutine.step()
local allDone = true
for _, v in ipairs(panelIds) do
local panelId = v
local ctrl = self.m_openedPanels[panelId]
if ctrl ~= nil and ctrl.view.gameObject.activeSelf and not self:IsInternalHidden(panelId) and self.m_waitClearPanels[panelId] then
allDone = false
break
end
end
if allDone then
self.m_ignoreBlockOrderUpdate = false
self:CalcOtherSystemPropertyByPanelOrder()
self.m_inClearScreen = false
self.m_curClearScreenKey = -1
callback(clearScreenKey)
break
end
end
end, self)
end
UIManager.RecoverScreen = HL.Method(HL.Number).Return(HL.Opt(HL.Number)) << function(self, clearScreenKey)
if self.m_inClearScreen then
if clearScreenKey == self.m_curClearScreenKey then
logger.error("清屏中不能RecoverScreen自己应该是时序有问题")
return -1
end
end
if self.m_cachedRecoverScreenKeys then
table.insert(self.m_cachedRecoverScreenKeys, clearScreenKey)
return -1
end
local clearedPanels = self.m_clearedPanelInfos[clearScreenKey]
if not clearedPanels then
return -1
end
self.m_clearedPanelInfos[clearScreenKey] = nil
self.m_ignoreBlockOrderUpdate = true
for id, _ in pairs(clearedPanels) do
local clearedByOthers = self.m_clearedPanelReverseInfos[id]
if clearedByOthers then
clearedByOthers[clearScreenKey] = nil
if not next(clearedByOthers) then
self.m_clearedPanelReverseInfos[id] = nil
end
if self:IsShow(id) then
self:_InternalShow(id)
end
end
end
self.m_ignoreBlockOrderUpdate = false
self:CalcOtherSystemPropertyByPanelOrder()
logger.info("UIManager.RecoverScreen", clearScreenKey)
return -1
end
UIManager._InitOrderManagers = HL.Method() << function(self)
local stackClass = require_ex("Common/Utils/DataStructure/Stack")
for _, v in pairs(Types.EPanelOrderTypes) do
local manager = {}
manager.stack = stackClass()
manager.initOrder = v * self.m_panelOrderTypeInterval
manager.maxOrder = manager.initOrder + self.m_panelOrderTypeInterval - self.m_panelOrderInterval
manager.nextPanelOrder = manager.initOrder
self.m_orderManagers[v] = manager
end
end
UIManager.GetBaseOrder = HL.Method(HL.Number).Return(HL.Number) << function(self, orderType)
return orderType * self.m_panelOrderTypeInterval
end
UIManager._AutoSetPanelOrder = HL.Method(HL.Table, HL.Boolean) << function(self, cfg, isInit)
isInit = isInit == true
local orderType = cfg.orderType
local manager = self.m_orderManagers[orderType]
if not manager then
logger.error("No Order Manager", orderType, inspect(cfg))
return
end
local stack = manager.stack
local recalculated = false
if manager.nextPanelOrder > manager.maxOrder then
logger.warn("动态面板层级超出区间,开始重新计算层级", orderType, manager.nextPanelOrder, manager.maxOrder)
recalculated = true
manager.nextPanelOrder = manager.initOrder
if stack:Count() > 0 then
for i = stack:BottomIndex(), stack:TopIndex() do
local id = stack:Get(i)
self.m_openedPanels[id]:SetSortingOrder(manager.nextPanelOrder, isInit)
manager.nextPanelOrder = manager.nextPanelOrder + self.m_panelOrderInterval
end
end
end
if manager.nextPanelOrder > manager.maxOrder then
logger.error("动态面板层级超出区间", orderType, manager.nextPanelOrder, manager.maxOrder, inspect(stack))
end
cfg.ctrl:SetSortingOrder(manager.nextPanelOrder, isInit)
manager.nextPanelOrder = manager.nextPanelOrder + self.m_panelOrderInterval
stack:Push(cfg.id)
self:CalcOtherSystemPropertyByPanelOrder()
if recalculated then
Notify(MessageConst.ON_PANEL_ORDER_RECALCULATED)
end
end
UIManager._RemoveFromOrderStack = HL.Method(HL.Number) << function(self, panelId)
local cfg = self.m_panelConfigs[panelId]
if cfg.selfMaintainOrder then
return
end
local manager = self.m_orderManagers[cfg.orderType]
local stack = manager.stack
if stack:Peek() == panelId then
manager.nextPanelOrder = manager.nextPanelOrder - self.m_panelOrderInterval
end
stack:Delete(panelId)
end
UIManager.SetTopOrder = HL.Method(HL.Number) << function(self, panelId)
if not self:IsOpen(panelId) then
logger.error("Panel Not Open", panelId)
return
end
local cfg = self.m_panelConfigs[panelId]
if cfg.selfMaintainOrder then
logger.error("Panel is selfMaintainOrder, can't SetTopOrder")
end
self:_RemoveFromOrderStack(panelId)
self:_AutoSetPanelOrder(cfg, false)
end
UIManager.CalcOtherSystemPropertyByPanelOrder = HL.Method() << function(self)
if self.m_ignoreBlockOrderUpdate or self.m_isClosingAll then
return
end
self.m_curBlockKeyboardEventPanelOrder = self:_FindTopPanelProperty(function(cfg, ctrl)
if ctrl:GetBlockKeyboardEvent() then
return ctrl:GetSortingOrder()
end
end) or -1
for _, type in pairs(Types.EPanelOrderTypes) do
local manager = self.m_orderManagers[type]
local stack = manager.stack
if stack:Count() > 0 then
local topIndex, bottomIndex = stack:TopIndex(), stack:BottomIndex()
local updatePanelList = {}
for i = bottomIndex, topIndex do
updatePanelList[i] = stack:Get(i)
end
for _, panelId in ipairs(updatePanelList) do
local ctrl = self.m_openedPanels[panelId]
ctrl:UpdateInputGroupState()
end
end
end
for _, ctrl in pairs(self.m_selfMaintainOrderPanels) do
ctrl:UpdateInputGroupState()
end
local multiTouchType, topPanelOrder, targetCtrl = self:_FindTopPanelProperty(function(cfg, ctrl)
local t = ctrl:GetMultiTouchType()
if t and t ~= Types.EPanelMultiTouchTypes.Both then
return t
end
end) or Types.EPanelMultiTouchTypes.Enable
if multiTouchType ~= Types.EPanelMultiTouchTypes.Both then
local enable = multiTouchType == Types.EPanelMultiTouchTypes.Enable
if InputManager.multiTouchEnabled ~= enable then
InputManager.multiTouchEnabled = enable
end
end
local cursorCfgName = DeviceInfo.usingController and "virtualMouseMode" or "realMouseMode"
local cursorMode = self:_FindTopPanelProperty(function(cfg, ctrl)
local mode = ctrl:GetCurPanelCfg(cursorCfgName)
if mode ~= Types.EPanelMouseMode.NotNeedShow then
return mode
end
end) or Types.EPanelMouseMode.NotNeedShow
InputManagerInst:ToggleCursorInHideCursorMode("blocked", cursorMode == Types.EPanelMouseMode.NeedShow)
self:_ToggleAutoShowCursor(cursorMode == Types.EPanelMouseMode.AutoShow)
if InputManagerInst.virtualMouse then
if cursorMode == Types.EPanelMouseMode.NotNeedShow then
InputManagerInst.virtualMouse.keepMousePosOnEnable = false
elseif cursorMode == Types.EPanelMouseMode.ForceHide then
InputManagerInst.virtualMouse.keepMousePosOnEnable = true
end
end
local gyroscopeEffectType = self:_FindTopPanelProperty(function(cfg, ctrl)
local t = ctrl:GetCurPanelCfg("gyroscopeEffect")
if t and t ~= Types.EPanelGyroscopeEffect.Both then
return t
end
end) or Types.EPanelGyroscopeEffect.Enable
if gyroscopeEffectType ~= Types.EPanelGyroscopeEffect.Both then
local enable = gyroscopeEffectType == Types.EPanelGyroscopeEffect.Enable
self.gyroscopeEffect.enableDetect = enable
end
Notify(MessageConst.ON_BLOCK_KEYBOARD_EVENT_PANEL_ORDER_CHANGED)
end
UIManager.CurBlockKeyboardEventPanelOrder = HL.Method().Return(HL.Number) << function(self)
return self.m_curBlockKeyboardEventPanelOrder
end
UIManager.GetPanelOrder = HL.Method(HL.Number).Return(HL.Opt(HL.Number)) << function(self, panelId)
local ctrl = self.m_openedPanels[panelId]
if not ctrl then
return
end
return ctrl:GetSortingOrder()
end
UIManager._FindTopPanelProperty = HL.Method(HL.Function).Return(HL.Opt(HL.Any, HL.Number, HL.Forward("UICtrl"))) << function(self, checkFunc)
local topPanelOrder, result, targetCtrl = -1, nil, nil
for type = Types.MaxPanelOrderType, 1, -1 do
local manager = self.m_orderManagers[type]
local stack = manager.stack
if stack:Count() > 0 then
local topIndex, bottomIndex = stack:TopIndex(), stack:BottomIndex()
for i = topIndex, bottomIndex, -1 do
local id = stack:Get(i)
if self:IsShow(id) then
local cfg = self.m_panelConfigs[id]
local ctrl = cfg.ctrl
local value = checkFunc(cfg, ctrl)
if value ~= nil then
topPanelOrder = ctrl:GetSortingOrder()
result = value
targetCtrl = ctrl
break
end
end
end
end
if result then
break
end
end
for id, ctrl in pairs(self.m_selfMaintainOrderPanels) do
if self:IsShow(id) then
local cfg = self.m_panelConfigs[id]
local value = checkFunc(cfg, ctrl)
local order = ctrl:GetSortingOrder()
if value ~= nil and order > topPanelOrder then
topPanelOrder = order
result = value
targetCtrl = ctrl
end
end
end
return result, topPanelOrder, targetCtrl
end
UIManager.m_isClosingAll = HL.Field(HL.Boolean) << false
UIManager.m_cachedRecoverScreenKeys = HL.Field(HL.Table)
UIManager.StartCacheRecoverScreen = HL.Method() << function(self)
if self.m_cachedRecoverScreenKeys then
return
end
logger.info("UIManager.StartCacheRecoverScreen")
self.m_cachedRecoverScreenKeys = {}
end
UIManager.EndCacheRecoverScreen = HL.Method() << function(self)
if not self.m_cachedRecoverScreenKeys then
return
end
local keys = self.m_cachedRecoverScreenKeys
self.m_cachedRecoverScreenKeys = nil
logger.info("UIManager.EndCacheRecoverScreen", keys)
for _, key in ipairs(keys) do
self:RecoverScreen(key)
end
end
UIManager._CloseAllUI = HL.Method(HL.Boolean, HL.Opt(HL.Table)) << function(self, isChangeScene, exceptPanelIds)
local exceptPanelIdMap = {}
if exceptPanelIds then
for _, id in ipairs(exceptPanelIds) do
exceptPanelIdMap[id] = true
end
end
self:_RealCloseAllUI(function(k, v)
return self:IsOpen(k) and not exceptPanelIdMap[k] and (not isChangeScene or v.closeWhenChangeScene)
end)
end
UIManager._RealCloseAllUI = HL.Method(HL.Function) << function(self, checkCanClose)
self.m_isClosingAll = true
self:StartCacheRecoverScreen()
for k, v in pairs(self.m_panelConfigs) do
if checkCanClose(k, v) then
local succ, log = xpcall(self.Close, debug.traceback, self, k)
if not succ then
logger.critical("_CloseAllUI Fail", v.name, log)
end
end
end
self.m_isClosingAll = false
self:CalcOtherSystemPropertyByPanelOrder()
self:EndCacheRecoverScreen()
self:ReleaseCachedPanelAsset()
end
UIManager._CloseAllUIForSwitchLanguage = HL.Method() << function(self)
self:_RealCloseAllUI(function(k, v)
return self:IsOpen(k) and not v.preserveWhenChangeLanguage
end)
end
UIManager.CloseAllUI = HL.Method(HL.Boolean, HL.Opt(HL.Table)) << function(self, isChangeScene, exceptPanelIds)
self:_CloseAllUI(isChangeScene, exceptPanelIds)
end
UIManager.SetUICameraFOV = HL.Method(HL.Number) << function(self, fov)
if self.uiCamera then
self.m_currentStandardFOV = fov
local referenceAspect = CS.Beyond.UI.UIConst.STANDARD_RATIO
local currentAspect = Screen.width / Screen.height;
if currentAspect < referenceAspect then
local hFOV = Unity.Camera.VerticalToHorizontalFieldOfView(fov, referenceAspect);
local vFOV = Unity.Camera.HorizontalToVerticalFieldOfView(hFOV, currentAspect);
fov = vFOV;
end
self.uiCamera.fieldOfView = fov
self.m_worldUICanvasScaleHelper:UpdateCanvas()
end
end
UIManager.GetUICameraFOV = HL.Method().Return(HL.Number) << function(self)
if self.uiCamera then
return self.uiCamera.fieldOfView
else
return -1
end
end
UIManager.m_rootInfos = HL.Field(HL.Table)
UIManager.m_panel2RootDic = HL.Field(HL.Table)
UIManager._InitRoots = HL.Method() << function(self)
self.m_rootInfos = {}
self.m_panel2RootDic = {}
for name, cfg in pairs(rootConfig.config) do
local info = {
name = name,
cfg = cfg,
}
local assetPath = string.format(UIConst.UI_ROOT_PREFAB_PATH, cfg.folder, name)
local asset = self.m_resourceLoader:LoadGameObject(assetPath)
local rootObj = CSUtils.CreateObject(asset, self.uiRoot)
rootObj.name = string.format("%sRoot", name)
info.gameObject = rootObj
info.transform = rootObj.transform
info.luaUIRoot = rootObj:GetComponent("LuaUIRoot")
info.rectTransform = rootObj:GetComponent("RectTransform")
info.rectTransform.localScale = Vector3.one
info.rectTransform.pivot = Vector2.one / 2
info.rectTransform.anchorMin = Vector2.zero
info.rectTransform.anchorMax = Vector2.one
info.rectTransform.offsetMin = Vector2.zero
info.rectTransform.offsetMax = Vector2.zero
self.m_rootInfos[name] = info
for panelName, _ in pairs(info.luaUIRoot.nodeDic.data) do
if self.m_panel2RootDic[panelName] then
logger.error("面板已经被其他Root使用", panelName, self.m_panel2RootDic[panelName].name)
else
self.m_panel2RootDic[panelName] = info
end
end
end
end
UIManager._GetPanelParentTransform = HL.Method(HL.Table).Return(Transform) << function(self, panelCfg)
if panelCfg.isWorldUI then
return self.worldUIRoot
end
local name = panelCfg.name
local rootInfo = self.m_panel2RootDic[name]
if rootInfo then
return rootInfo.luaUIRoot.nodeDic:get_Item(name).transform
end
return self.uiRoot
end
UIManager.Dispose = HL.Method() << function(self)
CS.Beyond.UI.LuaPanel.s_openedLuaPanels:Clear()
self.m_worldUICanvasScaleHelper.onScreenSizeChanged:RemoveListener(self.m_onScreenSizeChangedCallback)
TimerManager:ClearAllTimer(self)
self:_CloseAllUI(false)
self:OnToggleUiAction({ true })
InputManagerInst:DeleteGroup(self.persistentInputBindingKey)
if self.uiNode ~= nil then
GameObject.DestroyImmediate(self.uiNode.gameObject)
self.uiNode = nil
end
if self.worldObjectRoot ~= nil then
GameObject.DestroyImmediate(self.worldObjectRoot.gameObject)
self.worldObjectRoot = nil
end
self.m_resourceLoader:DisposeAllHandles()
if CS.TMPro.TMP_Settings.instance.dynamicFontAssetLoader ~= nil then
CS.TMPro.TMP_Settings.instance.dynamicFontAssetLoader:Dispose()
CS.TMPro.TMP_Settings.instance.dynamicFontAssetLoader = nil
end
CS.Beyond.UI.LuaPanel.s_openedLuaPanels:Clear()
end
UIManager._ToggleUIInputBinding = HL.Method(HL.Boolean, HL.String) << function(self, active, key)
if not active and key == "AirWall" and (self:IsOpen(PanelId.ShopMonthlyPassPopUp) or PhaseManager:IsOpen(PhaseId.ActivityPopup)) then
logger.error("防止卡死,取消 UIManager._ToggleUIInputBinding", key)
return
end
if active then
self.m_blockInputKeys[key] = nil
else
self.m_blockInputKeys[key] = true
end
local rst = next(self.m_blockInputKeys) == nil
InputManagerInst:ToggleGroup(self.uiInputBindingGroupMonoTarget.groupId, rst)
logger.info("UIManager._ToggleUIInputBinding", active, key, "CUR RESULT", rst)
end
UIManager.m_autoShowCursorCor = HL.Field(HL.Thread)
UIManager._ToggleAutoShowCursor = HL.Method(HL.Boolean) << function(self, active)
if not active then
if self.m_autoShowCursorCor then
logger.info("UIManager._ToggleAutoShowCursor AutoShowCursor", false)
InputManagerInst:ToggleCursorInHideCursorMode("AutoShowCursor", false)
CoroutineManager:ClearCoroutine(self.m_autoShowCursorCor)
self.m_autoShowCursorCor = nil
end
return
end
if self.m_autoShowCursorCor then
return
end
local nextHideTime
self.m_autoShowCursorCor = CoroutineManager:StartCoroutine(function()
while true do
coroutine.step()
local needShow = Input.anyKeyDown
if needShow then
logger.info("UIManager._ToggleAutoShowCursor AutoShowCursor", true)
InputManagerInst:ToggleCursorInHideCursorMode("AutoShowCursor", true)
nextHideTime = Time.unscaledTime + 5
else
if nextHideTime and Time.unscaledTime >= nextHideTime then
logger.info("UIManager._ToggleAutoShowCursor AutoShowCursor", false)
InputManagerInst:ToggleCursorInHideCursorMode("AutoShowCursor", false)
nextHideTime = nil
end
end
end
end, self)
end
UIManager.m_blockObtainWaysJumpKeys = HL.Field(HL.Table)
UIManager.ToggleBlockObtainWaysJump = HL.Method(HL.String, HL.Boolean, HL.Opt(HL.Boolean)) << function(self, name, shouldBlock, blockAllPhase)
if shouldBlock then
self.m_blockObtainWaysJumpKeys[name] = blockAllPhase == true
else
self.m_blockObtainWaysJumpKeys[name] = nil
end
end
UIManager.ShouldBlockObtainWaysJump = HL.Method().Return(HL.Boolean) << function(self)
return next(self.m_blockObtainWaysJumpKeys) ~= nil
end
UIManager.ShouldBlockAllObtainWaysJump = HL.Method().Return(HL.Boolean) << function(self)
for _, v in pairs(self.m_blockObtainWaysJumpKeys) do
if v == true then
return true
end
end
return false
end
UIManager.GetOpenedPanels = HL.Method().Return(HL.Number) << function(self)
local count = 0
for _, __ in pairs(self.m_openedPanels) do
count = count + 1
end
return count
end
UIManager.GetHidedPanels = HL.Method().Return(HL.Number) << function(self)
local count = 0
for _, __ in pairs(self.m_hidedPanels) do
count = count + 1
end
return count
end
UIManager.IsInFullScreenUI = HL.Method().Return(HL.Boolean) << function(self)
for id, ctrl in pairs(self.m_openedPanels) do
if self:IsShow(id) then
if ctrl:GetCurPanelCfg("hideCamera") then
return true
end
end
end
return false
end
UIManager.m_recentClosedPanelIds = HL.Field(HL.Table)
UIManager.m_panelAssetLRUCapacity = HL.Field(HL.Number) << 5
UIManager._UpdatePanelAssetLRU = HL.Method(HL.Number, HL.Boolean) << function(self, panelId, isOpen)
if self.m_isClosingAll then
return
end
if isOpen then
self:_RemoveFromPanelAssetLRU(panelId)
return
end
local count = #self.m_recentClosedPanelIds
if self.m_recentClosedPanelIds[count] == panelId then
return
end
local index
for k, v in ipairs(self.m_recentClosedPanelIds) do
if v == panelId then
index = k
break
end
end
if not index then
if count >= self.m_panelAssetLRUCapacity then
local removedCount = count - self.m_panelAssetLRUCapacity + 1
for k = 1, count do
if k <= removedCount then
local removedPanelId = self.m_recentClosedPanelIds[k]
local assetInfo = self.m_panel2Handle[removedPanelId]
if assetInfo then
self.m_panel2Handle[removedPanelId] = nil
self.m_resourceLoader:DisposeHandleByKey(assetInfo[1])
logger.info("UIManager._UpdatePanelAssetLRU DisposeHandleByKey", removedPanelId, self.m_names[removedPanelId])
end
end
self.m_recentClosedPanelIds[k] = self.m_recentClosedPanelIds[k + removedCount]
end
end
if self.m_panelAssetLRUCapacity > 0 then
table.insert(self.m_recentClosedPanelIds, panelId)
else
local assetInfo = self.m_panel2Handle[panelId]
if assetInfo then
self.m_panel2Handle[panelId] = nil
self.m_resourceLoader:DisposeHandleByKey(assetInfo[1])
logger.info("UIManager._UpdatePanelAssetLRU DisposeHandleByKey", panelId, self.m_names[panelId])
end
end
else
for k = index, count - 1 do
self.m_recentClosedPanelIds[k] = self.m_recentClosedPanelIds[k + 1]
end
self.m_recentClosedPanelIds[count] = panelId
end
end
UIManager.ReleaseCachedPanelAsset = HL.Method() << function(self)
for panelId, assetInfo in pairs(self.m_panel2Handle) do
if not self:IsOpen(panelId) then
self.m_panel2Handle[panelId] = nil
local assetKey = assetInfo[1]
self.m_resourceLoader:DisposeHandleByKey(assetKey)
end
end
self.m_recentClosedPanelIds = {}
end
UIManager._RemoveFromPanelAssetLRU = HL.Method(HL.Number) << function(self, panelId)
local index
for k, v in ipairs(self.m_recentClosedPanelIds) do
if v == panelId then
index = k
break
end
end
if index then
table.remove(self.m_recentClosedPanelIds, index)
end
end
UIManager._OnScreenSizeChanged = HL.Method() << function(self)
self:SetUICameraFOV(self.m_currentStandardFOV)
end
UIManager.OnToggleUiAction = HL.Method(HL.Table) << function(self, arg)
local isShow = unpack(arg)
if isShow then
CameraManager:RemoveUICamCullingMaskConfig("UIManager")
self:_ToggleUIInputBinding(true, "TOGGLE_UI_ACTION")
else
CameraManager:AddUICamCullingMaskConfig("UIManager", UIConst.LAYERS.Nothing)
self:_ToggleUIInputBinding(false, "TOGGLE_UI_ACTION")
end
Notify(MessageConst.AFTER_TOGGLE_UI_ACTION, { isShow })
end
UIManager.Dump = HL.Method().Return(HL.String) << function(self)
return self:GetCurPanelDebugInfo()
end
UIManager.GetCurPanelDebugInfo = HL.Method(HL.Opt(HL.Table)).Return(HL.String) << function(self, extraFieldInfo)
local extraFieldTitle = extraFieldInfo == nil and "" or string.format("%s\t", extraFieldInfo.extraFieldTitle)
local infos = { "\nPanelId\tIsShow\tSortingOrder\t" .. extraFieldTitle .. "PanelName\n" }
for type = Types.MaxPanelOrderType, 1, -1 do
local manager = self.m_orderManagers[type]
local stack = manager.stack
if stack:Count() > 0 then
table.insert(infos, "----------------Layer " .. type .. "----------------")
local topIndex, bottomIndex = stack:TopIndex(), stack:BottomIndex()
for i = topIndex, bottomIndex, -1 do
local id = stack:Get(i)
local cfg = self.m_panelConfigs[id]
local ctrl = cfg.ctrl
local extraField = ""
if extraFieldInfo ~= nil then
extraField = extraFieldInfo.extraFieldGetFunc(id, ctrl) .. "\t"
end
table.insert(infos, string.format("%d\t%s\t%d\t%s\t%s",
id,
self:IsShow(id),
ctrl:GetSortingOrder(),
extraField,
cfg.name
))
end
end
end
return table.concat(infos, "\n")
end
UIManager.GetCurPanelDebugInfoForBlockOtherInput = HL.Method().Return(HL.String) << function(self)
return self:GetCurPanelDebugInfo({
extraFieldTitle = "<color=white>BlockOtherInput</color>",
extraFieldGetFunc = function(id, ctrl)
local isShow = self:IsShow(id)
local warningFormat = "<color=yellow>%s</color>"
local normalFormat = "<color=white>%s</color>"
local blockKeyboardEvent = ctrl:GetBlockKeyboardEvent()
return (blockKeyboardEvent and isShow) and
string.format(warningFormat, blockKeyboardEvent) or
string.format(normalFormat, blockKeyboardEvent)
end
})
end
UIManager.GetCurPanelDebugInfoForCursorVisible = HL.Method().Return(HL.String) << function(self)
return self:GetCurPanelDebugInfo({
extraFieldTitle = "<color=white>CursorVisible</color>",
extraFieldGetFunc = function(id, ctrl)
local isShow = self:IsShow(id)
local cursorCfgName = DeviceInfo.usingController and "virtualMouseMode" or "realMouseMode"
local mode = ctrl:GetCurPanelCfg(cursorCfgName)
if mode == Types.EPanelMouseMode.NeedShow then
return isShow and "<color=yellow>ForceShow</color>" or "<color=white>ForceShow</color>"
elseif mode == Types.EPanelMouseMode.ForceHide then
return isShow and "<color=green>ForceHide</color>" or "<color=white>ForceHide</color>"
else
return "<color=white>Optional</color>"
end
end
})
end
UIManager.GetCurPanelDebugInfoForMultiTouch = HL.Method().Return(HL.String) << function(self)
return self:GetCurPanelDebugInfo({
extraFieldTitle = "<color=white>MultiTouch</color>",
extraFieldGetFunc = function(id, ctrl)
local isShow = self:IsShow(id)
local type = ctrl:GetMultiTouchType()
if type == Types.EPanelMultiTouchTypes.Enable then
return isShow and "<color=yellow>ForceEnable</color>" or "<color=white>ForceEnable</color>"
elseif type == Types.EPanelMultiTouchTypes.Disable then
return isShow and "<color=green>ForceDisable</color>" or "<color=white>ForceDisable</color>"
else
return "<color=white>Optional</color>"
end
end
})
end
UIManager.GetCurPanelDebugInfoForCustomField = HL.Method(HL.String).Return(HL.String) << function(self, fieldName)
return self:GetCurPanelDebugInfo({
extraFieldTitle = "<color=white>" .. fieldName .. "</color>",
extraFieldGetFunc = function(id, ctrl)
local fieldValue = ctrl:GetCurPanelCfg(fieldName)
return string.format("<color=white>%s</color>", fieldValue)
end
})
end
UIManager.UpdateUICanvasScaleHelpers = HL.Method() << function(self)
logger.info("UIManager.UpdateUICanvasScaleHelpers")
for _, scaleHelper in ipairs({ self.m_uiCanvasScaleHelper, self.m_worldUICanvasScaleHelper }) do
local res = scaleHelper:GetProperCanvasResolution()
for _, canvasScaler in pairs(scaleHelper.canvasScalerList) do
canvasScaler.referenceResolution = res
end
scaleHelper:UpdateCanvas()
end
end
UIManager.CreateNaviDummLayerObj = HL.Method().Return(GameObject) << function(self)
return CSUtils.CreateObject(self.uiDummyNaviLayerAsset, self.uiDummyNaviLayerRoot)
end
UIManager._TryAttachNaviDummyLayer = HL.Method(HL.Number) << function(self, panelId)
local cfg = self.m_panelConfigs[panelId]
if cfg.needNaviDummyLayer ~= true then
return
end
Notify(MessageConst.ATTACH_DUMMY_NAVI_LAYER, cfg.name)
end
UIManager._TryDetachNaviDummyLayer = HL.Method(HL.Number) << function(self, panelId)
local panelName = self.m_names[panelId]
Notify(MessageConst.DETACH_DUMMY_NAVI_LAYER, panelName)
end
HL.Commit(UIManager)
return UIManager