@vyr/three-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 ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@vyr/three-remote",
3
+ "version": "0.0.1",
4
+ "description": "",
5
+ "main": "./src/index.ts",
6
+ "author": "",
7
+ "sideEffects": true,
8
+ "license": "MIT",
9
+ "dependencies": {
10
+ "@vyr/locale": "0.0.1",
11
+ "@vyr/engine": "0.0.1",
12
+ "@vyr/remote": "0.0.1",
13
+ "@vyr/three": "0.0.1"
14
+ },
15
+ "files": [
16
+ "package.json",
17
+ "src/"
18
+ ],
19
+ "vyr": {
20
+ "type": "remote",
21
+ "order": 1000
22
+ }
23
+ }
package/src/Cache.ts ADDED
@@ -0,0 +1,65 @@
1
+ import { CameraDescriptor, Asset } from "@vyr/engine"
2
+ import { Collection } from "@vyr/remote"
3
+ import { AmbientLightDescriptor, BoxGeometryDescriptor, DirectionalLightDescriptor, LightDescriptor, MeshBasicMaterialDescriptor, PerspectiveCameraDescriptor, PlaneGeometryDescriptor, SphereGeometryDescriptor } from "@vyr/three"
4
+
5
+ class Cache {
6
+ private _camera: CameraDescriptor | null = null
7
+ get camera() {
8
+ if (this._camera === null) {
9
+ this._camera = new PerspectiveCameraDescriptor()
10
+ }
11
+ return this._camera
12
+ }
13
+
14
+ private _light: LightDescriptor | null = null
15
+ get light() {
16
+ if (this._light === null) {
17
+ this._light = new AmbientLightDescriptor({ color: '#2d2d2d' })
18
+ this._light.add(new DirectionalLightDescriptor({ position: { x: -100, y: 100, z: 0 } }))
19
+ }
20
+ return this._light
21
+ }
22
+
23
+ readonly materialUrl = Asset.createVirtualUrl('remote/asset/material/basic.material.json')
24
+ private _material: MeshBasicMaterialDescriptor | null = null
25
+ get material() {
26
+ if (this._material === null) {
27
+ this._material = new MeshBasicMaterialDescriptor()
28
+ }
29
+ return this._material
30
+ }
31
+
32
+ readonly boxUrl = Asset.createVirtualUrl('remote/asset/material/box.geometry.json')
33
+ private _box: BoxGeometryDescriptor | null = null
34
+ get box() {
35
+ if (this._box === null) {
36
+ this._box = new BoxGeometryDescriptor()
37
+ }
38
+ return this._box
39
+ }
40
+ readonly sphereUrl = Asset.createVirtualUrl('remote/asset/material/sphere.geometry.json')
41
+ private _sphere: SphereGeometryDescriptor | null = null
42
+ get sphere() {
43
+ if (this._sphere === null) {
44
+ this._sphere = new SphereGeometryDescriptor()
45
+ }
46
+ return this._sphere
47
+ }
48
+ readonly planeUrl = Asset.createVirtualUrl('remote/asset/material/plane.geometry.json')
49
+ private _plane: PlaneGeometryDescriptor | null = null
50
+ get plane() {
51
+ if (this._plane === null) {
52
+ this._plane = new PlaneGeometryDescriptor()
53
+ }
54
+ return this._plane
55
+ }
56
+
57
+ orbitCollection = new Collection()
58
+ transformCollection = new Collection()
59
+ }
60
+
61
+ const cache = new Cache()
62
+
63
+ export {
64
+ cache
65
+ }
@@ -0,0 +1,31 @@
1
+ import { Descriptor, Graphics, Scriptable, ServiceDescriptor } from "@vyr/engine";
2
+ import { TransformControllerChangeArgs, TransformControllerDescriptor } from '@vyr/three'
3
+ import { RemoteProcess, Job } from '@vyr/remote'
4
+ import { cache } from "./Cache"
5
+
6
+ class ChangeScriptable extends Scriptable {
7
+
8
+ execute(descriptor: TransformControllerDescriptor, graphics: Graphics, args: TransformControllerChangeArgs) {
9
+ const process = RemoteProcess.get(graphics.engine)
10
+ if (process === null) return
11
+
12
+ const target = Descriptor.get(args.event.target) as Descriptor
13
+ const service = ServiceDescriptor.traceService(target)
14
+ if (service) {
15
+ const orbit = cache.orbitCollection.get(service)
16
+ if (orbit) {
17
+ if (args.event.type === 'mousedown') {
18
+ orbit.enabled = false
19
+ } else if (args.event.type === 'mouseup') {
20
+ orbit.enabled = true
21
+ }
22
+ orbit.setNeedsUpdate()
23
+ }
24
+ }
25
+
26
+ const params = { eventType: args.event.type, target: args.event.target, descriptor: target.clone(false) }
27
+ process.bridge.send(new Job.invoke.transform.Response(params))
28
+ }
29
+ }
30
+
31
+ export default ChangeScriptable
@@ -0,0 +1,295 @@
1
+ import { Asset, Descriptor, DeserializationObject, HTMLDescriptor, NodeDescriptor, PrefabeDescriptor, ServiceDescriptor, ServiceSchedulerDescriptor, Unit, UpdateArgs, Vector3 as _V3 } from '@vyr/engine'
2
+ import { GeometryDescriptor, MaterialDescriptor, MeshDescriptor, NodeActor, OrbitControllerActor, OrbitControllerDescriptor, ParticleDescriptor, PerspectiveCameraDescriptor, PointsDescriptor, PointsMaterialDescriptor, SceneServiceDescriptor, SpriteDescriptor, SpriteMaterialDescriptor, TextureDescriptor, TransformControllerDescriptor, THREE } from '@vyr/three'
3
+ import { RemoteExecutor as _RemoteExecutor, Job, RemoteProcess } from '@vyr/remote'
4
+ import { checkParentValidity, flyTo, getControllerByService, getGraphics, getTransformEvent, lookAt, resize, updateModelByScheduler, updateOtherUpdateJob } from './utils'
5
+ import { cache } from './Cache'
6
+
7
+ class RemoteExecutor extends _RemoteExecutor {
8
+ async loadByAsset(task: InstanceType<typeof Job['asset']['load']['Task']>) {
9
+ await super.loadByAsset(task)
10
+ if (this.process.config.invoke) {
11
+ flyTo(this.process.scheduler.uuid, this.process)
12
+ updateModelByScheduler(this.process.scheduler, this.process)
13
+ }
14
+ }
15
+ async loadByScene(task: InstanceType<(typeof Job)['scene']['load']['Task']>) {
16
+ await super.loadByScene(task)
17
+ flyTo(this.process.scheduler.uuid, this.process)
18
+ updateModelByScheduler(this.process.scheduler, this.process)
19
+ }
20
+
21
+ async transformByInvoke(task: InstanceType<(typeof Job)['invoke']['transform']['Task']>) {
22
+ const transforms = cache.transformCollection.values()
23
+ for (const item of transforms) {
24
+ item.target = ''
25
+ item.mode = ''
26
+ item.enabled = false
27
+ item.setNeedsUpdate()
28
+ }
29
+
30
+ const target = Descriptor.get<Descriptor>(task.params.target)
31
+ let service = ServiceDescriptor.traceService(target)
32
+ if (service === null) return
33
+
34
+ if (target instanceof HTMLDescriptor && checkParentValidity(target)) {
35
+ if (service instanceof SceneServiceDescriptor) {
36
+ const ancestor = service.traceAncestor(false)
37
+ service = ServiceDescriptor.traceService(ancestor.parent)
38
+ }
39
+ super.transformByInvoke(task, service)
40
+ } else {
41
+ super.clearHTMLTransform()
42
+
43
+ const transform = cache.transformCollection.get<TransformControllerDescriptor>(service)
44
+ if (transform === null) return
45
+
46
+ const enabled = ['translate', 'rotate', 'scale'].includes(task.params.mode)
47
+ if (enabled) {
48
+ transform.target = task.params.target
49
+ transform.mode = task.params.mode
50
+ transform.enabled = true
51
+ }
52
+
53
+ if (target instanceof NodeDescriptor) lookAt(target, this.process)
54
+ }
55
+ }
56
+ async orbitByInvoke(task: InstanceType<(typeof Job)['invoke']['orbit']['Task']>) {
57
+ const orbits = cache.orbitCollection.values()
58
+ for (const orbit of orbits) {
59
+ orbit.enablePan = task.params.enablePan
60
+ orbit.screenSpacePanning = task.params.screenSpacePanning
61
+ orbit.setNeedsUpdate()
62
+ }
63
+ }
64
+ protected async getProperties(task: InstanceType<typeof Job['invoke']['properties']['Task']>,) {
65
+ let properties
66
+ const descriptor = Descriptor.get<Descriptor>(task.params.uuid)
67
+ const graphics = getGraphics(descriptor, this.process)
68
+ if (graphics === null) return
69
+
70
+ let targetUuid
71
+ if (task.params.type === 'getCurrentCamera') {
72
+ targetUuid = cache.camera.uuid
73
+ } else {
74
+ targetUuid = task.params.uuid
75
+ }
76
+
77
+ const target = Descriptor.get<Descriptor>(targetUuid)
78
+ if (target === null) return
79
+
80
+ properties = Descriptor.deepClone(target)
81
+
82
+ const response = new Job.invoke.properties.Response({ type: 'get', properties })
83
+ this.process.bridge.send(response)
84
+ }
85
+ protected async setProperties(task: InstanceType<typeof Job['invoke']['properties']['Task']>) {
86
+ const descriptor = Descriptor.get<Descriptor>(task.params.uuid)
87
+ const graphics = getGraphics(descriptor, this.process)
88
+ if (graphics === null) return
89
+
90
+ let targetUuid
91
+ if (task.params.type === 'setCurrentCamera') {
92
+ targetUuid = cache.camera.uuid
93
+ } else {
94
+ targetUuid = task.params.uuid
95
+ }
96
+
97
+ const target = Descriptor.get<Descriptor>(targetUuid)
98
+ if (descriptor instanceof NodeDescriptor && target instanceof NodeDescriptor) {
99
+ target.position.x = descriptor.position.x
100
+ target.position.y = descriptor.position.y
101
+ target.position.z = descriptor.position.z
102
+ target.scale.x = descriptor.scale.x
103
+ target.scale.y = descriptor.scale.y
104
+ target.scale.z = descriptor.scale.z
105
+ target.rotation.x = descriptor.rotation.x
106
+ target.rotation.y = descriptor.rotation.y
107
+ target.rotation.z = descriptor.rotation.z
108
+ target.setNeedsUpdate()
109
+ }
110
+
111
+ if (descriptor instanceof PerspectiveCameraDescriptor) {
112
+ const controller = getControllerByService(descriptor)
113
+ if (controller === null || controller.orbit === null) return
114
+ const args = { delta: 0 }
115
+ const camera = graphics.getActor<NodeActor>(descriptor, args)
116
+ camera.object.updateMatrixWorld(true)
117
+ const forward = camera.object.getWorldDirection(new THREE.Vector3())
118
+ const lookAtPosition = new THREE.Vector3()
119
+ .copy(camera.object.position)
120
+ .add(forward.multiplyScalar(1)).negate()
121
+ const orbitActor = graphics.getActor<OrbitControllerActor>(controller.orbit, args)
122
+ orbitActor.controls.setLookAt(
123
+ camera.object.position.x,
124
+ camera.object.position.y,
125
+ camera.object.position.z,
126
+ lookAtPosition.x,
127
+ lookAtPosition.y,
128
+ lookAtPosition.z,
129
+ )
130
+ }
131
+ }
132
+ async propertiesByInvoke(task: InstanceType<(typeof Job)['invoke']['properties']['Task']>) {
133
+ ['get', 'getCurrentCamera'].includes(task.params.type) ? this.getProperties(task) : this.setProperties(task)
134
+ }
135
+ async animationByInvoke(task: InstanceType<(typeof Job)['invoke']['animation']['Task']>) {
136
+ super.animationByInvoke(task)
137
+ }
138
+
139
+ resetTransformByRemoveJob(target: Descriptor) {
140
+ let service = ServiceDescriptor.traceService(target)
141
+ if (service === null) return
142
+
143
+ if (target instanceof HTMLDescriptor) {
144
+ if (service instanceof SceneServiceDescriptor) {
145
+ const ancestor = service.traceAncestor(false)
146
+ service = ServiceDescriptor.traceService(ancestor.parent)
147
+ }
148
+ super.resetTransformByRemoveJob(target, service)
149
+ } else {
150
+ const transform = cache.transformCollection.get<TransformControllerDescriptor>(service)
151
+ if (transform === null) return
152
+
153
+ if (transform.target === target.uuid) {
154
+ transform.target = ''
155
+ transform.enabled = false
156
+ transform.setNeedsUpdate()
157
+ }
158
+ }
159
+ }
160
+ updateOtherUpdateJob(target: Descriptor, deserialization: DeserializationObject<Descriptor>) {
161
+ let service = ServiceDescriptor.traceService(target)
162
+
163
+ if (target instanceof HTMLDescriptor) {
164
+ if (service instanceof SceneServiceDescriptor) {
165
+ const ancestor = service.traceAncestor(false)
166
+ service = ServiceDescriptor.traceService(ancestor.parent)
167
+ }
168
+ super.updateOtherUpdateJob(target, deserialization, service)
169
+ } else {
170
+ updateOtherUpdateJob(target, deserialization, service, this.process)
171
+ }
172
+ }
173
+
174
+ protected getRenderObject(url: string, descriptor: Descriptor) {
175
+ cache.material.map = ''
176
+ const mesh = new MeshDescriptor()
177
+ if (descriptor instanceof MaterialDescriptor) {
178
+ let target: (MeshDescriptor | SpriteDescriptor | PointsDescriptor | ParticleDescriptor) = mesh
179
+ if (descriptor instanceof PointsMaterialDescriptor) {
180
+ target = new PointsDescriptor()
181
+ target.geometry = cache.sphereUrl
182
+ Asset.set(cache.sphereUrl, cache.sphere)
183
+ } else if (descriptor instanceof SpriteMaterialDescriptor) {
184
+ target = new SpriteDescriptor()
185
+ } else {
186
+ target.geometry = cache.boxUrl
187
+ Asset.set(cache.boxUrl, cache.box)
188
+ }
189
+
190
+ target.material = url
191
+ return target
192
+ } else if (descriptor instanceof GeometryDescriptor) {
193
+ mesh.material = cache.materialUrl
194
+ mesh.geometry = url
195
+ Asset.set(cache.materialUrl, cache.material)
196
+ } else if (descriptor instanceof TextureDescriptor) {
197
+ cache.material.map = url
198
+ mesh.material = cache.materialUrl
199
+ mesh.geometry = cache.planeUrl
200
+ Asset.set(cache.materialUrl, cache.material)
201
+ Asset.set(cache.planeUrl, cache.plane)
202
+ }
203
+ return mesh
204
+ }
205
+ onLoadAsset(url: string, descriptor: Descriptor, scheduler: ServiceSchedulerDescriptor) {
206
+ super.onLoadAsset(url, descriptor, scheduler)
207
+ if (descriptor instanceof HTMLDescriptor) {
208
+ return
209
+ } else if (descriptor instanceof NodeDescriptor) {
210
+ const service = new SceneServiceDescriptor()
211
+ service.add(descriptor)
212
+ service.add(cache.light)
213
+ scheduler.add(service)
214
+ } else if (descriptor instanceof PrefabeDescriptor && descriptor.category === 'scene') {
215
+ const service = new SceneServiceDescriptor()
216
+ service.add(descriptor)
217
+ service.add(cache.light)
218
+ scheduler.add(service)
219
+ } else {
220
+ const service = new SceneServiceDescriptor()
221
+ service.add(this.getRenderObject(url, descriptor))
222
+ service.add(cache.light)
223
+ scheduler.add(service)
224
+ }
225
+ }
226
+ onAddService(service: ServiceDescriptor) {
227
+ super.onAddService(service)
228
+ if (service instanceof SceneServiceDescriptor) {
229
+ let transform = cache.transformCollection.get(service)
230
+ if (transform == null) {
231
+ transform = new TransformControllerDescriptor({ enabled: false, selectable: false })
232
+ cache.transformCollection.set(service, transform)
233
+ transform.camera = cache.camera.uuid
234
+ transform.event = getTransformEvent()
235
+ }
236
+ service.add(transform as TransformControllerDescriptor)
237
+
238
+ let orbit = cache.orbitCollection.get(service)
239
+ if (orbit === null) {
240
+ orbit = new OrbitControllerDescriptor({ enabled: true, selectable: false, draggingSmoothTime: 0, smoothTime: 0, restThreshold: 0, dollyToCursor: false })
241
+ cache.orbitCollection.set(service, orbit)
242
+ orbit.camera = cache.camera.uuid
243
+ }
244
+ service.add(orbit as OrbitControllerDescriptor)
245
+ }
246
+ }
247
+ onRemoveService(service: ServiceDescriptor) {
248
+ super.onRemoveService(service)
249
+ if (service instanceof SceneServiceDescriptor) {
250
+ const transform = cache.transformCollection.get<TransformControllerDescriptor>(service)
251
+ if (transform !== null) {
252
+ cache.transformCollection.delete(service)
253
+ service.remove(transform)
254
+ }
255
+
256
+ const orbit = cache.orbitCollection.get<OrbitControllerDescriptor>(service)
257
+ if (orbit !== null) {
258
+ cache.orbitCollection.delete(service)
259
+ service.remove(orbit)
260
+ }
261
+ }
262
+ }
263
+ onUpdateScheduler(unit: Unit, args: UpdateArgs) {
264
+ const descriptor = Descriptor.get<Descriptor>(unit.uuid)
265
+ const service = cache.transformCollection.getByMap<TransformControllerDescriptor>(descriptor)
266
+ ?? cache.orbitCollection.getByMap<OrbitControllerDescriptor>(descriptor)
267
+
268
+ if (service !== null) {
269
+ //@ts-ignore
270
+ window['__VYR_RUNTIME.DISABLED_INPUT'] = false
271
+ }
272
+
273
+ super.onUpdateScheduler(unit, args)
274
+ }
275
+
276
+ enhance(process: RemoteProcess) {
277
+ super.enhance(process, (scheduler) => {
278
+ Object.defineProperty(scheduler, 'camera', { get() { return cache.camera.uuid }, set() { } })
279
+ })
280
+ }
281
+
282
+ async listen() {
283
+ const transformEvent = getTransformEvent()
284
+ Asset.provider(transformEvent, () => import('./ChangeScriptable'))
285
+ Asset.load(transformEvent)
286
+
287
+ window.addEventListener('resize', resize(this.process))
288
+
289
+ await super.listen()
290
+ }
291
+ }
292
+
293
+ export {
294
+ RemoteExecutor
295
+ }
package/src/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { RemoteProcess } from '@vyr/remote'
2
+ import { RemoteExecutor } from './RemoteExecutor'
3
+
4
+ const setup = (process: RemoteProcess) => {
5
+ process.setExecutor(new RemoteExecutor(process))
6
+ }
7
+ RemoteProcess.register(setup)
8
+
9
+ export { setup }
10
+ export * from './locale'
@@ -0,0 +1,10 @@
1
+ import { Locale } from "@vyr/locale";
2
+ import { zhCnLanguageProvider, ZhCNLanguageProvider } from "./LanguageProvider";
3
+
4
+ Locale.register(zhCnLanguageProvider)
5
+
6
+ const language = Locale.getLanguage<ZhCNLanguageProvider>(zhCnLanguageProvider.name)
7
+
8
+ export {
9
+ language
10
+ }
@@ -0,0 +1,15 @@
1
+ import { LanguageProvider } from '@vyr/locale'
2
+
3
+ interface ZhCNLanguageProvider extends LanguageProvider {
4
+
5
+ }
6
+
7
+ const zhCnLanguageProvider: ZhCNLanguageProvider = {
8
+ id: 'zh_CN',
9
+ name: '@vyr/three-remote',
10
+ }
11
+
12
+ export {
13
+ ZhCNLanguageProvider,
14
+ zhCnLanguageProvider,
15
+ }
@@ -0,0 +1,2 @@
1
+ export * from './LanguageProvider'
2
+ export * from './Language'
@@ -0,0 +1,4 @@
1
+ declare module '*.vue' {
2
+ const component: DefineComponent<{}, {}, any>
3
+ export default component
4
+ }
@@ -0,0 +1,103 @@
1
+ import { CameraDescriptor, Graphics, Descriptor, NodeDescriptor, ServiceDescriptor, ServiceSchedulerDescriptor, UpdateArgs, Vector3 as _V3 } from "@vyr/engine"
2
+ import { NodeActor, OrbitControllerActor, OrbitControllerDescriptor, TransformControllerDescriptor, THREE } from "@vyr/three"
3
+ import { RemoteProcess } from "@vyr/remote"
4
+ import { cache } from "../Cache"
5
+
6
+ const rawVector3 = new THREE.Vector3(0, 0, 0)
7
+ const emptyBox = new THREE.Box3()
8
+ const getBox3 = (descriptor: Descriptor, graphics: Graphics, args: UpdateArgs) => {
9
+ const box3 = new THREE.Box3()
10
+ // const ignore: Descriptor[] = []
11
+ // if (instance) ignore.push(instance.orbit, instance.transform)
12
+ descriptor.traverse(sub => {
13
+ const actor = graphics.getActor<NodeActor<THREE.Object3D>>(sub, args)
14
+ if (actor instanceof NodeActor) {
15
+ if (actor.object.visible === false) return true
16
+ box3.expandByObject(actor.object)
17
+ return true
18
+ }
19
+ }, true)
20
+ return box3
21
+ }
22
+ const getControllerByService = (target: Descriptor) => {
23
+ const service = ServiceDescriptor.traceService(target)
24
+ if (service instanceof ServiceDescriptor) {
25
+ const orbit = cache.orbitCollection.get<OrbitControllerDescriptor>(service)
26
+ const transform = cache.transformCollection.get<TransformControllerDescriptor>(service)
27
+ return { transform, orbit }
28
+ }
29
+ return null
30
+ }
31
+ const getFlyInfo = (descriptor: Descriptor, graphics: Graphics, args: UpdateArgs) => {
32
+ const box3 = getBox3(descriptor, graphics, args)
33
+
34
+ if (box3.equals(emptyBox)) return null
35
+
36
+ const sphere = box3.getBoundingSphere(new THREE.Sphere())
37
+ const cameraActor = graphics.getActor<NodeActor<THREE.PerspectiveCamera>>(cache.camera, args)
38
+
39
+ const fov = THREE.MathUtils.degToRad(cameraActor.object.fov)
40
+ const fovHorizontal = 2 * Math.atan(Math.tan(fov / 2) * cameraActor.object.aspect)
41
+
42
+ const distanceV = sphere.radius / Math.tan(fov / 2);
43
+ const distanceH = sphere.radius / Math.tan(fovHorizontal / 2);
44
+ const distance = Math.max(distanceV, distanceH) * 1.05
45
+
46
+ const location = new THREE.Vector3().copy(sphere.center)
47
+ location.add(new THREE.Vector3(0, 0.5, 1).normalize().multiplyScalar(distance))
48
+
49
+ const position = rawVector3.equals(location) && rawVector3.equals(sphere.center) ? new THREE.Vector3(0, 0, 5) : location
50
+
51
+ return {
52
+ position,
53
+ lookAt: sphere.center
54
+ }
55
+ }
56
+ const flyToTarget = (descriptor: Descriptor, graphics: Graphics, args: UpdateArgs, orbit: OrbitControllerDescriptor | null) => {
57
+ const flyInfo = getFlyInfo(descriptor, graphics, args)
58
+ if (flyInfo === null) return
59
+
60
+ cache.camera.position.set(flyInfo.position.x, flyInfo.position.y, flyInfo.position.z)
61
+ cache.camera.setNeedsUpdate()
62
+ if (!orbit) return
63
+
64
+ const orbitActor = graphics.getActor<OrbitControllerActor>(orbit, args)
65
+ orbitActor.controls.setLookAt(
66
+ flyInfo.position.x,
67
+ flyInfo.position.y,
68
+ flyInfo.position.z,
69
+ flyInfo.lookAt.x,
70
+ flyInfo.lookAt.y,
71
+ flyInfo.lookAt.z,
72
+ )
73
+ }
74
+ const flyTo = (uuid: string, process: RemoteProcess) => {
75
+ const descriptor = Descriptor.get<NodeDescriptor>(uuid)
76
+ if (descriptor === null) return
77
+ const cameraDescriptor = Descriptor.get<CameraDescriptor>(process.scheduler.camera)
78
+ if (cameraDescriptor === null) return
79
+
80
+ const services: Descriptor[] = []
81
+ if (descriptor instanceof ServiceSchedulerDescriptor) {
82
+ RemoteProcess.getServices(descriptor, services)
83
+ } else if (descriptor instanceof ServiceDescriptor) {
84
+ services.push(descriptor)
85
+ }
86
+
87
+ const graphics = process.engine.getGraphics(process.scheduler)
88
+ const args = { delta: 0 }
89
+
90
+ if (services.length === 0) {
91
+ const controller = getControllerByService(descriptor)
92
+ if (controller === null) return
93
+ flyToTarget(descriptor, graphics, args, controller.orbit)
94
+ } else {
95
+ for (const service of services) {
96
+ const controller = getControllerByService(service)
97
+ if (controller === null) return
98
+ flyToTarget(descriptor, graphics, args, controller.orbit)
99
+ }
100
+ }
101
+ }
102
+
103
+ export { getControllerByService, getFlyInfo, flyToTarget, flyTo }
@@ -0,0 +1,92 @@
1
+ import { Descriptor, DynamicDescriptor, Generate, HTMLDescriptor, NodeDescriptor, PrefabeDescriptor, PrefabInstanceDescriptor, ServiceSchedulerDescriptor } from "@vyr/engine"
2
+ import { RemoteProcess } from "@vyr/remote"
3
+ import { HTMLConvertDescriptor, NodeActor, OrbitControllerActor, THREE } from "@vyr/three"
4
+ import { cache } from "../Cache"
5
+ import { getControllerByService, getFlyInfo } from './flyto'
6
+
7
+ let transformEvent = ''
8
+ const getTransformEvent = () => {
9
+ if (transformEvent === '') {
10
+ transformEvent = `TransformController/event/${Generate.uuid()}.ts`
11
+ }
12
+
13
+ return transformEvent
14
+ }
15
+
16
+ const getParent = (descriptor: Descriptor): Descriptor | boolean | null => {
17
+ const ancestor = descriptor.traceAncestor(false)
18
+ if (ancestor.parent === null) {
19
+ return null
20
+ } else if (ancestor.parent instanceof HTMLDescriptor) {
21
+ return ancestor.parent
22
+ } else if (ancestor.parent instanceof DynamicDescriptor) {
23
+ return getParent(ancestor.parent)
24
+ } else if (ancestor.parent instanceof PrefabeDescriptor) {
25
+ const nextParent = getParent(ancestor.parent)
26
+ return nextParent === null ? true : nextParent
27
+ } else if (ancestor.parent instanceof PrefabInstanceDescriptor) {
28
+ return getParent(ancestor.parent)
29
+ } else if (ancestor.parent instanceof HTMLConvertDescriptor) {
30
+ return null
31
+ } else if (ancestor.parent instanceof NodeDescriptor) {
32
+ return ancestor.parent
33
+ } else {
34
+ return null
35
+ }
36
+ }
37
+ const checkParentValidity = (html: HTMLDescriptor) => {
38
+ const parent = getParent(html)
39
+ if (parent === null) {
40
+ return false
41
+ } else if (parent instanceof HTMLDescriptor) {
42
+ return true
43
+ } else if (parent instanceof NodeDescriptor) {
44
+ return false
45
+ } else {
46
+ return true
47
+ }
48
+ }
49
+
50
+ const getGraphics = (descriptor: Descriptor, process: RemoteProcess) => {
51
+ const ancestor = descriptor.traceAncestor(true)
52
+ const scheduler = ancestor.collection[ancestor.collection.length - 1] as ServiceSchedulerDescriptor
53
+ return scheduler instanceof ServiceSchedulerDescriptor ? process.engine.getGraphics(scheduler) : null
54
+ }
55
+
56
+ const resize = (process: RemoteProcess) => {
57
+ return () => {
58
+ const graphics = process.engine.getGraphics(process.scheduler)
59
+ if (graphics == null) return
60
+ const interpreter = graphics.getInterpreter(cache.camera)
61
+ const actor = interpreter.getActor<NodeActor<THREE.PerspectiveCamera>>(cache.camera, { delta: 0 })
62
+ actor.object.aspect = process.engine.DOM.clientWidth / process.engine.DOM.clientHeight
63
+ actor.object.updateProjectionMatrix()
64
+ }
65
+ }
66
+
67
+ const lookAt = (target: Descriptor, process: RemoteProcess) => {
68
+ const controller = getControllerByService(target)
69
+ if (controller === null) return
70
+ const args = { delta: 0 }
71
+ const graphics = process.engine.getGraphics(process.scheduler)
72
+ const flyInfo = getFlyInfo(target, graphics, args)
73
+ if (flyInfo === null) return
74
+ if (!controller.orbit) return
75
+
76
+ const orbitActor = graphics.getActor<OrbitControllerActor>(controller.orbit, args)
77
+ orbitActor.controls.setTarget(
78
+ flyInfo.lookAt.x,
79
+ flyInfo.lookAt.y,
80
+ flyInfo.lookAt.z,
81
+ )
82
+ }
83
+
84
+ export {
85
+ getTransformEvent,
86
+ checkParentValidity,
87
+ getGraphics,
88
+ resize,
89
+ lookAt,
90
+ }
91
+ export * from './update'
92
+ export * from './flyto'
@@ -0,0 +1,92 @@
1
+ import { Asset, Descriptor, DeserializationObject, observer, ServiceDescriptor, ServiceSchedulerDescriptor } from "@vyr/engine"
2
+ import { TextureDescriptor, TransformControllerDescriptor, ModelDescriptor, AnimationActionDescriptor, SceneServiceDescriptor, SceneServiceActor, THREE } from "@vyr/three"
3
+ import { Job, RemoteProcess } from "@vyr/remote"
4
+ import { cache } from "../Cache"
5
+
6
+ const updateAnimationAction = async (uuid: string, url: string, process: RemoteProcess) => {
7
+ const animations: string[] = []
8
+ if (url) {
9
+ const currentUrl = `${url}?${uuid}`
10
+ Asset.load(currentUrl)
11
+ await Asset.readly()
12
+ const model = Asset.get<THREE.Object3D>(currentUrl)
13
+ for (const animation of model.animations) {
14
+ animations.push(animation.name)
15
+ }
16
+ }
17
+ process.bridge.send(new Job.invoke.animation.Response({ type: 'action', uuid: uuid, animations }))
18
+ }
19
+
20
+ const updateSceneService = (target: SceneServiceDescriptor, deserialization: DeserializationObject<SceneServiceDescriptor>, process: RemoteProcess) => {
21
+ if (target.shadowMapType === deserialization.shadowMapType) return
22
+ const args = { delta: 0 }
23
+ const graphics = process.engine.getGraphics(process.scheduler)
24
+ const actor = graphics.getActor<SceneServiceActor>(target, args)
25
+ if (actor === null) return
26
+ actor.pipeline.resetState()
27
+ actor.scene.traverse(sub => {
28
+ if (sub instanceof THREE.Light && sub.shadow) {
29
+ sub.shadow.map?.dispose(); // 释放旧的阴影贴图
30
+ sub.shadow.map = null; // 强制重新创建
31
+ }
32
+ //@ts-ignore
33
+ const material = sub.material
34
+ if (material instanceof THREE.Material) {
35
+ material.needsUpdate = true //强制更新材质
36
+ }
37
+ })
38
+ }
39
+
40
+ const updateModel = async (target: ModelDescriptor, deserialization: DeserializationObject<ModelDescriptor>, process: RemoteProcess) => {
41
+ if (target.url === deserialization.url) return
42
+ updateAnimationAction(target.uuid, deserialization.url, process)
43
+
44
+ if (deserialization.url) {
45
+ Asset.load(`${deserialization.url}?${deserialization.uuid}`)
46
+ await Asset.readly()
47
+ process.engine.listen('afterRender', () => {
48
+ for (const actionDescriptor of target.children) {
49
+ if (actionDescriptor instanceof AnimationActionDescriptor) {
50
+ actionDescriptor.setNeedsUpdate()
51
+ }
52
+ }
53
+ }, { once: true })
54
+ }
55
+ }
56
+
57
+ const updateModelByScheduler = (scheduler: ServiceSchedulerDescriptor, process: RemoteProcess) => {
58
+ scheduler.traverse(sub => {
59
+ if (sub instanceof ModelDescriptor) {
60
+ updateAnimationAction(sub.uuid, sub.url, process)
61
+ }
62
+ })
63
+ }
64
+
65
+ const updateTexture = (target: TextureDescriptor, deserialization: DeserializationObject<TextureDescriptor>, process: RemoteProcess) => {
66
+ if (target.url === deserialization.url) return
67
+ const args = { delta: 0 }
68
+ const graphics = process.engine.getGraphics(process.scheduler)
69
+ const unit = graphics.getUnit(target.uuid)
70
+ if (unit === null) return
71
+ graphics.doFree(unit, args)
72
+ graphics.addRoot(unit.queue.url, target)
73
+ observer.trigger('updateDeps', { self: target.uuid })
74
+ }
75
+
76
+ const updateOtherUpdateJob = (target: Descriptor, deserialization: DeserializationObject<Descriptor>, service: ServiceDescriptor | null, process: RemoteProcess) => {
77
+ if (target instanceof TextureDescriptor) {
78
+ updateTexture(target, deserialization as TextureDescriptor, process)
79
+ } else if (target instanceof ModelDescriptor) {
80
+ updateModel(target, deserialization as ModelDescriptor, process)
81
+ } else if (target instanceof SceneServiceDescriptor) {
82
+ updateSceneService(target, deserialization as SceneServiceDescriptor, process)
83
+ }
84
+ if (service === null) return
85
+ const transform = cache.transformCollection.get<TransformControllerDescriptor>(service)
86
+ if (transform === null) return
87
+ if (transform.target === target.uuid) {
88
+ process.engine.listen('afterRender', () => transform.setNeedsUpdate(), { once: true })
89
+ }
90
+ }
91
+
92
+ export { updateModelByScheduler, updateOtherUpdateJob }