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