2025-06-04 05:02:57 +08:00

412 lines
11 KiB
Plaintext
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.

autoImport("UINode")
autoImport("LStack")
autoImport("EventDispatcher")
--UILayer是UI的層級管理者管理UINode節點包括他們的depth、顯示隱藏、銷燬
--UILayer自己也能整體顯示和隱藏並且自己的gameobject名字為-->L{層級}_{層級名字}({uinode數量})({子uipanel數量})
--每層uilayer間隔配置15 depth如有collider墊板層的Layer,墊板層為layer最低層
UILayer = class("UILayer",EventDispatcher)
UILayer.AddChildEvent = "UILayer_AddChildEvent"
UILayer.EmptyChildEvent = "UILayer_EmptyChildEvent"
UILayer.ShowPos = Vector3.zero
UILayer.HidePos = Vector3(-10000,-10000,0)
function UILayer:ctor(data,root)
self.data = data
self.showHideMode = (self.data.showHideMode ~= nil and self.data.showHideMode or LayerShowHideMode.MoveOutAndMoveIn)
self.depthGap = 15
self.nodes = {}
self.hideMasters = {}
self.panelNum = 0
self.name = data.name
self.depth = data.depth
self.gameObject = GameObject()
self.panel = self.gameObject:AddComponent(UIPanel)
self.panel.depth = self.depth * self.depthGap
self.cachedNode = {}
self.stack = LStack.new()
-- GameObject.DontDestroyOnLoad(tempObj)
self.uiRoot = root
GameObjectUtil.Instance:ChangeLayersRecursively(self.gameObject,"UI")
self.gameObject.transform:SetParent(self.uiRoot.transform,false)
self:TryCreateColliderMask()
self:Rename()
self:InitShowHideModeCall()
end
function UILayer:StartDepth()
return self.data.depth * self.depthGap
end
function UILayer:UINodeStartDepth()
return self:StartDepth() + 1
end
function UILayer:TryCreateColliderMask()
if(self.data and self.data.coliderColor and not self.colliderMask) then
self.colliderMask = Game.AssetManager_UI:CreateAsset(ResourcePathHelper.UIView("ColliderView")):GetComponent(UIPanel);
self.colliderMaskContainer = GameObject("MaskContainer")
self.colliderMaskContainer.transform:SetParent(self.gameObject.transform,false)
self.colliderMask.transform:SetParent(self.colliderMaskContainer.transform,false)
self.colliderMask.depth = self:StartDepth()
local sprite = self.colliderMask.gameObject:GetComponentInChildren(UISprite)
sprite.color = self.data.coliderColor;
self:HideMask()
end
end
function UILayer:Rename()
self.gameObject.name = string.format("L%s_%s(%s)(%s)(%s)",self.depth,self.name,#self.nodes,self:GetPanelNum(),self.stack:GetCount())
end
function UILayer:AddHideMasterLayer(layer)
if(TableUtil.ArrayIndexOf(self.hideMasters,layer)==0) then
self.hideMasters[#self.hideMasters + 1] = layer
self:Hide()
end
end
function UILayer:RemoveHideMasterLayer(layer)
if(TableUtil.Remove(self.hideMasters,layer)>0) then
if(#self.hideMasters == 0) then
self:Show()
end
end
end
function UILayer:Show()
-- print(string.format("%s layer show",self.name))
if(self.showHideMode == LayerShowHideMode.ActiveAndDeactive) then
if(self.gameObject)then
self.gameObject:SetActive(true)
end
else
if(self.gameObject)then
self.gameObject.transform.localPosition = UILayer.ShowPos
end
if(self.colliderMaskContainer and not self.colliderMaskContainer.activeSelf) then
self.colliderMaskContainer:SetActive(true)
end
-- if(self.gameObject and not self.gameObject.activeSelf) then
-- self.gameObject:SetActive(true)
-- end
end
for i=1,#self.nodes do
self.nodes[i]:OnShow()
end
end
function UILayer:Hide()
-- print(string.format("%s layer hide",self.name))
if(self.showHideMode == LayerShowHideMode.ActiveAndDeactive) then
if(self.gameObject)then
self.gameObject:SetActive(false)
end
else
if(self.gameObject)then
self.gameObject.transform.localPosition = UILayer.HidePos
end
if(self.colliderMaskContainer and self.colliderMaskContainer.activeSelf) then
self.colliderMaskContainer:SetActive(false)
end
-- if(self.gameObject and self.gameObject.activeSelf) then
-- self.gameObject:SetActive(false)
-- end
end
for i=1,#self.nodes do
self.nodes[i]:OnHide()
end
end
function UILayer:ShowMask()
if(self.colliderMask and not self.colliderMask.gameObject.activeSelf) then
self.colliderMask.gameObject:SetActive(true)
end
end
function UILayer:HideMask()
if(self.colliderMask and self.colliderMask.gameObject.activeSelf) then
self.colliderMask.gameObject:SetActive(false)
end
end
function UILayer:GetPanelNum()
local num = 0
for i=1,#self.nodes do
num = num + self.nodes[i]:GetPanelNum()
end
return num
end
function UILayer:NodeCoExist(newNode)
local can = false
for i=1,#self.nodes do
if(newNode~=self.nodes[i] and newNode:CanCoExist(self.nodes[i])) then
can = true
end
end
return can
end
function UILayer:FindNodeFunc(cond,param)
for i=1,#self.nodes do
if(cond == self.nodes[i][param]) then
return self.nodes[i]
end
end
return nil
end
function UILayer:FindNode(ctrl)
return self:FindNodeFunc(ctrl,"viewCtrl")
end
function UILayer:FindNodeByName(ctrl)
return self:FindNodeFunc(ctrl,"viewname")
end
function UILayer:FindNodeByClassName(class)
return self:FindNodeFunc(class,"class")
end
function UILayer:CreateChild(data,prefab,class,needRollBack)
local node = self:FindNodeByName(data.viewname or prefab)
if(node and not self.data.reEntnerNotDestory) then
self:DestoryChild(node)
node = nil
end
if(not node) then
local viewClass = UINode.GetImport( class or data.viewname)
node = self.cachedNode[viewClass.__cname]
if(not node) then
node = UINode.new(data,prefab,class,self,needRollBack)
node:Create()
else
node:ResetViewData(data)
self.cachedNode[viewClass.__cname] = nil
end
self:AddChild(node)
end
return node
end
function UILayer:IndexOfSameUINode(node,compareNode)
return node.viewClass == compareNode.viewClass
end
function UILayer:PushToStack(previous,node)
local stackCount = self.stack:GetCount()
if(not node.needRollBack) then
self.stack:Clear()
end
if(node.needRollBack) then
local findSameDepth = self.stack:GetDepthByFunc(node,self.IndexOfSameUINode,self)
if(findSameDepth>0) then
--找到相同的
if(findSameDepth == stackCount) then
--同個界面,忽略
return
else
--清除之前的
self.stack:RemoveNum(findSameDepth)
end
end
if(previous:GetShowHideMode() == PanelShowHideMode.CreateAndDestroy) then
previous = previous:Clone()
end
self.stack:Push(previous)
end
end
function UILayer:TryRollBackPrevious()
local previous = self.stack:Pop()
if(previous) then
print("返回上一級界面")
previous:Create()
return self:AddChild(previous,false)
end
return false
end
function UILayer:AddChild(node,pushStack)
if(pushStack == nil) then
pushStack = true
end
if(node and not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject)) then
if(node.layer~=self) then
if(node.layer) then
node.layer:RemoveChild(node)
end
node:SetLayer(self)
end
--如果新的UI節點無法與目前的共存則銷燬目前UI
if(not self:NodeCoExist(node)) then
if(pushStack) then
for i=1,#self.nodes do
self:PushToStack(self.nodes[i],node)
end
end
self:DestoryAllChildren()
end
self.nodes[#self.nodes + 1] = node
if(#self.nodes == 1) then
self:DispatchEvent(UILayer.AddChildEvent)
end
self:ModeShow(node)
node:OnEnter()
node:SetDepth(self:UINodeStartDepth())
self:Rename()
--面板中可選擇是否需要擋板
if(node.data.view and node.data.view.hideCollider) then
self:HideMask()
else
self:ShowMask()
end
return true
else
printRed(string.format("%s Layer想新增一個不存在的uinode",self.name))
end
return false
end
function UILayer:RemoveChild(node)
if(node and TableUtil.Remove(self.nodes,node)>0) then
node:SetLayer(nil)
node:OnHide()
node:OnExit()
self:Rename()
if(#self.nodes==0) then
self:DispatchEvent(UILayer.EmptyChildEvent)
self:HideMask()
end
return true
end
return false
end
function UILayer:RemoveChildByCtrl(ctrl)
local node = self:FindNode(ctrl)
return self:RemoveChild(node)
end
function UILayer:DestoryChildByCtrl(ctrl)
local node = self:FindNode(ctrl)
return self:DestoryChild(node)
end
function UILayer:DestoryChild(node)
if(node and node.layer == self) then
self:RemoveChild(node)
-- self.cachedNode[node.viewClass.__cname] = node
self:ModeHide(node)
-- node:Dispose()
-- node = nil
end
end
function UILayer:DestoryAllChildren()
for k,v in pairs(self.nodes) do
self:DestoryChild(v)
end
self:DispatchEvent(UILayer.EmptyChildEvent)
self.nodes = {}
self:Rename()
self:HideMask()
end
function UILayer:InitShowHideModeCall()
self.ShowCallByMode = {}
self.ShowCallByMode[PanelShowHideMode.CreateAndDestroy] = self.ModeCreateShow
self.ShowCallByMode[PanelShowHideMode.ActiveAndDeactive] = self.ModeActiveShow
self.ShowCallByMode[PanelShowHideMode.MoveOutAndMoveIn] = self.ModeMoveInShow
self.HideCallByMode = {}
self.HideCallByMode[PanelShowHideMode.CreateAndDestroy] = self.ModeDestroyHide
self.HideCallByMode[PanelShowHideMode.ActiveAndDeactive] = self.ModeDeActiveHide
self.HideCallByMode[PanelShowHideMode.MoveOutAndMoveIn] = self.ModeMoveOutHide
end
function UILayer:ModeShow(node)
if(node) then
local func = self.ShowCallByMode[node:GetShowHideMode()]
if(func==nil) then
func = self.ModeCreateShow
end
if(func) then
func(self,node)
end
end
end
function UILayer:ModeHide(node)
if(node) then
local func = self.HideCallByMode[node:GetShowHideMode()]
if(func==nil) then
func = self.ModeDestroyHide
end
if(func) then
func(self,node)
end
end
end
function UILayer:ModeCreateShow(node)
if(not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject) ) then
node.gameObject.transform:SetParent(self.gameObject.transform,false)
end
end
function UILayer:ModeActiveShow(node)
if(not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject) ) then
if(node.gameObject.transform.parent ~= self.gameObject.transform) then
node.gameObject.transform:SetParent(self.gameObject.transform,false)
end
if(node:MediatorReActive()) then
node:RegisterMediator()
end
node:Show()
end
end
function UILayer:ModeMoveInShow(node)
if(not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject) ) then
if(node.gameObject.transform.parent ~= self.gameObject.transform) then
node.gameObject.transform:SetParent(self.gameObject.transform,false)
end
if(node:MediatorReActive()) then
node:RegisterMediator()
end
node.gameObject.transform.localPosition = UILayer.ShowPos
end
end
function UILayer:ModeDestroyHide(node)
node:Dispose()
end
function UILayer:ModeDeActiveHide(node)
if(not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject) ) then
self.cachedNode[node.viewClass.__cname] = node
node:Hide()
if(node:MediatorReActive()) then
node:UnRegisterMediator()
end
end
end
function UILayer:ModeMoveOutHide(node)
if(not GameObjectUtil.Instance:ObjectIsNULL(node.gameObject) ) then
self.cachedNode[node.viewClass.__cname] = node
node.gameObject.transform.localPosition = UILayer.HidePos
if(node:MediatorReActive()) then
node:UnRegisterMediator()
end
end
end