@vyr/engine 0.0.1

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 (95) hide show
  1. package/package.json +19 -0
  2. package/src/ArrayUtils.ts +65 -0
  3. package/src/AsyncTask.ts +72 -0
  4. package/src/Category.ts +119 -0
  5. package/src/Color.ts +111 -0
  6. package/src/Engine.ts +101 -0
  7. package/src/Generate.ts +40 -0
  8. package/src/InputSystem.ts +108 -0
  9. package/src/Listener.ts +59 -0
  10. package/src/ObjectPool.ts +84 -0
  11. package/src/ObjectUtils.ts +49 -0
  12. package/src/Scriptable.ts +27 -0
  13. package/src/Serialization.ts +49 -0
  14. package/src/Traverser.ts +39 -0
  15. package/src/actor/Actor.ts +28 -0
  16. package/src/actor/AnimationUnitActor.ts +289 -0
  17. package/src/actor/DivActor.ts +70 -0
  18. package/src/actor/FragmentActor.ts +56 -0
  19. package/src/actor/HTMActor.ts +166 -0
  20. package/src/actor/HTMServiceActor.ts +57 -0
  21. package/src/actor/HTMTransformControllerActor.ts +404 -0
  22. package/src/actor/StyleActor.ts +96 -0
  23. package/src/actor/index.ts +8 -0
  24. package/src/asset/Asset.ts +271 -0
  25. package/src/asset/AssetGraph.ts +246 -0
  26. package/src/asset/index.ts +2 -0
  27. package/src/descriptor/AnimationUnitDescriptor.ts +65 -0
  28. package/src/descriptor/CameraDescriptor.ts +12 -0
  29. package/src/descriptor/ControllerDescriptor.ts +16 -0
  30. package/src/descriptor/DatasetDescriptor.ts +92 -0
  31. package/src/descriptor/Descriptor.ts +415 -0
  32. package/src/descriptor/DivDescriptor.ts +18 -0
  33. package/src/descriptor/DynamicDescriptor.ts +27 -0
  34. package/src/descriptor/HTMLDescriptor.ts +87 -0
  35. package/src/descriptor/HTMLServiceDescriptor.ts +19 -0
  36. package/src/descriptor/HTMLTransformControllerDescriptor.ts +34 -0
  37. package/src/descriptor/NodeDescriptor.ts +32 -0
  38. package/src/descriptor/PrefabDescriptor.ts +53 -0
  39. package/src/descriptor/PrefabInstanceDescriptor.ts +32 -0
  40. package/src/descriptor/RoutineDescriptor.ts +54 -0
  41. package/src/descriptor/ServiceDescriptor.ts +32 -0
  42. package/src/descriptor/ServiceSchedulerDescriptor.ts +32 -0
  43. package/src/descriptor/StyleDescriptor.ts +213 -0
  44. package/src/descriptor/index.ts +17 -0
  45. package/src/graphics/Collection.ts +25 -0
  46. package/src/graphics/Compilation.ts +82 -0
  47. package/src/graphics/Graphics.ts +475 -0
  48. package/src/graphics/Observer.ts +36 -0
  49. package/src/graphics/Unit.ts +83 -0
  50. package/src/graphics/VariableProxy.ts +92 -0
  51. package/src/graphics/index.ts +5 -0
  52. package/src/index.ts +26 -0
  53. package/src/interpreter/AnimationUnitInterpreter.ts +53 -0
  54. package/src/interpreter/DatasetInterpreter.ts +11 -0
  55. package/src/interpreter/DivInterpreter.ts +44 -0
  56. package/src/interpreter/DynamicInterpreter.ts +207 -0
  57. package/src/interpreter/FragmentInterpreter.ts +34 -0
  58. package/src/interpreter/HTMLServiceInterpreter.ts +47 -0
  59. package/src/interpreter/HTMLTransformControllerInterpreter.ts +40 -0
  60. package/src/interpreter/Interpreter.ts +69 -0
  61. package/src/interpreter/PrefaInterpreter.ts +11 -0
  62. package/src/interpreter/PrefabInstanceInterpreter.ts +12 -0
  63. package/src/interpreter/RoutineInterpreter.ts +88 -0
  64. package/src/interpreter/ServiceInterpreter.ts +24 -0
  65. package/src/interpreter/ServiceSchedulerInterpreter.ts +42 -0
  66. package/src/interpreter/StyleInterpreter.ts +66 -0
  67. package/src/interpreter/index.ts +14 -0
  68. package/src/locale/Language.ts +10 -0
  69. package/src/locale/LanguageProvider.ts +48 -0
  70. package/src/locale/index.ts +2 -0
  71. package/src/math/Euler.ts +303 -0
  72. package/src/math/Matrix4.ts +1123 -0
  73. package/src/math/Quaternion.ts +737 -0
  74. package/src/math/Vector2.ts +680 -0
  75. package/src/math/Vector3.ts +1062 -0
  76. package/src/math/index.ts +5 -0
  77. package/src/math/utils.ts +17 -0
  78. package/src/preset/execute/dataset/index.ts +1 -0
  79. package/src/preset/execute/dataset/update.ts +52 -0
  80. package/src/preset/execute/graphics/index.ts +1 -0
  81. package/src/preset/execute/graphics/invoke.ts +49 -0
  82. package/src/preset/execute/index.ts +4 -0
  83. package/src/preset/execute/net/index.ts +1 -0
  84. package/src/preset/execute/net/request.ts +103 -0
  85. package/src/preset/execute/scheduler/index.ts +1 -0
  86. package/src/preset/execute/scheduler/switch.ts +46 -0
  87. package/src/preset/index.ts +7 -0
  88. package/src/preset/routine/graphics/index.ts +1 -0
  89. package/src/preset/routine/graphics/invoke.ts +27 -0
  90. package/src/preset/routine/index.ts +2 -0
  91. package/src/preset/routine/scheduler/index.ts +1 -0
  92. package/src/preset/routine/scheduler/switch.ts +27 -0
  93. package/src/setup/index.ts +17 -0
  94. package/src/utils/AssetProvider.ts +72 -0
  95. package/src/utils/index.ts +1 -0
