@archvisioninc/canvas 3.3.6 → 3.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/README_DEV.md +4 -1
  3. package/package.json +1 -1
  4. package/src/package/helpers/canvasUpdateHelpers.js +145 -0
  5. package/src/package/helpers/initHelpers.js +10 -0
  6. package/src/package/helpers/utilityHelpers.js +17 -0
  7. package/dist/Canvas.js +0 -67
  8. package/dist/actions/index.js +0 -1
  9. package/dist/actions/shortcutActions.js +0 -313
  10. package/dist/constants/constants.js +0 -80
  11. package/dist/constants/index.js +0 -1
  12. package/dist/enums/aspectRatios.js +0 -17
  13. package/dist/enums/dimensions.js +0 -20
  14. package/dist/enums/downscaling.js +0 -16
  15. package/dist/enums/exclusions.js +0 -4
  16. package/dist/enums/formats.js +0 -1
  17. package/dist/enums/index.js +0 -8
  18. package/dist/enums/orthoOptions.js +0 -28
  19. package/dist/enums/scaleUnits.js +0 -25
  20. package/dist/enums/shortcuts.js +0 -89
  21. package/dist/helpers/cameraHelpers.js +0 -86
  22. package/dist/helpers/canvasAddHelpers.js +0 -161
  23. package/dist/helpers/canvasCommunicationHelpers.js +0 -52
  24. package/dist/helpers/canvasRemoveHelpers.js +0 -230
  25. package/dist/helpers/canvasUpdateHelpers.js +0 -1247
  26. package/dist/helpers/gizmoHelpers.js +0 -156
  27. package/dist/helpers/guiHelpers.js +0 -46
  28. package/dist/helpers/index.js +0 -16
  29. package/dist/helpers/initHelpers.js +0 -507
  30. package/dist/helpers/lightHelpers.js +0 -17
  31. package/dist/helpers/loadHelpers.js +0 -269
  32. package/dist/helpers/materialHelpers.js +0 -34
  33. package/dist/helpers/meshHelpers.js +0 -169
  34. package/dist/helpers/rayHelpers.js +0 -11
  35. package/dist/helpers/shortcutHelpers.js +0 -35
  36. package/dist/helpers/utilityHelpers.js +0 -697
  37. package/dist/helpers/viewportHelpers.js +0 -364
  38. package/dist/styles.js +0 -25
