@gongxh/bit-ui 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bit-ui.cjs +1625 -1189
- package/dist/bit-ui.d.ts +273 -301
- package/dist/bit-ui.min.cjs +1 -1
- package/dist/bit-ui.min.mjs +1 -1
- package/dist/bit-ui.mjs +1627 -1191
- package/package.json +3 -3
package/dist/bit-ui.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var bitCore = require('@gongxh/bit-core');
|
|
4
3
|
var fairyguiCc = require('fairygui-cc');
|
|
4
|
+
var bitCore = require('@gongxh/bit-core');
|
|
5
5
|
var cc = require('cc');
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -34,97 +34,20 @@ exports.AdapterType = void 0;
|
|
|
34
34
|
/** 固定的 不适配 */
|
|
35
35
|
AdapterType[AdapterType["Fixed"] = 2] = "Fixed";
|
|
36
36
|
})(exports.AdapterType || (exports.AdapterType = {}));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
onHide() {
|
|
53
|
-
}
|
|
54
|
-
onAdapted() {
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* 初始化 (内部方法)
|
|
58
|
-
* @internal
|
|
59
|
-
*/
|
|
60
|
-
_init() {
|
|
61
|
-
this.onInit();
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 窗口适配 (内部方法)
|
|
65
|
-
* @internal
|
|
66
|
-
*/
|
|
67
|
-
_adapted() {
|
|
68
|
-
this.setPosition(bitCore.Screen.ScreenWidth * 0.5, bitCore.Screen.ScreenHeight * 0.5);
|
|
69
|
-
this.setPivot(0.5, 0.5, true);
|
|
70
|
-
switch (this.adapterType) {
|
|
71
|
-
case exports.AdapterType.Full:
|
|
72
|
-
this.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
73
|
-
break;
|
|
74
|
-
case exports.AdapterType.Bang:
|
|
75
|
-
this.setSize(bitCore.Screen.SafeWidth, bitCore.Screen.SafeHeight, true);
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
this.onAdapted();
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* 显示 (内部方法)
|
|
82
|
-
* @param {IWindow} window 所属窗口
|
|
83
|
-
* @internal
|
|
84
|
-
*/
|
|
85
|
-
_show(window) {
|
|
86
|
-
var _a;
|
|
87
|
-
this.visible = true;
|
|
88
|
-
this.onShow(window, (_a = window.getHeaderInfo()) === null || _a === void 0 ? void 0 : _a.userdata);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* 隐藏 (内部方法)
|
|
92
|
-
* @internal
|
|
93
|
-
*/
|
|
94
|
-
_hide() {
|
|
95
|
-
this.visible = false;
|
|
96
|
-
this.onHide();
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* 关闭 (内部方法)
|
|
100
|
-
* @internal
|
|
101
|
-
*/
|
|
102
|
-
_close() {
|
|
103
|
-
this.onClose();
|
|
104
|
-
this.dispose();
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* 增加引用计数 (内部方法)
|
|
108
|
-
* @internal
|
|
109
|
-
*/
|
|
110
|
-
_addRef() {
|
|
111
|
-
this._refCount++;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* 减少引用计数 (内部方法)
|
|
115
|
-
* @internal
|
|
116
|
-
*/
|
|
117
|
-
_decRef() {
|
|
118
|
-
return --this._refCount;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* 屏幕大小改变时被调用 (内部方法)
|
|
122
|
-
* @internal
|
|
123
|
-
*/
|
|
124
|
-
_screenResize() {
|
|
125
|
-
this._adapted();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
37
|
+
/** 定义装饰器元数据的key */
|
|
38
|
+
var MetadataKey;
|
|
39
|
+
(function (MetadataKey) {
|
|
40
|
+
/** 属性 */
|
|
41
|
+
MetadataKey["prop"] = "__uipropmeta__";
|
|
42
|
+
/** 回调 */
|
|
43
|
+
MetadataKey["callback"] = "__uicbmeta__";
|
|
44
|
+
/** 控制器 */
|
|
45
|
+
MetadataKey["control"] = "__uicontrolmeta__";
|
|
46
|
+
/** 动画 */
|
|
47
|
+
MetadataKey["transition"] = "__uitransitionmeta__";
|
|
48
|
+
/** 原始名称 */
|
|
49
|
+
MetadataKey["originalName"] = "__UI_ORIGINAL_NAME__";
|
|
50
|
+
})(MetadataKey || (MetadataKey = {}));
|
|
128
51
|
|
|
129
52
|
/**
|
|
130
53
|
* @Author: Gongxh
|
|
@@ -242,373 +165,1514 @@ PropsHelper._config = {};
|
|
|
242
165
|
|
|
243
166
|
/**
|
|
244
167
|
* @Author: Gongxh
|
|
245
|
-
* @Date:
|
|
246
|
-
* @Description:
|
|
168
|
+
* @Date: 2025-12-25
|
|
169
|
+
* @Description: 信息池 注册的窗口、header、自定义组件的信息
|
|
247
170
|
*/
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
171
|
+
/** @internal */
|
|
172
|
+
class InfoPool {
|
|
173
|
+
/**
|
|
174
|
+
* 添加窗口信息
|
|
175
|
+
* @param ctor 类的构造函数
|
|
176
|
+
* @param group 窗口组名
|
|
177
|
+
* @param pkg 包名
|
|
178
|
+
* @param name 窗口名
|
|
179
|
+
* @param bundleName bundle名
|
|
180
|
+
* @internal
|
|
181
|
+
*/
|
|
182
|
+
static add(ctor, group, pkg, name, pkgs) {
|
|
183
|
+
if (this.has(name)) {
|
|
184
|
+
console.warn(`窗口【${name}】已注册,跳过,请检查是否重复注册`);
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
bitCore.debug(`窗口注册 窗口名:${name} 包名:${pkg} 组名:${group}`);
|
|
188
|
+
this._windowInfos.set(name, {
|
|
189
|
+
ctor: ctor,
|
|
190
|
+
group: group,
|
|
191
|
+
pkgName: pkg,
|
|
192
|
+
name: name
|
|
193
|
+
});
|
|
194
|
+
// 窗口组件扩展
|
|
195
|
+
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
196
|
+
this.addWindowPkg(name, pkg);
|
|
197
|
+
if (pkgs.length > 0) {
|
|
198
|
+
for (const pkg of pkgs) {
|
|
199
|
+
this.addWindowPkg(name, pkg);
|
|
255
200
|
}
|
|
256
|
-
console.debug(`自定义组件注册 组件名:${res.name} 包名:${res.pkg}`);
|
|
257
|
-
this.registerComponent(ctor, res.pkg, res.name);
|
|
258
|
-
this._registeredComponents.add(componentKey);
|
|
259
201
|
}
|
|
260
202
|
}
|
|
261
203
|
/**
|
|
262
|
-
*
|
|
204
|
+
* 注册窗口header信息
|
|
205
|
+
* @param ctor 类的构造函数
|
|
206
|
+
* @param pkg 包名
|
|
207
|
+
* @param name 窗口名
|
|
208
|
+
* @param bundleName bundle名
|
|
209
|
+
* @internal
|
|
210
|
+
*/
|
|
211
|
+
static addHeader(ctor, pkg, name) {
|
|
212
|
+
if (this.hasHeader(name)) {
|
|
213
|
+
console.warn(`header【${name}】已注册,跳过,请检查是否重复注册`);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
bitCore.debug(`header注册 header名:${name} 包名:${pkg}`);
|
|
217
|
+
this._headerInfos.set(name, {
|
|
218
|
+
ctor: ctor,
|
|
219
|
+
pkgName: pkg
|
|
220
|
+
});
|
|
221
|
+
// 窗口header扩展
|
|
222
|
+
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* 注册自定义组件信息
|
|
263
226
|
* @param ctor 组件构造函数
|
|
264
227
|
* @param pkg 包名
|
|
265
228
|
* @param name 组件名
|
|
229
|
+
* @internal
|
|
266
230
|
*/
|
|
267
|
-
static
|
|
231
|
+
static addComponent(ctor, pkg, name) {
|
|
268
232
|
const componentKey = `${pkg}/${name}`;
|
|
269
|
-
if (this.
|
|
270
|
-
console.debug(
|
|
233
|
+
if (this._customComponents.has(componentKey)) {
|
|
234
|
+
console.debug(`自定义组件【${name}】已注册,跳过,请检查是否重复注册`);
|
|
271
235
|
return;
|
|
272
236
|
}
|
|
273
237
|
bitCore.debug(`自定义组件注册 组件名:${name} 包名:${pkg}`);
|
|
238
|
+
this._customComponents.add(componentKey);
|
|
274
239
|
this.registerComponent(ctor, pkg, name);
|
|
275
|
-
this._registeredComponents.add(componentKey);
|
|
276
240
|
}
|
|
277
241
|
/**
|
|
278
|
-
*
|
|
279
|
-
* @param
|
|
242
|
+
* 是否存在窗口信息
|
|
243
|
+
* @param name 窗口名
|
|
244
|
+
* @returns 是否存在
|
|
280
245
|
* @internal
|
|
281
246
|
*/
|
|
282
|
-
static
|
|
283
|
-
|
|
284
|
-
const onConstruct = function () {
|
|
285
|
-
PropsHelper.serializeProps(this, pkg, name);
|
|
286
|
-
this.onInit && this.onInit();
|
|
287
|
-
};
|
|
288
|
-
ctor.prototype.onConstruct = onConstruct;
|
|
289
|
-
// 自定义组件扩展
|
|
290
|
-
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
247
|
+
static has(name) {
|
|
248
|
+
return this._windowInfos.has(name);
|
|
291
249
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
static initPackageConfig(res) {
|
|
304
|
-
this._resPool.initPackageConfig(res);
|
|
250
|
+
/**
|
|
251
|
+
* 获取窗口信息
|
|
252
|
+
* @param name 窗口名
|
|
253
|
+
* @returns 窗口信息
|
|
254
|
+
* @internal
|
|
255
|
+
*/
|
|
256
|
+
static get(name) {
|
|
257
|
+
if (!this.has(name)) {
|
|
258
|
+
throw new Error(`窗口【${name}】未注册,请使用 _uidecorator.uiclass 注册窗口`);
|
|
259
|
+
}
|
|
260
|
+
return this._windowInfos.get(name);
|
|
305
261
|
}
|
|
306
262
|
/**
|
|
307
|
-
*
|
|
308
|
-
* @param
|
|
309
|
-
* @
|
|
263
|
+
* 是否存在窗口header信息
|
|
264
|
+
* @param name 窗口header名
|
|
265
|
+
* @returns 是否存在
|
|
266
|
+
* @internal
|
|
310
267
|
*/
|
|
311
|
-
static
|
|
312
|
-
return
|
|
313
|
-
this._resPool.loadWindowRes(windowName, {
|
|
314
|
-
complete: () => {
|
|
315
|
-
this.showWindowIm(windowName, userdata);
|
|
316
|
-
resolve();
|
|
317
|
-
},
|
|
318
|
-
fail: (pkgs) => {
|
|
319
|
-
reject(pkgs);
|
|
320
|
-
}
|
|
321
|
-
});
|
|
322
|
-
});
|
|
268
|
+
static hasHeader(name) {
|
|
269
|
+
return this._headerInfos.has(name);
|
|
323
270
|
}
|
|
324
271
|
/**
|
|
325
|
-
*
|
|
326
|
-
* @param
|
|
327
|
-
* @
|
|
272
|
+
* 获取窗口header信息
|
|
273
|
+
* @param name 窗口header名
|
|
274
|
+
* @returns 窗口header信息
|
|
275
|
+
* @internal
|
|
328
276
|
*/
|
|
329
|
-
static
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
277
|
+
static getHeader(name) {
|
|
278
|
+
if (!this.hasHeader(name)) {
|
|
279
|
+
throw new Error(`窗口header【${name}】未注册,请使用 _uidecorator.uiheader 注册窗口header`);
|
|
280
|
+
}
|
|
281
|
+
return this._headerInfos.get(name);
|
|
334
282
|
}
|
|
335
283
|
/**
|
|
336
|
-
*
|
|
337
|
-
* @param
|
|
284
|
+
* 设置UI包所在的bundle名
|
|
285
|
+
* @param pkg 包名
|
|
286
|
+
* @param bundleName bundle名
|
|
287
|
+
* @internal
|
|
338
288
|
*/
|
|
339
|
-
static
|
|
340
|
-
if (
|
|
341
|
-
console.warn(
|
|
289
|
+
static addBundleName(pkg, bundleName) {
|
|
290
|
+
if (this._customPackageBundle.has(pkg)) {
|
|
291
|
+
console.warn(`UI包【${pkg}】已设置过包名`);
|
|
342
292
|
return;
|
|
343
293
|
}
|
|
344
|
-
|
|
345
|
-
let info = this._resPool.get(windowName);
|
|
346
|
-
const windowGroup = this.getWindowGroup(info.group);
|
|
347
|
-
windowGroup._removeWindow(windowName);
|
|
348
|
-
// 窗口组中没有窗口了
|
|
349
|
-
if (windowGroup.size == 0) {
|
|
350
|
-
let index = this._queryGroupNames.indexOf(windowGroup.name);
|
|
351
|
-
if (index > 0 && windowGroup.name == this.getTopGroupName()) {
|
|
352
|
-
do {
|
|
353
|
-
const groupName = this._queryGroupNames[--index];
|
|
354
|
-
let group = this.getWindowGroup(groupName);
|
|
355
|
-
if (group.size > 0) {
|
|
356
|
-
this.getWindow(group.getTopWindowName())._recover();
|
|
357
|
-
break;
|
|
358
|
-
}
|
|
359
|
-
} while (index >= 0);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
294
|
+
this._customPackageBundle.set(pkg, bundleName);
|
|
362
295
|
}
|
|
363
296
|
/**
|
|
364
|
-
*
|
|
365
|
-
* @param
|
|
297
|
+
* 获取UI包所在的bundle名
|
|
298
|
+
* @param pkg 包名
|
|
299
|
+
* @returns bundle名
|
|
300
|
+
* @internal
|
|
366
301
|
*/
|
|
367
|
-
static
|
|
368
|
-
|
|
369
|
-
this._windows.forEach((window, name) => {
|
|
370
|
-
if (!existIgnore) {
|
|
371
|
-
this.closeWindow(name);
|
|
372
|
-
}
|
|
373
|
-
else if (!ignoreNames.includes(name)) {
|
|
374
|
-
this.closeWindow(name);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
if (!existIgnore) {
|
|
378
|
-
this._windows.clear();
|
|
379
|
-
}
|
|
302
|
+
static getBundleName(pkg) {
|
|
303
|
+
return this._customPackageBundle.get(pkg) || "resources";
|
|
380
304
|
}
|
|
381
305
|
/**
|
|
382
|
-
*
|
|
383
|
-
* @
|
|
384
|
-
* @
|
|
385
|
-
* @
|
|
386
|
-
*/
|
|
387
|
-
static
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (group.size > 0) {
|
|
392
|
-
return this.getWindow(group.getTopWindowName());
|
|
393
|
-
}
|
|
306
|
+
* UI包所在的自定义路径
|
|
307
|
+
* @param pkg 包名
|
|
308
|
+
* @param path 路径
|
|
309
|
+
* @internal
|
|
310
|
+
*/
|
|
311
|
+
static addPackagePath(pkg, path) {
|
|
312
|
+
if (this._customPackagePath.has(pkg)) {
|
|
313
|
+
console.warn(`UI包【${pkg}】已设置过自定义路径`);
|
|
314
|
+
return;
|
|
394
315
|
}
|
|
395
|
-
|
|
316
|
+
this._customPackagePath.set(pkg, path);
|
|
396
317
|
}
|
|
397
318
|
/**
|
|
398
|
-
*
|
|
399
|
-
* @
|
|
400
|
-
* @
|
|
401
|
-
* @
|
|
319
|
+
* 获取UI包所在的路径
|
|
320
|
+
* @param pkg 包名
|
|
321
|
+
* @returns 路径
|
|
322
|
+
* @internal
|
|
402
323
|
*/
|
|
403
|
-
static
|
|
404
|
-
return this.
|
|
324
|
+
static getPackagePath(pkg) {
|
|
325
|
+
return `${this._customPackagePath.get(pkg) || 'ui'}/${pkg}`;
|
|
405
326
|
}
|
|
406
327
|
/**
|
|
407
|
-
*
|
|
408
|
-
* @param
|
|
409
|
-
* @
|
|
328
|
+
* 添加窗口需要的包名
|
|
329
|
+
* @param windowName 窗口名
|
|
330
|
+
* @param pkg 包名
|
|
331
|
+
* @internal
|
|
410
332
|
*/
|
|
411
|
-
static
|
|
412
|
-
|
|
333
|
+
static addWindowPkg(windowName, pkg) {
|
|
334
|
+
this._dirty = true;
|
|
335
|
+
if (!this._windowPkgs.has(windowName)) {
|
|
336
|
+
this._windowPkgs.set(windowName, [pkg]);
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
this._windowPkgs.get(windowName).push(pkg);
|
|
340
|
+
}
|
|
413
341
|
}
|
|
414
342
|
/**
|
|
415
|
-
*
|
|
416
|
-
* @param
|
|
417
|
-
* @returns
|
|
343
|
+
* 获取窗口需要的包名列表
|
|
344
|
+
* @param windowName 窗口名
|
|
345
|
+
* @returns 包名列表
|
|
346
|
+
* @internal
|
|
418
347
|
*/
|
|
419
|
-
static
|
|
420
|
-
if (this.
|
|
421
|
-
|
|
348
|
+
static getWindowPkg(windowName) {
|
|
349
|
+
if (this._dirty) {
|
|
350
|
+
this.refreshWindowPackages();
|
|
351
|
+
this._dirty = false;
|
|
422
352
|
}
|
|
423
|
-
|
|
353
|
+
return this._windowPkgs.get(windowName) || [];
|
|
424
354
|
}
|
|
425
355
|
/**
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
356
|
+
* 添加手动管理资源加载 和 卸载的包名
|
|
357
|
+
* @param pkgName 包名
|
|
358
|
+
* @internal
|
|
429
359
|
*/
|
|
430
|
-
static
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
let name = this._queryGroupNames[i];
|
|
434
|
-
let group = this._groups.get(name);
|
|
435
|
-
if (group.size > 0) {
|
|
436
|
-
return name;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return "";
|
|
360
|
+
static addManualPackage(pkgName) {
|
|
361
|
+
this._dirty = true;
|
|
362
|
+
this._manualPackages.add(pkgName);
|
|
440
363
|
}
|
|
441
364
|
/**
|
|
442
|
-
*
|
|
443
|
-
* @param
|
|
365
|
+
* 注册自定义组件信息
|
|
366
|
+
* @param info
|
|
444
367
|
* @internal
|
|
445
368
|
*/
|
|
446
|
-
static
|
|
447
|
-
|
|
369
|
+
static registerComponent(ctor, pkg, name) {
|
|
370
|
+
// 自定义组件扩展
|
|
371
|
+
const onConstruct = function () {
|
|
372
|
+
PropsHelper.serializeProps(this, pkg, name);
|
|
373
|
+
this.onInit && this.onInit();
|
|
374
|
+
};
|
|
375
|
+
ctor.prototype.onConstruct = onConstruct;
|
|
376
|
+
// 自定义组件扩展
|
|
377
|
+
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
448
378
|
}
|
|
379
|
+
/** 刷新窗口需要的包名信息 */
|
|
380
|
+
static refreshWindowPackages() {
|
|
381
|
+
for (const packages of this._windowPkgs.values()) {
|
|
382
|
+
let len = packages.length;
|
|
383
|
+
for (let index = len - 1; index >= 0; index--) {
|
|
384
|
+
const name = packages[index];
|
|
385
|
+
if (this._manualPackages.has(name)) {
|
|
386
|
+
packages.splice(index, 1);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
/** @internal */
|
|
393
|
+
InfoPool._windowInfos = new Map(); // 窗口信息池 窗口名 -> 窗口信息
|
|
394
|
+
/** @internal */
|
|
395
|
+
InfoPool._headerInfos = new Map(); // 窗口header信息池 窗口header名 -> header信息
|
|
396
|
+
/** @internal */
|
|
397
|
+
InfoPool._customComponents = new Set(); // 自定义组件信息池 自定义组件名 -> 组件信息
|
|
398
|
+
/** @internal */
|
|
399
|
+
InfoPool._customPackageBundle = new Map(); // UI包所在的bundle名 1对1 默认: resources
|
|
400
|
+
/** @internal */
|
|
401
|
+
InfoPool._customPackagePath = new Map(); // 自定义UI包所在的路径 1对1
|
|
402
|
+
/** @internal */
|
|
403
|
+
InfoPool._windowPkgs = new Map(); // 窗口名对应的包名列表 窗口名 -> 包名列表
|
|
404
|
+
/** @internal */
|
|
405
|
+
InfoPool._manualPackages = new Set(); // 需要手动管理的资源包名
|
|
406
|
+
/** @internal */
|
|
407
|
+
InfoPool._dirty = true;
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* @Author: Gongxh
|
|
411
|
+
* @Date: 2024-12-13
|
|
412
|
+
* @Description:
|
|
413
|
+
*/
|
|
414
|
+
/** @internal */
|
|
415
|
+
class ResLoader {
|
|
449
416
|
/**
|
|
450
|
-
*
|
|
451
|
-
* @param name 窗口的唯一标识符。
|
|
452
|
-
* @param window 要添加的窗口对象,需实现 IWindow 接口。
|
|
417
|
+
* 设置UI包加载相关回调函数
|
|
453
418
|
* @internal
|
|
454
419
|
*/
|
|
455
|
-
static
|
|
456
|
-
this.
|
|
420
|
+
static setCallbacks(callbacks) {
|
|
421
|
+
this._showWaitWindow = callbacks.showWaitWindow;
|
|
422
|
+
this._hideWaitWindow = callbacks.hideWaitWindow;
|
|
423
|
+
this._onLoadFail = callbacks.fail;
|
|
424
|
+
}
|
|
425
|
+
/** @internal */
|
|
426
|
+
static setAutoRelease(auto) {
|
|
427
|
+
this.autoRelease = auto;
|
|
457
428
|
}
|
|
458
429
|
/**
|
|
459
|
-
*
|
|
460
|
-
* @param name 窗口的名称。
|
|
430
|
+
* 增加等待窗的引用计数
|
|
461
431
|
* @internal
|
|
462
432
|
*/
|
|
463
|
-
static
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
this.
|
|
467
|
-
this._resPool.releaseWindowRes(name);
|
|
433
|
+
static addWaitRef() {
|
|
434
|
+
var _a;
|
|
435
|
+
if (this.waitRef++ === 0) {
|
|
436
|
+
(_a = this._showWaitWindow) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
468
437
|
}
|
|
469
438
|
}
|
|
470
439
|
/**
|
|
471
|
-
*
|
|
472
|
-
* 该方法遍历所有通过_uidecorator.getWindowMaps()获取的窗口映射,
|
|
473
|
-
* 并将每个窗口的资源名称、构造函数、分组和包信息添加到资源池中。
|
|
440
|
+
* 减少等待窗的引用计数
|
|
474
441
|
* @internal
|
|
475
442
|
*/
|
|
476
|
-
static
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
this._resPool.add(ctor, res.group, res.pkg, res.name, res.bundle);
|
|
481
|
-
}
|
|
482
|
-
// 窗口header注册
|
|
483
|
-
for (const { ctor, res } of exports._uidecorator.getHeaderMaps().values()) {
|
|
484
|
-
bitCore.debug(`header注册 header名:${res.name} 包名:${res.pkg}`);
|
|
485
|
-
this._resPool.addHeader(ctor, res.pkg, res.name, res.bundle);
|
|
443
|
+
static decWaitRef() {
|
|
444
|
+
var _a;
|
|
445
|
+
if (--this.waitRef === 0) {
|
|
446
|
+
(_a = this._hideWaitWindow) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
486
447
|
}
|
|
487
|
-
// 组件注册
|
|
488
|
-
ComponentExtendHelper.register();
|
|
489
448
|
}
|
|
490
|
-
/**
|
|
491
|
-
static
|
|
492
|
-
|
|
493
|
-
this._resPool.add(ctor, group, pkg, name, bundle);
|
|
449
|
+
/** @internal */
|
|
450
|
+
static getRef(pkg) {
|
|
451
|
+
return this.pkgRefs.get(pkg) || 0;
|
|
494
452
|
}
|
|
495
|
-
/**
|
|
496
|
-
static
|
|
497
|
-
|
|
498
|
-
|
|
453
|
+
/** @internal */
|
|
454
|
+
static addRef(pkg) {
|
|
455
|
+
this.pkgRefs.set(pkg, this.getRef(pkg) + 1);
|
|
456
|
+
}
|
|
457
|
+
/** @internal */
|
|
458
|
+
static subRef(pkg) {
|
|
459
|
+
let ref = this.getRef(pkg) - 1;
|
|
460
|
+
this.pkgRefs.set(pkg, ref);
|
|
461
|
+
return ref;
|
|
499
462
|
}
|
|
500
463
|
/**
|
|
501
|
-
*
|
|
502
|
-
* @param
|
|
503
|
-
* @internal
|
|
464
|
+
* 加载窗口需要的包
|
|
465
|
+
* @param windowName 窗口名
|
|
504
466
|
*/
|
|
505
|
-
static
|
|
506
|
-
|
|
507
|
-
|
|
467
|
+
static loadWindowRes(windowName) {
|
|
468
|
+
// 获取窗口需要的资源包
|
|
469
|
+
let packageNames = InfoPool.getWindowPkg(windowName);
|
|
470
|
+
if (packageNames.length <= 0) {
|
|
471
|
+
return Promise.resolve();
|
|
508
472
|
}
|
|
509
|
-
this.
|
|
510
|
-
// 不忽略查询 加到列表中
|
|
511
|
-
!group.isIgnore && this._queryGroupNames.push(group.name);
|
|
473
|
+
return this.loadUIPackages(packageNames, windowName);
|
|
512
474
|
}
|
|
513
475
|
/**
|
|
514
|
-
*
|
|
476
|
+
* 卸载窗口需要的包
|
|
477
|
+
* @param windowName 窗口名
|
|
478
|
+
*/
|
|
479
|
+
static unloadWindowRes(windowName) {
|
|
480
|
+
// 获取窗口需要的资源包
|
|
481
|
+
let packageNames = InfoPool.getWindowPkg(windowName);
|
|
482
|
+
if (packageNames.length <= 0) {
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
this.unloadUIPackages(packageNames);
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* 根据传入的UIPackage名称集合 加载多个UI包资源
|
|
489
|
+
* @param packages 包名列表
|
|
490
|
+
* @param windowName 窗口名(用于失败回调)
|
|
515
491
|
* @internal
|
|
516
492
|
*/
|
|
517
|
-
static
|
|
493
|
+
static loadUIPackages(packages, windowName) {
|
|
494
|
+
// 先找出来所有需要加载的包名
|
|
495
|
+
let list = packages.filter(pkg => this.getRef(pkg) <= 0);
|
|
496
|
+
if (list.length <= 0) {
|
|
497
|
+
// 增加引用计数
|
|
498
|
+
packages.forEach(pkg => this.addRef(pkg));
|
|
499
|
+
return Promise.resolve();
|
|
500
|
+
}
|
|
501
|
+
// 一定有需要加载的资源
|
|
502
|
+
this.addWaitRef();
|
|
503
|
+
// 获取包对应的bundle名
|
|
504
|
+
let bundleNames = list.map(pkg => InfoPool.getBundleName(pkg));
|
|
505
|
+
// 加载bundle
|
|
506
|
+
return this.loadBundles(bundleNames, windowName).then(() => {
|
|
507
|
+
// 顺序加载每个UI包
|
|
508
|
+
return this.loadUIPackagesSequentially(list, windowName);
|
|
509
|
+
}).then(() => {
|
|
510
|
+
// 所有包加载成功后,减少等待窗引用计数
|
|
511
|
+
this.decWaitRef();
|
|
512
|
+
// 增加包资源的引用计数
|
|
513
|
+
packages.forEach(pkg => this.addRef(pkg));
|
|
514
|
+
}).catch((err) => {
|
|
515
|
+
// 减少等待窗的引用计数
|
|
516
|
+
this.decWaitRef();
|
|
517
|
+
throw err;
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* 加载多个bundle(顺序加载)
|
|
522
|
+
* @param bundleNames bundle名集合
|
|
523
|
+
* @param windowName 窗口名(用于失败回调)
|
|
524
|
+
* @internal
|
|
525
|
+
*/
|
|
526
|
+
static loadBundles(bundleNames, windowName) {
|
|
527
|
+
let unloadedBundleNames = bundleNames.filter(bundleName => bundleName !== "resources" && !cc.assetManager.getBundle(bundleName));
|
|
528
|
+
if (unloadedBundleNames.length <= 0) {
|
|
529
|
+
return Promise.resolve();
|
|
530
|
+
}
|
|
531
|
+
// 递归方式实现顺序加载
|
|
532
|
+
const loadNext = (index) => {
|
|
533
|
+
if (index >= unloadedBundleNames.length) {
|
|
534
|
+
return Promise.resolve();
|
|
535
|
+
}
|
|
536
|
+
const bundleName = unloadedBundleNames[index];
|
|
537
|
+
return new Promise((resolve, reject) => {
|
|
538
|
+
cc.assetManager.loadBundle(bundleName, (err, bundle) => {
|
|
539
|
+
if (err) {
|
|
540
|
+
// 调用失败回调
|
|
541
|
+
if (this._onLoadFail) {
|
|
542
|
+
this._onLoadFail(windowName, 1, bundleName);
|
|
543
|
+
}
|
|
544
|
+
reject(new Error(`bundle【${bundleName}】加载失败`));
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
resolve(null);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
}).then(() => {
|
|
551
|
+
// 加载下一个
|
|
552
|
+
return loadNext(index + 1);
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
return loadNext(0);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* 顺序加载多个 UI 包
|
|
559
|
+
* @param packages 包名列表
|
|
560
|
+
* @param windowName 窗口名(用于失败回调)
|
|
561
|
+
* @internal
|
|
562
|
+
*/
|
|
563
|
+
static loadUIPackagesSequentially(packages, windowName) {
|
|
564
|
+
// 递归方式实现顺序加载
|
|
565
|
+
const loadNext = (index) => {
|
|
566
|
+
if (index >= packages.length) {
|
|
567
|
+
return Promise.resolve();
|
|
568
|
+
}
|
|
569
|
+
const pkg = packages[index];
|
|
570
|
+
return this.loadSingleUIPackage(pkg, windowName).then(() => {
|
|
571
|
+
// 加载下一个
|
|
572
|
+
return loadNext(index + 1);
|
|
573
|
+
});
|
|
574
|
+
};
|
|
575
|
+
return loadNext(0);
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* 加载单个 UI 包
|
|
579
|
+
* @param pkg 包名
|
|
580
|
+
* @param windowName 窗口名(用于失败回调)
|
|
581
|
+
* @internal
|
|
582
|
+
*/
|
|
583
|
+
static loadSingleUIPackage(pkg, windowName) {
|
|
584
|
+
return new Promise((resolve, reject) => {
|
|
585
|
+
let bundleName = InfoPool.getBundleName(pkg);
|
|
586
|
+
let bundle = bundleName === "resources" ? cc.resources : cc.assetManager.getBundle(bundleName);
|
|
587
|
+
fairyguiCc.UIPackage.loadPackage(bundle, InfoPool.getPackagePath(pkg), (err) => {
|
|
588
|
+
if (err) {
|
|
589
|
+
// 调用失败回调
|
|
590
|
+
if (windowName && this._onLoadFail) {
|
|
591
|
+
this._onLoadFail(windowName, 2, pkg);
|
|
592
|
+
}
|
|
593
|
+
reject(new Error(`UI包【${pkg}】加载失败`));
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
resolve();
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* 根据传入的UIPackage名称集合 卸载多个UI包资源
|
|
603
|
+
* @param pkgNames UIPackage名称集合
|
|
604
|
+
* @internal
|
|
605
|
+
*/
|
|
606
|
+
static unloadUIPackages(packages) {
|
|
607
|
+
for (const pkg of packages) {
|
|
608
|
+
if (this.subRef(pkg) === 0 && this.autoRelease) {
|
|
609
|
+
fairyguiCc.UIPackage.removePackage(pkg);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* 释放不再使用中的自动加载的UI资源
|
|
615
|
+
* 释放所有引用计数 <= 0 的UI资源
|
|
616
|
+
* @internal
|
|
617
|
+
*/
|
|
618
|
+
static releaseUnusedRes() {
|
|
619
|
+
let keys = Array.from(this.pkgRefs.keys());
|
|
620
|
+
for (const key of keys) {
|
|
621
|
+
if (this.getRef(key) <= 0) {
|
|
622
|
+
fairyguiCc.UIPackage.removePackage(key);
|
|
623
|
+
this.pkgRefs.delete(key);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* 等待窗口的引用计数
|
|
630
|
+
* 每次加载开始时 +1 每次加载完成时 -1
|
|
631
|
+
* @internal
|
|
632
|
+
*/
|
|
633
|
+
ResLoader.waitRef = 0;
|
|
634
|
+
/** 包的引用计数 包名 -> 引用计数 */
|
|
635
|
+
ResLoader.pkgRefs = new Map();
|
|
636
|
+
/**
|
|
637
|
+
* 自动释放UI资源
|
|
638
|
+
* @internal
|
|
639
|
+
*/
|
|
640
|
+
ResLoader.autoRelease = true;
|
|
641
|
+
/** UI包加载回调 - 显示加载等待窗 @internal */
|
|
642
|
+
ResLoader._showWaitWindow = null;
|
|
643
|
+
/** UI包加载回调 - 隐藏加载等待窗 @internal */
|
|
644
|
+
ResLoader._hideWaitWindow = null;
|
|
645
|
+
/** UI包加载回调 - 打开窗口时UI包加载失败 @internal */
|
|
646
|
+
ResLoader._onLoadFail = null;
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* @Author: Gongxh
|
|
650
|
+
* @Date: 2024-12-07
|
|
651
|
+
* @Description: 窗口管理类
|
|
652
|
+
*/
|
|
653
|
+
class WindowManager {
|
|
654
|
+
/** @internal */
|
|
655
|
+
static get bgAlpha() {
|
|
656
|
+
return this._bgAlpha;
|
|
657
|
+
}
|
|
658
|
+
/** @internal */
|
|
659
|
+
static set bgAlpha(value) {
|
|
660
|
+
this._bgAlpha = value;
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* 屏幕大小改变时 调用所有窗口的screenResize方法 (内部方法)
|
|
664
|
+
* @internal
|
|
665
|
+
*/
|
|
666
|
+
static onScreenResize() {
|
|
667
|
+
// 半透明遮罩适配
|
|
668
|
+
if (this._alphaGraph) {
|
|
669
|
+
this._alphaGraph.setPosition(bitCore.Screen.ScreenWidth * 0.5, bitCore.Screen.ScreenHeight * 0.5);
|
|
670
|
+
this._alphaGraph.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
671
|
+
}
|
|
672
|
+
// 所有窗口适配
|
|
518
673
|
this._windows.forEach((window) => {
|
|
519
|
-
window.
|
|
674
|
+
window._adapted();
|
|
520
675
|
});
|
|
521
|
-
|
|
522
|
-
|
|
676
|
+
// 所有header适配
|
|
677
|
+
HeaderManager.onScreenResize();
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* 添加手动管理资源加载 和 卸载的包名
|
|
681
|
+
* @param pkgName 包名
|
|
682
|
+
*/
|
|
683
|
+
static addManualPackage(pkgName) {
|
|
684
|
+
InfoPool.addManualPackage(pkgName);
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* 提供一种特殊需求 用来手动设置包所在的 bundle名 以及包在bundle中的路径
|
|
688
|
+
* @param name 窗口名称
|
|
689
|
+
* @param bundleName bundle名 默认: resources
|
|
690
|
+
* @param path 包在bundle中的路径 默认: ui目录
|
|
691
|
+
*/
|
|
692
|
+
static setPackageInfo(pkgName, bundleName = "resources", path = "ui") {
|
|
693
|
+
if (bundleName !== "resources") {
|
|
694
|
+
InfoPool.addBundleName(pkgName, bundleName);
|
|
695
|
+
}
|
|
696
|
+
if (path !== "ui") {
|
|
697
|
+
InfoPool.addPackagePath(pkgName, path);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* 用于手动设置UI导出数据
|
|
702
|
+
* @param config UI导出数据
|
|
703
|
+
*/
|
|
704
|
+
static setUIConfig(config) {
|
|
705
|
+
PropsHelper.setConfig(config);
|
|
706
|
+
}
|
|
707
|
+
/**
|
|
708
|
+
* 设置UI包加载相关回调函数
|
|
709
|
+
* @param callbacks 包含加载回调的对象
|
|
710
|
+
* @param callbacks.showWaitWindow 显示加载等待窗的回调
|
|
711
|
+
* @param callbacks.hideWaitWindow 隐藏加载等待窗的回调
|
|
712
|
+
* @param callbacks.fail 打开窗口时资源加载失败的回调 code( 1:bundle加载失败 2:包加载失败 )
|
|
713
|
+
*/
|
|
714
|
+
static setPackageCallbacks(callbacks) {
|
|
715
|
+
ResLoader.setCallbacks(callbacks);
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* 向窗口管理器添加一个窗口组 如果窗口组名称已存在,则抛出错误. (内部方法)
|
|
719
|
+
* @param group 要添加的窗口组
|
|
720
|
+
* @internal
|
|
721
|
+
*/
|
|
722
|
+
static addWindowGroup(group) {
|
|
723
|
+
if (this._groups.has(group.name)) {
|
|
724
|
+
throw new Error(`窗口组【${group.name}】已存在`);
|
|
725
|
+
}
|
|
726
|
+
this._groups.set(group.name, group);
|
|
727
|
+
this._groupNames.push(group.name);
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* 设置半透明遮罩
|
|
731
|
+
* @param alphaGraph 半透明遮罩
|
|
732
|
+
* @internal
|
|
733
|
+
*/
|
|
734
|
+
static setAlphaGraph(alphaGraph) {
|
|
735
|
+
this._alphaGraph = alphaGraph;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* 异步打开一个窗口 (如果UI包的资源未加载, 会自动加载 可以配合 WindowManager.setPackageCallbacks一起使用)
|
|
739
|
+
* @param 窗口类
|
|
740
|
+
* @param userdata 用户数据
|
|
741
|
+
*/
|
|
742
|
+
static showWindow(window, userdata) {
|
|
743
|
+
// 优先使用装饰器设置的静态属性,避免代码混淆后 constructor.name 变化
|
|
744
|
+
const name = window[MetadataKey.originalName];
|
|
745
|
+
if (!name) {
|
|
746
|
+
throw new Error(`窗口【${window.name}】未注册,请使用 _uidecorator.uiclass 注册窗口`);
|
|
747
|
+
}
|
|
748
|
+
return this.showWindowByName(name, userdata);
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* 通过窗口名称打开一个窗口
|
|
752
|
+
* @param name 窗口名称
|
|
753
|
+
* @param userdata 用户数据
|
|
754
|
+
* @internal
|
|
755
|
+
*/
|
|
756
|
+
static showWindowByName(name, userdata) {
|
|
757
|
+
// 找到他所属的窗口组
|
|
758
|
+
const info = InfoPool.get(name);
|
|
759
|
+
const group = this.getWindowGroup(info.group);
|
|
760
|
+
return group.showWindow(info, userdata);
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* 关闭一个窗口
|
|
764
|
+
* @param ctor 窗口类
|
|
765
|
+
*/
|
|
766
|
+
static closeWindow(window) {
|
|
767
|
+
// 取到窗口的名称,优先使用装饰器设置的静态属性
|
|
768
|
+
const name = window[MetadataKey.originalName];
|
|
769
|
+
this.closeWindowByName(name);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* 通过窗口名称关闭一个窗口
|
|
773
|
+
* @param name 窗口名称
|
|
774
|
+
*/
|
|
775
|
+
static closeWindowByName(name) {
|
|
776
|
+
if (!this.hasWindow(name)) {
|
|
777
|
+
console.warn(`窗口不存在 ${name} 不需要关闭`);
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
const info = InfoPool.get(name);
|
|
781
|
+
const group = this.getWindowGroup(info.group);
|
|
782
|
+
group.removeWindow(name);
|
|
783
|
+
// 调整半透明遮罩
|
|
784
|
+
this.adjustAlphaGraph();
|
|
785
|
+
// 找到最上层的窗口 调用toTop方法
|
|
786
|
+
let topWindow = this.getTopWindow();
|
|
787
|
+
if (topWindow && !topWindow.isTop()) {
|
|
788
|
+
topWindow._toTop();
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* 是否存在窗口
|
|
793
|
+
* @param name 窗口名称
|
|
794
|
+
*/
|
|
795
|
+
static hasWindow(name) {
|
|
796
|
+
return this._windows.has(name);
|
|
797
|
+
}
|
|
798
|
+
/**
|
|
799
|
+
* 添加窗口
|
|
800
|
+
* @param name 窗口名称
|
|
801
|
+
* @param window 要添加的窗口对象,需实现 IWindow 接口。
|
|
802
|
+
* @internal
|
|
803
|
+
*/
|
|
804
|
+
static addWindow(name, window) {
|
|
805
|
+
this._windows.set(name, window);
|
|
806
|
+
}
|
|
807
|
+
/**
|
|
808
|
+
* 移除窗口
|
|
809
|
+
* @param name 窗口名称
|
|
810
|
+
* @internal
|
|
811
|
+
*/
|
|
812
|
+
static removeWindow(name) {
|
|
813
|
+
this._windows.delete(name);
|
|
814
|
+
}
|
|
815
|
+
/**
|
|
816
|
+
* 根据窗口名称获取窗口实例。
|
|
817
|
+
* @template T 窗口类型,必须继承自IWindow接口。
|
|
818
|
+
* @param name 窗口名称
|
|
819
|
+
* @returns 如果找到窗口,则返回对应类型的窗口实例;否则返回null。
|
|
820
|
+
*/
|
|
821
|
+
static getWindow(name) {
|
|
822
|
+
return this._windows.get(name);
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* 获取当前最顶层的窗口实例。
|
|
826
|
+
* 默认会忽略掉忽略查询的窗口组
|
|
827
|
+
* @returns {T | null} - 返回最顶层的窗口实例,如果没有找到则返回 null。
|
|
828
|
+
*/
|
|
829
|
+
static getTopWindow(isAll = true) {
|
|
830
|
+
const names = this._groupNames;
|
|
831
|
+
for (let i = names.length - 1; i >= 0; i--) {
|
|
832
|
+
const group = this.getWindowGroup(names[i]);
|
|
833
|
+
if (group.isIgnore && !isAll) {
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (group.size === 0) {
|
|
837
|
+
continue;
|
|
838
|
+
}
|
|
839
|
+
return group.getTopWindow();
|
|
840
|
+
}
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* 获取所有窗口组的名称列表(按层级顺序)
|
|
845
|
+
* @returns 窗口组的名称列表
|
|
846
|
+
*/
|
|
847
|
+
static getGroupNames() {
|
|
848
|
+
return this._groupNames;
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* 根据给定的组名获取窗口组。如果组不存在,则抛出错误。
|
|
852
|
+
* @param name 窗口组名称
|
|
853
|
+
* @returns 返回找到的窗口组。
|
|
854
|
+
*/
|
|
855
|
+
static getWindowGroup(name) {
|
|
856
|
+
if (this._groups.has(name)) {
|
|
857
|
+
return this._groups.get(name);
|
|
858
|
+
}
|
|
859
|
+
throw new Error(`窗口组【${name}】不存在`);
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* 关闭所有窗口
|
|
863
|
+
* @param ignores 不关闭的窗口
|
|
864
|
+
*/
|
|
865
|
+
static closeAllWindow(ignores = []) {
|
|
866
|
+
let len = this._groupNames.length;
|
|
867
|
+
for (let i = len - 1; i >= 0; i--) {
|
|
868
|
+
let group = this.getWindowGroup(this._groupNames[i]);
|
|
869
|
+
group.closeAllWindow(ignores);
|
|
870
|
+
}
|
|
871
|
+
// 找到最上层的窗口 调用toTop方法
|
|
872
|
+
let topWindow = this.getTopWindow();
|
|
873
|
+
if (topWindow && !topWindow.isTop()) {
|
|
874
|
+
topWindow._toTop();
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* 调整半透明遮罩的显示层级
|
|
879
|
+
* 从上到下(从所有窗口组)查找第一个bgAlpha不为0的窗口,将遮罩放到该窗口下方
|
|
880
|
+
* @internal
|
|
881
|
+
*/
|
|
882
|
+
static adjustAlphaGraph() {
|
|
883
|
+
let topWindow = null;
|
|
884
|
+
// 从后往前遍历窗口组(后面的窗口组层级更高)
|
|
885
|
+
for (let i = this._groupNames.length - 1; i >= 0; i--) {
|
|
886
|
+
const group = this._groups.get(this._groupNames[i]);
|
|
887
|
+
if (group.size === 0) {
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
// 在当前窗口组中从上到下查找第一个bgAlpha不为0的窗口
|
|
891
|
+
for (let j = group.windowNames.length - 1; j >= 0; j--) {
|
|
892
|
+
const name = group.windowNames[j];
|
|
893
|
+
const win = WindowManager.getWindow(name);
|
|
894
|
+
if (win.bgAlpha > 0) {
|
|
895
|
+
topWindow = win;
|
|
896
|
+
break;
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
if (topWindow) {
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
// 如果找到了需要遮罩的窗口
|
|
904
|
+
if (topWindow) {
|
|
905
|
+
// 获取窗口组的根节点
|
|
906
|
+
const parent = topWindow.parent;
|
|
907
|
+
// 将遮罩设置到目标窗口的下方
|
|
908
|
+
const windowIndex = parent.getChildIndex(topWindow);
|
|
909
|
+
let gIndex = 0;
|
|
910
|
+
// 确保遮罩在目标窗口组的根节点下
|
|
911
|
+
if (this._alphaGraph.parent !== parent) {
|
|
912
|
+
this._alphaGraph.removeFromParent();
|
|
913
|
+
parent.addChild(this._alphaGraph);
|
|
914
|
+
gIndex = parent.numChildren - 1;
|
|
915
|
+
}
|
|
916
|
+
else {
|
|
917
|
+
gIndex = parent.getChildIndex(this._alphaGraph);
|
|
918
|
+
}
|
|
919
|
+
let newIndex = gIndex >= windowIndex ? windowIndex : windowIndex - 1;
|
|
920
|
+
parent.setChildIndex(this._alphaGraph, newIndex);
|
|
921
|
+
// 显示遮罩
|
|
922
|
+
this._alphaGraph.visible = true;
|
|
923
|
+
// 半透明遮罩绘制
|
|
924
|
+
this._bgColor.a = topWindow.bgAlpha * 255;
|
|
925
|
+
this._alphaGraph.clearGraphics();
|
|
926
|
+
this._alphaGraph.drawRect(0, this._bgColor, this._bgColor);
|
|
927
|
+
}
|
|
928
|
+
else {
|
|
929
|
+
// 没有找到需要遮罩的窗口,隐藏遮罩
|
|
930
|
+
this._alphaGraph.visible = false;
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
/**
|
|
934
|
+
* 释放不再使用中的自动加载的UI资源
|
|
935
|
+
* 针对在 UIModule 中设置了不自动释放资源的场景
|
|
936
|
+
*/
|
|
937
|
+
static releaseUnusedRes() {
|
|
938
|
+
ResLoader.releaseUnusedRes();
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
WindowManager._bgAlpha = 0.75;
|
|
942
|
+
WindowManager._bgColor = new cc.Color(0, 0, 0, 0);
|
|
943
|
+
/** @internal */
|
|
944
|
+
WindowManager._alphaGraph = null; // 半透明的遮罩
|
|
945
|
+
/** @internal */
|
|
946
|
+
WindowManager._groups = new Map(); // 窗口组
|
|
947
|
+
/** @internal */
|
|
948
|
+
WindowManager._groupNames = []; // 窗口组的名称列表
|
|
949
|
+
/** @internal */
|
|
950
|
+
WindowManager._windows = new Map(); // 所有窗口的引用
|
|
951
|
+
|
|
952
|
+
/**
|
|
953
|
+
* @Author: Gongxh
|
|
954
|
+
* @Date: 2025-12-29
|
|
955
|
+
* @Description: header(资源栏)管理类
|
|
956
|
+
*/
|
|
957
|
+
class HeaderManager {
|
|
958
|
+
/**
|
|
959
|
+
* 屏幕适配
|
|
960
|
+
* @internal
|
|
961
|
+
*/
|
|
962
|
+
static onScreenResize() {
|
|
963
|
+
for (const header of this._headers.values()) {
|
|
964
|
+
header._adapted();
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* 为窗口请求一个header
|
|
969
|
+
* @param windowName 窗口名
|
|
970
|
+
* @param headerInfo header信息
|
|
971
|
+
*/
|
|
972
|
+
static requestHeader(windowName, headerInfo) {
|
|
973
|
+
// 保存header的信息
|
|
974
|
+
if (!headerInfo) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
this._headerInfos.set(windowName, headerInfo);
|
|
978
|
+
const headerName = headerInfo.name;
|
|
979
|
+
// 如果header不存在,创建它
|
|
980
|
+
if (!this._headers.has(headerName)) {
|
|
981
|
+
const header = this.createHeader(headerInfo);
|
|
982
|
+
this._headers.set(headerName, header);
|
|
983
|
+
this._refCounts.set(headerName, 0);
|
|
984
|
+
this._headerWindowsMap.set(headerName, new Set());
|
|
985
|
+
}
|
|
986
|
+
// 增加引用计数
|
|
987
|
+
this._refCounts.set(headerName, this._refCounts.get(headerName) + 1);
|
|
988
|
+
// 记录窗口和header的关系
|
|
989
|
+
this._headerWindowsMap.get(headerName).add(windowName);
|
|
990
|
+
}
|
|
991
|
+
/**
|
|
992
|
+
* 显示指定窗口的header
|
|
993
|
+
* @param windowName 窗口名
|
|
994
|
+
* @param fromHide 窗口是否从隐藏状态恢复显示
|
|
995
|
+
*/
|
|
996
|
+
static showHeader(windowName) {
|
|
997
|
+
if (!this.hasHeader(windowName)) {
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
const headerName = this.getHeaderName(windowName);
|
|
1001
|
+
const header = this.getHeader(headerName);
|
|
1002
|
+
// 更新最上层窗口(智能判断,只在必要时重新计算)
|
|
1003
|
+
this.updateTopWindow(headerName, windowName, true);
|
|
1004
|
+
// 只有当前窗口是最上层时才显示
|
|
1005
|
+
const currentTopWindow = this._cacheHeaderTopWindow.get(headerName);
|
|
1006
|
+
if (currentTopWindow === windowName) {
|
|
1007
|
+
header._show(this.getHeaderUserData(windowName));
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* 隐藏指定窗口的header
|
|
1012
|
+
* @param windowName 窗口名
|
|
1013
|
+
*/
|
|
1014
|
+
static hideHeader(windowName) {
|
|
1015
|
+
if (!this.hasHeader(windowName)) {
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
const headerName = this.getHeaderName(windowName);
|
|
1019
|
+
const header = this.getHeader(headerName);
|
|
1020
|
+
// 更新最上层窗口(会自动处理切换逻辑)
|
|
1021
|
+
this.updateTopWindow(headerName, windowName, false);
|
|
1022
|
+
// 如果切换到了新的窗口,传递新的userdata0
|
|
1023
|
+
if (this._cacheHeaderTopWindow.has(headerName)) {
|
|
1024
|
+
const newTopWindowName = this._cacheHeaderTopWindow.get(headerName);
|
|
1025
|
+
header._show(this.getHeaderUserData(newTopWindowName));
|
|
1026
|
+
}
|
|
1027
|
+
else if (header.isShowing()) {
|
|
1028
|
+
header._hide();
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* 释放窗口的header(减少引用计数)
|
|
1033
|
+
* @param windowName 窗口名
|
|
1034
|
+
*/
|
|
1035
|
+
static releaseHeader(windowName) {
|
|
1036
|
+
if (!this.hasHeader(windowName)) {
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
const headerName = this.getHeaderName(windowName);
|
|
1040
|
+
// 减少引用计数
|
|
1041
|
+
const refCount = this._refCounts.get(headerName) - 1;
|
|
1042
|
+
// 移除映射关系
|
|
1043
|
+
this._headerWindowsMap.get(headerName).delete(windowName);
|
|
1044
|
+
// 清除窗口的header信息
|
|
1045
|
+
this._headerInfos.delete(windowName);
|
|
1046
|
+
const header = this.getHeader(headerName);
|
|
1047
|
+
// 如果引用计数为0,销毁header
|
|
1048
|
+
if (refCount === 0) {
|
|
1049
|
+
header._close();
|
|
1050
|
+
this._headers.delete(headerName);
|
|
1051
|
+
this._refCounts.delete(headerName);
|
|
1052
|
+
this._headerWindowsMap.delete(headerName);
|
|
1053
|
+
this._cacheHeaderTopWindow.delete(headerName);
|
|
1054
|
+
}
|
|
1055
|
+
else {
|
|
1056
|
+
// 更新引用计数
|
|
1057
|
+
this._refCounts.set(headerName, refCount);
|
|
1058
|
+
// 查找新的最上层窗口 并显示
|
|
1059
|
+
const newTopWindowName = this.findTopWindowForHeader(headerName, windowName);
|
|
1060
|
+
if (newTopWindowName) {
|
|
1061
|
+
this._cacheHeaderTopWindow.set(headerName, newTopWindowName);
|
|
1062
|
+
this.adjustHeaderPosition(headerName, newTopWindowName);
|
|
1063
|
+
header._show(this.getHeaderUserData(newTopWindowName));
|
|
1064
|
+
}
|
|
1065
|
+
else {
|
|
1066
|
+
// 没找到需要显示的 隐藏掉
|
|
1067
|
+
this._cacheHeaderTopWindow.delete(headerName);
|
|
1068
|
+
header.isShowing() && header._hide();
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
/**
|
|
1073
|
+
* 获取窗口关联的header
|
|
1074
|
+
* @param windowName 窗口名
|
|
1075
|
+
* @returns header实例,如果没有则返回null
|
|
1076
|
+
*/
|
|
1077
|
+
static getHeaderByWindow(windowName) {
|
|
1078
|
+
if (!this.hasHeader(windowName)) {
|
|
1079
|
+
return null;
|
|
1080
|
+
}
|
|
1081
|
+
const headerName = this.getHeaderName(windowName);
|
|
1082
|
+
return this._headers.get(headerName) || null;
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* 刷新窗口的header
|
|
1086
|
+
* 如果新的header和旧的header不是同一个,先释放旧的,再创建新的
|
|
1087
|
+
* 如果是同一个,更新userdata并重新显示
|
|
1088
|
+
* @param windowName 窗口名
|
|
1089
|
+
* @param newHeaderInfo 新的header信息
|
|
1090
|
+
*/
|
|
1091
|
+
static refreshWindowHeader(windowName, newHeaderInfo) {
|
|
1092
|
+
const oldHeaderName = this.getHeaderName(windowName);
|
|
1093
|
+
const newHeaderName = newHeaderInfo === null || newHeaderInfo === void 0 ? void 0 : newHeaderInfo.name;
|
|
1094
|
+
// 情况1:新旧 header 名称相同,只需要更新 userdata 并重新显示
|
|
1095
|
+
if (oldHeaderName === newHeaderName) {
|
|
1096
|
+
if (newHeaderInfo) {
|
|
1097
|
+
// 更新保存的 userdata
|
|
1098
|
+
this._headerInfos.set(windowName, newHeaderInfo);
|
|
1099
|
+
// 重新显示 header(如果当前窗口是最上层)
|
|
1100
|
+
const currentTopWindow = this._cacheHeaderTopWindow.get(newHeaderName);
|
|
1101
|
+
if (currentTopWindow === windowName) {
|
|
1102
|
+
const header = this.getHeader(newHeaderName);
|
|
1103
|
+
header._show(newHeaderInfo.userdata);
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
// 情况2:header 名称不同,先释放旧的,再创建新的
|
|
1109
|
+
// 释放旧的 header
|
|
1110
|
+
if (oldHeaderName) {
|
|
1111
|
+
this.releaseHeader(windowName);
|
|
1112
|
+
}
|
|
1113
|
+
// 请求新的 header 并显示
|
|
1114
|
+
if (newHeaderInfo) {
|
|
1115
|
+
this.requestHeader(windowName, newHeaderInfo);
|
|
1116
|
+
this.showHeader(windowName);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
static createHeader(headerInfo) {
|
|
1120
|
+
// 创建header实例
|
|
1121
|
+
const info = InfoPool.getHeader(headerInfo.name);
|
|
1122
|
+
const header = fairyguiCc.UIPackage.createObject(info.pkgName, headerInfo.name);
|
|
1123
|
+
header.name = headerInfo.name;
|
|
1124
|
+
PropsHelper.serializeProps(header, info.pkgName);
|
|
1125
|
+
header._init();
|
|
1126
|
+
header._adapted();
|
|
1127
|
+
return header;
|
|
1128
|
+
}
|
|
1129
|
+
/**
|
|
1130
|
+
* 获取窗口记录的header userdata
|
|
1131
|
+
* @internal
|
|
1132
|
+
*/
|
|
1133
|
+
static getHeaderUserData(windowName) {
|
|
1134
|
+
var _a;
|
|
1135
|
+
return (_a = this._headerInfos.get(windowName)) === null || _a === void 0 ? void 0 : _a.userdata;
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* 根据窗口名字获取header名称
|
|
1139
|
+
* @internal
|
|
1140
|
+
*/
|
|
1141
|
+
static getHeaderName(windowName) {
|
|
1142
|
+
var _a;
|
|
1143
|
+
return (_a = this._headerInfos.get(windowName)) === null || _a === void 0 ? void 0 : _a.name;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* 窗口上是否存在header
|
|
1147
|
+
* @internal
|
|
1148
|
+
*/
|
|
1149
|
+
static hasHeader(windowName) {
|
|
1150
|
+
return this._headerInfos.has(windowName);
|
|
1151
|
+
}
|
|
1152
|
+
/** 通过名称直接获取header实例 */
|
|
1153
|
+
static getHeader(name) {
|
|
1154
|
+
return this._headers.get(name);
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* 更新header的最上层窗口(智能判断是否需要重新计算)
|
|
1158
|
+
* @internal
|
|
1159
|
+
*/
|
|
1160
|
+
static updateTopWindow(headerName, changedWindowName, isShowing) {
|
|
1161
|
+
// 记录的最上层窗口名
|
|
1162
|
+
const topWindowName = this._cacheHeaderTopWindow.get(headerName);
|
|
1163
|
+
if (isShowing) {
|
|
1164
|
+
// 情况1:新窗口显示,且它在更高层级
|
|
1165
|
+
if (!topWindowName || this.isWindowAbove(changedWindowName, topWindowName)) {
|
|
1166
|
+
// 新窗口更靠上, 调整header位置并缓存
|
|
1167
|
+
this._cacheHeaderTopWindow.set(headerName, changedWindowName);
|
|
1168
|
+
this.adjustHeaderPosition(headerName, changedWindowName);
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
else if (topWindowName === changedWindowName) {
|
|
1173
|
+
// 最上层的窗口需要隐藏, 查找新的最上层窗口
|
|
1174
|
+
const newTopWindowName = this.findTopWindowForHeader(headerName, changedWindowName);
|
|
1175
|
+
if (newTopWindowName) {
|
|
1176
|
+
this._cacheHeaderTopWindow.set(headerName, newTopWindowName);
|
|
1177
|
+
this.adjustHeaderPosition(headerName, newTopWindowName);
|
|
1178
|
+
}
|
|
1179
|
+
else {
|
|
1180
|
+
this._cacheHeaderTopWindow.delete(headerName);
|
|
1181
|
+
const header = this.getHeader(headerName);
|
|
1182
|
+
if (header && header.isShowing()) {
|
|
1183
|
+
header._hide();
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
/**
|
|
1189
|
+
* 判断窗口A是否在窗口B的上层 (如果是同一个窗口,返回false)
|
|
1190
|
+
* @internal
|
|
1191
|
+
*/
|
|
1192
|
+
static isWindowAbove(windowA, windowB) {
|
|
1193
|
+
if (windowA === windowB) {
|
|
1194
|
+
return false;
|
|
1195
|
+
}
|
|
1196
|
+
const infoA = InfoPool.get(windowA);
|
|
1197
|
+
const infoB = InfoPool.get(windowB);
|
|
1198
|
+
// 先比较窗口组
|
|
1199
|
+
const groupNames = WindowManager.getGroupNames();
|
|
1200
|
+
const groupIndexA = groupNames.indexOf(infoA.group);
|
|
1201
|
+
const groupIndexB = groupNames.indexOf(infoB.group);
|
|
1202
|
+
if (groupIndexA !== groupIndexB) {
|
|
1203
|
+
return groupIndexA > groupIndexB;
|
|
1204
|
+
}
|
|
1205
|
+
// 同一个组,比较窗口在组内的位置
|
|
1206
|
+
const group = WindowManager.getWindowGroup(infoA.group);
|
|
1207
|
+
const indexA = group.windowNames.indexOf(windowA);
|
|
1208
|
+
const indexB = group.windowNames.indexOf(windowB);
|
|
1209
|
+
return indexA > indexB;
|
|
1210
|
+
}
|
|
1211
|
+
/**
|
|
1212
|
+
* 为header查找新的最上层窗口(排除指定窗口)
|
|
1213
|
+
* @internal
|
|
1214
|
+
*/
|
|
1215
|
+
static findTopWindowForHeader(headerName, excludeWindow) {
|
|
1216
|
+
const windowNames = this._headerWindowsMap.get(headerName);
|
|
1217
|
+
if (!windowNames || windowNames.size === 0) {
|
|
1218
|
+
return null;
|
|
1219
|
+
}
|
|
1220
|
+
// 从上到下遍历窗口组
|
|
1221
|
+
const groupNames = WindowManager.getGroupNames();
|
|
1222
|
+
for (let i = groupNames.length - 1; i >= 0; i--) {
|
|
1223
|
+
// 从上到下遍历组内窗口
|
|
1224
|
+
const group = WindowManager.getWindowGroup(groupNames[i]);
|
|
1225
|
+
for (let j = group.windowNames.length - 1; j >= 0; j--) {
|
|
1226
|
+
const wName = group.windowNames[j];
|
|
1227
|
+
if (wName === excludeWindow) {
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
if (!windowNames.has(wName)) {
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
const win = WindowManager.getWindow(wName);
|
|
1234
|
+
if (win && win.isShowing()) {
|
|
1235
|
+
return wName; // 找到就返回,不继续遍历
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
return null;
|
|
1240
|
+
}
|
|
1241
|
+
/**
|
|
1242
|
+
* 调整header到指定窗口的位置
|
|
1243
|
+
* @internal
|
|
1244
|
+
*/
|
|
1245
|
+
static adjustHeaderPosition(headerName, windowName) {
|
|
1246
|
+
const header = this._headers.get(headerName);
|
|
1247
|
+
const window = WindowManager.getWindow(windowName);
|
|
1248
|
+
const info = InfoPool.get(windowName);
|
|
1249
|
+
const group = WindowManager.getWindowGroup(info.group);
|
|
1250
|
+
const parent = group.root;
|
|
1251
|
+
// 移动header到对应的group
|
|
1252
|
+
if (header.parent !== parent) {
|
|
1253
|
+
header.removeFromParent();
|
|
1254
|
+
parent.addChild(header);
|
|
1255
|
+
}
|
|
1256
|
+
// 调整层级:找到该组中最上层的显示窗口
|
|
1257
|
+
let maxWindowIndex = parent.getChildIndex(window);
|
|
1258
|
+
for (let i = group.windowNames.length - 1; i >= 0; i--) {
|
|
1259
|
+
const win = WindowManager.getWindow(group.windowNames[i]);
|
|
1260
|
+
if (win && win.isShowing()) {
|
|
1261
|
+
maxWindowIndex = Math.max(maxWindowIndex, parent.getChildIndex(win));
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
parent.setChildIndex(header, maxWindowIndex + 1);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
/** @internal */
|
|
1268
|
+
HeaderManager._headers = new Map(); // header名 > header实例
|
|
1269
|
+
/** @internal */
|
|
1270
|
+
HeaderManager._refCounts = new Map(); // header名 > 引用计数
|
|
1271
|
+
/** @internal */
|
|
1272
|
+
HeaderManager._headerWindowsMap = new Map(); // header名 > 窗口名列表
|
|
1273
|
+
/** @internal */
|
|
1274
|
+
HeaderManager._headerInfos = new Map(); // 窗口名 > header的数据
|
|
1275
|
+
/** @internal */
|
|
1276
|
+
HeaderManager._cacheHeaderTopWindow = new Map(); // header名 > 缓存的当前显示该header的最上层窗口名
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* @Author: Gongxh
|
|
1280
|
+
* @Date: 2024-12-08
|
|
1281
|
+
* @Description: 窗口组 (在同一个窗口容器的上的窗口)
|
|
1282
|
+
*/
|
|
1283
|
+
class WindowGroup {
|
|
1284
|
+
/**
|
|
1285
|
+
* 获取窗口组的名称。
|
|
1286
|
+
* @returns {string} 窗口组的名称。
|
|
1287
|
+
*/
|
|
1288
|
+
get name() { return this._name; }
|
|
1289
|
+
/** 获取窗口组的根节点 */
|
|
1290
|
+
get root() { return this._root; }
|
|
1291
|
+
/**
|
|
1292
|
+
* 获取当前窗口组中窗口的数量。
|
|
1293
|
+
* @returns 窗口数量
|
|
1294
|
+
*/
|
|
1295
|
+
get size() { return this._windowNames.length; }
|
|
1296
|
+
/** 获取窗口组中窗口的名称列表 */
|
|
1297
|
+
get windowNames() { return this._windowNames; }
|
|
1298
|
+
/**
|
|
1299
|
+
* 获取是否忽略查询的状态。
|
|
1300
|
+
* @returns {boolean} 如果忽略查询,则返回 true,否则返回 false。
|
|
1301
|
+
*/
|
|
1302
|
+
get isIgnore() { return this._ignore; }
|
|
1303
|
+
/**
|
|
1304
|
+
* 实例化
|
|
1305
|
+
* @param name 组名
|
|
1306
|
+
* @param root 窗口组的根节点 一个fgui的组件
|
|
1307
|
+
* @param ignoreQuery 是否忽略顶部窗口查询
|
|
1308
|
+
* @param swallowTouch 是否吞掉触摸事件
|
|
1309
|
+
* @param bgAlpha 半透明遮罩的透明度
|
|
1310
|
+
* @internal
|
|
1311
|
+
*/
|
|
1312
|
+
constructor(name, root, ignoreQuery, swallowTouch) {
|
|
1313
|
+
/** @internal */
|
|
1314
|
+
this._name = ""; // 窗口组的名字
|
|
1315
|
+
/** @internal */
|
|
1316
|
+
this._ignore = false; // 忽略查询
|
|
1317
|
+
/** @internal */
|
|
1318
|
+
this._swallowTouch = false; // 吞噬触摸事件
|
|
1319
|
+
/** @internal */
|
|
1320
|
+
this._windowNames = []; // 窗口名列表 顺序为窗口显示的层级 (最后一个显示在最上层)
|
|
1321
|
+
this._name = name;
|
|
1322
|
+
this._root = root;
|
|
1323
|
+
this._ignore = ignoreQuery;
|
|
1324
|
+
this._swallowTouch = swallowTouch;
|
|
1325
|
+
this._windowNames = [];
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* 显示一个窗口
|
|
1329
|
+
* @param info 窗口信息
|
|
1330
|
+
* @param userdata
|
|
1331
|
+
* @internal
|
|
1332
|
+
*/
|
|
1333
|
+
showWindow(info, userdata) {
|
|
1334
|
+
return new Promise((resolve, reject) => {
|
|
1335
|
+
let lastTopWindow = WindowManager.getTopWindow();
|
|
1336
|
+
if (WindowManager.hasWindow(info.name)) {
|
|
1337
|
+
const window = WindowManager.getWindow(info.name);
|
|
1338
|
+
this.showAdjustment(window, userdata);
|
|
1339
|
+
if (lastTopWindow && lastTopWindow.name !== window.name) {
|
|
1340
|
+
lastTopWindow._toBottom();
|
|
1341
|
+
}
|
|
1342
|
+
window._toTop();
|
|
1343
|
+
resolve(window);
|
|
1344
|
+
}
|
|
1345
|
+
else {
|
|
1346
|
+
ResLoader.loadWindowRes(info.name).then(() => {
|
|
1347
|
+
const window = this.createWindow(info.pkgName, info.name);
|
|
1348
|
+
this.showAdjustment(window, userdata);
|
|
1349
|
+
if (lastTopWindow && lastTopWindow.name !== window.name) {
|
|
1350
|
+
lastTopWindow._toBottom();
|
|
1351
|
+
}
|
|
1352
|
+
resolve(window);
|
|
1353
|
+
}).catch((err) => {
|
|
1354
|
+
reject(new Error(`窗口【${info.name}】打开失败: ${err.message}`));
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
523
1357
|
});
|
|
524
1358
|
}
|
|
525
1359
|
/**
|
|
526
|
-
*
|
|
527
|
-
* @
|
|
1360
|
+
* show一个界面后的调整
|
|
1361
|
+
* @param window
|
|
1362
|
+
* @internal
|
|
1363
|
+
*/
|
|
1364
|
+
showAdjustment(window, userdata) {
|
|
1365
|
+
// 如果窗口不在最上层 则调整层级
|
|
1366
|
+
this.moveWindowToTop(window);
|
|
1367
|
+
// 显示窗口
|
|
1368
|
+
window._show(userdata);
|
|
1369
|
+
// 尝试显示header
|
|
1370
|
+
HeaderManager.showHeader(window.name);
|
|
1371
|
+
// 调整半透明遮罩
|
|
1372
|
+
WindowManager.adjustAlphaGraph();
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* 将指定名称的窗口移动到窗口组的最顶层。
|
|
1376
|
+
* @param name 窗口的名称。
|
|
1377
|
+
* @internal
|
|
1378
|
+
*/
|
|
1379
|
+
moveWindowToTop(window) {
|
|
1380
|
+
if (window.name !== this._windowNames[this.size - 1]) {
|
|
1381
|
+
const index = this._windowNames.indexOf(window.name);
|
|
1382
|
+
if (index < 0) {
|
|
1383
|
+
console.error(`[BUG] 窗口【${window.name}】不在数组中,数据结构已损坏`);
|
|
1384
|
+
return;
|
|
1385
|
+
}
|
|
1386
|
+
this._windowNames.splice(index, 1);
|
|
1387
|
+
// 放到数组的末尾
|
|
1388
|
+
this._windowNames.push(window.name);
|
|
1389
|
+
}
|
|
1390
|
+
// 根据窗口的type, 处理上一个窗口的关闭状态
|
|
1391
|
+
this._processWindowCloseStatus(window);
|
|
1392
|
+
// 调整窗口的显示层级
|
|
1393
|
+
window.setDepth(this._root.numChildren - 1);
|
|
1394
|
+
// 处理窗口显示和隐藏状态
|
|
1395
|
+
this.processWindowHideStatus(this.size - 1);
|
|
1396
|
+
}
|
|
1397
|
+
/**
|
|
1398
|
+
* 根据窗口名创建窗口 并添加到显示节点
|
|
1399
|
+
* @param windowName 窗口名
|
|
1400
|
+
* @internal
|
|
1401
|
+
*/
|
|
1402
|
+
createWindow(pkg, name) {
|
|
1403
|
+
let window = fairyguiCc.UIPackage.createObject(pkg, name);
|
|
1404
|
+
window.name = name;
|
|
1405
|
+
PropsHelper.serializeProps(window, pkg);
|
|
1406
|
+
window._init(this._swallowTouch);
|
|
1407
|
+
window._adapted();
|
|
1408
|
+
// 添加到显示节点
|
|
1409
|
+
this._root.addChild(window);
|
|
1410
|
+
// 窗口组之前没有窗口, 显示窗口组节点
|
|
1411
|
+
if (this.size === 0) {
|
|
1412
|
+
this._root.visible = true;
|
|
1413
|
+
}
|
|
1414
|
+
this._windowNames.push(name);
|
|
1415
|
+
WindowManager.addWindow(name, window);
|
|
1416
|
+
// 处理header(只请求,不立即添加到节点,由adjustHeaderDepth动态管理)
|
|
1417
|
+
HeaderManager.requestHeader(name, window.getHeaderInfo());
|
|
1418
|
+
return window;
|
|
1419
|
+
}
|
|
1420
|
+
/**
|
|
1421
|
+
* 处理index下层窗口的隐藏状态的私有方法。递归调用
|
|
1422
|
+
* @param index - 窗口索引
|
|
1423
|
+
*/
|
|
1424
|
+
processWindowHideStatus(startIndex) {
|
|
1425
|
+
let curWindow = WindowManager.getWindow(this._windowNames[startIndex]);
|
|
1426
|
+
// 如果当前是当前组中的最后一个窗口并且当前窗口是隐藏状态 则恢复隐藏
|
|
1427
|
+
if (curWindow && startIndex == this.size - 1 && !curWindow.isShowing()) {
|
|
1428
|
+
curWindow._showFromHide();
|
|
1429
|
+
// 恢复显示header
|
|
1430
|
+
HeaderManager.showHeader(curWindow.name);
|
|
1431
|
+
}
|
|
1432
|
+
// 已经是最后一个了
|
|
1433
|
+
if (startIndex <= 0) {
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
// 遍历到倒数第二个窗口停止
|
|
1437
|
+
for (let index = startIndex; index > 0; index--) {
|
|
1438
|
+
let window = WindowManager.getWindow(this._windowNames[index]);
|
|
1439
|
+
if (!window) {
|
|
1440
|
+
console.error(`[BUG] 窗口【${this._windowNames[index]}】不存在,数据结构已损坏`);
|
|
1441
|
+
return;
|
|
1442
|
+
}
|
|
1443
|
+
if (window.type === exports.WindowType.HideAll) {
|
|
1444
|
+
// 隐藏所有
|
|
1445
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
1446
|
+
let name = this._windowNames[i];
|
|
1447
|
+
const window = WindowManager.getWindow(name);
|
|
1448
|
+
if (window && window.isShowing()) {
|
|
1449
|
+
window._hide();
|
|
1450
|
+
// 隐藏header
|
|
1451
|
+
HeaderManager.hideHeader(name);
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
break;
|
|
1455
|
+
}
|
|
1456
|
+
else if (window.type === exports.WindowType.HideOne) {
|
|
1457
|
+
// 隐藏前一个窗口
|
|
1458
|
+
let prevWindowName = this._windowNames[index - 1];
|
|
1459
|
+
let prevWindow = WindowManager.getWindow(prevWindowName);
|
|
1460
|
+
if (prevWindow && prevWindow.isShowing()) {
|
|
1461
|
+
prevWindow._hide();
|
|
1462
|
+
// 隐藏header
|
|
1463
|
+
HeaderManager.hideHeader(prevWindowName);
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
else {
|
|
1467
|
+
// 如果前一个窗口是隐藏状态 需要恢复显示
|
|
1468
|
+
let prevWindowName = this._windowNames[index - 1];
|
|
1469
|
+
let prevWindow = WindowManager.getWindow(prevWindowName);
|
|
1470
|
+
if (prevWindow && !prevWindow.isShowing()) {
|
|
1471
|
+
prevWindow._showFromHide();
|
|
1472
|
+
// 恢复显示header(使用记录的userdata)
|
|
1473
|
+
HeaderManager.showHeader(prevWindowName);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* 根据传入窗口的关闭类型, 处理上一个窗口或者所有窗口的关闭
|
|
1480
|
+
* @param window 新创建的窗口
|
|
1481
|
+
* @internal
|
|
1482
|
+
*/
|
|
1483
|
+
_processWindowCloseStatus(window) {
|
|
1484
|
+
// 最后一个是新显示上来的窗口
|
|
1485
|
+
if (window.type === exports.WindowType.CloseOne) {
|
|
1486
|
+
// 关闭上一个窗口(倒数第二个,因为最后一个是当前窗口)
|
|
1487
|
+
if (this.size <= 1) {
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1490
|
+
const name = this._windowNames[this.size - 2];
|
|
1491
|
+
this._windowNames.splice(this.size - 2, 1);
|
|
1492
|
+
const win = WindowManager.getWindow(name);
|
|
1493
|
+
if (!win) {
|
|
1494
|
+
console.error(`[BUG] 窗口【${name}】不存在,数据结构已损坏`);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
// 释放header
|
|
1498
|
+
HeaderManager.releaseHeader(name);
|
|
1499
|
+
win._close();
|
|
1500
|
+
WindowManager.removeWindow(name);
|
|
1501
|
+
}
|
|
1502
|
+
else if (window.type === exports.WindowType.CloseAll) {
|
|
1503
|
+
// 关闭所有窗口 从后向前依次删除
|
|
1504
|
+
for (let i = this.size - 2; i >= 0; i--) {
|
|
1505
|
+
const name = this._windowNames[i];
|
|
1506
|
+
const win = WindowManager.getWindow(name);
|
|
1507
|
+
if (!win) {
|
|
1508
|
+
console.error(`[BUG] 窗口【${name}】不存在,数据结构已损坏`);
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
// 释放header
|
|
1512
|
+
HeaderManager.releaseHeader(name);
|
|
1513
|
+
win._close();
|
|
1514
|
+
WindowManager.removeWindow(name);
|
|
1515
|
+
}
|
|
1516
|
+
// 清理数组,只保留最后一个(当前窗口)
|
|
1517
|
+
this._windowNames.splice(0, this.size - 1);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* 移除指定名称的窗口。
|
|
1522
|
+
* @param name 窗口的名称。
|
|
1523
|
+
* @internal
|
|
1524
|
+
*/
|
|
1525
|
+
removeWindow(name) {
|
|
1526
|
+
let window = WindowManager.getWindow(name);
|
|
1527
|
+
if (!window) {
|
|
1528
|
+
console.error(`[BUG] 窗口【${name}】不存在,数据结构已损坏`);
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1531
|
+
// 释放header引用
|
|
1532
|
+
HeaderManager.releaseHeader(name);
|
|
1533
|
+
window._close();
|
|
1534
|
+
// 先删除窗口组中记录的窗口名称
|
|
1535
|
+
let index = this._windowNames.lastIndexOf(name);
|
|
1536
|
+
if (index < 0) {
|
|
1537
|
+
console.error(`[BUG] 窗口【${name}】不在数组中,数据结构已损坏`);
|
|
1538
|
+
return;
|
|
1539
|
+
}
|
|
1540
|
+
this._windowNames.splice(index, 1);
|
|
1541
|
+
// 删除WindowManager中记录的窗口
|
|
1542
|
+
WindowManager.removeWindow(name);
|
|
1543
|
+
// 释放资源
|
|
1544
|
+
ResLoader.unloadWindowRes(name);
|
|
1545
|
+
if (this.size == 0) {
|
|
1546
|
+
this._root.visible = false;
|
|
1547
|
+
}
|
|
1548
|
+
else {
|
|
1549
|
+
this.processWindowHideStatus(this.size - 1);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
hasWindow(name) {
|
|
1553
|
+
return this._windowNames.indexOf(name) >= 0;
|
|
1554
|
+
}
|
|
1555
|
+
/**
|
|
1556
|
+
* 获取窗口组顶部窗口实例
|
|
1557
|
+
* @returns {IWindow} 顶部窗口实例
|
|
1558
|
+
*/
|
|
1559
|
+
getTopWindow() {
|
|
1560
|
+
if (this.size > 0) {
|
|
1561
|
+
return WindowManager.getWindow(this._windowNames[this.size - 1]);
|
|
1562
|
+
}
|
|
1563
|
+
console.warn(`窗口组【${this._name}】中不存在窗口`);
|
|
1564
|
+
return null;
|
|
1565
|
+
}
|
|
1566
|
+
/**
|
|
1567
|
+
* 关闭窗口组中的所有窗口
|
|
1568
|
+
* @param ignores 不关闭的窗口名
|
|
528
1569
|
* @internal
|
|
529
1570
|
*/
|
|
530
|
-
|
|
531
|
-
|
|
1571
|
+
closeAllWindow(ignores = []) {
|
|
1572
|
+
let len = this.size - 1;
|
|
1573
|
+
for (let i = len; i >= 0; i--) {
|
|
1574
|
+
let name = this._windowNames[i];
|
|
1575
|
+
// 如果当前窗口在ignores列表中,跳过
|
|
1576
|
+
if (ignores.some(ignore => ignore.name === name)) {
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
const window = WindowManager.getWindow(name);
|
|
1580
|
+
if (!window) {
|
|
1581
|
+
console.error(`[BUG] 窗口【${name}】不存在,数据结构已损坏`);
|
|
1582
|
+
return;
|
|
1583
|
+
}
|
|
1584
|
+
// 释放header
|
|
1585
|
+
HeaderManager.releaseHeader(name);
|
|
1586
|
+
window._close();
|
|
1587
|
+
WindowManager.removeWindow(name);
|
|
1588
|
+
// 从数组中删除
|
|
1589
|
+
this._windowNames.splice(i, 1);
|
|
1590
|
+
}
|
|
1591
|
+
// 统一处理窗口的显示状态
|
|
1592
|
+
if (this.size == 0) {
|
|
1593
|
+
this._root.visible = false;
|
|
1594
|
+
}
|
|
1595
|
+
else {
|
|
1596
|
+
this.processWindowHideStatus(this.size - 1);
|
|
1597
|
+
}
|
|
532
1598
|
}
|
|
533
1599
|
}
|
|
534
|
-
/** 窗口组 @internal */
|
|
535
|
-
UIManager._groups = new Map();
|
|
536
|
-
/** 不忽略查询的窗口组名 @internal */
|
|
537
|
-
UIManager._queryGroupNames = [];
|
|
538
|
-
/** 所有窗口全部放到这个map中 @internal */
|
|
539
|
-
UIManager._windows = new Map();
|
|
540
1600
|
|
|
541
1601
|
/**
|
|
542
1602
|
* @Author: Gongxh
|
|
543
1603
|
* @Date: 2024-12-11
|
|
544
1604
|
* @Description: UI 装饰器
|
|
545
1605
|
*/
|
|
1606
|
+
/**
|
|
1607
|
+
* 获取对象属性
|
|
1608
|
+
* @param obj 对象
|
|
1609
|
+
* @param key 属性名
|
|
1610
|
+
* @returns 属性值
|
|
1611
|
+
*/
|
|
1612
|
+
function getObjectProp(obj, key) {
|
|
1613
|
+
if (obj.hasOwnProperty(key)) {
|
|
1614
|
+
return obj[key];
|
|
1615
|
+
}
|
|
1616
|
+
return (obj[key] = Object.assign({}, obj[key]));
|
|
1617
|
+
}
|
|
546
1618
|
exports._uidecorator = void 0;
|
|
547
1619
|
(function (_uidecorator) {
|
|
548
1620
|
/** @internal */
|
|
549
|
-
const
|
|
1621
|
+
const uiclassMap = new Map(); // 窗口注册信息
|
|
550
1622
|
/** @internal */
|
|
551
|
-
const
|
|
1623
|
+
const uicomponentMap = new Map(); // 组件注册信息
|
|
552
1624
|
/** @internal */
|
|
553
|
-
const
|
|
554
|
-
/** @internal */
|
|
555
|
-
const UITransitionMeta = "__uitransitionmeta__";
|
|
556
|
-
/** 用来存储窗口注册信息 @internal */
|
|
557
|
-
const uiclassMap = new Map();
|
|
558
|
-
/**
|
|
559
|
-
* 获取对象属性
|
|
560
|
-
* @param obj 对象
|
|
561
|
-
* @param key 属性名
|
|
562
|
-
* @returns 属性值
|
|
563
|
-
*/
|
|
564
|
-
function getObjectProp(obj, key) {
|
|
565
|
-
if (obj.hasOwnProperty(key)) {
|
|
566
|
-
return obj[key];
|
|
567
|
-
}
|
|
568
|
-
return (obj[key] = Object.assign({}, obj[key]));
|
|
569
|
-
}
|
|
1625
|
+
const uiheaderMap = new Map(); // header注册信息
|
|
570
1626
|
/** 获取窗口注册信息 */
|
|
571
|
-
function getWindowMaps() {
|
|
572
|
-
return uiclassMap;
|
|
573
|
-
}
|
|
1627
|
+
function getWindowMaps() { return uiclassMap; }
|
|
574
1628
|
_uidecorator.getWindowMaps = getWindowMaps;
|
|
1629
|
+
/** 获取组件注册信息 */
|
|
1630
|
+
function getComponentMaps() { return uicomponentMap; }
|
|
1631
|
+
_uidecorator.getComponentMaps = getComponentMaps;
|
|
1632
|
+
/** 获取header注册信息 */
|
|
1633
|
+
function getHeaderMaps() { return uiheaderMap; }
|
|
1634
|
+
_uidecorator.getHeaderMaps = getHeaderMaps;
|
|
575
1635
|
/**
|
|
576
1636
|
* 窗口装饰器
|
|
577
1637
|
* @param {string} groupName 窗口组名称
|
|
578
1638
|
* @param {string} pkgName fgui包名
|
|
579
1639
|
* @param {string} name 窗口名 (与fgui中的组件名一一对应)
|
|
1640
|
+
* @param {string[] | string} inlinePkgs 内联的包名 当前界面需要引用其他包中的资源时使用 引用多个包用数组 引用单个包用字符串
|
|
1641
|
+
*
|
|
1642
|
+
* @example @uiclass("窗口组", "UI包名", "MyWindow", ["包名1", "包名2"])
|
|
1643
|
+
* @example @uiclass("窗口组", "UI包名", "MyWindow", "包名1")
|
|
580
1644
|
*/
|
|
581
|
-
function uiclass(groupName, pkgName, name,
|
|
1645
|
+
function uiclass(groupName, pkgName, name, inlinePkgs) {
|
|
582
1646
|
/** target 类的构造函数 */
|
|
583
1647
|
return function (ctor) {
|
|
584
1648
|
// 检查是否有原始构造函数引用(由其他装饰器如 @dataclass 提供)
|
|
585
1649
|
const originalCtor = ctor;
|
|
1650
|
+
// 给构造函数添加静态属性,存储窗口名称(避免混淆后 constructor.name 变化)
|
|
1651
|
+
ctor[MetadataKey.originalName] = name;
|
|
586
1652
|
uiclassMap.set(originalCtor, {
|
|
587
1653
|
ctor: ctor, // 存储实际的构造函数(可能被包装过)
|
|
588
|
-
props: ctor[
|
|
589
|
-
callbacks: ctor[
|
|
590
|
-
controls: ctor[
|
|
591
|
-
transitions: ctor[
|
|
1654
|
+
props: ctor[MetadataKey.prop] || null,
|
|
1655
|
+
callbacks: ctor[MetadataKey.callback] || null,
|
|
1656
|
+
controls: ctor[MetadataKey.control] || null,
|
|
1657
|
+
transitions: ctor[MetadataKey.transition] || null,
|
|
592
1658
|
res: {
|
|
593
1659
|
group: groupName,
|
|
594
1660
|
pkg: pkgName,
|
|
595
1661
|
name: name,
|
|
596
|
-
bundle: bundle || "",
|
|
597
1662
|
},
|
|
598
1663
|
});
|
|
599
|
-
|
|
600
|
-
|
|
1664
|
+
let pkgs = [];
|
|
1665
|
+
if (Array.isArray(inlinePkgs)) {
|
|
1666
|
+
pkgs = inlinePkgs;
|
|
1667
|
+
}
|
|
1668
|
+
else if (typeof inlinePkgs === "string") {
|
|
1669
|
+
pkgs = [inlinePkgs];
|
|
1670
|
+
}
|
|
1671
|
+
InfoPool.add(ctor, groupName, pkgName, name, pkgs);
|
|
601
1672
|
return ctor;
|
|
602
1673
|
};
|
|
603
1674
|
}
|
|
604
1675
|
_uidecorator.uiclass = uiclass;
|
|
605
|
-
/** 用来存储组件注册信息 @internal */
|
|
606
|
-
let uicomponentMap = new Map();
|
|
607
|
-
/** 获取组件注册信息 */
|
|
608
|
-
function getComponentMaps() {
|
|
609
|
-
return uicomponentMap;
|
|
610
|
-
}
|
|
611
|
-
_uidecorator.getComponentMaps = getComponentMaps;
|
|
612
1676
|
/**
|
|
613
1677
|
* UI组件装饰器
|
|
614
1678
|
* @param {string} pkg 包名
|
|
@@ -619,54 +1683,46 @@ exports._uidecorator = void 0;
|
|
|
619
1683
|
// 检查是否有原始构造函数引用(由其他装饰器如 @dataclass 提供)
|
|
620
1684
|
const originalCtor = ctor;
|
|
621
1685
|
// log(`pkg:【${pkg}】 uicom prop >${JSON.stringify(ctor[UIPropMeta] || {})}<`);
|
|
1686
|
+
ctor[MetadataKey.originalName] = name;
|
|
622
1687
|
uicomponentMap.set(originalCtor, {
|
|
623
1688
|
ctor: ctor, // 存储实际的构造函数(可能被包装过)
|
|
624
|
-
props: ctor[
|
|
625
|
-
callbacks: ctor[
|
|
626
|
-
controls: ctor[
|
|
627
|
-
transitions: ctor[
|
|
1689
|
+
props: ctor[MetadataKey.prop] || null,
|
|
1690
|
+
callbacks: ctor[MetadataKey.callback] || null,
|
|
1691
|
+
controls: ctor[MetadataKey.control] || null,
|
|
1692
|
+
transitions: ctor[MetadataKey.transition] || null,
|
|
628
1693
|
res: {
|
|
629
1694
|
pkg: pkg,
|
|
630
1695
|
name: name,
|
|
631
1696
|
}
|
|
632
1697
|
});
|
|
633
|
-
|
|
634
|
-
_registerFinish && ComponentExtendHelper.dynamicRegister(ctor, pkg, name);
|
|
1698
|
+
InfoPool.addComponent(ctor, pkg, name);
|
|
635
1699
|
return ctor;
|
|
636
1700
|
};
|
|
637
1701
|
}
|
|
638
1702
|
_uidecorator.uicom = uicom;
|
|
639
|
-
/** 用来存储组件注册信息 @internal */
|
|
640
|
-
let uiheaderMap = new Map();
|
|
641
|
-
/** 获取header注册信息 */
|
|
642
|
-
function getHeaderMaps() {
|
|
643
|
-
return uiheaderMap;
|
|
644
|
-
}
|
|
645
|
-
_uidecorator.getHeaderMaps = getHeaderMaps;
|
|
646
1703
|
/**
|
|
647
1704
|
* UI header装饰器
|
|
648
1705
|
* @param {string} pkg 包名
|
|
649
1706
|
* @param {string} name 组件名
|
|
650
1707
|
*/
|
|
651
|
-
function uiheader(pkg, name
|
|
1708
|
+
function uiheader(pkg, name) {
|
|
652
1709
|
return function (ctor) {
|
|
653
1710
|
// 检查是否有原始构造函数引用(由其他装饰器如 @dataclass 提供)
|
|
654
1711
|
const originalCtor = ctor;
|
|
655
1712
|
// log(`pkg:【${pkg}】 uiheader prop >${JSON.stringify(ctor[UIPropMeta] || {})}<`);
|
|
1713
|
+
ctor[MetadataKey.originalName] = name;
|
|
656
1714
|
uiheaderMap.set(originalCtor, {
|
|
657
1715
|
ctor: ctor, // 存储实际的构造函数(可能被包装过)
|
|
658
|
-
props: ctor[
|
|
659
|
-
callbacks: ctor[
|
|
660
|
-
controls: ctor[
|
|
661
|
-
transitions: ctor[
|
|
1716
|
+
props: ctor[MetadataKey.prop] || null,
|
|
1717
|
+
callbacks: ctor[MetadataKey.callback] || null,
|
|
1718
|
+
controls: ctor[MetadataKey.control] || null,
|
|
1719
|
+
transitions: ctor[MetadataKey.transition] || null,
|
|
662
1720
|
res: {
|
|
663
1721
|
pkg: pkg,
|
|
664
1722
|
name: name,
|
|
665
|
-
bundle: bundle || "",
|
|
666
1723
|
}
|
|
667
1724
|
});
|
|
668
|
-
|
|
669
|
-
_registerFinish && UIManager.dynamicRegisterHeader(ctor, pkg, name, bundle || "");
|
|
1725
|
+
InfoPool.addHeader(ctor, pkg, name);
|
|
670
1726
|
return ctor;
|
|
671
1727
|
};
|
|
672
1728
|
}
|
|
@@ -680,7 +1736,7 @@ exports._uidecorator = void 0;
|
|
|
680
1736
|
*/
|
|
681
1737
|
function uiprop(target, name) {
|
|
682
1738
|
// debug("属性装饰器:", target.constructor, name);
|
|
683
|
-
getObjectProp(target.constructor,
|
|
1739
|
+
getObjectProp(target.constructor, MetadataKey.prop)[name] = 1;
|
|
684
1740
|
}
|
|
685
1741
|
_uidecorator.uiprop = uiprop;
|
|
686
1742
|
/**
|
|
@@ -692,7 +1748,7 @@ exports._uidecorator = void 0;
|
|
|
692
1748
|
*/
|
|
693
1749
|
function uicontrol(target, name) {
|
|
694
1750
|
// debug("属性装饰器:", target.constructor, name);
|
|
695
|
-
getObjectProp(target.constructor,
|
|
1751
|
+
getObjectProp(target.constructor, MetadataKey.control)[name] = 1;
|
|
696
1752
|
}
|
|
697
1753
|
_uidecorator.uicontrol = uicontrol;
|
|
698
1754
|
/**
|
|
@@ -704,7 +1760,7 @@ exports._uidecorator = void 0;
|
|
|
704
1760
|
*/
|
|
705
1761
|
function uitransition(target, name) {
|
|
706
1762
|
// debug("属性装饰器:", target.constructor, name);
|
|
707
|
-
getObjectProp(target.constructor,
|
|
1763
|
+
getObjectProp(target.constructor, MetadataKey.transition)[name] = 1;
|
|
708
1764
|
}
|
|
709
1765
|
_uidecorator.uitransition = uitransition;
|
|
710
1766
|
/**
|
|
@@ -714,15 +1770,9 @@ exports._uidecorator = void 0;
|
|
|
714
1770
|
*/
|
|
715
1771
|
function uiclick(target, name, descriptor) {
|
|
716
1772
|
// debug("方法装饰器:", target.constructor, name, descriptor);
|
|
717
|
-
getObjectProp(target.constructor,
|
|
1773
|
+
getObjectProp(target.constructor, MetadataKey.callback)[name] = descriptor.value;
|
|
718
1774
|
}
|
|
719
1775
|
_uidecorator.uiclick = uiclick;
|
|
720
|
-
let _registerFinish = false;
|
|
721
|
-
/** 首次UI注册完成 */
|
|
722
|
-
function setRegisterFinish() {
|
|
723
|
-
_registerFinish = true;
|
|
724
|
-
}
|
|
725
|
-
_uidecorator.setRegisterFinish = setRegisterFinish;
|
|
726
1776
|
})(exports._uidecorator || (exports._uidecorator = {}));
|
|
727
1777
|
const _global = (globalThis || window || global);
|
|
728
1778
|
_global["getKunpoRegisterWindowMaps"] = function () {
|
|
@@ -737,55 +1787,51 @@ _global["getKunpoRegisterHeaderMaps"] = function () {
|
|
|
737
1787
|
|
|
738
1788
|
/**
|
|
739
1789
|
* @Author: Gongxh
|
|
740
|
-
* @Date:
|
|
741
|
-
* @Description:
|
|
1790
|
+
* @Date: 2025-01-11
|
|
1791
|
+
* @Description: 窗口顶边栏
|
|
1792
|
+
* 窗口顶边资源栏 同组中只会有一个显示
|
|
742
1793
|
*/
|
|
743
|
-
class
|
|
1794
|
+
class Header extends fairyguiCc.GComponent {
|
|
744
1795
|
constructor() {
|
|
745
1796
|
super(...arguments);
|
|
746
|
-
/** 窗口类型 */
|
|
747
|
-
this.type = exports.WindowType.Normal;
|
|
748
1797
|
/** 窗口适配类型 */
|
|
749
1798
|
this.adapterType = exports.AdapterType.Full;
|
|
750
|
-
/** header (内部使用) @internal */
|
|
751
|
-
this._header = null;
|
|
752
|
-
/** 窗口是否被遮挡了 @internal */
|
|
753
|
-
this._isCover = false;
|
|
754
|
-
/** 吞噬触摸的节点 @internal */
|
|
755
|
-
this._swallowComponent = null;
|
|
756
1799
|
}
|
|
1800
|
+
onAdapted() { }
|
|
1801
|
+
;
|
|
1802
|
+
onClose() { }
|
|
1803
|
+
;
|
|
1804
|
+
onHide() { }
|
|
1805
|
+
;
|
|
1806
|
+
onShowFromHide() { }
|
|
1807
|
+
;
|
|
757
1808
|
/**
|
|
758
|
-
*
|
|
759
|
-
|
|
760
|
-
|
|
1809
|
+
* 是否显示中
|
|
1810
|
+
*/
|
|
1811
|
+
isShowing() {
|
|
1812
|
+
return this.visible;
|
|
1813
|
+
}
|
|
1814
|
+
/**
|
|
1815
|
+
* 初始化 (内部方法)
|
|
761
1816
|
* @internal
|
|
762
1817
|
*/
|
|
763
|
-
_init(
|
|
764
|
-
|
|
765
|
-
// 吞噬触摸事件,需要一个全屏的节点, 窗口本身可能留有安全区的边
|
|
766
|
-
let bgNode = new fairyguiCc.GComponent();
|
|
767
|
-
bgNode.name = "swallow";
|
|
768
|
-
bgNode.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
769
|
-
bgNode.setPivot(0.5, 0.5, true);
|
|
770
|
-
bgNode.setPosition(this.width * 0.5, this.height * 0.5);
|
|
771
|
-
this.addChild(bgNode);
|
|
772
|
-
// 调整显示层级
|
|
773
|
-
bgNode.parent.setChildIndex(bgNode, 0);
|
|
774
|
-
bgNode.onClick(this.onEmptyAreaClick, this);
|
|
775
|
-
bgNode.opaque = swallowTouch;
|
|
776
|
-
this._swallowComponent = bgNode;
|
|
777
|
-
}
|
|
778
|
-
// 窗口自身也要设置是否吞噬触摸
|
|
779
|
-
this.opaque = swallowTouch;
|
|
780
|
-
this.bgAlpha = bgAlpha;
|
|
1818
|
+
_init() {
|
|
1819
|
+
this.opaque = false;
|
|
781
1820
|
this.onInit();
|
|
782
1821
|
}
|
|
783
1822
|
/**
|
|
784
|
-
*
|
|
1823
|
+
* 关闭 (内部方法)
|
|
1824
|
+
* @internal
|
|
1825
|
+
*/
|
|
1826
|
+
_close() {
|
|
1827
|
+
this.onClose();
|
|
1828
|
+
this.dispose();
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* 窗口适配
|
|
785
1832
|
* @internal
|
|
786
1833
|
*/
|
|
787
1834
|
_adapted() {
|
|
788
|
-
var _a, _b;
|
|
789
1835
|
this.setPosition(bitCore.Screen.ScreenWidth * 0.5, bitCore.Screen.ScreenHeight * 0.5);
|
|
790
1836
|
this.setPivot(0.5, 0.5, true);
|
|
791
1837
|
switch (this.adapterType) {
|
|
@@ -796,21 +1842,11 @@ class UIWindow extends fairyguiCc.GComponent {
|
|
|
796
1842
|
this.setSize(bitCore.Screen.SafeWidth, bitCore.Screen.SafeHeight, true);
|
|
797
1843
|
break;
|
|
798
1844
|
}
|
|
799
|
-
(_a = this._swallowComponent) === null || _a === void 0 ? void 0 : _a.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
800
|
-
(_b = this._swallowComponent) === null || _b === void 0 ? void 0 : _b.setPosition(this.width * 0.5, +this.height * 0.5);
|
|
801
1845
|
this.onAdapted();
|
|
802
1846
|
}
|
|
803
1847
|
/**
|
|
804
|
-
*
|
|
805
|
-
* @
|
|
806
|
-
*/
|
|
807
|
-
_close() {
|
|
808
|
-
this.onClose();
|
|
809
|
-
this.dispose();
|
|
810
|
-
}
|
|
811
|
-
/**
|
|
812
|
-
* 显示窗口 (框架内部使用)
|
|
813
|
-
* @param userdata 用户自定义数据
|
|
1848
|
+
* 显示
|
|
1849
|
+
* @param userdata 用户数据
|
|
814
1850
|
* @internal
|
|
815
1851
|
*/
|
|
816
1852
|
_show(userdata) {
|
|
@@ -818,530 +1854,203 @@ class UIWindow extends fairyguiCc.GComponent {
|
|
|
818
1854
|
this.onShow(userdata);
|
|
819
1855
|
}
|
|
820
1856
|
/**
|
|
821
|
-
*
|
|
1857
|
+
* 隐藏
|
|
822
1858
|
* @internal
|
|
823
1859
|
*/
|
|
824
1860
|
_hide() {
|
|
825
1861
|
this.visible = false;
|
|
826
1862
|
this.onHide();
|
|
827
1863
|
}
|
|
828
|
-
/**
|
|
829
|
-
* 从隐藏状态恢复显示
|
|
830
|
-
* @internal
|
|
831
|
-
*/
|
|
832
|
-
_showFromHide() {
|
|
833
|
-
this.visible = true;
|
|
834
|
-
this.onShowFromHide();
|
|
835
|
-
}
|
|
836
|
-
/**
|
|
837
|
-
* 遮挡窗口 被同组或者不同组的其他窗口覆盖 (框架内部使用)
|
|
838
|
-
* @internal
|
|
839
|
-
*/
|
|
840
|
-
_cover() {
|
|
841
|
-
this._isCover = true;
|
|
842
|
-
this.onCover();
|
|
843
|
-
}
|
|
844
|
-
/**
|
|
845
|
-
* 遮挡恢复窗口 被同组或者不同组的其他窗口覆盖恢复 (框架内部使用)
|
|
846
|
-
* @internal
|
|
847
|
-
*/
|
|
848
|
-
_recover() {
|
|
849
|
-
this._isCover = false;
|
|
850
|
-
this.onRecover();
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* 设置窗口深度
|
|
854
|
-
* @param depth 深度
|
|
855
|
-
* @internal
|
|
856
|
-
*/
|
|
857
|
-
_setDepth(depth) {
|
|
858
|
-
this.parent.setChildIndex(this, depth);
|
|
859
|
-
}
|
|
860
|
-
isShowing() {
|
|
861
|
-
return this.visible;
|
|
862
|
-
}
|
|
863
|
-
isCover() {
|
|
864
|
-
return this._isCover;
|
|
865
|
-
}
|
|
866
|
-
/** @internal */
|
|
867
|
-
screenResize() {
|
|
868
|
-
this._adapted();
|
|
869
|
-
}
|
|
870
|
-
/**
|
|
871
|
-
* 获取窗口顶部资源栏数据 默认返回空数组
|
|
872
|
-
* @returns {WindowHeaderInfo[]}
|
|
873
|
-
*/
|
|
874
|
-
getHeaderInfo() {
|
|
875
|
-
return null;
|
|
876
|
-
}
|
|
877
|
-
getHeader() {
|
|
878
|
-
return this._header;
|
|
879
|
-
}
|
|
880
|
-
/** @internal */
|
|
881
|
-
_setHeader(header) {
|
|
882
|
-
this._header = header;
|
|
883
|
-
}
|
|
884
1864
|
}
|
|
885
1865
|
|
|
886
1866
|
/**
|
|
887
1867
|
* @Author: Gongxh
|
|
888
|
-
* @Date:
|
|
889
|
-
* @Description:
|
|
1868
|
+
* @Date: 2025-01-10
|
|
1869
|
+
* @Description: 窗口顶部资源栏信息
|
|
890
1870
|
*/
|
|
891
|
-
class
|
|
892
|
-
onAdapted() {
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* 窗口关闭时的处理逻辑。
|
|
896
|
-
* 子类可以重写此方法以实现自定义的关闭行为。
|
|
897
|
-
*/
|
|
898
|
-
onClose() {
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* 窗口显示时的回调函数。
|
|
902
|
-
* @param userdata 可选参数,传递给窗口显示时的用户数据。
|
|
903
|
-
*/
|
|
904
|
-
onShow(userdata) {
|
|
905
|
-
}
|
|
906
|
-
/**
|
|
907
|
-
* 隐藏窗口时的处理逻辑。
|
|
908
|
-
* 重写此方法以实现自定义的隐藏行为。
|
|
909
|
-
*/
|
|
910
|
-
onHide() {
|
|
911
|
-
}
|
|
912
|
-
/**
|
|
913
|
-
* 当窗口从隐藏状态变为显示状态时调用。
|
|
914
|
-
* 这个方法可以被子类重写以实现特定的显示逻辑。
|
|
915
|
-
*/
|
|
916
|
-
onShowFromHide() {
|
|
917
|
-
}
|
|
918
|
-
/**
|
|
919
|
-
* 当窗口被覆盖时触发的事件处理函数。
|
|
920
|
-
* 子类可以重写此方法以添加自定义行为。
|
|
921
|
-
*/
|
|
922
|
-
onCover() {
|
|
923
|
-
}
|
|
924
|
-
/**
|
|
925
|
-
* 恢复窗口状态时的处理逻辑。
|
|
926
|
-
* 此方法在窗口从隐藏或最小化状态恢复时被调用。
|
|
927
|
-
*/
|
|
928
|
-
onRecover() {
|
|
929
|
-
}
|
|
1871
|
+
class HeaderInfo {
|
|
930
1872
|
/**
|
|
931
|
-
*
|
|
932
|
-
*
|
|
1873
|
+
* 创建 WindowHeaderInfo
|
|
1874
|
+
* @param {string} name header窗口名
|
|
1875
|
+
* @param {*} [userdata] 自定义数据
|
|
1876
|
+
* @returns {HeaderInfo}
|
|
933
1877
|
*/
|
|
934
|
-
|
|
1878
|
+
static create(ctor, userdata) {
|
|
1879
|
+
// 优先使用装饰器设置的静态属性,避免代码混淆后 constructor.name 变化
|
|
1880
|
+
const name = ctor[MetadataKey.originalName];
|
|
1881
|
+
if (!name) {
|
|
1882
|
+
throw new Error(`header【${ctor.name}】未注册,请使用 _uidecorator.uiheader 注册header`);
|
|
1883
|
+
}
|
|
1884
|
+
const info = new HeaderInfo();
|
|
1885
|
+
info.name = name;
|
|
1886
|
+
info.userdata = userdata;
|
|
1887
|
+
return info;
|
|
935
1888
|
}
|
|
936
1889
|
}
|
|
937
1890
|
|
|
938
1891
|
/**
|
|
939
1892
|
* @Author: Gongxh
|
|
940
|
-
* @Date: 2024-12-
|
|
941
|
-
* @Description:
|
|
1893
|
+
* @Date: 2024-12-14
|
|
1894
|
+
* @Description: 窗口基类和fgui组件对接
|
|
942
1895
|
*/
|
|
943
|
-
class
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
*/
|
|
955
|
-
get size() {
|
|
956
|
-
return this._windowNames.length;
|
|
957
|
-
}
|
|
958
|
-
/**
|
|
959
|
-
* 获取是否忽略查询的状态。
|
|
960
|
-
* @returns {boolean} 如果忽略查询,则返回 true,否则返回 false。
|
|
961
|
-
*/
|
|
962
|
-
get isIgnore() {
|
|
963
|
-
return this._ignoreQuery;
|
|
964
|
-
}
|
|
965
|
-
/**
|
|
966
|
-
* 实例化
|
|
967
|
-
* @param name 组名
|
|
968
|
-
* @param root 窗口组的根节点 一个fgui的组件
|
|
969
|
-
* @param ignoreQuery 是否忽略顶部窗口查询
|
|
970
|
-
* @param swallowTouch 是否吞掉触摸事件
|
|
971
|
-
* @param bgAlpha 半透明遮罩的透明度
|
|
972
|
-
* @internal
|
|
973
|
-
*/
|
|
974
|
-
constructor(name, root, ignoreQuery, swallowTouch, bgAlpha) {
|
|
975
|
-
/** 窗口组的名字 @internal */
|
|
976
|
-
this._name = "";
|
|
977
|
-
/** 忽略顶部窗口查询 @internal */
|
|
978
|
-
this._ignoreQuery = false;
|
|
979
|
-
/** 吞噬触摸事件 @internal */
|
|
980
|
-
this._swallowTouch = false;
|
|
981
|
-
/** 窗口容器中的窗口名列表 @internal */
|
|
982
|
-
this._windowNames = [];
|
|
983
|
-
/** 窗口顶部资源栏 @internal */
|
|
984
|
-
this._headers = new Map();
|
|
985
|
-
/** 半透明遮罩的透明度 @internal */
|
|
986
|
-
this._bgAlpha = 0;
|
|
987
|
-
/** 半透明遮罩的颜色 @internal */
|
|
988
|
-
this._color = new cc.Color(0, 0, 0, 255);
|
|
989
|
-
this._name = name;
|
|
990
|
-
this._root = root;
|
|
991
|
-
this._ignoreQuery = ignoreQuery;
|
|
992
|
-
this._swallowTouch = swallowTouch;
|
|
993
|
-
this._bgAlpha = bgAlpha;
|
|
994
|
-
const alphaGraph = new fairyguiCc.GGraph();
|
|
995
|
-
alphaGraph.touchable = false;
|
|
996
|
-
alphaGraph.name = "bgAlpha";
|
|
997
|
-
alphaGraph.setPosition(root.width * 0.5, root.height * 0.5);
|
|
998
|
-
alphaGraph.setSize(root.width, root.height, true);
|
|
999
|
-
alphaGraph.setPivot(0.5, 0.5, true);
|
|
1000
|
-
root.addChild(alphaGraph);
|
|
1001
|
-
this._alphaGraph = alphaGraph;
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
* 根据窗口名创建窗口 并添加到显示节点
|
|
1005
|
-
* @param windowName 窗口名
|
|
1006
|
-
* @internal
|
|
1007
|
-
*/
|
|
1008
|
-
_createWindow(pkg, name) {
|
|
1009
|
-
let window = fairyguiCc.UIPackage.createObject(pkg, name);
|
|
1010
|
-
window.name = name;
|
|
1011
|
-
PropsHelper.serializeProps(window, pkg);
|
|
1012
|
-
window._init(this._swallowTouch, this._bgAlpha);
|
|
1013
|
-
window._adapted();
|
|
1014
|
-
this._createHeader(window);
|
|
1015
|
-
// 添加到显示节点
|
|
1016
|
-
this._addWindow(window);
|
|
1017
|
-
return window;
|
|
1896
|
+
class WindowBase extends fairyguiCc.GComponent {
|
|
1897
|
+
constructor() {
|
|
1898
|
+
super(...arguments);
|
|
1899
|
+
/** 窗口类型 */
|
|
1900
|
+
this.type = exports.WindowType.Normal;
|
|
1901
|
+
/** 窗口适配类型 */
|
|
1902
|
+
this.adapterType = exports.AdapterType.Full;
|
|
1903
|
+
/** @internal */
|
|
1904
|
+
this._swallowNode = null; // 吞噬触摸的节点
|
|
1905
|
+
/** @internal */
|
|
1906
|
+
this._isTop = true;
|
|
1018
1907
|
}
|
|
1019
1908
|
/**
|
|
1020
|
-
*
|
|
1021
|
-
* @param
|
|
1909
|
+
* 初始化方法 (框架内部使用)
|
|
1910
|
+
* @param swallowTouch 是否吞噬触摸事件
|
|
1911
|
+
* @param bgAlpha 底部遮罩的透明度
|
|
1022
1912
|
* @internal
|
|
1023
1913
|
*/
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
}
|
|
1040
|
-
this._moveWindowToTop(name);
|
|
1041
|
-
// 处理header的显示
|
|
1042
|
-
this._processHeaderStatus();
|
|
1043
|
-
// 显示窗口组
|
|
1044
|
-
this._root.visible = true;
|
|
1914
|
+
_init(swallowTouch) {
|
|
1915
|
+
// 窗口本身可能留有安全区的边, 所以需要一个全屏的节点来吞噬触摸事件
|
|
1916
|
+
let bgNode = new fairyguiCc.GComponent();
|
|
1917
|
+
bgNode.name = "swallow";
|
|
1918
|
+
bgNode.setPivot(0.5, 0.5, true);
|
|
1919
|
+
this.addChild(bgNode);
|
|
1920
|
+
bgNode.parent.setChildIndex(bgNode, 0); // 调整显示层级
|
|
1921
|
+
bgNode.onClick(this.onEmptyAreaClick, this); // 空白区域点击事件
|
|
1922
|
+
bgNode.opaque = swallowTouch;
|
|
1923
|
+
this._swallowNode = bgNode;
|
|
1924
|
+
// 窗口自身也要设置是否吞噬触摸
|
|
1925
|
+
this.opaque = swallowTouch;
|
|
1926
|
+
this._isTop = true;
|
|
1927
|
+
this.bgAlpha = WindowManager.bgAlpha;
|
|
1928
|
+
this.onInit();
|
|
1045
1929
|
}
|
|
1046
1930
|
/**
|
|
1047
|
-
*
|
|
1048
|
-
* @param name 窗口的名称。
|
|
1931
|
+
* 适配窗口
|
|
1049
1932
|
* @internal
|
|
1050
1933
|
*/
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
this._windowNames.splice(index, 1);
|
|
1062
|
-
// 关闭窗口 并从窗口map中移除
|
|
1063
|
-
UIManager._removeWindow(name);
|
|
1064
|
-
// 处理窗口显示和隐藏状态
|
|
1065
|
-
this._processWindowHideStatus(this.size - 1, true);
|
|
1066
|
-
if (this.size == 0) {
|
|
1067
|
-
// 窗口组中不存在窗口时 隐藏窗口组节点
|
|
1068
|
-
this._root.visible = false;
|
|
1069
|
-
}
|
|
1070
|
-
else if (lastIndex == index && index > 0) {
|
|
1071
|
-
// 删除的窗口是最后一个 并且前边还有窗口 调整半透明节点的显示层级
|
|
1072
|
-
let topName = this.getTopWindowName();
|
|
1073
|
-
let window = UIManager.getWindow(topName);
|
|
1074
|
-
// 调整半透明遮罩
|
|
1075
|
-
this._adjustAlphaGraph(window);
|
|
1076
|
-
// 调整窗口的显示层级
|
|
1077
|
-
window._setDepth(this._root.numChildren - 1);
|
|
1934
|
+
_adapted() {
|
|
1935
|
+
this.setPosition(bitCore.Screen.ScreenWidth * 0.5, bitCore.Screen.ScreenHeight * 0.5);
|
|
1936
|
+
this.setPivot(0.5, 0.5, true);
|
|
1937
|
+
switch (this.adapterType) {
|
|
1938
|
+
case exports.AdapterType.Full:
|
|
1939
|
+
this.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
1940
|
+
break;
|
|
1941
|
+
case exports.AdapterType.Bang:
|
|
1942
|
+
this.setSize(bitCore.Screen.SafeWidth, bitCore.Screen.SafeHeight, true);
|
|
1943
|
+
break;
|
|
1078
1944
|
}
|
|
1079
|
-
|
|
1945
|
+
// 屏幕的宽高
|
|
1946
|
+
this._swallowNode.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
1947
|
+
// 位置放在窗口的中心
|
|
1948
|
+
this._swallowNode.setPosition(this.width * 0.5, this.height * 0.5);
|
|
1949
|
+
this.onAdapted();
|
|
1080
1950
|
}
|
|
1081
1951
|
/**
|
|
1082
|
-
*
|
|
1083
|
-
* @param name 窗口的名称。
|
|
1952
|
+
* 窗口关闭
|
|
1084
1953
|
* @internal
|
|
1085
1954
|
*/
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
console.warn(`WindowGroup.moveWindowToTop: window group 【${this._name}】 is empty`);
|
|
1090
|
-
return false;
|
|
1091
|
-
}
|
|
1092
|
-
if (this._windowNames[this.size - 1] == name) ;
|
|
1093
|
-
else {
|
|
1094
|
-
const index = this._windowNames.indexOf(name);
|
|
1095
|
-
if (index == -1) {
|
|
1096
|
-
console.warn(`WindowGroup.moveWindowToTop: window 【${name}】 not found in window group 【${this._name}】`);
|
|
1097
|
-
return false;
|
|
1098
|
-
}
|
|
1099
|
-
if (index < this._windowNames.length - 1) {
|
|
1100
|
-
this._windowNames.splice(index, 1);
|
|
1101
|
-
// 放到数组的末尾
|
|
1102
|
-
this._windowNames.push(name);
|
|
1103
|
-
isMoved = true;
|
|
1104
|
-
}
|
|
1105
|
-
}
|
|
1106
|
-
let window = UIManager.getWindow(name);
|
|
1107
|
-
// 先调整半透明遮罩
|
|
1108
|
-
this._adjustAlphaGraph(window);
|
|
1109
|
-
// 再调整窗口的显示层级
|
|
1110
|
-
window._setDepth(this._root.numChildren - 1);
|
|
1111
|
-
// 处理窗口显示和隐藏状态
|
|
1112
|
-
this._processWindowHideStatus(this.size - 1, isMoved);
|
|
1113
|
-
return true;
|
|
1955
|
+
_close() {
|
|
1956
|
+
this.onClose();
|
|
1957
|
+
this.dispose();
|
|
1114
1958
|
}
|
|
1115
1959
|
/**
|
|
1116
|
-
*
|
|
1117
|
-
* @param
|
|
1118
|
-
* @param isRecursion - 是否递归调用
|
|
1960
|
+
* 显示窗口 (框架内部使用)
|
|
1961
|
+
* @param userdata 用户自定义数据
|
|
1119
1962
|
* @internal
|
|
1120
1963
|
*/
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
}
|
|
1125
|
-
let windowName = this._windowNames[index];
|
|
1126
|
-
let curWindow = UIManager.getWindow(windowName);
|
|
1127
|
-
// 如果当前是当前组中的最后一个窗口并且当前窗口是隐藏状态 则恢复隐藏
|
|
1128
|
-
if (index == this.size - 1 && !curWindow.isShowing()) {
|
|
1129
|
-
curWindow._showFromHide();
|
|
1130
|
-
}
|
|
1131
|
-
if (index == 0) {
|
|
1132
|
-
return;
|
|
1133
|
-
}
|
|
1134
|
-
let windowType = curWindow.type;
|
|
1135
|
-
if (windowType == exports.WindowType.HideAll) {
|
|
1136
|
-
for (let i = index - 1; i >= 0; --i) {
|
|
1137
|
-
let name = this._windowNames[i];
|
|
1138
|
-
const window = UIManager.getWindow(name);
|
|
1139
|
-
window.isShowing() && window._hide();
|
|
1140
|
-
}
|
|
1141
|
-
return;
|
|
1142
|
-
}
|
|
1143
|
-
else if (windowType == exports.WindowType.HideOne) {
|
|
1144
|
-
// 隐藏前一个
|
|
1145
|
-
let prevWindowName = this._windowNames[index - 1];
|
|
1146
|
-
let prevWindow = UIManager.getWindow(prevWindowName);
|
|
1147
|
-
prevWindow.isShowing() && prevWindow._hide();
|
|
1148
|
-
}
|
|
1149
|
-
else {
|
|
1150
|
-
// 如果前一个窗口被隐藏了 需要恢复显示
|
|
1151
|
-
let prevWindowName = this._windowNames[index - 1];
|
|
1152
|
-
let prevWindow = UIManager.getWindow(prevWindowName);
|
|
1153
|
-
!prevWindow.isShowing() && prevWindow._showFromHide();
|
|
1154
|
-
}
|
|
1155
|
-
isRecursion && this._processWindowHideStatus(index - 1, isRecursion);
|
|
1964
|
+
_show(userdata) {
|
|
1965
|
+
this.visible = true;
|
|
1966
|
+
this.onShow(userdata);
|
|
1156
1967
|
}
|
|
1157
1968
|
/**
|
|
1158
|
-
*
|
|
1159
|
-
* 处理上一个窗口或者所有窗口的关闭
|
|
1160
|
-
* @param window 新创建的窗口
|
|
1969
|
+
* 隐藏窗口 (框架内部使用)
|
|
1161
1970
|
* @internal
|
|
1162
1971
|
*/
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
let size = this.size;
|
|
1167
|
-
while (size > 0) {
|
|
1168
|
-
let name = this._windowNames.pop();
|
|
1169
|
-
let window = UIManager.getWindow(name);
|
|
1170
|
-
let header = window.getHeader();
|
|
1171
|
-
header && this._removeHeader(header);
|
|
1172
|
-
UIManager._removeWindow(name);
|
|
1173
|
-
break;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
else if (window.type == exports.WindowType.CloseAll) {
|
|
1177
|
-
let size = this.size;
|
|
1178
|
-
for (let i = size; i > 0;) {
|
|
1179
|
-
let name = this._windowNames[--i];
|
|
1180
|
-
let window = UIManager.getWindow(name);
|
|
1181
|
-
let header = window.getHeader();
|
|
1182
|
-
header && this._removeHeader(header);
|
|
1183
|
-
UIManager._removeWindow(name);
|
|
1184
|
-
}
|
|
1185
|
-
this._windowNames.length = 0;
|
|
1186
|
-
}
|
|
1972
|
+
_hide() {
|
|
1973
|
+
this.visible = false;
|
|
1974
|
+
this.onHide();
|
|
1187
1975
|
}
|
|
1188
1976
|
/**
|
|
1189
|
-
*
|
|
1977
|
+
* 从隐藏状态恢复显示
|
|
1190
1978
|
* @internal
|
|
1191
1979
|
*/
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
let firstWindow = null;
|
|
1196
|
-
let index = this.size - 1;
|
|
1197
|
-
for (let i = this.size - 1; i >= 0; --i) {
|
|
1198
|
-
let name = this._windowNames[i];
|
|
1199
|
-
let window = UIManager.getWindow(name);
|
|
1200
|
-
if (window.isShowing() && window.getHeader()) {
|
|
1201
|
-
firstWindow = window;
|
|
1202
|
-
firstHeader = window.getHeader();
|
|
1203
|
-
index = i;
|
|
1204
|
-
break;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
this._headers.forEach((header, name) => {
|
|
1208
|
-
this._root.setChildIndex(header, 0);
|
|
1209
|
-
if (!firstHeader && header.visible) {
|
|
1210
|
-
header._hide();
|
|
1211
|
-
}
|
|
1212
|
-
else if (firstHeader) {
|
|
1213
|
-
if (firstHeader.name == name && !header.visible) {
|
|
1214
|
-
header._show(firstWindow);
|
|
1215
|
-
}
|
|
1216
|
-
else if (firstHeader.name != name && header.visible) {
|
|
1217
|
-
header._hide();
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
});
|
|
1221
|
-
if (firstHeader) {
|
|
1222
|
-
if (index == this.size - 1) {
|
|
1223
|
-
this._root.setChildIndex(firstHeader, this._root.numChildren - 1);
|
|
1224
|
-
}
|
|
1225
|
-
else {
|
|
1226
|
-
this._root.setChildIndex(firstHeader, this._root.numChildren - this.size + index - 1);
|
|
1227
|
-
}
|
|
1228
|
-
}
|
|
1980
|
+
_showFromHide() {
|
|
1981
|
+
this.visible = true;
|
|
1982
|
+
this.onShowFromHide();
|
|
1229
1983
|
}
|
|
1230
1984
|
/**
|
|
1231
|
-
*
|
|
1232
|
-
* @param window - 需要调整透明度的窗口对象。
|
|
1985
|
+
* 除忽略的窗口组外, 显示到最上层时
|
|
1233
1986
|
* @internal
|
|
1234
1987
|
*/
|
|
1235
|
-
|
|
1236
|
-
this.
|
|
1237
|
-
|
|
1238
|
-
this._color.a = window.bgAlpha * 255;
|
|
1239
|
-
this._alphaGraph.clearGraphics();
|
|
1240
|
-
this._alphaGraph.drawRect(0, this._color, this._color);
|
|
1241
|
-
}
|
|
1242
|
-
hasWindow(name) {
|
|
1243
|
-
return this._windowNames.indexOf(name) >= 0;
|
|
1988
|
+
_toTop() {
|
|
1989
|
+
this._isTop = true;
|
|
1990
|
+
this.onToTop();
|
|
1244
1991
|
}
|
|
1245
1992
|
/**
|
|
1246
|
-
*
|
|
1247
|
-
* @returns {string} 顶部窗口的名称。
|
|
1248
|
-
*/
|
|
1249
|
-
getTopWindowName() {
|
|
1250
|
-
if (this.size > 0) {
|
|
1251
|
-
return this._windowNames[this.size - 1];
|
|
1252
|
-
}
|
|
1253
|
-
console.warn(`WindowGroup.getTopWindowName: window group 【${this._name}】 is empty`);
|
|
1254
|
-
return "";
|
|
1255
|
-
}
|
|
1256
|
-
/** 根据窗口 创建顶部资源栏 (内部方法) @internal */
|
|
1257
|
-
_createHeader(window) {
|
|
1258
|
-
// 只有创建界面的时候, 才会尝试创建顶部资源栏
|
|
1259
|
-
let headerInfo = window.getHeaderInfo();
|
|
1260
|
-
if (!headerInfo) {
|
|
1261
|
-
return;
|
|
1262
|
-
}
|
|
1263
|
-
let name = headerInfo.name;
|
|
1264
|
-
let header = this._getHeader(name);
|
|
1265
|
-
if (header) {
|
|
1266
|
-
window._setHeader(header);
|
|
1267
|
-
header._addRef();
|
|
1268
|
-
}
|
|
1269
|
-
else {
|
|
1270
|
-
// 创建header节点
|
|
1271
|
-
let { pkg } = UIManager._getResPool().getHeader(name);
|
|
1272
|
-
let newHeader = fairyguiCc.UIPackage.createObject(pkg, name);
|
|
1273
|
-
newHeader.name = name;
|
|
1274
|
-
newHeader.opaque = false;
|
|
1275
|
-
window._setHeader(newHeader);
|
|
1276
|
-
newHeader.visible = false;
|
|
1277
|
-
PropsHelper.serializeProps(newHeader, pkg);
|
|
1278
|
-
newHeader._init();
|
|
1279
|
-
newHeader._adapted();
|
|
1280
|
-
this._root.addChild(newHeader);
|
|
1281
|
-
// 添加到显示节点
|
|
1282
|
-
newHeader._addRef();
|
|
1283
|
-
this._headers.set(newHeader.name, newHeader);
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
/**
|
|
1287
|
-
* 顶部资源栏窗口 从管理器中移除 (内部方法)
|
|
1288
|
-
* @param header 资源栏
|
|
1993
|
+
* 除忽略的窗口组外, 被上层窗口覆盖时
|
|
1289
1994
|
* @internal
|
|
1290
1995
|
*/
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
if (refCount <= 0) {
|
|
1295
|
-
this._headers.delete(header.name);
|
|
1296
|
-
header._close();
|
|
1297
|
-
}
|
|
1298
|
-
}
|
|
1996
|
+
_toBottom() {
|
|
1997
|
+
this._isTop = false;
|
|
1998
|
+
this.onToBottom();
|
|
1299
1999
|
}
|
|
1300
2000
|
/**
|
|
1301
|
-
*
|
|
1302
|
-
* @param
|
|
2001
|
+
* 设置窗口深度
|
|
2002
|
+
* @param depth 深度
|
|
1303
2003
|
* @internal
|
|
1304
2004
|
*/
|
|
1305
|
-
|
|
1306
|
-
|
|
2005
|
+
setDepth(depth) {
|
|
2006
|
+
this.parent.setChildIndex(this, depth);
|
|
1307
2007
|
}
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
this.
|
|
1314
|
-
|
|
1315
|
-
|
|
2008
|
+
isShowing() {
|
|
2009
|
+
return this.visible;
|
|
2010
|
+
}
|
|
2011
|
+
/** 是否在最上层显示 (除忽略的窗口组外, 显示到最上层时) */
|
|
2012
|
+
isTop() {
|
|
2013
|
+
return this._isTop;
|
|
2014
|
+
}
|
|
2015
|
+
/** @internal */
|
|
2016
|
+
screenResize() {
|
|
2017
|
+
this._adapted();
|
|
1316
2018
|
}
|
|
1317
2019
|
/**
|
|
1318
|
-
*
|
|
2020
|
+
* 刷新顶部资源栏
|
|
2021
|
+
* 调用这个方法会重新创建 或者 刷新header
|
|
2022
|
+
* 用来在同一个界面显示不同的header
|
|
1319
2023
|
*/
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
2024
|
+
refreshHeader() {
|
|
2025
|
+
HeaderManager.refreshWindowHeader(this.name, this.getHeaderInfo());
|
|
2026
|
+
}
|
|
2027
|
+
/**
|
|
2028
|
+
* 用于在界面中关闭自己
|
|
2029
|
+
*/
|
|
2030
|
+
removeSelf() {
|
|
2031
|
+
WindowManager.closeWindowByName(this.name);
|
|
1325
2032
|
}
|
|
1326
2033
|
}
|
|
1327
2034
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
2035
|
+
class Window extends WindowBase {
|
|
2036
|
+
onAdapted() {
|
|
2037
|
+
}
|
|
2038
|
+
onHide() { }
|
|
2039
|
+
onShowFromHide() { }
|
|
2040
|
+
onToTop() { }
|
|
2041
|
+
onToBottom() { }
|
|
1334
2042
|
/**
|
|
1335
|
-
*
|
|
1336
|
-
*
|
|
1337
|
-
* @param {*} [userdata] 自定义数据
|
|
1338
|
-
* @returns {WindowHeaderInfo}
|
|
2043
|
+
* 空白区域点击事件处理函数。
|
|
2044
|
+
* 当用户点击窗口的空白区域时触发此方法。
|
|
1339
2045
|
*/
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
2046
|
+
onEmptyAreaClick() {
|
|
2047
|
+
}
|
|
2048
|
+
/**
|
|
2049
|
+
* 获取窗口顶部资源栏数据 默认返回空数组
|
|
2050
|
+
* @returns {HeaderInfo}
|
|
2051
|
+
*/
|
|
2052
|
+
getHeaderInfo() {
|
|
2053
|
+
return null;
|
|
1345
2054
|
}
|
|
1346
2055
|
}
|
|
1347
2056
|
|
|
@@ -1374,294 +2083,6 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
1374
2083
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
1375
2084
|
};
|
|
1376
2085
|
|
|
1377
|
-
/**
|
|
1378
|
-
* @Author: Gongxh
|
|
1379
|
-
* @Date: 2024-12-13
|
|
1380
|
-
* @Description:
|
|
1381
|
-
*/
|
|
1382
|
-
/** @internal */
|
|
1383
|
-
class WindowResPool {
|
|
1384
|
-
constructor() {
|
|
1385
|
-
/** 窗口信息池 @internal */
|
|
1386
|
-
this._windowInfos = new Map();
|
|
1387
|
-
/** 窗口header信息池 @internal */
|
|
1388
|
-
this._headerInfos = new Map();
|
|
1389
|
-
/** UI包所在的bundle名 */
|
|
1390
|
-
this._pkgBundles = new Map();
|
|
1391
|
-
/** 是否设置过配置内容 @internal */
|
|
1392
|
-
this._isInit = false;
|
|
1393
|
-
/** 窗口名对应的包名列表 @internal */
|
|
1394
|
-
this._windowPkgs = new Map();
|
|
1395
|
-
/** 包的引用计数 @internal */
|
|
1396
|
-
this._pkgRefs = {};
|
|
1397
|
-
/** UI包路径 @internal */
|
|
1398
|
-
// private _uipath: string = "";
|
|
1399
|
-
/** UI包在bundle中的路径 @internal */
|
|
1400
|
-
this._uiPaths = {};
|
|
1401
|
-
/** 手动管理的包 @internal */
|
|
1402
|
-
this._manualPackages = new Set();
|
|
1403
|
-
/** 立即释放的包 @internal */
|
|
1404
|
-
this._imReleasePackages = new Set();
|
|
1405
|
-
/** 注册的回调函数 @internal */
|
|
1406
|
-
this._showWaitWindow = null;
|
|
1407
|
-
/** 隐藏等待窗口的回调函数 @internal */
|
|
1408
|
-
this._hideWaitWindow = null;
|
|
1409
|
-
/** 加载失败回调函数 @internal */
|
|
1410
|
-
this._fail = null;
|
|
1411
|
-
/** 等待窗口的引用计数 @internal */
|
|
1412
|
-
this._waitRef = 0;
|
|
1413
|
-
}
|
|
1414
|
-
/**
|
|
1415
|
-
* 注册窗口信息
|
|
1416
|
-
* @param info
|
|
1417
|
-
*/
|
|
1418
|
-
add(ctor, group, pkg, name, bundle) {
|
|
1419
|
-
if (this.has(name)) {
|
|
1420
|
-
return;
|
|
1421
|
-
}
|
|
1422
|
-
this._windowInfos.set(name, {
|
|
1423
|
-
ctor: ctor,
|
|
1424
|
-
group: group,
|
|
1425
|
-
pkg: pkg,
|
|
1426
|
-
name: name,
|
|
1427
|
-
bundle: bundle
|
|
1428
|
-
});
|
|
1429
|
-
this._pkgBundles.set(pkg, bundle || "resources");
|
|
1430
|
-
this.addWindowPkg(name, pkg);
|
|
1431
|
-
// 窗口组件扩展
|
|
1432
|
-
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
1433
|
-
}
|
|
1434
|
-
has(name) {
|
|
1435
|
-
return this._windowInfos.has(name);
|
|
1436
|
-
}
|
|
1437
|
-
get(name) {
|
|
1438
|
-
if (!this.has(name)) {
|
|
1439
|
-
throw new Error(`窗口【${name}】未注册,请使用 _uidecorator.uiclass 注册窗口`);
|
|
1440
|
-
}
|
|
1441
|
-
return this._windowInfos.get(name);
|
|
1442
|
-
}
|
|
1443
|
-
/**
|
|
1444
|
-
* 注册窗口header信息
|
|
1445
|
-
* @param info
|
|
1446
|
-
*/
|
|
1447
|
-
addHeader(ctor, pkg, name, bundle) {
|
|
1448
|
-
if (this.hasHeader(name)) {
|
|
1449
|
-
return;
|
|
1450
|
-
}
|
|
1451
|
-
this._headerInfos.set(name, {
|
|
1452
|
-
ctor: ctor,
|
|
1453
|
-
pkg: pkg,
|
|
1454
|
-
bundle: bundle
|
|
1455
|
-
});
|
|
1456
|
-
this._pkgBundles.set(pkg, bundle || "resources");
|
|
1457
|
-
// 窗口header扩展
|
|
1458
|
-
fairyguiCc.UIObjectFactory.setExtension(`ui://${pkg}/${name}`, ctor);
|
|
1459
|
-
}
|
|
1460
|
-
hasHeader(name) {
|
|
1461
|
-
return this._headerInfos.has(name);
|
|
1462
|
-
}
|
|
1463
|
-
getHeader(name) {
|
|
1464
|
-
if (!this.hasHeader(name)) {
|
|
1465
|
-
throw new Error(`窗口header【${name}】未注册,请使用 _uidecorator.uiheader 注册窗口header`);
|
|
1466
|
-
}
|
|
1467
|
-
return this._headerInfos.get(name);
|
|
1468
|
-
}
|
|
1469
|
-
/** 资源配置相关接口 */
|
|
1470
|
-
initPackageConfig(res) {
|
|
1471
|
-
var _a, _b;
|
|
1472
|
-
if (!res || !res.config) {
|
|
1473
|
-
return;
|
|
1474
|
-
}
|
|
1475
|
-
if (this._isInit) {
|
|
1476
|
-
throw new Error("资源配置已初始化,请勿重复设置");
|
|
1477
|
-
}
|
|
1478
|
-
this._isInit = true;
|
|
1479
|
-
this._showWaitWindow = res === null || res === void 0 ? void 0 : res.showWaitWindow;
|
|
1480
|
-
this._hideWaitWindow = res === null || res === void 0 ? void 0 : res.hideWaitWindow;
|
|
1481
|
-
this._fail = res === null || res === void 0 ? void 0 : res.fail;
|
|
1482
|
-
this._uiPaths = ((_a = res.config) === null || _a === void 0 ? void 0 : _a.bundlePaths) || {};
|
|
1483
|
-
this._uiPaths["resources"] = ((_b = res.config) === null || _b === void 0 ? void 0 : _b.uiPath) || "";
|
|
1484
|
-
for (const bundle in this._uiPaths) {
|
|
1485
|
-
if (this._uiPaths[bundle] != "" && !this._uiPaths[bundle].endsWith("/")) {
|
|
1486
|
-
this._uiPaths[bundle] += "/";
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
this._manualPackages = new Set(res.config.manualPackages || []);
|
|
1490
|
-
this._imReleasePackages = new Set(res.config.imReleasePackages || []);
|
|
1491
|
-
let windowPkgs = res.config.linkPackages || {};
|
|
1492
|
-
for (const windowName in windowPkgs) {
|
|
1493
|
-
let pkgs = windowPkgs[windowName];
|
|
1494
|
-
for (const pkg of pkgs || []) {
|
|
1495
|
-
this.addWindowPkg(windowName, pkg);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1498
|
-
// 遍历一遍,剔除手动管理的包
|
|
1499
|
-
this._windowPkgs.forEach((pkgs, windowName) => {
|
|
1500
|
-
for (let i = pkgs.length - 1; i >= 0; i--) {
|
|
1501
|
-
if (this._manualPackages.has(pkgs[i])) {
|
|
1502
|
-
pkgs.splice(i, 1);
|
|
1503
|
-
}
|
|
1504
|
-
}
|
|
1505
|
-
if (pkgs.length <= 0) {
|
|
1506
|
-
this._windowPkgs.delete(windowName);
|
|
1507
|
-
}
|
|
1508
|
-
});
|
|
1509
|
-
}
|
|
1510
|
-
/** 添加窗口对应的包名 */
|
|
1511
|
-
addWindowPkg(windowName, pkgName) {
|
|
1512
|
-
if (!this._windowPkgs.has(windowName)) {
|
|
1513
|
-
this._windowPkgs.set(windowName, [pkgName]);
|
|
1514
|
-
}
|
|
1515
|
-
else {
|
|
1516
|
-
this._windowPkgs.get(windowName).push(pkgName);
|
|
1517
|
-
}
|
|
1518
|
-
}
|
|
1519
|
-
/**
|
|
1520
|
-
* 加载窗口需要的包资源
|
|
1521
|
-
* @param windowName 窗口名
|
|
1522
|
-
*/
|
|
1523
|
-
loadWindowRes(windowName, listenter) {
|
|
1524
|
-
var _a;
|
|
1525
|
-
// 资源配置未初始化 直接返回成功
|
|
1526
|
-
if (!this._isInit) {
|
|
1527
|
-
console.warn(`UI包信息未配置 将手动管理所有UI包资源的加载,如果需要配置,请使用 【UIManager.initPackageConfig】接口`);
|
|
1528
|
-
listenter.complete();
|
|
1529
|
-
return;
|
|
1530
|
-
}
|
|
1531
|
-
// 不需要包资源 直接返回成功
|
|
1532
|
-
if (!this.hasWindowPkg(windowName)) {
|
|
1533
|
-
listenter.complete();
|
|
1534
|
-
return;
|
|
1535
|
-
}
|
|
1536
|
-
if (this._waitRef++ <= 0) {
|
|
1537
|
-
// 调用注入的回调函数 用来显示等待窗
|
|
1538
|
-
(_a = this._showWaitWindow) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1539
|
-
}
|
|
1540
|
-
this.loadPackages({
|
|
1541
|
-
pkgs: this.getWindowPkgs(windowName),
|
|
1542
|
-
complete: () => {
|
|
1543
|
-
var _a;
|
|
1544
|
-
if (--this._waitRef <= 0) {
|
|
1545
|
-
// 调用注入的回调函数 关闭等待窗
|
|
1546
|
-
listenter.complete();
|
|
1547
|
-
(_a = this._hideWaitWindow) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
1548
|
-
}
|
|
1549
|
-
},
|
|
1550
|
-
fail: (pkgs) => {
|
|
1551
|
-
var _a, _b;
|
|
1552
|
-
console.warn(`界面${windowName}打开失败`);
|
|
1553
|
-
listenter.fail(pkgs);
|
|
1554
|
-
(_a = this._fail) === null || _a === void 0 ? void 0 : _a.call(this, windowName, "UI包加载失败", pkgs);
|
|
1555
|
-
if (--this._waitRef <= 0) {
|
|
1556
|
-
// 调用注入的回调函数 关闭等待窗
|
|
1557
|
-
(_b = this._hideWaitWindow) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
1558
|
-
}
|
|
1559
|
-
}
|
|
1560
|
-
});
|
|
1561
|
-
}
|
|
1562
|
-
addResRef(windowName) {
|
|
1563
|
-
if (!this._isInit) {
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
// 不需要包资源 直接返回成功
|
|
1567
|
-
if (!this.hasWindowPkg(windowName)) {
|
|
1568
|
-
return;
|
|
1569
|
-
}
|
|
1570
|
-
let pkgs = this.getWindowPkgs(windowName);
|
|
1571
|
-
for (const pkg of pkgs) {
|
|
1572
|
-
this.addRef(pkg);
|
|
1573
|
-
}
|
|
1574
|
-
}
|
|
1575
|
-
/**
|
|
1576
|
-
* 释放窗口资源
|
|
1577
|
-
* @param windowName 窗口名
|
|
1578
|
-
*/
|
|
1579
|
-
releaseWindowRes(windowName) {
|
|
1580
|
-
if (!this._isInit || !this.hasWindowPkg(windowName)) {
|
|
1581
|
-
return;
|
|
1582
|
-
}
|
|
1583
|
-
let pkgs = this.getWindowPkgs(windowName);
|
|
1584
|
-
for (const pkg of pkgs) {
|
|
1585
|
-
this.decRef(pkg);
|
|
1586
|
-
}
|
|
1587
|
-
}
|
|
1588
|
-
/**
|
|
1589
|
-
* 加载fgui包
|
|
1590
|
-
* @param pkgs 包名集合
|
|
1591
|
-
* @param progress 进度回调
|
|
1592
|
-
* @param complete 加载完成回调
|
|
1593
|
-
*/
|
|
1594
|
-
loadPackages(res) {
|
|
1595
|
-
// 过滤已经加载的包
|
|
1596
|
-
let needLoadPkgs = res.pkgs.filter(pkg => this.getRef(pkg) <= 0);
|
|
1597
|
-
let successPkgs = [];
|
|
1598
|
-
let failPkgs = [];
|
|
1599
|
-
let total = needLoadPkgs.length;
|
|
1600
|
-
if (total <= 0) {
|
|
1601
|
-
res.complete();
|
|
1602
|
-
return;
|
|
1603
|
-
}
|
|
1604
|
-
for (const pkg of needLoadPkgs) {
|
|
1605
|
-
let bundleName = this.getPkgBundle(pkg);
|
|
1606
|
-
let bundle = bundleName === "resources" ? cc.resources : cc.assetManager.getBundle(bundleName);
|
|
1607
|
-
if (!bundle) {
|
|
1608
|
-
throw new Error(`UI包【${pkg}】所在的bundle【${bundleName}】未加载`);
|
|
1609
|
-
}
|
|
1610
|
-
fairyguiCc.UIPackage.loadPackage(bundle, this.getPkgPath(pkg), (err) => {
|
|
1611
|
-
total--;
|
|
1612
|
-
err ? failPkgs.push(pkg) : successPkgs.push(pkg);
|
|
1613
|
-
if (total > 0) {
|
|
1614
|
-
return;
|
|
1615
|
-
}
|
|
1616
|
-
if (failPkgs.length > 0) {
|
|
1617
|
-
res.fail(failPkgs);
|
|
1618
|
-
}
|
|
1619
|
-
else {
|
|
1620
|
-
res.complete();
|
|
1621
|
-
}
|
|
1622
|
-
});
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
/** 获取UI包所在的bundle名 */
|
|
1626
|
-
getPkgBundle(pkg) {
|
|
1627
|
-
return this._pkgBundles.get(pkg) || "resources";
|
|
1628
|
-
}
|
|
1629
|
-
/** 获取UI包在bundle中的路径 */
|
|
1630
|
-
getPkgPath(pkg) {
|
|
1631
|
-
let bundle = this._pkgBundles.get(pkg);
|
|
1632
|
-
return this._uiPaths[bundle] + pkg;
|
|
1633
|
-
}
|
|
1634
|
-
/** 获取窗口对应的包名列表 */
|
|
1635
|
-
getWindowPkgs(windowName) {
|
|
1636
|
-
if (this._windowPkgs.has(windowName)) {
|
|
1637
|
-
return this._windowPkgs.get(windowName);
|
|
1638
|
-
}
|
|
1639
|
-
return [];
|
|
1640
|
-
}
|
|
1641
|
-
hasWindowPkg(windowName) {
|
|
1642
|
-
return this._windowPkgs.has(windowName);
|
|
1643
|
-
}
|
|
1644
|
-
/** 获取包的引用计数 */
|
|
1645
|
-
getRef(pkg) {
|
|
1646
|
-
return this._pkgRefs[pkg] ? this._pkgRefs[pkg] : 0;
|
|
1647
|
-
}
|
|
1648
|
-
/** 增加包的引用计数 */
|
|
1649
|
-
addRef(pkg) {
|
|
1650
|
-
this._pkgRefs[pkg] = this.getRef(pkg) + 1;
|
|
1651
|
-
}
|
|
1652
|
-
/** 减少包的引用计数 */
|
|
1653
|
-
decRef(pkg) {
|
|
1654
|
-
this._pkgRefs[pkg] = this.getRef(pkg) - 1;
|
|
1655
|
-
if (this.getRef(pkg) <= 0) {
|
|
1656
|
-
delete this._pkgRefs[pkg];
|
|
1657
|
-
// 如果需要立即释放 释放包资源
|
|
1658
|
-
if (this._imReleasePackages.has(pkg)) {
|
|
1659
|
-
fairyguiCc.UIPackage.removePackage(pkg);
|
|
1660
|
-
}
|
|
1661
|
-
}
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
2086
|
/**
|
|
1666
2087
|
* @Author: Gongxh
|
|
1667
2088
|
* @Date: 2024-12-08
|
|
@@ -1673,7 +2094,6 @@ let CocosWindowContainer = class CocosWindowContainer extends cc.Component {
|
|
|
1673
2094
|
super(...arguments);
|
|
1674
2095
|
this.ignoreQuery = false;
|
|
1675
2096
|
this.swallowTouch = false;
|
|
1676
|
-
this.bgAlpha = 0.75;
|
|
1677
2097
|
}
|
|
1678
2098
|
/**
|
|
1679
2099
|
* 初始化窗口容器
|
|
@@ -1689,7 +2109,7 @@ let CocosWindowContainer = class CocosWindowContainer extends cc.Component {
|
|
|
1689
2109
|
root.opaque = this.swallowTouch;
|
|
1690
2110
|
root.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
1691
2111
|
fairyguiCc.GRoot.inst.addChild(root);
|
|
1692
|
-
|
|
2112
|
+
WindowManager.addWindowGroup(new WindowGroup(name, root, this.ignoreQuery, this.swallowTouch));
|
|
1693
2113
|
}
|
|
1694
2114
|
};
|
|
1695
2115
|
__decorate([
|
|
@@ -1698,52 +2118,68 @@ __decorate([
|
|
|
1698
2118
|
__decorate([
|
|
1699
2119
|
property$1({ displayName: "吞噬触摸事件", tooltip: "窗口组是否会吞噬触摸事件,防止层级下的窗口接收触摸事件" })
|
|
1700
2120
|
], CocosWindowContainer.prototype, "swallowTouch", void 0);
|
|
1701
|
-
__decorate([
|
|
1702
|
-
property$1({ displayName: "底部遮罩透明度", tooltip: "底部半透明遮罩的默认透明度", min: 0, max: 1, step: 0.01 })
|
|
1703
|
-
], CocosWindowContainer.prototype, "bgAlpha", void 0);
|
|
1704
2121
|
CocosWindowContainer = __decorate([
|
|
1705
2122
|
ccclass$1("CocosWindowContainer"),
|
|
1706
|
-
menu$1("
|
|
2123
|
+
menu$1("bit/UIContainer")
|
|
1707
2124
|
], CocosWindowContainer);
|
|
1708
2125
|
|
|
1709
2126
|
const { ccclass, menu, property } = cc._decorator;
|
|
1710
|
-
exports.UIModule = class UIModule extends
|
|
2127
|
+
exports.UIModule = class UIModule extends bitCore.Module {
|
|
1711
2128
|
constructor() {
|
|
1712
2129
|
super(...arguments);
|
|
2130
|
+
this.ui_config = null;
|
|
2131
|
+
this.bgAlpha = 0.75;
|
|
2132
|
+
this.autoReleaseUIRes = true;
|
|
1713
2133
|
/** 模块名称 */
|
|
1714
2134
|
this.moduleName = "UI模块";
|
|
1715
2135
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
2136
|
+
onInit() {
|
|
2137
|
+
this.ui_config && PropsHelper.setConfig(this.ui_config.json);
|
|
2138
|
+
ResLoader.setAutoRelease(this.autoReleaseUIRes);
|
|
2139
|
+
// 设置底部遮罩的默认透明度
|
|
2140
|
+
WindowManager.bgAlpha = this.bgAlpha;
|
|
1718
2141
|
/** 初始化窗口管理系统 */
|
|
1719
|
-
UIManager._init(new WindowResPool());
|
|
1720
2142
|
fairyguiCc.GRoot.create();
|
|
1721
2143
|
bitCore.debug("初始化 WindowContainers");
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
2144
|
+
const alphaGraph = new fairyguiCc.GGraph();
|
|
2145
|
+
alphaGraph.touchable = false;
|
|
2146
|
+
alphaGraph.name = "bgAlpha";
|
|
2147
|
+
alphaGraph.setPosition(bitCore.Screen.ScreenWidth * 0.5, bitCore.Screen.ScreenHeight * 0.5);
|
|
2148
|
+
alphaGraph.setSize(bitCore.Screen.ScreenWidth, bitCore.Screen.ScreenHeight, true);
|
|
2149
|
+
alphaGraph.setPivot(0.5, 0.5, true);
|
|
2150
|
+
alphaGraph.visible = false;
|
|
2151
|
+
fairyguiCc.GRoot.inst.addChild(alphaGraph);
|
|
2152
|
+
WindowManager.setAlphaGraph(alphaGraph);
|
|
2153
|
+
for (const container of this.getComponentsInChildren(CocosWindowContainer)) {
|
|
2154
|
+
container.init();
|
|
1725
2155
|
}
|
|
1726
|
-
// fgui.UIObjectFactory.setLoaderExtension(GLoader);
|
|
1727
|
-
// this._uiInitializer = new UIInitializer(this.node, this.getPackageLoader());
|
|
1728
|
-
// this._uiInitializer.init(this.reAdaptWhenScreenResize, this.fullIfWideScreen);
|
|
1729
2156
|
this.node.destroyAllChildren();
|
|
1730
|
-
|
|
1731
|
-
UIManager.registerUI();
|
|
1732
|
-
exports._uidecorator.setRegisterFinish();
|
|
1733
|
-
this.onInit();
|
|
2157
|
+
bitCore.Adapter.instance.addResizeListener(this.onScreenResize.bind(this));
|
|
1734
2158
|
}
|
|
1735
|
-
/**
|
|
1736
|
-
|
|
1737
|
-
|
|
2159
|
+
/**
|
|
2160
|
+
* 屏幕大小改变时被调用
|
|
2161
|
+
* @internal
|
|
2162
|
+
*/
|
|
2163
|
+
onScreenResize(...args) {
|
|
2164
|
+
WindowManager.onScreenResize();
|
|
1738
2165
|
}
|
|
1739
2166
|
};
|
|
2167
|
+
__decorate([
|
|
2168
|
+
property({ type: cc.JsonAsset, displayName: "配置文件", tooltip: "编辑器:https://store.cocos.com/app/detail/7213 导出的配置文件" })
|
|
2169
|
+
], exports.UIModule.prototype, "ui_config", void 0);
|
|
2170
|
+
__decorate([
|
|
2171
|
+
property({ displayName: "底部遮罩透明度", tooltip: "半透明遮罩的默认透明度", min: 0, max: 1, step: 0.01 })
|
|
2172
|
+
], exports.UIModule.prototype, "bgAlpha", void 0);
|
|
2173
|
+
__decorate([
|
|
2174
|
+
property({ displayName: "自动释放UI资源", tooltip: "界面关闭时自动释放加载的资源" })
|
|
2175
|
+
], exports.UIModule.prototype, "autoReleaseUIRes", void 0);
|
|
1740
2176
|
exports.UIModule = __decorate([
|
|
1741
2177
|
ccclass("UIModule"),
|
|
1742
|
-
menu("
|
|
2178
|
+
menu("bit/UIModule")
|
|
1743
2179
|
], exports.UIModule);
|
|
1744
2180
|
|
|
1745
|
-
exports.
|
|
1746
|
-
exports.
|
|
2181
|
+
exports.Header = Header;
|
|
2182
|
+
exports.HeaderInfo = HeaderInfo;
|
|
1747
2183
|
exports.Window = Window;
|
|
1748
2184
|
exports.WindowGroup = WindowGroup;
|
|
1749
|
-
exports.
|
|
2185
|
+
exports.WindowManager = WindowManager;
|