@@ -0,0 +1,59 @@
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 }
@@ -0,0 +1,84 @@
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 }
@@ -0,0 +1,49 @@
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 }
@@ -0,0 +1,27 @@
1
+ import { Descriptor, UpdateArgs } from "./descriptor"
2
+ import { Graphics } from "./graphics/Graphics"
3
+
4
+ /**
5
+ * 可编程脚本(脚本不会在服务端实例化)
6
+ */
7
+ class Scriptable {
8
+ readonly uuid
9
+ /**脚本文件的url路径 */
10
+ get url() {
11
+ return this.uuid
12
+ }
13
+
14
+ constructor(url: string) {
15
+ this.uuid = url
16
+ }
17
+
18
+ /**脚本的准备事件,该方法在脚本被实例化后立即执行
19
+ *
20
+ * 一般在该事件中进行脚本的准备工作,如从服务端获取资源或数据
21
+ */
22
+ async ready() { }
23
+
24
+ execute(descriptor: Descriptor, graphics: Graphics, args: UpdateArgs): any { }
25
+ }
26
+
27
+ export { Scriptable }
@@ -0,0 +1,49 @@
1
+ interface SerializationObject {
2
+ [k: string]: any
3
+ }
4
+
5
+ type DeserializationObject<T extends { [k: string]: any } = { [k: string]: any }> = {
6
+ -readonly [K in keyof T as T[K] extends Function ? never : K]:
7
+ T[K] extends Array<infer U>
8
+ ? U extends { [k: string]: any }
9
+ ? Array<DeserializationObject<U>>
10
+ : T[K]
11
+ : T[K] extends object
12
+ ? DeserializationObject<T[K]>
13
+ : T[K]
14
+ };
15
+
16
+ const privateRules = [
17
+ { parse: Infinity, stringify: '__vyr_infinity+__', },
18
+ { parse: -Infinity, stringify: '__vyr_infinity-__', },
19
+ ]
20
+
21
+ const privateToStringify = (key: string, value: any) => {
22
+ for (const rule of privateRules) {
23
+ if (rule.parse === value) return rule.stringify
24
+ }
25
+ return value
26
+ }
27
+ const privateToJson = (key: string, value: any) => {
28
+ for (const rule of privateRules) {
29
+ if (rule.stringify === value) return rule.parse
30
+ }
31
+ return value
32
+ }
33
+
34
+ class Serialization {
35
+
36
+ static stringify(obj: SerializationObject) {
37
+ return JSON.stringify(obj, privateToStringify)
38
+ }
39
+
40
+ static parse(str: string) {
41
+ return JSON.parse(str, privateToJson) as DeserializationObject
42
+ }
43
+
44
+ static deepClone<T extends any = any>(obj: SerializationObject) {
45
+ return this.parse(this.stringify(obj)) as T
46
+ }
47
+ }
48
+
49
+ export { SerializationObject, DeserializationObject, Serialization }
@@ -0,0 +1,39 @@
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 }
@@ -0,0 +1,28 @@
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,
28
+ }
@@ -0,0 +1,289 @@
1
+ import { Euler, Quaternion, Vector2, Vector3 } from "../math"
2
+ import { AnimationUnitDescriptor, Descriptor, UpdateArgs } from "../descriptor"
3
+ import { AnimationUnitInterpreter } from "../interpreter"
4
+ import { Graphics } from "../graphics"
5
+ import { ObjectUtils } from '../ObjectUtils'
6
+ import { Color } from '../Color'
7
+ import { Actor } from "./Actor"
8
+
9
+ abstract class AnimationUnitActor extends Actor {
10
+ static parse(descriptor: AnimationUnitDescriptor) {
11
+ switch (descriptor.frameData.type) {
12
+ case 'number':
13
+ return new NumberAnimationUnitargetActor(descriptor, descriptor.frameData.startValue, descriptor.frameData.endValue)
14
+ case 'vector2':
15
+ return new Vector2AnimationUnitargetActor(descriptor, new Vector2(...descriptor.frameData.startValue), new Vector2(...descriptor.frameData.endValue))
16
+ case 'vector3':
17
+ return new Vector3AnimationUnitargetActor(descriptor, new Vector3(...descriptor.frameData.startValue), new Vector3(...descriptor.frameData.endValue))
18
+ case 'euler':
19
+ return new EulerAnimationUnitargetActor(descriptor, new Euler(...descriptor.frameData.startValue), new Euler(...descriptor.frameData.endValue))
20
+ case 'boolean':
21
+ return new BooleanAnimationUnitargetActor(descriptor, descriptor.frameData.startValue, descriptor.frameData.endValue)
22
+ case 'color':
23
+ return new ColorAnimationUnitargetActor(descriptor, new Color(descriptor.frameData.startValue), new Color(descriptor.frameData.endValue))
24
+ }
25
+ }
26
+
27
+ play: boolean
28
+ startTime: number
29
+ duration: number
30
+ mode: number
31
+ path: string
32
+ keys: string[]
33
+ count: number
34
+ uptime: number
35
+ unlisten!: () => void
36
+ target!: Descriptor
37
+ rawValue!: any
38
+
39
+ constructor(descriptor: AnimationUnitDescriptor) {
40
+ super()
41
+ this.play = descriptor.play
42
+ this.startTime = descriptor.startTime
43
+ this.duration = descriptor.duration
44
+ this.mode = descriptor.mode
45
+ this.path = descriptor.path
46
+ this.keys = ObjectUtils.parseKey(descriptor.path)
47
+ this.count = descriptor.count
48
+ this.uptime = 0
49
+ }
50
+
51
+ listen(graphics: Graphics) {
52
+ graphics.engine.listen('afterRender', this.update)
53
+ this.unlisten = () => {
54
+ graphics.engine.unlisten('afterRender', this.update)
55
+ this.reset()
56
+ }
57
+ }
58
+
59
+ setTarget(descriptor: Descriptor) {
60
+ this.target = descriptor
61
+ let rawValue = descriptor as any
62
+ for (const key of this.keys) {
63
+ rawValue = rawValue[key]
64
+ if (rawValue === undefined) return
65
+ }
66
+ this.rawValue = Descriptor.deepClone(rawValue)
67
+ }
68
+
69
+ getRadio(radio: number, count: number) {
70
+ if (this.mode === 2) {
71
+ radio = (count % 2 === 1) ? 1 - radio : radio
72
+ }
73
+ return radio
74
+ }
75
+
76
+ abstract setValue(radio: number): void
77
+
78
+ traverseWithTailCallback(set: (target: any, key: string) => void) {
79
+ let target: { [k: string]: any } = this.target
80
+ const count = this.keys.length - 1
81
+ for (let i = 0; i <= count; i++) {
82
+ if (i === count) {
83
+ const key = this.keys[i]
84
+ if (target[key] === undefined) return
85
+ set(target, key)
86
+ this.target.setNeedsUpdate()
87
+ } else {
88
+ target = target[this.keys[i]]
89
+ if (!target) return
90
+ }
91
+ }
92
+ }
93
+
94
+ update = (args: UpdateArgs) => {
95
+ if (AnimationUnitInterpreter.enabled === false) return
96
+ if (this.play === false) return
97
+ const uptime = this.uptime + args.delta
98
+
99
+ const count = (this.uptime - this.startTime) / this.duration
100
+ if (count > this.count) {
101
+ this.uptime = uptime
102
+ return
103
+ }
104
+
105
+ const currentTime = uptime - this.startTime
106
+ if (currentTime < 0) {
107
+ this.uptime = uptime
108
+ return
109
+ }
110
+
111
+ const currentCount = currentTime / this.duration
112
+
113
+ let radio
114
+ if (currentCount > this.count) {
115
+ if (this.mode === 2) {
116
+ radio = this.count % 2 === 1 ? 1 : 0
117
+ } else {
118
+ radio = 1
119
+ }
120
+ } else {
121
+ radio = this.getRadio(currentCount % 1, Math.floor(currentCount))
122
+ }
123
+ this.setValue(radio)
124
+ this.uptime = uptime
125
+ }
126
+
127
+ reset(time = 0) {
128
+ this.uptime = 0
129
+ this.traverseWithTailCallback((target, key) => {
130
+ target[key] = Descriptor.deepClone(this.rawValue)
131
+ })
132
+ this.update({ delta: time })
133
+ }
134
+ }
135
+
136
+ class NumberAnimationUnitargetActor extends AnimationUnitActor {
137
+ startValue
138
+ distance
139
+
140
+ constructor(descriptor: AnimationUnitDescriptor, startValue: number, endValue: number) {
141
+ super(descriptor)
142
+ this.startValue = startValue
143
+ this.distance = endValue - startValue
144
+ }
145
+
146
+ setValue(radio: number) {
147
+ const value = this.startValue + this.distance * radio
148
+ this.traverseWithTailCallback((target, key) => {
149
+ target[key] = value
150
+ })
151
+ }
152
+ }
153
+
154
+ let _vector2: Vector2 | null = null
155
+ class Vector2AnimationUnitargetActor extends AnimationUnitActor {
156
+ static get vector() {
157
+ if (_vector2 === null) {
158
+ _vector2 = new Vector2()
159
+ }
160
+ return _vector2
161
+ }
162
+ startValue: Vector2
163
+ endValue: Vector2
164
+ constructor(descriptor: AnimationUnitDescriptor, startValue: Vector2, endValue: Vector2) {
165
+ super(descriptor)
166
+ this.startValue = startValue
167
+ this.endValue = endValue
168
+ }
169
+
170
+ setValue(radio: number) {
171
+ this.traverseWithTailCallback((target, key) => {
172
+ Vector2AnimationUnitargetActor.vector.lerpVectors(this.startValue, this.endValue, radio)
173
+ target[key].x = Vector2AnimationUnitargetActor.vector.x
174
+ target[key].y = Vector2AnimationUnitargetActor.vector.y
175
+ })
176
+ }
177
+ }
178
+
179
+ let _vector3: Vector3 | null = null
180
+ class Vector3AnimationUnitargetActor extends AnimationUnitActor {
181
+ static get vector() {
182
+ if (_vector3 === null) {
183
+ _vector3 = new Vector3()
184
+ }
185
+ return _vector3
186
+ }
187
+ declare startValue: Vector3
188
+ declare endValue: Vector3
189
+ constructor(descriptor: AnimationUnitDescriptor, startValue: Vector3, endValue: Vector3) {
190
+ super(descriptor)
191
+ this.startValue = startValue
192
+ this.endValue = endValue
193
+ }
194
+ setValue(radio: number) {
195
+ this.traverseWithTailCallback((target, key) => {
196
+ Vector3AnimationUnitargetActor.vector.lerpVectors(this.startValue, this.endValue, radio)
197
+ target[key].x = Vector3AnimationUnitargetActor.vector.x
198
+ target[key].y = Vector3AnimationUnitargetActor.vector.y
199
+ target[key].z = Vector3AnimationUnitargetActor.vector.z
200
+ })
201
+ }
202
+ }
203
+
204
+ let _euler: Euler | null = null
205
+ let _startQuat: Quaternion | null = null
206
+ let _endQuat: Quaternion | null = null
207
+ class EulerAnimationUnitargetActor extends AnimationUnitActor {
208
+ static get euler() {
209
+ if (_euler === null) {
210
+ _euler = new Euler()
211
+ }
212
+ return _euler
213
+ }
214
+ static get startQuat() {
215
+ if (_startQuat === null) {
216
+ _startQuat = new Quaternion()
217
+ }
218
+ return _startQuat
219
+ }
220
+ static get endQuat() {
221
+ if (_endQuat === null) {
222
+ _endQuat = new Quaternion()
223
+ }
224
+ return _endQuat
225
+ }
226
+ declare startValue: Euler
227
+ declare endValue: Euler
228
+ constructor(descriptor: AnimationUnitDescriptor, startValue: Euler, endValue: Euler) {
229
+ super(descriptor)
230
+ this.startValue = startValue
231
+ this.endValue = endValue
232
+ }
233
+ setValue(radio: number) {
234
+ this.traverseWithTailCallback((target, key) => {
235
+ EulerAnimationUnitargetActor.startQuat.setFromEuler(this.startValue)
236
+ EulerAnimationUnitargetActor.endQuat.setFromEuler(this.endValue)
237
+ EulerAnimationUnitargetActor.startQuat.slerp(EulerAnimationUnitargetActor.endQuat, radio)
238
+ EulerAnimationUnitargetActor.euler.setFromQuaternion(EulerAnimationUnitargetActor.startQuat)
239
+ target[key].x = EulerAnimationUnitargetActor.euler.x
240
+ target[key].y = EulerAnimationUnitargetActor.euler.y
241
+ target[key].y = EulerAnimationUnitargetActor.euler.y
242
+ target[key].order = EulerAnimationUnitargetActor.euler.order
243
+ })
244
+ }
245
+ }
246
+
247
+ class BooleanAnimationUnitargetActor extends AnimationUnitActor {
248
+ declare startValue: number
249
+ declare endValue: number
250
+ constructor(descriptor: AnimationUnitDescriptor, startValue: number, endValue: number) {
251
+ super(descriptor)
252
+ this.startValue = startValue
253
+ this.endValue = endValue
254
+ }
255
+ setValue(radio: number) {
256
+ switch (radio) {
257
+ case 0:
258
+ this.traverseWithTailCallback((target, key) => {
259
+ target[key] = this.startValue
260
+ })
261
+ break
262
+ case 1:
263
+ this.traverseWithTailCallback((target, key) => {
264
+ target[key] = this.endValue
265
+ })
266
+ break
267
+ }
268
+ }
269
+ }
270
+
271
+ class ColorAnimationUnitargetActor extends AnimationUnitActor {
272
+ declare startValue: Color
273
+ declare endValue: Color
274
+ constructor(descriptor: AnimationUnitDescriptor, startValue: Color, endValue: Color) {
275
+ super(descriptor)
276
+ this.startValue = startValue
277
+ this.endValue = endValue
278
+ }
279
+ setValue(radio: number) {
280
+ this.traverseWithTailCallback((target, key) => {
281
+ const currentValue = Color.mix(this.startValue, this.endValue, radio)
282
+ target[key] = currentValue.toHexString()
283
+ })
284
+ }
285
+ }
286
+
287
+ export {
288
+ AnimationUnitActor
289
+ }
@@ -0,0 +1,70 @@
1
+ import { DivDescriptor, StyleDescriptor, UpdateArgs } from "../descriptor"
2
+ import { Actor } from "./Actor"
3
+ import { HTMLActor } from "./HTMActor"
4
+
5
+ class DivActor extends HTMLActor {
6
+ private _text: Text | null = null
7
+ get text() {
8
+ if (this._text === null) {
9
+ this._text = document.createTextNode('')
10
+ }
11
+ return this._text
12
+ }
13
+ private _wrapper: HTMLElement | null = null
14
+ readonly DOM
15
+
16
+ constructor(uuid: string) {
17
+ super(uuid)
18
+ this.DOM = this.createDOM()
19
+ const wrapper = this.getWrapper()
20
+ wrapper.appendChild(this.DOM)
21
+ }
22
+
23
+ protected createWrapper() {
24
+ const wrapper = document.createElement('div')
25
+ wrapper.setAttribute('class', HTMLActor.className)
26
+ wrapper.setAttribute(HTMLActor.uuidKey, this.uuid)
27
+ return wrapper
28
+ }
29
+
30
+ getWrapper() {
31
+ if (this._wrapper === null) {
32
+ this._wrapper = this.createWrapper()
33
+ }
34
+
35
+ return this._wrapper
36
+ }
37
+
38
+ add(actor: Actor) {
39
+ if (actor instanceof HTMLActor) {
40
+ const wrapper = actor.getWrapper()
41
+ if (wrapper === null) return
42
+ if (this.DOM.contains(wrapper)) return
43
+ this.DOM.appendChild(wrapper)
44
+ }
45
+ }
46
+
47
+ remove(actor: Actor) {
48
+ if (actor instanceof HTMLActor) {
49
+ const wrapper = actor.getWrapper()
50
+ if (wrapper === null) return
51
+ if (this.DOM.contains(wrapper)) this.DOM.removeChild(wrapper)
52
+ }
53
+ }
54
+
55
+ update(descriptor: DivDescriptor, args: UpdateArgs) {
56
+ const wrapper = this.getWrapper()
57
+ const style = this.getWrapperStyle(descriptor, args)
58
+ this.setHTMLStyle(wrapper, style)
59
+ this.setHTMLInteraction(wrapper, descriptor, args)
60
+ this.setHTMLStyle(this.DOM, this.getLayoutStyle(descriptor, args))
61
+ const styleClass = [...this.getStyleClass(descriptor, args)]
62
+ if (descriptor.active) styleClass.push(StyleDescriptor.activeName)
63
+ this.setStyleClass(this.DOM, styleClass)
64
+ this.DOM.style.backgroundImage = descriptor.backroundIamge ? `url(${descriptor.backroundIamge})` : ''
65
+ this.text.textContent = descriptor.text
66
+ if (this.DOM.contains(this.text) === false) this.DOM.appendChild(this.text)
67
+ }
68
+ }
69
+
70
+ export { DivActor }