PGRData/Script/matrix/xmanager/XLuaUiManager.lua
2024-09-01 22:49:41 +02:00

1437 lines
No EOL
39 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.

-------------------------------------------------------------------------------------------------------------
CsXUiType = CS.XUiType
-- CsXUiResType = CS.XUiResType
CsXUiManager = CS.XUiManager
-- CsIBaseEventListener = CS.IBaseEventListener
CsXGameEventManager = CS.XGameEventManager
-- CsXLuaEventProxy = CS.XLuaEventProxy
-- CsXUi = CS.XUi
-- CsXChildUi = CS.XChildUi
-- CsXGameUi = CS.XGameUi
-- CsXMaskManager = CS.XMaskManager
-- CsXUguiEventListener = CS.XUguiEventListener
-- CsXUiData = CS.XUiData
-- CsXUiStackContainer = CS.XUiStackContainer
-- CsXUiListContainer = CS.XUiListContainer
-- CsXUiChildContainer = CS.XUiChildContainer
CsXUiHelper = CS.XUiHelper
CsXTextManagerGetText = CS.XTextManager.GetText
CSXTextManagerGetText = CsXTextManagerGetText
CSObjectInstantiate = CS.UnityEngine.Object.Instantiate
Vector2 = CS.UnityEngine.Vector2
Vector3 = CS.UnityEngine.Vector3
local IsWindowsEditor = XMain.IsWindowsEditor
local _UIUid = 0
local GenUIUid = function()
_UIUid = _UIUid + 1
return _UIUid
end
local UIBindControl = require("MVCA/UIBindControl")
---@class XUiNode
XUiNode = XClass(nil, "XUiNode")
if IsWindowsEditor then
XUiNode._profiler = {}
setmetatable(XUiNode._profiler, {__mode = "kv"})
XUiNode._Profiler = function ()
collectgarbage("collect") --得调用Lua Profiler界面的GC才能释放干净
XLog.Debug("XUiNode._Profiler", XUiNode._profiler)
end
XUiNode._ProfilerNode = function (key)
for node, classname in pairs(XUiNode._profiler) do
if classname == key then
LuaMemorySnapshotDump.SnapshotObject(node)
break
end
end
end
end
--XUiNode._Profiler()
--XUiNode._ProfilerNode("XUiGridCharacterNew")
function XUiNode:Ctor(ui, parent, ...)
self:InitNode(ui, parent, ...)
end
function XUiNode:InitNode(ui, parent, ...)
if IsWindowsEditor then
XUiNode._profiler[self] = self.__cname
end
self._IsPopPanel = false
self._Uid = GenUIUid()
self.GameObject = ui.gameObject
self.Transform = ui.transform
self.Parent = parent
---@type XUiNode[]
self._ChildNodes = {} --子节点
self._Control = nil
self._IsShow = self.GameObject.activeSelf
self._EnabledCount = 0
self._BindControlId = nil
XTool.InitUiObject(self)
self:BindParent() --跟父节点绑定关系
self:InitBindControlId() --实例化要绑定的control名字,优先父节点
self:BindControl() --绑定control
self._LuaEvents = self:OnGetLuaEvents()
self:OnStart(...) --执行子类的onStart
if self._IsShow then
self:OnEnableUi()
end
end
---设置是否为弹出的界面, 用于那种使用内部节点做资源, 但是有独立的弹出窗体的界面
function XUiNode:SetIsPopPanel(value)
self._IsPopPanel = value
end
function XUiNode:GetIsPopPanel()
return self._IsPopPanel
end
function XUiNode:OnGetLuaEvents()
end
function XUiNode:OnNotify(evt, ...)
end
function XUiNode:OnStart()
end
function XUiNode:OnEnableUi()
self:OnEnable()
if self._LuaEvents then
for i = 1, #self._LuaEvents do
XUIEventBind.AddEventListener(self._LuaEvents[i], self.OnNotify, self)
end
end
if self._EnabledCount > 0 then
self:EnableChildNodes()
end
self._EnabledCount = self._EnabledCount + 1
end
function XUiNode:OnEnable()
end
function XUiNode:OnDisableUi()
if self._LuaEvents then
for i = 1, #self._LuaEvents do
XUIEventBind.RemoveEventListener(self._LuaEvents[i], self.OnNotify, self)
end
end
self:OnDisable()
self:DisableChildNodes()
end
function XUiNode:OnDisable()
end
function XUiNode:EnableChildNodes()
for _, child in ipairs(self._ChildNodes) do
if child._IsShow then
child:OnEnableUi()
end
end
end
function XUiNode:DisableChildNodes()
for _, child in ipairs(self._ChildNodes) do
if child._IsShow then
child:OnDisableUi()
end
end
end
---显示节点
function XUiNode:Open()
if not self._IsShow then
self._IsShow = true
self:SetDisplay(true)
self:OnEnableUi()
end
end
---隐藏节点
function XUiNode:Close()
if self._IsShow then
self._IsShow = false
self:SetDisplay(false)
self:OnDisableUi()
end
end
---设置显示, 子类可以重写
---@param val boolean 是否显示
function XUiNode:SetDisplay(val)
self.GameObject:SetActiveEx(val)
end
function XUiNode:BindParent()
if self.Parent then
if self.Parent.AddChildNode then
self.Parent:AddChildNode(self)
else
local parentClsName = self.Parent.__cname and self.Parent.__cname or ""
if IsWindowsEditor then
XLog.Error("Parent 不为XLuaUi 或 XUiNode: ".. parentClsName)
end
end
else
if IsWindowsEditor then
XLog.Error("XUiNode has not Parent: "..self.__cname)
end
end
end
--暂时没有中途移除的需求
function XUiNode:UnBindParent()
if self.Parent then
if self.Parent.RemoveChildNode then
self.Parent:RemoveChildNode(self)
else
local parentClsName = self.Parent.__cname and self.Parent.__cname or ""
if IsWindowsEditor then
XLog.Error("Parent 不为XLuaUi 或 XUiNode: ".. parentClsName)
end
end
else
if IsWindowsEditor then
XLog.Error("XUiNode has not Parent: "..self.__cname)
end
end
end
---@param node XUiNode
function XUiNode:AddChildNode(node)
if not table.contains(self._ChildNodes, node) then
table.insert(self._ChildNodes, node)
end
end
---@param node XUiNode
function XUiNode:RemoveChildNode(node)
local index = table.indexof(self._ChildNodes, node)
if index then
table.remove(self._ChildNodes, index)
end
end
---获取绑定的control名字,优先获取父节点
function XUiNode:InitBindControlId()
local tempBindName = UIBindControl[self.__cname] --有配置的优先读取配置
if not tempBindName then
if self.Parent then
if self.Parent._BindControlId then --这个有值证明可以绑定
tempBindName = self.Parent._BindControlId
elseif self.Parent.__cname and UIBindControl[self.Parent.__cname] then
tempBindName = UIBindControl[self.Parent.__cname]
end
end
end
self._BindControlId = tempBindName
end
function XUiNode:BindControl()
if self._BindControlId then --子界面用_BindControlId
self._Control = XMVCA:_GetOrRegisterControl(self._BindControlId)
self._Control:AddViewRef(self._Uid)
end
end
function XUiNode:UnBindControl()
self._BindControlId = nil
if self._Control then
if not self._Control:GetIsRelease() then
self._Control:SubViewRef(self._Uid)
XMVCA:CheckReleaseControl(self._Control:GetId())
end
self._Control = nil
end
end
function XUiNode:Release()
self:OnRelease()
self:UnBindControl() --移除控制器
self:ReleaseChildNodes() --执行子节点的
self.GameObject = nil
self.Transform = nil
self.Parent = nil
self._LuaEvents = nil
end
function XUiNode:ReleaseChildNodes()
for _, child in ipairs(self._ChildNodes) do
child:Release()
end
self._ChildNodes = nil
end
--这是给子类重写的
function XUiNode:OnRelease()
end
------------------------------------------------LuaUI---------------------------------------------------------
---@class XLuaUi
---@field UiModel XUiModel
XLuaUi = XClass(nil, "XLuaUi")
function XLuaUi:Ctor(name, uiProxy)
self._Uid = GenUIUid()
self.Name = name
self.UiProxy = uiProxy
self.Ui = uiProxy.Ui
-- 页面自动关闭时间id
self.AutoCloseTimerId = nil
self.OpenAutoClose = false
self.AutoCloseEndTime = 0
self.AutoCloseCallback = nil
self.AutoCloseIntervalTime = nil
self.AutoCloseDelayTime = nil
self._Control = nil
---@type XUiNode[]
self._ChildNodes = {} --子节点
self._EnabledCount = 0
self:BindControl()
self._LuaEvents = self:OnGetLuaEvents()
end
function XLuaUi:BindControl()
if UIBindControl[self.__cname] then
local controlId = UIBindControl[self.__cname]
self._Control = XMVCA:_GetOrRegisterControl(controlId)
self._Control:AddViewRef(self._Uid)
end
end
function XLuaUi:UnBindControl()
if self._Control then
if not self._Control:GetIsRelease() then
self._Control:SubViewRef(self._Uid)
XMVCA:CheckReleaseControl(self._Control:GetId())
end
self._Control = nil
end
end
---@param node XUiNode
function XLuaUi:AddChildNode(node)
if not table.contains(self._ChildNodes, node) then
table.insert(self._ChildNodes, node)
end
end
---@param node XUiNode
function XLuaUi:RemoveChildNode(node)
local index = table.indexof(self._ChildNodes, node)
if index then
table.remove(self._ChildNodes, index)
end
end
function XLuaUi:ReleaseChildNodes()
for _, child in ipairs(self._ChildNodes) do
child:Release()
end
self._ChildNodes = nil
end
function XLuaUi:EnableChildNodes()
for _, child in ipairs(self._ChildNodes) do
if child._IsShow then
child:OnEnableUi()
end
end
end
function XLuaUi:DisableChildNodes()
for _, child in ipairs(self._ChildNodes) do
if child._IsShow then
child:OnDisableUi()
end
end
end
-- PS:如果页面重写了OnEnable和OnDisable使用时必须在OnEnable和OnDisable调用下父类方法
-- XXX.Super.OnEnable(self)
-- interval : 间隔多少毫秒执行,默认是一秒
-- delay : 初次延迟多少毫秒执行,默认是一秒
function XLuaUi:SetAutoCloseInfo(endTime, callback, interval, delay)
interval = interval or XScheduleManager.SECOND
delay = delay or XScheduleManager.SECOND
self.OpenAutoClose = endTime ~= nil
self.AutoCloseEndTime = endTime or 0
self.AutoCloseCallback = callback
self.AutoCloseIntervalTime = interval
self.AutoCloseDelayTime = delay
end
function XLuaUi:SetGameObject()
self.Transform = self.Ui.Transform
self.GameObject = self.Ui.GameObject
self.UiAnimation = self.Ui.UiAnimation
self.UiSceneInfo = self.Ui.UiSceneInfo
self.UiModelGo = self.Ui.UiModelGo
self.UiModel = self.Ui.UiModel
self:InitUiObjects()
end
function XLuaUi:OnAwakeUi()
self:OnAwake()
end
function XLuaUi:OnAwake()
end
function XLuaUi:OnStartUi(...)
self:OnStart(...)
end
function XLuaUi:OnStart()
end
function XLuaUi:OnEnableUi(...)
self:OnEnable(...)
if self._LuaEvents then
for i = 1, #self._LuaEvents do
XUIEventBind.AddEventListener(self._LuaEvents[i], self.OnNotify, self)
end
end
if self.OpenAutoClose then
self:_StartAutoCloseTimer()
end
if self._EnabledCount > 0 then
self:EnableChildNodes()
end
self._EnabledCount = self._EnabledCount + 1
end
function XLuaUi:OnEnable()
end
function XLuaUi:OnDisableUi()
if self._LuaEvents then
for i = 1, #self._LuaEvents do
XUIEventBind.RemoveEventListener(self._LuaEvents[i], self.OnNotify, self)
end
end
if self.OpenAutoClose then
self:_StopAutoCloseTimer()
end
self:OnDisable()
self:DisableChildNodes()
end
function XLuaUi:OnDisable()
end
function XLuaUi:OnDestroyUi()
self:ReleaseRedPoint()
self:OnDestroy()
end
function XLuaUi:OnDestroy()
end
function XLuaUi:_StartAutoCloseTimer()
self.AutoCloseTimerId = XScheduleManager.ScheduleForever(
function()
local time = XTime.GetServerNowTimestamp()
if time > self.AutoCloseEndTime then
if self.AutoCloseCallback then
self.AutoCloseCallback(true)
end
self:_StopAutoCloseTimer()
else
if self.AutoCloseCallback then
self.AutoCloseCallback(false)
end
end
-- PS:-1 * self.AutoCloseIntervalTime 这么处理是因为XScheduleManager.ScheduleForever里计算时间自动叠加多一次Interval
end,
self.AutoCloseIntervalTime,
self.AutoCloseDelayTime + -1 * self.AutoCloseIntervalTime
)
end
function XLuaUi:_StopAutoCloseTimer()
if self.AutoCloseTimerId then
XScheduleManager.UnSchedule(self.AutoCloseTimerId)
self.AutoCloseTimerId = nil
end
end
function XLuaUi:OnReleaseInstOnly()
XLuaUiManager.SetUiData(self.Name, self:OnReleaseInst())
end
function XLuaUi:OnReleaseInst()
end
function XLuaUi:OnResumeUi()
self:OnResume(XLuaUiManager.GetUiData(self.Name))
XLuaUiManager.RemoveUiData(self.Name)
end
function XLuaUi:OnResume()
end
--用于释放lua的内存
function XLuaUi:OnRelease()
--self.Name = nil
self.UiProxy = nil
self.Ui = nil
self.ParentUi = nil
self.Transform = nil
self.GameObject = nil
self.UiAnimation = nil
self.UiSceneInfo = nil
self.UiModelGo = nil
self.UiModel = nil
-- 释放自动关闭数据
-- 做个防御,避免外部使用错误导致没有释放
self:_StopAutoCloseTimer()
self.AutoCloseTimerId = nil
self.OpenAutoClose = nil
self.AutoCloseEndTime = 0
self.AutoCloseCallback = nil
self.AutoCloseIntervalTime = nil
self.AutoCloseDelayTime = nil
self._LuaEvents = nil
-- 释放信号数据
if self.SignalData then
self.SignalData:Release()
self.SignalData = nil
end
if self.ChildSignalDatas then
for _, signalData in ipairs(self.ChildSignalDatas) do
signalData:Release()
end
self.ChildSignalDatas = nil
end
if self._GridsDic then
self._GridsDic = nil
end
--释放ViewModel层已绑定对象
if self._ViewModelDic then
for viewModel in pairs(self._ViewModelDic) do
viewModel:UnBindUiObjs(self.Name)
end
self._ViewModelDic = nil
end
self:UnBindControl()
self:ReleaseChildNodes()
if self.Obj and self.Obj:Exist() then
local nameList = self.Obj.NameList
for _, v in pairs(nameList) do
self[v] = nil
end
self.Obj = nil
end
for k, v in pairs(self) do
local t = type(v)
if t == "userdata" and CsXUiHelper.IsUnityObject(v) then
self[k] = nil
end
end
end
--CS.XEventId.EVENT_UI_ALLOWOPERATE 允许UI操作事件可以理解为动画播放完成后的回调
function XLuaUi:OnNotify(evt, ...)
end
function XLuaUi:OnGetEvents()
end
function XLuaUi:OnGetLuaEvents()
end
function XLuaUi:SetUiSprite(image, spriteName, callBack)
self.UiProxy:SetUiSprite(image, spriteName, callBack)
end
--快捷隐藏界面(不建议使用)
function XLuaUi:SetActive(active)
local temp = active and true or false
self.UiProxy:SetActive(temp)
end
--快捷关闭界面
function XLuaUi:Close()
if self.UiProxy == nil then
XLog.Error(self.Name .. "重复Close")
else
self.UiProxy:Close()
end
end
--快捷移除UI,移除的UI不会播放进场、退场动画
--不允许用于移除栈顶的UI 使用时注意!!!
function XLuaUi:Remove()
if self.UiProxy then
self.UiProxy:Remove()
end
end
--注册点击事件
function XLuaUi:RegisterClickEvent(button, handle, clear)
clear = clear and true or false
self.UiProxy:RegisterClickEvent(
button,
function(eventData)
if handle then
handle(self, eventData)
end
end,
clear
)
end
--返回指定名字的子节点的Component
--@name 子节点名称
--@type Component类型
function XLuaUi:FindComponent(name, type)
return self.UiProxy:FindComponent(name, type)
end
--通过名字查找GameObject 例如:A/B/C
--@name 要查找的名字
function XLuaUi:FindGameObject(name)
return self.UiProxy:FindGameObject(name)
end
--通过名字查找Transfrom 例如:A/B/C
--@name 要查找的名字
function XLuaUi:FindTransform(name)
return self.UiProxy:FindTransform(name)
end
--打开一个子UI
--@childUIName 子UI名字
--@... 传到OnStart的参数
function XLuaUi:OpenChildUi(childUIName, ...)
self.UiProxy:OpenChildUi(childUIName, ...)
end
--打开一个子UI,会关闭其他已显示的子UI
--@childUIName 子UI名字
--@... 传到OnStart的参数
function XLuaUi:OpenOneChildUi(childUIName, ...)
self.UiProxy:OpenOneChildUi(childUIName, ...)
--self.UiProxy:OpenOneChildUi(childUIName, ...)
end
--关闭子UI
--@childUIName 子UI名字
function XLuaUi:CloseChildUi(childUIName)
self.UiProxy:CloseChildUi(childUIName)
end
--查找子窗口对应的lua对象
--@childUiName 子窗口名字
function XLuaUi:FindChildUiObj(childUiName)
local childUi = self.UiProxy:FindChildUi(childUiName)
if childUi then
return childUi.UiProxy.UiLuaTable
end
end
function XLuaUi:InitUiObjects()
self.Obj = self.Transform:GetComponent("UiObject")
if self.Obj ~= nil then
for i = 0, self.Obj.NameList.Count - 1 do
self[self.Obj.NameList[i]] = self.Obj.ObjList[i]
end
end
end
function XLuaUi:InitChildUis()
if self.Ui == nil then
return
end
if not self.Ui.UiData.HasChildUi then
return
end
local childUis = self.Ui:GetAllChildUis()
if childUis == nil then
return
end
--子UI初始化完成后可在父UI通过self.Child+子UI名称的方式直接获取句柄
local childUiName
for k, v in pairs(childUis) do
childUiName = "Child" .. k
if self[childUiName] then
XLog.Error(string.format("%s该名字已被占用", childUiName))
else
self[childUiName] = v.UiProxy.UiLuaTable
end
end
end
--播放动画只支持Timeline模式
-- 符合以下命名的动画将会自动播放无须手动调用AnimStart、AnimEnable、AnimDisable、AnimDestroy
function XLuaUi:PlayAnimation(animName, callback, beginCallback, wrapMode)
self.UiProxy:PlayAnimation(
animName,
callback,
beginCallback,
wrapMode or CS.UnityEngine.Playables.DirectorWrapMode.Hold
)
end
--播放动画只支持Timeline模式, 增加Mask阻止操作打断动画
function XLuaUi:PlayAnimationWithMask(animName, callback, beginCallback, wrapMode)
self.UiProxy:PlayAnimation(
animName,
function(state)
XLuaUiManager.SetMask(false)
if callback then
callback(state)
end
end,
function()
XLuaUiManager.SetMask(true)
if beginCallback then
beginCallback()
end
end,
wrapMode or CS.UnityEngine.Playables.DirectorWrapMode.Hold
)
end
--获取Open传递的参数
function XLuaUi:GetArgs()
return self.UiProxy:GetArgs()
end
-- 加载(切换)ui场景
function XLuaUi:LoadUiScene(sceneUrl, modelUrl, cb, force)
if force == nil then
force = true
end
self.Ui:LoadUiScene(sceneUrl, modelUrl, force)
self.UiModelGo = self.Ui.UiModelGo
self.UiModel = self.Ui.UiModel
self.UiSceneInfo = self.Ui.UiSceneInfo
if cb then
cb(sceneUrl, modelUrl)
end
end
-- 异步加载(切换)ui场景
function XLuaUi:LoadUiSceneAsync(sceneUrl, modelUrl, cb)
self.Ui:LoadUiSceneAsync(sceneUrl, modelUrl, function()
self.UiModelGo = self.Ui.UiModelGo
self.UiModel = self.Ui.UiModel
self.UiSceneInfo = self.Ui.UiSceneInfo
if cb then
cb(sceneUrl, modelUrl)
end
end)
end
-- 根据名字查找虚拟相机位置
function XLuaUi:FindVirtualCamera(virtualCamName)
local virtualCamTrans = nil
local sceneVirtualCamRoot = self.UiSceneInfo.Transform:FindTransform("UiCamContainer")
if sceneVirtualCamRoot then
virtualCamTrans = sceneVirtualCamRoot:FindTransform(virtualCamName)
if virtualCamTrans then
return virtualCamTrans
end
end
virtualCamTrans = self.UiModelGo:FindTransform(virtualCamName)
return virtualCamTrans
end
-- 默认ui场景路径
function XLuaUi:GetDefaultSceneUrl()
return self.Ui.UiData.SceneUrl
end
-- 默认ui场景模型路径
function XLuaUi:GetDefaultUiModelUrl()
return self.Ui.UiData.UiModelUrl
end
-- 绑定返回/主界面按钮
function XLuaUi:BindExitBtns(btnBack, btnMainUi)
btnBack = btnBack or self.BtnBack
btnMainUi = btnMainUi or self.BtnMainUi
self:RegisterClickEvent(
btnBack,
function()
self:Close()
end
)
self:RegisterClickEvent(
btnMainUi,
function()
XLuaUiManager.RunMain()
end
)
end
-- 绑定帮助按钮
function XLuaUi:BindHelpBtn(btn, helpDataKey, cb, openCb)
btn = btn or self.BtnHelp
helpDataKey = helpDataKey or self.Name
if not btn then
XLog.Error("XLuaUi.BindHelpBtn Error: Buttton Is Nil")
return
end
if not helpDataKey then
XLog.Error("XLuaUi.BindHelpBtn Error: HelpDataKey Is Nil")
return
end
if CS.XTool.ConfirmObjectType(btn, "XUiButton") then
btn.CallBack = function()
if openCb then openCb() end
XUiManager.ShowHelpTip(helpDataKey, cb)
end
return
end
if CS.XTool.ConfirmObjectType(btn, "Button") then
self:RegisterClickEvent(
btn,
function()
if openCb then openCb() end
XUiManager.ShowHelpTip(helpDataKey, cb)
end
)
return
end
XLog.Error("XLuaUi.BindHelpBtn Faild")
end
function XLuaUi:BindHelpBtnNew(btn, getHelpDataFunc, cb)
if not btn then
XLog.Error("XLuaUi.BindHelpBtn Error: Buttton Is Nil")
return
end
if not getHelpDataFunc then
XLog.Error("XLuaUi.BindHelpBtn Error: GetHelpDataFunc Is Nil")
return
end
if CS.XTool.ConfirmObjectType(btn, "XUiButton") then
btn.CallBack = function()
XUiManager.ShowHelpTipNew(getHelpDataFunc, cb)
end
return
end
if CS.XTool.ConfirmObjectType(btn, "Button") then
self:RegisterClickEvent(
btn,
function()
XUiManager.ShowHelpTipNew(getHelpDataFunc, cb)
end
)
return
end
XLog.Error("XLuaUi.BindHelpBtnNew Faild")
end
function XLuaUi:BindHelpBtnOnly(btn)
-- TODO 对帮助按钮进行统一隐藏
end
--添加红点绑定接口优化红点释放问题如果页面重写了OnDisable使用时需要手动在子类调用ReleaseRedPoint方法
function XLuaUi:BindRedPoint(node, func, listener, conditionGroup, args, isCheck)
if not self.RedEventDic then
self.RedEventDic = {}
end
if self.RedEventDic[node] then
return
end
local id = XRedPointManager.AddRedPointEvent(node, func, listener, conditionGroup, args, isCheck)
self.RedEventDic[node] = id
end
function XLuaUi:ReleaseRedPoint()
if XTool.IsTableEmpty(self.RedEventDic) then
return
end
for _, redPointId in ipairs(self.RedEventDic) do
XRedPointManager.RemoveRedPointEvent(redPointId)
end
end
function XLuaUi:AwaitSignal(signalName, fromObj)
if self.SignalData == nil then
self.SignalData = XSignalData.New()
end
return self.SignalData:AwaitSignal(signalName, fromObj)
end
function XLuaUi:EmitSignal(signalName, ...)
if self.SignalData == nil then
return
end
self.SignalData:EmitSignal(signalName, ...)
end
function XLuaUi:CheckHasSignal(signalName, fromObj)
if self.SignalData == nil then
return false
end
return self.SignalData:CheckHasSignal(signalName, fromObj)
end
-- 连接单个信号
function XLuaUi:ConnectSignal(path, event, callback, caller, returnArgKey)
if self.ChildSignalDatas == nil then
-- 对子信号的一个管理,方便页面释放
self.ChildSignalDatas = {}
end
table.insert(self.ChildSignalDatas, XTool.ConnectSignal(self, path, event, callback, caller, returnArgKey))
end
-- 连接多个信号
function XLuaUi:ConnectSignals(path, event, callback, caller)
if self.ChildSignalDatas == nil then
-- 对子信号的一个管理,方便页面释放
self.ChildSignalDatas = {}
end
appendArray(self.ChildSignalDatas, XTool.ConnectSignals(self, path, event, callback, caller))
end
function XLuaUi:GetSignalData()
if self.SignalData == nil then
self.SignalData = XSignalData.New()
end
return self.SignalData
end
-- value : XSignalData
function XLuaUi:AddChildSignalData(value)
if self.ChildSignalDatas == nil then
self.ChildSignalDatas = {}
end
table.insert(self.ChildSignalDatas, value)
end
--[[ 绑定ViewModel层属性到Ui对象单向绑定
@param viewModel:XDataEntityBase
@param propertyName:viewModel字段名称
@param func:更新函数闭包
]]
function XLuaUi:BindViewModelPropertyToObj(viewModel, func, propertyName)
self._ViewModelDic = self._ViewModelDic or {}
self._ViewModelDic[viewModel] = self._ViewModelDic[viewModel] or viewModel
viewModel:BindPropertyToObj(self.Name, func, propertyName)
end
--[[ 绑定ViewModel层属性到Ui对象单向多重绑定
@param viewModel:XDataEntityBase
@param func:更新函数闭包
@param ...:多个viewModel字段名称
]]
function XLuaUi:BindViewModelPropertiesToObj(viewModel, func, ...)
self._ViewModelDic = self._ViewModelDic or {}
self._ViewModelDic[viewModel] = self._ViewModelDic[viewModel] or viewModel
viewModel:BindPropertiesToObj(self.Name, func, ...)
end
--根据指定模板创建一批格子并刷新对应格子视图数据
function XLuaUi:RefreshTemplateGrids(templateGo, dataList, parents, ctor, name, refreshFunc)
self._GridsDic = self._GridsDic or {}
name = name or "_DefualtGrids"
local grids = self._GridsDic[name] or {}
local multiTemplateGo = false --有些情况下无需copy格子直接传入UI做好的格子gameobject
if type(templateGo) == "table" then
multiTemplateGo = true
for _, go in pairs(templateGo) do
go.gameObject:SetActiveEx(false)
end
else
templateGo.gameObject:SetActiveEx(false)
end
--有些情况下可能需要挂载不同的父节点
local multiParents = type(parents) == "table"
for index, data in ipairs(dataList) do
local grid = grids[index]
if not grid then
local parent = multiParents and parents[index] or parents
local go
if multiTemplateGo then
go = templateGo[index]
else
if parent then
go = CSObjectInstantiate(templateGo, parent)
else
go = templateGo
end
end
if ctor then
if type(ctor) == "function" then
grid = ctor()
else
grid = ctor.New()
end
else
grid = {}
end
--统一构造函数,省略冗余代码
grid.Index = index
grid.GameObject = go.gameObject
grid.Transform = go.transform
grid.Parent = self
XTool.InitUiObject(grid)
if grid.Init then
grid:Init()
end
grids[index] = grid
end
--先显示再刷新,避免动画被打断
grid.GameObject:SetActiveEx(true)
if refreshFunc then
refreshFunc(grid, data)
elseif grid.Refresh then
grid:Refresh(data)
end
end
for index = #dataList + 1, #grids do
grids[index].GameObject:SetActiveEx(false)
end
self._GridsDic[name] = grids
end
--根据数据列表获取已经创建过的格子
function XLuaUi:GetGrid(index, name)
if XTool.IsTableEmpty(self._GridsDic) then
return
end
name = name or "_DefualtGrids"
return self._GridsDic[name] and self._GridsDic[name][index]
end
------------------------------------------------------------------------------------------------------------------------
XLuaUiCheckGC = XClass(XLuaUi, "XLuaUiCheckGC")
function XLuaUiCheckGC:Ctor()
XLog.Warning(string.format("====================%sUi已创建", self.Name))
local metatable = getmetatable(self)
-- metatable.__mode = "kv"
metatable.__gc = function()
XLog.Warning(string.format("====================%sUi已释放", self.Name))
end
setmetatable(self, metatable)
end
-- function XLuaUiCheckGC:OnRelease()
-- XLuaUiCheckGC.Super.OnRelease(self)
-- end
------------------------------------------------------------------------------------------------------------------------
---@class XLuaUiManager
XLuaUiManager = XClass(nil, "XLuaUiManager")
local UiData = {}
local ClassType = {}
local ImportModule = {}
local XUiPrefix = "XUi/X%s/X%s"
local UiMainName = "UiMain"
local Registry = require("UiRegistry")
--- 注册Ui
---@param super XLuaUi 父类
---@param uiName string ui名
---@return XLuaUi
--------------------------
function XLuaUiManager.Register(super, uiName)
super = super or XLuaUi
local uiObject = XClass(super, uiName)
ClassType[uiName] = uiObject
return uiObject
end
--创建一个LuaUI的实例
--@name LuaUI脚本名字
--@gameUI C#的GameUI
function XLuaUiManager.New(uiName, uiProxy)
local baseName = uiName
local class = ClassType[baseName]
if not class then
local register = Registry[baseName]
if register then
require(register)
end
class = ClassType[baseName]
end
if not class then
baseName = string.match(baseName, "%w*[^(%d)$*]") -- 解析包含数字后缀的界面
class = ClassType[baseName]
if not class then
XLog.Error("XLuaUiManager.New error, class not exist, name: " .. uiName)
return nil
end
end
local obj = class.New(uiName, uiProxy)
uiProxy:SetLuaTable(obj)
return obj
end
--打开UI
--@uiName 打开的UI名字
function XLuaUiManager.Open(uiName, ...)
CsXUiManager.Instance:Open(uiName, ...)
end
--打开UI完成后执行回调
--@uiName 打开的UI名称
--@callback 打开完成回调
--@... 传递到OnStart的参数
function XLuaUiManager.OpenWithCallback(uiName, callback, ...)
CsXUiManager.Instance:OpenWithCallback(uiName, callback, ...)
end
--关闭UI完成后执行回调
--@uiName 打开的UI名称
--@callback 打开完成回调
function XLuaUiManager.CloseWithCallback(uiName, callback)
CsXUiManager.Instance:CloseWithCallback(uiName, callback)
end
--针对Normal类型的管理关闭上一个界面然后打开下一个界面无缝切换
--@uiName 需要打开的UI名字
--@... 传递到OnStart的参数
function XLuaUiManager.PopThenOpen(uiName, ...)
CsXUiManager.Instance:PopThenOpen(uiName, ...)
end
--针对Normal类型的管理关闭栈中所有界面然后打开下一个界面无缝切换
--@uiName 需要打开的UI名字
--@... 传递到OnStart的参数
function XLuaUiManager.PopAllThenOpen(uiName, ...)
CsXUiManager.Instance:PopAllThenOpen(uiName, ...)
end
--关闭UI
--@uiName 关闭的UI名字(只能关闭当前显示的UI)
function XLuaUiManager.Close(uiName)
CsXUiManager.Instance:Close(uiName)
end
--移除UI,移除的UI不会播放进场、退场动画
--@uiName 关闭的UI名字可以关闭非当前显示UI
function XLuaUiManager.Remove(uiName)
CsXUiManager.Instance:Remove(uiName)
end
--某个UI是否显示
function XLuaUiManager.IsUiShow(uiName)
return CsXUiManager.Instance:IsUiShow(uiName)
end
--某个UI是否正在推入中打开即推入Awake推出
function XLuaUiManager.IsUiPushing(uiName)
return CsXUiManager.Instance:IsUiPushing(uiName)
end
--某个UI是否已经加载
function XLuaUiManager.IsUiLoad(uiName)
return CsXUiManager.Instance:IsUiLoad(uiName)
end
local _MaskCount = {}
--设置maskvisible=true时不能操作
function XLuaUiManager.SetMask(visible, key)
visible = visible and true or false
CsXUiManager.Instance:SetMask(visible)
-- key分类计数
if key then
if not _MaskCount[key] then
_MaskCount[key] = 0
end
if visible then
_MaskCount[key] = _MaskCount[key] + 1
else
_MaskCount[key] = math.max(_MaskCount[key] - 1, 0)
end
end
end
function XLuaUiManager.IsMaskShow(key)
if not key then
XLog.Error("[XLuaUiManager] 不支持获取计数")
return false
end
return (_MaskCount[key] or 0) > 0
end
--设置animationMasktag标签,visible=true时不能操作delay(默认2秒)后会展示菊花
function XLuaUiManager.SetAnimationMask(tag, visible, delay)
visible = visible and true or false
delay = delay or 2
CsXUiManager.Instance:SetAnimationMask(tag, visible, delay)
end
function XLuaUiManager.ClearMask(resetMaskCount)
resetMaskCount = resetMaskCount and true or false
if resetMaskCount then
_MaskCount = {}
end
CsXUiManager.Instance:ClearMask(resetMaskCount)
end
function XLuaUiManager.ClearAnimationMask()
CsXUiManager.Instance:ClearAnimationMask()
end
function XLuaUiManager.ClearAllMask(resetMaskCount)
XLuaUiManager.ClearMask(resetMaskCount)
CsXUiManager.Instance:ClearAnimationMask()
end
function XLuaUiManager.TryImportLuaFile(name)
local module = ImportModule[name]
if module then
return
end
local str = string.format(XUiPrefix, name, name)
XLog.Error(str)
require(str)
ImportModule[name] = 1
end
--返回主界面
function XLuaUiManager.RunMain(notDialogTip)
--CsXUiManager.Instance:Clear()
local needClearUiName = {
"UiFubenMainLineChapter",
"UiFubenMainLineChapterFw",
"UiFubenMainLineChapterDP",
"UiPrequel"
}
for _, uiName in pairs(needClearUiName) do
XLuaUiManager.RemoveUiData(uiName)
end
if XDataCenter.RoomManager.RoomData then
if notDialogTip then
XDataCenter.RoomManager.Quit(
function()
CsXUiManager.Instance:RunMain()
end
)
return
end
-- 如果在房间中,需要先弹确认框
local title = CsXTextManagerGetText("TipTitle")
local cancelMatchMsg
local stageId = XDataCenter.RoomManager.RoomData.StageId
local stageInfo = XDataCenter.FubenManager.GetStageInfo(stageId)
if stageInfo.Type == XDataCenter.FubenManager.StageType.ArenaOnline then
cancelMatchMsg = CsXTextManagerGetText("ArenaOnlineInstanceQuitRoom")
else
cancelMatchMsg = CsXTextManagerGetText("OnlineInstanceQuitRoom")
end
XUiManager.DialogTip(
title,
cancelMatchMsg,
XUiManager.DialogType.Normal,
nil,
function()
XDataCenter.RoomManager.Quit(
function()
CsXUiManager.Instance:RunMain()
end
)
end
)
elseif XDataCenter.RoomManager.Matching then
if notDialogTip then
XDataCenter.RoomManager.CancelMatch(
function()
CsXUiManager.Instance:RunMain()
end
)
return
end
local title = CsXTextManagerGetText("TipTitle")
local cancelMatchMsg = CsXTextManagerGetText("OnlineInstanceCancelMatch")
XUiManager.DialogTip(
title,
cancelMatchMsg,
XUiManager.DialogType.Normal,
nil,
function()
XDataCenter.RoomManager.CancelMatch(
function()
CsXUiManager.Instance:RunMain()
end
)
end
)
elseif XDataCenter.DlcRoomManager.IsInRoom() then
XDataCenter.DlcRoomManager.DialogTipQuitRoom(function()
CsXUiManager.Instance:RunMain()
end)
else
local unionFightData = XDataCenter.FubenUnionKillRoomManager.GetUnionRoomData()
local unionInfo = XDataCenter.FubenUnionKillManager.GetUnionKillInfo()
local inActivity = false
if unionInfo and unionInfo.Id and unionInfo.Id > 0 then
inActivity = XFubenUnionKillConfigs.UnionKillInActivity(unionInfo.Id)
end
if inActivity and unionFightData and unionFightData.Id then
if notDialogTip then
XDataCenter.FubenUnionKillRoomManager.LeaveUnionTeamRoom(function()
CsXUiManager.Instance:RunMain()
end)
return
end
local title = CsXTextManagerGetText("TipTitle")
local cancelMatchMsg = CsXTextManagerGetText("UnionKillExitRoom")
XUiManager.DialogTip(
title,
cancelMatchMsg,
XUiManager.DialogType.Normal,
nil, function()
XDataCenter.FubenUnionKillRoomManager.LeaveUnionTeamRoom(function()
CsXUiManager.Instance:RunMain()
end)
end
)
else
if XLoginManager.IsFirstOpenMainUi() then
CS.XCustomUi.Instance:GetData()
end
CsXUiManager.Instance:RunMain()
end
end
end
function XLuaUiManager.ShowTopUi()
CsXUiManager.Instance:ShowTopUi()
end
--获取ui状态
function XLuaUiManager.GetUiData(uiName)
if UiData then
return UiData[uiName]
end
end
--缓存ui状态
function XLuaUiManager.SetUiData(uiName, data)
UiData = UiData and UiData or {}
UiData[uiName] = data
end
function XLuaUiManager.RemoveUiData(uiName)
if UiData then
UiData[uiName] = nil
end
end
function XLuaUiManager.FindTopUi(uiname)
return CsXUiManager.Instance:FindTopUi(uiname)
end
function XLuaUiManager.GetTopUiName()
return CsXUiManager.Instance:GetTopUiName()
end
-- 等待uiname页面signalName信号
function XLuaUiManager.AwaitSignal(uiname, signalName, fromObj)
local luaUi = XLuaUiManager.FindTopUi(uiname)
if luaUi == nil then return XSignalCode.EMPTY_UI end
luaUi = luaUi.UiProxy
if luaUi == nil then return XSignalCode.EMPTY_UI end
luaUi = luaUi.UiLuaTable
if luaUi == nil then return XSignalCode.EMPTY_UI end
return luaUi:AwaitSignal(signalName, fromObj)
end
function XLuaUiManager.GetTopLuaUi(uiname)
local luaUi = XLuaUiManager.FindTopUi(uiname)
if luaUi == nil then return nil end
luaUi = luaUi.UiProxy
if luaUi == nil then return nil end
luaUi = luaUi.UiLuaTable
if luaUi == nil then return nil end
return luaUi
end
function XLuaUiManager.SafeClose(uiName)
if XLuaUiManager.IsUiShow(uiName) then
XLuaUiManager.Close(uiName)
return
end
XLuaUiManager.Remove(uiName)
end
function XLuaUiManager.OpenSingleUi(uiName, ...)
if XLuaUiManager.IsUiShow(uiName) then
XLuaUiManager.Close(uiName)
elseif XLuaUiManager.IsUiLoad(uiName) then
XLuaUiManager.Remove(uiName)
end
XLuaUiManager.Open(uiName, ...)
end
function XLuaUiManager.RemoveTopOne(uiName)
CsXUiManager.Instance:RemoveTopOne(uiName)
end