From 115cb63fe331e744fe251d8aa549de5372d8ccbe Mon Sep 17 00:00:00 2001 From: dgflash Date: Fri, 15 Aug 2025 16:55:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20LayerGame=20=E8=87=AA?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E5=B1=82=E8=8A=82=E7=82=B9=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=201.=20=E6=94=AF=E6=8C=81=E9=A2=84=E5=88=B6?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E6=B7=BB=E5=8A=A0=E3=80=81=E5=88=A0=E9=99=A4?= =?UTF-8?q?=202.=20=E6=94=AF=E6=8C=81=E9=A2=84=E5=88=B6=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/core/gui/layer/LayerEnum.ts | 18 +- assets/core/gui/layer/LayerGame.ts | 169 ++++++++++++++++++ assets/core/gui/layer/LayerGame.ts.meta | 9 + assets/core/gui/layer/LayerGameElement.ts | 27 +++ .../core/gui/layer/LayerGameElement.ts.meta | 9 + assets/core/gui/layer/LayerManager.ts | 17 +- assets/core/gui/layer/UIConfig.ts | 19 ++ 7 files changed, 254 insertions(+), 14 deletions(-) create mode 100644 assets/core/gui/layer/LayerGame.ts create mode 100644 assets/core/gui/layer/LayerGame.ts.meta create mode 100644 assets/core/gui/layer/LayerGameElement.ts create mode 100644 assets/core/gui/layer/LayerGameElement.ts.meta diff --git a/assets/core/gui/layer/LayerEnum.ts b/assets/core/gui/layer/LayerEnum.ts index 5ded033..e656455 100644 --- a/assets/core/gui/layer/LayerEnum.ts +++ b/assets/core/gui/layer/LayerEnum.ts @@ -15,10 +15,18 @@ export enum ScreenAdapterType { Portrait } -/** 界面层类型 */ -export enum LayerType { +/** 自定义层类型 */ +export enum LayerCustomType { /** 二维游戏层 */ Game = "LayerGame", + /** 消息提示层 */ + Notify = "LayerNotify", + /** 新手引导层 */ + Guide = "LayerGuide" +} + +/** 界面层类型 */ +export enum LayerType { /** 主界面层 */ UI = "LayerUI", /** 弹窗层 */ @@ -27,10 +35,6 @@ export enum LayerType { Dialog = "LayerDialog", /** 系统触发模式窗口层 */ System = "LayerSystem", - /** 消息提示层 */ - Notify = "LayerNotify", - /** 新手引导层 */ - Guide = "LayerGuide" } /** 界面层组件类型 */ @@ -43,6 +47,8 @@ export enum LayerTypeCls { Dialog = "Dialog", /** 消息提示层 */ Notify = "Notify", + /** 游戏层 */ + Game = "Game", /** 自定义节点层 */ Node = "Node" } diff --git a/assets/core/gui/layer/LayerGame.ts b/assets/core/gui/layer/LayerGame.ts new file mode 100644 index 0000000..c16ef28 --- /dev/null +++ b/assets/core/gui/layer/LayerGame.ts @@ -0,0 +1,169 @@ +/* + * @Author: dgflash + * @Date: 2025-08-15 10:06:47 + * @LastEditors: dgflash + * @LastEditTime: 2025-08-15 10:06:47 + */ +import { Layers, Node, NodePool, Prefab, Vec3, warn, Widget } from "cc"; +import { resLoader } from "../../common/loader/ResLoader"; +import { ViewUtil } from "../../utils/ViewUtil"; +import { LayerCustomType } from "./LayerEnum"; +import { GameElementParams, LayerGameElement } from "./LayerGameElement"; +import { GameElementConfig } from "./UIConfig"; + +/* 二维游戏层 */ +export class LayerGame extends Node { + /** 当前显示的元素节点 */ + protected elements = new Map(); + + constructor() { + super(LayerCustomType.Game); + + const widget: Widget = this.addComponent(Widget); + widget.isAlignLeft = widget.isAlignRight = widget.isAlignTop = widget.isAlignBottom = true; + widget.left = widget.right = widget.top = widget.bottom = 0; + widget.alignMode = 2; + widget.enabled = true; + + this.layer = Layers.Enum.UI_2D; + } + + /** + * 添加游戏元素 + * @param prefab 资源地址 + * @param config 游戏元素自定义配置 + */ + add(prefab: string, config: GameElementConfig = {}): Node { + let params = this.setParams(prefab, config, false); + let node = ViewUtil.createPrefabNode(prefab, params.config.bundle); + if (node) { + // 设置自定义属性 + this.setNode(node, config); + + let lge = node.addComponent(LayerGameElement); + lge.params = params; + params.nodes.push(node); + } + return node; + } + + /** + * 加载资源并添加游戏元素 + * @param prefab 资源地址 + * @param config 游戏元素自定义配置 + */ + addAsync(prefab: string, config: GameElementConfig = {}): Promise { + return new Promise(async (resolve, reject) => { + let bundleName = config.bundle ? config.bundle : resLoader.defaultBundleName; + await resLoader.loadAsync(bundleName, prefab, Prefab); + let node = this.add(prefab, config); + resolve(node); + }); + } + + /** + * 添加游戏元素 - 支持对象池 + * @param prefab 资源地址 + * @param config 游戏元素自定义配置 + */ + addPool(prefab: string, config: GameElementConfig = {}): Node { + let params = this.setParams(prefab, config, true); + let node: Node = null!; + if (params.pool.size() > 0) { + node = params.pool.get()!; + } + else { + node = ViewUtil.createPrefabNode(prefab, params.config.bundle); + node.addComponent(LayerGameElement); + } + + // 设置自定义属性 + this.setNode(node, config); + + let lge = node.getComponent(LayerGameElement)!; + lge.params = params; + + return node; + } + + /** + * 加载资源并添加游戏元素 - 支持对象池 + * @param prefab 资源地址 + * @param config 游戏元素自定义配置 + */ + addPoolAsync(prefab: string, config: GameElementConfig = {}): Promise { + return new Promise(async (resolve, reject) => { + let bundleName = config.bundle ? config.bundle : resLoader.defaultBundleName; + await resLoader.loadAsync(bundleName, prefab, Prefab); + let node = this.addPool(prefab, config); + resolve(node); + }); + } + + /** 清理池数据 */ + clearPool(node: Node) { + let lge = node.getComponent(LayerGameElement)!; + if (lge) { + let params = this.elements.get(lge.params.uiid); + if (params) params.pool.clear(); + } + } + + /** + * 移除游戏元素 + * @param node 游戏元素节点 + */ + remove(node: Node) { + let lge = node.getComponent(LayerGameElement)!; + if (lge) { + if (lge.params.pool) { + lge.params.pool.put(node); + } + else { + let nodes = lge.params.nodes; + let index = nodes.indexOf(node); + if (index != -1) { + nodes.splice(index, 1); + if (nodes.length == 0) { + this.elements.delete(lge.params.uiid); + resLoader.release(lge.params.config.prefab!, lge.params.config.bundle); + } + } + node.removeFromParent(); + } + } + else { + warn(`当前删除游戏元素的 Node 不是通过框架添加的`); + } + } + + /** 设置元素参数 */ + private setParams(prefab: string, config: GameElementConfig, pool: boolean) { + let bundleName = config.bundle ? config.bundle : resLoader.defaultBundleName; + let uuid = bundleName + "_" + prefab; + let params = this.elements.get(uuid); + if (params == null) { + config.prefab = prefab; + params = new GameElementParams(); + params.uiid = uuid; + params.config = config; + if (pool) { + params.pool = new NodePool(); + } + else { + params.nodes = []; + } + this.elements.set(uuid, params); + } + return params; + } + + /** 设置自定义属性 */ + private setNode(node: Node, config: GameElementConfig) { + node.scale = config.scale ? config.scale : Vec3.ONE; + node.position = config.position ? config.position : Vec3.ZERO; + node.eulerAngles = config.eulerAngles ? config.eulerAngles : Vec3.ZERO; + node.parent = config.parent ? config.parent : this; + if (config.siblingIndex != null) node.setSiblingIndex(config.siblingIndex); + } +} \ No newline at end of file diff --git a/assets/core/gui/layer/LayerGame.ts.meta b/assets/core/gui/layer/LayerGame.ts.meta new file mode 100644 index 0000000..5801e2c --- /dev/null +++ b/assets/core/gui/layer/LayerGame.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "77041037-badf-4f11-b538-33a855aae209", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/core/gui/layer/LayerGameElement.ts b/assets/core/gui/layer/LayerGameElement.ts new file mode 100644 index 0000000..011a30a --- /dev/null +++ b/assets/core/gui/layer/LayerGameElement.ts @@ -0,0 +1,27 @@ +import { _decorator, Component, Node, NodePool } from "cc"; +import { GameElementConfig } from "./UIConfig"; + +const { ccclass } = _decorator; + +/** 窗口事件触发组件 */ +@ccclass('LayerGameElement') +export class LayerGameElement extends Component { + /** 视图参数 */ + params: GameElementParams = null!; + + protected onDestroy(): void { + this.params = null!; + } +} + +/** 游戏元素参数 */ +export class GameElementParams { + /** 游戏元素唯一编号 */ + uiid: string = null!; + /** 游戏元素配置 */ + config: GameElementConfig = null! + /** 同类游戏元素集合 */ + nodes: Node[] = null!; + /** 同类游戏元素对象池 */ + pool: NodePool = null!; +} \ No newline at end of file diff --git a/assets/core/gui/layer/LayerGameElement.ts.meta b/assets/core/gui/layer/LayerGameElement.ts.meta new file mode 100644 index 0000000..bed6853 --- /dev/null +++ b/assets/core/gui/layer/LayerGameElement.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "b43406cb-41d3-42a1-9393-40dbcd0a853e", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/core/gui/layer/LayerManager.ts b/assets/core/gui/layer/LayerManager.ts index 67dae73..c23e7b4 100644 --- a/assets/core/gui/layer/LayerManager.ts +++ b/assets/core/gui/layer/LayerManager.ts @@ -4,7 +4,8 @@ import { oops } from "../../Oops"; import { UICallbacks } from "./Defines"; import { DelegateComponent } from "./DelegateComponent"; import { LayerDialog } from "./LayerDialog"; -import { LayerType, LayerTypeCls, UIConfigMap, Uiid } from "./LayerEnum"; +import { LayerCustomType, LayerTypeCls, UIConfigMap, Uiid } from "./LayerEnum"; +import { LayerGame } from "./LayerGame"; import { LayerNotify } from "./LayerNotify"; import { LayerPopUp } from "./LayerPopup"; import { LayerUI } from "./LayerUI"; @@ -17,7 +18,7 @@ export class LayerManager { /** 界面摄像机 */ camera!: Camera; /** 游戏界面特效层 */ - game!: Node; + game!: LayerGame; /** 新手引导层 */ guide!: Node; @@ -42,6 +43,7 @@ export class LayerManager { this.clsLayers.set(LayerTypeCls.PopUp, LayerPopUp); this.clsLayers.set(LayerTypeCls.Dialog, LayerDialog); this.clsLayers.set(LayerTypeCls.Notify, LayerNotify); + this.clsLayers.set(LayerTypeCls.Game, LayerGame); this.clsLayers.set(LayerTypeCls.Node, null); } @@ -76,13 +78,10 @@ export class LayerManager { let data = config[i]; let layer: Node = null!; if (data.type == LayerTypeCls.Node) { - layer = this.create_node(data.name); switch (data.name) { - case LayerType.Game: - this.game = layer; - break - case LayerType.Guide: - this.guide = layer; + case LayerCustomType.Guide: + this.guide = this.create_node(data.name); + layer = this.guide; break } } @@ -101,6 +100,8 @@ export class LayerManager { this.uiLayers.set(data.name, layer); else if (layer instanceof LayerNotify) this.notify = layer; + else if (layer instanceof LayerGame) + this.game = layer; } } diff --git a/assets/core/gui/layer/UIConfig.ts b/assets/core/gui/layer/UIConfig.ts index b66f4cd..344c4d7 100644 --- a/assets/core/gui/layer/UIConfig.ts +++ b/assets/core/gui/layer/UIConfig.ts @@ -1,3 +1,4 @@ +import { Node, Vec3 } from "cc"; /** * 界面配置结构体 @@ -43,3 +44,21 @@ export interface UIConfig { /** 界面弹出时的节点排序索引 */ siblingIndex?: number; } + +/** 游戏元素配置 */ +export interface GameElementConfig { + /** 预制资源相对路径 */ + prefab?: string; + /** 游戏元素副节点 */ + parent?: Node; + /** 游戏元素位置 */ + position?: Vec3; + /** 游戏元素旋转 */ + eulerAngles?: Vec3; + /** 游戏元素缩放 */ + scale?: Vec3; + /** 远程包名 */ + bundle?: string; + /** 节点排序索引 */ + siblingIndex?: number; +}