@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,364 +0,0 @@
1
- import * as BABYLON from 'babylonjs';
2
- import * as BABYLONGUI from 'babylonjs-gui';
3
- import { scene, highlightManager, hoverHighlightManager, theme, $selectedTheme, newColor, newVector, groundOptions, guiTexture, attachToSelectMeshesNode, getMeshesInCameraView, getMeshVertices, getWorldPositionsByMesh, canvas, WorldToGUIPos, serializeScene, toRadians, newMetaDataEntry, buildMeshIdArray, gizmoManager, getUserMeshes, getUserMaterials, buildSelectedMaterialArray } from '../helpers';
4
- import { GUI, MESH_COUNT_THRESHOLD, AXIS_COLORS } from '../constants';
5
- import { resetManagerGizmos } from '../actions';
6
- import { reactProps as props } from '../Canvas';
7
- import { extent } from 'd3-array';
8
- import _ from 'lodash';
9
- const highlightColor = () => newColor(theme.colors[$selectedTheme].accent);
10
- const hoverColor = () => newColor(theme.colors[$selectedTheme].white);
11
- export let selectedMeshes = [];
12
- export let selectedMaterials = [];
13
- export let hoverMesh;
14
- let hadSelection = false;
15
- let tempMesh;
16
- let dragStarted = false;
17
- let hasDragged = false;
18
- let x1;
19
- let y1;
20
- let x2;
21
- let y2;
22
- const isInstanceMesh = mesh => mesh instanceof BABYLON.InstancedMesh;
23
- const isTargetIn = (startPosition, endPosition, target) => {
24
- const minX = Math.min(startPosition.x, endPosition.x);
25
- const minY = Math.min(startPosition.y, endPosition.y);
26
- const maxX = Math.max(startPosition.x, endPosition.x);
27
- const maxY = Math.max(startPosition.y, endPosition.y);
28
- return minX < target.maxX && target.minX < maxX && minY < target.maxY && target.minY < maxY;
29
- };
30
- const getClientRectFromMesh = mesh => {
31
- const meshVectors = mesh?.getBoundingInfo().boundingBox.vectors;
32
- const worldMatrix = mesh.getWorldMatrix();
33
- const transformMatrix = scene.getTransformMatrix();
34
- const viewport = scene.activeCamera.viewport;
35
- const coordinates = meshVectors.map(v => {
36
- const proj = BABYLON.Vector3.Project(v, worldMatrix, transformMatrix, viewport);
37
- proj.x = proj.x * canvas.clientWidth;
38
- proj.y = proj.y * canvas.clientHeight;
39
- return proj;
40
- });
41
- const [minX, maxX] = extent(coordinates, c => c.x);
42
- const [minY, maxY] = extent(coordinates, c => c.y);
43
- const rect = {
44
- minX,
45
- minY,
46
- maxX,
47
- maxY
48
- };
49
- return rect;
50
- };
51
- export const addNewMesh = selectedMesh => {
52
- const hasMaterial = !_.isEmpty(selectedMesh.material);
53
- const selectedMaterial = selectedMesh.material;
54
- const inSelectedMaterials = selectedMaterials.includes(selectedMaterial);
55
- if (isInstanceMesh(selectedMesh)) {
56
- const message = 'Instance mesh selection unavailable. Please use the Materials panel.';
57
- const config = {
58
- type: 'warning'
59
- };
60
- const clearExisting = true;
61
- props.addNotification([{
62
- message,
63
- config
64
- }], clearExisting);
65
- return;
66
- }
67
- if (!selectedMeshes.includes(selectedMesh)) {
68
- selectedMeshes.push(selectedMesh);
69
- }
70
- if (hasMaterial && !inSelectedMaterials) {
71
- selectedMaterials.push(selectedMesh.material);
72
- }
73
- attachToSelectMeshesNode();
74
- };
75
- const removeSelectedMesh = selectedMesh => {
76
- if (tempMesh) {
77
- const tempHasMaterial = !_.isEmpty(tempMesh.material);
78
- const includesTempMaterial = selectedMaterials.includes(tempMesh.material);
79
- selectedMeshes.push(tempMesh);
80
- if (tempHasMaterial && !includesTempMaterial) selectedMaterials.push(tempMesh.material);
81
- tempMesh = null;
82
- }
83
- const withoutSelected = selectedMeshes.filter(mesh => !_.isEqual(mesh, selectedMesh) && mesh.subMeshes);
84
- selectedMeshes = withoutSelected;
85
- selectedMaterials = [];
86
- withoutSelected.forEach(mesh => {
87
- const hasMaterial = !_.isEmpty(mesh.material);
88
- const includesMaterial = selectedMaterials.includes(mesh.material);
89
- if (hasMaterial && !includesMaterial) selectedMaterials.push(mesh.material);
90
- });
91
- attachToSelectMeshesNode();
92
- };
93
- const addHoverMesh = pickedMesh => {
94
- if (props.integration?.meshHighlighting === false) return;
95
- if (props.previewMode) return;
96
- const isSelected = selectedMeshes.includes(pickedMesh);
97
- removeHoverMesh();
98
- if (isSelected) {
99
- tempMesh = pickedMesh;
100
- highlightManager.removeMesh(pickedMesh);
101
- hoverHighlightManager.addMesh(pickedMesh, hoverColor());
102
- return;
103
- }
104
- if (hoverMesh) removeHoverMesh();
105
- if (isInstanceMesh(pickedMesh)) return;
106
- hoverMesh = pickedMesh;
107
- hoverHighlightManager.addMesh(hoverMesh, hoverColor());
108
- };
109
- const removeHoverMesh = () => {
110
- if (props.integration?.meshHighlighting === false) return;
111
- if (props.previewMode) return;
112
- hoverHighlightManager.removeAllMeshes();
113
- if (tempMesh) {
114
- highlightManager.addMesh(tempMesh, highlightColor());
115
- tempMesh = null;
116
- }
117
- hoverMesh = null;
118
- };
119
- export const resetSelectedMeshes = () => {
120
- const userMaterials = getUserMaterials();
121
- const firstMaterial = userMaterials[0] || {};
122
- newMetaDataEntry('selectedMaterials', []);
123
- if (!_.isEmpty(firstMaterial)) {
124
- const existingMaterial = scene.metadata?.materials?.find?.(mat => mat.materialId === firstMaterial.id);
125
- newMetaDataEntry('selectedMaterials', [existingMaterial]);
126
- }
127
- if (props.integration?.meshHighlighting !== false && highlightManager) {
128
- highlightManager.removeAllMeshes();
129
- }
130
- selectedMeshes = [];
131
- selectedMaterials = [];
132
- newMetaDataEntry('selectedMeshes', []);
133
- props.setSerializedData?.(serializeScene());
134
- };
135
- export const refreshHighlight = () => {
136
- if (props.integration?.meshHighlighting === false) return;
137
- highlightManager.removeAllMeshes();
138
- selectedMeshes.forEach(mesh => highlightManager.addMesh(mesh, highlightColor()));
139
- };
140
- const handleDragStart = e => {
141
- if (e.event.shiftKey) {
142
- const {
143
- event
144
- } = e;
145
- x1 = event.clientX - (event.clientX - event.offsetX);
146
- y1 = event.clientY - (event.clientY - event.offsetY);
147
- dragStarted = true;
148
- scene.activeCamera.inputs.attached.pointers.detachControl();
149
- }
150
- };
151
- const handleDrag = e => {
152
- if (dragStarted) {
153
- hasDragged = true;
154
- const {
155
- event
156
- } = e;
157
- const dragBox = guiTexture.getControlByName(GUI.dragSelectBox);
158
- x2 = event.clientX - (event.clientX - event.offsetX);
159
- y2 = event.clientY - (event.clientY - event.offsetY);
160
- dragBox.isVisible = true;
161
- dragBox.left = Math.min(x1, x2);
162
- dragBox.top = Math.min(y1, y2);
163
- dragBox.widthInPixels = Math.abs(x2 - x1);
164
- dragBox.heightInPixels = Math.abs(y2 - y1);
165
- }
166
- };
167
- const boundingBoxSelection = (meshes, start, end) => {
168
- meshes.forEach(mesh => {
169
- const meshRect = getClientRectFromMesh(mesh);
170
- const inTarget = isTargetIn(start, end, meshRect);
171
- const shouldBeSelected = mesh.isPickable && inTarget;
172
- if (shouldBeSelected) addNewMesh(mesh);
173
- });
174
- };
175
- const verticeSelection = (verticesByMesh, camera, start, end, debug) => {
176
- const worldPositionsByMesh = verticesByMesh.map(obj => {
177
- return {
178
- mesh: obj.mesh,
179
- worldPositions: getWorldPositionsByMesh(obj.mesh, obj.vertices)
180
- };
181
- });
182
- const worldToScaleGUIScreen = worldPositionsByMesh.map(obj => {
183
- const guiPositions = [];
184
- obj.worldPositions.forEach(vertex => {
185
- const guiPos = WorldToGUIPos(camera.position, camera.absoluteRotation, camera.fov, canvas.width, canvas.height, vertex);
186
- guiPositions.push(guiPos);
187
- });
188
- return {
189
- mesh: obj.mesh,
190
- vertices: guiPositions
191
- };
192
- });
193
- worldToScaleGUIScreen.forEach(obj => {
194
- if (debug) {
195
- obj.vertices.forEach(vertex => {
196
- const dot = new BABYLONGUI.Rectangle('item');
197
- dot.cornerRadius = 1;
198
- dot.thickness = 2;
199
- dot.alpha = 0.75;
200
- dot.color = theme.colors[$selectedTheme].accent;
201
- dot.background = `${theme.colors[$selectedTheme].accent}25`;
202
- dot.horizontalAlignment = BABYLONGUI.Control.HORIZONTAL_ALIGNMENT_LEFT;
203
- dot.verticalAlignment = BABYLONGUI.Control.VERTICAL_ALIGNMENT_TOP;
204
- dot.leftInPixels = vertex.x * canvas.width;
205
- dot.topInPixels = vertex.y * canvas.height;
206
- dot.widthInPixels = 1;
207
- dot.heightInPixels = 1;
208
- guiTexture.addControl(dot);
209
- });
210
- }
211
- const shouldSelect = obj.vertices.some(vertex => vertex.x <= end.x && vertex.x >= start.x && vertex.y <= end.y && vertex.y >= start.y);
212
- if (shouldSelect && hasDragged) addNewMesh(scene.getMeshById(obj.mesh));
213
- });
214
- };
215
- const handleDragEnd = () => {
216
- const debug = false;
217
- if (dragStarted) {
218
- const dragBox = guiTexture.getControlByName(GUI.dragSelectBox);
219
- const camera = scene.activeCamera;
220
- const possibleMeshes = getMeshesInCameraView();
221
- const verticesByMesh = getMeshVertices(possibleMeshes);
222
- const minRangeX = dragBox.leftInPixels / canvas.width;
223
- const minRangeY = dragBox.topInPixels / canvas.height;
224
- const maxRangeX = (dragBox.leftInPixels + dragBox.widthInPixels) / canvas.width;
225
- const maxRangeY = (dragBox.topInPixels + dragBox.heightInPixels) / canvas.height;
226
- const manyMeshes = getUserMeshes().length > MESH_COUNT_THRESHOLD;
227
- const startPos = {
228
- x: minRangeX,
229
- y: minRangeY
230
- };
231
- const endPos = {
232
- x: maxRangeX,
233
- y: maxRangeY
234
- };
235
- const bbStartPos = {
236
- x: minRangeX * canvas.width,
237
- y: minRangeY * canvas.height
238
- };
239
- const bbEndPos = {
240
- x: maxRangeX * canvas.width,
241
- y: maxRangeY * canvas.height
242
- };
243
- manyMeshes ? boundingBoxSelection(possibleMeshes, bbStartPos, bbEndPos) : verticeSelection(verticesByMesh, camera, startPos, endPos, debug);
244
- if (selectedMeshes.length > 1) attachToSelectMeshesNode();
245
- dragBox.isVisible = false;
246
- x1 = null;
247
- y1 = null;
248
- x2 = null;
249
- y2 = null;
250
- dragStarted = false;
251
- hasDragged = false;
252
- scene.activeCamera.inputs.attached.pointers.attachControl();
253
- refreshHighlight();
254
- }
255
- };
256
- export const handleMousePointerTap = e => {
257
- const clickedOnMesh = e?._pickInfo?.hit;
258
- if (!clickedOnMesh && !dragStarted) {
259
- resetSelectedMeshes();
260
- resetManagerGizmos();
261
- attachToSelectMeshesNode();
262
- }
263
- };
264
- const handleMousePointerPick = e => {
265
- const meshName = e._pickInfo?.pickedMesh?.name;
266
- const selectedMesh = meshName && scene.getMeshByName(meshName);
267
- if (hasDragged) return;
268
- if (!e.event.shiftKey) resetSelectedMeshes();
269
- if (!e.event.shiftKey && selectedMesh) return addNewMesh(selectedMesh);
270
- selectedMeshes.includes(selectedMesh) ? removeSelectedMesh(selectedMesh) : addNewMesh(selectedMesh);
271
- };
272
- const handleMousePointerMove = () => {
273
- if (props.previewMode) return;
274
- const ray = scene.createPickingRay(scene.pointerX, scene.pointerY, BABYLON.Matrix.Identity(), scene.activeCamera);
275
- const {
276
- hit,
277
- pickedMesh
278
- } = scene.pickWithRay(ray);
279
- !hit ? removeHoverMesh() : addHoverMesh(pickedMesh);
280
- };
281
- const handleSerializationUpdates = () => {
282
- const differentSelection = !_.isEqual(scene.metadata?.selectedMeshes, buildMeshIdArray());
283
- const deselecting = _.isEmpty(selectedMeshes) && hadSelection;
284
- if (differentSelection) {
285
- newMetaDataEntry('selectedMeshes', buildMeshIdArray());
286
- newMetaDataEntry('selectedMaterials', buildSelectedMaterialArray());
287
- props.setSerializedData?.(serializeScene());
288
- hadSelection = true;
289
- }
290
- if (deselecting) {
291
- hadSelection = false;
292
- resetSelectedMeshes();
293
- }
294
- if (gizmoManager.boundingBoxGizmoEnabled !== scene.metadata.boundingBoxEnabled) {
295
- newMetaDataEntry('boundingBoxEnabled', gizmoManager.boundingBoxGizmoEnabled);
296
- props.setSerializedData?.(serializeScene());
297
- }
298
- };
299
- export const handleMouseListeners = () => {
300
- scene.onPointerObservable.add(e => {
301
- switch (e.type) {
302
- case BABYLON.PointerEventTypes.POINTERMOVE:
303
- handleMousePointerMove(e);
304
- handleDrag(e);
305
- break;
306
- case BABYLON.PointerEventTypes.POINTERDOWN:
307
- handleDragStart(e);
308
- break;
309
- case BABYLON.PointerEventTypes.POINTERPICK:
310
- handleMousePointerPick(e);
311
- handleSerializationUpdates();
312
- break;
313
- case BABYLON.PointerEventTypes.POINTERUP:
314
- handleDragEnd(e);
315
- handleSerializationUpdates();
316
- break;
317
- case BABYLON.PointerEventTypes.POINTERTAP:
318
- handleMousePointerTap(e);
319
- handleSerializationUpdates();
320
- break;
321
- default:
322
- break;
323
- }
324
- });
325
- };
326
- export const prepareAxes = () => {
327
- const xAxisTNode = new BABYLON.TransformNode('xAxis', scene);
328
- const yAxisTNode = new BABYLON.TransformNode('yAxis', scene);
329
- const zAxisTNode = new BABYLON.TransformNode('zAxis', scene);
330
- const {
331
- height,
332
- width
333
- } = groundOptions();
334
- const gridMax = Math.max(height, width);
335
- const unitBounds = 8;
336
- const axisLength = 1 / unitBounds * gridMax;
337
- const xAxisLine = [BABYLON.Vector3.Zero(), newVector(axisLength, 0, 0)];
338
- const yAxisLine = [BABYLON.Vector3.Zero(), newVector(0, axisLength, 0)];
339
- const zAxisLine = [BABYLON.Vector3.Zero(), newVector(0, 0, axisLength)];
340
- const xAxisMesh = new BABYLON.MeshBuilder.CreateLines('xAxisMesh', {
341
- points: xAxisLine
342
- }, scene);
343
- const yAxisMesh = new BABYLON.MeshBuilder.CreateLines('yAxisMesh', {
344
- points: yAxisLine
345
- }, scene);
346
- const zAxisMesh = new BABYLON.MeshBuilder.CreateLines('zAxisMesh', {
347
- points: zAxisLine
348
- }, scene);
349
- const xAxisColor = newColor(AXIS_COLORS.xAxis);
350
- const yAxisColor = newColor(AXIS_COLORS.yAxis);
351
- const zAxisColor = newColor(AXIS_COLORS.zAxis);
352
- xAxisMesh.color = xAxisColor;
353
- yAxisMesh.color = yAxisColor;
354
- zAxisMesh.color = zAxisColor;
355
- xAxisMesh.rotation = newVector(0, toRadians(-90), 0);
356
- yAxisMesh.rotation = newVector(toRadians(90), 0, 0);
357
- xAxisMesh.isPickable = false;
358
- yAxisMesh.isPickable = false;
359
- zAxisMesh.isPickable = false;
360
- xAxisMesh.parent = xAxisTNode;
361
- yAxisMesh.parent = yAxisTNode;
362
- zAxisMesh.parent = zAxisTNode;
363
- new BABYLON.AxesViewer(scene, 1, null, xAxisTNode, yAxisTNode, zAxisTNode, 0.5);
364
- };
package/dist/styles.js DELETED
@@ -1,25 +0,0 @@
1
- import styled from 'styled-components';
2
- export const CanvasContainer = styled('div')`
3
- display: flex;
4
- position: relative;
5
- align-items: center;
6
- justify-content: center;
7
- height: 100%;
8
- width: 100%;
9
-
10
- #scene-explorer-host,
11
- #inspector-host {
12
- // Babylon inspector
13
- position: relative;
14
- z-index: 100;
15
- height: 100%;
16
- }
17
- `;
18
- export const RenderCanvas = styled('canvas')`
19
- width: 100%;
20
- height: 100%;
21
-
22
- &:focus {
23
- outline: none;
24
- }
25
- `;