@@ -1,1247 +0,0 @@
1
- /* eslint-disable */
2
- import { getUserMeshes, resetSelectedMeshes, addNewMesh, scene, mirrorGround, ground, newVector, newColor, newScreenshot, serializeScene, newMetaDataEntry, selectedMeshes, singleMeshTNode, toRadians, toDegrees, multiMeshTNode, handleMousePointerTap, prepareCamera, buildMaterialsArray, buildMeshPositionsArray, createBoundingMesh, attachToSelectMeshesNode, newTexture, getUserMaterials, buildSelectedMaterialArray, buildMeshIdArray, refreshHighlight, guiTexture, getBoundingMeshData, getScaleFactor, gizmoManager, iblShadowPipeline, buildLightsArray } from '../helpers';
3
- import { toggleSafeFrame, toggleOrthographicViews, toggleBoundingBoxWidget, resetManagerGizmos, modelToOrigin, focusCamera } from '../actions';
4
- import { GLTF2 } from 'babylonjs-loaders';
5
- import { GIZMOS, TRANSPARENCY_MODES, GUI } from '../constants';
6
- import { reactProps as props } from '../Canvas';
7
- import { ratios, scaleUnits } from '../enums';
8
- import * as BABYLON from 'babylonjs';
9
- import _ from 'lodash';
10
- export let hiddenMeshes = [];
11
- const unitless = 'unitless';
12
- const performTransform = args => {
13
- const {
14
- type,
15
- vector,
16
- globalTransform,
17
- newTrackingData,
18
- tx,
19
- ty,
20
- tz,
21
- rx,
22
- ry,
23
- rz,
24
- sx,
25
- sy,
26
- sz
27
- } = args;
28
- const globalTransforms = scene.metadata.globalTransforms;
29
- let newTransforms;
30
- const updateNode = () => {
31
- const fallback = type === 'scale' ? 1 : 0;
32
- const node0 = scene.getNodeByName('node0');
33
- const node = globalTransform ? node0 : singleMeshTNode;
34
- if (node) {
35
- switch (type) {
36
- case 'move':
37
- node.position = globalTransform ? vector.multiplyByFloats(-1, 1, 1) : vector;
38
- newTransforms = {
39
- tx: tx || fallback,
40
- ty: ty || fallback,
41
- tz: tz || fallback
42
- };
43
- break;
44
- case 'rotate':
45
- if (globalTransform) {
46
- vector.applyRotationQuaternionInPlace(node.absoluteRotationQuaternion);
47
- }
48
- node.rotation = globalTransform ? vector.multiplyByFloats(-1, 1, -1) : vector;
49
- newTransforms = {
50
- rx: (rx || fallback) % 360,
51
- ry: (ry || fallback) % 360,
52
- rz: (rz || fallback) % 360
53
- };
54
- break;
55
- default:
56
- node.scaling = vector;
57
- newTransforms = {
58
- sx: sx || fallback,
59
- sy: sy || fallback,
60
- sz: sz || fallback
61
- };
62
- break;
63
- }
64
- }
65
- };
66
- const getPositionsChangeAfterGlobal = () => {
67
- const userMeshes = getUserMeshes();
68
- const updatedPositions = scene.metadata.meshChangeTracking?.map(mesh => {
69
- const userMesh = userMeshes.find(userMesh => userMesh.id === mesh.meshId);
70
- const parent = userMesh?.parent;
71
- userMesh?.setParent?.(null);
72
- const boundingBox = getBoundingMeshData([userMesh]);
73
- const {
74
- center,
75
- rotation
76
- } = boundingBox;
77
- const newTracking = {
78
- ...mesh,
79
- tx: center.x,
80
- ty: center.y,
81
- tz: center.z,
82
- rx: -toDegrees(rotation.x) % 360,
83
- ry: toDegrees(rotation.y) % 360,
84
- rz: -toDegrees(rotation.z) % 360
85
- };
86
- userMesh?.setParent?.(parent);
87
- return newTracking;
88
- });
89
- return updatedPositions;
90
- };
91
- if (globalTransform) {
92
- /*
93
- TODO: Changing any transform input box value when multiple meshes are selected does nothing.
94
- TODO: Look into this rotation bug:
95
- Rotation:
96
- - Global rotate 90 on x.
97
- - Select balloon.
98
- - Local reset rotation Y to 0.
99
- - Local reset rotation X to 0.
100
- - Global reset rotation X to 0.
101
- - Select balloon.
102
- - First issue: Local rotation X value should be 90, reads -90.
103
- - Local reset rotation X to 0.
104
- - Result: Mesh is upside down.
105
- */
106
-
107
- updateNode();
108
- newMetaDataEntry('globalTransforms', {
109
- ...globalTransforms,
110
- ...newTransforms
111
- });
112
- newMetaDataEntry('meshChangeTracking', getPositionsChangeAfterGlobal());
113
- return;
114
- }
115
- updateNode();
116
- newMetaDataEntry('meshChangeTracking', newTrackingData(newTransforms));
117
- };
118
- const applyUVSettings = args => {
119
- const {
120
- texture,
121
- material
122
- } = args || {};
123
- if (!_.isEmpty(texture) && !_.isEmpty(material)) {
124
- const workingMaterial = scene.metadata.materials.find(mat => mat.materialId === material.id);
125
- const {
126
- uvXScale,
127
- uvYScale,
128
- uvXRotation,
129
- uvYRotation,
130
- uvZRotation,
131
- uvXOffset,
132
- uvYOffset
133
- } = workingMaterial?.uvSettings || {};
134
- texture.uAng = uvXRotation;
135
- texture.wAng = uvYRotation;
136
- texture.vAng = uvZRotation;
137
- texture.uOffset = uvXOffset;
138
- texture.vOffset = uvYOffset;
139
- texture.uScale = uvXScale;
140
- texture.vScale = uvYScale;
141
- }
142
- };
143
- const updateTextureChannel = (imageToMaintain, newImage, channelToUpdate) => {
144
- const maintainHeight = imageToMaintain?.naturalHeight ?? 0;
145
- const maintainWidth = imageToMaintain?.naturalWidth ?? 0;
146
- const newHeight = newImage?.naturalHeight ?? 0;
147
- const newWidth = newImage?.naturalWidth ?? 0;
148
- let maintainData;
149
- let newData;
150
- const maxHeight = Math.max(...[maintainHeight, newHeight, 1024]);
151
- const maxWidth = Math.max(...[maintainWidth, newWidth, 1024]);
152
- const canvas = document.createElement('canvas');
153
- const ctx = canvas.getContext('2d', {
154
- willReadFrequently: true
155
- });
156
- canvas.width = maxWidth;
157
- canvas.height = maxHeight;
158
- if (newImage) {
159
- ctx.drawImage(newImage, 0, 0, maxWidth, maxHeight);
160
- newData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
161
- }
162
- if (imageToMaintain) {
163
- ctx.drawImage(imageToMaintain, 0, 0, maxWidth, maxHeight);
164
- maintainData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
165
- }
166
- const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
167
- const combinedData = combinedImageData.data;
168
- for (let i = 0; i < combinedData.length; i += 4) {
169
- const maintainRed = maintainData ? maintainData[i] : 1;
170
- const maintainGreen = maintainData ? maintainData[i + 1] : 0;
171
- const maintainBlue = maintainData ? maintainData[i + 2] : 0;
172
- const maintainAlpha = maintainData ? maintainData[i + 3] : 255;
173
- const newRed = newData ? newData[i] : 1;
174
- const newGreen = newData ? newData[i + 1] : 0;
175
- const newBlue = newData ? newData[i + 2] : 0;
176
- const newAlpha = newData ? newData[i + 3] : 255;
177
- combinedData[i] = channelToUpdate === 'R' ? newRed : maintainRed;
178
- combinedData[i + 1] = channelToUpdate === 'G' ? newGreen : maintainGreen;
179
- combinedData[i + 2] = channelToUpdate === 'B' ? newBlue : maintainBlue;
180
- combinedData[i + 3] = channelToUpdate === 'A' ? newAlpha : maintainAlpha;
181
- }
182
- ctx.putImageData(combinedImageData, 0, 0);
183
- return canvas.toDataURL('image/png');
184
- };
185
-
186
- // eslint-disable-next-line
187
- const loadImage = async file => {
188
- return new Promise(resolve => {
189
- const reader = new FileReader();
190
- reader.onload = event => {
191
- const img = new Image();
192
- img.onload = () => resolve(img);
193
- img.onerror = () => {
194
- resolve(null);
195
- };
196
- img.src = event.target.result;
197
- };
198
- reader.onerror = () => {
199
- resolve(null);
200
- };
201
- reader.readAsDataURL(file);
202
- });
203
- };
204
- const metallicTextureToImage = texture => {
205
- return new Promise(resolve => {
206
- if (!texture.readPixels()) {
207
- resolve(null);
208
- return;
209
- }
210
- texture.readPixels().then(pixels => {
211
- const canvas = document.createElement('canvas');
212
- const ctx = canvas.getContext('2d');
213
- const {
214
- width,
215
- height
216
- } = texture.getSize();
217
- canvas.width = width;
218
- canvas.height = height;
219
- const img = new Image();
220
- const imageData = ctx.createImageData(width, height);
221
- imageData.data.set(new Uint8ClampedArray(pixels));
222
- ctx.putImageData(imageData, 0, 0);
223
- img.onload = () => {
224
- resolve(img);
225
- };
226
- img.onerror = () => {
227
- resolve(null);
228
- };
229
- img.src = canvas.toDataURL();
230
- }).catch(() => {
231
- resolve(null);
232
- });
233
- });
234
- };
235
- const dataUrlToBlob = dataURI => {
236
- // convert base64 to raw binary data held in a string
237
- // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
238
- const byteString = atob(dataURI.split(',')[1]);
239
-
240
- // separate out the mime component
241
- const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
242
-
243
- // write the bytes of the string to an ArrayBuffer
244
- const ab = new ArrayBuffer(byteString.length);
245
-
246
- // create a view into the buffer
247
- const ia = new Uint8Array(ab);
248
-
249
- // set the bytes of the buffer to the correct values
250
- for (let i = 0; i < byteString.length; i++) {
251
- ia[i] = byteString.charCodeAt(i);
252
- }
253
-
254
- // write the ArrayBuffer to a blob, and you're done
255
- const blob = new Blob([ab], {
256
- type: mimeString
257
- });
258
- return blob;
259
- };
260
- export const updateMaterial = inboundData => {
261
- const {
262
- payload
263
- } = inboundData;
264
- const {
265
- id,
266
- meshSimplification,
267
- textureDownscaling,
268
- newId,
269
- selectMaterial,
270
- backfaceCullingEnabled,
271
- wireFrameEnabled,
272
- pointsCloudEnabled,
273
- albedoColor,
274
- albedoTexture,
275
- environmentIntensity,
276
- metallic,
277
- metallicTexture,
278
- roughness,
279
- roughnessTexture,
280
- ambientColor,
281
- ambientTextureStrength,
282
- ambientTexture,
283
- microSurfaceTexture,
284
- emissiveColor,
285
- emissiveIntensity,
286
- emissiveTexture,
287
- bumpIntensity,
288
- bumpTexture,
289
- clearCoatEnabled,
290
- clearCoatIntensity,
291
- clearCoatRoughness,
292
- clearCoatIOR,
293
- alpha,
294
- transparencyType,
295
- sssIOR,
296
- sssRefractionIntensity,
297
- transparencyEnabled,
298
- opacityTexture,
299
- newSelectedMaterial,
300
- albedoHasAlpha,
301
- clearTextureChannels,
302
- uvXScale,
303
- uvYScale,
304
- uvScaleLock,
305
- uvXRotation,
306
- uvYRotation,
307
- uvZRotation,
308
- uvXOffset,
309
- uvYOffset
310
- } = payload;
311
- const material = scene?.getMaterialByName?.(id, true);
312
- if (material) {
313
- // Renaming material.
314
- if (newId) {
315
- material.id = newId;
316
- material.name = newId;
317
- if (Array.isArray(scene.metadata.selectedMaterials) && scene.metadata.selectedMaterials.length > 0) {
318
- // We currently only support one selectedMaterial at a time so we should set the changed material to selected
319
- newMetaDataEntry('selectedMaterials', [material]);
320
- }
321
- }
322
-
323
- // Select all meshes with current material.
324
- if (selectMaterial) {
325
- resetSelectedMeshes();
326
- const userMeshes = getUserMeshes();
327
- userMeshes.forEach(mesh => mesh.material?.name === id && addNewMesh(mesh));
328
- newMetaDataEntry('selectedMeshes', buildMeshIdArray());
329
- refreshHighlight();
330
- return;
331
- }
332
-
333
- // Selecting single material.
334
- if (newSelectedMaterial) {
335
- resetSelectedMeshes();
336
- const newMaterial = scene.metadata.materials.find(mat => mat.materialId === id);
337
- newMetaDataEntry('selectedMaterials', [newMaterial]);
338
- refreshHighlight();
339
- return;
340
- }
341
-
342
- // Reset supported texture channels, useful when manually importing a new material.
343
- if (clearTextureChannels) {
344
- const workingMaterial = scene.metadata.materials.find(mat => mat.materialId === id) || {};
345
- Object.keys(workingMaterial)?.forEach(key => {
346
- if (key.endsWith('Texture')) {
347
- material[key] = null;
348
- }
349
- });
350
- }
351
-
352
- // Back-face culling
353
- if (backfaceCullingEnabled !== undefined) material.backFaceCulling = backfaceCullingEnabled;
354
-
355
- // Wireframe
356
- if (wireFrameEnabled !== undefined) material.wireframe = wireFrameEnabled;
357
-
358
- // Point cloud
359
- if (pointsCloudEnabled !== undefined) material.pointsCloud = pointsCloudEnabled;
360
-
361
- // Mesh simplification and texture downscaling
362
- if (!_.isEmpty(meshSimplification)) {
363
- material.meshSimplification = {
364
- ...material.meshSimplification,
365
- ...meshSimplification
366
- };
367
- }
368
- if (!_.isEmpty(textureDownscaling)) {
369
- material.textureDownscaling = {
370
- ...material.textureDownscaling,
371
- ...textureDownscaling
372
- };
373
- }
374
-
375
- // Diffuse
376
- if (albedoColor) material.albedoColor = newColor(albedoColor);
377
- if (environmentIntensity !== undefined) material.environmentIntensity = environmentIntensity;
378
- if (!_.isEmpty(albedoTexture?.src || albedoTexture?.url)) {
379
- material.albedoTexture = newTexture(albedoTexture?.src || albedoTexture?.url);
380
- material.albedoTexture.name = albedoTexture.name;
381
- applyUVSettings({
382
- texture: material.albedoTexture,
383
- material
384
- });
385
- }
386
-
387
- // Metallic
388
- if (metallic !== undefined) material.metallic = metallic;
389
- if (!_.isEmpty(metallicTexture?.src || metallicTexture?.url)) {
390
- // Metallic Texture uses the B channel of the metallicTexture for a PBRMaterial
391
- const texture = newTexture(metallicTexture?.src || metallicTexture?.url);
392
- let currentTexture = material.metallicTexture;
393
- if (!currentTexture) {
394
- material.metallicTexture = newTexture();
395
- material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
396
- currentTexture = material.metallicTexture;
397
- }
398
- const metallicBlob = dataUrlToBlob(texture.url);
399
- Promise.all([loadImage(metallicBlob), metallicTextureToImage(currentTexture)]).then(data => {
400
- const [metallicImage, currentImage] = data;
401
- const combinedTexture = updateTextureChannel(currentImage, metallicImage, 'B');
402
- currentTexture.updateURL(combinedTexture);
403
- material.useRoughnessFromMetallicTextureAlpha = false;
404
- material.useMetalnessFromMetallicTextureBlue = true;
405
- texture.dispose();
406
- applyUVSettings({
407
- texture: material.metallicTexture,
408
- material
409
- });
410
- newMetaDataEntry('materials', buildMaterialsArray());
411
- newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
412
- props.clearNotifications?.();
413
- props.setSerializedData?.(serializeScene());
414
- }).catch(err => {
415
- console.log(`Error updating the roughness texture of material: ${material.name}`);
416
- console.log({
417
- err
418
- });
419
- });
420
- }
421
-
422
- // Roughness
423
- if (roughness !== undefined) material.roughness = roughness;
424
- if (!_.isEmpty(microSurfaceTexture?.src || microSurfaceTexture?.url)) {
425
- material.microSurfaceTexture = newTexture(microSurfaceTexture?.src || microSurfaceTexture?.url);
426
- material.microSurfaceTexture.name = microSurfaceTexture.name;
427
- applyUVSettings({
428
- texture: material.microSurfaceTexture,
429
- material
430
- });
431
- }
432
- if (!_.isEmpty(roughnessTexture?.src || roughnessTexture?.url)) {
433
- // Roughness Texture uses the G channel of the metallicTexture for a PBRMaterial
434
- const texture = newTexture(roughnessTexture?.src || roughnessTexture?.url);
435
- let currentTexture = material.metallicTexture;
436
- if (!currentTexture) {
437
- material.metallicTexture = newTexture();
438
- material.metallicTexture.name = `${material.name} (Metallic-Roughness)`;
439
- currentTexture = material.metallicTexture;
440
- }
441
- const roughnessBlob = dataUrlToBlob(texture.url);
442
- Promise.all([loadImage(roughnessBlob), metallicTextureToImage(currentTexture)]).then(data => {
443
- const [roughnessImage, metallicImage] = data;
444
- const combinedTexture = updateTextureChannel(metallicImage, roughnessImage, 'G');
445
- currentTexture.updateURL(combinedTexture);
446
- material.useRoughnessFromMetallicTextureAlpha = false;
447
- material.useRoughnessFromMetallicTextureGreen = true;
448
- texture.dispose();
449
- applyUVSettings({
450
- texture: material.metallicTexture,
451
- material
452
- });
453
- newMetaDataEntry('materials', buildMaterialsArray());
454
- newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
455
- props.clearNotifications?.();
456
- props.setSerializedData?.(serializeScene());
457
- }).catch(err => {
458
- console.log(`Error updating the roughness texture of material: ${material.name}`);
459
- console.log({
460
- err
461
- });
462
- });
463
- }
464
-
465
- // Ambient
466
- if (ambientColor) material.ambientColor = newColor(ambientColor);
467
- if (ambientTextureStrength !== undefined) material.ambientTextureStrength = ambientTextureStrength;
468
- if (!_.isEmpty(ambientTexture?.src || ambientTexture?.url)) {
469
- material.ambientTexture = newTexture(ambientTexture?.src || ambientTexture?.url);
470
- material.ambientTexture.name = ambientTexture.name;
471
- applyUVSettings({
472
- texture: material.ambientTexture,
473
- material
474
- });
475
- }
476
-
477
- // Emissive
478
- if (emissiveColor) material.emissiveColor = newColor(emissiveColor);
479
- if (emissiveIntensity !== undefined) material.emissiveIntensity = emissiveIntensity;
480
- if (!_.isEmpty(emissiveTexture?.src || emissiveTexture?.url)) {
481
- material.emissiveTexture = newTexture(emissiveTexture?.src || emissiveTexture?.url);
482
- material.emissiveTexture.name = emissiveTexture.name;
483
- applyUVSettings({
484
- texture: material.emissiveTexture,
485
- material
486
- });
487
- }
488
-
489
- // Normal/Bump
490
- if (bumpIntensity !== undefined && !_.isEmpty(material.bumpTexture?.url)) {
491
- material.bumpTexture.level = bumpIntensity;
492
- }
493
- if (!_.isEmpty(bumpTexture?.src || bumpTexture?.url)) {
494
- material.bumpTexture = newTexture(bumpTexture?.src || bumpTexture?.url);
495
- material.bumpTexture.name = bumpTexture.name;
496
- applyUVSettings({
497
- texture: material.bumpTexture,
498
- material
499
- });
500
- }
501
-
502
- // Clear coat
503
- if (clearCoatEnabled !== undefined) material.clearCoat.isEnabled = clearCoatEnabled;
504
- if (material.clearCoat?.isEnabled) {
505
- if (clearCoatIntensity !== undefined) material.clearCoat.intensity = clearCoatIntensity ?? 1;
506
- if (clearCoatRoughness !== undefined) material.clearCoat.roughness = clearCoatRoughness ?? 0.1;
507
- if (clearCoatIOR !== undefined) material.clearCoat.indexOfRefraction = clearCoatIOR ?? 1.52;
508
- }
509
-
510
- // Transparency
511
- if (!_.isEmpty(id) && material && transparencyEnabled !== undefined) {
512
- if (!albedoHasAlpha) {
513
- material.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
514
- }
515
- material.transparencyEnabled = transparencyEnabled;
516
- }
517
-
518
- // Albedo alpha
519
- if (!_.isEmpty(id) && material && albedoHasAlpha !== undefined) {
520
- const hasAlbedoTexture = material?.albedoTexture;
521
- const alphaMode = albedoHasAlpha ? 'PBRMATERIAL_ALPHATEST' : 'PBRMATERIAL_ALPHABLEND';
522
- if (hasAlbedoTexture) {
523
- material.albedoTexture.hasAlpha = albedoHasAlpha;
524
- material.albedoTexture.useAlphaFromAlbedoTexture = albedoHasAlpha;
525
- material.transparencyMode = BABYLON.PBRMaterial[alphaMode];
526
- }
527
- }
528
- if (alpha !== undefined) material.alpha = alpha ?? 1;
529
- if (!_.isEmpty(opacityTexture?.src || opacityTexture?.url)) {
530
- material.opacityTexture = newTexture(opacityTexture?.src || opacityTexture?.url);
531
- material.opacityTexture.name = opacityTexture.name;
532
- applyUVSettings({
533
- texture: material.opacityTexture,
534
- material
535
- });
536
- }
537
- if (transparencyType) {
538
- material.transparencyType = _.toLower(transparencyType);
539
- }
540
- const isComplex = _.toLower(material.transparencyType) === TRANSPARENCY_MODES.complex;
541
- if (material.subSurface) {
542
- material.subSurface.isRefractionEnabled = isComplex;
543
- }
544
- if (isComplex) {
545
- if (sssRefractionIntensity !== undefined) material.subSurface.refractionIntensity = sssRefractionIntensity ?? 1;
546
- if (sssIOR !== undefined) material.subSurface.indexOfRefraction = sssIOR ?? 1.52;
547
- }
548
-
549
- // UV scale, rotation and offset
550
- const xScaleReq = uvXScale !== undefined;
551
- const yScaleReq = uvYScale !== undefined;
552
- const xRotationReq = uvXRotation !== undefined;
553
- const yRotationReq = uvYRotation !== undefined;
554
- const zRotationReq = uvZRotation !== undefined;
555
- const xOffsetReq = uvXOffset !== undefined;
556
- const yOffsetReq = uvYOffset !== undefined;
557
- const uvChangeRequest = xScaleReq || yScaleReq || xRotationReq || yRotationReq || zRotationReq || xOffsetReq || yOffsetReq;
558
- if (uvChangeRequest) {
559
- const workingMaterial = scene.metadata.materials.find(mat => mat.materialId === id) || {};
560
- Object.keys(workingMaterial)?.forEach(key => {
561
- const texture = material[key];
562
- const validMaterialWithTexture = _.isObject(texture) && !_.isArray(texture) && key.endsWith('Texture');
563
- const hasAllKeys = texture && ['uAng', 'wAng', 'vAng', 'uOffset', 'vOffset', 'uScale', 'vScale'].every(key => texture[key] !== undefined);
564
- if (validMaterialWithTexture && hasAllKeys) {
565
- if (xRotationReq) texture.uAng = uvXRotation;
566
- if (yRotationReq) texture.wAng = uvYRotation;
567
- if (zRotationReq) texture.vAng = uvZRotation;
568
- if (xOffsetReq) texture.uOffset = uvXOffset;
569
- if (yOffsetReq) texture.vOffset = uvYOffset;
570
- if ((xScaleReq || yScaleReq) && uvScaleLock) {
571
- texture.uScale = uvXScale ?? uvYScale;
572
- texture.vScale = uvXScale ?? uvYScale;
573
- return;
574
- }
575
- if (xScaleReq) texture.uScale = uvXScale;
576
- if (yScaleReq) texture.vScale = uvYScale;
577
- if (uvScaleLock !== undefined) newMetaDataEntry('uvScaleLock', uvScaleLock);
578
- }
579
- });
580
- }
581
- newMetaDataEntry('materials', buildMaterialsArray());
582
- newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
583
- }
584
- };
585
- export const updateMesh = inboundData => {
586
- const {
587
- payload
588
- } = inboundData;
589
- const {
590
- id,
591
- useSavedPosition,
592
- axisCompensation,
593
- boundingBoxEnabled,
594
- transforms,
595
- flipHorizontally,
596
- globalTransform,
597
- variantName,
598
- resetVariant,
599
- sourceUnit,
600
- displayUnit
601
- } = payload;
602
- const khrExtension = GLTF2.KHR_materials_variants;
603
- const selectedMesh = scene.metadata.selectedMeshes?.[0];
604
- const meshChangeTracking = scene.metadata?.meshChangeTracking || [];
605
- const selectedSourceUnit = scene.metadata.selectedSourceUnit;
606
- const selectedDisplayUnit = scene.metadata?.selectedDisplayUnit;
607
- const isBoundingBoxEnabled = gizmoManager.boundingBoxGizmoEnabled;
608
- const userMeshes = getUserMeshes();
609
- const rootMesh = scene.getMeshByID('__root__');
610
- const newTrackingData = args => meshChangeTracking?.map(mesh => {
611
- return mesh.meshId === selectedMesh?.id ? {
612
- ...mesh,
613
- ...args
614
- } : mesh;
615
- });
616
-
617
- // Change display units
618
- if (!_.isEmpty(displayUnit) && selectedSourceUnit && selectedSourceUnit !== unitless) {
619
- const newDisplayUnit = displayUnit === unitless ? selectedSourceUnit : displayUnit;
620
- newMetaDataEntry('selectedDisplayUnit', newDisplayUnit);
621
- if (isBoundingBoxEnabled) {
622
- toggleBoundingBoxWidget();
623
- toggleBoundingBoxWidget();
624
- }
625
- }
626
-
627
- // Change mesh scale based on source units
628
- if (!_.isEmpty(sourceUnit) && !_.isEmpty(userMeshes)) {
629
- const globalTransforms = scene.metadata.globalTransforms;
630
- const {
631
- tx,
632
- ty,
633
- tz,
634
- sx,
635
- sy,
636
- sz
637
- } = globalTransforms;
638
- const scaleFactor = getScaleFactor(sourceUnit);
639
- const resetScaleFactor = getScaleFactor(selectedSourceUnit) / scaleFactor;
640
- const isDifferent = !_.isEqual(sourceUnit, selectedSourceUnit);
641
- const isMeter = _.isEqual(sourceUnit, 'm') || _.isEqual(sourceUnit, 'meter');
642
- const newScale = scaleValue => {
643
- if (!selectedSourceUnit && !isMeter) return scaleValue * scaleFactor;
644
- if (selectedSourceUnit && isMeter) return scaleValue / resetScaleFactor;
645
- if (isMeter) return scaleValue / scaleFactor;
646
- if (selectedSourceUnit === 'm' || selectedSourceUnit === 'meter') {
647
- return scaleValue / resetScaleFactor;
648
- }
649
- if (selectedSourceUnit && !isMeter || selectedSourceUnit && sourceUnit === unitless) {
650
- // NOTE: If switching to unit other than meter, or user sends source unit reset,
651
- // reset back to original mystery unit size/scale first.
652
- const lastScaleFactor = getScaleFactor(selectedSourceUnit);
653
- const originalScale = scaleValue / lastScaleFactor;
654
- return originalScale * scaleFactor;
655
- }
656
- return scaleValue / resetScaleFactor * scaleFactor;
657
- };
658
- const convertedScales = {
659
- tx: newScale(tx),
660
- ty: newScale(ty),
661
- tz: newScale(tz),
662
- sx: newScale(sx),
663
- sy: newScale(sy),
664
- sz: newScale(sz)
665
- };
666
- if (isDifferent) {
667
- const unit = scaleUnits.find(unit => unit.abbreviation === sourceUnit || unit.name === sourceUnit);
668
- const {
669
- tx,
670
- ty,
671
- tz,
672
- sx,
673
- sy,
674
- sz
675
- } = convertedScales;
676
- const scalingVector = newVector(sx, sy, sz);
677
- const positionVector = newVector(tx, ty, tz);
678
- const sourceUnitScaleOperation = true;
679
- performTransform({
680
- type: 'scale',
681
- vector: scalingVector,
682
- newTrackingData,
683
- globalTransform: true,
684
- sx,
685
- sy,
686
- sz
687
- });
688
- performTransform({
689
- type: 'move',
690
- vector: positionVector,
691
- newTrackingData,
692
- globalTransform: true,
693
- tx,
694
- ty,
695
- tz
696
- });
697
- if (sourceUnit !== unitless) {
698
- newMetaDataEntry('selectedSourceUnit', sourceUnit);
699
- !selectedDisplayUnit && newMetaDataEntry('selectedDisplayUnit', unit?.abbreviation);
700
- }
701
- if (sourceUnit === unitless) {
702
- newMetaDataEntry('selectedSourceUnit', null);
703
- newMetaDataEntry('selectedDisplayUnit', null);
704
- }
705
- newMetaDataEntry('globalTransforms', {
706
- ...globalTransforms,
707
- ...convertedScales
708
- });
709
- modelToOrigin(sourceUnitScaleOperation);
710
- isBoundingBoxEnabled && toggleBoundingBoxWidget();
711
- focusCamera();
712
- isBoundingBoxEnabled && toggleBoundingBoxWidget();
713
- return;
714
- }
715
- }
716
-
717
- // Change mesh variant data
718
- if (!_.isEmpty(variantName) && rootMesh) {
719
- khrExtension.SelectVariant(rootMesh, variantName);
720
- newMetaDataEntry('selectedMaterialVariant', variantName);
721
- }
722
-
723
- // Reset mesh variant data
724
- if (_.isEmpty(variantName) && resetVariant && rootMesh) {
725
- khrExtension.Reset(rootMesh);
726
- newMetaDataEntry('selectedMaterialVariant', null);
727
- }
728
-
729
- // Bounding Box Toggle
730
- if (boundingBoxEnabled !== undefined) {
731
- toggleBoundingBoxWidget();
732
- }
733
- if (flipHorizontally) {
734
- const multiMeshOperation = userMeshes.length > 1;
735
- userMeshes.forEach(mesh => addNewMesh(mesh));
736
- multiMeshOperation ? multiMeshTNode.scaling = newVector(-1, 1, 1) : singleMeshTNode.scaling = newVector(-1, 1, 1);
737
- handleMousePointerTap();
738
- return;
739
- }
740
- const meshPosition = useSavedPosition ? scene.metadata?.userMeshPositions?.find(mesh => mesh.positionId === id && selectedMesh.id === mesh.meshId) || {} : transforms;
741
- if (_.isEmpty(meshPosition)) return;
742
- const {
743
- tx,
744
- ty,
745
- tz,
746
- rx,
747
- ry,
748
- rz,
749
- sx,
750
- sy,
751
- sz
752
- } = meshPosition;
753
- if (useSavedPosition) {
754
- const filteredPositions = scene.metadata.selectedUserMeshPositions.filter(pos => pos.meshId !== meshPosition.meshId);
755
- filteredPositions.push(meshPosition);
756
- newMetaDataEntry('selectedUserMeshPositions', filteredPositions);
757
- }
758
-
759
- // Axis Compensation
760
- if (_.isString(axisCompensation) && transforms && scene.metadata.selectedAxisCompensation !== axisCompensation) {
761
- const userMaterials = getUserMaterials();
762
- const firstMaterial = userMaterials[0] || {};
763
- const multiMeshOperation = userMeshes.length > 1;
764
- resetSelectedMeshes();
765
- userMeshes.forEach(mesh => addNewMesh(mesh));
766
- multiMeshOperation ? multiMeshTNode.rotation = newVector(toRadians(rx), toRadians(ry), toRadians(rz)) : singleMeshTNode.rotation = newVector(toRadians(rx), toRadians(ry), toRadians(rz));
767
- handleMousePointerTap();
768
- newMetaDataEntry('selectedAxisCompensation', axisCompensation);
769
- newMetaDataEntry('meshChangeTracking', buildMeshPositionsArray());
770
- newMetaDataEntry('selectedMaterials', []);
771
-
772
- // Reset scaling to previous
773
- meshChangeTracking.forEach(mesh => {
774
- const foundMesh = meshChangeTracking.find(prevMesh => prevMesh.id === mesh.id);
775
- if (foundMesh) {
776
- mesh.sx = foundMesh.sx;
777
- mesh.sy = foundMesh.sy;
778
- mesh.sz = foundMesh.sz;
779
- }
780
- });
781
- if (!_.isEmpty(firstMaterial)) {
782
- const existingMaterial = scene.metadata.materials.find(mat => mat.materialId === firstMaterial.id);
783
- newMetaDataEntry('selectedMaterials', [existingMaterial]);
784
- }
785
- newMetaDataEntry('selectedMeshes', []);
786
- modelToOrigin();
787
- focusCamera();
788
- multiMeshOperation ? multiMeshTNode.rotation = newVector(toRadians(0), toRadians(0), toRadians(0)) : singleMeshTNode.rotation = newVector(toRadians(0), toRadians(0), toRadians(0));
789
- }
790
-
791
- // Transform inputs and Custom user position restoring.
792
- if (meshPosition) {
793
- const doPosition = [tx, ty, tz].every(val => val !== undefined);
794
- const doRotation = [rx, ry, rz].every(val => val !== undefined);
795
- const doScale = [sx, sy, sz].every(val => val !== undefined);
796
- if (doPosition) {
797
- const positionVector = newVector(tx, ty, tz);
798
- performTransform({
799
- type: 'move',
800
- vector: positionVector,
801
- newTrackingData,
802
- globalTransform,
803
- tx,
804
- ty,
805
- tz
806
- });
807
- }
808
- if (doRotation) {
809
- const rotationVector = newVector(toRadians(rx), toRadians(ry), toRadians(rz));
810
- performTransform({
811
- type: 'rotate',
812
- vector: rotationVector,
813
- newTrackingData,
814
- globalTransform,
815
- rx,
816
- ry,
817
- rz
818
- });
819
- }
820
- if (doScale) {
821
- // TODO: Handle zeroes
822
- const currentMeshTracking = globalTransform ? scene.metadata.globalTransforms : scene.metadata.meshChangeTracking.find(mesh => mesh.meshId === selectedMesh.id);
823
- const {
824
- sx: currentSx,
825
- sy: currentSy,
826
- sz: currentSz
827
- } = currentMeshTracking;
828
- const newScaleX = globalTransform ? sx : sx / currentSx || 1;
829
- const newScaleY = globalTransform ? sy : sy / currentSy || 1;
830
- const newScaleZ = globalTransform ? sz : sz / currentSz || 1;
831
- const isValid = [newScaleX, newScaleY, newScaleZ].every(val => val !== 0);
832
- if (isValid) {
833
- const scalingVector = newVector(newScaleX, newScaleY, newScaleZ);
834
- performTransform({
835
- type: 'scale',
836
- vector: scalingVector,
837
- newTrackingData,
838
- globalTransform,
839
- sx,
840
- sy,
841
- sz
842
- });
843
- }
844
- }
845
- }
846
- attachToSelectMeshesNode();
847
- createBoundingMesh();
848
- resetManagerGizmos(GIZMOS.BoundingBoxGizmo);
849
- };
850
- export const updateCamera = inboundData => {
851
- const {
852
- payload
853
- } = inboundData;
854
- const {
855
- id,
856
- transforms,
857
- enableSafeFrame,
858
- aspectRatio,
859
- orthoCamera,
860
- resetCamera,
861
- takeScreenshot,
862
- isBillboard,
863
- imageDataOnly
864
- } = payload;
865
- const camera = scene.activeCamera;
866
- if (camera) {
867
- // Orthographic view selections.
868
- if (orthoCamera !== undefined) toggleOrthographicViews(null, orthoCamera);
869
-
870
- // Update camera position and rotation.
871
- if (_.isString(id) && !_.isEmpty(transforms)) {
872
- const {
873
- tx,
874
- ty,
875
- tz,
876
- rx,
877
- ry,
878
- rz,
879
- tarX,
880
- tarY,
881
- tarZ
882
- } = transforms;
883
- if (tx && ty && tz) camera.position = newVector(tx, ty, tz);
884
- if (rx && ry && rz) camera.rotation = newVector(rx, ry, rz);
885
- if (tarX && tarY && tarZ) camera.target = newVector(tarX, tarY, tarZ);
886
- if (camera.mode === BABYLON.Camera.ORTHOGRAPHIC_CAMERA) {
887
- camera.mode = BABYLON.Camera.PERSPECTIVE_CAMERA;
888
- }
889
- newMetaDataEntry('selectedUserCameraView', {
890
- id,
891
- tx,
892
- ty,
893
- tz,
894
- rx,
895
- ry,
896
- rz,
897
- tarX,
898
- tarY,
899
- tarZ
900
- });
901
- }
902
-
903
- // Reset camera to default position and rotation.
904
- if (resetCamera !== undefined) {
905
- prepareCamera();
906
- const {
907
- position,
908
- rotation,
909
- target
910
- } = scene.activeCamera;
911
- const [tx, ty, tz] = [position.x, position.y, position.z];
912
- const [rx, ry, rz] = [rotation.x, rotation.y, rotation.z];
913
- const [tarX, tarY, tarZ] = [target.x, target.y, target.z];
914
- newMetaDataEntry('selectedOrthoView', '');
915
- newMetaDataEntry('selectedUserCameraView', {
916
- id: 'Default',
917
- tx,
918
- ty,
919
- tz,
920
- rx,
921
- ry,
922
- rz,
923
- tarX,
924
- tarY,
925
- tarZ
926
- });
927
- }
928
-
929
- // Toggle safe frame.
930
- if (enableSafeFrame !== undefined && _.isNumber(aspectRatio)) {
931
- const newMetaValue = enableSafeFrame ? Object.values(ratios).find(ratio => ratio.value === aspectRatio) : {};
932
- toggleSafeFrame(null, aspectRatio, enableSafeFrame);
933
- newMetaDataEntry('selectedRatio', newMetaValue);
934
- }
935
-
936
- // Take screenshot.
937
- if (takeScreenshot !== undefined && _.isNumber(aspectRatio)) {
938
- const callback = screenshotData => {
939
- newMetaDataEntry('screenshotData', screenshotData);
940
- const outerFrame = guiTexture.getControlByName(GUI.outerSafeFrame);
941
- const {
942
- widthInPixels,
943
- heightInPixels,
944
- centerX,
945
- centerY
946
- } = outerFrame;
947
- const baseResolution = 2048;
948
- const ratio = widthInPixels > heightInPixels ? widthInPixels / baseResolution : heightInPixels / baseResolution;
949
- const highResHeight = heightInPixels / ratio;
950
- const highResWidth = widthInPixels / ratio;
951
-
952
- // NOTE: Serializes scene for billboard screenshots exactly onSuccess.
953
- props.setSerializedData?.(serializeScene());
954
- const canvas = document.createElement('canvas');
955
- const context = canvas.getContext('2d');
956
- canvas.width = highResWidth;
957
- canvas.height = highResHeight;
958
- const image = new Image();
959
- image.src = screenshotData;
960
- image.onload = () => {
961
- context.drawImage(image, outerFrame.isVisible ? centerX - widthInPixels / 2 : centerX - canvas.width / 2,
962
- // Moves image right
963
- outerFrame.isVisible ? centerY - heightInPixels / 2 : centerY - canvas.height / 2,
964
- // Moves image down
965
- outerFrame.isVisible ? widthInPixels : canvas.width, outerFrame.isVisible ? heightInPixels : canvas.height, 0,
966
- // Moves image right
967
- 0,
968
- // Moves image down
969
- highResWidth, highResHeight);
970
- const imageData = canvas.toDataURL('image/png', 1.0);
971
-
972
- // Download
973
- if (!imageDataOnly) {
974
- const link = document.createElement('a');
975
- link.download = 'screenshot.png';
976
- link.href = imageData;
977
- document.body.appendChild(link);
978
- link.click();
979
- document.body.removeChild(link);
980
- }
981
- };
982
- };
983
- newScreenshot(isBillboard, callback);
984
- newMetaDataEntry('selectedRatio', Object.values(ratios).find(ratio => ratio.value === aspectRatio));
985
- }
986
- }
987
- };
988
- export const updateEnvironment = inboundData => {
989
- const {
990
- payload
991
- } = inboundData;
992
- const {
993
- url,
994
- envIntensity,
995
- envBlur,
996
- transforms
997
- } = payload;
998
- const skyBox = scene.getMaterialById('skyBox', true);
999
- if (skyBox) {
1000
- // Intensity
1001
- if (envIntensity !== undefined) {
1002
- scene.environmentIntensity = envIntensity;
1003
- newMetaDataEntry('environmentIntensity', envIntensity);
1004
- }
1005
-
1006
- // Blur
1007
- if (envBlur !== undefined) {
1008
- skyBox.microSurface = 1 - envBlur;
1009
- newMetaDataEntry('environmentBlur', envBlur);
1010
- }
1011
-
1012
- // Update environment texture.
1013
- if (_.isString(url)) {
1014
- const selectedUserEnvironment = scene.metadata?.userEnvironments?.find(env => env.url === url) || props.defaultEnvironments.find(item => item.envURL === url) || {
1015
- id: 'Default',
1016
- url: scene.metadata.defaultEnvironment
1017
- };
1018
- const {
1019
- id,
1020
- name,
1021
- envURL,
1022
- url: userURL
1023
- } = selectedUserEnvironment;
1024
- const metaName = id || name;
1025
- const metaURL = userURL || envURL;
1026
- scene.environmentTexture.url = metaURL;
1027
- scene.environmentTexture.name = metaURL;
1028
- skyBox.reflectionTexture.url = metaURL;
1029
- skyBox.reflectionTexture.name = metaURL;
1030
- const newEnv = scene.environmentTexture.clone();
1031
- const newSkyBox = skyBox.reflectionTexture.clone();
1032
- scene.environmentTexture.dispose();
1033
- skyBox.reflectionTexture.dispose();
1034
- scene.environmentTexture = newEnv;
1035
- skyBox.reflectionTexture = newSkyBox;
1036
- newMetaDataEntry('selectedUserEnvironment', {
1037
- id: metaName,
1038
- url: metaURL
1039
- });
1040
- }
1041
-
1042
- // Rotation
1043
- if (transforms?.rotation?.ry !== undefined) {
1044
- const envRotation = toRadians(transforms.rotation.ry);
1045
- skyBox.reflectionTexture.rotationY = envRotation;
1046
- scene.environmentTexture.rotationY = envRotation;
1047
- newMetaDataEntry('environmentRotation', toDegrees(envRotation));
1048
- }
1049
- }
1050
- };
1051
- export const updateViewport = inboundData => {
1052
- const {
1053
- payload
1054
- } = inboundData;
1055
- const {
1056
- envVisible,
1057
- shadows,
1058
- iblPipeline,
1059
- axes,
1060
- grid,
1061
- hideSelected,
1062
- unhideAll,
1063
- unhideLast,
1064
- deselectAll
1065
- } = payload;
1066
- const hdrSkyBox = scene.getMeshByName('hdrSkyBox');
1067
- const xAxisMesh = scene.getMeshByName('xAxisMesh');
1068
- const yAxisMesh = scene.getMeshByName('yAxisMesh');
1069
- const zAxisMesh = scene.getMeshByName('zAxisMesh');
1070
-
1071
- // Hide selected meshes.
1072
- if (hideSelected) {
1073
- selectedMeshes.forEach(mesh => {
1074
- mesh.isVisible = false;
1075
- hiddenMeshes.push(mesh);
1076
- });
1077
- resetSelectedMeshes();
1078
- }
1079
-
1080
- // Unhide all meshes.
1081
- if (unhideAll) {
1082
- const userMeshes = getUserMeshes();
1083
- userMeshes.forEach(mesh => mesh.isVisible = true);
1084
- hiddenMeshes = [];
1085
- }
1086
-
1087
- // Unhide last hidden mesh.
1088
- if (unhideLast) {
1089
- if (!_.isEmpty(hiddenMeshes)) {
1090
- const mesh = hiddenMeshes.pop();
1091
- mesh.isVisible = true;
1092
- }
1093
- }
1094
-
1095
- // Deselect all meshes.
1096
- if (deselectAll) resetSelectedMeshes();
1097
-
1098
- // Environment visibility.
1099
- if (envVisible !== undefined) {
1100
- hdrSkyBox.setEnabled(envVisible);
1101
- newMetaDataEntry('viewportEnvironment', envVisible);
1102
- }
1103
-
1104
- // Shadow visbility
1105
- if (shadows !== undefined) {
1106
- mirrorGround.receiveShadows = shadows;
1107
- newMetaDataEntry('viewportShadows', shadows);
1108
- }
1109
-
1110
- // Grid visibility
1111
- if (grid !== undefined) {
1112
- ground.setEnabled(grid);
1113
- newMetaDataEntry('viewportGround', grid);
1114
- }
1115
-
1116
- // Axis visibility
1117
- if (axes !== undefined) {
1118
- xAxisMesh.setEnabled(axes);
1119
- yAxisMesh.setEnabled(axes);
1120
- zAxisMesh.setEnabled(axes);
1121
- newMetaDataEntry('viewportAxes', axes);
1122
- }
1123
-
1124
- // IBL Shadow Rendering Pipeline
1125
- if (iblPipeline !== undefined) {
1126
- iblShadowPipeline.toggleShadow(iblPipeline);
1127
- newMetaDataEntry('iblShadowPipelineEnabled', iblPipeline);
1128
- }
1129
- };
1130
- export const updatePublish = inboundData => {
1131
- const {
1132
- payload
1133
- } = inboundData;
1134
- const existingPublish = scene.metadata?.publish || {};
1135
- const totalTriangles = +(scene.metadata.statistics?.triangles?.replace?.(/,/g, '') || 0);
1136
- const incomingTargetTriangles = payload?.meshSimplification?.userTargetTriangles || existingPublish?.meshSimplification?.userTargetTriangles || totalTriangles;
1137
- const estimatedTriangles = payload?.meshSimplification?.estimatedTriangles || existingPublish?.meshSimplification?.estimatedTriangles || 99; // Percent
1138
-
1139
- const category = payload?.category || existingPublish?.category;
1140
- const tags = payload?.tags || existingPublish?.tags;
1141
- const proxy = payload?.proxy || existingPublish?.proxy;
1142
- const title = payload?.title || existingPublish?.title;
1143
- const withOptimizationValues = {
1144
- ...existingPublish,
1145
- category,
1146
- tags,
1147
- proxy,
1148
- title,
1149
- textureDownscaling: {
1150
- ...(existingPublish?.textureDownscaling || {}),
1151
- ...(payload?.textureDownscaling || {})
1152
- },
1153
- meshSimplification: {
1154
- ...(existingPublish?.meshSimplification || {}),
1155
- ...(payload?.meshSimplification || {}),
1156
- totalTriangles: totalTriangles,
1157
- estimatedTriangles: estimatedTriangles,
1158
- userTargetTriangles: incomingTargetTriangles,
1159
- targetTriangles: Math.round(totalTriangles * (estimatedTriangles / 100))
1160
- }
1161
- };
1162
- newMetaDataEntry('publish', withOptimizationValues);
1163
- };
1164
- export const updateLighting = inboundData => {
1165
- const {
1166
- payload
1167
- } = inboundData;
1168
- const {
1169
- id,
1170
- transforms,
1171
- target,
1172
- enable,
1173
- diffuse,
1174
- specular,
1175
- radius,
1176
- intensity,
1177
- distance,
1178
- rotation
1179
- } = payload;
1180
- const light = scene.getLightByName(id);
1181
- if (!_.isEmpty(transforms)) {
1182
- const {
1183
- tx,
1184
- ty,
1185
- tz,
1186
- dirX,
1187
- dirY,
1188
- dirZ
1189
- } = transforms;
1190
- const isPosition = tx !== undefined && ty !== undefined && tz !== undefined;
1191
- const isDirection = dirX !== undefined && dirY !== undefined && dirZ !== undefined;
1192
- if (isPosition) light.position = newVector(tx, ty, tz);
1193
- if (isDirection) light.direction = newVector(dirX, dirY, dirZ);
1194
- }
1195
- if (target) {
1196
- light.setDirectionToTarget(target);
1197
- }
1198
- if (enable !== undefined) {
1199
- light.setEnabled(enable);
1200
- }
1201
- if (radius !== undefined) {
1202
- light.radius = radius;
1203
- }
1204
- if (diffuse) {
1205
- const {
1206
- r,
1207
- g,
1208
- b
1209
- } = diffuse;
1210
- light.diffuse = newColor(r, g, b);
1211
- }
1212
- if (specular) {
1213
- const {
1214
- r,
1215
- g,
1216
- b
1217
- } = specular;
1218
- light.specular = newColor(r, g, b);
1219
- }
1220
- if (intensity !== undefined) {
1221
- light.intensity = intensity;
1222
- }
1223
- if (distance !== undefined) {
1224
- const rotation = light?.rotation || 0;
1225
- const angleRad = rotation * Math.PI / 180;
1226
- light.position = newVector(distance * Math.cos(angleRad), distance * Math.tanh(angleRad), distance * Math.sin(angleRad));
1227
- light.setDirectionToTarget(newVector(0, 0, 0));
1228
- light.distance = distance;
1229
- }
1230
- if (rotation !== undefined) {
1231
- const {
1232
- position
1233
- } = light;
1234
- const {
1235
- x,
1236
- y,
1237
- z
1238
- } = position;
1239
- const angleRad = rotation * Math.PI / 180;
1240
- let distance = light?.distance || Math.sqrt(Math.pow(Math.abs(x), 2) + Math.pow(Math.abs(y), 2) + Math.pow(Math.abs(z), 2));
1241
- distance = distance > 200 ? 200 : distance;
1242
- light.position = newVector(distance * Math.cos(angleRad), distance * Math.tanh(angleRad), distance * Math.sin(angleRad));
1243
- light.setDirectionToTarget(newVector(0, 0, 0));
1244
- light.rotation = rotation;
1245
- }
1246
- newMetaDataEntry('lights', buildLightsArray());
1247
- };