@vyr/engine 0.0.33 → 0.0.35

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.
Files changed (137) hide show
  1. package/package.json +6 -3
  2. package/src/ArrayUtils.ts +63 -65
  3. package/src/AsyncTask.ts +67 -71
  4. package/src/Category.ts +69 -86
  5. package/src/Color.ts +3 -111
  6. package/src/Engine.ts +12 -24
  7. package/src/Executor.ts +109 -0
  8. package/src/Generate.ts +23 -40
  9. package/src/InputSystem.ts +106 -108
  10. package/src/Listener.ts +58 -59
  11. package/src/ObjectPool.ts +83 -84
  12. package/src/ObjectUtils.ts +97 -49
  13. package/src/Scriptable.ts +82 -0
  14. package/src/Serialization.ts +4 -6
  15. package/src/Traverser.ts +41 -39
  16. package/src/actor/Actor.ts +23 -27
  17. package/src/actor/AnimationUnitActor.ts +22 -36
  18. package/src/actor/DivActor.ts +21 -41
  19. package/src/actor/FragmentActor.ts +1 -5
  20. package/src/actor/HTMLActor.ts +81 -0
  21. package/src/actor/HTMLServiceActor.ts +49 -0
  22. package/src/actor/{HTMTransformControllerActor.ts → HTMLTransformControllerActor.ts} +178 -71
  23. package/src/actor/InputActor.ts +50 -0
  24. package/src/actor/TextActor.ts +51 -0
  25. package/src/actor/index.ts +6 -5
  26. package/src/asset/Asset.ts +23 -68
  27. package/src/asset/AssetGraph.ts +21 -28
  28. package/src/descriptor/AnimationUnit.ts +81 -0
  29. package/src/descriptor/Camera.ts +12 -0
  30. package/src/descriptor/Controller.ts +6 -0
  31. package/src/descriptor/Descriptor.ts +133 -113
  32. package/src/descriptor/Div.ts +29 -0
  33. package/src/descriptor/HTML.ts +22 -0
  34. package/src/descriptor/HTMLService.ts +42 -0
  35. package/src/descriptor/HTMLTransformController.ts +67 -0
  36. package/src/descriptor/Input.ts +29 -0
  37. package/src/descriptor/Interaction.ts +80 -0
  38. package/src/descriptor/Node.ts +98 -0
  39. package/src/descriptor/Scene.ts +110 -0
  40. package/src/descriptor/Service.ts +11 -0
  41. package/src/descriptor/Store.ts +136 -0
  42. package/src/descriptor/Text.ts +36 -0
  43. package/src/descriptor/index.ts +14 -15
  44. package/src/graphics/Collection.ts +1 -5
  45. package/src/graphics/Compilation.ts +15 -19
  46. package/src/graphics/Graphics.ts +41 -54
  47. package/src/graphics/Observer.ts +6 -14
  48. package/src/graphics/Unit.ts +3 -9
  49. package/src/graphics/VariableProxy.ts +11 -15
  50. package/src/index.ts +5 -5
  51. package/src/interpreter/AnimationUnitInterpreter.ts +7 -9
  52. package/src/interpreter/DivInterpreter.ts +10 -13
  53. package/src/interpreter/FragmentInterpreter.ts +2 -6
  54. package/src/interpreter/HTMLServiceInterpreter.ts +25 -15
  55. package/src/interpreter/HTMLTransformControllerInterpreter.ts +9 -12
  56. package/src/interpreter/InputInterpreter.ts +41 -0
  57. package/src/interpreter/Interpreter.ts +3 -4
  58. package/src/interpreter/SceneInterpreter.ts +93 -0
  59. package/src/interpreter/ServiceInterpreter.ts +8 -15
  60. package/src/interpreter/StoreInterpreter.ts +7 -0
  61. package/src/interpreter/TextInterpreter.ts +41 -0
  62. package/src/interpreter/index.ts +5 -7
  63. package/src/locale/Language.ts +1 -5
  64. package/src/locale/LanguageProvider.ts +164 -21
  65. package/src/math/Euler.ts +2 -5
  66. package/src/math/Matrix4.ts +2 -4
  67. package/src/math/Quaternion.ts +2 -4
  68. package/src/math/Vector2.ts +4 -4
  69. package/src/math/Vector3.ts +2 -4
  70. package/src/math/utils.ts +1 -5
  71. package/src/schema/AnimationUnit.ts +68 -0
  72. package/src/schema/Asset.ts +13 -0
  73. package/src/schema/Descriptor.ts +41 -0
  74. package/src/schema/HTML.ts +261 -0
  75. package/src/schema/Interaction.ts +50 -0
  76. package/src/schema/Scene.ts +138 -0
  77. package/src/schema/Store.ts +8 -0
  78. package/src/schema/index.ts +7 -0
  79. package/src/scripts/ConditionScriptable.ts +196 -0
  80. package/src/scripts/FetchScriptable.ts +51 -0
  81. package/src/scripts/FindScriptable.ts +23 -0
  82. package/src/scripts/InvokeScriptable.ts +13 -0
  83. package/src/scripts/SwitchSceneScriptable.ts +18 -0
  84. package/src/scripts/UpdateScriptable.ts +60 -0
  85. package/src/scripts/index.ts +6 -0
  86. package/src/utils/AssetProvider.ts +4 -77
  87. package/src/utils/DOM.ts +37 -0
  88. package/src/utils/HTML.ts +5 -0
  89. package/src/utils/Service.ts +40 -0
  90. package/src/utils/constants.ts +1 -5
  91. package/src/utils/http.ts +2 -21
  92. package/src/utils/index.ts +3 -1
  93. package/src/actor/HTMActor.ts +0 -169
  94. package/src/actor/HTMServiceActor.ts +0 -57
  95. package/src/actor/StyleActor.ts +0 -96
  96. package/src/descriptor/AnimationUnitDescriptor.ts +0 -65
  97. package/src/descriptor/CameraDescriptor.ts +0 -12
  98. package/src/descriptor/ControllerDescriptor.ts +0 -16
  99. package/src/descriptor/DatasetDescriptor.ts +0 -90
  100. package/src/descriptor/DivDescriptor.ts +0 -18
  101. package/src/descriptor/DynamicDescriptor.ts +0 -27
  102. package/src/descriptor/HTMLDescriptor.ts +0 -87
  103. package/src/descriptor/HTMLServiceDescriptor.ts +0 -19
  104. package/src/descriptor/HTMLTransformControllerDescriptor.ts +0 -34
  105. package/src/descriptor/NodeDescriptor.ts +0 -32
  106. package/src/descriptor/PrefabDescriptor.ts +0 -53
  107. package/src/descriptor/PrefabInstanceDescriptor.ts +0 -32
  108. package/src/descriptor/ServiceDescriptor.ts +0 -32
  109. package/src/descriptor/ServiceSchedulerDescriptor.ts +0 -32
  110. package/src/descriptor/StyleDescriptor.ts +0 -213
  111. package/src/interaction/InteractionDescriptor.ts +0 -96
  112. package/src/interaction/InteractionExecutor.ts +0 -84
  113. package/src/interaction/Scriptable.ts +0 -44
  114. package/src/interaction/index.ts +0 -3
  115. package/src/interpreter/DatasetInterpreter.ts +0 -11
  116. package/src/interpreter/DynamicInterpreter.ts +0 -207
  117. package/src/interpreter/PrefaInterpreter.ts +0 -11
  118. package/src/interpreter/PrefabInstanceInterpreter.ts +0 -12
  119. package/src/interpreter/ServiceSchedulerInterpreter.ts +0 -42
  120. package/src/interpreter/StyleInterpreter.ts +0 -66
  121. package/src/preset/execute/dataset/index.ts +0 -1
  122. package/src/preset/execute/dataset/update.ts +0 -51
  123. package/src/preset/execute/graphics/index.ts +0 -1
  124. package/src/preset/execute/graphics/invoke.ts +0 -48
  125. package/src/preset/execute/index.ts +0 -4
  126. package/src/preset/execute/net/http.ts +0 -52
  127. package/src/preset/execute/net/index.ts +0 -1
  128. package/src/preset/execute/scheduler/index.ts +0 -1
  129. package/src/preset/execute/scheduler/switch.ts +0 -46
  130. package/src/preset/index.ts +0 -7
  131. package/src/preset/interaction/graphics/index.ts +0 -1
  132. package/src/preset/interaction/graphics/invoke.ts +0 -27
  133. package/src/preset/interaction/index.ts +0 -2
  134. package/src/preset/interaction/scheduler/index.ts +0 -1
  135. package/src/preset/interaction/scheduler/switch.ts +0 -27
  136. package/src/setup/index.ts +0 -17
  137. package/src/utils/compile.ts +0 -50
