@archvisioninc/canvas 3.3.8 → 3.3.9
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/dist/Canvas.js +67 -0
- package/dist/actions/index.js +1 -0
- package/dist/actions/shortcutActions.js +313 -0
- package/dist/constants/constants.js +80 -0
- package/dist/constants/index.js +1 -0
- package/dist/enums/aspectRatios.js +17 -0
- package/dist/enums/dimensions.js +20 -0
- package/dist/enums/downscaling.js +16 -0
- package/dist/enums/exclusions.js +4 -0
- package/dist/enums/formats.js +1 -0
- package/dist/enums/index.js +8 -0
- package/dist/enums/orthoOptions.js +28 -0
- package/dist/enums/scaleUnits.js +25 -0
- package/dist/enums/shortcuts.js +89 -0
- package/dist/helpers/cameraHelpers.js +86 -0
- package/dist/helpers/canvasAddHelpers.js +161 -0
- package/dist/helpers/canvasCommunicationHelpers.js +52 -0
- package/dist/helpers/canvasRemoveHelpers.js +230 -0
- package/dist/helpers/canvasUpdateHelpers.js +1365 -0
- package/dist/helpers/gizmoHelpers.js +156 -0
- package/dist/helpers/guiHelpers.js +46 -0
- package/dist/helpers/index.js +16 -0
- package/dist/helpers/initHelpers.js +513 -0
- package/dist/helpers/lightHelpers.js +17 -0
- package/dist/helpers/loadHelpers.js +269 -0
- package/dist/helpers/materialHelpers.js +34 -0
- package/dist/helpers/meshHelpers.js +169 -0
- package/dist/helpers/rayHelpers.js +11 -0
- package/dist/helpers/shortcutHelpers.js +35 -0
- package/dist/helpers/utilityHelpers.js +710 -0
- package/dist/helpers/viewportHelpers.js +364 -0
- package/dist/styles.js +25 -0
- package/package.json +2 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as BABYLON from 'babylonjs';
|
|
2
|
+
import { newVector } from './utilityHelpers';
|
|
3
|
+
import { scene, engine, canvas, selectedMeshes, getParamOfSelectedMeshes, getUserMeshes, defaultCameraPosition, getBoundingMeshData } from '../helpers';
|
|
4
|
+
import { CAMERAS, MESH_PARAMS } from '../constants';
|
|
5
|
+
import { focusCamera, toggleTurntable } from '../actions';
|
|
6
|
+
import { orthoOptions, ratios } from '../enums';
|
|
7
|
+
import _ from 'lodash';
|
|
8
|
+
export const newCamera = (name, location, type, meta = {}) => {
|
|
9
|
+
const defaultName = `camera_${getSceneCameras().length + 1}`;
|
|
10
|
+
if (type === CAMERAS.ArcRotateCamera) {
|
|
11
|
+
return new BABYLON.ArcRotateCamera(name || defaultName, meta.alpha || 0, meta.beta || 0, meta.radius || 0, newVector(location.x, location.y, location.z), scene);
|
|
12
|
+
}
|
|
13
|
+
if (CAMERAS[type] && typeof BABYLON[type] === 'function') {
|
|
14
|
+
return new BABYLON[type](name || defaultName, newVector(location.x, location.y, location.z), scene);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const prepareCamera = () => {
|
|
18
|
+
const camera = scene.activeCamera;
|
|
19
|
+
const canvasDimensions = engine?.getRenderingCanvasClientRect?.();
|
|
20
|
+
const width = canvasDimensions?.width || ratios.square.value;
|
|
21
|
+
const height = canvasDimensions?.height || ratios.square.value;
|
|
22
|
+
const aspect = height / width;
|
|
23
|
+
const userMeshes = getUserMeshes();
|
|
24
|
+
camera.orthoLeft = -camera.radius;
|
|
25
|
+
camera.orthoTop = camera.radius * aspect;
|
|
26
|
+
camera.orthoRight = camera.radius;
|
|
27
|
+
camera.orthoBottom = -camera.radius * aspect;
|
|
28
|
+
camera.lowerRadiusLimit = 1;
|
|
29
|
+
camera.upperRadiusLimit = 5000;
|
|
30
|
+
camera.minZ = 0.1;
|
|
31
|
+
camera.setPosition?.(defaultCameraPosition());
|
|
32
|
+
camera.setTarget(BABYLON.Vector3.Zero());
|
|
33
|
+
camera.attachControl(canvas, true);
|
|
34
|
+
_.isEmpty(userMeshes) ? toggleTurntable(true) : focusCamera();
|
|
35
|
+
};
|
|
36
|
+
export const prepareMaterialCamera = () => {
|
|
37
|
+
const camera = scene.activeCamera;
|
|
38
|
+
const sphere = scene.getMeshById('node0');
|
|
39
|
+
camera.position = defaultCameraPosition();
|
|
40
|
+
if (sphere) {
|
|
41
|
+
const primarySurfaces = [sphere];
|
|
42
|
+
const meshCenter = getBoundingMeshData(primarySurfaces).center;
|
|
43
|
+
camera.setTarget(meshCenter);
|
|
44
|
+
camera.alpha = 1.57;
|
|
45
|
+
camera.beta = 1.65;
|
|
46
|
+
camera.lowerRadiusLimit = 0.3239;
|
|
47
|
+
camera.upperRadiusLimit = 5000;
|
|
48
|
+
camera.minZ = 0.1;
|
|
49
|
+
camera.maxZ = 10000;
|
|
50
|
+
camera.radius = 4;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
export const toggleCameraMode = (orthoCamera, requestedMode) => {
|
|
54
|
+
const camera = scene.activeCamera;
|
|
55
|
+
const babylonOrthographic = BABYLON.Camera.ORTHOGRAPHIC_CAMERA;
|
|
56
|
+
const ratio = canvas.height / canvas.width;
|
|
57
|
+
if (!camera) return;
|
|
58
|
+
camera.mode = requestedMode;
|
|
59
|
+
if (camera.mode === babylonOrthographic) {
|
|
60
|
+
if (!_.isEmpty(selectedMeshes)) {
|
|
61
|
+
camera.target = getParamOfSelectedMeshes(MESH_PARAMS.center);
|
|
62
|
+
}
|
|
63
|
+
camera.alpha = orthoOptions[orthoCamera].alpha;
|
|
64
|
+
camera.beta = orthoOptions[orthoCamera].beta;
|
|
65
|
+
|
|
66
|
+
// Zooming
|
|
67
|
+
camera.lowerRadiusLimit = 5;
|
|
68
|
+
camera.upperRadiusLimit = 5000;
|
|
69
|
+
camera.minZ = 0.1;
|
|
70
|
+
camera.maxZ = 10000;
|
|
71
|
+
camera.wheelDeltaPercentage = 0.01;
|
|
72
|
+
let oldRadius = camera.radius;
|
|
73
|
+
scene.onBeforeRenderObservable.add(() => {
|
|
74
|
+
if (oldRadius !== camera.radius) {
|
|
75
|
+
const radiusChangeRatio = camera.radius / oldRadius;
|
|
76
|
+
camera.orthoLeft *= radiusChangeRatio;
|
|
77
|
+
camera.orthoRight *= radiusChangeRatio;
|
|
78
|
+
oldRadius = camera.radius;
|
|
79
|
+
camera.orthoTop = camera.orthoRight * ratio;
|
|
80
|
+
camera.orthoBottom = camera.orthoLeft * ratio;
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
focusCamera?.();
|
|
85
|
+
};
|
|
86
|
+
export const getSceneCameras = () => scene.cameras;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { scene } from './initHelpers';
|
|
2
|
+
import { newMetaDataEntry, newTexture } from './utilityHelpers';
|
|
3
|
+
import { selectedMeshes } from './viewportHelpers';
|
|
4
|
+
import { singleMeshTNode, toDegrees } from '../helpers';
|
|
5
|
+
import { MESSAGE_TYPES } from '../constants';
|
|
6
|
+
import { reactProps as props } from '../Canvas';
|
|
7
|
+
import _ from 'lodash';
|
|
8
|
+
export const addToMaterial = inboundData => {
|
|
9
|
+
const {
|
|
10
|
+
payload
|
|
11
|
+
} = inboundData;
|
|
12
|
+
const {
|
|
13
|
+
id,
|
|
14
|
+
albedoTexture,
|
|
15
|
+
metallicTexture,
|
|
16
|
+
microSurfaceTexture,
|
|
17
|
+
emissiveTexture,
|
|
18
|
+
bumpTexture
|
|
19
|
+
} = payload;
|
|
20
|
+
const material = scene.getMaterialByName(id, true);
|
|
21
|
+
if (material) {
|
|
22
|
+
// Basic attribute textures.
|
|
23
|
+
if (_.isString(albedoTexture)) material.albedoTexture = newTexture(albedoTexture);
|
|
24
|
+
if (_.isString(metallicTexture)) material.metallicTexture = newTexture(metallicTexture);
|
|
25
|
+
if (_.isString(microSurfaceTexture)) material.microSurfaceTexture = newTexture(microSurfaceTexture);
|
|
26
|
+
if (_.isString(emissiveTexture)) material.emissiveTexture = newTexture(emissiveTexture);
|
|
27
|
+
if (_.isString(bumpTexture)) material.bumpTexture = newTexture(bumpTexture);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export const addToMesh = inboundData => {
|
|
31
|
+
const {
|
|
32
|
+
payload
|
|
33
|
+
} = inboundData;
|
|
34
|
+
const {
|
|
35
|
+
id
|
|
36
|
+
} = payload;
|
|
37
|
+
if (_.isEmpty(selectedMeshes) || selectedMeshes.length > 1) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const mesh = selectedMeshes[0];
|
|
41
|
+
if (mesh) {
|
|
42
|
+
// Custom user mesh positions.
|
|
43
|
+
const duplicate = scene.metadata?.userMeshPositions?.find(meshPos => meshPos.meshId === mesh.id && meshPos.positionId === id);
|
|
44
|
+
if (_.isString(id) && !duplicate) {
|
|
45
|
+
const {
|
|
46
|
+
position,
|
|
47
|
+
rotation,
|
|
48
|
+
scaling
|
|
49
|
+
} = singleMeshTNode;
|
|
50
|
+
const [tx, ty, tz] = position.asArray();
|
|
51
|
+
const [rx, ry, rz] = rotation.asArray().map(val => toDegrees(val * -1));
|
|
52
|
+
const [sx, sy, sz] = scaling.asArray();
|
|
53
|
+
const positionObj = {
|
|
54
|
+
meshId: mesh.id,
|
|
55
|
+
positionId: id,
|
|
56
|
+
tx,
|
|
57
|
+
ty,
|
|
58
|
+
tz,
|
|
59
|
+
rx,
|
|
60
|
+
ry,
|
|
61
|
+
rz,
|
|
62
|
+
sx,
|
|
63
|
+
sy,
|
|
64
|
+
sz
|
|
65
|
+
};
|
|
66
|
+
const updatedPositions = [...(scene.metadata?.userMeshPositions || {}), positionObj];
|
|
67
|
+
const selectedUserMeshPositions = scene.metadata.selectedUserMeshPositions;
|
|
68
|
+
const filteredPositions = selectedUserMeshPositions.filter(pos => pos.meshId !== mesh.id);
|
|
69
|
+
filteredPositions.push(positionObj);
|
|
70
|
+
newMetaDataEntry('userMeshPositions', updatedPositions.filter(item => item));
|
|
71
|
+
newMetaDataEntry('selectedUserMeshPositions', filteredPositions);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
export const addToCamera = inboundData => {
|
|
76
|
+
const {
|
|
77
|
+
payload
|
|
78
|
+
} = inboundData;
|
|
79
|
+
const {
|
|
80
|
+
id
|
|
81
|
+
} = payload;
|
|
82
|
+
const camera = scene.activeCamera;
|
|
83
|
+
if (camera) {
|
|
84
|
+
// Custom user camera views.
|
|
85
|
+
const duplicate = scene.metadata?.userCameraViews.find(cameraPos => cameraPos.id === id);
|
|
86
|
+
if (_.isString(id) && !duplicate) {
|
|
87
|
+
const {
|
|
88
|
+
position,
|
|
89
|
+
rotation,
|
|
90
|
+
target
|
|
91
|
+
} = scene.activeCamera;
|
|
92
|
+
const [tx, ty, tz] = [position.x, position.y, position.z];
|
|
93
|
+
const [rx, ry, rz] = [rotation.x, rotation.y, rotation.z];
|
|
94
|
+
const [tarX, tarY, tarZ] = [target.x, target.y, target.z];
|
|
95
|
+
const updatedPositions = [...(scene.metadata?.userCameraViews || []), {
|
|
96
|
+
id,
|
|
97
|
+
tx,
|
|
98
|
+
ty,
|
|
99
|
+
tz,
|
|
100
|
+
rx,
|
|
101
|
+
ry,
|
|
102
|
+
rz,
|
|
103
|
+
tarX,
|
|
104
|
+
tarY,
|
|
105
|
+
tarZ
|
|
106
|
+
}];
|
|
107
|
+
newMetaDataEntry('userCameraViews', updatedPositions.filter(item => item));
|
|
108
|
+
newMetaDataEntry('selectedUserCameraView', {
|
|
109
|
+
id,
|
|
110
|
+
tx,
|
|
111
|
+
ty,
|
|
112
|
+
tz,
|
|
113
|
+
rx,
|
|
114
|
+
ry,
|
|
115
|
+
rz,
|
|
116
|
+
tarX,
|
|
117
|
+
tarY,
|
|
118
|
+
tarZ
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
export const addToEnvironment = inboundData => {
|
|
124
|
+
const {
|
|
125
|
+
payload
|
|
126
|
+
} = inboundData;
|
|
127
|
+
const {
|
|
128
|
+
id,
|
|
129
|
+
url
|
|
130
|
+
} = payload;
|
|
131
|
+
const skyBox = scene.getMaterialById('skyBox', true);
|
|
132
|
+
if (skyBox) {
|
|
133
|
+
// Add custom user environment.
|
|
134
|
+
const duplicate = scene.metadata?.userEnvironments.find(env => env.id === id);
|
|
135
|
+
const isNotDefault = url !== scene.metadata.defaultEnvironment;
|
|
136
|
+
const isValid = isNotDefault && _.isString(id) && _.isString(url) && !duplicate;
|
|
137
|
+
if (isValid) {
|
|
138
|
+
const message = 'Adding custom environment...';
|
|
139
|
+
const clearExisting = true;
|
|
140
|
+
const isUserFile = true;
|
|
141
|
+
const config = {
|
|
142
|
+
type: MESSAGE_TYPES.loading,
|
|
143
|
+
showModal: true,
|
|
144
|
+
closeButton: false
|
|
145
|
+
};
|
|
146
|
+
props.addNotification?.([{
|
|
147
|
+
message,
|
|
148
|
+
config
|
|
149
|
+
}], clearExisting);
|
|
150
|
+
newTexture(url, isUserFile);
|
|
151
|
+
const updatedEnvironments = [...(scene.metadata?.userEnvironments || {}), {
|
|
152
|
+
id,
|
|
153
|
+
url
|
|
154
|
+
}];
|
|
155
|
+
newMetaDataEntry('userEnvironments', updatedEnvironments.filter(item => item));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
export const addToViewport = () => {
|
|
160
|
+
// Add functions here...
|
|
161
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UPDATABLE_ITEMS } from '../constants';
|
|
2
|
+
import { updateMaterial, addToMaterial, removeFromMaterial, updateMesh, addToMesh, removeFromMesh, updateCamera, addToCamera, removeFromCamera, updateEnvironment, addToEnvironment, removeFromEnvironment, updateViewport, addToViewport, removeFromViewport, serializeScene, updatePublish, newMetaDataEntry, buildMeshIdArray, updateLighting } from '../helpers';
|
|
3
|
+
import { reactProps as props } from '../Canvas';
|
|
4
|
+
export const updateItem = inboundData => {
|
|
5
|
+
const {
|
|
6
|
+
type,
|
|
7
|
+
method
|
|
8
|
+
} = inboundData;
|
|
9
|
+
const types = Object.keys(UPDATABLE_ITEMS);
|
|
10
|
+
const isValidType = types.includes(type);
|
|
11
|
+
const hidden = true;
|
|
12
|
+
if (isValidType) {
|
|
13
|
+
switch (type) {
|
|
14
|
+
case UPDATABLE_ITEMS.material:
|
|
15
|
+
if (method === 'update') updateMaterial(inboundData);
|
|
16
|
+
if (method === 'add') addToMaterial(inboundData);
|
|
17
|
+
if (method === 'remove') removeFromMaterial(inboundData);
|
|
18
|
+
break;
|
|
19
|
+
case UPDATABLE_ITEMS.mesh:
|
|
20
|
+
if (method === 'update') updateMesh(inboundData);
|
|
21
|
+
if (method === 'add') addToMesh(inboundData);
|
|
22
|
+
if (method === 'remove') removeFromMesh(inboundData);
|
|
23
|
+
break;
|
|
24
|
+
case UPDATABLE_ITEMS.camera:
|
|
25
|
+
if (method === 'update') updateCamera(inboundData);
|
|
26
|
+
if (method === 'add') addToCamera(inboundData);
|
|
27
|
+
if (method === 'remove') removeFromCamera(inboundData);
|
|
28
|
+
break;
|
|
29
|
+
case UPDATABLE_ITEMS.environment:
|
|
30
|
+
if (method === 'update') updateEnvironment(inboundData);
|
|
31
|
+
if (method === 'add') addToEnvironment(inboundData);
|
|
32
|
+
if (method === 'remove') removeFromEnvironment(inboundData);
|
|
33
|
+
break;
|
|
34
|
+
case UPDATABLE_ITEMS.viewport:
|
|
35
|
+
if (method === 'update') updateViewport(inboundData);
|
|
36
|
+
if (method === 'add') addToViewport(inboundData);
|
|
37
|
+
if (method === 'remove') removeFromViewport(inboundData);
|
|
38
|
+
break;
|
|
39
|
+
case UPDATABLE_ITEMS.publish:
|
|
40
|
+
if (method === 'update') updatePublish(inboundData);
|
|
41
|
+
break;
|
|
42
|
+
case UPDATABLE_ITEMS.lighting:
|
|
43
|
+
if (method === 'update') updateLighting(inboundData);
|
|
44
|
+
break;
|
|
45
|
+
default:
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
newMetaDataEntry('hiddenMeshes', buildMeshIdArray(hidden));
|
|
49
|
+
props.setSerializedData?.(serializeScene());
|
|
50
|
+
props.clearUpdateData?.();
|
|
51
|
+
}
|
|
52
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import { scene, newMetaDataEntry, selectedMeshes, updateCamera, updateEnvironment, buildMaterialsArray, buildSelectedMaterialArray, serializeScene } from '../helpers';
|
|
2
|
+
import { reactProps as props } from '../Canvas';
|
|
3
|
+
import { deleteSelected } from '../actions';
|
|
4
|
+
import { TRANSPARENCY_MODES } from '../constants';
|
|
5
|
+
import * as BABYLON from 'babylonjs';
|
|
6
|
+
import _ from 'lodash';
|
|
7
|
+
const removeChannelFromTexture = (image, channel) => {
|
|
8
|
+
const imageHeight = image?.naturalHeight ?? 0;
|
|
9
|
+
const imageWidth = image?.naturalWidth ?? 0;
|
|
10
|
+
let imageData;
|
|
11
|
+
const maxHeight = Math.max(...[imageHeight, 1024]);
|
|
12
|
+
const maxWidth = Math.max(...[imageWidth, 1024]);
|
|
13
|
+
const canvas = document.createElement('canvas');
|
|
14
|
+
const ctx = canvas.getContext('2d');
|
|
15
|
+
canvas.width = maxWidth;
|
|
16
|
+
canvas.height = maxHeight;
|
|
17
|
+
if (image) {
|
|
18
|
+
ctx.drawImage(image, 0, 0, maxWidth, maxHeight);
|
|
19
|
+
imageData = ctx.getImageData(0, 0, maxWidth, maxHeight).data;
|
|
20
|
+
}
|
|
21
|
+
const combinedImageData = ctx.createImageData(maxWidth, maxHeight);
|
|
22
|
+
const combinedData = combinedImageData.data;
|
|
23
|
+
for (let i = 0; i < combinedData.length; i += 4) {
|
|
24
|
+
combinedData[i] = channel === 'R' ? 0 : imageData[i];
|
|
25
|
+
combinedData[i + 1] = channel === 'G' ? 0 : imageData[i + 1];
|
|
26
|
+
combinedData[i + 2] = channel === 'B' ? 0 : imageData[i + 2];
|
|
27
|
+
combinedData[i + 3] = channel === 'A' ? 255 : imageData[i + 3];
|
|
28
|
+
}
|
|
29
|
+
ctx.putImageData(combinedImageData, 0, 0);
|
|
30
|
+
return canvas.toDataURL('image/png');
|
|
31
|
+
};
|
|
32
|
+
const textureToImage = texture => {
|
|
33
|
+
return new Promise(resolve => {
|
|
34
|
+
if (!texture.readPixels()) {
|
|
35
|
+
resolve(null);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
texture.readPixels().then(pixels => {
|
|
39
|
+
const canvas = document.createElement('canvas');
|
|
40
|
+
const ctx = canvas.getContext('2d');
|
|
41
|
+
const {
|
|
42
|
+
width,
|
|
43
|
+
height
|
|
44
|
+
} = texture.getSize();
|
|
45
|
+
canvas.width = width;
|
|
46
|
+
canvas.height = height;
|
|
47
|
+
const img = new Image();
|
|
48
|
+
const imageData = ctx.createImageData(width, height);
|
|
49
|
+
imageData.data.set(new Uint8ClampedArray(pixels));
|
|
50
|
+
ctx.putImageData(imageData, 0, 0);
|
|
51
|
+
img.onload = () => {
|
|
52
|
+
resolve(img);
|
|
53
|
+
};
|
|
54
|
+
img.onerror = () => {
|
|
55
|
+
resolve(null);
|
|
56
|
+
};
|
|
57
|
+
img.src = canvas.toDataURL();
|
|
58
|
+
}).catch(() => {
|
|
59
|
+
resolve(null);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
export const removeFromMaterial = inboundData => {
|
|
64
|
+
const {
|
|
65
|
+
payload
|
|
66
|
+
} = inboundData;
|
|
67
|
+
const {
|
|
68
|
+
id,
|
|
69
|
+
removeAlbedoTexture,
|
|
70
|
+
removeMetallicTexture,
|
|
71
|
+
removeMicroSurfaceTexture,
|
|
72
|
+
removeEmissiveTexture,
|
|
73
|
+
removeBumpTexture,
|
|
74
|
+
removeOpacityTexture,
|
|
75
|
+
removeRoughnessTexture,
|
|
76
|
+
removeAmbientTexture
|
|
77
|
+
} = payload;
|
|
78
|
+
const material = scene.getMaterialByName(id, true);
|
|
79
|
+
if (material) {
|
|
80
|
+
// Basic attribute textures.
|
|
81
|
+
if (removeAlbedoTexture) {
|
|
82
|
+
const isStencil = material.transparencyType === TRANSPARENCY_MODES.stencil;
|
|
83
|
+
if (isStencil) {
|
|
84
|
+
material.albedoTexture.hasAlpha = false;
|
|
85
|
+
material.albedoTexture.useAlphaFromAlbedoTexture = false;
|
|
86
|
+
material.transparencyMode = BABYLON.PBRMaterial.PBRMATERIAL_ALPHABLEND;
|
|
87
|
+
material.transparencyType = TRANSPARENCY_MODES.simple;
|
|
88
|
+
}
|
|
89
|
+
material.albedoTexture?.dispose();
|
|
90
|
+
material.albedoTexture = null;
|
|
91
|
+
}
|
|
92
|
+
if (removeMetallicTexture) {
|
|
93
|
+
if (material.metallicTexture) {
|
|
94
|
+
textureToImage(material.metallicTexture).then(data => {
|
|
95
|
+
const updatedTexture = removeChannelFromTexture(data, 'B');
|
|
96
|
+
material.metallicTexture.updateURL(updatedTexture);
|
|
97
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
98
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
99
|
+
props.clearNotifications?.();
|
|
100
|
+
props.setSerializedData?.(serializeScene());
|
|
101
|
+
}).catch(() => {
|
|
102
|
+
console.log('Failed to remove metallic texture');
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (removeMicroSurfaceTexture) {
|
|
107
|
+
material.microSurfaceTexture?.dispose();
|
|
108
|
+
material.microSurfaceTexture = null;
|
|
109
|
+
}
|
|
110
|
+
if (removeEmissiveTexture) {
|
|
111
|
+
material.emissiveTexture?.dispose();
|
|
112
|
+
material.emissiveTexture = null;
|
|
113
|
+
}
|
|
114
|
+
if (removeBumpTexture) {
|
|
115
|
+
material.bumpTexture?.dispose();
|
|
116
|
+
material.bumpTexture = null;
|
|
117
|
+
}
|
|
118
|
+
if (removeOpacityTexture) {
|
|
119
|
+
material.opacityTexture?.dispose();
|
|
120
|
+
material.opacityTexture = null;
|
|
121
|
+
}
|
|
122
|
+
if (removeAmbientTexture) {
|
|
123
|
+
material.ambientTexture?.dispose();
|
|
124
|
+
material.ambientTexture = null;
|
|
125
|
+
}
|
|
126
|
+
if (removeRoughnessTexture) {
|
|
127
|
+
if (material.metallicTexture) {
|
|
128
|
+
textureToImage(material.metallicTexture).then(data => {
|
|
129
|
+
const updatedTexture = removeChannelFromTexture(data, 'G');
|
|
130
|
+
material.metallicTexture.updateURL(updatedTexture);
|
|
131
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
132
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
133
|
+
props.clearNotifications?.();
|
|
134
|
+
props.setSerializedData?.(serializeScene());
|
|
135
|
+
}).catch(() => {
|
|
136
|
+
console.log('Failed to remove roughness texture');
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
newMetaDataEntry('materials', buildMaterialsArray());
|
|
141
|
+
newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
export const removeFromMesh = inboundData => {
|
|
145
|
+
const {
|
|
146
|
+
payload
|
|
147
|
+
} = inboundData;
|
|
148
|
+
const {
|
|
149
|
+
id
|
|
150
|
+
} = payload;
|
|
151
|
+
if (_.isString(id)) {
|
|
152
|
+
if (_.isEmpty(selectedMeshes) || selectedMeshes.length > 1) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const selectedMesh = selectedMeshes[0];
|
|
156
|
+
|
|
157
|
+
// Remove custom user mesh positions.
|
|
158
|
+
const userMeshPositions = scene.metadata?.userMeshPositions?.filter(mesh => mesh.meshId !== selectedMesh.id || mesh.positionId !== id) || [];
|
|
159
|
+
const filteredSelectedPositions = scene.metadata.selectedUserMeshPositions.filter(pos => pos.meshId !== selectedMesh.id || pos.positionId !== id);
|
|
160
|
+
const defaultPosition = userMeshPositions.find(pos => pos.meshId === selectedMesh.id && pos.positionId === 'Default');
|
|
161
|
+
filteredSelectedPositions.push(defaultPosition);
|
|
162
|
+
newMetaDataEntry('userMeshPositions', userMeshPositions);
|
|
163
|
+
newMetaDataEntry('selectedUserMeshPositions', filteredSelectedPositions);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
export const removeFromCamera = inboundData => {
|
|
167
|
+
const {
|
|
168
|
+
payload
|
|
169
|
+
} = inboundData;
|
|
170
|
+
const {
|
|
171
|
+
id
|
|
172
|
+
} = payload;
|
|
173
|
+
if (_.isString(id)) {
|
|
174
|
+
// Custom user camera views.
|
|
175
|
+
const filteredPositions = scene.metadata?.userCameraViews.filter(cameraPos => cameraPos.id !== id) || [];
|
|
176
|
+
const inboundData = {
|
|
177
|
+
payload: {
|
|
178
|
+
resetCamera: true
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
newMetaDataEntry('userCameraViews', filteredPositions);
|
|
182
|
+
updateCamera(inboundData);
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
export const removeFromEnvironment = inboundData => {
|
|
186
|
+
const {
|
|
187
|
+
payload
|
|
188
|
+
} = inboundData;
|
|
189
|
+
const {
|
|
190
|
+
id
|
|
191
|
+
} = payload;
|
|
192
|
+
const userEnv = scene.metadata?.userEnvironments.find(env => env.id === id);
|
|
193
|
+
|
|
194
|
+
// remove custom user environment.
|
|
195
|
+
if (_.isString(id) && _.isString(userEnv?.url)) {
|
|
196
|
+
const filteredEnvs = scene.metadata?.userEnvironments.filter(env => env.id != id) || [];
|
|
197
|
+
const inboundData = {
|
|
198
|
+
payload: {
|
|
199
|
+
url: scene.metadata.defaultEnvironment,
|
|
200
|
+
transforms: {
|
|
201
|
+
rotation: {
|
|
202
|
+
ry: scene.metadata.environmentRotation
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
newMetaDataEntry('userEnvironments', filteredEnvs);
|
|
208
|
+
updateEnvironment(inboundData);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
export const removeFromViewport = inboundData => {
|
|
212
|
+
const {
|
|
213
|
+
payload
|
|
214
|
+
} = inboundData;
|
|
215
|
+
const {
|
|
216
|
+
deleteSelectedMesh
|
|
217
|
+
} = payload;
|
|
218
|
+
const hasSelection = selectedMeshes.length > 0;
|
|
219
|
+
|
|
220
|
+
// Delete selected mesh.
|
|
221
|
+
if (deleteSelectedMesh !== undefined && hasSelection) {
|
|
222
|
+
const multiSelection = selectedMeshes.length > 1;
|
|
223
|
+
const confirmConfig = {
|
|
224
|
+
message: `Are you sure you want to delete ${multiSelection ? 'these meshes' : 'this mesh'}?`,
|
|
225
|
+
onConfirm: () => deleteSelected(),
|
|
226
|
+
onClose: () => props.setConfirmMessage?.(null)
|
|
227
|
+
};
|
|
228
|
+
props.setConfirmMessage?.(confirmConfig);
|
|
229
|
+
}
|
|
230
|
+
};
|