@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,96 @@
1
+ import { Asset } from "../asset"
2
+ import { Actor } from "./Actor"
3
+ import { StyleDescriptor } from "../descriptor"
4
+ import { StyleInterpreter } from "../interpreter"
5
+
6
+ interface RuleObjects extends Array<{ name: string, value: string }> { }
7
+
8
+ class StyleActor extends Actor {
9
+ private _styleCollection = new Map<string, RuleObjects>()
10
+ private _className: string[] = []
11
+
12
+ getStyleValue() {
13
+ const styles: string[] = []
14
+
15
+ const entries = this._styleCollection.entries()
16
+ for (const [selectorText, rules] of entries) {
17
+ const style: string[] = []
18
+ style.push(`${selectorText}{`)
19
+ if (rules.length === 0) {
20
+ style.push('/* 如果需要样式,在这里添加 */')
21
+ } else {
22
+ for (const rule of rules) {
23
+ style.push(`${rule.name}:${rule.value};`)
24
+ }
25
+ }
26
+ style.push(`}`)
27
+ styles.push(style.join('\n'))
28
+ }
29
+
30
+ return styles
31
+ }
32
+
33
+ getClassName() {
34
+ return [...this._className]
35
+ }
36
+
37
+ updateRule(sheet: CSSStyleSheet) {
38
+ let count = 0
39
+ for (const rule of sheet.cssRules) {
40
+ if (rule instanceof CSSStyleRule) {
41
+ const styleObjects = this._styleCollection.get(rule.selectorText)
42
+ if (styleObjects === undefined) continue
43
+
44
+ count++
45
+ rule.style.cssText = ''
46
+ for (const styleObject of styleObjects) {
47
+ rule.style.setProperty(styleObject.name, styleObject.value)
48
+ }
49
+
50
+ if (count === 2) return true
51
+ }
52
+ }
53
+ return false
54
+ }
55
+
56
+ update(descriptor: StyleDescriptor, className: string) {
57
+ this._className.length = 0
58
+ this._styleCollection.clear()
59
+
60
+ let inherit = Asset.get<StyleDescriptor>(descriptor.inherit)
61
+ if (inherit) {
62
+ const graphics = Actor.getGraphics(this)
63
+ const interpreter = graphics.getInterpreter<StyleInterpreter>(inherit)
64
+ this._className.push(interpreter.className)
65
+ }
66
+ this._className.push(className)
67
+
68
+ const rules: RuleObjects = []
69
+ for (const rule of descriptor.rules) {
70
+ if (rule.inherit === true) continue
71
+ const value = rule.getValue()
72
+ rules.push({ name: rule.name, value })
73
+ }
74
+ this._styleCollection.set(`.${className}`, rules)
75
+
76
+ const hover: RuleObjects = []
77
+ for (const rule of descriptor.hoverRules) {
78
+ if (rule.inherit === true) continue
79
+ const value = rule.getValue()
80
+ hover.push({ name: rule.name, value })
81
+ }
82
+ this._styleCollection.set(`.${className}:hover`, hover)
83
+
84
+ const active: RuleObjects = []
85
+ for (const rule of descriptor.activeRules) {
86
+ if (rule.inherit === true) continue
87
+ const value = rule.getValue()
88
+ active.push({ name: rule.name, value })
89
+ }
90
+ this._styleCollection.set(`.${className}.${StyleDescriptor.activeName}`, active)
91
+ }
92
+ }
93
+
94
+ export {
95
+ StyleActor
96
+ }
@@ -0,0 +1,8 @@
1
+ export * from './Actor'
2
+ export * from './StyleActor'
3
+ export * from './AnimationUnitActor'
4
+ export * from './FragmentActor'
5
+ export * from './HTMActor'
6
+ export * from './DivActor'
7
+ export * from './HTMServiceActor'
8
+ export * from './HTMTransformControllerActor'
@@ -0,0 +1,271 @@
1
+ import { language } from "../locale"
2
+ import { Category } from "../Category"
3
+ import { DatasetDescriptor, Descriptor } from "../descriptor"
4
+ import { AsyncTask } from "../AsyncTask"
5
+ import { Scriptable } from '../Scriptable'
6
+ import { AssetGraph } from "./AssetGraph"
7
+
8
+ type JsonAsset = { [k: string]: any }
9
+ type RawAsset = HTMLImageElement | ImageBitmap | HTMLAudioElement | AudioBuffer | HTMLVideoElement | string | JsonAsset
10
+ type StaticFactory = (url: string, forced?: boolean) => Promise<any>
11
+ type DescriptorProvider = () => Promise<Descriptor>
12
+ type ScriptableProvider = () => Promise<{ default: typeof Scriptable }>
13
+ type AssetProperty = { url: string }
14
+ type AssetPropertyCollection<T extends AssetProperty = AssetProperty> = T[]
15
+
16
+ const privateState = {
17
+ requestpPrefix: ['http://', 'https://'],
18
+ assetCache: new Map<string, RawAsset | Descriptor>(),
19
+ idToUrlCache: new Map<string, string>(),
20
+ providerCollection: new Map<string, DescriptorProvider | ScriptableProvider>(),
21
+ assetFactoryCollection: new Map<string, StaticFactory>(),
22
+ taskCollection: new Map<string, AsyncTask>(),
23
+ activeAssets: [] as string[],
24
+ parseStatus(url: string) {
25
+ const urlClips = url.split('/')
26
+ const name = urlClips[urlClips.length - 1]
27
+ if (name === undefined) return null
28
+
29
+ return Category.parseName(name.split('?')[0])
30
+ }
31
+ }
32
+
33
+ class Asset {
34
+ static baseUrl = ''
35
+ static graph = new AssetGraph()
36
+
37
+ static fetch(url: string, params?: any) {
38
+ return new Promise<Response>(async (resolve, reject) => {
39
+ const res = await fetch(url, params)
40
+ res.ok ? resolve(res) : reject(url)
41
+ })
42
+ }
43
+
44
+ static dumpCache() {
45
+ return [...privateState.assetCache.entries()]
46
+ }
47
+
48
+ static createVirtualUrl(fileName: string) {
49
+ return `/virtual:/${fileName}`
50
+ }
51
+
52
+ static provider(url: string, provider: DescriptorProvider | ScriptableProvider) {
53
+ privateState.providerCollection.set(url, provider)
54
+ }
55
+
56
+ static hasProvider(url: string) {
57
+ return privateState.providerCollection.has(url)
58
+ }
59
+
60
+ /**注册资产的生成器 */
61
+ static register(category: string, factory: StaticFactory) {
62
+ privateState.assetFactoryCollection.set(category, factory)
63
+ }
64
+
65
+ static joinUrl(url: string) {
66
+ for (const pre of privateState.requestpPrefix) {
67
+ if (url.indexOf(pre) > -1) return url
68
+ }
69
+ return `${Asset.baseUrl}${url}`
70
+ }
71
+
72
+ /**加载指定的资产文件
73
+ *
74
+ * 场景资产会自动根据`manifest`文件加载场景初始化时所需的所有资产,除此之外的其他资产仅加载它本身。
75
+ *
76
+ */
77
+ static load<U extends keyof SnowAssets>(url: U, forced?: boolean): Promise<void[]>
78
+ static load(url: string, forced?: boolean): Promise<void[]>
79
+ static async load(url: string | string[], forced = false) {
80
+ const urls = Array.isArray(url) ? url : [url]
81
+
82
+ const tasks: Promise<void>[] = []
83
+
84
+ for (const assetUrl of urls) {
85
+ if (!assetUrl) continue
86
+
87
+ const cacheAsset = this.get(assetUrl)
88
+ if (forced === false && cacheAsset !== null) continue
89
+
90
+ const factoryingTask = privateState.taskCollection.get(assetUrl)
91
+ if (factoryingTask) {
92
+ tasks.push(factoryingTask.done())
93
+ continue
94
+ }
95
+
96
+ const status = privateState.parseStatus(assetUrl)
97
+ if (status === null) continue
98
+
99
+ let factory = privateState.assetFactoryCollection.get(status.category)
100
+ if (factory === undefined) throw language.get('asset.load.fail', { category: status.category })
101
+
102
+ const task = new AsyncTask(async () => {
103
+ const asset = await factory(assetUrl, forced)
104
+ this.set(assetUrl, asset)
105
+ })
106
+ privateState.taskCollection.set(assetUrl, task)
107
+
108
+ tasks.push(task.run())
109
+
110
+ try {
111
+ await task.done()
112
+ } catch (error) {
113
+ console.log(error)
114
+ } finally {
115
+ privateState.taskCollection.delete(assetUrl)
116
+ }
117
+ }
118
+
119
+ return Promise.all(tasks)
120
+ }
121
+
122
+ static unload<U extends keyof SnowAssets>(url: U): void
123
+ static unload(url: string): void
124
+ static unload(url: string) {
125
+ const asset = this.get(url)
126
+ if (asset === null) return
127
+ privateState.assetCache.delete(url)
128
+ }
129
+
130
+ /**等待当前的资产文件加载完毕 */
131
+ static readly() {
132
+ const tasks = privateState.taskCollection.values()
133
+ const waits = []
134
+ for (const task of tasks) {
135
+ waits.push(task.done())
136
+ }
137
+ return Promise.all(waits)
138
+ }
139
+
140
+ static get<U extends keyof SnowAssets>(url: U): SnowAssets[U]
141
+ static get<T extends SnowAssets[keyof SnowAssets] = SnowAssets[keyof SnowAssets]>(url: keyof SnowAssets): T
142
+ static get<T extends RawAsset | Descriptor | null = Descriptor | null>(url: string): T
143
+ static get<T extends RawAsset | Descriptor | null = Descriptor | null>(url: string) {
144
+ return (privateState.assetCache.get(url) ?? null) as T
145
+ }
146
+
147
+ static set(url: string, asset: RawAsset | Descriptor) {
148
+ if (privateState.assetCache.has(url)) console.log(url, language.get('asset.already.exists'))
149
+ privateState.assetCache.set(url, asset)
150
+ if (asset instanceof Descriptor) {
151
+ privateState.idToUrlCache.set(asset.uuid, url)
152
+ this.graph.create(url)
153
+ }
154
+ }
155
+
156
+ static getTask(url: string) {
157
+ return privateState.taskCollection.get(url) ?? null
158
+ }
159
+
160
+ static getUrlByUuid(uuid: string) {
161
+ return privateState.idToUrlCache.get(uuid) ?? ''
162
+ }
163
+
164
+ static activate(...urls: string[]) {
165
+ privateState.activeAssets.push(...urls)
166
+ }
167
+
168
+ static free() {
169
+ privateState.activeAssets.length = 0
170
+ }
171
+
172
+ static async loadAll(url: string, forced = false, record: string[] = []) {
173
+ await Asset.load(url, forced)
174
+ Asset.graph.create(url)
175
+
176
+ record.push(url)
177
+ const dependencide = Asset.graph.getDependencide(url)
178
+
179
+ const tasks: Promise<void>[] = []
180
+ for (const dep of dependencide.all) {
181
+ if (record.includes(dep)) continue
182
+ const subForced = Asset.get(dep) ? false : true
183
+ tasks.push(this.loadAll(dep, subForced, record))
184
+ }
185
+
186
+ await Promise.all(tasks)
187
+ }
188
+ }
189
+
190
+ export { Asset, JsonAsset, RawAsset, DescriptorProvider, ScriptableProvider, AssetProperty, AssetPropertyCollection, privateState }
191
+
192
+ const getAssetByProvider = async (url: string) => {
193
+ const scriptableProvider = privateState.providerCollection.get(url)
194
+ if (scriptableProvider === undefined) return null
195
+ return await scriptableProvider() as unknown as any
196
+ }
197
+
198
+ const factoryDescriptor = async (url: string) => {
199
+ const preset = await getAssetByProvider(url)
200
+ if (preset !== null) return preset
201
+ const res = await Asset.fetch(Asset.joinUrl(url))
202
+ const text = await res.text()
203
+ const asset = Descriptor.create(Descriptor.deserialization(text))
204
+ return asset
205
+ }
206
+ Asset.register(Category.style, factoryDescriptor)
207
+ Asset.register(Category.material, factoryDescriptor)
208
+ Asset.register(Category.geometry, factoryDescriptor)
209
+ Asset.register(Category.texture, factoryDescriptor)
210
+ Asset.register(Category.prefab, factoryDescriptor)
211
+ Asset.register(Category.routine, factoryDescriptor)
212
+
213
+ const factoryDataset = async (url: string) => {
214
+ const asset = await factoryDescriptor(url) as DatasetDescriptor
215
+ if (asset.auto) await asset.fetch()
216
+ return asset
217
+ }
218
+
219
+ Asset.register(Category.dataset, factoryDataset)
220
+
221
+ const factoryJson = async (url: string) => {
222
+ const res = await Asset.fetch(Asset.joinUrl(url))
223
+ const text = await res.text()
224
+ return Descriptor.deserialization(text)
225
+ }
226
+ Asset.register(Category.json, factoryJson)
227
+
228
+ const factoryScene = (url: string, forced?: boolean) => {
229
+ return new Promise<Descriptor>(async (resolve, reject) => {
230
+ const sceneUrl = Asset.joinUrl(url)
231
+ try {
232
+ const res = await Asset.fetch(sceneUrl)
233
+
234
+ const scene = await res.text()
235
+
236
+ const sceneDes = Descriptor.create(Descriptor.deserialization(scene))
237
+
238
+ resolve(sceneDes)
239
+ } catch (error) {
240
+ reject(error)
241
+ }
242
+ })
243
+ }
244
+ Asset.register(Category.scene, factoryScene)
245
+
246
+ const factoryScript = (url: string) => {
247
+ return new Promise(async (resolve, reject) => {
248
+ try {
249
+ const module = await getAssetByProvider(url)
250
+ if (module === null) return reject(language.get('asset.provider.notFound', { url }))
251
+
252
+ /**
253
+ * Class constructor { ClassName } cannot be invoked without 'new'
254
+ *
255
+ * 将代码的编译目标(webpack、ts、vite等配置文件)调整为es6
256
+ */
257
+ const scriptable = new module.default(url)
258
+ await scriptable.ready()
259
+ resolve(scriptable)
260
+ } catch (error) {
261
+ reject(error)
262
+ }
263
+ })
264
+ }
265
+ Asset.register(Category.ts, factoryScript)
266
+
267
+ const factoryOther = async (url: string) => {
268
+ const res = await Asset.fetch(Asset.joinUrl(url))
269
+ return await res.arrayBuffer()
270
+ }
271
+ Asset.register(Category.other, factoryOther)
@@ -0,0 +1,246 @@
1
+ import { Asset } from "./Asset"
2
+ import { Category } from "../Category"
3
+ import { ArrayUtils } from "../ArrayUtils"
4
+ import { ObjectPool } from "../ObjectPool";
5
+ import { Descriptor } from "../descriptor";
6
+
7
+ interface Edge {
8
+ key: string
9
+ asset: string
10
+ category: string
11
+ }
12
+
13
+ interface Port {
14
+ descriptor: string
15
+ edges: Edge[]
16
+ }
17
+
18
+ interface Cell {
19
+ url: string
20
+ uuid: string
21
+ ports: Port[]
22
+ }
23
+
24
+ interface UrlCell {
25
+ url: string
26
+ cells: Cell[]
27
+ }
28
+
29
+ type Provider<T extends Descriptor = Descriptor> = (descriptor: T, port: Port) => void
30
+
31
+ const privateState = {
32
+ providerCollection: new Map<string, Provider>(),
33
+ }
34
+
35
+ class Dependencide {
36
+ all: string[] = []
37
+ descriptor: string[] = []
38
+ prefab: string[] = []
39
+ dataset: string[] = []
40
+ style: string[] = []
41
+ routine: string[] = []
42
+ texture: string[] = []
43
+ material: string[] = []
44
+ geometry: string[] = []
45
+
46
+ add(type: keyof Dependencide, url: string) {
47
+ const collection = this[type] as string[]
48
+ if (collection === undefined) return console.warn(type, url)
49
+ collection.push(url)
50
+ this.descriptor.push(url)
51
+ }
52
+
53
+ foreach(cb: (url: string) => void) {
54
+ for (const url of this.dataset) cb(url)
55
+ for (const url of this.style) cb(url)
56
+ for (const url of this.routine) cb(url)
57
+ for (const url of this.texture) cb(url)
58
+ for (const url of this.material) cb(url)
59
+ for (const url of this.geometry) cb(url)
60
+ }
61
+
62
+ clear() {
63
+ this.all.length = 0
64
+ this.descriptor.length = 0
65
+ this.prefab.length = 0
66
+ this.dataset.length = 0
67
+ this.style.length = 0
68
+ this.routine.length = 0
69
+ this.texture.length = 0
70
+ this.material.length = 0
71
+ this.geometry.length = 0
72
+ }
73
+ }
74
+
75
+ /**资产关系图,表示资产和资产之间的依赖关系 */
76
+ class AssetGraph {
77
+
78
+ private static build(descriptor: Descriptor, port: Port) {
79
+ let Prototype = descriptor.constructor as typeof Descriptor
80
+ while (Prototype.prototype instanceof ObjectPool) {
81
+ const provider = privateState.providerCollection.get(Prototype.type)
82
+ Prototype = Object.getPrototypeOf(Prototype)
83
+ if (provider === undefined) continue
84
+ provider(descriptor, port)
85
+ }
86
+ }
87
+
88
+ static register<T extends Descriptor = Descriptor>(type: string, provider: Provider<T>) {
89
+ privateState.providerCollection.set(type, provider as Provider)
90
+ }
91
+
92
+ static get(descriptor: Descriptor, ports: Port[] = []) {
93
+
94
+ const port: Port = { descriptor: descriptor.uuid, edges: [] }
95
+ this.build(descriptor, port)
96
+ if (port.edges.length > 0) ports.push(port)
97
+
98
+ return ports
99
+ }
100
+
101
+ /**依赖项集合 */
102
+ private _dependencideCollection = new Map<string, Cell>()
103
+ /**依赖者集合 */
104
+ private _dependentCollection = new Map<string, Cell[]>()
105
+
106
+ protected getDescriptor(url: string) {
107
+ return Asset.get<Descriptor | null>(url)
108
+ }
109
+
110
+ protected compiler(url: string) {
111
+ const cell: Cell = { url, uuid: '', ports: [] }
112
+ const descriptor = this.getDescriptor(url)
113
+ if (descriptor instanceof Descriptor) {
114
+ cell.uuid = descriptor.uuid
115
+ this.build(descriptor, cell.ports)
116
+ }
117
+ return cell
118
+ }
119
+
120
+ protected setCell(asset: string, cell: Cell) {
121
+ let collection = this._dependentCollection.get(asset)
122
+ if (collection === undefined) {
123
+ collection = [cell]
124
+ this._dependentCollection.set(asset, collection)
125
+ } else {
126
+ ArrayUtils.insert(collection, cell)
127
+ }
128
+ }
129
+
130
+ protected deleteCell(asset: string, cell: Cell) {
131
+ let collection = this._dependentCollection.get(asset)
132
+ if (collection === undefined) return
133
+ ArrayUtils.remove(collection, cell)
134
+ }
135
+
136
+ protected collection(asset: string, dependencide: Dependencide, isDescriptor: boolean, category: keyof Dependencide) {
137
+ const index = dependencide.all.indexOf(asset)
138
+ if (index > -1) return
139
+ dependencide.all.push(asset)
140
+ if (isDescriptor) dependencide.add(category, asset)
141
+ this.getDependencide(asset, dependencide)
142
+ }
143
+
144
+ get(url: string) {
145
+ return this._dependencideCollection.get(url) ?? null
146
+ }
147
+
148
+ /**创建资产的依赖关系图 */
149
+ create(url: string) {
150
+ this.delete(url)
151
+
152
+ const cell = this.compiler(url)
153
+ this._dependencideCollection.set(url, cell)
154
+
155
+ for (const port of cell.ports) {
156
+ for (const edge of port.edges) {
157
+ this.setCell(edge.asset, cell)
158
+ }
159
+ }
160
+ }
161
+
162
+ build(descriptor: Descriptor, ports: Port[] = []) {
163
+ descriptor.traverse(sub => { AssetGraph.get(sub, ports) })
164
+ return ports
165
+ }
166
+
167
+ /**更新资产的依赖关系图 */
168
+ update(url: string) {
169
+ this.delete(url)
170
+ this.create(url)
171
+ }
172
+
173
+ /**将资产从依赖关系图中删除 */
174
+ delete(url: string) {
175
+ const cell = this._dependencideCollection.get(url)
176
+ if (cell === undefined) return
177
+ this._dependencideCollection.delete(url)
178
+
179
+ for (const port of cell.ports) {
180
+ for (const edge of port.edges) {
181
+ this.deleteCell(edge.asset, cell)
182
+ }
183
+ }
184
+ }
185
+
186
+ /**获取Ports所依赖的全部资产
187
+ * - 0 获取所有资产
188
+ * - 1 仅获取描述器资产
189
+ */
190
+ getDependencidesByPorts(ports: Port[], dependencide = new Dependencide()) {
191
+ if (ports.length === 0) return dependencide
192
+ for (const port of ports) {
193
+ for (const edge of port.edges) {
194
+ const isDescriptor = Category.isDescriptor(edge.category, 'category')
195
+ this.collection(edge.asset, dependencide, isDescriptor, edge.category as keyof Dependencide)
196
+ }
197
+ }
198
+ return dependencide
199
+ }
200
+
201
+ /**获取指定资产所依赖的全部资产
202
+ * - 0 获取所有资产
203
+ * - 1 仅获取描述器资产
204
+ */
205
+ getDependencide(url: string, dependencide = new Dependencide()) {
206
+ const cell = this._dependencideCollection.get(url)
207
+ if (cell === undefined) return dependencide
208
+ this.getDependencidesByPorts(cell.ports, dependencide)
209
+ return dependencide
210
+ }
211
+
212
+ /**获取指定资产的所有依赖者 */
213
+ getDependents(url: string) {
214
+ return this._dependentCollection.get(url) ?? []
215
+ }
216
+
217
+ getUrlCells(urls: string[], urlCells: UrlCell[] = []) {
218
+ for (const url of urls) {
219
+ const cells = this.getDependents(url)
220
+ if (cells.length > 0) urlCells.push({ url, cells })
221
+ }
222
+ return urlCells
223
+ }
224
+
225
+ forEdge(cell: Cell, cb: (port: Port, edge: Edge) => void) {
226
+ for (const port of cell.ports) {
227
+ for (const edge of port.edges) cb(port, edge)
228
+ }
229
+ }
230
+
231
+ hasAssetReference(port: Port, url: string) {
232
+ for (const edge of port.edges) {
233
+ if (Array.isArray(edge.asset)) {
234
+ for (const asset of edge.asset) {
235
+ if (asset === url) return true
236
+ }
237
+ } else {
238
+ if (edge.asset === url) return true
239
+ }
240
+ }
241
+
242
+ return false
243
+ }
244
+ }
245
+
246
+ export { Edge, Port, Cell, UrlCell, Dependencide, AssetGraph }
@@ -0,0 +1,2 @@
1
+ export * from './Asset'
2
+ export * from './AssetGraph'
@@ -0,0 +1,65 @@
1
+ import { DeserializationObject } from "../Serialization"
2
+ import { Descriptor } from "./Descriptor"
3
+
4
+ interface FrameData {
5
+ type: string
6
+ startValue: Array<string | number | boolean> | number | string
7
+ endValue: Array<string | number | boolean> | number | string
8
+ }
9
+
10
+ interface NumberFrameData extends FrameData {
11
+ type: 'number' | 'boolean'
12
+ startValue: number
13
+ endValue: number
14
+ }
15
+
16
+ interface VectorFrameData extends FrameData {
17
+ type: 'vector2' | 'vector3' | 'euler'
18
+ startValue: number[]
19
+ endValue: number[]
20
+ }
21
+
22
+ interface ColorFrameData extends FrameData {
23
+ type: 'color'
24
+ startValue: string
25
+ endValue: string
26
+ }
27
+
28
+ type AnimationFrameData = NumberFrameData | VectorFrameData | ColorFrameData
29
+
30
+ class AnimationUnitDescriptor extends Descriptor {
31
+ static type = 'AnimationUnit'
32
+
33
+ play: boolean
34
+ duration: number
35
+ /**循环次数 */
36
+ count: number
37
+ /**循环模式
38
+ *
39
+ * - 1 顺序循环
40
+ * - 2 往返循环
41
+ */
42
+ mode: number
43
+ startTime: number
44
+ path: string
45
+ frameData: AnimationFrameData
46
+
47
+ constructor(descriptor: Partial<DeserializationObject<AnimationUnitDescriptor>> = {}) {
48
+ super(descriptor)
49
+ this.play = descriptor.play ?? false
50
+ this.duration = descriptor.duration ?? 0
51
+ this.count = descriptor.count ?? Infinity
52
+ this.mode = descriptor.mode ?? 1
53
+ this.startTime = descriptor.startTime ?? 0
54
+ this.path = descriptor.path ?? ''
55
+ this.frameData = descriptor.frameData ? Descriptor.deepClone<AnimationFrameData>(descriptor.frameData) : { type: 'vector2', startValue: [], endValue: [] } as VectorFrameData
56
+ }
57
+ }
58
+ Descriptor.register(AnimationUnitDescriptor)
59
+
60
+ export {
61
+ NumberFrameData,
62
+ VectorFrameData,
63
+ AnimationFrameData,
64
+ AnimationUnitDescriptor
65
+ }
@@ -0,0 +1,12 @@
1
+ import { DeserializationObject } from "../Serialization"
2
+ import { NodeDescriptor } from "./NodeDescriptor"
3
+
4
+ class CameraDescriptor extends NodeDescriptor {
5
+ static type = 'Camera'
6
+
7
+ constructor(descriptor: Partial<DeserializationObject<CameraDescriptor>> = {}) {
8
+ super(descriptor)
9
+ }
10
+ }
11
+
12
+ export { CameraDescriptor }