@vyr/remote 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 +18 -0
- package/src/Bridge.ts +133 -0
- package/src/ChangeScriptable.ts +22 -0
- package/src/Collection.ts +36 -0
- package/src/RemoteExecutor.ts +514 -0
- package/src/RemoteInvoker.ts +72 -0
- package/src/RemoteProcess.ts +87 -0
- package/src/index.ts +7 -0
- package/src/job/IJob.ts +6 -0
- package/src/job/Job.ts +16 -0
- package/src/job/asset/add.ts +23 -0
- package/src/job/asset/dragdrap.ts +24 -0
- package/src/job/asset/index.ts +6 -0
- package/src/job/asset/load.ts +20 -0
- package/src/job/asset/remove.ts +20 -0
- package/src/job/asset/unload.ts +18 -0
- package/src/job/asset/update.ts +22 -0
- package/src/job/bridge/connection.ts +18 -0
- package/src/job/bridge/disconnect.ts +29 -0
- package/src/job/bridge/index.ts +2 -0
- package/src/job/index.ts +1 -0
- package/src/job/invoke/alert.ts +20 -0
- package/src/job/invoke/animation.ts +45 -0
- package/src/job/invoke/event.ts +40 -0
- package/src/job/invoke/index.ts +8 -0
- package/src/job/invoke/orbit.ts +20 -0
- package/src/job/invoke/pick.ts +15 -0
- package/src/job/invoke/properties.ts +43 -0
- package/src/job/invoke/screenshot.ts +35 -0
- package/src/job/invoke/transform.ts +36 -0
- package/src/job/scene/add.ts +22 -0
- package/src/job/scene/dragdrap.ts +23 -0
- package/src/job/scene/index.ts +6 -0
- package/src/job/scene/load.ts +19 -0
- package/src/job/scene/remove.ts +19 -0
- package/src/job/scene/unload.ts +17 -0
- package/src/job/scene/update.ts +20 -0
- package/src/locale/Language.ts +10 -0
- package/src/locale/LanguageProvider.ts +15 -0
- package/src/locale/index.ts +2 -0
- package/src/utils/index.ts +85 -0
- package/src/utils/screenshot.ts +20 -0
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
import { AnimationUnitInterpreter, Asset, Compilation, Descriptor, DeserializationObject, DivDescriptor, DynamicDescriptor, Engine, Graphics, HTMLDescriptor, HTMLServiceDescriptor, HTMLTransformControllerDescriptor, observer, PrefabeDescriptor, ServiceDescriptor, ServiceSchedulerDescriptor, StyleDescriptor, Unit, UpdateArgs } from '@vyr/engine'
|
|
2
|
+
import { cleanPickupObject, getAnimationUnit, createControllerStyle, pickupObject, getAnimationUnitByAsset, screenshot } from './utils'
|
|
3
|
+
import { Collection } from './Collection'
|
|
4
|
+
import { RemoteProcess } from './RemoteProcess'
|
|
5
|
+
import { Job } from './job'
|
|
6
|
+
|
|
7
|
+
class RemoteExecutor {
|
|
8
|
+
private _defaultScheduleUrl = Asset.createVirtualUrl('remote/schedule/default.ts')
|
|
9
|
+
readonly htmlTransformCollection = new Collection()
|
|
10
|
+
readonly process
|
|
11
|
+
|
|
12
|
+
constructor(process: RemoteProcess) {
|
|
13
|
+
this.process = process
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async loadByScene(task: InstanceType<typeof Job['scene']['load']['Task']>) {
|
|
17
|
+
let loadTask = Asset.getTask(task.params.url)
|
|
18
|
+
if (loadTask === null) {
|
|
19
|
+
const nextTask = Asset.getTask(this.process.scene)
|
|
20
|
+
nextTask?.cancel()
|
|
21
|
+
|
|
22
|
+
this.process.scene = task.params.url
|
|
23
|
+
await Asset.loadAll(task.params.url)
|
|
24
|
+
|
|
25
|
+
//渲染新场景
|
|
26
|
+
const scheduler = Asset.get<ServiceSchedulerDescriptor>(task.params.url)
|
|
27
|
+
if (this.process.config.invoke) {
|
|
28
|
+
scheduler.traverse(sub => {
|
|
29
|
+
if (sub instanceof ServiceDescriptor) this.onAddService(sub)
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnit(scheduler))
|
|
34
|
+
|
|
35
|
+
this.process.scheduler = scheduler
|
|
36
|
+
this.process.engine.switch(scheduler)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async unloadByScene(task: InstanceType<typeof Job['scene']['unload']['Task']>) {
|
|
40
|
+
const scheduler = Asset.get<ServiceSchedulerDescriptor>(this.process.scene)
|
|
41
|
+
if (scheduler !== null) {
|
|
42
|
+
scheduler.traverse(child => {
|
|
43
|
+
if (child instanceof ServiceDescriptor) this.onRemoveService(child)
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const nextTask = Asset.getTask(this.process.scene)
|
|
48
|
+
nextTask?.cancel()
|
|
49
|
+
this.process.scene = ''
|
|
50
|
+
this.process.scheduler = new ServiceSchedulerDescriptor()
|
|
51
|
+
this.process.engine.switch(this.process.scheduler)
|
|
52
|
+
}
|
|
53
|
+
async addByScene(task: InstanceType<typeof Job['scene']['add']['Task']>) {
|
|
54
|
+
const target = Descriptor.get<Descriptor>(task.params.parent)
|
|
55
|
+
if (target === null) return
|
|
56
|
+
|
|
57
|
+
const subs: Descriptor[] = []
|
|
58
|
+
const tasks: Promise<void>[] = []
|
|
59
|
+
for (const node of task.params.node) {
|
|
60
|
+
const sub = Descriptor.create(node)
|
|
61
|
+
subs.push(sub)
|
|
62
|
+
|
|
63
|
+
const ports = Asset.graph.build(sub)
|
|
64
|
+
const dep = Asset.graph.getDependencidesByPorts(ports)
|
|
65
|
+
for (const url of dep.all) {
|
|
66
|
+
if (Asset.get(url) === null) tasks.push(Asset.loadAll(url, false))
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (this.process.config.invoke) {
|
|
70
|
+
sub.traverse(child => {
|
|
71
|
+
if (child instanceof ServiceDescriptor) this.onAddService(child)
|
|
72
|
+
})
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
await Promise.all(tasks)
|
|
77
|
+
|
|
78
|
+
if (task.params.next) {
|
|
79
|
+
for (const sub of subs) target.insertBefore(sub.uuid, task.params.next)
|
|
80
|
+
} else {
|
|
81
|
+
for (const sub of subs) target.add(sub)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
await Asset.loadAll(this.process.scene)
|
|
85
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnit(this.process.scheduler))
|
|
86
|
+
}
|
|
87
|
+
async removeyScene(task: InstanceType<typeof Job['scene']['remove']['Task']>) {
|
|
88
|
+
for (const uuid of task.params.uuids) {
|
|
89
|
+
const target = Descriptor.get<Descriptor>(uuid)
|
|
90
|
+
if (target === null) continue
|
|
91
|
+
|
|
92
|
+
this.resetTransformByRemoveJob(target)
|
|
93
|
+
|
|
94
|
+
const acestor = target.traceAncestor()
|
|
95
|
+
if (acestor.parent) acestor.parent.remove(target)
|
|
96
|
+
|
|
97
|
+
if (this.process.config.invoke) {
|
|
98
|
+
target.traverse(child => {
|
|
99
|
+
if (child instanceof ServiceDescriptor) this.onRemoveService(child)
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await Asset.loadAll(this.process.scene)
|
|
105
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnit(this.process.scheduler))
|
|
106
|
+
}
|
|
107
|
+
async dragdrapyScene(task: InstanceType<typeof Job['scene']['dragdrap']['Task']>) {
|
|
108
|
+
const root = Asset.get<Descriptor>(this.process.scene)
|
|
109
|
+
if (root) {
|
|
110
|
+
|
|
111
|
+
const method = task.params.next ? 'insertBefore' : task.params.type
|
|
112
|
+
const target = task.params.next || task.params.targetData.data.uuid
|
|
113
|
+
|
|
114
|
+
for (const uuid of task.params.dragData.data.uuids) {
|
|
115
|
+
root[method](uuid, target)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
async updateyScene(task: InstanceType<typeof Job['scene']['update']['Task']>) {
|
|
120
|
+
const target = Descriptor.get<Descriptor>(task.params.content.uuid)
|
|
121
|
+
if (target === null) return
|
|
122
|
+
|
|
123
|
+
const temp = target.clone(false)
|
|
124
|
+
temp.syncWith(task.params.content)
|
|
125
|
+
const ports = Asset.graph.build(temp)
|
|
126
|
+
const dep = Asset.graph.getDependencidesByPorts(ports)
|
|
127
|
+
const tasks: Promise<void>[] = []
|
|
128
|
+
for (const url of dep.all) {
|
|
129
|
+
if (Asset.get(url) === null) tasks.push(Asset.loadAll(url, false))
|
|
130
|
+
}
|
|
131
|
+
await Promise.all(tasks)
|
|
132
|
+
|
|
133
|
+
this.updateOtherUpdateJob(target, task.params.content)
|
|
134
|
+
target.syncWith(task.params.content)
|
|
135
|
+
await Asset.loadAll(this.process.scene)
|
|
136
|
+
|
|
137
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnit(this.process.scheduler))
|
|
138
|
+
|
|
139
|
+
target.setNeedsUpdate()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async loadByAsset(task: InstanceType<typeof Job['asset']['load']['Task']>) {
|
|
143
|
+
let loadTask = Asset.getTask(task.params.url)
|
|
144
|
+
if (loadTask === null) {
|
|
145
|
+
const nextTask = Asset.getTask(this.process.asset)
|
|
146
|
+
nextTask?.cancel()
|
|
147
|
+
|
|
148
|
+
this.process.asset = task.params.url
|
|
149
|
+
await Asset.loadAll(task.params.url)
|
|
150
|
+
|
|
151
|
+
const scheduler = new ServiceSchedulerDescriptor()
|
|
152
|
+
const descriptor = Asset.get<Descriptor>(task.params.url)
|
|
153
|
+
if (descriptor instanceof PrefabeDescriptor && descriptor.category === 'html') {
|
|
154
|
+
const service = new HTMLServiceDescriptor()
|
|
155
|
+
service.add(descriptor)
|
|
156
|
+
scheduler.add(service)
|
|
157
|
+
} else {
|
|
158
|
+
this.onLoadAsset(task.params.url, descriptor, scheduler)
|
|
159
|
+
}
|
|
160
|
+
scheduler.traverse(sub => {
|
|
161
|
+
if (sub instanceof ServiceDescriptor) this.onAddService(sub)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
Asset.set(this._defaultScheduleUrl, scheduler)
|
|
165
|
+
Asset.graph.create(task.params.url)
|
|
166
|
+
|
|
167
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnitByAsset(task.params.url))
|
|
168
|
+
|
|
169
|
+
this.process.scheduler = scheduler
|
|
170
|
+
this.process.engine.switch(scheduler)
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async unloadByAsset(task: InstanceType<typeof Job['asset']['unload']['Task']>) {
|
|
174
|
+
const scheduler = Asset.get<ServiceSchedulerDescriptor>(this.process.asset)
|
|
175
|
+
if (scheduler !== null) {
|
|
176
|
+
|
|
177
|
+
if (this.process.config.invoke) {
|
|
178
|
+
scheduler.traverse(child => {
|
|
179
|
+
if (child instanceof ServiceDescriptor) this.onRemoveService(child)
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const nextTask = Asset.getTask(this.process.asset)
|
|
185
|
+
nextTask?.cancel()
|
|
186
|
+
this.process.asset = ''
|
|
187
|
+
|
|
188
|
+
this.process.scheduler = new ServiceSchedulerDescriptor()
|
|
189
|
+
this.process.engine.switch(this.process.scheduler)
|
|
190
|
+
}
|
|
191
|
+
async addByAsset(task: InstanceType<typeof Job['asset']['add']['Task']>) {
|
|
192
|
+
const parent = Descriptor.get<Descriptor>(task.params.parent)
|
|
193
|
+
if (parent === null) return
|
|
194
|
+
|
|
195
|
+
const subs: Descriptor[] = []
|
|
196
|
+
const tasks: Promise<void>[] = []
|
|
197
|
+
|
|
198
|
+
for (const node of task.params.node) {
|
|
199
|
+
const sub = Descriptor.create(node)
|
|
200
|
+
subs.push(sub)
|
|
201
|
+
|
|
202
|
+
const ports = Asset.graph.build(sub)
|
|
203
|
+
const dep = Asset.graph.getDependencidesByPorts(ports)
|
|
204
|
+
for (const url of dep.all) {
|
|
205
|
+
if (Asset.get(url) === null) tasks.push(Asset.loadAll(url, false))
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
sub.traverse(child => {
|
|
209
|
+
if (child instanceof ServiceDescriptor) this.onAddService(child)
|
|
210
|
+
})
|
|
211
|
+
}
|
|
212
|
+
await Promise.all(tasks)
|
|
213
|
+
|
|
214
|
+
if (task.params.next) {
|
|
215
|
+
for (const sub of subs) parent.insertBefore(sub.uuid, task.params.next)
|
|
216
|
+
} else {
|
|
217
|
+
for (const sub of subs) parent.add(sub)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
await Asset.loadAll(task.params.url)
|
|
221
|
+
Asset.graph.update(this._defaultScheduleUrl)
|
|
222
|
+
|
|
223
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnitByAsset(task.params.url))
|
|
224
|
+
}
|
|
225
|
+
async removeyAsset(task: InstanceType<typeof Job['asset']['remove']['Task']>) {
|
|
226
|
+
for (const uuid of task.params.uuids) {
|
|
227
|
+
const target = Descriptor.get<Descriptor>(uuid)
|
|
228
|
+
if (target === null) continue
|
|
229
|
+
|
|
230
|
+
this.resetTransformByRemoveJob(target)
|
|
231
|
+
|
|
232
|
+
const acestor = target.traceAncestor()
|
|
233
|
+
if (acestor.parent) acestor.parent.remove(target)
|
|
234
|
+
|
|
235
|
+
if (this.process.config.invoke) {
|
|
236
|
+
target.traverse(child => {
|
|
237
|
+
if (child instanceof ServiceDescriptor) this.onRemoveService(child)
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
await Asset.loadAll(task.params.url)
|
|
243
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnitByAsset(task.params.url))
|
|
244
|
+
}
|
|
245
|
+
async dragdrapyAsset(task: InstanceType<typeof Job['asset']['dragdrap']['Task']>) {
|
|
246
|
+
const root = Asset.get<Descriptor>(task.params.url)
|
|
247
|
+
if (root) {
|
|
248
|
+
|
|
249
|
+
const method = task.params.next ? 'insertBefore' : task.params.type
|
|
250
|
+
const target = task.params.next || task.params.targetData.data.uuid
|
|
251
|
+
|
|
252
|
+
for (const uuid of task.params.dragData.data.uuids) {
|
|
253
|
+
root[method](uuid, target)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async updateyAsset(task: InstanceType<typeof Job['asset']['update']['Task']>) {
|
|
258
|
+
const target = Descriptor.get<Descriptor>(task.params.content.uuid)
|
|
259
|
+
if (target === null) return
|
|
260
|
+
|
|
261
|
+
const temp = target.clone(false)
|
|
262
|
+
temp.syncWith(task.params.content)
|
|
263
|
+
const ports = Asset.graph.build(temp)
|
|
264
|
+
const dep = Asset.graph.getDependencidesByPorts(ports)
|
|
265
|
+
const tasks: Promise<void>[] = []
|
|
266
|
+
for (const url of dep.all) {
|
|
267
|
+
if (Asset.get(url) === null) tasks.push(Asset.loadAll(url, false))
|
|
268
|
+
}
|
|
269
|
+
await Promise.all(tasks)
|
|
270
|
+
|
|
271
|
+
this.updateOtherUpdateJob(target, task.params.content)
|
|
272
|
+
target.syncWith(task.params.content)
|
|
273
|
+
await Asset.loadAll(task.params.url)
|
|
274
|
+
Asset.graph.update(this._defaultScheduleUrl)
|
|
275
|
+
|
|
276
|
+
this.sendAnimationUnitToRemote(0, getAnimationUnitByAsset(task.params.url))
|
|
277
|
+
|
|
278
|
+
target.setNeedsUpdate()
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
clearHTMLTransform() {
|
|
282
|
+
const htmlTransforms = this.htmlTransformCollection.values()
|
|
283
|
+
for (const item of htmlTransforms) {
|
|
284
|
+
item.target = ''
|
|
285
|
+
item.mode = ''
|
|
286
|
+
item.enabled = false
|
|
287
|
+
item.setNeedsUpdate()
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async transformByInvoke(task: InstanceType<typeof Job['invoke']['transform']['Task']>, service: ServiceDescriptor | null = null) {
|
|
291
|
+
this.clearHTMLTransform()
|
|
292
|
+
|
|
293
|
+
const target = Descriptor.get<Descriptor>(task.params.target)
|
|
294
|
+
if (service === null) {
|
|
295
|
+
service = ServiceDescriptor.traceService(target)
|
|
296
|
+
} else {
|
|
297
|
+
const isHTMLServiceDescriptor = service instanceof HTMLServiceDescriptor
|
|
298
|
+
if (isHTMLServiceDescriptor === false) return
|
|
299
|
+
}
|
|
300
|
+
if (service === null) return
|
|
301
|
+
|
|
302
|
+
const enabled = ['translate', 'rotate', 'scale'].includes(task.params.mode)
|
|
303
|
+
const htmlTransform = this.htmlTransformCollection.get<HTMLTransformControllerDescriptor>(service)
|
|
304
|
+
|
|
305
|
+
if (htmlTransform !== null && enabled === true && target instanceof HTMLDescriptor) {
|
|
306
|
+
htmlTransform.target = task.params.target
|
|
307
|
+
htmlTransform.mode = task.params.mode
|
|
308
|
+
htmlTransform.enabled = true
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
async orbitByInvoke(task: InstanceType<typeof Job['invoke']['orbit']['Task']>) { }
|
|
312
|
+
async propertiesByInvoke(task: InstanceType<typeof Job['invoke']['properties']['Task']>) { }
|
|
313
|
+
async animationByInvoke(task: InstanceType<typeof Job['invoke']['animation']['Task']>) {
|
|
314
|
+
if (task.reset) AnimationUnitInterpreter.reset(task.params.currentTime)
|
|
315
|
+
AnimationUnitInterpreter.enabled = task.params.enabled
|
|
316
|
+
}
|
|
317
|
+
async screenshot(task: InstanceType<typeof Job['invoke']['screenshot']['Task']>) {
|
|
318
|
+
const base64 = await screenshot(document.body)
|
|
319
|
+
const msg = new Job.invoke.screenshot.Response({ target: task.params.target, base64 })
|
|
320
|
+
this.process.bridge.send(msg)
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
onLoadAsset(url: string, descriptor: Descriptor, scheduler: ServiceSchedulerDescriptor) {
|
|
324
|
+
if (descriptor instanceof StyleDescriptor) {
|
|
325
|
+
const service = new HTMLServiceDescriptor()
|
|
326
|
+
service.add(new DivDescriptor({ style: url, text: '演示文字' }))
|
|
327
|
+
scheduler.add(service)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
onAddService(service: ServiceDescriptor) {
|
|
331
|
+
if (service instanceof HTMLServiceDescriptor) {
|
|
332
|
+
let htmlTransform = this.htmlTransformCollection.get(service)
|
|
333
|
+
if (htmlTransform === null) {
|
|
334
|
+
htmlTransform = new HTMLTransformControllerDescriptor({ enabled: false, selectable: false })
|
|
335
|
+
this.htmlTransformCollection.set(service, htmlTransform)
|
|
336
|
+
htmlTransform.event = RemoteProcess.transformEvent
|
|
337
|
+
}
|
|
338
|
+
service.add(htmlTransform as HTMLTransformControllerDescriptor)
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
onRemoveService(service: ServiceDescriptor) {
|
|
342
|
+
if (service instanceof HTMLServiceDescriptor) {
|
|
343
|
+
const htmlTransform = this.htmlTransformCollection.get<HTMLTransformControllerDescriptor>(service)
|
|
344
|
+
if (htmlTransform !== null) {
|
|
345
|
+
this.htmlTransformCollection.delete(service)
|
|
346
|
+
service.remove(htmlTransform)
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
onUpdateScheduler(unit: Unit, args: UpdateArgs) {
|
|
351
|
+
const htmlTransform = Descriptor.get<Descriptor>(unit.uuid)
|
|
352
|
+
const service = this.htmlTransformCollection.getByMap(htmlTransform)
|
|
353
|
+
if (service !== null) {
|
|
354
|
+
//@ts-ignore
|
|
355
|
+
window['__VYR_RUNTIME.DISABLED_INPUT'] = false
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
resetTransformByRemoveJob(target: Descriptor, service: ServiceDescriptor | null = null) {
|
|
360
|
+
if (service === null) service = ServiceDescriptor.traceService(target)
|
|
361
|
+
|
|
362
|
+
if (service instanceof HTMLServiceDescriptor) {
|
|
363
|
+
const htmlTransform = this.htmlTransformCollection.get<HTMLTransformControllerDescriptor>(service)
|
|
364
|
+
if (htmlTransform === null) return
|
|
365
|
+
|
|
366
|
+
if (htmlTransform.target === target.uuid) {
|
|
367
|
+
htmlTransform.target = ''
|
|
368
|
+
htmlTransform.enabled = false
|
|
369
|
+
htmlTransform.setNeedsUpdate()
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
private _updateStyle(target: StyleDescriptor, deserialization: DeserializationObject<StyleDescriptor>) {
|
|
374
|
+
if (target.inherit === deserialization.inherit) return
|
|
375
|
+
observer.trigger('updateDeps', { self: target.uuid })
|
|
376
|
+
}
|
|
377
|
+
updateOtherUpdateJob(target: Descriptor, deserialization: DeserializationObject<Descriptor>, service: ServiceDescriptor | null = null) {
|
|
378
|
+
if (target instanceof StyleDescriptor) this._updateStyle(target, deserialization as any)
|
|
379
|
+
if (service === null) {
|
|
380
|
+
service = ServiceDescriptor.traceService(target)
|
|
381
|
+
}
|
|
382
|
+
if (service === null) return
|
|
383
|
+
const htmlTransform = this.htmlTransformCollection.get<HTMLTransformControllerDescriptor>(service)
|
|
384
|
+
if (htmlTransform === null) return
|
|
385
|
+
if (htmlTransform.target === target.uuid) {
|
|
386
|
+
this.process.engine.listen('afterRender', () => htmlTransform.setNeedsUpdate(), { once: true })
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
enhance(process: RemoteProcess, schedulerWrapper: ((scheduler: ServiceSchedulerDescriptor) => void) | null = null) {
|
|
391
|
+
const executor = process.getExecutor()
|
|
392
|
+
const listen = Compilation.prototype.listen
|
|
393
|
+
|
|
394
|
+
Compilation.prototype.listen = function (scheduler: ServiceSchedulerDescriptor, engine: Engine) {
|
|
395
|
+
if (schedulerWrapper !== null) schedulerWrapper(scheduler)
|
|
396
|
+
listen.call(this, scheduler, engine)
|
|
397
|
+
const graphics = engine.getGraphics(scheduler)
|
|
398
|
+
if (graphics === null || graphics.__VYR_REMOTE_WRAPPER === true) return graphics
|
|
399
|
+
graphics.__VYR_REMOTE_WRAPPER = true
|
|
400
|
+
|
|
401
|
+
return graphics
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
const doUpdate = Graphics.prototype.doUpdate
|
|
405
|
+
Graphics.prototype.doUpdate = function (unit: Unit, args: UpdateArgs) {
|
|
406
|
+
if (this.__VYR_REMOTE_WRAPPER === true) {
|
|
407
|
+
//@ts-ignore
|
|
408
|
+
window['__VYR_RUNTIME.DISABLED_INPUT'] = true
|
|
409
|
+
executor.onUpdateScheduler(unit, args)
|
|
410
|
+
doUpdate.call(this, unit, args)
|
|
411
|
+
} else {
|
|
412
|
+
doUpdate.call(this, unit, args)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
process.engine.listen('afterRender', (args) => this.sendAnimationUnitToRemote(args.delta))
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
protected stopWheel(e: WheelEvent) {
|
|
420
|
+
if (e.ctrlKey === true) {
|
|
421
|
+
e.preventDefault()
|
|
422
|
+
e.stopPropagation()
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
protected onEvent(event: MouseEvent | KeyboardEvent) {
|
|
426
|
+
let task
|
|
427
|
+
if (event instanceof MouseEvent) {
|
|
428
|
+
task = new Job.invoke.event.Response({
|
|
429
|
+
type: 'mouse',
|
|
430
|
+
properties: {
|
|
431
|
+
type: event.type,
|
|
432
|
+
bubbles: event.bubbles,
|
|
433
|
+
cancelable: event.cancelable,
|
|
434
|
+
altKey: event.altKey,
|
|
435
|
+
ctrlKey: event.ctrlKey,
|
|
436
|
+
shiftKey: event.shiftKey,
|
|
437
|
+
clientX: event.clientX,
|
|
438
|
+
clientY: event.clientY,
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
} else {
|
|
442
|
+
task = new Job.invoke.event.Response({
|
|
443
|
+
type: 'keyboard',
|
|
444
|
+
properties: {
|
|
445
|
+
type: event.type,
|
|
446
|
+
altKey: event.altKey,
|
|
447
|
+
ctrlKey: event.ctrlKey,
|
|
448
|
+
shiftKey: event.shiftKey,
|
|
449
|
+
code: event.code,
|
|
450
|
+
}
|
|
451
|
+
})
|
|
452
|
+
if (event.code === 'Tab') event.preventDefault()
|
|
453
|
+
}
|
|
454
|
+
this.process.bridge.send(task)
|
|
455
|
+
}
|
|
456
|
+
protected onMessage(args: any) {
|
|
457
|
+
if (args.type === DynamicDescriptor.type) {
|
|
458
|
+
//动态节点发生了循环引用,动态节点 arsg.uuid
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
sendAnimationUnitToRemote(delta: number, max?: number) {
|
|
463
|
+
this.process.bridge.send(new Job.invoke.animation.Response({ type: 'unit', delta, max }))
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
async listen() {
|
|
467
|
+
window.addEventListener('wheel', this.stopWheel, { passive: false })
|
|
468
|
+
|
|
469
|
+
if (this.process.config.execute) {
|
|
470
|
+
this.process.bridge.listen(Job.asset.load.Method, this.loadByAsset.bind(this))
|
|
471
|
+
this.process.bridge.listen(Job.asset.unload.Method, this.unloadByAsset.bind(this))
|
|
472
|
+
this.process.bridge.listen(Job.asset.add.Method, this.addByAsset.bind(this))
|
|
473
|
+
this.process.bridge.listen(Job.asset.remove.Method, this.removeyAsset.bind(this))
|
|
474
|
+
this.process.bridge.listen(Job.asset.dragdrap.Method, this.dragdrapyAsset.bind(this))
|
|
475
|
+
this.process.bridge.listen(Job.asset.update.Method, this.updateyAsset.bind(this))
|
|
476
|
+
|
|
477
|
+
this.process.bridge.listen(Job.scene.load.Method, this.loadByScene.bind(this))
|
|
478
|
+
this.process.bridge.listen(Job.scene.unload.Method, this.unloadByScene.bind(this))
|
|
479
|
+
this.process.bridge.listen(Job.scene.add.Method, this.addByScene.bind(this))
|
|
480
|
+
this.process.bridge.listen(Job.scene.remove.Method, this.removeyScene.bind(this))
|
|
481
|
+
this.process.bridge.listen(Job.scene.dragdrap.Method, this.dragdrapyScene.bind(this))
|
|
482
|
+
this.process.bridge.listen(Job.scene.update.Method, this.updateyScene.bind(this))
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (this.process.config.invoke) {
|
|
486
|
+
createControllerStyle()
|
|
487
|
+
pickupObject(this.process)
|
|
488
|
+
cleanPickupObject(this.process)
|
|
489
|
+
this.enhance(this.process)
|
|
490
|
+
|
|
491
|
+
this.process.bridge.listen(Job.invoke.transform.Method, this.transformByInvoke.bind(this))
|
|
492
|
+
this.process.bridge.listen(Job.invoke.orbit.Method, this.orbitByInvoke.bind(this))
|
|
493
|
+
this.process.bridge.listen(Job.invoke.properties.Method, this.propertiesByInvoke.bind(this))
|
|
494
|
+
this.process.bridge.listen(Job.invoke.animation.Method, this.animationByInvoke.bind(this))
|
|
495
|
+
this.process.bridge.listen(Job.invoke.screenshot.Method, this.screenshot.bind(this))
|
|
496
|
+
|
|
497
|
+
window.addEventListener('keydown', this.onEvent.bind(this))
|
|
498
|
+
window.addEventListener('keyup', this.onEvent.bind(this))
|
|
499
|
+
window.addEventListener('mousedown', this.onEvent.bind(this))
|
|
500
|
+
window.addEventListener('click', this.onEvent.bind(this))
|
|
501
|
+
window.addEventListener('mouseup', this.onEvent.bind(this))
|
|
502
|
+
|
|
503
|
+
//@ts-ignore
|
|
504
|
+
window['__VYR_RUNTIME.DISABLED_INPUT'] = true
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
observer.listen('__VYR_RUNTIME@remote', this.onMessage.bind(this))
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
export {
|
|
513
|
+
RemoteExecutor
|
|
514
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { AsyncTask, Generate } from '@vyr/engine'
|
|
2
|
+
import { Bridge, RemoteConfig } from './Bridge'
|
|
3
|
+
|
|
4
|
+
interface RemoteSanbox {
|
|
5
|
+
[k: string]: any
|
|
6
|
+
DOM: HTMLDivElement
|
|
7
|
+
useRemote: () => Promise<Window>
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**远程调用器 */
|
|
11
|
+
class RemoteInvoker {
|
|
12
|
+
static createRemoteLocation(config: RemoteConfig) {
|
|
13
|
+
const location = Bridge.createBaseUrl() + `/preview.html?config=${JSON.stringify(config)}`
|
|
14
|
+
return location
|
|
15
|
+
}
|
|
16
|
+
static createIframe(location: string) {
|
|
17
|
+
const DOM = document.createElement('iframe')
|
|
18
|
+
DOM.width = '100%'
|
|
19
|
+
DOM.height = '100%'
|
|
20
|
+
DOM.style.width = '100%'
|
|
21
|
+
DOM.style.height = '100%'
|
|
22
|
+
DOM.style.border = 'none'
|
|
23
|
+
DOM.setAttribute('src', location)
|
|
24
|
+
const promise = new Promise<Window>((resolve) => DOM.addEventListener('load', () => resolve(DOM.contentWindow as Window)))
|
|
25
|
+
const task = new AsyncTask(() => promise)
|
|
26
|
+
const listeners = ['keydown', 'keyup', 'mousedown', 'mouseup']
|
|
27
|
+
const stop = (e: Event) => { e.preventDefault(); e.stopPropagation() }
|
|
28
|
+
for (const key of listeners) DOM.addEventListener(key, stop)
|
|
29
|
+
const useRemote = async () => task.done()
|
|
30
|
+
const snabox: RemoteSanbox = { DOM, useRemote }
|
|
31
|
+
task.run()
|
|
32
|
+
return snabox
|
|
33
|
+
}
|
|
34
|
+
static createWindow(location: string) {
|
|
35
|
+
const DOM = document.createElement('div')
|
|
36
|
+
const win = window.open(location)
|
|
37
|
+
const snabox: RemoteSanbox = { DOM, useRemote: async () => win as Window }
|
|
38
|
+
return snabox
|
|
39
|
+
}
|
|
40
|
+
static createSandbox(config: RemoteConfig) {
|
|
41
|
+
const location = this.createRemoteLocation(config)
|
|
42
|
+
return config.env === 'window' ? this.createWindow(location) : this.createIframe(location)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private sanbox
|
|
46
|
+
readonly id
|
|
47
|
+
readonly bridge
|
|
48
|
+
|
|
49
|
+
constructor(window: Window, options: Partial<Omit<RemoteConfig, 'id'>> = {}) {
|
|
50
|
+
const config: RemoteConfig = { id: `${Generate.id()}`, env: 'window', execute: false, invoke: false }
|
|
51
|
+
Object.assign(config, options)
|
|
52
|
+
this.id = config.id
|
|
53
|
+
this.sanbox = RemoteInvoker.createSandbox(config)
|
|
54
|
+
this.bridge = new Bridge({ id: config.id, useRemote: this.sanbox.useRemote })
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
mount(id: string) {
|
|
58
|
+
if (this.sanbox === null) return
|
|
59
|
+
const container = document.getElementById(id)
|
|
60
|
+
if (container !== null) container.appendChild(this.sanbox.DOM)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
dispose() {
|
|
64
|
+
this.bridge.close()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async ready() {
|
|
68
|
+
return this.bridge.connected.done()
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { RemoteInvoker }
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Asset, Descriptor, Engine, Generate, ServiceDescriptor, ServiceSchedulerDescriptor } from '@vyr/engine'
|
|
2
|
+
import { Bridge, RemoteConfig } from './Bridge'
|
|
3
|
+
import { RemoteExecutor } from './RemoteExecutor'
|
|
4
|
+
import { Job } from './job'
|
|
5
|
+
|
|
6
|
+
type RemoteSetup = (process: RemoteProcess) => void
|
|
7
|
+
|
|
8
|
+
const privateState = {
|
|
9
|
+
setupCollection: [] as RemoteSetup[],
|
|
10
|
+
executorCollection: new Map<string, RemoteProcess>(),
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
class RemoteProcess {
|
|
14
|
+
static transformEvent = `TransformController/event/${Generate.uuid()}.ts`
|
|
15
|
+
static get(engine: Engine) {
|
|
16
|
+
return privateState.executorCollection.get(engine.uuid) ?? null
|
|
17
|
+
}
|
|
18
|
+
static register(setup: RemoteSetup) {
|
|
19
|
+
privateState.setupCollection.push(setup)
|
|
20
|
+
}
|
|
21
|
+
static getServices(descriptor: Descriptor, services: Descriptor[] = []) {
|
|
22
|
+
descriptor.traverse(sub => {
|
|
23
|
+
if (sub instanceof ServiceDescriptor) services.push(sub)
|
|
24
|
+
})
|
|
25
|
+
return services
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private _executor!: RemoteExecutor
|
|
29
|
+
readonly config
|
|
30
|
+
readonly element
|
|
31
|
+
readonly engine
|
|
32
|
+
scene = ''
|
|
33
|
+
asset = ''
|
|
34
|
+
scheduler: ServiceSchedulerDescriptor
|
|
35
|
+
bridge!: Bridge
|
|
36
|
+
|
|
37
|
+
constructor(element: string | HTMLElement, engine = new Engine()) {
|
|
38
|
+
privateState.executorCollection.set(engine.uuid, this)
|
|
39
|
+
this.element = element
|
|
40
|
+
this.engine = engine
|
|
41
|
+
this.config = this._initConfig()
|
|
42
|
+
this.scheduler = new ServiceSchedulerDescriptor()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private _initConfig() {
|
|
46
|
+
const params: { [k: string]: string } = {}
|
|
47
|
+
const url = document.location.search
|
|
48
|
+
const kvdata = url.slice(1).split('&')
|
|
49
|
+
for (const kv of kvdata) {
|
|
50
|
+
const kvClips = kv.split('=')
|
|
51
|
+
params[kvClips[0]] = kvClips[1]
|
|
52
|
+
}
|
|
53
|
+
return (params.config ? JSON.parse(decodeURIComponent(params.config)) : {}) as RemoteConfig
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async listen() {
|
|
57
|
+
for (const setup of privateState.setupCollection) setup(this)
|
|
58
|
+
|
|
59
|
+
this.bridge = new Bridge({ id: this.config.id, args: [this] })
|
|
60
|
+
|
|
61
|
+
let executor = this.getExecutor()
|
|
62
|
+
if (executor === null) {
|
|
63
|
+
executor = new RemoteExecutor(this)
|
|
64
|
+
this.setExecutor(executor)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
await executor.listen()
|
|
68
|
+
|
|
69
|
+
this.engine.run(this.element)
|
|
70
|
+
|
|
71
|
+
if (this.config.scene) executor.loadByScene(new Job.scene.load.Task({ url: this.config.scene }))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
setExecutor(executor: RemoteExecutor) {
|
|
75
|
+
this._executor = executor
|
|
76
|
+
}
|
|
77
|
+
getExecutor<T extends RemoteExecutor = RemoteExecutor>() {
|
|
78
|
+
return this._executor as T
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Asset.provider(RemoteProcess.transformEvent, () => import('./ChangeScriptable'))
|
|
83
|
+
Asset.load(RemoteProcess.transformEvent)
|
|
84
|
+
|
|
85
|
+
export {
|
|
86
|
+
RemoteProcess
|
|
87
|
+
}
|
package/src/index.ts
ADDED