miduo_client/Assets/ManagedResources/~Lua/Framework/Manager/UIManager.lua

663 lines
22 KiB
Lua
Raw Normal View History

2020-05-09 13:31:21 +08:00
UIManager = {}
local this = UIManager
--监听ui事件的对象
this.eventSystem = nil
--正常UI面板节点
this.uiNode = nil
--固定层级面板节点
this.maxNode = nil
--UI的配置信息
this.configs = {}
--桟式UI列表
this.stackList = {}
--固定层级UI列表
this.fixedList= {}
--已经打开过的UI
this.openedList= {}
--窗口之间的层级间隔
this.space = 100
local UIConfig
local unpack = unpack
local standard = 16 / 9
local DELAY_TIME = 15 --超过延迟时间,界面被销毁
local delayDestoryList = {}
local function update()
for k,v in pairs(delayDestoryList) do
if v.delayTime < Time.realtimeSinceStartup then
this.DestroyPanel(v.panel)
this.openedList[k] = nil
delayDestoryList[k] = nil
end
end
end
UIType = {
--[[
--]]
FullType = 1,
--[[
--]]
Popup = 2,
--固定层级面板
--[[
--]]
Fixed = 3
}
function UIManager.Initialize()
UIConfig = ConfigManager.GetConfig(ConfigName.UIConfig)
local prefab = resMgr:LoadAsset("UIRoot")
local gameObj = GameObject.Instantiate(prefab)
gameObj.name = "UIRoot"
this.eventSystem = GameObject.Find("EventSystem")
this.uiRoot = gameObj
this.uiNode = gameObj.transform:Find("UIRoot/UINode")
this.fullNode = gameObj.transform:Find("UIRoot/FullNode")
2020-05-09 13:31:21 +08:00
this.fixedNode = gameObj.transform:Find("UIRoot/FixedNode")
this.screenMask1 = gameObj.transform:Find("UIRoot/ScreenMask1").gameObject
this.screenMask2 = gameObj.transform:Find("UIRoot/ScreenMask2").gameObject
this.camera = gameObj.transform:Find("UICamera"):GetComponent("Camera")
this.Adapter()
this.InitCommonPanels()
UpdateBeat:Add(update, this)
end
function UIManager.InitCommonPanels()
require("Modules/Message/MsgPanel")
require("Modules/Message/RequestPanel")
require("Modules/Message/LoadingPanel")
require("Modules/Message/PopupTipPanel")
require("Modules/Message/SwitchPanel")
require("Modules/Message/NotEnoughPopup")
require("Modules/Popup/CostConfirmPopup")
2020-05-25 19:16:23 +08:00
require("Modules/Message/HorseRaceLampView")
2020-06-03 19:09:01 +08:00
require("Modules/Message/MissionDailyTipPanel")
2020-05-25 19:16:23 +08:00
UIManager.OpenPanel(UIName.HorseRaceLampView)
2020-05-09 13:31:21 +08:00
end
function UIManager.Adapter()
2020-06-30 18:59:44 +08:00
local notchHeight = 0
if AppConst.isSDK then
notchHeight = NotchScreenUtil.Instance:GetNotchHeight()
Log("********************* 刘海屏的高度是:"..notchHeight)
if notchHeight == -1 then
--TODO: 这里再配置一套小众的手机的屏幕高度
notchHeight = 0
end
end
2020-06-28 17:52:29 +08:00
UIManager.Offset = {
2020-09-01 14:38:02 +08:00
Top = 48,
2020-09-01 14:44:51 +08:00
Bottom = 0,
2020-06-28 17:52:29 +08:00
Left = 0,
Right = 0,
}
2020-09-01 14:38:02 +08:00
2020-06-28 17:52:29 +08:00
-- 屏幕大小
UIManager.width = Screen.width
UIManager.height = Screen.height
2020-09-01 14:38:02 +08:00
-- 计算屏幕比例的比值,用于部分界面进行屏幕适配的缩放
UIManager.adapterScale = (1920/1080)/(Screen.height / Screen.width)
2020-06-28 17:52:29 +08:00
-- ui实际大小
UIManager.realHeigt = Screen.height - UIManager.Offset.Top - UIManager.Offset.Bottom
UIManager.realWidth = Screen.width - UIManager.Offset.Left - UIManager.Offset.Right
2020-05-09 13:31:21 +08:00
local n = Screen.height / Screen.width
if n > standard then
local rectTransform = this.uiNode.gameObject:GetComponent("RectTransform")
2020-06-28 17:52:29 +08:00
rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x, rectTransform.offsetMin.y + UIManager.Offset.Bottom)
rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x, rectTransform.offsetMax.y - UIManager.Offset.Top)
2020-05-09 13:31:21 +08:00
2020-09-01 14:38:02 +08:00
-- rectTransform = this.screenMask1:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(0, 1)
-- rectTransform.anchorMax = Vector2.New(1, 1)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.pivot = Vector2.New(0.5, 1)
-- rectTransform.sizeDelta = Vector2.New(0, UIManager.Offset.Top)
2020-07-28 17:00:19 +08:00
2020-09-01 14:38:02 +08:00
-- rectTransform = this.screenMask2:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(0, 0)
-- rectTransform.anchorMax = Vector2.New(1, 0)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.pivot = Vector2.New(0.5, 0)
-- rectTransform.sizeDelta = Vector2.New(0, UIManager.Offset.Bottom)
2020-07-28 17:00:19 +08:00
2020-05-09 13:31:21 +08:00
elseif n < standard then
local w = 1920 / Screen.height * Screen.width
local f = (w-1080) / 2
local rectTransform = this.uiNode.gameObject:GetComponent("RectTransform")
rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x + f, rectTransform.offsetMin.y)
rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x - f, rectTransform.offsetMax.y)
rectTransform = this.fixedNode.gameObject:GetComponent("RectTransform")
rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x + f, rectTransform.offsetMin.y)
rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x - f, rectTransform.offsetMax.y)
rectTransform = this.screenMask1:GetComponent("RectTransform")
rectTransform.anchorMin = Vector2.New(0, 0)
rectTransform.anchorMax = Vector2.New(0, 1)
rectTransform.offsetMin = Vector2.New(0, 0)
rectTransform.offsetMax = Vector2.New(0, 0)
rectTransform.sizeDelta = Vector2.New(f*2, 0)
rectTransform = this.screenMask2:GetComponent("RectTransform")
rectTransform.anchorMin = Vector2.New(1, 0)
rectTransform.anchorMax = Vector2.New(1, 1)
rectTransform.offsetMin = Vector2.New(0, 0)
rectTransform.offsetMax = Vector2.New(0, 0)
rectTransform.sizeDelta = Vector2.New(f*2, 0)
UIManager.width = Screen.width - f*2
UIManager.height = Screen.height
else
this.screenMask1:SetActive(false)
this.screenMask2:SetActive(false)
UIManager.height = Screen.height
UIManager.width = Screen.width
end
2020-06-28 17:52:29 +08:00
-- local n = Screen.height / Screen.width
-- if n > standard then
-- local f = (n-standard)*Screen.width / 2
-- local rectTransform = this.uiNode.gameObject:GetComponent("RectTransform")
-- rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x, rectTransform.offsetMin.y + f)
-- rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x, rectTransform.offsetMax.y - f)
-- rectTransform = this.fixedNode.gameObject:GetComponent("RectTransform")
-- rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x, rectTransform.offsetMin.y + f)
-- rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x, rectTransform.offsetMax.y - f)
-- rectTransform = this.screenMask1:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(0, 1)
-- rectTransform.anchorMax = Vector2.New(1, 1)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.sizeDelta = Vector2.New(0, f*2)
-- rectTransform = this.screenMask2:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(0, 0)
-- rectTransform.anchorMax = Vector2.New(1, 0)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.sizeDelta = Vector2.New(0, f*2)
-- UIManager.width = Screen.width
-- UIManager.height = Screen.height - f*2
-- elseif n < standard then
-- local w = 1920 / Screen.height * Screen.width
-- local f = (w-1080) / 2
-- local rectTransform = this.uiNode.gameObject:GetComponent("RectTransform")
-- rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x + f, rectTransform.offsetMin.y)
-- rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x - f, rectTransform.offsetMax.y)
-- rectTransform = this.fixedNode.gameObject:GetComponent("RectTransform")
-- rectTransform.offsetMin = Vector2.New(rectTransform.offsetMin.x + f, rectTransform.offsetMin.y)
-- rectTransform.offsetMax = Vector2.New(rectTransform.offsetMax.x - f, rectTransform.offsetMax.y)
-- rectTransform = this.screenMask1:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(0, 0)
-- rectTransform.anchorMax = Vector2.New(0, 1)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.sizeDelta = Vector2.New(f*2, 0)
-- rectTransform = this.screenMask2:GetComponent("RectTransform")
-- rectTransform.anchorMin = Vector2.New(1, 0)
-- rectTransform.anchorMax = Vector2.New(1, 1)
-- rectTransform.offsetMin = Vector2.New(0, 0)
-- rectTransform.offsetMax = Vector2.New(0, 0)
-- rectTransform.sizeDelta = Vector2.New(f*2, 0)
-- UIManager.width = Screen.width - f*2
-- UIManager.height = Screen.height
-- else
-- this.screenMask1:SetActive(false)
-- this.screenMask2:SetActive(false)
-- UIManager.height = Screen.height
-- UIManager.width = Screen.width
-- end
2020-05-09 13:31:21 +08:00
end
function UIManager.ChangeTo2D()
this.camera.orthographic = true
end
function UIManager.ChangeTo3D()
this.camera.orthographic = false
end
--打开面板
function UIManager.OpenPanel(id, ...)
-- 如果是
if id == UIName.BattlePanel and this.IsOpen(UIName.BattlePanel) then
LogError("战斗界面重复打开!!")
return
end
2020-05-09 13:31:21 +08:00
return UIManager.GetPanel(id, true, nil, ...)
end
--异步打开面板
function UIManager.OpenPanelAsync(id, func, ...)
UIManager.GetPanel(id, false, func, ...)
end
local SetSortingOrder = function(uiConfig, panel, isStackPanel, ...)
if isStackPanel then
if uiConfig.type == UIType.FullType then
for i = 1, #this.stackList do
2020-05-25 19:16:23 +08:00
if this.stackList[i] and this.stackList[i].isOpened then
2020-05-09 13:31:21 +08:00
this.stackList[i].gameObject:SetActive(false)
this.stackList[i]:CloseUI()
end
end
else
--上一个打开的窗口若是全屏窗口,则失去焦点
for i = #this.stackList, 1,-1 do
2020-05-25 19:16:23 +08:00
if this.stackList[i] and this.stackList[i].isOpened then
2020-05-09 13:31:21 +08:00
if this.stackList[i].uiConfig.type == UIType.FullType then
this.stackList[i]:LoseFocus()
end
break
end
end
end
this.stackList[#this.stackList+1] = panel
for i = 1, #this.stackList do
this.stackList[i].transform:SetAsLastSibling()
this.stackList[i]:SetSortingOrder(i * this.space)
end
else
this.fixedList[#this.fixedList+1] = panel
panel:SetSortingOrder(uiConfig.sortingOrder)
end
panel.gameObject:SetActive(true)
panel:OpenUI(false, ...)
panel.openNum = panel.openNum + 1
delayDestoryList[panel.uiConfig.id] = nil
end
function UIManager.GetPanel(id, isSync, func, ...)
local uiConfig = UIConfig[id]
if(uiConfig == nil) then
LogError("UIManager====>没有找到UI的配置信息:"..id)
return
end
local panel
local isStackPanel = uiConfig.type == UIType.FullType or uiConfig.type == UIType.Popup
local list = isStackPanel and this.stackList or this.fixedList
for i = 1, #list do
if list[i].uiConfig.id == uiConfig.id then
panel = list[i]
--如果找到了,从桟中移除
table.remove(list, i)
break
end
end
local args = {...}
local action = function(panel)
if not panel then --在缓存里面找一找
panel = this.openedList[uiConfig.id]
end
if not panel then
panel = reimport("Modules/"..uiConfig.script)
this.openedList[uiConfig.id] = panel
panel.uiConfig = uiConfig
local rootNode = this.fixedNode
if isStackPanel then
if uiConfig.type == UIType.FullType then
rootNode = this.uiNode
elseif uiConfig.type == UIType.Popup then
rootNode = this.fullNode
end
end
2020-05-09 13:31:21 +08:00
if isSync then
local gameObject = this.CreatePanel(uiConfig, rootNode)
2020-05-09 13:31:21 +08:00
panel:CreateUI(gameObject)
else
this.CreatePanelAsync(uiConfig, rootNode, function (gameObject)
2020-05-09 13:31:21 +08:00
panel:CreateUI(gameObject)
SetSortingOrder(uiConfig, panel, isStackPanel,unpack(args, 1, table.maxn(args)))
if func then
func(panel)
end
end)
end
end
if isSync then
SetSortingOrder(uiConfig, panel, isStackPanel,unpack(args, 1, table.maxn(args)))
return panel
else
if panel.gameObject then
SetSortingOrder(uiConfig, panel, isStackPanel,unpack(args, 1, table.maxn(args)))
end
end
end
if isStackPanel and uiConfig.type == UIType.FullType then --如果栈界面有需要播放关闭动画的界面,则新打开的界面需要等到关闭动画播放完成以后
local closeNum = 0
local closeTotal = 0
for i = 1, #this.stackList do
if this.stackList[i].isOpened and this.stackList[i].OnCloseBefore then
closeTotal = closeTotal + 1
this.stackList[i]:OnCloseBefore(function()
closeNum = closeNum + 1
if closeNum == closeTotal then
this.eventSystem:SetActive(true)
return action(panel)
end
end)
end
end
if closeTotal == 0 then
return action(panel)
else
this.eventSystem:SetActive(false)
end
else
return action(panel)
end
end
--界面是否已经打开过
function UIManager.IsOpen(id)
local uiConfig = UIConfig[id]
if(uiConfig==nil) then return end
local list
if(uiConfig.type == UIType.FullType or uiConfig.type == UIType.Popup) then
list = this.stackList
else
list = this.fixedList
end
for i=1,#list do
if(list[i].uiConfig.id == id and list[i].isOpened) then
return true
end
end
return false
end
2020-05-25 19:16:23 +08:00
-- 判断界面是否显示在最上层
function UIManager.IsTopShow(id)
local uiConfig = UIConfig[id]
if(uiConfig==nil) then return end
local list
if(uiConfig.type == UIType.FullType or uiConfig.type == UIType.Popup) then
list = this.stackList
else
list = this.fixedList
end
local len = #list
if list[len].uiConfig.id == id and list[len].isOpened then
return true
end
return false
end
2020-05-09 13:31:21 +08:00
--获取已经打开的面板
function UIManager.GetOpenPanel(id)
local uiConfig = UIConfig[id]
if(uiConfig==nil) then return end
local list
if(uiConfig.type == UIType.FullType or uiConfig.type == UIType.Popup) then
list = this.stackList
else
list = this.fixedList
end
for i=1,#list do
if(list[i].uiConfig.id == id) then
return list[i]
end
end
return nil
end
--关闭面板
function UIManager.ClosePanel(id,isDestroy)
if not id then
Log("UIManager.ClosePanel====>关闭面板id不能为空")
return
end
local uiConfig = UIConfig[id]
if(uiConfig == nil) then
Log("UIManager====>没有找到UI的配置信息:"..id)
return
end
isDestroy = isDestroy or uiConfig.noDestory == 0
if(uiConfig.type == UIType.FullType or uiConfig.type == UIType.Popup) then
this.CloseStackPanel(uiConfig,isDestroy)
else
this.CloseFixedPanel(uiConfig,isDestroy)
end
end
function UIManager.CloseFixedPanel(uiConfig,isDestroy)
if(#this.fixedList== 0) then return end
local panel
for i = 1, #this.fixedList do
if(this.fixedList[i].uiConfig.id == uiConfig.id) then
panel = this.fixedList[i]
table.remove(this.fixedList,i)
break
end
end
if(panel == nil) then return end
local closeAction = function()
if(panel.isOpened) then
panel.gameObject:SetActive(false)
panel:CloseUI()
end
if(isDestroy) then
this.DelayDestroyPanel(panel)
end
this.eventSystem:SetActive(true)
end
if panel.OnCloseBefore then
this.eventSystem:SetActive(false)
panel:OnCloseBefore(closeAction)
else
closeAction()
end
end
--关掉桟式面板
function UIManager.CloseStackPanel(uiConfig,isDestroy)
if(#this.stackList== 0) then return end
local panel = nil
for i = 1, #this.stackList do
if(this.stackList[i].uiConfig.id == uiConfig.id) then
panel = this.stackList[i]
table.remove(this.stackList,i)
break
end
end
if not panel then return end
local closeAction = function()
if panel.isOpened then
panel.gameObject:SetActive(false)
panel:CloseUI()
end
--如果是全屏窗口,向后回退到一个全屏窗口为止
if uiConfig.type == UIType.FullType then
2020-06-28 17:52:29 +08:00
-- 找到上一个全屏窗口的位置
local startIndex
2020-05-09 13:31:21 +08:00
for i = #this.stackList, 1,-1 do
local panel = this.stackList[i]
if panel.uiConfig.type == UIType.FullType then
2020-06-28 17:52:29 +08:00
startIndex = i
2020-05-09 13:31:21 +08:00
break
end
2020-06-28 17:52:29 +08:00
end
--
for i = startIndex, #this.stackList do
local panel = this.stackList[i]
panel.gameObject:SetActive(true)
panel:OpenUI(true)
2020-05-09 13:31:21 +08:00
end
else
--回退的第一个打开的窗口若是全屏窗口,则被唤醒
for i = #this.stackList, 1,-1 do
if this.stackList[i].isOpened then
if this.stackList[i].uiConfig.type == UIType.FullType then
this.stackList[i]:Focus()
end
break
end
end
end
if isDestroy then
this.DelayDestroyPanel(panel)
end
this.eventSystem:SetActive(true)
end
if panel.OnCloseBefore then
this.eventSystem:SetActive(false)
panel:OnCloseBefore(closeAction)
else
closeAction()
end
end
--加载面板
function UIManager.CreatePanel(uiConfig, parent)
local prefab = resMgr:LoadAsset(uiConfig.assetName)
if prefab == nil then
LogError("资源创建失败!! 没有找到对应的资源!! key:"..uiConfig.id..",assetName:"..uiConfig.assetName)
resMgr:UnLoadAsset(uiConfig.assetName)
return
end
Log(uiConfig.assetName)
local gameObject = GameObject.Instantiate(prefab)
gameObject.name = prefab.name
local transform = gameObject.transform
transform:SetParent(parent)
transform.localScale = Vector3.one
local recTransform = transform:GetComponent("RectTransform")
recTransform.anchoredPosition3D = Vector3.New(0, 0, 0)
recTransform.sizeDelta = Vector2.New(0, 0)
transform.localRotation = Quaternion.identity
return gameObject
end
--异步加载面板
function UIManager.CreatePanelAsync(uiConfig, parent, func)
resMgr:LoadAssetAsync(uiConfig.assetName, function(name, prefab)
if prefab == nil then
LogError("资源创建失败!! 没有找到对应的资源!! key:"..uiConfig.id..",assetName:"..uiConfig.assetName)
resMgr:UnLoadAsset(uiConfig.assetName)
return
end
Log(uiConfig.assetName)
local gameObject = GameObject.Instantiate(prefab)
gameObject.name = prefab.name
local transform = gameObject.transform
transform:SetParent(parent)
transform.localScale = Vector3.one
local recTransform = transform:GetComponent("RectTransform")
recTransform.anchoredPosition3D = Vector3.New(0, 0, 0)
recTransform.sizeDelta = Vector2.New(0, 0)
transform.localRotation = Quaternion.identity
if func then
func(gameObject)
end
end)
end
--关闭所有面板
function UIManager.CloseAll(isDestroy)
local panel = nil
while(#this.stackList~=0)
do
panel = this.stackList[1]
panel.gameObject:SetActive(false)
panel:CloseUI()
if(isDestroy) then
this.DestroyPanel(panel)
end
table.remove(this.stackList,1)
end
while(#this.fixedList~=0)
do
panel = this.fixedList[1]
panel.gameObject:SetActive(false)
panel:CloseUI()
if(isDestroy) then
Log("UIManager.DestroyPanel")
this.DestroyPanel(panel)
end
table.remove(this.fixedList,1)
end
this.openedList = {}
delayDestoryList = {}
end
--延时销毁界面避免频繁的GC开销
function UIManager.DelayDestroyPanel(panel)
local item = delayDestoryList[panel.uiConfig.id]
if not item then
item = { delayTime = 0, panel = panel }
delayDestoryList[panel.uiConfig.id] = item
end
item.delayTime = Time.realtimeSinceStartup + DELAY_TIME * panel.openNum
end
function UIManager.DestroyPanel(panel)
panel:DestroyUI()
GameObject.Destroy(panel.gameObject)
resMgr:UnLoadAsset(panel.uiConfig.assetName)
end
--获取UI配置
function UIManager.GetConfig(key)
return UIConfig[key]
end
--根据配置关闭游戏的所有面板
function UIManager.CloseAllGamePanel(uiConfig)
for i, v in pairs(uiConfig) do
UIManager.ClosePanel(v.id,true)
end
end
function UIManager.GetLocalPositionToTarget(parent,target)
local screenPos = this.camera:WorldToScreenPoint (target.transform.position)
local flag,targetPos = RectTransformUtility.ScreenPointToLocalPointInRectangle (parent.transform,screenPos,this.camera,nil)
return targetPos
end
function UIManager.Dispose()
UIManager.CloseAll(true)
GameObject.DestroyImmediate(this.uiRoot)
end
return UIManager