@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
|
@@ -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,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 }
|