@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 +23 -0
- package/src/Cache.ts +65 -0
- package/src/ChangeScriptable.ts +31 -0
- package/src/RemoteExecutor.ts +295 -0
- package/src/index.ts +10 -0
- package/src/locale/Language.ts +10 -0
- package/src/locale/LanguageProvider.ts +15 -0
- package/src/locale/index.ts +2 -0
- package/src/shims-vue.d.ts +4 -0
- package/src/utils/flyto.ts +103 -0
- package/src/utils/index.ts +92 -0
- package/src/utils/update.ts +92 -0
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,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 }
|