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 = "BlockOtherInput", extraFieldGetFunc = function(id, ctrl) local isShow = self:IsShow(id) local warningFormat = "%s" local normalFormat = "%s" 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 = "CursorVisible", 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 "ForceShow" or "ForceShow" elseif mode == Types.EPanelMouseMode.ForceHide then return isShow and "ForceHide" or "ForceHide" else return "Optional" end end }) end UIManager.GetCurPanelDebugInfoForMultiTouch = HL.Method().Return(HL.String) << function(self) return self:GetCurPanelDebugInfo({ extraFieldTitle = "MultiTouch", extraFieldGetFunc = function(id, ctrl) local isShow = self:IsShow(id) local type = ctrl:GetMultiTouchType() if type == Types.EPanelMultiTouchTypes.Enable then return isShow and "ForceEnable" or "ForceEnable" elseif type == Types.EPanelMultiTouchTypes.Disable then return isShow and "ForceDisable" or "ForceDisable" else return "Optional" end end }) end UIManager.GetCurPanelDebugInfoForCustomField = HL.Method(HL.String).Return(HL.String) << function(self, fieldName) return self:GetCurPanelDebugInfo({ extraFieldTitle = "" .. fieldName .. "", extraFieldGetFunc = function(id, ctrl) local fieldValue = ctrl:GetCurPanelCfg(fieldName) return string.format("%s", 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