package/src/ObjectPool.ts CHANGED
@@ -1,84 +1,83 @@
1
- import { Generate } from "./Generate"
2
-
3
- const privateState = {
4
- instances: new Map<string, WeakRef<ObjectPool>>(),
5
- freeWatcher: [] as Array<(uuid: string) => void>,
6
- monitoring: () => {
7
- let currentIndex = 0
8
-
9
- const loop = () => {
10
- setTimeout(loop, 5000)
11
-
12
- const uuids = [...privateState.instances.keys()]
13
- const total = uuids.length
14
-
15
- if (currentIndex >= total) currentIndex = 0
16
-
17
- let count = 0
18
- let startIndex = currentIndex
19
- const startTime = performance.now()
20
-
21
- while (count < 500 && performance.now() - startTime < 5) {
22
- if (startIndex >= total) break
23
- count++
24
- const uuid = uuids[startIndex++]
25
- ObjectPool.get(uuid) === null ? destroyInstance(uuid) : currentIndex++
26
- }
27
- }
28
-
29
- loop()
30
- },
31
- }
32
-
33
- const listenInstance = (type: 'free', watcher: (uuid: string) => void) => {
34
- switch (type) {
35
- case 'free':
36
- privateState.freeWatcher.push(watcher)
37
- break;
38
- default:
39
- break;
40
- }
41
- }
42
-
43
- /**将实例销毁并回收相关资源 */
44
- const destroyInstance = (uuid: string) => {
45
- const instance = privateState.instances.get(uuid)
46
- if (instance === undefined) return
47
- for (const free of privateState.freeWatcher) free(uuid)
48
- privateState.instances.delete(uuid)
49
- }
50
-
51
- /**对象池
52
- *
53
- * 以`uuid`为标识,同一个`uuid`只会存在一个实例
54
- */
55
- class ObjectPool {
56
- /**获取缓存实例 */
57
- static get<T extends ObjectPool | null = ObjectPool | null>(uuid: string) {
58
- const instance = privateState.instances.get(uuid)
59
- if (instance === undefined) return null as T
60
- return (instance.deref() ?? null) as T
61
- }
62
-
63
- readonly uuid!: string
64
- /**
65
- * @param uuid 实例的唯一标识
66
- */
67
- constructor(uuid = Generate.uuid()) {
68
- const instance = ObjectPool.get(uuid)
69
- if (instance !== null) {
70
- instance.beenInstantiated(instance)
71
- return instance
72
- }
73
- this.uuid = uuid
74
-
75
- privateState.instances.set(uuid, new WeakRef(this))
76
- }
77
-
78
- /**若在初始化时发现已存在相同uuid的实例,则会调用该方法 */
79
- protected beenInstantiated(instance: ObjectPool) { }
80
- }
81
-
82
- privateState.monitoring()
83
-
84
- export { listenInstance, destroyInstance, ObjectPool }
1
+ import { Generate } from "./Generate"
2
+
3
+ const privateState = {
4
+ instances: new Map<string, WeakRef<ObjectPool>>(),
5
+ freeWatcher: [] as Array<(uuid: string) => void>,
6
+ monitoring: () => {
7
+ let currentIndex = 0
8
+
9
+ const loop = () => {
10
+ setTimeout(loop, 5000)
11
+
12
+ const uuids = [...privateState.instances.keys()]
13
+ const total = uuids.length
14
+
15
+ if (currentIndex >= total) currentIndex = 0
16
+
17
+ let count = 0
18
+ let startIndex = currentIndex
19
+ const startTime = performance.now()
20
+
21
+ while (count < 500 && performance.now() - startTime < 5) {
22
+ if (startIndex >= total) break
23
+ count++
24
+ const uuid = uuids[startIndex++]
25
+ ObjectPool.get(uuid) === null ? destroyInstance(uuid) : currentIndex++
26
+ }
27
+ }
28
+
29
+ loop()
30
+ },
31
+ }
32
+
33
+ export const listenInstance = (type: 'free', watcher: (uuid: string) => void) => {
34
+ switch (type) {
35
+ case 'free':
36
+ privateState.freeWatcher.push(watcher)
37
+ break;
38
+ default:
39
+ break;
40
+ }
41
+ }
42
+
43
+ /**将实例销毁并回收相关资源 */
44
+ export const destroyInstance = (uuid: string) => {
45
+ const instance = privateState.instances.get(uuid)
46
+ if (instance === undefined) return
47
+ for (const free of privateState.freeWatcher) free(uuid)
48
+ privateState.instances.delete(uuid)
49
+ }
50
+
51
+ /**对象池
52
+ *
53
+ */
54
+ export class ObjectPool {
55
+ /**获取缓存实例 */
56
+ static get<T extends ObjectPool | null = ObjectPool | null>(uuid: string) {
57
+ const instance = privateState.instances.get(uuid)
58
+ if (instance === undefined) return null as T
59
+ return (instance.deref() ?? null) as T
60
+ }
61
+
62
+ /**节点标识
63
+ *
64
+ * `uuid` 必须保证全局唯一,使用标准的 uuid v4 算法
65
+ */
66
+ readonly uuid!: string
67
+
68
+ constructor(uuid = Generate.uuid()) {
69
+ const instance = ObjectPool.get(uuid)
70
+ if (instance !== null) {
71
+ instance.beenInstantiated(instance)
72
+ return instance
73
+ }
74
+ this.uuid = uuid
75
+
76
+ privateState.instances.set(uuid, new WeakRef(this))
77
+ }
78
+
79
+ /**若在初始化时发现已存在相同uuid的实例,则会调用该方法 */
80
+ protected beenInstantiated(instance: ObjectPool) { }
81
+ }
82
+
83
+ privateState.monitoring()
@@ -1,49 +1,97 @@
1
- import { ArrayUtils } from "./ArrayUtils"
2
- class ObjectUtils {
3
-
4
- static equals(left: { [k: string]: any }, right: { [k: string]: any }, ignore: string[] = []) {
5
- const keys = Object.keys(left)
6
- const rkeys = Object.keys(right)
7
- if (keys.length !== rkeys.length) return false
8
- const rset = new Set(rkeys)
9
- for (const key of keys) {
10
- if (rset.has(key) === false) return false
11
- if (ignore.includes(key)) continue
12
-
13
- const value = left[key]
14
- const t = typeof value
15
-
16
- if (t === 'string' || t === 'boolean' || t === 'number' || t === 'bigint' || t === 'undefined' || t === 'symbol' || t === null) {
17
- if (value !== right[key]) return false
18
- }
19
-
20
- if (Array.isArray(value)) {
21
- if (ArrayUtils.equals(value, right[key], ignore) == false) return false
22
- continue
23
- }
24
-
25
- if (t === 'object') {
26
- if (ObjectUtils.equals(value, right[key], ignore) === false) return false
27
- continue
28
- }
29
- }
30
-
31
- return true
32
- }
33
-
34
- static parseKey(key: string) {
35
- return key.split('.').filter(clip => clip !== '')
36
- }
37
-
38
- static getValueByKey(target: { [k: string]: any }, key: string) {
39
- if (!target) return
40
- const keys = this.parseKey(key)
41
- for (const key of keys) {
42
- target = target[key]
43
- if (target === undefined) return
44
- }
45
- return target
46
- }
47
- }
48
-
49
- export { ObjectUtils }
1
+ import { ArrayUtils } from "./ArrayUtils"
2
+
3
+ interface BaseObject {
4
+ [k: string]: any
5
+ }
6
+
7
+ export class ObjectUtils {
8
+
9
+ static equals(left: BaseObject, right: BaseObject, ignore: string[] = []) {
10
+ const keys = Object.keys(left)
11
+ const rkeys = Object.keys(right)
12
+ if (keys.length !== rkeys.length) return false
13
+ const rset = new Set(rkeys)
14
+ for (const key of keys) {
15
+ if (rset.has(key) === false) return false
16
+ if (ignore.includes(key)) continue
17
+
18
+ const value = left[key]
19
+ const t = typeof value
20
+
21
+ if (t === 'string' || t === 'boolean' || t === 'number' || t === 'bigint' || t === 'undefined' || t === 'symbol' || t === null) {
22
+ if (value !== right[key]) return false
23
+ }
24
+
25
+ if (Array.isArray(value)) {
26
+ if (ArrayUtils.equals(value, right[key], ignore) == false) return false
27
+ continue
28
+ }
29
+
30
+ if (t === 'object') {
31
+ if (ObjectUtils.equals(value, right[key], ignore) === false) return false
32
+ continue
33
+ }
34
+ }
35
+
36
+ return true
37
+ }
38
+
39
+ static isObject(obj?: BaseObject | null) {
40
+ return obj !== null && typeof obj === 'object'
41
+ }
42
+
43
+ static getValueByKey(target: BaseObject, propertyPath: string) {
44
+ let value
45
+ this.nextByPropertyPath(target, propertyPath, (property, key) => {
46
+ value = property[key]
47
+ })
48
+ return value
49
+ }
50
+
51
+ static doArrayKey(target: BaseObject, propertyPath: string) {
52
+ const [name, ...indexClips] = propertyPath.split('[')
53
+ const max = indexClips.length - 1
54
+
55
+ target = target[name]
56
+ let key = ''
57
+ for (let i = 0; i <= max; i++) {
58
+ key = indexClips[i].slice(0, -1)
59
+ if (i === max) break
60
+ target[key]
61
+ }
62
+
63
+ return {
64
+ target,
65
+ key,
66
+ }
67
+ }
68
+
69
+ static nextByPropertyPath(target: BaseObject, propertyPath: string, end: (property: BaseObject, key: string) => void) {
70
+ const keys = propertyPath.split('.')
71
+ const max = keys.length - 1
72
+ let property = target
73
+
74
+ for (let i = 0; i <= max; i++) {
75
+ const key = keys[i]
76
+
77
+ if (ObjectUtils.isObject(property) === false) break
78
+
79
+ if (key.endsWith(']')) {
80
+ const result = this.doArrayKey(property, key)
81
+ if (i === max) {
82
+ end(result.target, result.key)
83
+ break
84
+ }
85
+ property = result.target[result.key]
86
+
87
+ } else {
88
+ if (i === max) {
89
+ end(property, key)
90
+ break
91
+ }
92
+ property = property[key]
93
+ }
94
+ if (property === undefined) break
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,82 @@
1
+ import z from 'zod'
2
+ import { ObjectUtils } from './ObjectUtils'
3
+ import { Graphics } from "./graphics/Graphics"
4
+
5
+ export const scriptableInputSchame = z.object().catchall(z.any())
6
+
7
+ export type ScriptableInput = z.infer<typeof scriptableInputSchame>
8
+
9
+ export interface ScriptableArgs {
10
+ result: Map<string, any>,
11
+ previous: string
12
+ }
13
+
14
+ /**
15
+ * 可编程脚本(脚本不会在服务端实例化)
16
+ */
17
+ export class Scriptable {
18
+ private static defineCollection = new Map<string, typeof Scriptable>()
19
+ private static instanceCollection = new Map<string, Scriptable>()
20
+ static register(Define: typeof Scriptable) {
21
+ this.defineCollection.set(Define.id, Define)
22
+ }
23
+ static use(id: string) {
24
+ let instance = this.instanceCollection.get(id)
25
+ if (instance === undefined) {
26
+ const Define = this.defineCollection.get(id)
27
+ if (Define === undefined) return null
28
+ instance = new Define()
29
+ this.instanceCollection.set(id, instance)
30
+ }
31
+ return instance
32
+ }
33
+ static list() {
34
+ const values = this.defineCollection.values()
35
+ const options: { id: string, name: string }[] = []
36
+ for (const Define of values) {
37
+ options.push({ id: Define.id, name: Define.name })
38
+ }
39
+ return options
40
+ }
41
+ static get(id: string) {
42
+ return this.defineCollection.get(id) ?? null
43
+ }
44
+ static id = ''
45
+ static name = ''
46
+ static inputSchame: z.ZodObject | z.ZodUnion<readonly z.ZodType<any>[]> = scriptableInputSchame
47
+ static outputSchame?: z.ZodType | z.ZodUnion
48
+
49
+ readonly id: string
50
+ readonly name: string
51
+ readonly inputSchame
52
+ readonly outputSchame
53
+
54
+ constructor() {
55
+ this.id = (this.constructor as typeof Scriptable).id
56
+ this.name = (this.constructor as typeof Scriptable).name
57
+ this.inputSchame = (this.constructor as typeof Scriptable).inputSchame
58
+ this.outputSchame = (this.constructor as typeof Scriptable).outputSchame
59
+ }
60
+
61
+ /**脚本的准备事件,该方法在脚本被实例化后立即执行
62
+ *
63
+ * 一般在该事件中进行脚本的准备工作,如从服务端获取资源或数据
64
+ */
65
+ async ready() { }
66
+
67
+ aggregateResults(defaultValue: { [k: string]: any }, ids: string, args?: ScriptableArgs) {
68
+ const idClips = ids.split(',')
69
+
70
+ if (args === undefined) return defaultValue
71
+ for (const id of idClips) {
72
+ const value = args.result.get(id)
73
+ if (ObjectUtils.isObject(value)) {
74
+ Object.assign(defaultValue, value)
75
+ }
76
+ }
77
+
78
+ return defaultValue
79
+ }
80
+
81
+ execute(graphics: Graphics, trigger: string, input: ScriptableInput, args?: ScriptableArgs): any { }
82
+ }
@@ -1,8 +1,8 @@
1
- interface SerializationObject {
1
+ export interface SerializationObject {
2
2
  [k: string]: any
3
3
  }
4
4
 
5
- type DeserializationObject<T extends { [k: string]: any } = { [k: string]: any }> = {
5
+ export type DeserializationObject<T extends { [k: string]: any } = { [k: string]: any }> = {
6
6
  -readonly [K in keyof T as T[K] extends Function ? never : K]:
7
7
  T[K] extends Array<infer U>
8
8
  ? U extends { [k: string]: any }
@@ -31,7 +31,7 @@ const privateToJson = (key: string, value: any) => {
31
31
  return value
32
32
  }
33
33
 
34
- class Serialization {
34
+ export class Serialization {
35
35
 
36
36
  static stringify(obj: SerializationObject) {
37
37
  return JSON.stringify(obj, privateToStringify)
@@ -44,6 +44,4 @@ class Serialization {
44
44
  static deepClone<T extends any = any>(obj: SerializationObject) {
45
45
  return this.parse(this.stringify(obj)) as T
46
46
  }
47
- }
48
-
49
- export { SerializationObject, DeserializationObject, Serialization }
47
+ }
package/src/Traverser.ts CHANGED
@@ -1,39 +1,41 @@
1
- interface TraverseNode {
2
- children: TraverseNode[]
3
- }
4
- interface PreItem<T extends TraverseNode = TraverseNode> {
5
- parent: T | null
6
- des: T
7
- }
8
-
9
- /**遍历器 */
10
- class Traverser {
11
-
12
- /**前序遍历 */
13
- static pre<T extends TraverseNode = TraverseNode, D extends T | null = null>(descriptor: T, cb: (sub: T, parent: D) => void, defaultParent: D = null as D) {
14
- const whileQuaua: PreItem<T>[] = [{ parent: defaultParent, des: descriptor }]
15
-
16
- while (whileQuaua.length > 0) {
17
- const item = whileQuaua.pop() as PreItem<T>
18
- cb(item.des, item.parent as D)
19
- for (let i = item.des.children.length - 1; i >= 0; i--) {
20
- whileQuaua.push({ parent: item.des, des: item.des.children[i] as T })
21
- }
22
- }
23
- }
24
-
25
- /**前序遍历且可以终止 */
26
- static preTerminated<T extends TraverseNode = TraverseNode, D extends T | null = null>(descriptor: T, cb: (sub: T, parent: D) => true | void, defaultParent: D = null as D) {
27
- const whileQuaua: PreItem<T>[] = [{ parent: defaultParent, des: descriptor }]
28
-
29
- while (whileQuaua.length > 0) {
30
- const item = whileQuaua.pop() as PreItem<T>
31
- if (cb(item.des, item.parent as D) === true) continue
32
- for (let i = item.des.children.length - 1; i >= 0; i--) {
33
- whileQuaua.push({ parent: item.des, des: item.des.children[i] as T })
34
- }
35
- }
36
- }
37
- }
38
-
39
- export { Traverser }
1
+ export interface TraverseNode {
2
+ children: TraverseNode[]
3
+ }
4
+ export interface PreItem<T extends TraverseNode = TraverseNode> {
5
+ parent: T | null
6
+ des: T
7
+ }
8
+
9
+ /**遍历器 */
10
+ export class Traverser {
11
+
12
+ /**前序遍历 */
13
+ static pre<T extends TraverseNode = TraverseNode, D extends T | null = null>(descriptor: T, cb: (sub: T, parent: D) => void, defaultParent: D = null as D) {
14
+ const whileQuaua: PreItem<T>[] = [{ parent: defaultParent, des: descriptor }]
15
+
16
+ while (whileQuaua.length > 0) {
17
+ const item = whileQuaua.pop() as PreItem<T>
18
+ cb(item.des, item.parent as D)
19
+ const children = item.des.children
20
+ if (Array.isArray(children) === false) continue
21
+ for (let i = children.length - 1; i >= 0; i--) {
22
+ whileQuaua.push({ parent: item.des, des: children[i] as T })
23
+ }
24
+ }
25
+ }
26
+
27
+ /**前序遍历且可以终止 */
28
+ static preTerminated<T extends TraverseNode = TraverseNode, D extends T | null = null>(descriptor: T, cb: (sub: T, parent: D) => true | void, defaultParent: D = null as D) {
29
+ const whileQuaua: PreItem<T>[] = [{ parent: defaultParent, des: descriptor }]
30
+
31
+ while (whileQuaua.length > 0) {
32
+ const item = whileQuaua.pop() as PreItem<T>
33
+ if (cb(item.des, item.parent as D) === true) continue
34
+ const children = item.des.children
35
+ if (Array.isArray(children) === false) continue
36
+ for (let i = children.length - 1; i >= 0; i--) {
37
+ whileQuaua.push({ parent: item.des, des: children[i] as T })
38
+ }
39
+ }
40
+ }
41
+ }
@@ -1,28 +1,24 @@
1
- import { Graphics } from '../graphics/Graphics'
2
-
3
- const privateState = {
4
- idBuilder: 0,
5
- collection: new Map<number, Graphics>()
6
- }
7
-
8
- class Actor {
9
- static seGraphics(actor: Actor, graphics: Graphics) {
10
- privateState.collection.set(actor.id, graphics)
11
- }
12
- static getGraphics<T extends Graphics = Graphics>(actor: Actor) {
13
- return (privateState.collection.get(actor.id) ?? null) as T
14
- }
15
- static deleteGraphics(actor: Actor) {
16
- privateState.collection.delete(actor.id)
17
- }
18
- readonly id = privateState.idBuilder++
19
- object?: any
20
-
21
- add(actor: Actor) { }
22
-
23
- remove(actor: Actor) { }
24
- }
25
-
26
- export {
27
- Actor,
1
+ import { Graphics } from '../graphics/Graphics'
2
+
3
+ const privateState = {
4
+ idBuilder: 0,
5
+ collection: new Map<number, Graphics>()
6
+ }
7
+
8
+ export class Actor {
9
+ static seGraphics(actor: Actor, graphics: Graphics) {
10
+ privateState.collection.set(actor.id, graphics)
11
+ }
12
+ static getGraphics<T extends Graphics = Graphics>(actor: Actor) {
13
+ return (privateState.collection.get(actor.id) ?? null) as T
14
+ }
15
+ static deleteGraphics(actor: Actor) {
16
+ privateState.collection.delete(actor.id)
17
+ }
18
+ readonly id = privateState.idBuilder++
19
+ object?: any
20
+
21
+ add(actor: Actor) { }
22
+
23
+ remove(actor: Actor) { }
28
24
  }