123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /** @format */
- import {Data, Mgr} from '../GameControl'
- import {Log} from '../utils/LogUtils'
- import {ccUtils} from '../utils/ccUtils'
- import {GAME_TYPE} from '../enums/Enum'
- import Bundle = cc.AssetManager.Bundle
- import {UI} from '../enums/UI'
- /**
- * BaseUI界面基础类
- *
- * 1. 快速关闭与屏蔽点击的选项配置
- * 2. 界面缓存设置(开启后界面关闭不会被释放,以便下次快速打开)
- * 3. 界面显示类型配置
- *
- * 4. 加载资源接口(随界面释放自动释放),this.loadRes(xxx)
- * 5. 由UIManager释放
- *
- * 5. 界面初始化回调(只调用一次)
- * 6. 界面打开回调(每次打开回调)
- * 7. 界面打开动画播放结束回调(动画播放完回调)
- * 8. 界面关闭回调
- * 9. 界面置顶回调
- *
- */
- const {ccclass, property} = cc._decorator
- /** 界面展示类型 */
- export enum UIShowTypes {
- UISingle, // 单界面显示
- UIAddition = 500, // 叠加显示
- UITop = 1000, // 最上层显示,消息弹窗,悬浮提示等UI
- }
- @ccclass
- export class BaseUI extends cc.Component {
- /** 快速关闭 */
- @property()
- quickClose: boolean = false
- /** 屏蔽点击选项 在UIConf设置屏蔽点击*/
- // @property
- // preventTouch: boolean = true;
- /** 缓存选项 */
- @property()
- cache: boolean = false
- /** 界面显示类型 */
- @property({type: cc.Enum(UIShowTypes)})
- showType: UIShowTypes = UIShowTypes.UISingle
- /** 阻止点击事件穿透 */
- @property()
- prevent: boolean = true
- /** 界面id */
- public uiID: number = 0
- /** 通过全局预制体加载的节点 */
- public itemsNodes: cc.Node[] = []
- private loadAsset: any[] = []
- private nodeLoadingMap: Map<cc.Node, boolean> = new Map()
- private nodeLoadInfoMap: Map<cc.Node, any[]> = new Map()
- /********************** UI的回调 ***********************/
- /**
- * 当界面被创建时回调,生命周期内只调用
- * @param args 可变参数
- */
- public init(...args): void {}
- /**
- * 当界面被打开时回调,每次调用Open时回调
- * @param args 可变参数
- * @param fromUI 从哪个UI打开的
- */
- public onShow(args, fromUI: number): void {}
- /**
- * 每次界面Open动画播放完毕时回调
- */
- public onOpenAniOver(): void {}
- /**
- * 当界面被关闭时回调,每次调用Close时回调
- * 返回值会传递给下一个界面
- */
- public onHide(): any {}
- /**
- * 当界面被置顶时回调,Open时并不会回调该函数
- * @param preID 前一个ui
- * @param args 可变参数,
- */
- public onTop(preID: number, ...args): void {}
- /**
- * 隐藏当前界面
- */
- public hide(): void {
- Mgr.ui.hideBaseUI(this)
- }
- /**
- * 动态加载加入引用计数
- * @param bundle
- * @param url
- * @param node
- * @param childUrl
- */
- public load<T extends cc.Asset>(
- bundle: cc.AssetManager.Bundle,
- url: string,
- type: typeof cc.Asset,
- onComplete?: (error: Error, assets: T) => void,
- node?: cc.Node,
- childUrl?: string,
- addRef?: boolean,
- notRecordRef?: boolean,
- ) {
- if ((node && !cc.isValid(node)) || !bundle) {
- cc.warn(
- 'BaseUI.load node is not Valid:',
- (node && !cc.isValid(node)) == true,
- 'bundle is Valid:',
- cc.isValid(bundle),
- )
- return
- }
- if (childUrl) {
- const child = cc.find(childUrl, node)
- if (child) {
- node = cc.find(childUrl, node)
- }
- }
- let sprite
- if (node) {
- sprite = node.getComponent(cc.Sprite)
- }
- if (sprite && sprite.spriteFrame && !notRecordRef) {
- let index = this.loadAsset.findIndex(value => value.asset == sprite.spriteFrame)
- if (index >= 0) {
- let data = this.loadAsset[index]
- if (data.sprite == sprite && data.url == bundle.name + url) {
- //相同的sprite重复加载了同一个资源,return
- return
- }
- if (sprite.addRefTag) {
- sprite.spriteFrame = null
- let same = this.loadAsset.splice(index, 1)
- same[0].asset.decRef()
- if (same[0].asset.refCount < 0) {
- console.error('refCount < 0', same[0].asset)
- }
- }
- //console.log(same[0].name, '--->uuid:', same[0]['_uuid'], '-->已在预制体加载计数-1')
- }
- }
- let onCompleteFuc = (err, asset: T) => {
- if (!err && this.node.activeInHierarchy) {
- let data: any = {asset: asset, url: bundle.name + url, addRef, decRef: false}
- if (type == cc.SpriteFrame) {
- if (!sprite) console.error('sprite is null', 'node.name-->', node.name, 'childUrl-->', childUrl)
- sprite.spriteFrame = asset
- data.sprite = sprite
- sprite.addRefTag = addRef
- }
- if (type == cc.AnimationClip) {
- data.animation = node.getComponent(cc.Animation)
- }
- if (!notRecordRef) {
- if (addRef) {
- asset.addRef()
- data.decRef = url.includes(UI[this.uiID])
- // console.log(
- // asset.name,
- // '--->uuid:',
- // asset['_uuid'],
- // '-->计数+1',
- // '-->isValid:',
- // asset.isValid,
- // asset,
- // )
- } else {
- if (type == cc.SpriteFrame) {
- let index = this.loadAsset.findIndex(value => value.asset == asset && !value.addRef)
- if (index == -1) {
- // console.log(
- // asset.name,
- // '--->uuid:',
- // asset['_uuid'],
- // '-->计数只为1',
- // '-->isValid:',
- // asset.isValid,
- // asset,
- // )
- asset.addRef()
- data.decRef = url.includes(UI[this.uiID])
- }
- }
- }
- this.loadAsset.push(data)
- }
- } else if (err) {
- //console.log(err)
- }
- onComplete && onComplete(err, asset)
- let arr = this.nodeLoadInfoMap.get(node)
- if (arr && arr.length > 0) {
- let info = arr.shift()
- bundle.load(info.url, info.type, info.onCompleteFuc)
- } else {
- this.nodeLoadingMap.set(node, false)
- }
- }
- if (node) {
- let isLoading = this.nodeLoadingMap.get(node)
- if (!isLoading) {
- this.nodeLoadingMap.set(node, true)
- // 等待当前资源释放帧结束,不然会有概率加载重复资源时完成时间小于资源释放,导致被提前释放
- this.scheduleOnce(() => {
- bundle.load(url, type, onCompleteFuc)
- })
- } else {
- let arr = this.nodeLoadInfoMap.get(node)
- if (arr) {
- arr.push({url, type, onCompleteFuc})
- } else {
- arr = [{url, type, onCompleteFuc}]
- this.nodeLoadInfoMap.set(node, arr)
- }
- }
- } else {
- bundle.load(url, type, onCompleteFuc)
- }
- }
- public loadTexImg(url: string, node?: cc.Node, childUrl?: string, addRef?: boolean) {
- this.load(Data.main.texBundle, url, cc.SpriteFrame, null, node, childUrl, addRef)
- }
- public loadNotRefTexImg(url: string, node?: cc.Node, childUrl?: string) {
- this.load(Data.main.texBundle, url, cc.SpriteFrame, null, node, childUrl, false, true)
- }
- /**
- * 减去当前UI生命周期内动态加载的资源引用
- */
- public decAllRef(): void {
- for (let i = this.itemsNodes.length - 1; i > 0; i--) {
- let node = this.itemsNodes.splice(i, 1)
- if (node[0]['uiID'] == this.uiID) {
- Data.main.itemsPoolMap.get(node[0].name)?.put(node[0])
- }
- }
- this.loadAsset.forEach(value => {
- if (value.decRef) {
- value.asset.decRef()
- }
- if (value.sprite) {
- value.sprite.spriteFrame = null
- }
- if (value.animation) {
- let clips = value.animation.getClips()
- if (clips) {
- clips.forEach(clip => {
- if (clip.name == value.asset.name) value.animation.removeClip(clip, true)
- })
- }
- }
- // console.log(
- // value.asset.name,
- // '--->uuid:',
- // value.asset['_uuid'],
- // '--->refCount:',
- // value.asset.refCount,
- // '-->尝试释放',
- // value,
- // )
- })
- this.loadAsset = []
- this.nodeLoadInfoMap.clear()
- this.nodeLoadingMap.clear()
- }
- creatAniNode(parent: cc.Node, bundle: Bundle, url: string, isDestroy?: boolean, finishFuc?: Function): cc.Node {
- let node = new cc.Node()
- node.name = url.substring(url.lastIndexOf('/') + 1)
- node.addComponent(cc.Sprite)
- node.parent = parent
- let ani = node.addComponent(cc.Animation)
- this.load(
- bundle,
- url,
- cc.AnimationClip,
- (err, animationClip: cc.AnimationClip) => {
- if (!err && this.node.activeInHierarchy) {
- ani.addClip(animationClip)
- ccUtils.playAni(animationClip.name, 0, node)
- ani.once('finished', () => {
- finishFuc && finishFuc()
- if (isDestroy) node.destroy()
- })
- }
- },
- node,
- )
- return node
- }
- }
|