mirror of
https://gitee.com/dgflash/oops-plugin-framework.git
synced 2026-06-07 18:52:23 +08:00
1、修复PopUp多窗口打开时,关闭一个导致PopUp层事件阻挡消失问题
2、修复Dialog窗口连续弹出时,且带关闭动画情况下,有几率后续窗口关闭不了的问题 3、扩展GUI框架可配置是否触摸非窗口区域关闭 4、扩展GUI框架可配置是否打开窗口后显示背景遮罩 5、扩展GUI框架可配置是否缓存打开的界面,使下次打开立即显示 6、重构GUI框架,代码更简洁,源API使用体验不变
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* @LastEditTime: 2023-01-09 11:52:38
|
||||
*/
|
||||
import { Node } from "cc";
|
||||
import { UIConfig } from "./LayerManager";
|
||||
|
||||
/*** 界面回调参数对象定义 */
|
||||
export interface UICallbacks {
|
||||
@@ -23,8 +24,6 @@ export interface UICallbacks {
|
||||
onRemoved?: (node: Node | null, params: any) => void,
|
||||
|
||||
/**
|
||||
* 注意:调用`delete`或`$delete`才会触发此回调,如果`this.node.destroy()`,该回调将直接忽略。
|
||||
*
|
||||
* 如果指定onBeforeRemoved,则next必须调用,否则节点不会被正常删除。
|
||||
*
|
||||
* 比如希望节点做一个FadeOut然后删除,则可以在`onBeforeRemoved`当中播放action动画,动画结束后调用next
|
||||
@@ -34,21 +33,10 @@ export interface UICallbacks {
|
||||
onBeforeRemove?: (node: Node, next: Function) => void
|
||||
}
|
||||
|
||||
/** 弹框层回调对象定义 */
|
||||
export interface PopViewParams extends UICallbacks {
|
||||
/** 是否触摸背景关闭弹窗 */
|
||||
touchClose?: boolean,
|
||||
|
||||
/** 控制暗色背景的透明度 默认为190*/
|
||||
opacity?: number;
|
||||
}
|
||||
|
||||
/** 本类型仅供gui模块内部使用,请勿在功能逻辑中使用 */
|
||||
export class ViewParams {
|
||||
/** 界面唯一标识 */
|
||||
uuid: string = null!;
|
||||
/** 预制路径 */
|
||||
prefabPath: string = null!;
|
||||
/** 界面配置 */
|
||||
config: UIConfig = null!;
|
||||
/** 传递给打开界面的参数 */
|
||||
params: any = null!;
|
||||
/** 窗口事件 */
|
||||
@@ -57,4 +45,13 @@ export class ViewParams {
|
||||
valid: boolean = true;
|
||||
/** 界面根节点 */
|
||||
node: Node = null!;
|
||||
}
|
||||
|
||||
/** 弹框层回调对象定义(废弃) */
|
||||
export interface PopViewParams extends UICallbacks {
|
||||
/** 是否触摸背景关闭弹窗 */
|
||||
touchClose?: boolean,
|
||||
|
||||
/** 控制暗色背景的透明度 默认为190*/
|
||||
opacity?: number;
|
||||
}
|
||||
@@ -14,50 +14,58 @@ const { ccclass } = _decorator;
|
||||
@ccclass('DelegateComponent')
|
||||
export class DelegateComponent extends Component {
|
||||
/** 视图参数 */
|
||||
viewParams: ViewParams = null!;
|
||||
vp: ViewParams = null!;
|
||||
/** 界面关闭回调 - 包括关闭动画播放完 */
|
||||
onHide: Function = null!;
|
||||
|
||||
/** 窗口添加 */
|
||||
add() {
|
||||
// 触发窗口组件上添加到父节点后的事件
|
||||
this.applyComponentsFunction(this.node, "onAdded", this.viewParams.params);
|
||||
if (typeof this.viewParams.callbacks.onAdded === "function") {
|
||||
this.viewParams.callbacks.onAdded(this.node, this.viewParams.params);
|
||||
this.applyComponentsFunction(this.node, "onAdded", this.vp.params);
|
||||
if (typeof this.vp.callbacks.onAdded === "function") {
|
||||
this.vp.callbacks.onAdded(this.node, this.vp.params);
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除节点,该方法只能调用一次,将会触发onBeforeRemoved回调 */
|
||||
remove(isDestroy: boolean) {
|
||||
if (this.viewParams.valid) {
|
||||
// 触发窗口组件上移除之前的事件
|
||||
this.applyComponentsFunction(this.node, "onBeforeRemove", this.viewParams.params);
|
||||
remove(isDestroy?: boolean) {
|
||||
if (this.vp.valid) {
|
||||
// 触发窗口移除舞台之前事件
|
||||
this.applyComponentsFunction(this.node, "onBeforeRemove", this.vp.params);
|
||||
|
||||
// 通知外部对象窗口组件上移除之前的事件(关闭窗口前的关闭动画处理)
|
||||
if (typeof this.viewParams.callbacks.onBeforeRemove === "function") {
|
||||
this.viewParams.callbacks.onBeforeRemove(
|
||||
if (typeof this.vp.callbacks.onBeforeRemove === "function") {
|
||||
this.vp.callbacks.onBeforeRemove(
|
||||
this.node,
|
||||
() => {
|
||||
this.removed(this.viewParams, isDestroy);
|
||||
this.removed(this.vp, isDestroy);
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.removed(this.viewParams, isDestroy);
|
||||
this.removed(this.vp, isDestroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 窗口组件中触发移除事件与释放窗口对象 */
|
||||
private removed(viewParams: ViewParams, isDestroy: boolean) {
|
||||
viewParams.valid = false;
|
||||
private removed(vp: ViewParams, isDestroy?: boolean) {
|
||||
vp.valid = false;
|
||||
|
||||
if (typeof viewParams.callbacks.onRemoved === "function") {
|
||||
viewParams.callbacks!.onRemoved(this.node, viewParams.params);
|
||||
if (typeof vp.callbacks.onRemoved === "function") {
|
||||
vp.callbacks!.onRemoved(this.node, vp.params);
|
||||
}
|
||||
|
||||
// 界面移除舞台事件
|
||||
this.onHide && this.onHide(vp);
|
||||
|
||||
if (isDestroy) {
|
||||
// 释放界面显示对象
|
||||
this.node.destroy();
|
||||
|
||||
// 释放界面相关资源
|
||||
oops.res.release(viewParams.prefabPath);
|
||||
oops.res.release(vp.config.prefab);
|
||||
|
||||
// oops.log.logView(`【界面管理】释放【${vp.config.prefab}】界面资源`);
|
||||
}
|
||||
else {
|
||||
this.node.removeFromParent();
|
||||
@@ -66,14 +74,8 @@ export class DelegateComponent extends Component {
|
||||
|
||||
onDestroy() {
|
||||
// 触发窗口组件上窗口移除之后的事件
|
||||
this.applyComponentsFunction(this.node, "onRemoved", this.viewParams.params);
|
||||
|
||||
// 通知外部对象窗口移除之后的事件
|
||||
// if (typeof this.viewParams.callbacks!.onRemoved === "function") {
|
||||
// this.viewParams.callbacks!.onRemoved(this.node, this.viewParams.params);
|
||||
// }
|
||||
|
||||
this.viewParams = null!;
|
||||
this.applyComponentsFunction(this.node, "onRemoved", this.vp.params);
|
||||
this.vp = null!;
|
||||
}
|
||||
|
||||
protected applyComponentsFunction(node: Node, funName: string, params: any) {
|
||||
|
||||
@@ -23,54 +23,53 @@ type DialogParam = {
|
||||
export class LayerDialog extends LayerPopUp {
|
||||
/** 窗口调用参数队列 */
|
||||
private params: Array<DialogParam> = [];
|
||||
/** 当前窗口数据 */
|
||||
private current!: ViewParams;
|
||||
|
||||
add(config: UIConfig, params?: any, callbacks?: UICallbacks): string {
|
||||
this.black.enabled = true;
|
||||
|
||||
if (this.current && this.current.valid) {
|
||||
let uuid = this.getUuid(config.prefab);
|
||||
add(config: UIConfig, params?: any, callbacks?: UICallbacks) {
|
||||
// 控制同一时间只能显示一个模式窗口
|
||||
if (this.ui_nodes.size > 0) {
|
||||
this.params.push({
|
||||
config: config,
|
||||
params: params,
|
||||
callbacks: callbacks,
|
||||
});
|
||||
return uuid;
|
||||
return;
|
||||
}
|
||||
return this.show(config, params, callbacks);
|
||||
|
||||
this.black.enabled = true;
|
||||
this.show(config, params, callbacks);
|
||||
}
|
||||
|
||||
/** 显示模式弹窗 */
|
||||
private show(config: UIConfig, params?: any, callbacks?: UICallbacks): string {
|
||||
let prefabPath = config.prefab
|
||||
var uuid = this.getUuid(prefabPath);
|
||||
var viewParams = this.ui_nodes.get(uuid);
|
||||
if (viewParams == null) {
|
||||
viewParams = new ViewParams();
|
||||
viewParams.uuid = this.getUuid(prefabPath);
|
||||
viewParams.prefabPath = prefabPath;
|
||||
viewParams.valid = true;
|
||||
this.ui_nodes.set(viewParams.uuid, viewParams);
|
||||
var vp = this.ui_cache.get(config.prefab);
|
||||
if (vp == null) {
|
||||
vp = new ViewParams();
|
||||
vp.config = config
|
||||
vp.valid = true;
|
||||
}
|
||||
this.ui_nodes.set(vp.config.prefab, vp);
|
||||
|
||||
viewParams.callbacks = callbacks ?? {};
|
||||
var onRemove_Source = viewParams.callbacks.onRemoved;
|
||||
viewParams.callbacks.onRemoved = (node: Node | null, params: any) => {
|
||||
vp.callbacks = callbacks ?? {};
|
||||
var onRemove_Source = vp.callbacks.onRemoved;
|
||||
vp.callbacks.onRemoved = (node: Node | null, params: any) => {
|
||||
if (onRemove_Source) {
|
||||
onRemove_Source(node, params);
|
||||
}
|
||||
setTimeout(this.next.bind(this), 0);
|
||||
};
|
||||
|
||||
viewParams.params = params || {};
|
||||
this.current = viewParams;
|
||||
this.load(viewParams, config.bundle);
|
||||
vp.params = params || {};
|
||||
this.load(vp, config.bundle);
|
||||
|
||||
return uuid;
|
||||
return config.prefab;
|
||||
}
|
||||
|
||||
protected setBlackDisable() {
|
||||
if (this.params.length == 0) this.black.enabled = false;
|
||||
if (this.params.length == 0) {
|
||||
this.black.enabled = false;
|
||||
this.closeVacancyRemove();
|
||||
this.closeMask()
|
||||
}
|
||||
}
|
||||
|
||||
private next() {
|
||||
|
||||
@@ -50,8 +50,15 @@ export interface UIConfig {
|
||||
layer: LayerType;
|
||||
/** 预制资源相对路径 */
|
||||
prefab: string;
|
||||
/** 是否触摸非窗口区域关闭 */
|
||||
vacancy?: boolean,
|
||||
/** 是否打开窗口后显示背景遮罩 */
|
||||
mask?: boolean;
|
||||
/** 是否自动施放 */
|
||||
destroy?: boolean;
|
||||
}
|
||||
|
||||
/** 界面层级管理器 */
|
||||
export class LayerManager {
|
||||
/** 界面根节点 */
|
||||
root!: Node;
|
||||
@@ -260,16 +267,16 @@ export class LayerManager {
|
||||
var result: Node = null!;
|
||||
switch (config.layer) {
|
||||
case LayerType.UI:
|
||||
result = this.ui.getByPrefabPath(config.prefab);
|
||||
result = this.ui.get(config.prefab);
|
||||
break;
|
||||
case LayerType.PopUp:
|
||||
result = this.popup.getByPrefabPath(config.prefab);
|
||||
result = this.popup.get(config.prefab);
|
||||
break;
|
||||
case LayerType.Dialog:
|
||||
result = this.dialog.getByPrefabPath(config.prefab);
|
||||
result = this.dialog.get(config.prefab);
|
||||
break;
|
||||
case LayerType.System:
|
||||
result = this.system.getByPrefabPath(config.prefab);
|
||||
result = this.system.get(config.prefab);
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
@@ -282,7 +289,7 @@ export class LayerManager {
|
||||
* @example
|
||||
* oops.gui.remove(UIID.Loading);
|
||||
*/
|
||||
remove(uiId: number, isDestroy: boolean = true) {
|
||||
remove(uiId: number, isDestroy?: boolean) {
|
||||
var config = this.configs[uiId];
|
||||
if (config == null) {
|
||||
warn(`删除编号为【${uiId}】的界面失败,配置信息不存在`);
|
||||
@@ -308,16 +315,39 @@ export class LayerManager {
|
||||
/**
|
||||
* 删除一个通过this框架添加进来的节点
|
||||
* @param node 窗口节点
|
||||
* @param isDestroy 移除后是否释放
|
||||
* @param isDestroy 移除后是否释放资源
|
||||
* @example
|
||||
* oops.gui.removeByNode(cc.Node);
|
||||
*/
|
||||
removeByNode(node: Node, isDestroy: boolean = false) {
|
||||
removeByNode(node: Node, isDestroy?: boolean) {
|
||||
if (node instanceof Node) {
|
||||
let comp = node.getComponent(DelegateComponent);
|
||||
if (comp && comp.viewParams) {
|
||||
// @ts-ignore 注:不对外使用
|
||||
(node.parent as LayerUI).removeByUuid(comp.viewParams.uuid, isDestroy);
|
||||
if (comp && comp.vp) {
|
||||
// 释放显示的界面
|
||||
if (node.parent) {
|
||||
(node.parent as LayerUI).remove(comp.vp.config.prefab, isDestroy);
|
||||
}
|
||||
// 释放缓存中的界面
|
||||
else if (isDestroy) {
|
||||
switch (comp.vp.config.layer) {
|
||||
case LayerType.UI:
|
||||
// @ts-ignore 注:不对外使用
|
||||
this.ui.removeCache(comp.vp.config.prefab);
|
||||
break;
|
||||
case LayerType.PopUp:
|
||||
// @ts-ignore 注:不对外使用
|
||||
this.popup.removeCache(comp.vp.config.prefab);
|
||||
break;
|
||||
case LayerType.Dialog:
|
||||
// @ts-ignore 注:不对外使用
|
||||
this.dialog.removeCache(comp.vp.config.prefab);
|
||||
break;
|
||||
case LayerType.System:
|
||||
// @ts-ignore 注:不对外使用
|
||||
this.system.removeCache(comp.vp.config.prefab);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
warn(`当前删除的node不是通过界面管理器添加到舞台上`);
|
||||
|
||||
@@ -4,16 +4,20 @@
|
||||
* @LastEditTime: 2022-09-02 13:44:28
|
||||
*/
|
||||
|
||||
import { BlockInputEvents, Layers } from "cc";
|
||||
import { PopViewParams } from "./Defines";
|
||||
import { BlockInputEvents, EventTouch, Layers, Node } from "cc";
|
||||
import { ViewUtil } from "../../utils/ViewUtil";
|
||||
import { ViewParams } from "./Defines";
|
||||
import { UIConfig } from "./LayerManager";
|
||||
import { LayerUI } from "./LayerUI";
|
||||
|
||||
/*
|
||||
* 弹窗层,允许同时弹出多个窗口,弹框参数可以查看 PopViewParams
|
||||
*/
|
||||
const Mask: string = 'common/prefab/mask';
|
||||
|
||||
/* 弹窗层,允许同时弹出多个窗口 */
|
||||
export class LayerPopUp extends LayerUI {
|
||||
/** 触摸事件阻挡 */
|
||||
protected black!: BlockInputEvents;
|
||||
/** 半透明遮罩资源 */
|
||||
protected mask!: Node;
|
||||
|
||||
constructor(name: string) {
|
||||
super(name);
|
||||
@@ -26,34 +30,95 @@ export class LayerPopUp extends LayerUI {
|
||||
this.black.enabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个预制件节点到PopUp层容器中,该方法将返回一个唯一uuid来标识该操作节点
|
||||
* @param prefabPath 预制件路径
|
||||
* @param params 传给组件onAdded、onRemoved方法的参数。
|
||||
* @param popParams 弹出界面的设置定义,详情见PopViewParams
|
||||
*/
|
||||
add(config: UIConfig, params: any, popParams?: PopViewParams): string {
|
||||
protected showUi(vp: ViewParams) {
|
||||
super.showUi(vp);
|
||||
|
||||
// 界面加载完成显示时,启动触摸非窗口区域关闭
|
||||
this.openVacancyRemove(vp.config);
|
||||
|
||||
// 界面加载完成显示时,层级事件阻挡
|
||||
this.black.enabled = true;
|
||||
return super.add(config, params, popParams);
|
||||
}
|
||||
|
||||
remove(prefabPath: string, isDestroy: boolean): void {
|
||||
super.remove(prefabPath, isDestroy);
|
||||
this.setBlackDisable();
|
||||
}
|
||||
|
||||
protected removeByUuid(prefabPath: string, isDestroy: boolean): void {
|
||||
super.removeByUuid(prefabPath, isDestroy);
|
||||
protected onHide(vp: ViewParams) {
|
||||
super.onHide(vp);
|
||||
|
||||
// 界面关闭后,关闭触摸事件阻挡、关闭触摸非窗口区域关闭、关闭遮罩
|
||||
this.setBlackDisable();
|
||||
}
|
||||
|
||||
/** 设置触摸事件阻挡 */
|
||||
protected setBlackDisable() {
|
||||
this.black.enabled = false;
|
||||
// 所有弹窗关闭后,关闭事件阻挡功能
|
||||
if (this.ui_nodes.size == 0) {
|
||||
this.black.enabled = false;
|
||||
}
|
||||
this.closeVacancyRemove();
|
||||
this.closeMask();
|
||||
}
|
||||
|
||||
/** 关闭遮罩 */
|
||||
protected closeMask() {
|
||||
var flag = true;
|
||||
for (var value of this.ui_nodes.values()) {
|
||||
if (value.config.mask) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag) {
|
||||
this.mask.parent = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 启动触摸非窗口区域关闭 */
|
||||
protected openVacancyRemove(config: UIConfig) {
|
||||
if (!this.hasEventListener(Node.EventType.TOUCH_END, this.onTouchEnd, this)) {
|
||||
this.on(Node.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
}
|
||||
|
||||
// 背景半透明遮罩
|
||||
if (this.mask == null) {
|
||||
this.mask = ViewUtil.createPrefabNode(Mask);
|
||||
}
|
||||
if (config.mask) {
|
||||
this.mask.parent = this;
|
||||
this.mask.setSiblingIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
/** 关闭触摸非窗口区域关闭 */
|
||||
protected closeVacancyRemove() {
|
||||
var flag = true;
|
||||
for (var value of this.ui_nodes.values()) {
|
||||
if (value.config.vacancy) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag && this.hasEventListener(Node.EventType.TOUCH_END, this.onTouchEnd, this)) {
|
||||
this.off(Node.EventType.TOUCH_END, this.onTouchEnd, this);
|
||||
}
|
||||
}
|
||||
|
||||
private onTouchEnd(event: EventTouch) {
|
||||
if (event.target === this) {
|
||||
this.ui_nodes.forEach(vp => {
|
||||
// 关闭已显示的界面
|
||||
if (vp.valid && vp.config.vacancy) {
|
||||
this.remove(vp.config.prefab, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
clear(isDestroy: boolean) {
|
||||
super.clear(isDestroy)
|
||||
this.black.enabled = false;
|
||||
this.active = false;
|
||||
this.closeVacancyRemove();
|
||||
this.closeMask();
|
||||
}
|
||||
}
|
||||
@@ -2,14 +2,11 @@
|
||||
* UI基础层,允许添加多个预制件节点
|
||||
* add : 添加一个预制件节点到层容器中,该方法将返回一个唯一uuid来标识该操作Node节点。
|
||||
* delete : 根据uuid删除Node节点,如果节点还在队列中也会被删除, 删除节点可以用gui.delete(node)或this.node.destroy()
|
||||
* deleteByUuid : 根据预制件路径删除,预制件如在队列中也会被删除,如果该预制件存在多个也会一起删除。
|
||||
* get : 根据uuid获取Node节点,如果节点不存在或者预制件还在队列中,则返回null 。
|
||||
* getByUuid : 根据预制件路径获取当前显示的该预制件的所有Node节点数组。
|
||||
* get : 根据预制路径获取已打开界面的节点对象,如果节点不存在或者预制件还在队列中,则返回null 。
|
||||
* has : 判断当前层是否包含 uuid或预制件路径对应的Node节点。
|
||||
* find : 判断当前层是否包含 uuid或预制件路径对应的Node节点。
|
||||
* clear : 清除所有Node节点,队列当中未创建的任务也会被清除。
|
||||
*/
|
||||
import { error, instantiate, isValid, Node, Prefab, warn, Widget } from "cc";
|
||||
import { error, instantiate, Node, Prefab, warn, Widget } from "cc";
|
||||
import { oops } from "../../Oops";
|
||||
import { UICallbacks, ViewParams } from "./Defines";
|
||||
import { DelegateComponent } from "./DelegateComponent";
|
||||
@@ -17,7 +14,7 @@ import { UIConfig } from "./LayerManager";
|
||||
|
||||
/** 界面层对象 */
|
||||
export class LayerUI extends Node {
|
||||
/** 界面节点集合 */
|
||||
/** 显示界面节点集合 */
|
||||
protected ui_nodes = new Map<string, ViewParams>();
|
||||
/** 被移除的界面缓存数据 */
|
||||
protected ui_cache = new Map<string, ViewParams>();
|
||||
@@ -37,85 +34,81 @@ export class LayerUI extends Node {
|
||||
widget.enabled = true;
|
||||
}
|
||||
|
||||
/** 构造一个唯一标识UUID */
|
||||
protected getUuid(prefabPath: string): string {
|
||||
var uuid = `${this.name}_${prefabPath}`;
|
||||
return uuid.replace(/\//g, "_");
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个预制件节点到层容器中,该方法将返回一个唯一`uuid`来标识该操作节点
|
||||
* @param prefabPath 预制件路径
|
||||
* @param params 自定义参数
|
||||
* @param callbacks 回调函数对象,可选
|
||||
* @returns ture为成功,false为失败
|
||||
*/
|
||||
add(config: UIConfig, params?: any, callbacks?: UICallbacks): string {
|
||||
let prefabPath = config.prefab;
|
||||
var uuid = this.getUuid(prefabPath);
|
||||
var viewParams = this.ui_nodes.get(uuid);
|
||||
|
||||
if (viewParams && viewParams.valid) {
|
||||
warn(`路径为【${prefabPath}】的预制重复加载`);
|
||||
return "";
|
||||
add(config: UIConfig, params?: any, callbacks?: UICallbacks) {
|
||||
if (this.ui_nodes.has(config.prefab)) {
|
||||
warn(`路径为【${config.prefab}】的预制重复加载`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (viewParams == null) {
|
||||
viewParams = new ViewParams();
|
||||
viewParams.uuid = uuid;
|
||||
viewParams.prefabPath = prefabPath;
|
||||
this.ui_nodes.set(viewParams.uuid, viewParams);
|
||||
// 检查缓存中是否存界面
|
||||
var vp = this.ui_cache.get(config.prefab);
|
||||
if (vp == null) {
|
||||
vp = new ViewParams();
|
||||
vp.config = config;
|
||||
}
|
||||
this.ui_nodes.set(config.prefab, vp);
|
||||
|
||||
viewParams.params = params ?? {};
|
||||
viewParams.callbacks = callbacks ?? {};
|
||||
viewParams.valid = true;
|
||||
vp.params = params ?? {};
|
||||
vp.callbacks = callbacks ?? {};
|
||||
vp.valid = true;
|
||||
|
||||
this.load(viewParams, config.bundle)
|
||||
|
||||
return uuid;
|
||||
this.load(vp, config.bundle)
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载界面资源
|
||||
* @param viewParams 显示参数
|
||||
* @param vp 显示参数
|
||||
* @param bundle 远程资源包名,如果为空就是默认本地资源包
|
||||
*/
|
||||
protected load(viewParams: ViewParams, bundle?: string) {
|
||||
var vp: ViewParams = this.ui_nodes.get(viewParams.uuid)!;
|
||||
protected load(vp: ViewParams, bundle?: string) {
|
||||
if (vp && vp.node) {
|
||||
this.createNode(vp);
|
||||
this.showUi(vp);
|
||||
}
|
||||
else {
|
||||
// 优先加载配置的指定资源包中资源,如果没配置则加载默认资源包资源
|
||||
bundle = bundle || oops.res.defaultBundleName;
|
||||
oops.res.load(bundle, viewParams.prefabPath, (err: Error | null, res: Prefab) => {
|
||||
oops.res.load(bundle, vp.config.prefab, (err: Error | null, res: Prefab) => {
|
||||
if (err) {
|
||||
this.ui_nodes.delete(viewParams.uuid);
|
||||
error(`路径为【${viewParams.prefabPath}】的预制加载失败`);
|
||||
this.ui_nodes.delete(vp.config.prefab);
|
||||
error(`路径为【${vp.config.prefab}】的预制加载失败`);
|
||||
return;
|
||||
}
|
||||
|
||||
let childNode: Node = instantiate(res);
|
||||
viewParams.node = childNode;
|
||||
vp.node = childNode;
|
||||
|
||||
let comp = childNode.addComponent(DelegateComponent);
|
||||
comp.viewParams = viewParams;
|
||||
comp.vp = vp;
|
||||
comp.onHide = this.onHide.bind(this);
|
||||
|
||||
this.createNode(viewParams);
|
||||
this.showUi(vp);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected onHide(vp: ViewParams) {
|
||||
this.ui_nodes.delete(vp.config.prefab);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建界面节点
|
||||
* @param viewParams 视图参数
|
||||
* @param vp 视图参数
|
||||
*/
|
||||
protected createNode(viewParams: ViewParams) {
|
||||
viewParams.valid = true;
|
||||
|
||||
let comp = viewParams.node.getComponent(DelegateComponent)!;
|
||||
protected showUi(vp: ViewParams) {
|
||||
// 触发窗口添加事件
|
||||
let comp = vp.node.getComponent(DelegateComponent)!;
|
||||
comp.add();
|
||||
viewParams.node.parent = this;
|
||||
vp.node.parent = this;
|
||||
|
||||
// 标记界面为使用状态
|
||||
vp.valid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,55 +116,40 @@ export class LayerUI extends Node {
|
||||
* @param prefabPath 预制路径
|
||||
* @param isDestroy 移除后是否释放
|
||||
*/
|
||||
remove(prefabPath: string, isDestroy: boolean): void {
|
||||
// 验证是否删除后台缓存界面
|
||||
if (isDestroy) this.removeCache(prefabPath);
|
||||
remove(prefabPath: string, isDestroy?: boolean): void {
|
||||
var release = true;
|
||||
// 默认不配置为关闭界面释放资源
|
||||
if (isDestroy == undefined) release = true;
|
||||
|
||||
// 界面移出舞台
|
||||
let children = this.__nodes();
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let viewParams = children[i].viewParams;
|
||||
if (viewParams.prefabPath === prefabPath) {
|
||||
if (isDestroy) {
|
||||
// 直接释放界面
|
||||
this.ui_nodes.delete(viewParams.uuid);
|
||||
}
|
||||
else {
|
||||
// 不释放界面,缓存起来待下次使用
|
||||
this.ui_cache.set(viewParams.prefabPath, viewParams);
|
||||
}
|
||||
|
||||
children[i].remove(isDestroy);
|
||||
viewParams.valid = false;
|
||||
var vp = this.ui_nodes.get(prefabPath);
|
||||
if (vp) {
|
||||
// 优先使用参数中控制的释放条件,如果未传递参数则用配置中的释放条件
|
||||
if (isDestroy == undefined && vp.config.destroy != undefined) {
|
||||
release = vp.config.destroy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据唯一标识删除节点,如果节点还在队列中也会被删除
|
||||
* @param uuid 唯一标识
|
||||
*/
|
||||
protected removeByUuid(uuid: string, isDestroy: boolean): void {
|
||||
var viewParams = this.ui_nodes.get(uuid);
|
||||
if (viewParams) {
|
||||
if (isDestroy)
|
||||
this.ui_nodes.delete(viewParams.uuid);
|
||||
// 不释放界面,缓存起来待下次使用
|
||||
if (!release) {
|
||||
this.ui_cache.set(vp.config.prefab, vp);
|
||||
}
|
||||
|
||||
var childNode = viewParams.node;
|
||||
var childNode = vp.node;
|
||||
var comp = childNode.getComponent(DelegateComponent)!;
|
||||
comp.remove(isDestroy);
|
||||
comp.remove(release);
|
||||
}
|
||||
|
||||
// 验证是否删除后台缓存界面
|
||||
if (release) this.removeCache(prefabPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除缓存的界面,当缓存界面被移除舞台时,可通过此方法删除缓存界面
|
||||
*/
|
||||
/** 删除缓存的界面,当缓存界面被移除舞台时,可通过此方法删除缓存界面 */
|
||||
private removeCache(prefabPath: string) {
|
||||
let viewParams = this.ui_cache.get(prefabPath);
|
||||
if (viewParams) {
|
||||
this.ui_nodes.delete(viewParams.uuid);
|
||||
let vp = this.ui_cache.get(prefabPath);
|
||||
if (vp) {
|
||||
this.ui_nodes.delete(vp.config.prefab);
|
||||
this.ui_cache.delete(prefabPath);
|
||||
var childNode = viewParams.node;
|
||||
var childNode = vp.node;
|
||||
childNode.destroy();
|
||||
}
|
||||
}
|
||||
@@ -180,80 +158,19 @@ export class LayerUI extends Node {
|
||||
* 根据预制路径获取已打开界面的节点对象
|
||||
* @param prefabPath 预制路径
|
||||
*/
|
||||
getByPrefabPath(prefabPath: string): Node {
|
||||
var uuid = this.getUuid(prefabPath);
|
||||
return this.getByUuid(uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据唯一标识获取节点,如果节点不存在或者还在队列中,则返回null
|
||||
* @param uuid 唯一标识
|
||||
*/
|
||||
getByUuid(uuid: string): Node {
|
||||
let children = this.__nodes();
|
||||
for (let comp of children) {
|
||||
if (comp.viewParams && comp.viewParams.uuid === uuid) {
|
||||
return comp.node;
|
||||
}
|
||||
}
|
||||
get(prefabPath: string): Node {
|
||||
var vp = this.ui_nodes.get(prefabPath);
|
||||
if (vp)
|
||||
return vp.node;
|
||||
return null!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据预制件路径获取当前显示的该预制件的所有Node节点数组
|
||||
* @param prefabPath
|
||||
*/
|
||||
get(prefabPath: string): Array<Node> {
|
||||
let arr: Array<Node> = [];
|
||||
let children = this.__nodes();
|
||||
for (let comp of children) {
|
||||
if (comp.viewParams.prefabPath === prefabPath) {
|
||||
arr.push(comp.node);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前层是否包含 uuid或预制件路径对应的Node节点
|
||||
* @param prefabPathOrUUID 预制件路径或者UUID
|
||||
* @param prefabPath 预制件路径或者UUID
|
||||
*/
|
||||
has(prefabPathOrUUID: string): boolean {
|
||||
let children = this.__nodes();
|
||||
for (let comp of children) {
|
||||
if (comp.viewParams.uuid === prefabPathOrUUID || comp.viewParams.prefabPath === prefabPathOrUUID) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前层包含指定正则匹配的Node节点。
|
||||
* @param prefabPathReg 匹配预制件路径的正则表达式对象
|
||||
*/
|
||||
find(prefabPathReg: RegExp): Node[] {
|
||||
let arr: Node[] = [];
|
||||
let children = this.__nodes();
|
||||
for (let comp of children) {
|
||||
if (prefabPathReg.test(comp.viewParams.prefabPath)) {
|
||||
arr.push(comp.node);
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
/** 获取当前层所有窗口事件触发组件 */
|
||||
protected __nodes(): Array<DelegateComponent> {
|
||||
let result: Array<DelegateComponent> = [];
|
||||
let children = this.children;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let comp = children[i].getComponent(DelegateComponent);
|
||||
if (comp && comp.viewParams && comp.viewParams.valid && isValid(comp)) {
|
||||
result.push(comp);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
has(prefabPath: string): boolean {
|
||||
return this.ui_nodes.has(prefabPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -263,7 +180,7 @@ export class LayerUI extends Node {
|
||||
clear(isDestroy: boolean): void {
|
||||
// 清除所有显示的界面
|
||||
this.ui_nodes.forEach((value: ViewParams, key: string) => {
|
||||
this.removeByUuid(value.uuid, isDestroy);
|
||||
this.remove(value.config.prefab, isDestroy);
|
||||
value.valid = false;
|
||||
});
|
||||
this.ui_nodes.clear();
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* @LastEditTime: 2022-03-25 23:43:25
|
||||
*/
|
||||
|
||||
import { Material } from 'cc';
|
||||
import { Color, Component, macro, MeshRenderer, Node, renderer, v2, Vec2, Vec3, _decorator } from 'cc';
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -32,7 +33,7 @@ export class NavLine extends Component {
|
||||
xEuler = true;
|
||||
|
||||
/* 材质 */
|
||||
private mat: renderer.MaterialInstance = null!;
|
||||
private mat: Material | renderer.MaterialInstance | null = null!;
|
||||
|
||||
/* 导航线是否启动 */
|
||||
private inited = false;
|
||||
@@ -56,7 +57,7 @@ export class NavLine extends Component {
|
||||
this.mesh.node.active = true;
|
||||
this.frame = 0;
|
||||
this.inited = true;
|
||||
this.mat.setProperty("mainColor", this.color);
|
||||
this.mat?.setProperty("mainColor", this.color);
|
||||
|
||||
this.start_pos.set(this.player.worldPosition);
|
||||
this.target_pos.set(pos);
|
||||
@@ -76,7 +77,7 @@ export class NavLine extends Component {
|
||||
this.node.setScale(this.node.scale.x, this.node.scale.y, this.distance);
|
||||
this.node.setWorldPosition(this.player.worldPosition);
|
||||
this.tOffset.y = this.distance * this.density;
|
||||
this.mat.setProperty("tilingOffset", this.tOffset);
|
||||
this.mat?.setProperty("tilingOffset", this.tOffset);
|
||||
|
||||
if (this.xEuler) this.rotation(this.start_pos, this.target_pos);
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ export class ModuleUtil {
|
||||
* @param uiId 界面资源编号
|
||||
* @param isDestroy 是否释放界面缓存
|
||||
*/
|
||||
public static removeView(ent: ecs.Entity, ctor: CompType<ecs.IComp>, uiId: number, isDestroy: boolean = true) {
|
||||
public static removeView(ent: ecs.Entity, ctor: CompType<ecs.IComp>, uiId: number, isDestroy?: boolean) {
|
||||
ent.remove(ctor);
|
||||
oops.gui.remove(uiId, isDestroy);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user