@vyr/engine 0.0.32 → 0.0.34

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
@@ -0,0 +1,109 @@
1
+ import { Scriptable } from "./Scriptable"
2
+ import { Interaction } from "./descriptor/Interaction"
3
+ import { Graphics } from "./graphics/Graphics"
4
+ import { InteractionNode, InteractionNodeInputCollection } from "./schema"
5
+
6
+ type ExecuteResult = { [k: string]: any } | null
7
+
8
+ export class Executor {
9
+ readonly collection = new Map<string, InteractionNode>()
10
+ readonly linkCollection = new Map<string, string[]>()
11
+
12
+ update(interaction: Interaction) {
13
+ this.collection.clear()
14
+ this.linkCollection.clear()
15
+
16
+ for (const node of interaction.nodes) {
17
+ this.collection.set(node.id, node)
18
+ }
19
+
20
+ for (const mapper of interaction.mappers) {
21
+ let link = this.linkCollection.get(mapper.source)
22
+ if (link === undefined) {
23
+ link = []
24
+ this.linkCollection.set(mapper.source, link)
25
+ }
26
+ link.push(mapper.target)
27
+ }
28
+ }
29
+
30
+ async doScript(current: string, previous: string, nodes: InteractionNodeInputCollection, interaction: Interaction, graphics: Graphics, result: Map<string, ExecuteResult>, trigger: string, otherArgs?: any) {
31
+ const active = this.collection.get(current)
32
+ if (active === undefined) return
33
+
34
+ const nodeInput = nodes[current] ?? active.input
35
+ const script = Scriptable.use(active.script)
36
+ if (script) {
37
+ const args = { previous, result }
38
+ if (otherArgs) Object.assign(args, otherArgs)
39
+ const safeInput = script.inputSchame.parse(nodeInput)
40
+ const executeResult = await script.execute(graphics, trigger, safeInput, args)
41
+ if (script.outputSchame !== undefined) script.outputSchame.parse(executeResult)
42
+ result.set(current, executeResult)
43
+ }
44
+ }
45
+
46
+ async doCondition(conditions: InteractionNode[], previous: string, nodes: InteractionNodeInputCollection, interaction: Interaction, graphics: Graphics, result: Map<string, ExecuteResult>, trigger: string, otherArgs?: any) {
47
+ const queue: Promise<void>[] = []
48
+ for (const condition of conditions) {
49
+ queue.push(this.doScript(condition.id, previous, nodes, interaction, graphics, result, trigger))
50
+ }
51
+
52
+ await Promise.all(queue)
53
+
54
+ for (const condition of conditions) {
55
+ const conditionResult = result.get(condition.id)
56
+ if (conditionResult?.success !== true) continue
57
+
58
+ const nexts = this.linkCollection.get(condition.id)
59
+ if (nexts === undefined) continue
60
+ for (const next of nexts) {
61
+ await this.doExecute(next, previous, nodes, interaction, graphics, result, trigger, otherArgs)
62
+ }
63
+ }
64
+ }
65
+
66
+ async doNext(current: string, nodes: InteractionNodeInputCollection, interaction: Interaction, graphics: Graphics, result: Map<string, ExecuteResult>, trigger: string, otherArgs?: any) {
67
+ const nexts = this.linkCollection.get(current)
68
+ if (nexts === undefined) return
69
+
70
+ const executes: InteractionNode[] = []
71
+ const conditions: InteractionNode[] = []
72
+ for (const next of nexts) {
73
+ const node = this.collection.get(next)
74
+ if (node === undefined) continue
75
+ if (node.type === 'Condition') {
76
+ conditions.push(node)
77
+ } else if (node.type === 'Execute') {
78
+ executes.push(node)
79
+ }
80
+ }
81
+
82
+ const queue: Promise<void>[] = []
83
+ if (conditions.length > 0) {
84
+ queue.push(this.doCondition(conditions, current, nodes, interaction, graphics, result, trigger))
85
+ await Promise.all(queue)
86
+ }
87
+
88
+ if (executes.length > 0) {
89
+ queue.length = 0
90
+ for (const execute of executes) {
91
+ queue.push(this.doExecute(execute.id, current, nodes, interaction, graphics, result, trigger))
92
+ }
93
+ await Promise.all(queue)
94
+ }
95
+ }
96
+
97
+ async doExecute(current: string, previous: string, nodes: InteractionNodeInputCollection, interaction: Interaction, graphics: Graphics, result: Map<string, ExecuteResult>, trigger: string, otherArgs?: any) {
98
+ await this.doScript(current, previous, nodes, interaction, graphics, result, trigger, otherArgs)
99
+
100
+ await this.doNext(current, nodes, interaction, graphics, result, trigger, otherArgs)
101
+ }
102
+
103
+ async execute(nodes: InteractionNodeInputCollection, interaction: Interaction, graphics: Graphics, trigger: string, otherArgs?: any) {
104
+ for (const root of interaction.roots) {
105
+ const resultCollection = new Map()
106
+ await this.doExecute(root, '', nodes, interaction, graphics, resultCollection, trigger, otherArgs)
107
+ }
108
+ }
109
+ }
package/src/Generate.ts CHANGED
@@ -1,40 +1,23 @@
1
- let id = 1;
2
- const _lut = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff'];
3
-
4
- class Generate {
5
- static id() {
6
- return id++
7
- }
8
-
9
- static uuid() {
10
- const d0 = Math.random() * 0xffffffff | 0;
11
- const d1 = Math.random() * 0xffffffff | 0;
12
- const d2 = Math.random() * 0xffffffff | 0;
13
- const d3 = Math.random() * 0xffffffff | 0;
14
- const uuid = _lut[d0 & 0xff] + _lut[d0 >> 8 & 0xff] + _lut[d0 >> 16 & 0xff] + _lut[d0 >> 24 & 0xff] + '-' +
15
- _lut[d1 & 0xff] + _lut[d1 >> 8 & 0xff] + '-' + _lut[d1 >> 16 & 0x0f | 0x40] + _lut[d1 >> 24 & 0xff] + '-' +
16
- _lut[d2 & 0x3f | 0x80] + _lut[d2 >> 8 & 0xff] + '-' + _lut[d2 >> 16 & 0xff] + _lut[d2 >> 24 & 0xff] +
17
- _lut[d3 & 0xff] + _lut[d3 >> 8 & 0xff] + _lut[d3 >> 16 & 0xff] + _lut[d3 >> 24 & 0xff];
18
-
19
- return uuid.toLowerCase()
20
- }
21
-
22
- static delayExecute(cb: (...args: any[]) => any) {
23
- const delaySatate = {
24
- args: [] as any[],
25
- execute: false
26
- }
27
- const execute = (...args: any[]) => {
28
- delaySatate.args = args
29
- if (delaySatate.execute === true) return
30
- delaySatate.execute = true
31
- requestAnimationFrame(() => {
32
- cb(...delaySatate.args)
33
- delaySatate.execute = false
34
- })
35
- }
36
- return execute
37
- }
38
- }
39
-
40
- export { Generate }
1
+ let id = 1;
2
+ const _lut = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '0a', '0b', '0c', '0d', '0e', '0f', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '1a', '1b', '1c', '1d', '1e', '1f', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '2a', '2b', '2c', '2d', '2e', '2f', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '3a', '3b', '3c', '3d', '3e', '3f', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '4a', '4b', '4c', '4d', '4e', '4f', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '5a', '5b', '5c', '5d', '5e', '5f', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '6a', '6b', '6c', '6d', '6e', '6f', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '7a', '7b', '7c', '7d', '7e', '7f', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '8a', '8b', '8c', '8d', '8e', '8f', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '9a', '9b', '9c', '9d', '9e', '9f', 'a0', 'a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7', 'a8', 'a9', 'aa', 'ab', 'ac', 'ad', 'ae', 'af', 'b0', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8', 'b9', 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'c0', 'c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7', 'c8', 'c9', 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'd0', 'd1', 'd2', 'd3', 'd4', 'd5', 'd6', 'd7', 'd8', 'd9', 'da', 'db', 'dc', 'dd', 'de', 'df', 'e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7', 'e8', 'e9', 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'f0', 'f1', 'f2', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9', 'fa', 'fb', 'fc', 'fd', 'fe', 'ff'];
3
+
4
+ export class Generate {
5
+ static id() {
6
+ return id++
7
+ }
8
+
9
+ static uuid() {
10
+ const d0 = Math.random() * 0xffffffff | 0;
11
+ const d1 = Math.random() * 0xffffffff | 0;
12
+ const d2 = Math.random() * 0xffffffff | 0;
13
+ const d3 = Math.random() * 0xffffffff | 0;
14
+ const uuid = _lut[d0 & 0xff] + _lut[d0 >> 8 & 0xff] + _lut[d0 >> 16 & 0xff] + _lut[d0 >> 24 & 0xff] + '-'
15
+ + _lut[d1 & 0xff] + _lut[d1 >> 8 & 0xff] + '-'
16
+ + _lut[d1 >> 16 & 0x0f | 0x40] + _lut[d1 >> 24 & 0xff] + '-'
17
+ + _lut[d2 & 0x3f | 0x80] + _lut[d2 >> 8 & 0xff] + '-'
18
+ + _lut[d2 >> 16 & 0xff] + _lut[d2 >> 24 & 0xff]
19
+ + _lut[d3 & 0xff] + _lut[d3 >> 8 & 0xff] + _lut[d3 >> 16 & 0xff] + _lut[d3 >> 24 & 0xff];
20
+
21
+ return uuid.toLowerCase()
22
+ }
23
+ }
@@ -1,108 +1,106 @@
1
- type IEM = GlobalEventHandlersEventMap
2
-
3
- interface InputConfig {
4
- /**事件只触发一次,默认`false` */
5
- once: boolean
6
- /**将事件的处理顺序设为事件捕获,默认`false` */
7
- capture: boolean
8
- /**处理函数不会调用`preventDefault`来阻止默认行为时应设为true,默认`false` */
9
- passive: boolean
10
- /**事件触发的对象 */
11
- target: Window | Document | HTMLElement
12
- }
13
-
14
- const privateState = {
15
- id: 1,
16
- listener: {
17
- default: (input: InputEvent, system: InputSystem) => {
18
- return (event: Event) => {
19
- input.event = event
20
- if (input.enable) return
21
- input.enable = true
22
- system.quaua.push(input)
23
- }
24
- },
25
- once: (input: InputEvent, system: InputSystem) => {
26
- const execute = privateState.listener.default(input, system)
27
- return (e: Event) => {
28
- execute(e)
29
- system.unlisten(input.id)
30
- }
31
- },
32
- }
33
- }
34
-
35
- class InputEvent {
36
- readonly id = privateState.id++
37
- readonly type
38
- readonly target
39
- readonly callback: (e: Event) => void
40
- readonly listener: (e: Event) => void
41
- enable = false
42
- event!: Event
43
-
44
- constructor(type: keyof IEM, callback: (e: any) => void, system: InputSystem, config: InputConfig) {
45
- this.type = type
46
- this.target = config.target
47
- this.callback = callback
48
- this.listener = config.once ? privateState.listener.once(this, system) : privateState.listener.default(this, system)
49
- }
50
-
51
- execute() {
52
- this.callback(this.event)
53
- this.enable = false
54
- }
55
- }
56
-
57
- class InputSystem {
58
- private _target
59
- private _registry: InputEvent[] = []
60
- readonly quaua: InputEvent[] = []
61
-
62
- constructor(target: InputConfig['target']) {
63
- this._target = target
64
- }
65
-
66
- /**
67
- * 监听事件输入,事件在一帧中只执行一次
68
- * @param type 事件类型
69
- * @param callback 事件触发时的回调
70
- * @param options.once 只执行一次回调
71
- * @param options.target 监听事件的绑定对象
72
- * @param options.capture 事件执行的阶段,true:捕获阶段执行,false:冒泡阶段执行
73
- */
74
- listen<T extends keyof IEM>(type: T, callback: (event: IEM[T]) => void, options: Partial<InputConfig> = {}) {
75
- const config: InputConfig = { once: false, target: this._target, passive: false, capture: false, ...options }
76
-
77
- for (const input of this._registry) {
78
- if (input.type === type && input.callback === callback && options.target === input.target) return input.id
79
- }
80
-
81
- const input = new InputEvent(type, callback, this, config)
82
- this._registry.push(input)
83
- input.target.addEventListener(type, input.listener, config.capture)
84
-
85
- return input.id
86
- }
87
-
88
- /**解除事件监听 */
89
- unlisten(id: number) {
90
- for (let i = 0; i < this._registry.length; i++) {
91
- const input = this._registry[i]
92
- if (input.id === id) {
93
- this._registry.splice(i, 1)
94
- input.target.removeEventListener(input.type, input.listener)
95
- return
96
- }
97
- }
98
- }
99
-
100
- /**处理输入事件 */
101
- process() {
102
- const quaua = [...this.quaua]
103
- for (const input of quaua) input.execute()
104
- this.quaua.length = 0
105
- }
106
- }
107
-
108
- export { InputSystem }
1
+ export type IEM = GlobalEventHandlersEventMap
2
+
3
+ export interface InputConfig {
4
+ /**事件只触发一次,默认`false` */
5
+ once: boolean
6
+ /**将事件的处理顺序设为事件捕获,默认`false` */
7
+ capture: boolean
8
+ /**处理函数不会调用`preventDefault`来阻止默认行为时应设为true,默认`false` */
9
+ passive: boolean
10
+ /**事件触发的对象 */
11
+ target: Window | Document | HTMLElement
12
+ }
13
+
14
+ const privateState = {
15
+ id: 1,
16
+ listener: {
17
+ default: (input: InputEvent, system: InputSystem) => {
18
+ return (event: Event) => {
19
+ input.event = event
20
+ if (input.enable) return
21
+ input.enable = true
22
+ system.quaua.push(input)
23
+ }
24
+ },
25
+ once: (input: InputEvent, system: InputSystem) => {
26
+ const execute = privateState.listener.default(input, system)
27
+ return (e: Event) => {
28
+ execute(e)
29
+ system.unlisten(input.id)
30
+ }
31
+ },
32
+ }
33
+ }
34
+
35
+ export class InputEvent {
36
+ readonly id = privateState.id++
37
+ readonly type
38
+ readonly target
39
+ readonly callback: (e: Event) => void
40
+ readonly listener: (e: Event) => void
41
+ enable = false
42
+ event!: Event
43
+
44
+ constructor(type: keyof IEM, callback: (e: any) => void, system: InputSystem, config: InputConfig) {
45
+ this.type = type
46
+ this.target = config.target
47
+ this.callback = callback
48
+ this.listener = config.once ? privateState.listener.once(this, system) : privateState.listener.default(this, system)
49
+ }
50
+
51
+ execute() {
52
+ this.callback(this.event)
53
+ this.enable = false
54
+ }
55
+ }
56
+
57
+ export class InputSystem {
58
+ private _target
59
+ private _registry: InputEvent[] = []
60
+ readonly quaua: InputEvent[] = []
61
+
62
+ constructor(target: InputConfig['target']) {
63
+ this._target = target
64
+ }
65
+
66
+ /**
67
+ * 监听事件输入,事件在一帧中只执行一次
68
+ * @param type 事件类型
69
+ * @param callback 事件触发时的回调
70
+ * @param options.once 只执行一次回调
71
+ * @param options.target 监听事件的绑定对象
72
+ * @param options.capture 事件执行的阶段,true:捕获阶段执行,false:冒泡阶段执行
73
+ */
74
+ listen<T extends keyof IEM>(type: T, callback: (event: IEM[T]) => void, options: Partial<InputConfig> = {}) {
75
+ const config: InputConfig = { once: false, target: this._target, passive: false, capture: false, ...options }
76
+
77
+ for (const input of this._registry) {
78
+ if (input.type === type && input.callback === callback && options.target === input.target) return input.id
79
+ }
80
+
81
+ const input = new InputEvent(type, callback, this, config)
82
+ this._registry.push(input)
83
+ input.target.addEventListener(type, input.listener, config.capture)
84
+
85
+ return input.id
86
+ }
87
+
88
+ /**解除事件监听 */
89
+ unlisten(id: number) {
90
+ for (let i = 0; i < this._registry.length; i++) {
91
+ const input = this._registry[i]
92
+ if (input.id === id) {
93
+ this._registry.splice(i, 1)
94
+ input.target.removeEventListener(input.type, input.listener)
95
+ return
96
+ }
97
+ }
98
+ }
99
+
100
+ /**处理输入事件 */
101
+ process() {
102
+ const quaua = [...this.quaua]
103
+ for (const input of quaua) input.execute()
104
+ this.quaua.length = 0
105
+ }
106
+ }
package/src/Listener.ts CHANGED
@@ -1,59 +1,58 @@
1
- type DeafultCallback = (...args: any[]) => any
2
- type CallbackCollection<T extends {} = {}> = { [k: string]: DeafultCallback } & T
3
-
4
- interface listenOptions {
5
- once?: boolean
6
- insertIndex?: number
7
- }
8
-
9
- class Listener<T extends {} = {}> {
10
- private registrys: any = {}
11
-
12
- listen<K extends keyof T>(type: K, callback: T[K], options?: listenOptions): () => void
13
- listen(type: string, callback: DeafultCallback, options?: listenOptions): () => void
14
- listen<K extends keyof T>(type: K | string, callback?: T[K], options: listenOptions = {}) {
15
-
16
- let register = this.registrys[type]
17
- if (register === undefined) {
18
- register = []
19
- this.registrys[type] = register
20
- }
21
- const insertIndex = options.insertIndex === undefined ? register.length : options.insertIndex
22
-
23
- const row = register.find((r: any) => r.callback === callback)
24
- if (!row) register.splice(insertIndex, 0, { once: options.once ?? false, callback })
25
- const unlisten = () => this.unlisten(type as any, callback)
26
- return unlisten
27
- }
28
-
29
- unlisten<K extends keyof T>(type: K, callback: T[K]): void
30
- unlisten(type: string, callback: DeafultCallback): void
31
- unlisten<K extends keyof T>(type: K, callback: T[K]) {
32
- let registry = this.registrys[type]
33
- if (registry === undefined) return
34
-
35
- for (let i = 0; i < registry.length; i++) {
36
- if (registry[i].callback !== callback) continue
37
-
38
- registry.splice(i, 1)
39
- if (registry.length === 0) delete this.registrys[type]
40
- return
41
- }
42
- }
43
-
44
- trigger<K extends keyof T>(type: K, ...args: Parameters<CallbackCollection<T>[K]>): void
45
- trigger(type: string, ...args: any[]): void
46
- trigger<K extends keyof T>(type: K, ...args: Parameters<CallbackCollection<T>[K]>) {
47
- let registry = this.registrys[type]
48
- if (registry === undefined) return //console.warn(`无法触发该事件 ${type as string}`)
49
-
50
- if (registry.length === 0) return
51
-
52
- registry = [...this.registrys[type]]
53
- for (let i = 0; i < registry.length; i++) {
54
- registry[i].callback(...args as any)
55
- if (registry[i].once === true) this.unlisten(type, registry[i].callback)
56
- }
57
- }
58
- }
59
- export { Listener }
1
+ export type DeafultCallback = (...args: any[]) => any
2
+ export type CallbackCollection<T extends {} = {}> = { [k: string]: DeafultCallback } & T
3
+
4
+ export interface listenOptions {
5
+ once?: boolean
6
+ insertIndex?: number
7
+ }
8
+
9
+ export class Listener<T extends {} = {}> {
10
+ private registrys: any = {}
11
+
12
+ listen<K extends keyof T>(type: K, callback: T[K], options?: listenOptions): () => void
13
+ listen(type: string, callback: DeafultCallback, options?: listenOptions): () => void
14
+ listen<K extends keyof T>(type: K | string, callback?: T[K], options: listenOptions = {}) {
15
+
16
+ let register = this.registrys[type]
17
+ if (register === undefined) {
18
+ register = []
19
+ this.registrys[type] = register
20
+ }
21
+ const insertIndex = options.insertIndex === undefined ? register.length : options.insertIndex
22
+
23
+ const row = register.find((r: any) => r.callback === callback)
24
+ if (!row) register.splice(insertIndex, 0, { once: options.once ?? false, callback })
25
+ const unlisten = () => this.unlisten(type as any, callback)
26
+ return unlisten
27
+ }
28
+
29
+ unlisten<K extends keyof T>(type: K, callback: T[K]): void
30
+ unlisten(type: string, callback: DeafultCallback): void
31
+ unlisten<K extends keyof T>(type: K, callback: T[K]) {
32
+ let registry = this.registrys[type]
33
+ if (registry === undefined) return
34
+
35
+ for (let i = 0; i < registry.length; i++) {
36
+ if (registry[i].callback !== callback) continue
37
+
38
+ registry.splice(i, 1)
39
+ if (registry.length === 0) delete this.registrys[type]
40
+ return
41
+ }
42
+ }
43
+
44
+ trigger<K extends keyof T>(type: K, ...args: Parameters<CallbackCollection<T>[K]>): void
45
+ trigger(type: string, ...args: any[]): void
46
+ trigger<K extends keyof T>(type: K, ...args: Parameters<CallbackCollection<T>[K]>) {
47
+ let registry = this.registrys[type]
48
+ if (registry === undefined) return //console.warn(`无法触发该事件 ${type as string}`)
49
+
50
+ if (registry.length === 0) return
51
+
52
+ registry = [...this.registrys[type]]
53
+ for (let i = 0; i < registry.length; i++) {
54
+ registry[i].callback(...args as any)
55
+ if (registry[i].once === true) this.unlisten(type, registry[i].callback)
56
+ }
57
+ }
58
+ }