/**
 * UI 的渲染在 v3.0 变为使用 node.layer 来判断可见性，为了保证老版本项目升级后表现一致，
 * Creator 会在运行时动态分配一个未使用的 layer 给常驻节点的 UI，避免常驻节点的 UI 与场景中
 * 的其他 UI 的 layer 发生冲突，当你确定不会发生冲突时，你可以移除此脚本.
 *
 * UI rendering has changed in v3.0 to use node.layer to determine visibility.
 * To ensure consistent performance after upgrading old projects.
 * Creator will dynamically assign an unused layer to the UI node in the persist node at
 * runtime to avoid conflicts between the layer of UI in the persist node and the
 * layer of other UI in the scene. You can remove this script when you
 * are sure there is no conflict
 */ import { _decorator , Node , director , Director , game , BaseNode , Canvas , Camera } from 'cc' ; const customLayerMask = 0x000fffff ; const builtinLayerMask = 0xfff00000 ; director . on ( Director . EVENT_AFTER_SCENE_LAUNCH , ( ) => { const roots = director . getScene ( ) ?. children as BaseNode [ ] ; let allCanvases = director . getScene ( ) ?. getComponentsInChildren ( Canvas ) as Canvas [ ] ; if ( allCanvases . length <= 1 ) return ; allCanvases = allCanvases . filter ( x => ! ! x . cameraComponent ) ; let allCameras = director . getScene ( ) ?. getComponentsInChildren ( Camera ) as Camera [ ] ; let usedLayer = 0 ; allCameras . forEach ( x => usedLayer |= ( x . visibility & customLayerMask ) ) ; const persistCanvas = [ ] ; for ( let i = 0 , l = roots . length ; i < l ; i ++ ) { const root = roots [ i ] ; if ( ! game . isPersistRootNode ( root ) ) continue ; const canvases = root . getComponentsInChildren ( Canvas ) ; if ( canvases . length === 0 ) continue ; persistCanvas . push ( ... canvases . filter ( x => ! ! x . cameraComponent ) ) ; } persistCanvas . forEach ( ( val ) => { const isLayerCollided = allCanvases . find ( x => x !== val && ( x . cameraComponent ! . visibility & val . cameraComponent ! . visibility & customLayerMask ) ) ; if ( isLayerCollided ) { const availableLayers = ~ usedLayer ; const lastAvailableLayer = availableLayers & ~ ( availableLayers - 1 ) ; val . cameraComponent ! . visibility = lastAvailableLayer | ( val . cameraComponent ! . visibility & builtinLayerMask ) ; setChildrenLayer ( val . node , lastAvailableLayer ) ; usedLayer |= availableLayers ; } } ) ; } ) ; function setChildrenLayer ( node , layer ) { for ( let i = 0 , l = node . children . length ; i < l ; i ++ ) { node . children [ i ] . layer = layer ; setChildrenLayer ( node . children [ i ] , layer ) ; } } let setParentEngine = cc . Node . prototype . setParent ; cc . Node . prototype . setParent = function ( value , keepWorldTransform ) { setParentEngine . call ( this , value , keepWorldTransform ) ; if ( ! value ) return ; let layer = getCanvasCameraLayer ( this ) ; if ( layer ) { this . layer = layer ; setChildrenLayer ( this , layer ) ; } } ; function getCanvasCameraLayer ( node ) { let layer = null ; let canvas = node . getComponent ( Canvas ) ; if ( canvas && canvas . cameraComponent ) { if ( canvas . cameraComponent . visibility & canvas . node . layer ) { layer = canvas . node . layer ; } else { layer = canvas . cameraComponent . visibility & ~ ( canvas . cameraComponent . visibility - 1 ) ; } return layer ; } if ( node . parent ) { layer = getCanvasCameraLayer ( node . parent ) ; } return layer ; }