hzengine-core 0.1.2-dev
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/async/index.js +162 -0
- package/dist/async/zeppos_timer.js +58 -0
- package/dist/audio/index.js +260 -0
- package/dist/config/index.js +57 -0
- package/dist/debug/index.js +8 -0
- package/dist/index.js +103 -0
- package/dist/platform/index.js +1 -0
- package/dist/plugins/basic_command/$.js +8 -0
- package/dist/plugins/basic_command/audio.js +40 -0
- package/dist/plugins/basic_command/basic.js +124 -0
- package/dist/plugins/basic_command/character.js +112 -0
- package/dist/plugins/basic_command/conditional.js +260 -0
- package/dist/plugins/basic_command/config.js +22 -0
- package/dist/plugins/basic_command/decorator.js +24 -0
- package/dist/plugins/basic_command/eval.js +67 -0
- package/dist/plugins/basic_command/img.js +249 -0
- package/dist/plugins/basic_command/index.js +22 -0
- package/dist/plugins/basic_command/menu.js +140 -0
- package/dist/plugins/global_gesture/index.js +25 -0
- package/dist/plugins/transform/animation.js +440 -0
- package/dist/plugins/transform/commands.js +38 -0
- package/dist/plugins/transform/example_profiles.js +32 -0
- package/dist/plugins/transform/hz_anime.js +211 -0
- package/dist/plugins/transform/index.js +93 -0
- package/dist/script/index.js +537 -0
- package/dist/script/readscript.js +15 -0
- package/dist/script/strtools.js +157 -0
- package/dist/storage/decorator.js +260 -0
- package/dist/storage/fs.js +96 -0
- package/dist/storage/index.js +442 -0
- package/dist/system/index.js +144 -0
- package/dist/ui/index.js +535 -0
- package/dist/utils/path.js +289 -0
- package/license.txt +202 -0
- package/package.json +26 -0
- package/src/async/index.ts +124 -0
- package/src/async/zeppos_timer.js +65 -0
- package/src/audio/index.ts +224 -0
- package/src/config/index.ts +80 -0
- package/src/debug/index.ts +11 -0
- package/src/index.ts +122 -0
- package/src/platform/index.ts +158 -0
- package/src/plugins/basic_command/$.ts +11 -0
- package/src/plugins/basic_command/audio.ts +53 -0
- package/src/plugins/basic_command/basic.ts +145 -0
- package/src/plugins/basic_command/character.ts +144 -0
- package/src/plugins/basic_command/conditional.ts +349 -0
- package/src/plugins/basic_command/config.ts +29 -0
- package/src/plugins/basic_command/decorator.ts +29 -0
- package/src/plugins/basic_command/eval.ts +88 -0
- package/src/plugins/basic_command/img.ts +317 -0
- package/src/plugins/basic_command/index.ts +24 -0
- package/src/plugins/basic_command/menu.ts +178 -0
- package/src/plugins/global_gesture/index.ts +29 -0
- package/src/plugins/transform/animation.ts +542 -0
- package/src/plugins/transform/commands.ts +53 -0
- package/src/plugins/transform/example_profiles.ts +36 -0
- package/src/plugins/transform/hz_anime.ts +214 -0
- package/src/plugins/transform/index.ts +141 -0
- package/src/plugins/transform/readme.md +1 -0
- package/src/script/index.ts +623 -0
- package/src/script/readscript.ts +17 -0
- package/src/script/strtools.ts +159 -0
- package/src/storage/decorator.ts +473 -0
- package/src/storage/fs.ts +104 -0
- package/src/storage/index.ts +541 -0
- package/src/system/index.ts +95 -0
- package/src/ui/index.ts +699 -0
- package/src/utils/path.js +338 -0
- package/tsconfig.json +111 -0
- package/types/async/index.d.ts +24 -0
- package/types/async/zeppos_timer.d.ts +14 -0
- package/types/audio/index.d.ts +64 -0
- package/types/config/index.d.ts +9 -0
- package/types/debug/index.d.ts +6 -0
- package/types/index.d.ts +41 -0
- package/types/platform/index.d.ts +134 -0
- package/types/plugins/basic_command/$.d.ts +2 -0
- package/types/plugins/basic_command/audio.d.ts +2 -0
- package/types/plugins/basic_command/basic.d.ts +3 -0
- package/types/plugins/basic_command/character.d.ts +2 -0
- package/types/plugins/basic_command/conditional.d.ts +2 -0
- package/types/plugins/basic_command/config.d.ts +2 -0
- package/types/plugins/basic_command/decorator.d.ts +2 -0
- package/types/plugins/basic_command/eval.d.ts +2 -0
- package/types/plugins/basic_command/img.d.ts +2 -0
- package/types/plugins/basic_command/index.d.ts +2 -0
- package/types/plugins/basic_command/menu.d.ts +2 -0
- package/types/plugins/global_gesture/index.d.ts +2 -0
- package/types/plugins/transform/animation.d.ts +131 -0
- package/types/plugins/transform/commands.d.ts +7 -0
- package/types/plugins/transform/example_profiles.d.ts +2 -0
- package/types/plugins/transform/hz_anime.d.ts +51 -0
- package/types/plugins/transform/index.d.ts +13 -0
- package/types/script/index.d.ts +123 -0
- package/types/script/readscript.d.ts +2 -0
- package/types/script/strtools.d.ts +31 -0
- package/types/storage/decorator.d.ts +41 -0
- package/types/storage/fs.d.ts +1 -0
- package/types/storage/index.d.ts +86 -0
- package/types/system/index.d.ts +35 -0
- package/types/ui/index.d.ts +167 -0
- package/types/utils/path.d.ts +84 -0
package/src/ui/index.ts
ADDED
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
import { HZEngineCore, Platform } from "../index.js";
|
|
2
|
+
import { Save, CustomSave } from "../storage/decorator.js";
|
|
3
|
+
import { Storage } from "../storage/index.js";
|
|
4
|
+
// / <reference path="node_modules/@zeppos/device-types/dist/index.d.ts" />
|
|
5
|
+
// import * as hmUI from "@zos/ui";
|
|
6
|
+
// import {} from "@zos/ui";
|
|
7
|
+
|
|
8
|
+
// import { getDeviceInfo, SCREEN_SHAPE_SQUARE } from "@zos/device";
|
|
9
|
+
// const { width, height, screenShape } = getDeviceInfo();
|
|
10
|
+
export class UI<PlatformType extends Platform = any> {
|
|
11
|
+
constructor(public _core: HZEngineCore<PlatformType>) {
|
|
12
|
+
this._initUI();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
private _initUI() {
|
|
16
|
+
this.addLayer("bg", 1);
|
|
17
|
+
this.addLayer("fg", 2);
|
|
18
|
+
this.addLayer("ct", 3);
|
|
19
|
+
this.addLayer("overlay", 4);
|
|
20
|
+
this.addRouter("page", "overlay", false);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private _cleanUI() {
|
|
24
|
+
for (let [key, value] of this.layerList) {
|
|
25
|
+
value.destroy();
|
|
26
|
+
}
|
|
27
|
+
this.layerList.clear();
|
|
28
|
+
this._routerMap.clear();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
resetUI() {
|
|
32
|
+
this._cleanUI();
|
|
33
|
+
this._initUI();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Layer
|
|
37
|
+
@CustomSave(
|
|
38
|
+
"ui.layerList",
|
|
39
|
+
function serializer(layerList) {
|
|
40
|
+
let obj: Record<string, [name: string, z_index: number]> = {};
|
|
41
|
+
for (let [key, value] of this.layerList) {
|
|
42
|
+
obj[key] = [value.name, value.z_index];
|
|
43
|
+
}
|
|
44
|
+
return obj;
|
|
45
|
+
},
|
|
46
|
+
function deserializer(obj) {
|
|
47
|
+
// destroy old layer
|
|
48
|
+
for (let [key, value] of this.layerList) {
|
|
49
|
+
value.destroy();
|
|
50
|
+
}
|
|
51
|
+
this.layerList.clear();
|
|
52
|
+
|
|
53
|
+
let newLayerList = new Map<string, UI.Layer<PlatformType>>();
|
|
54
|
+
// create new layer
|
|
55
|
+
for (let key in obj) {
|
|
56
|
+
let newLayer = new UI.Layer(this._core, obj[key][0], obj[key][1]);
|
|
57
|
+
newLayerList.set(key, newLayer);
|
|
58
|
+
this._core.emit("afterAddLayer", newLayer);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return newLayerList;
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
private accessor _layerList: Map<string, UI.Layer<PlatformType>> = new Map();
|
|
65
|
+
|
|
66
|
+
get layerList() {
|
|
67
|
+
return this._layerList;
|
|
68
|
+
}
|
|
69
|
+
addLayer(name: string, z_index: number) {
|
|
70
|
+
this._core.emit("beforeAddLayer", name, z_index);
|
|
71
|
+
if (this._layerList.has(name)) throw `Layer ${name} already exist`;
|
|
72
|
+
let newLayer = new UI.Layer(this._core, name, z_index);
|
|
73
|
+
this._layerList.set(name, newLayer);
|
|
74
|
+
this._core.emit("afterAddLayer", newLayer);
|
|
75
|
+
}
|
|
76
|
+
getLayer(name: string): UI.Layer<PlatformType> | undefined {
|
|
77
|
+
return this.layerList.get(name);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// View Class
|
|
81
|
+
private _viewClassMap: Map<
|
|
82
|
+
string,
|
|
83
|
+
UI.ViewClass<Storage.Saveable<unknown>, PlatformType>
|
|
84
|
+
> = new Map();
|
|
85
|
+
// _activeViewList: [name: string, layer: string, instance: UI.View<unknown>][] =
|
|
86
|
+
// [];
|
|
87
|
+
|
|
88
|
+
registerView<PropType extends Storage.Saveable<PropType>>(
|
|
89
|
+
name: string,
|
|
90
|
+
cls: UI.ViewClass<PropType, PlatformType>
|
|
91
|
+
): void {
|
|
92
|
+
this._viewClassMap.set(name, cls);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// View
|
|
96
|
+
@Save("ui.nextViewId")
|
|
97
|
+
private accessor _nextViewId: number = 50;
|
|
98
|
+
|
|
99
|
+
@CustomSave(
|
|
100
|
+
"ui.viewMap",
|
|
101
|
+
function serializer(viewMap) {
|
|
102
|
+
let obj: Record<string, UI.View.Serialized> = {};
|
|
103
|
+
for (let [id, view] of viewMap) {
|
|
104
|
+
// 注意viewMap中的id是number,而obj中的id會自動轉成string
|
|
105
|
+
if (view.isSave) obj[id] = view.serialize();
|
|
106
|
+
}
|
|
107
|
+
return obj;
|
|
108
|
+
},
|
|
109
|
+
function deserializer(obj) {
|
|
110
|
+
let newViewMap = new Map<
|
|
111
|
+
number,
|
|
112
|
+
UI.View<Storage.Saveable<unknown>, PlatformType>
|
|
113
|
+
>();
|
|
114
|
+
for (let key in obj) {
|
|
115
|
+
let item = obj[key] as UI.View.Serialized;
|
|
116
|
+
let view = this._produceViewWithId(
|
|
117
|
+
item.name,
|
|
118
|
+
item.layer,
|
|
119
|
+
item.prop,
|
|
120
|
+
Number(key)
|
|
121
|
+
);
|
|
122
|
+
view.isSave = true;
|
|
123
|
+
newViewMap.set(Number(key), view);
|
|
124
|
+
}
|
|
125
|
+
return newViewMap;
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
private accessor _viewMap: Map<
|
|
129
|
+
number,
|
|
130
|
+
UI.View<Storage.Saveable<unknown>, PlatformType>
|
|
131
|
+
> = new Map();
|
|
132
|
+
|
|
133
|
+
getView(id: number): UI.View<Storage.Saveable<unknown>, PlatformType> | null {
|
|
134
|
+
return this._viewMap.get(id) ?? null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
createView<PropType extends Storage.Saveable<PropType>>(
|
|
138
|
+
name: string,
|
|
139
|
+
layer: string,
|
|
140
|
+
prop: PropType,
|
|
141
|
+
isSave: boolean
|
|
142
|
+
): UI.View<PropType, PlatformType> {
|
|
143
|
+
let id = this._nextViewId++;
|
|
144
|
+
let viewInstance = this._produceViewWithId(name, layer, prop, id);
|
|
145
|
+
this._core.debug.log(`creating view ${viewInstance.name}`);
|
|
146
|
+
viewInstance.isSave = isSave;
|
|
147
|
+
this._viewMap.set(id, viewInstance);
|
|
148
|
+
return viewInstance;
|
|
149
|
+
}
|
|
150
|
+
updateView<PropType extends Storage.Saveable<PropType>>(
|
|
151
|
+
viewInstance: UI.View<PropType, PlatformType>,
|
|
152
|
+
new_prop: PropType
|
|
153
|
+
) {
|
|
154
|
+
viewInstance.commit(new_prop);
|
|
155
|
+
}
|
|
156
|
+
destroyView(viewInstance: UI.View<Storage.Saveable<unknown>, PlatformType>) {
|
|
157
|
+
if (viewInstance.id != null) this._viewMap.delete(viewInstance.id);
|
|
158
|
+
viewInstance.destroy();
|
|
159
|
+
}
|
|
160
|
+
/**由調用者提供id,創建一個View,不會處理isSave,也不會更新viewMap */
|
|
161
|
+
private _produceViewWithId<PropType extends Storage.Saveable<PropType>>(
|
|
162
|
+
name: string,
|
|
163
|
+
layer: string,
|
|
164
|
+
prop: PropType,
|
|
165
|
+
id: number
|
|
166
|
+
): UI.View<PropType, PlatformType> {
|
|
167
|
+
if (!this._viewClassMap.get(name)) {
|
|
168
|
+
throw "要创建的View不存在";
|
|
169
|
+
}
|
|
170
|
+
let _ViewFactory = this._viewClassMap.get(name);
|
|
171
|
+
let viewInstance = new _ViewFactory!(layer, this._core) as UI.View<
|
|
172
|
+
PropType,
|
|
173
|
+
PlatformType
|
|
174
|
+
>;
|
|
175
|
+
viewInstance.id = id;
|
|
176
|
+
viewInstance.name = name;
|
|
177
|
+
viewInstance.create(prop);
|
|
178
|
+
this._core.debug.log(`producing view ${viewInstance.name}`);
|
|
179
|
+
return viewInstance;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@CustomSave(
|
|
183
|
+
"ui.routerMap",
|
|
184
|
+
function serializer(routerMap) {
|
|
185
|
+
let obj: Record<string, UI.Router.Serialized> = {};
|
|
186
|
+
for (let [key, value] of routerMap) {
|
|
187
|
+
if (!value.isSave) continue;
|
|
188
|
+
obj[key] = value.serialize();
|
|
189
|
+
}
|
|
190
|
+
return obj;
|
|
191
|
+
},
|
|
192
|
+
function deserializer(obj) {
|
|
193
|
+
let newRouterMap = new Map<string, UI.Router<PlatformType>>();
|
|
194
|
+
// reshow not save router
|
|
195
|
+
for (let [name, router] of this._routerMap) {
|
|
196
|
+
if (!router.isSave) {
|
|
197
|
+
if (router.length > 0) {
|
|
198
|
+
// TODO 因爲讀檔的時候會重置整個ui系統,所以要重新創建activeViewInstance 這裏感覺有點問題
|
|
199
|
+
router.activeViewInstance = this._core.ui.createView(
|
|
200
|
+
router.viewStack[0][0],
|
|
201
|
+
router.layer,
|
|
202
|
+
router.viewStack[0][1],
|
|
203
|
+
router.isSave
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
newRouterMap.set(name, router);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
// reshow save router
|
|
210
|
+
for (let key in obj) {
|
|
211
|
+
newRouterMap.set(key, UI.Router.deserialize(this, obj[key]));
|
|
212
|
+
}
|
|
213
|
+
return newRouterMap;
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
private accessor _routerMap: Map<string, UI.Router<PlatformType>> = new Map();
|
|
217
|
+
|
|
218
|
+
getRouter(tag: string) {
|
|
219
|
+
return this._routerMap.get(tag);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
addRouter(tag: string, layer: string, isSave: boolean = true) {
|
|
223
|
+
if (this._routerMap.has(tag))
|
|
224
|
+
throw `Route with tag [${tag}] already exist!`;
|
|
225
|
+
let router = new UI.Router(this, tag, layer, isSave);
|
|
226
|
+
this._routerMap.set(tag, router);
|
|
227
|
+
return router;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
getScreenSize() {
|
|
231
|
+
let [width, height] = this._core.platform.getScreenSize();
|
|
232
|
+
return { width, height };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* 根据 BasicUniversalProp 计算屏幕上的位置
|
|
236
|
+
* @param prop 包含 BasicUniversalProp 的 prop
|
|
237
|
+
* @param size (可选)图像的尺寸,若不指定,返回的anchor坐标和origin坐标一样
|
|
238
|
+
* @returns
|
|
239
|
+
*/
|
|
240
|
+
calcPosition(
|
|
241
|
+
prop: UI.BasicUniversalProp,
|
|
242
|
+
size?: UI.Size
|
|
243
|
+
): {
|
|
244
|
+
/** 锚点(算上偏移)的屏幕位置 */
|
|
245
|
+
anchor: UI.Coordinate;
|
|
246
|
+
/** 图像左上角的屏幕位置 */
|
|
247
|
+
origin: UI.Coordinate;
|
|
248
|
+
} {
|
|
249
|
+
let { width, height } = this.getScreenSize();
|
|
250
|
+
// 1. 确定 anchor
|
|
251
|
+
// 2. 通过 align 确定初始位置
|
|
252
|
+
// 3. offset
|
|
253
|
+
// 返回左上角的位置
|
|
254
|
+
let anchor_coord = {
|
|
255
|
+
x:
|
|
256
|
+
(width * ((prop.xalign ?? 0) + 1)) / 2 + // 根据 align 求出 anchor 位置
|
|
257
|
+
(prop.xoffset ?? 0), // offset
|
|
258
|
+
y:
|
|
259
|
+
(height * ((prop.yalign ?? 0) + 1)) / 2 + // 根据 align 求出 anchor 位置
|
|
260
|
+
(prop.yoffset ?? 0), // offset
|
|
261
|
+
};
|
|
262
|
+
let origin_coord = {
|
|
263
|
+
x: anchor_coord.x - (((prop.xanchor ?? 0) + 1) / 2) * (size?.width ?? 0),
|
|
264
|
+
y: anchor_coord.y - (((prop.yanchor ?? 0) + 1) / 2) * (size?.height ?? 0),
|
|
265
|
+
};
|
|
266
|
+
return {
|
|
267
|
+
anchor: anchor_coord,
|
|
268
|
+
origin: origin_coord,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export namespace UI {
|
|
274
|
+
export type ViewClass<
|
|
275
|
+
PropType extends Storage.Saveable<PropType>,
|
|
276
|
+
PlatformType extends Platform
|
|
277
|
+
> = {
|
|
278
|
+
new (layer: string, core: HZEngineCore<PlatformType>): View<
|
|
279
|
+
PropType,
|
|
280
|
+
PlatformType
|
|
281
|
+
>;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
export abstract class View<
|
|
285
|
+
PropType extends Storage.Saveable<PropType>,
|
|
286
|
+
PlatformType extends Platform = any
|
|
287
|
+
> {
|
|
288
|
+
public id: number | null = null;
|
|
289
|
+
public name: string | null = null;
|
|
290
|
+
public isSave: boolean = true;
|
|
291
|
+
private _prop: PropType | null = null;
|
|
292
|
+
public get prop(): PropType | null {
|
|
293
|
+
return this._prop;
|
|
294
|
+
}
|
|
295
|
+
private set prop(prop: PropType | null) {
|
|
296
|
+
this._prop = prop;
|
|
297
|
+
}
|
|
298
|
+
constructor(
|
|
299
|
+
public layer: string,
|
|
300
|
+
public core: HZEngineCore<PlatformType>
|
|
301
|
+
) {}
|
|
302
|
+
create(prop: PropType) {
|
|
303
|
+
this.prop = prop;
|
|
304
|
+
this.onCreate(prop);
|
|
305
|
+
}
|
|
306
|
+
protected abstract onCreate(prop: PropType): void;
|
|
307
|
+
commit(prop: PropType) {
|
|
308
|
+
this.prop = prop;
|
|
309
|
+
this.onCommit(prop);
|
|
310
|
+
}
|
|
311
|
+
protected abstract onCommit(prop: PropType): void;
|
|
312
|
+
destroy() {
|
|
313
|
+
this.onDestroy();
|
|
314
|
+
this.prop = null;
|
|
315
|
+
this.id = null;
|
|
316
|
+
}
|
|
317
|
+
protected abstract onDestroy(): void;
|
|
318
|
+
|
|
319
|
+
serialize(): View.Serialized {
|
|
320
|
+
if (this.name == null)
|
|
321
|
+
throw new Error("View name is null when serialize");
|
|
322
|
+
return {
|
|
323
|
+
name: this.name,
|
|
324
|
+
layer: this.layer,
|
|
325
|
+
prop: this.prop,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export namespace View {
|
|
331
|
+
export interface Serialized {
|
|
332
|
+
name: string;
|
|
333
|
+
layer: string;
|
|
334
|
+
prop: Storage.Saveable<unknown>;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
export interface BasicUniversalProp {
|
|
339
|
+
// 透明度 [0, 1]
|
|
340
|
+
alpha?: number;
|
|
341
|
+
// 锚点对齐位置 [0, 1]; 在不指定的情况下,默认位于屏幕中心
|
|
342
|
+
xalign?: number;
|
|
343
|
+
yalign?: number;
|
|
344
|
+
// 锚点相对图像位置 [0, 1]; 在不指定的情况下,以图像中心作为锚点
|
|
345
|
+
xanchor?: number;
|
|
346
|
+
yanchor?: number;
|
|
347
|
+
// px; 不指定就是不偏移
|
|
348
|
+
xoffset?: number;
|
|
349
|
+
yoffset?: number;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// export function getScreenSize(): Size {
|
|
353
|
+
// let [width, height] =
|
|
354
|
+
// return {
|
|
355
|
+
// width,
|
|
356
|
+
// height,
|
|
357
|
+
// };
|
|
358
|
+
// }
|
|
359
|
+
|
|
360
|
+
export interface Message {
|
|
361
|
+
who: string;
|
|
362
|
+
what: string;
|
|
363
|
+
}
|
|
364
|
+
export abstract class MessageView<PlatformType extends Platform> extends View<
|
|
365
|
+
Message,
|
|
366
|
+
PlatformType
|
|
367
|
+
> {}
|
|
368
|
+
|
|
369
|
+
export interface MenuItemData {
|
|
370
|
+
text: string;
|
|
371
|
+
position: [path: string, index: number];
|
|
372
|
+
enable_js_expression?: string;
|
|
373
|
+
}
|
|
374
|
+
export type MenuViewProp = {
|
|
375
|
+
itemList: MenuItemData[];
|
|
376
|
+
};
|
|
377
|
+
export abstract class MenuView<PlatformType extends Platform> extends View<
|
|
378
|
+
MenuViewProp,
|
|
379
|
+
PlatformType
|
|
380
|
+
> {}
|
|
381
|
+
|
|
382
|
+
export type Coordinate = { x: number; y: number };
|
|
383
|
+
export type Size = { width: number; height: number };
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 立绘/道具等显示在`fg`layer上的图片View
|
|
387
|
+
*/
|
|
388
|
+
export type FgImgViewProp = {
|
|
389
|
+
imgPath: string;
|
|
390
|
+
offset: Coordinate;
|
|
391
|
+
size: Size;
|
|
392
|
+
};
|
|
393
|
+
export abstract class FgImgView<PlatformType extends Platform> extends View<
|
|
394
|
+
FgImgViewProp,
|
|
395
|
+
PlatformType
|
|
396
|
+
> {}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* cg等显示在`bg`layer上的图片View
|
|
400
|
+
*/
|
|
401
|
+
export type BgImgViewProp = {
|
|
402
|
+
imgPath: string;
|
|
403
|
+
offset: Coordinate;
|
|
404
|
+
size: Size;
|
|
405
|
+
};
|
|
406
|
+
export abstract class BgImgView<PlatformType extends Platform> extends View<
|
|
407
|
+
FgImgViewProp,
|
|
408
|
+
PlatformType
|
|
409
|
+
> {}
|
|
410
|
+
|
|
411
|
+
export class Layer<PlatformType extends Platform> {
|
|
412
|
+
widgetFactory: ReturnType<PlatformType["createUILayer"]>;
|
|
413
|
+
constructor(
|
|
414
|
+
public _core: HZEngineCore<PlatformType>,
|
|
415
|
+
public name: string,
|
|
416
|
+
public z_index: number
|
|
417
|
+
) {
|
|
418
|
+
// this.widgetFactory = hmUI.createWidget(
|
|
419
|
+
// (hmUI.widget as any).VIEW_CONTAINER,
|
|
420
|
+
// {
|
|
421
|
+
// scroll_enable: 0,
|
|
422
|
+
// z_index,
|
|
423
|
+
// }
|
|
424
|
+
// ) as unknown as Layer.WidgetFactory;
|
|
425
|
+
this.widgetFactory = _core.platform.createUILayer({
|
|
426
|
+
z_index,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
destroy() {
|
|
430
|
+
// hmUI.deleteWidget(this.widgetFactory as any);
|
|
431
|
+
this._core.platform.deleteUILayer(this.widgetFactory);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
export namespace Layer {
|
|
435
|
+
// export interface WidgetFactory {
|
|
436
|
+
// createWidget(widgetType: number, option: Record<string, any>): any;
|
|
437
|
+
// deleteWidget(widget: any): void;
|
|
438
|
+
// }
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
export class Router<PlatformType extends Platform> {
|
|
442
|
+
constructor(
|
|
443
|
+
private _ui: UI<PlatformType>,
|
|
444
|
+
public tag: string,
|
|
445
|
+
public layer: string,
|
|
446
|
+
public isSave = true
|
|
447
|
+
) {}
|
|
448
|
+
serialize(): Router.Serialized {
|
|
449
|
+
return {
|
|
450
|
+
tag: this.tag,
|
|
451
|
+
layer: this.layer,
|
|
452
|
+
isSave: this.isSave,
|
|
453
|
+
viewStack: this.viewStack,
|
|
454
|
+
activeViewId: this.activeViewInstance?.id ?? null,
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
defaultRouteStrategy: Router.RouteStrategy = {
|
|
458
|
+
destroy: (viewInstance, ui) => {
|
|
459
|
+
this._ui._core.debug.log(`destroy view ${viewInstance.name}`);
|
|
460
|
+
ui.destroyView(viewInstance);
|
|
461
|
+
},
|
|
462
|
+
create: (viewName, layer, prop, ui, isSave) => {
|
|
463
|
+
this._ui._core.debug.log(`create view ${viewName}`);
|
|
464
|
+
return ui.createView(viewName, layer, prop, isSave);
|
|
465
|
+
},
|
|
466
|
+
update: (viewInstance, prop, ui) => {
|
|
467
|
+
this._ui._core.debug.log(`update view ${viewInstance.name}`);
|
|
468
|
+
ui.updateView(viewInstance, prop);
|
|
469
|
+
},
|
|
470
|
+
};
|
|
471
|
+
static deserialize<PlatformType extends Platform>(
|
|
472
|
+
ui: UI<PlatformType>,
|
|
473
|
+
data: Router.Serialized
|
|
474
|
+
) {
|
|
475
|
+
let router = new Router(ui, data.tag, data.layer, data.isSave);
|
|
476
|
+
router.viewStack = data.viewStack;
|
|
477
|
+
if (data.activeViewId != null) {
|
|
478
|
+
let viewInstance = ui.getView(data.activeViewId);
|
|
479
|
+
if (!viewInstance)
|
|
480
|
+
throw `View [${data.activeViewId}] not found when deserialize`;
|
|
481
|
+
router.activeViewInstance = viewInstance;
|
|
482
|
+
}
|
|
483
|
+
return router;
|
|
484
|
+
}
|
|
485
|
+
viewStack: [view_name: string, prop: Storage.Saveable<unknown>][] = [];
|
|
486
|
+
get length() {
|
|
487
|
+
return this.viewStack.length;
|
|
488
|
+
}
|
|
489
|
+
activeViewInstance: View<Storage.Saveable<unknown>, PlatformType> | null =
|
|
490
|
+
null;
|
|
491
|
+
push<T extends Storage.Saveable<T>>(
|
|
492
|
+
view_name: string,
|
|
493
|
+
prop: T,
|
|
494
|
+
strategy?: Router.RouteStrategy
|
|
495
|
+
) {
|
|
496
|
+
if (this.activeViewInstance) {
|
|
497
|
+
// this._ui.destroyView(this.activeViewInstance);
|
|
498
|
+
// (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
|
|
499
|
+
// this.activeViewInstance,
|
|
500
|
+
// this._ui
|
|
501
|
+
// );
|
|
502
|
+
if (strategy?.destroy) {
|
|
503
|
+
strategy.destroy(this.activeViewInstance, this._ui);
|
|
504
|
+
} else {
|
|
505
|
+
this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
|
|
506
|
+
}
|
|
507
|
+
this.activeViewInstance = null;
|
|
508
|
+
}
|
|
509
|
+
let layerInstance = this._ui.getLayer(this.layer);
|
|
510
|
+
if (!layerInstance) throw `Layer [${this.layer}] not found`;
|
|
511
|
+
// this.activeViewInstance = (
|
|
512
|
+
// strategy?.create ?? this.defaultRouteStrategy.create!
|
|
513
|
+
// )(view_name, this.layer, prop, this._ui, this.isSave);
|
|
514
|
+
if (strategy?.create) {
|
|
515
|
+
this.activeViewInstance = strategy.create(
|
|
516
|
+
view_name,
|
|
517
|
+
this.layer,
|
|
518
|
+
prop,
|
|
519
|
+
this._ui,
|
|
520
|
+
this.isSave
|
|
521
|
+
);
|
|
522
|
+
} else {
|
|
523
|
+
this.activeViewInstance = this.defaultRouteStrategy.create!(
|
|
524
|
+
view_name,
|
|
525
|
+
this.layer,
|
|
526
|
+
prop,
|
|
527
|
+
this._ui,
|
|
528
|
+
this.isSave
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
this.viewStack.push([view_name, prop]);
|
|
532
|
+
}
|
|
533
|
+
pop<T extends Storage.Saveable<T>>(
|
|
534
|
+
back_prop?: T,
|
|
535
|
+
strategy?: Router.RouteStrategy
|
|
536
|
+
) {
|
|
537
|
+
if (this.activeViewInstance) {
|
|
538
|
+
// this._ui.destroyView(this.activeViewInstance);
|
|
539
|
+
// (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
|
|
540
|
+
// this.activeViewInstance,
|
|
541
|
+
// this._ui
|
|
542
|
+
// );
|
|
543
|
+
if (strategy?.destroy) {
|
|
544
|
+
strategy.destroy(this.activeViewInstance, this._ui);
|
|
545
|
+
} else {
|
|
546
|
+
this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
|
|
547
|
+
}
|
|
548
|
+
this.activeViewInstance = null;
|
|
549
|
+
}
|
|
550
|
+
this.viewStack.pop();
|
|
551
|
+
|
|
552
|
+
if (this.viewStack.length) {
|
|
553
|
+
let backViewInfo = this.viewStack[this.viewStack.length - 1];
|
|
554
|
+
let layerInstance = this._ui.getLayer(this.layer);
|
|
555
|
+
if (!layerInstance) throw `Layer [${this.layer}] not found`;
|
|
556
|
+
// this.activeViewInstance = (
|
|
557
|
+
// strategy?.create ?? this.defaultRouteStrategy.create!
|
|
558
|
+
// )(
|
|
559
|
+
// backViewInfo[0],
|
|
560
|
+
// this.layer,
|
|
561
|
+
// back_prop ?? backViewInfo[1],
|
|
562
|
+
// this._ui,
|
|
563
|
+
// this.isSave
|
|
564
|
+
// );
|
|
565
|
+
if (strategy?.create) {
|
|
566
|
+
this.activeViewInstance = strategy.create(
|
|
567
|
+
backViewInfo[0],
|
|
568
|
+
this.layer,
|
|
569
|
+
back_prop ?? backViewInfo[1],
|
|
570
|
+
this._ui,
|
|
571
|
+
this.isSave
|
|
572
|
+
);
|
|
573
|
+
} else {
|
|
574
|
+
this.activeViewInstance = this.defaultRouteStrategy.create!(
|
|
575
|
+
backViewInfo[0],
|
|
576
|
+
this.layer,
|
|
577
|
+
back_prop ?? backViewInfo[1],
|
|
578
|
+
this._ui,
|
|
579
|
+
this.isSave
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
replace<T extends Storage.Saveable<T>>(
|
|
585
|
+
view_name: string,
|
|
586
|
+
prop: T,
|
|
587
|
+
strategy?: Router.RouteStrategy
|
|
588
|
+
) {
|
|
589
|
+
if (this.activeViewInstance) {
|
|
590
|
+
// this._ui.destroyView(this.activeViewInstance);
|
|
591
|
+
// (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
|
|
592
|
+
// this.activeViewInstance,
|
|
593
|
+
// this._ui
|
|
594
|
+
// );
|
|
595
|
+
if (strategy?.destroy) {
|
|
596
|
+
strategy.destroy(this.activeViewInstance, this._ui);
|
|
597
|
+
} else {
|
|
598
|
+
this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
|
|
599
|
+
}
|
|
600
|
+
this.activeViewInstance = null;
|
|
601
|
+
}
|
|
602
|
+
this.viewStack.pop();
|
|
603
|
+
|
|
604
|
+
let layerInstance = this._ui.getLayer(this.layer);
|
|
605
|
+
if (!layerInstance) throw `Layer [${this.layer}] not found`;
|
|
606
|
+
// this.activeViewInstance = (
|
|
607
|
+
// strategy?.create ?? this.defaultRouteStrategy.create!
|
|
608
|
+
// )(view_name, this.layer, prop, this._ui, this.isSave);
|
|
609
|
+
if (strategy?.create) {
|
|
610
|
+
this.activeViewInstance = strategy.create(
|
|
611
|
+
view_name,
|
|
612
|
+
this.layer,
|
|
613
|
+
prop,
|
|
614
|
+
this._ui,
|
|
615
|
+
this.isSave
|
|
616
|
+
);
|
|
617
|
+
} else {
|
|
618
|
+
this.activeViewInstance = this.defaultRouteStrategy.create!(
|
|
619
|
+
view_name,
|
|
620
|
+
this.layer,
|
|
621
|
+
prop,
|
|
622
|
+
this._ui,
|
|
623
|
+
this.isSave
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
this.viewStack.push([view_name, prop]);
|
|
627
|
+
}
|
|
628
|
+
update<T extends Storage.Saveable<T>>(
|
|
629
|
+
prop: T,
|
|
630
|
+
strategy?: Router.RouteStrategy
|
|
631
|
+
) {
|
|
632
|
+
if (!this.activeViewInstance)
|
|
633
|
+
throw `Update View but activeViewInstance is null`;
|
|
634
|
+
this.viewStack[this.viewStack.length - 1][1] = prop;
|
|
635
|
+
// (strategy?.update ?? this.defaultRouteStrategy.update!)(
|
|
636
|
+
// this.activeViewInstance,
|
|
637
|
+
// prop,
|
|
638
|
+
// this._ui
|
|
639
|
+
// );
|
|
640
|
+
if (strategy?.update) {
|
|
641
|
+
strategy.update(this.activeViewInstance, prop, this._ui);
|
|
642
|
+
} else {
|
|
643
|
+
this.defaultRouteStrategy.update!(
|
|
644
|
+
this.activeViewInstance,
|
|
645
|
+
prop,
|
|
646
|
+
this._ui
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
clear(strategy?: Router.RouteStrategy) {
|
|
651
|
+
if (this.activeViewInstance) {
|
|
652
|
+
// (strategy?.destroy ?? this.defaultRouteStrategy.destroy!)(
|
|
653
|
+
// this.activeViewInstance,
|
|
654
|
+
// this._ui
|
|
655
|
+
// );
|
|
656
|
+
if (strategy?.destroy) {
|
|
657
|
+
strategy.destroy(this.activeViewInstance, this._ui);
|
|
658
|
+
} else {
|
|
659
|
+
this.defaultRouteStrategy.destroy!(this.activeViewInstance, this._ui);
|
|
660
|
+
}
|
|
661
|
+
this.activeViewInstance = null;
|
|
662
|
+
}
|
|
663
|
+
this.viewStack = [];
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
export namespace Router {
|
|
667
|
+
export interface Serialized {
|
|
668
|
+
tag: string;
|
|
669
|
+
layer: string;
|
|
670
|
+
isSave: boolean;
|
|
671
|
+
viewStack: [view_name: string, prop: Storage.Saveable<unknown>][];
|
|
672
|
+
activeViewId: number | null;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// 实现自定义路由策略,允许接管Router对View的创建和销毁,实现例如动画等功能
|
|
676
|
+
export interface RouteStrategy<
|
|
677
|
+
PropType extends Storage.Saveable<PropType> = Storage.Saveable<unknown>,
|
|
678
|
+
PlatformType extends Platform = any
|
|
679
|
+
> {
|
|
680
|
+
destroy?(
|
|
681
|
+
viewInstance: View<PropType, PlatformType>,
|
|
682
|
+
ui: UI<PlatformType>
|
|
683
|
+
): void;
|
|
684
|
+
create?(
|
|
685
|
+
viewName: string,
|
|
686
|
+
layer: string,
|
|
687
|
+
prop: PropType,
|
|
688
|
+
ui: UI<PlatformType>,
|
|
689
|
+
isSave: boolean
|
|
690
|
+
): View<Storage.Saveable<PropType>, PlatformType>;
|
|
691
|
+
|
|
692
|
+
update?(
|
|
693
|
+
viewInstance: View<PropType, PlatformType>,
|
|
694
|
+
prop: PropType,
|
|
695
|
+
ui: UI<PlatformType>
|
|
696
|
+
): void;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|