@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.
- package/package.json +19 -0
- package/src/ArrayUtils.ts +65 -0
- package/src/AsyncTask.ts +72 -0
- package/src/Category.ts +119 -0
- package/src/Color.ts +111 -0
- package/src/Engine.ts +101 -0
- package/src/Generate.ts +40 -0
- package/src/InputSystem.ts +108 -0
- package/src/Listener.ts +59 -0
- package/src/ObjectPool.ts +84 -0
- package/src/ObjectUtils.ts +49 -0
- package/src/Scriptable.ts +27 -0
- package/src/Serialization.ts +49 -0
- package/src/Traverser.ts +39 -0
- package/src/actor/Actor.ts +28 -0
- package/src/actor/AnimationUnitActor.ts +289 -0
- package/src/actor/DivActor.ts +70 -0
- package/src/actor/FragmentActor.ts +56 -0
- package/src/actor/HTMActor.ts +166 -0
- package/src/actor/HTMServiceActor.ts +57 -0
- package/src/actor/HTMTransformControllerActor.ts +404 -0
- package/src/actor/StyleActor.ts +96 -0
- package/src/actor/index.ts +8 -0
- package/src/asset/Asset.ts +271 -0
- package/src/asset/AssetGraph.ts +246 -0
- package/src/asset/index.ts +2 -0
- package/src/descriptor/AnimationUnitDescriptor.ts +65 -0
- package/src/descriptor/CameraDescriptor.ts +12 -0
- package/src/descriptor/ControllerDescriptor.ts +16 -0
- package/src/descriptor/DatasetDescriptor.ts +92 -0
- package/src/descriptor/Descriptor.ts +415 -0
- package/src/descriptor/DivDescriptor.ts +18 -0
- package/src/descriptor/DynamicDescriptor.ts +27 -0
- package/src/descriptor/HTMLDescriptor.ts +87 -0
- package/src/descriptor/HTMLServiceDescriptor.ts +19 -0
- package/src/descriptor/HTMLTransformControllerDescriptor.ts +34 -0
- package/src/descriptor/NodeDescriptor.ts +32 -0
- package/src/descriptor/PrefabDescriptor.ts +53 -0
- package/src/descriptor/PrefabInstanceDescriptor.ts +32 -0
- package/src/descriptor/RoutineDescriptor.ts +54 -0
- package/src/descriptor/ServiceDescriptor.ts +32 -0
- package/src/descriptor/ServiceSchedulerDescriptor.ts +32 -0
- package/src/descriptor/StyleDescriptor.ts +213 -0
- package/src/descriptor/index.ts +17 -0
- package/src/graphics/Collection.ts +25 -0
- package/src/graphics/Compilation.ts +82 -0
- package/src/graphics/Graphics.ts +475 -0
- package/src/graphics/Observer.ts +36 -0
- package/src/graphics/Unit.ts +83 -0
- package/src/graphics/VariableProxy.ts +92 -0
- package/src/graphics/index.ts +5 -0
- package/src/index.ts +26 -0
- package/src/interpreter/AnimationUnitInterpreter.ts +53 -0
- package/src/interpreter/DatasetInterpreter.ts +11 -0
- package/src/interpreter/DivInterpreter.ts +44 -0
- package/src/interpreter/DynamicInterpreter.ts +207 -0
- package/src/interpreter/FragmentInterpreter.ts +34 -0
- package/src/interpreter/HTMLServiceInterpreter.ts +47 -0
- package/src/interpreter/HTMLTransformControllerInterpreter.ts +40 -0
- package/src/interpreter/Interpreter.ts +69 -0
- package/src/interpreter/PrefaInterpreter.ts +11 -0
- package/src/interpreter/PrefabInstanceInterpreter.ts +12 -0
- package/src/interpreter/RoutineInterpreter.ts +88 -0
- package/src/interpreter/ServiceInterpreter.ts +24 -0
- package/src/interpreter/ServiceSchedulerInterpreter.ts +42 -0
- package/src/interpreter/StyleInterpreter.ts +66 -0
- package/src/interpreter/index.ts +14 -0
- package/src/locale/Language.ts +10 -0
- package/src/locale/LanguageProvider.ts +48 -0
- package/src/locale/index.ts +2 -0
- package/src/math/Euler.ts +303 -0
- package/src/math/Matrix4.ts +1123 -0
- package/src/math/Quaternion.ts +737 -0
- package/src/math/Vector2.ts +680 -0
- package/src/math/Vector3.ts +1062 -0
- package/src/math/index.ts +5 -0
- package/src/math/utils.ts +17 -0
- package/src/preset/execute/dataset/index.ts +1 -0
- package/src/preset/execute/dataset/update.ts +52 -0
- package/src/preset/execute/graphics/index.ts +1 -0
- package/src/preset/execute/graphics/invoke.ts +49 -0
- package/src/preset/execute/index.ts +4 -0
- package/src/preset/execute/net/index.ts +1 -0
- package/src/preset/execute/net/request.ts +103 -0
- package/src/preset/execute/scheduler/index.ts +1 -0
- package/src/preset/execute/scheduler/switch.ts +46 -0
- package/src/preset/index.ts +7 -0
- package/src/preset/routine/graphics/index.ts +1 -0
- package/src/preset/routine/graphics/invoke.ts +27 -0
- package/src/preset/routine/index.ts +2 -0
- package/src/preset/routine/scheduler/index.ts +1 -0
- package/src/preset/routine/scheduler/switch.ts +27 -0
- package/src/setup/index.ts +17 -0
- package/src/utils/AssetProvider.ts +72 -0
- package/src/utils/index.ts +1 -0
package/src/Listener.ts
ADDED
|
@@ -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 }
|
package/src/Traverser.ts
ADDED
|
@@ -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 }
|