@ives_xxz/framework 1.4.8 → 1.4.9

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/FW.d.ts CHANGED
@@ -660,6 +660,11 @@ declare namespace FW {
660
660
  * @param name
661
661
  */
662
662
  closeFromLayerName(name: string | string[]);
663
+ /**
664
+ * 移除所有子Layer
665
+ * @param layer
666
+ */
667
+ removeAllChildren(layer: Layer);
663
668
 
664
669
  getLayerMap(): Map<new () => LayerController, LayerData>;
665
670
  };
@@ -968,6 +973,8 @@ declare namespace FW {
968
973
 
969
974
  type Layer = {
970
975
  readonly entry: FW.Entry;
976
+ node: cc.Node;
977
+ ctr: LayerController;
971
978
  onLoad(): void;
972
979
  start(): void;
973
980
  onEnable(): void;
@@ -1219,33 +1226,6 @@ declare namespace FW {
1219
1226
  * @returns
1220
1227
  */
1221
1228
  createSkeleton(skeleton: sp.Skeleton): FW.Skeleton;
1222
- /**
1223
- * 获取一个skeleton动画
1224
- * @param animationName
1225
- * @returns
1226
- */
1227
- getSkeleton(animationName: string): FW.Skeleton;
1228
-
1229
- /**
1230
- * 暂停一个skeleton动画
1231
- * @param animationName
1232
- * @returns
1233
- */
1234
- pauseSkeleton(animationName: string): void;
1235
-
1236
- /**
1237
- * 恢复一个skeleton动画
1238
- * @param animationName
1239
- * @returns
1240
- */
1241
- resumeSkeleton(animationName: string): void;
1242
-
1243
- /**
1244
- * 移除一个skeleton动画
1245
- * @param animationName
1246
- * @returns
1247
- */
1248
- removeSkeleton(animationName: string): void;
1249
1229
 
1250
1230
  /**
1251
1231
  * 暂停所有动画
@@ -1255,19 +1235,6 @@ declare namespace FW {
1255
1235
  * 恢复所有动画
1256
1236
  * */
1257
1237
  resumeAll(): void;
1258
- /**
1259
- * 创建动画机
1260
- * @param animationMachineName
1261
- * @returns
1262
- */
1263
- createAnimationMachine(animationMachineName: string): void;
1264
-
1265
- /**
1266
- * 移除动画机
1267
- * @param animationMachineName
1268
- * @returns
1269
- */
1270
- removeAnimationMachine(animationMachineName: string): void;
1271
1238
  };
1272
1239
 
1273
1240
  type Tween = {
package/Framework.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import 'reflect-metadata';
2
2
  import { Container, interfaces } from 'inversify';
3
3
  import { FWSystemDefine } from './define/FWSystemDefine';
4
- import FWLog from './log/FWLog';
5
4
 
6
5
  class Framework {
7
6
  private container: Container;
@@ -140,15 +139,12 @@ class Framework {
140
139
  */
141
140
  register(data: FW.RegisterFramework) {
142
141
  const classes = [data.logic, data.data, data.config, data.sender, data.handle];
143
- FWLog.debug('framework注册->', classes);
144
142
  classes.forEach((cls, index) => {
145
143
  if (cls && !this.container.isBound(cls)) {
146
- FWLog.debug('framework容器绑定成功->', cls);
147
144
  this.container.bind(cls).toSelf().inSingletonScope();
148
145
  this.container.bind(this.getKey(data.bundleName, index)).toService(cls);
149
146
  }
150
147
  });
151
- FWLog.debug('framework注册完成->', this.container);
152
148
  }
153
149
  /**
154
150
  * 注销数据
@@ -157,21 +153,17 @@ class Framework {
157
153
  */
158
154
  unRegister(data: FW.RegisterFramework) {
159
155
  const classes = [data.logic, data.data, data.config, data.sender, data.handle];
160
- FWLog.debug('framework注销->', classes);
161
156
  classes.forEach((cls, index) => {
162
157
  const key = this.getKey(data.bundleName, index);
163
158
  if (cls && this.container.isBound(cls)) {
164
159
  this.container.get(key)['onDestroy']?.();
165
160
  this.container.unbind(cls);
166
- FWLog.debug('framework容器解开绑定->', cls);
167
161
  }
168
162
  if (this.container.isBound(key)) {
169
163
  this.container.get(key)['onDestroy']?.();
170
164
  this.container.unbind(this.getKey(data.bundleName, index));
171
- FWLog.debug('framework容器解开绑定->', this.getKey(data.bundleName, index));
172
165
  }
173
166
  });
174
- FWLog.debug('framework注销完成->', this.container);
175
167
  }
176
168
 
177
169
  private getKey(bundleName: string, tag: FWSystemDefine.FWBindTag) {
@@ -28,7 +28,6 @@ export class FWSkeleton extends FWAnimation implements FW.Skeleton {
28
28
  return new Promise((resolve) => {
29
29
  this.animation.setCompleteListener(() => {
30
30
  this.animation.setCompleteListener(null);
31
- FW.Entry.animationMgr.removeSkeleton(this.animationName);
32
31
  args?.cb?.();
33
32
  resolve();
34
33
  });
@@ -137,4 +137,11 @@ export namespace FWSystemDefine {
137
137
  REJECTED = 'rejected',
138
138
  CANCELLED = 'cancelled',
139
139
  }
140
+
141
+ export enum FWLayerState {
142
+ CLOSED = 'closed',
143
+ OPENING = 'opening',
144
+ OPENED = 'opened',
145
+ CLOSING = 'closing',
146
+ }
140
147
  }
package/layer/FWLayer.ts CHANGED
@@ -3,6 +3,7 @@ const { ccclass, property } = cc._decorator;
3
3
  @ccclass
4
4
  export default class FWLayer extends cc.Component implements FW.Layer {
5
5
  public readonly entry: FW.Entry = FW.Entry;
6
+ public ctr: FW.LayerController;
6
7
  public onLoad(): void {}
7
8
  public start(): void {}
8
9
  public onEnable(): void {}
@@ -44,47 +44,6 @@ export default class FWAnimationManager extends FWManager {
44
44
  return s;
45
45
  }
46
46
 
47
- /**
48
- * 获取一个skeleton动画
49
- * @param animationName
50
- * @returns
51
- */
52
- getSkeleton(animationName: string) {
53
- if (!this.animationMachineMap.has(FWSystemDefine.FWAnimationMachineType.SKELETON)) return;
54
- return this.animationMachineMap
55
- .get(FWSystemDefine.FWAnimationMachineType.SKELETON)
56
- .getAnimation(animationName) as FWSkeleton;
57
- }
58
-
59
- /**
60
- * 暂停一个skeleton动画
61
- * @param animationName
62
- * @returns
63
- */
64
- pauseSkeleton(animationName: string) {
65
- if (!this.animationMachineMap.has(FWSystemDefine.FWAnimationMachineType.SKELETON)) return;
66
- this.animationMachineMap.get(animationName).pause();
67
- }
68
-
69
- /**
70
- * 恢复一个skeleton动画
71
- * @param animationName
72
- * @returns
73
- */
74
- resumeSkeleton(animationName: string) {
75
- if (!this.animationMachineMap.has(FWSystemDefine.FWAnimationMachineType.SKELETON)) return;
76
- this.animationMachineMap.get(animationName).resume();
77
- }
78
- /**
79
- * 移除一个skeleton动画
80
- * @param animationName
81
- * @returns
82
- */
83
- removeSkeleton(animationName: string) {
84
- if (!this.animationMachineMap.has(FWSystemDefine.FWAnimationMachineType.SKELETON)) return;
85
- this.animationMachineMap.delete(animationName);
86
- }
87
-
88
47
  /**
89
48
  * 暂停所有动画
90
49
  */
@@ -102,7 +61,7 @@ export default class FWAnimationManager extends FWManager {
102
61
  * @param animationMachineName
103
62
  * @returns
104
63
  */
105
- createAnimationMachine(animationMachineName: string) {
64
+ private createAnimationMachine(animationMachineName: string) {
106
65
  if (this.animationMachineMap.has(animationMachineName)) {
107
66
  FWLog.warn(`已创建动画机:${animationMachineName},请勿重复注册!`);
108
67
  return;
@@ -117,12 +76,16 @@ export default class FWAnimationManager extends FWManager {
117
76
  * @param animationMachineName
118
77
  * @returns
119
78
  */
120
- removeAnimationMachine(animationMachineName: string) {
79
+ private removeAnimationMachine(animationMachineName: string) {
121
80
  if (!this.animationMachineMap.has(animationMachineName)) {
122
81
  return;
123
82
  }
124
83
  this.animationMachineMap.delete(animationMachineName);
125
84
  }
126
85
 
127
- onDestroy(): void {}
86
+ onDestroy(): void {
87
+ this.animationMachineMap.forEach((v, k) => {
88
+ this.removeAnimationMachine(k);
89
+ });
90
+ }
128
91
  }
@@ -18,7 +18,7 @@ export class FWLayerData<T extends FW.LayerController = FW.LayerController>
18
18
  layerRenderOrder: FWSystemDefine.FWLayerRenderOrder;
19
19
  layerType: FWSystemDefine.FWLayerType;
20
20
  layerParent?: cc.Node;
21
- layerPosition?: cc.Vec3;
21
+ layerPosition?: FW.Vec3;
22
22
  controllerName: string;
23
23
  controller: FW.LayerController;
24
24
  loaded: boolean;
@@ -26,282 +26,570 @@ export class FWLayerData<T extends FW.LayerController = FW.LayerController>
26
26
  externalReference?: Set<(ref: FW.LayerController | null) => void>;
27
27
  }
28
28
 
29
- export class FWLayerManager extends FWManager implements FW.LayerManager {
29
+ class FWLayerDataManager {
30
+ private layerMap: Map<new () => FW.LayerController, FWLayerData> = new Map();
31
+ private layerRegistry: Set<new () => FW.LayerController> = new Set();
32
+
30
33
  /**
31
- * 当前待打开的layer队列
34
+ * 获取已存在的Layer
32
35
  */
33
- private layerQueue: FWQueue<FW.LayerData>;
36
+ getExistingLayer<Ctr extends FW.LayerController = FW.LayerController>(
37
+ type: new () => Ctr,
38
+ ): Ctr | undefined {
39
+ for (const [key, value] of this.layerMap) {
40
+ if (value.controllerConstructor === type) {
41
+ return value.controllerProxy as Ctr;
42
+ }
43
+ }
44
+ return undefined;
45
+ }
46
+
34
47
  /**
35
- * 当前已经打开的layer缓存容器
48
+ * 从类型创建Layer数据
36
49
  */
37
- private layerMap: Map<new () => FW.LayerController, FW.LayerData>;
50
+ createLayerDataFromType<Ctr extends FW.LayerController = FW.LayerController>(
51
+ type: new () => Ctr,
52
+ ): FWLayerData | undefined {
53
+ const ctr = new type();
54
+ const ctrName = cc.js.getClassName(ctr);
55
+ const layerData = this.createBaseLayerData(ctr);
56
+
57
+ layerData.controllerConstructor = type;
58
+ layerData.controller = ctr;
59
+ layerData.controllerName = ctrName;
60
+
61
+ this.layerMap.set(type, layerData);
62
+ return layerData;
63
+ }
38
64
 
39
65
  /**
40
- * 当前所有打开Layer注册表
66
+ * 创建基础Layer数据
41
67
  */
42
- private layerRegistry: Set<new () => FW.LayerController>;
68
+ private createBaseLayerData(ctr: FW.LayerController): FWLayerData {
69
+ const layerData = new FWLayerData();
70
+ const layerType = ctr.layerType;
71
+
72
+ layerData.layerRenderOrder = ctr.renderOrder;
73
+ layerData.layerAssetProperty = ctr.layerAssetProperty;
74
+ layerData.layerType = layerType;
75
+ layerData.controller = ctr;
76
+ layerData.loaded = false;
77
+ layerData.externalReference = new Set();
78
+
79
+ return layerData;
80
+ }
81
+
43
82
  /**
44
- * layer栈队列
83
+ * 检查注册状态并添加
45
84
  */
46
- private layerStack: FWLayerData[];
85
+ checkRegistryAndAdd(type: new () => FW.LayerController): boolean {
86
+ if (this.layerRegistry.has(type)) {
87
+ return true;
88
+ }
89
+ this.layerRegistry.add(type);
90
+ return false;
91
+ }
47
92
 
48
- public initialize(): void {
49
- this.layerQueue = new FWQueue<FW.LayerData>();
50
- this.layerMap = new Map<new () => FW.LayerController, FW.LayerData>();
51
- this.layerRegistry = new Set<new () => FW.LayerController>();
52
- this.layerStack = [];
93
+ /**
94
+ * 获取已存在的代理
95
+ */
96
+ getExistingProxy<Ctr extends FW.LayerController = FW.LayerController>(
97
+ type: new () => Ctr,
98
+ ): Ctr | undefined {
99
+ return this.layerMap.get(type)?.controllerProxy as Ctr;
53
100
  }
54
101
 
55
102
  /**
56
- * 异步打开layer
57
- * @param layerData
58
- * @returns
103
+ * 设置Layer数据
59
104
  */
60
- protected async openLayerAsync(layerData: FWLayerData) {
61
- try {
62
- const res = await FW.Entry.resMgr.loadAssetData<cc.Prefab>(layerData.layerAssetProperty);
105
+ setupLayerData(
106
+ layerData: FWLayerData,
107
+ res: { asset: cc.Prefab; uuid: string },
108
+ layer: FWLayer,
109
+ layerName: string,
110
+ ): void {
111
+ layerData.loaded = true;
112
+ layerData.layer = layer;
113
+ layerData.layerName = layerName;
114
+ layerData.uuid = res.uuid;
63
115
 
64
- /** 保存资源数据 */
65
- res.user = layerData.layerName;
66
- res.autoRelease = layerData.controller.autoRelease;
67
- res.dependentBundle = layerData.controller.layerAssetProperty.bundle;
116
+ layerData.controller.layerData = layerData;
117
+ layerData.controller.layer = layer;
118
+ layerData.controller.uuid = res.uuid;
68
119
 
69
- return res;
70
- } catch (e) {
71
- FWLog.error(`openLayerAsync failed : `, e);
72
- }
120
+ layer.ctr = layerData.controller;
73
121
  }
122
+
74
123
  /**
75
- * 同步打开layer
76
- * @param layerData
77
- * @returns
124
+ * 创建控制器代理
78
125
  */
79
- protected openLayerSync(layerData: FWLayerData) {
80
- layerData.layerAssetProperty.bundle =
81
- layerData.layerAssetProperty.bundle || FW.Entry.bundleName;
82
- const res = FW.Entry.resMgr.getAssetData<cc.Prefab>(layerData.layerAssetProperty);
83
- /** 保存资源数据 */
84
- res.user = layerData.layerName;
85
- res.autoRelease = layerData.controller.autoRelease;
86
- res.dependentBundle = layerData.controller.layerAssetProperty.bundle;
126
+ createControllerProxy(layerData: FWLayerData): FW.LayerController {
127
+ return new Proxy(layerData.controller, {
128
+ get: (target, prop) => {
129
+ if (prop === ADD_EXTERNAL_REFERENCE) {
130
+ return (cb: (ref: FW.LayerController | null) => void) => {
131
+ layerData.externalReference.add(cb);
132
+ };
133
+ }
134
+ return target[prop];
135
+ },
136
+ });
137
+ }
87
138
 
88
- layerData.uuid = res.uuid;
139
+ /**
140
+ * 清理失败的Layer
141
+ */
142
+ cleanupFailedLayer(layerData: FWLayerData): void {
143
+ this.layerMap.delete(layerData.controllerConstructor);
144
+ this.layerRegistry.delete(layerData.controllerConstructor);
145
+ }
89
146
 
90
- return res;
147
+ /**
148
+ * 通知外部引用更新
149
+ */
150
+ notifyExternalRefUpdates(layerData: FWLayerData): void {
151
+ layerData.externalReference.forEach((cb) => {
152
+ try {
153
+ cb?.(null);
154
+ } catch (e) {
155
+ FWLog.error('External ref update callback error:', e);
156
+ }
157
+ });
158
+ layerData.externalReference.clear();
159
+ }
160
+
161
+ getLayerMap(): Map<new () => FW.LayerController, FWLayerData> {
162
+ return this.layerMap;
163
+ }
164
+
165
+ removeFromRegistry(type: new () => FW.LayerController): void {
166
+ this.layerRegistry.delete(type);
167
+ }
168
+
169
+ removeFromMap(type: new () => FW.LayerController): void {
170
+ this.layerMap.delete(type);
171
+ }
172
+
173
+ clear(): void {
174
+ this.layerMap.clear();
175
+ this.layerRegistry.clear();
91
176
  }
177
+ }
178
+
179
+ class FWLayerCreateManager {
180
+ private lifecycleManager: FWLayerLifecycleManager = new FWLayerLifecycleManager();
92
181
 
93
182
  /**
94
- * 创建layer数据
95
- * @param ctr
96
- * @returns
183
+ * 创建Layer节点
97
184
  */
98
- protected createLayerData(ctr: FW.LayerController) {
99
- const layerData = new FWLayerData();
100
- const layerType = ctr.layerType;
185
+ createLayer(
186
+ prefab: cc.Prefab,
187
+ layerComponent: string,
188
+ renderOrder: number,
189
+ parent: cc.Node,
190
+ position: FW.Vec3,
191
+ ): FWLayer {
192
+ parent = parent || FW.Entry.scene?.node;
193
+ position = position || cc.Vec3.ZERO;
101
194
 
102
- /** 记录layer数据 */
103
- layerData.layerRenderOrder = ctr.renderOrder;
104
- layerData.layerAssetProperty = ctr.layerAssetProperty;
105
- layerData.layerType = layerType;
106
- layerData.controller = ctr;
107
- layerData.loaded = false;
108
- layerData.externalReference = new Set();
195
+ if (!parent.activeInHierarchy || !cc.isValid(parent)) {
196
+ FWLog.error(`createLayer failed , parent : ${parent}`);
197
+ return;
198
+ }
109
199
 
110
- return layerData;
200
+ const node = cc.instantiate(prefab);
201
+ const p = cc.v3(position.x, position.y);
202
+ node.setParent(parent);
203
+ node.setPosition(p);
204
+ node.zIndex = renderOrder;
205
+
206
+ !node.getComponent(layerComponent) && node.addComponent(layerComponent);
207
+ return node.getComponent(FWLayer);
111
208
  }
112
209
 
113
210
  /**
114
- * 异步打开layer
115
- * @param data
116
- * @returns
211
+ * 设置Layer生命周期
117
212
  */
118
- async openAsync<Ctr extends FW.LayerController = FW.LayerController>(
213
+ setupLayerLifecycle(layer: FWLayer, ctr: FW.LayerController): void {
214
+ this.lifecycleManager.setupLifecycleHooks(layer, ctr);
215
+ }
216
+
217
+ /**
218
+ * 初始化控制器
219
+ */
220
+ initializeController(ctr: FW.LayerController, data: any): void {
221
+ ctr.initialize();
222
+ ctr.onInit?.(data);
223
+ }
224
+ }
225
+
226
+ class FWLayerOpenManager {
227
+ constructor(
228
+ private dataManager: FWLayerDataManager,
229
+ private resourceManager: FWLayerResourceManager,
230
+ private createManager: FWLayerCreateManager,
231
+ private stackManager: FWLayerStackManager,
232
+ private queueManager: FWLayerQueueManager,
233
+ ) {}
234
+
235
+ /**
236
+ * 统一的Layer打开方法
237
+ */
238
+ async openLayer<Ctr extends FW.LayerController = FW.LayerController>(
119
239
  data: FW.LayerOpenArgs,
240
+ isAsync: boolean,
120
241
  ): Promise<Ctr> {
121
- if (!data) {
122
- FWLog.error(`打开Layer失败:${data},请检查参数!`);
123
- return undefined;
242
+ if (!this.validateOpenData(data)) {
243
+ return this.getUndefinedResult(isAsync);
124
244
  }
125
245
 
126
- for (const [key, value] of this.layerMap) {
127
- if (value.controllerConstructor == data.type) {
128
- return value.controllerProxy as Ctr;
129
- }
246
+ const existingLayer = this.dataManager.getExistingLayer(data.type);
247
+ if (existingLayer) {
248
+ return this.wrapResult(existingLayer, isAsync) as Ctr;
130
249
  }
131
250
 
132
- const ctr = new data.type();
133
- const ctrName = cc.js.getClassName(ctr);
134
- const layerData = this.createLayerData(ctr);
251
+ const layerData = this.dataManager.createLayerDataFromType(data.type);
252
+ if (!layerData) {
253
+ return this.getUndefinedResult(isAsync);
254
+ }
135
255
 
136
- layerData.controllerConstructor = data.type;
137
- layerData.controller = ctr;
138
- layerData.controllerName = ctrName;
256
+ if (this.dataManager.checkRegistryAndAdd(data.type)) {
257
+ const proxy = this.dataManager.getExistingProxy(data.type);
258
+ return this.wrapResult(proxy, isAsync) as Ctr;
259
+ }
139
260
 
140
- this.layerMap.set(data.type, layerData);
261
+ if (this.queueManager.handlePopupQueue(layerData, this.dataManager.getLayerMap())) {
262
+ return this.getUndefinedResult(isAsync);
263
+ }
264
+
265
+ if (isAsync) {
266
+ return this.loadAndCreateLayerAsync(layerData, data);
267
+ } else {
268
+ return this.loadAndCreateLayerSync(layerData, data) as Ctr;
269
+ }
270
+ }
141
271
 
142
- if (this.layerRegistry.has(data.type)) {
143
- return this.layerMap.get(data.type).controllerProxy as Ctr;
272
+ /**
273
+ * 验证打开数据
274
+ */
275
+ private validateOpenData(data: FW.LayerOpenArgs): boolean {
276
+ if (!data) {
277
+ FWLog.error(`打开Layer失败:${data},请检查参数!`);
278
+ return false;
144
279
  }
280
+ return true;
281
+ }
145
282
 
146
- this.layerRegistry.add(data.type);
283
+ /**
284
+ * 获取undefined结果
285
+ */
286
+ private getUndefinedResult<Ctr>(isAsync: boolean): Promise<Ctr> | Ctr {
287
+ return isAsync ? Promise.resolve(undefined) : undefined;
288
+ }
147
289
 
148
- if (ctr.layerType == FWSystemDefine.FWLayerType.POPUP_QUEUE) {
149
- if (this.layerRegistry.size == 0) {
150
- let unclose = true;
151
- for (const [key, value] of this.layerMap) {
152
- if (value.layerType != FWSystemDefine.FWLayerType.PERMANENT) {
153
- unclose = false;
154
- }
155
- }
156
- if (!unclose) {
157
- this.layerQueue.add(ctr.layerData);
158
- return;
159
- }
160
- }
290
+ /**
291
+ * 包装结果
292
+ */
293
+ private wrapResult<Ctr>(result: Ctr, isAsync: boolean): Promise<Ctr> | Ctr {
294
+ return isAsync ? Promise.resolve(result) : result;
295
+ }
296
+
297
+ /**
298
+ * 异步加载资源并创建Layer
299
+ */
300
+ private async loadAndCreateLayerAsync<Ctr extends FW.LayerController = FW.LayerController>(
301
+ layerData: FWLayerData,
302
+ data: FW.LayerOpenArgs,
303
+ ): Promise<Ctr> {
304
+ try {
305
+ const res = await this.resourceManager.loadLayerAsync(layerData);
306
+ return this.createLayerAndSetup(layerData, res, data) as Ctr;
307
+ } catch (e) {
308
+ FWLog.error(`loadAndCreateLayerAsync failed:`, e);
309
+ this.dataManager.cleanupFailedLayer(layerData);
310
+ throw e;
161
311
  }
312
+ }
162
313
 
163
- ctr.initialize();
314
+ /**
315
+ * 同步加载资源并创建Layer
316
+ */
317
+ private loadAndCreateLayerSync<Ctr extends FW.LayerController = FW.LayerController>(
318
+ layerData: FWLayerData,
319
+ data: FW.LayerOpenArgs,
320
+ ): Ctr {
321
+ try {
322
+ const res = this.resourceManager.loadLayerSync(layerData);
323
+ return this.createLayerAndSetup(layerData, res, data);
324
+ } catch (e) {
325
+ FWLog.error(`loadAndCreateLayerSync failed:`, e);
326
+ this.dataManager.cleanupFailedLayer(layerData);
327
+ return undefined;
328
+ }
329
+ }
164
330
 
165
- const res = await this.openLayerAsync(layerData);
166
- const layer = await this.createLayer(
331
+ /**
332
+ * 创建Layer并进行设置
333
+ */
334
+ private createLayerAndSetup<Ctr extends FW.LayerController = FW.LayerController>(
335
+ layerData: FWLayerData,
336
+ res: { asset: cc.Prefab; uuid: string },
337
+ data: FW.LayerOpenArgs,
338
+ ): Ctr {
339
+ const layer = this.createManager.createLayer(
167
340
  res.asset,
168
341
  res.asset.name,
169
- ctr.renderOrder,
342
+ layerData.controller.renderOrder,
170
343
  data.parent,
171
344
  data.position,
172
345
  );
173
-
174
346
  const layerName = cc.js.getClassName(layer);
175
347
 
176
- ctr.layerData = layerData;
177
- ctr.layerData.loaded = true;
178
- ctr.layer = layer;
179
- ctr.layerData.layerName = layerName;
180
- ctr.layerData.uuid = res.uuid;
181
- ctr.uuid = res.uuid;
182
- ctr.onInit?.(data.args);
348
+ this.dataManager.setupLayerData(layerData, res, layer, layerName);
183
349
 
184
- this.lifecycleProcessing(ctr);
350
+ this.createManager.initializeController(layerData.controller, data.args);
185
351
 
186
- if (ctr.layerType !== FWSystemDefine.FWLayerType.PERMANENT) {
187
- this.layerStack.push(layerData);
352
+ this.createManager.setupLayerLifecycle(layer, layerData.controller);
353
+
354
+ if (layerData.controller.layerType !== FWSystemDefine.FWLayerType.PERMANENT) {
355
+ this.stackManager.push(layerData);
188
356
  }
189
357
 
190
- this.layerRegistry.delete(data.type);
358
+ this.dataManager.removeFromRegistry(layerData.controllerConstructor);
359
+
360
+ const proxy = this.dataManager.createControllerProxy(layerData);
361
+ layerData.controllerProxy = proxy;
191
362
 
192
- const proxy = new Proxy(ctr, {
193
- get: (target, prop) => {
194
- if (prop === ADD_EXTERNAL_REFERENCE) {
195
- return (cb: (ref: FW.LayerController | null) => void) => {
196
- layerData.externalReference.add(cb);
197
- };
198
- }
199
- return target[prop];
200
- },
201
- });
202
- ctr.layerData.controllerProxy = proxy;
203
363
  return proxy as Ctr;
204
364
  }
365
+ }
205
366
 
206
- /**
207
- * 同步打开
208
- * @param data
209
- * @returns
210
- */
211
- openSync<Ctr extends FW.LayerController = FW.LayerController>(data: FW.LayerOpenArgs): Ctr {
212
- if (!data) {
213
- FWLog.error(`open layer failed:${data},please check param!`);
214
- return undefined;
367
+ class FWLayerResourceManager {
368
+ async loadLayerAsync(layerData: FWLayerData): Promise<{ asset: cc.Prefab; uuid: string }> {
369
+ try {
370
+ const res = await FW.Entry.resMgr.loadAssetData<cc.Prefab>(layerData.layerAssetProperty);
371
+ res.user = layerData.layerName;
372
+ res.autoRelease = layerData.controller.autoRelease;
373
+ res.dependentBundle = layerData.controller.layerAssetProperty.bundle;
374
+ return { asset: res.asset as cc.Prefab, uuid: res.uuid };
375
+ } catch (e) {
376
+ FWLog.error(`loadLayerAsync failed:`, e);
377
+ throw e;
215
378
  }
379
+ }
216
380
 
217
- for (const [key, value] of this.layerMap) {
218
- if (value.controllerConstructor == data.type) {
219
- return value.controllerProxy as Ctr;
220
- }
221
- }
381
+ loadLayerSync(layerData: FWLayerData): { asset: cc.Prefab; uuid: string } {
382
+ layerData.layerAssetProperty.bundle =
383
+ layerData.layerAssetProperty.bundle || FW.Entry.bundleName;
384
+ const res = FW.Entry.resMgr.getAssetData<cc.Prefab>(layerData.layerAssetProperty);
385
+ res.user = layerData.layerName;
386
+ res.autoRelease = layerData.controller.autoRelease;
387
+ res.dependentBundle = layerData.controller.layerAssetProperty.bundle;
388
+ return { asset: res.asset as cc.Prefab, uuid: res.uuid };
389
+ }
390
+ }
222
391
 
223
- const ctr = new data.type();
224
- const ctrName = cc.js.getClassName(ctr);
225
- const layerData = this.createLayerData(ctr);
392
+ class FWLayerStackManager {
393
+ private layerStack: FWLayerData[] = [];
226
394
 
227
- layerData.controllerConstructor = data.type;
228
- layerData.controller = ctr;
229
- layerData.controllerName = ctrName;
395
+ push(layerData: FWLayerData): void {
396
+ if (layerData.controller.layerType !== FWSystemDefine.FWLayerType.PERMANENT) {
397
+ this.layerStack.push(layerData);
398
+ }
399
+ }
230
400
 
231
- this.layerMap.set(data.type, layerData);
401
+ pop(): FWLayerData | undefined {
402
+ return this.layerStack.pop();
403
+ }
232
404
 
233
- if (this.layerRegistry.has(data.type)) {
234
- return this.layerMap.get(data.type).controllerProxy as Ctr;
405
+ remove(layerData: FWLayerData): void {
406
+ const index = this.layerStack.findIndex((v) => v.controller === layerData.controller);
407
+ if (index > -1) {
408
+ this.layerStack.splice(index, 1);
235
409
  }
410
+ }
236
411
 
237
- this.layerRegistry.add(data.type);
412
+ getStack(): FWLayerData[] {
413
+ return [...this.layerStack];
414
+ }
238
415
 
239
- if (ctr.layerType == FWSystemDefine.FWLayerType.POPUP_QUEUE) {
240
- if (this.layerRegistry.size == 0) {
241
- let unclose = true;
242
- for (const [key, value] of this.layerMap) {
243
- if (value.layerType != FWSystemDefine.FWLayerType.PERMANENT) {
244
- unclose = false;
245
- }
246
- }
247
- if (!unclose) {
248
- this.layerQueue.add(ctr.layerData);
249
- return;
250
- }
416
+ clear(): void {
417
+ this.layerStack = [];
418
+ }
419
+ }
420
+
421
+ class FWLayerStateManager {
422
+ private layerStates = new Map<new () => FW.LayerController, FWSystemDefine.FWLayerState>();
423
+
424
+ setState(ctrType: new () => FW.LayerController, state: FWSystemDefine.FWLayerState): void {
425
+ this.layerStates.set(ctrType, state);
426
+ }
427
+
428
+ getState(ctrType: new () => FW.LayerController): FWSystemDefine.FWLayerState {
429
+ return this.layerStates.get(ctrType) || FWSystemDefine.FWLayerState.CLOSED;
430
+ }
431
+
432
+ isOpening(ctrType: new () => FW.LayerController): boolean {
433
+ return this.getState(ctrType) === FWSystemDefine.FWLayerState.OPENING;
434
+ }
435
+
436
+ isOpened(ctrType: new () => FW.LayerController): boolean {
437
+ return this.getState(ctrType) === FWSystemDefine.FWLayerState.OPENED;
438
+ }
439
+
440
+ isClosing(ctrType: new () => FW.LayerController): boolean {
441
+ return this.getState(ctrType) === FWSystemDefine.FWLayerState.CLOSING;
442
+ }
443
+
444
+ removeState(ctrType: new () => FW.LayerController): void {
445
+ this.layerStates.delete(ctrType);
446
+ }
447
+
448
+ clear(): void {
449
+ this.layerStates.clear();
450
+ }
451
+ }
452
+
453
+ class FWLayerQueueManager {
454
+ private layerQueue: FWQueue<FWLayerData> = new FWQueue<FWLayerData>();
455
+
456
+ handlePopupQueue(
457
+ layerData: FWLayerData,
458
+ layerMap: Map<new () => FW.LayerController, FWLayerData>,
459
+ ): boolean {
460
+ if (layerData.controller.layerType === FWSystemDefine.FWLayerType.POPUP_QUEUE) {
461
+ const hasNonPermanentLayers = Array.from(layerMap.values()).some(
462
+ (value) => value.layerType !== FWSystemDefine.FWLayerType.PERMANENT,
463
+ );
464
+
465
+ if (hasNonPermanentLayers) {
466
+ this.add(layerData);
467
+ return true;
251
468
  }
252
469
  }
470
+ return false;
471
+ }
253
472
 
254
- ctr.initialize();
473
+ getNextLayer(): FWLayerData | undefined {
474
+ return this.shift();
475
+ }
255
476
 
256
- const res = this.openLayerSync(layerData);
257
- const layer = this.createLayer(
258
- res.asset,
259
- res.asset.name,
260
- layerData.layerRenderOrder,
261
- layerData.layerParent,
262
- layerData.layerPosition,
263
- );
264
- const layerName = cc.js.getClassName(layer);
477
+ add(layerData: FWLayerData): void {
478
+ this.layerQueue.add(layerData);
479
+ }
265
480
 
266
- ctr.layerData = layerData;
267
- ctr.layerData.loaded = true;
268
- ctr.layer = layer;
269
- ctr.layerData.layerName = layerName;
270
- ctr.layerData.uuid = res.uuid;
271
- ctr.uuid = res.uuid;
272
- ctr.onInit?.(data.args);
481
+ shift(): FWLayerData | undefined {
482
+ return this.layerQueue.shift();
483
+ }
273
484
 
274
- this.lifecycleProcessing(ctr);
485
+ isEmpty(): boolean {
486
+ return this.layerQueue.isEmpty();
487
+ }
275
488
 
276
- if (ctr.layerType !== FWSystemDefine.FWLayerType.PERMANENT) {
277
- this.layerStack.push(layerData);
278
- }
489
+ clear(): void {
490
+ this.layerQueue.clear();
491
+ }
279
492
 
280
- this.layerRegistry.delete(data.type);
493
+ getQueue(): FWLayerData[] {
494
+ return this.layerQueue.getQueue();
495
+ }
496
+ }
281
497
 
282
- const proxy = new Proxy(ctr, {
283
- get: (target, prop) => {
284
- if (prop === 'addExternalReference') {
285
- return (cb: (ref: FW.LayerController | null) => void) => {
286
- layerData.externalReference.add(cb);
287
- };
288
- }
289
- return target[prop];
290
- },
291
- });
292
- ctr.layerData.controllerProxy = proxy;
293
- return proxy as Ctr;
498
+ class FWLayerLifecycleManager {
499
+ setupLifecycleHooks(layer: FWLayer, ctr: FW.LayerController): void {
500
+ const originalOnLoad = layer['onLoad'];
501
+ layer['onLoad'] = function () {
502
+ originalOnLoad?.call(this);
503
+ ctr.onLoad?.();
504
+ };
505
+
506
+ const originalStart = layer['start'];
507
+ layer['start'] = function () {
508
+ originalStart?.call(this);
509
+ ctr.onStart?.();
510
+ };
511
+
512
+ const originalOnEnable = layer['onEnable'];
513
+ layer['onEnable'] = function () {
514
+ originalOnEnable?.call(this);
515
+ ctr.onEnable?.();
516
+ };
517
+
518
+ const originalOnDisable = layer['onDisable'];
519
+ layer['onDisable'] = function () {
520
+ originalOnDisable?.call(this);
521
+ ctr.onDisable?.();
522
+ };
523
+
524
+ const originalOnDestroy = layer['onDestroy'];
525
+ layer['onDestroy'] = function () {
526
+ originalOnDestroy?.call(this);
527
+ ctr.onDestroy?.();
528
+ };
529
+
530
+ const originalUpdate = layer['update'];
531
+ layer['update'] = function (dt: number) {
532
+ originalUpdate?.call(this, dt);
533
+ ctr.onUpdate?.(dt);
534
+ };
535
+
536
+ const originalLateUpdate = layer['lateUpdate'];
537
+ layer['lateUpdate'] = function () {
538
+ originalLateUpdate?.call(this);
539
+ ctr.onLateUpdate?.();
540
+ };
541
+ }
542
+ }
543
+
544
+ export class FWLayerManager extends FWManager implements FW.LayerManager {
545
+ private resourceManager: FWLayerResourceManager;
546
+ private dataManager: FWLayerDataManager;
547
+ private createManager: FWLayerCreateManager;
548
+ private stackManager: FWLayerStackManager;
549
+ private stateManager: FWLayerStateManager;
550
+ private queueManager: FWLayerQueueManager;
551
+ private openManager: FWLayerOpenManager;
552
+
553
+ public initialize(): void {
554
+ this.resourceManager = new FWLayerResourceManager();
555
+ this.dataManager = new FWLayerDataManager();
556
+ this.createManager = new FWLayerCreateManager();
557
+ this.stackManager = new FWLayerStackManager();
558
+ this.stateManager = new FWLayerStateManager();
559
+ this.queueManager = new FWLayerQueueManager();
560
+
561
+ this.openManager = new FWLayerOpenManager(
562
+ this.dataManager,
563
+ this.resourceManager,
564
+ this.createManager,
565
+ this.stackManager,
566
+ this.queueManager,
567
+ );
568
+ }
569
+
570
+ /**
571
+ * 异步打开Layer
572
+ */
573
+ async openAsync<Ctr extends FW.LayerController = FW.LayerController>(
574
+ data: FW.LayerOpenArgs,
575
+ ): Promise<Ctr> {
576
+ return this.openManager.openLayer(data, true) as Promise<Ctr>;
577
+ }
578
+
579
+ /**
580
+ * 同步打开
581
+ */
582
+ openSync<Ctr extends FW.LayerController = FW.LayerController>(data: FW.LayerOpenArgs): Ctr {
583
+ return this.openManager.openLayer(data, false) as unknown as Ctr;
294
584
  }
295
585
 
296
586
  /**
297
587
  * 显示layer并恢复所有节点事件
298
- * @param ctr
299
- * @returns
300
588
  */
301
589
  displayLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
302
590
  const layerData = ctr.layerData;
303
591
 
304
- if (!this.layerMap.has(ctr.layerData.controllerConstructor)) {
592
+ if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
305
593
  FWLog.warn(`display layer failed,layer name : ${layerData.layerName}`);
306
594
  return;
307
595
  }
@@ -313,17 +601,17 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
313
601
  node.resumeSystemEvents(true);
314
602
 
315
603
  FW.Entry.evtMgr.targetResume(ctr);
316
- FW.Entry.timeMgr.pauseSchedule(ctr);
604
+ FW.Entry.timeMgr.resumeSchedule(ctr);
605
+
606
+ return ctr;
317
607
  }
318
608
 
319
609
  /**
320
610
  * 隐藏layer并隐藏所有节点事件
321
- * @param ctr
322
- * @returns
323
611
  */
324
612
  hideLayer<Ctr extends FW.LayerController = FW.LayerController>(ctr: Ctr): Ctr {
325
613
  const layerData = ctr.layerData;
326
- if (!this.layerMap.has(ctr.layerData.controllerConstructor)) {
614
+ if (!this.dataManager.getLayerMap().has(ctr.layerData.controllerConstructor)) {
327
615
  FWLog.warn(`hide layer failed,layer name : ${layerData.layerName}`);
328
616
  return;
329
617
  }
@@ -335,15 +623,16 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
335
623
  node.opacity = 0;
336
624
  node.pauseSystemEvents(true);
337
625
  FW.Entry.evtMgr.targetPause(ctr);
338
- FW.Entry.timeMgr.resumeSchedule(ctr);
626
+ FW.Entry.timeMgr.pauseSchedule(ctr);
627
+
628
+ return ctr;
339
629
  }
340
630
 
341
631
  /**
342
632
  * 通过layer名字关闭
343
- * @param name
344
633
  */
345
634
  closeFromLayerName(name: string | string[]): void {
346
- this.layerMap.forEach((v) => {
635
+ this.dataManager.getLayerMap().forEach((v) => {
347
636
  if (Array.isArray(name)) {
348
637
  name.forEach((n) => {
349
638
  if (n === v.layerName) {
@@ -357,15 +646,16 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
357
646
  }
358
647
  });
359
648
  }
649
+
360
650
  /**
361
651
  * 从栈关闭
362
652
  */
363
653
  closeFromStack(count?: number) {
364
654
  count = count ? count : 1;
365
655
  for (let i = 0; i < count; i++) {
366
- let layerData = this.layerStack.pop();
656
+ let layerData = this.stackManager.pop();
367
657
  let ctr = layerData.controller;
368
- if (!this.layerMap.has(layerData.controllerConstructor)) {
658
+ if (!this.dataManager.getLayerMap().has(layerData.controllerConstructor)) {
369
659
  return;
370
660
  }
371
661
  if (cc.isValid(ctr.layer?.node)) {
@@ -373,15 +663,28 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
373
663
  if (ctr.autoRelease) {
374
664
  FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
375
665
  }
376
- this.notifyExternalRefUpdates(ctr.layerData);
666
+ this.dataManager.notifyExternalRefUpdates(ctr.layerData);
377
667
  }
378
- this.layerMap.delete(layerData.controllerConstructor);
668
+ this.dataManager.removeFromMap(layerData.controllerConstructor);
379
669
  }
380
670
  }
671
+ /**
672
+ * 移除指定Layer所有子Layer
673
+ * @param layer
674
+ * @returns
675
+ */
676
+ async removeAllChildren(layer: FW.Layer) {
677
+ if (cc.isValid(!layer?.node)) return;
678
+ const layers = layer.node.getComponentsInChildren(FWLayer);
679
+ layers.forEach((v) => {
680
+ if (cc.isValid(v?.node)) {
681
+ v?.ctr?.close();
682
+ }
683
+ });
684
+ }
381
685
 
382
686
  /**
383
687
  * 关闭layer
384
- * @param ctr
385
688
  */
386
689
  async close<Ctr extends FW.LayerController = FW.LayerController>(
387
690
  ctr: Ctr,
@@ -397,20 +700,22 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
397
700
  if (ctr.autoRelease) {
398
701
  FW.Entry.resMgr.releaseAsset(ctr.layerData.layerAssetProperty);
399
702
  }
400
- this.notifyExternalRefUpdates(ctr.layerData);
703
+ this.dataManager.notifyExternalRefUpdates(ctr.layerData);
401
704
  }
402
705
 
403
- this.layerMap.delete(layerData.controllerConstructor);
404
- this.layerRegistry.delete(ctr.layerData.controllerConstructor);
706
+ this.dataManager.removeFromMap(layerData.controllerConstructor);
707
+ this.dataManager.removeFromRegistry(ctr.layerData.controllerConstructor);
405
708
 
406
- const index = this.layerStack.findIndex((v) => {
709
+ const index = this.stackManager.getStack().findIndex((v) => {
407
710
  v.controller == ctr;
408
711
  });
409
- this.layerStack.slice(index, 1);
712
+ if (index > -1) {
713
+ this.stackManager.getStack().splice(index, 1);
714
+ }
410
715
 
411
716
  /** 如果队列中还有等待打开的layer */
412
- if (!this.layerQueue.isEmpty()) {
413
- const nextLayerData = this.layerQueue.shift();
717
+ if (!this.queueManager.isEmpty()) {
718
+ const nextLayerData = this.queueManager.getNextLayer();
414
719
  /** 先尝试同步打开 */
415
720
  const nextLayer = this.openSync({
416
721
  parent: nextLayerData.layerParent,
@@ -432,102 +737,19 @@ export class FWLayerManager extends FWManager implements FW.LayerManager {
432
737
  }
433
738
  }
434
739
 
435
- private notifyExternalRefUpdates(layerData: FW.LayerData) {
436
- layerData.externalReference.forEach((cb) => {
437
- try {
438
- cb?.(null);
439
- } catch (e) {
440
- FWLog.error('External ref update callback error:', e);
441
- }
442
- });
443
- layerData.externalReference.clear();
444
- }
445
- /** 创建layer */
446
- private createLayer(
447
- prefab: cc.Prefab,
448
- layerComponent: string,
449
- renderOrder: number,
450
- parent: cc.Node,
451
- position: FW.Vec3,
452
- ) {
453
- parent = parent || FW.Entry.scene?.node;
454
-
455
- position = position || cc.Vec3.ZERO;
456
-
457
- if (!parent.activeInHierarchy || !cc.isValid(parent)) {
458
- FWLog.error(`createLayer failed , parent : ${parent}`);
459
- return;
460
- }
461
- const node = cc.instantiate(prefab);
462
- const p = cc.v3(position.x, position.y);
463
- node.setParent(parent);
464
- node.setPosition(p);
465
- node.zIndex = renderOrder;
466
- !node.getComponent(layerComponent) && node.addComponent(layerComponent);
467
- return node.getComponent(FWLayer);
468
- }
469
-
470
- private lifecycleProcessing(ctr: FW.LayerController) {
471
- const layer = ctr.layer;
472
-
473
- const onLoad = layer['onLoad'];
474
- layer['onLoad'] = () => {
475
- onLoad?.call(layer);
476
- ctr.onLoad?.();
477
- };
478
-
479
- const onStart = layer['start'];
480
- layer['start'] = () => {
481
- onStart?.call(layer);
482
- ctr.onStart?.();
483
- };
484
-
485
- const onEnable = layer['onEnable'];
486
- layer['onEnable'] = () => {
487
- onEnable?.call(layer);
488
- ctr.onEnable?.();
489
- };
490
-
491
- const onDisable = layer['onDisable'];
492
- layer['onDisable'] = () => {
493
- onDisable?.call(layer);
494
- ctr.onDisable?.();
495
- };
496
-
497
- const onDestroy = layer['onDestroy'];
498
- layer['onDestroy'] = () => {
499
- onDestroy?.call(layer);
500
- ctr.onDestroy?.();
501
- };
502
-
503
- const onUpdate = layer['update'];
504
- layer['update'] = (dt?: number) => {
505
- onUpdate?.call(layer);
506
- ctr.onUpdate?.(dt);
507
- };
508
-
509
- const onLateUpdate = layer['lateUpdate'];
510
- layer['lateUpdate'] = () => {
511
- onLateUpdate?.call(layer);
512
- ctr.onLateUpdate?.();
513
- };
514
- }
515
-
516
- getLayerMap(): Map<new () => FW.LayerController, FW.LayerData> {
517
- return this.layerMap;
740
+ getLayerMap(): Map<new () => FW.LayerController, FWLayerData> {
741
+ return this.dataManager.getLayerMap();
518
742
  }
519
743
 
520
744
  public clear() {
521
- this.layerQueue = new FWQueue();
522
- this.layerStack = [];
523
- this.layerRegistry = new Set<new () => FW.LayerController>();
524
- this.layerMap.forEach((v) => this.close(v.controller));
525
- this.layerMap.clear();
745
+ this.queueManager.clear();
746
+ this.stackManager.clear();
747
+ this.stateManager.clear();
748
+ this.dataManager.clear();
749
+ this.dataManager.getLayerMap().forEach((v) => this.close(v.controller));
526
750
  }
527
751
 
528
752
  public onDestroy(): void {
529
- this.layerMap.clear();
530
- this.layerMap = null;
531
- this.layerQueue = null;
753
+ this.clear();
532
754
  }
533
755
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ives_xxz/framework",
3
- "version": "1.4.8",
3
+ "version": "1.4.9",
4
4
  "description": "cocoscreator 2.x mvc framework",
5
5
  "main": "index.js",
6
6
  "keywords": ["123456"],
package/utils/FWQueue.ts CHANGED
@@ -44,4 +44,12 @@ export class FWQueue<T> {
44
44
  public size() {
45
45
  return this.queue.length;
46
46
  }
47
+
48
+ public clear() {
49
+ this.queue = [];
50
+ }
51
+
52
+ public getQueue() {
53
+ return this.queue;
54
+ }
47
55
  }