architwin 1.15.4 → 1.15.6

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.
@@ -1,5 +1,5 @@
1
1
  import { Pane } from 'tweakpane';
2
- import { dispatchSpaceEvent, renderPolygon, getPolygonFloorOffset, getCurrentFloor, getWallBaseHeight, getFloorBaseHeight, isToolbarFeatureEnabled } from "../architwin";
2
+ import { dispatchSpaceEvent, renderPolygon, getPolygonFloorOffset, getCurrentFloor, getWallBaseHeight, getFloorBaseHeight, isToolbarFeatureEnabled, getDrawingConfig, getVertexPath } from "../architwin";
3
3
  import { SPACE_EVENTS } from "../types";
4
4
  import { getPolygonArea } from "../utils";
5
5
  import { PolygonCalculator, WallCalculator } from "../math";
@@ -184,6 +184,10 @@ export class TubeLine {
184
184
  if (this.panel) {
185
185
  this.panel.refresh();
186
186
  }
187
+ dispatchSpaceEvent(SPACE_EVENTS.PATH_UPDATED, {
188
+ path: this.inputs.path,
189
+ textColor: this.inputs.textColor
190
+ });
187
191
  };
188
192
  this.setBillboard = (value) => {
189
193
  this.billboard = value;
@@ -367,13 +371,14 @@ export const tubeLineFactory = function (mpSdk) {
367
371
  };
368
372
  export class Vertice {
369
373
  constructor(mpSdk) {
374
+ this.cachedWallNormal = null;
370
375
  this.inputs = {
371
376
  index: null,
372
377
  radius: 0.1,
373
378
  position: null,
374
379
  fillColor: 'rgb(0,255,0)',
375
380
  hoverColor: 'rgb(255,0,0)',
376
- ringVisibility: false
381
+ ringVisibility: false,
377
382
  };
378
383
  this.emits = {
379
384
  active: true,
@@ -418,18 +423,70 @@ export class Vertice {
418
423
  };
419
424
  this.mpSdk = mpSdk;
420
425
  }
426
+ calculateWallNormalFromVertices() {
427
+ const vertexPath = getVertexPath();
428
+ if (!vertexPath || vertexPath.length < 3) {
429
+ return null;
430
+ }
431
+ const THREE = this.context.three;
432
+ const p0 = new THREE.Vector3(vertexPath[0].x, vertexPath[0].y, vertexPath[0].z);
433
+ const p1 = new THREE.Vector3(vertexPath[1].x, vertexPath[1].y, vertexPath[1].z);
434
+ const p2 = new THREE.Vector3(vertexPath[2].x, vertexPath[2].y, vertexPath[2].z);
435
+ const v1 = new THREE.Vector3().subVectors(p1, p0);
436
+ const v2 = new THREE.Vector3().subVectors(p2, p0);
437
+ const normal = new THREE.Vector3().crossVectors(v1, v2);
438
+ const normalLen = normal.length();
439
+ if (normalLen === 0) {
440
+ // Vertices are collinear, can't determine plane
441
+ return null;
442
+ }
443
+ return normal.normalize();
444
+ }
421
445
  onEvent(eventType, data) {
422
446
  var _a;
423
447
  if (eventType === 'INTERACTION.DRAG') {
424
448
  //this.pointerIntersection.object === 'intersectedobject.model'
425
449
  if (this.pointerIntersection.object) {
426
450
  let e = Object.assign({}, this.pointerIntersection.position);
427
- const floorLevel = getFloorBaseHeight();
428
- if (floorLevel != undefined) {
429
- e.y = floorLevel;
451
+ const drawingConfig = getDrawingConfig();
452
+ // Apply floor level constraint only for non-window modes
453
+ if (!drawingConfig || drawingConfig.lineTypeComponentConfig.drawingMode !== 'window') {
454
+ const floorLevel = getFloorBaseHeight();
455
+ if (floorLevel != undefined) {
456
+ e.y = floorLevel;
457
+ }
458
+ else {
459
+ e.y = this.mesh.position.y;
460
+ }
430
461
  }
431
- else {
432
- e.y = this.mesh.position.y;
462
+ if (drawingConfig && drawingConfig.lineTypeComponentConfig.drawingMode == 'window') {
463
+ const firstVertex = getVertexPath()[0];
464
+ // Skip constraint for first vertex (index 0) - it defines the wall plane
465
+ if (this.inputs.index !== 0 && firstVertex) {
466
+ const THREE = this.context.three;
467
+ // Use cached normal if available, otherwise fall back to pointer normal
468
+ let wallNormal = this.cachedWallNormal;
469
+ if (!wallNormal && this.pointerIntersection.normal) {
470
+ // Fallback for when we don't have 3 vertices yet
471
+ wallNormal = new THREE.Vector3(this.pointerIntersection.normal.x, this.pointerIntersection.normal.y, this.pointerIntersection.normal.z).normalize();
472
+ }
473
+ if (wallNormal) {
474
+ // First vertex position defines a point on the wall plane
475
+ const planePoint = new THREE.Vector3(firstVertex.x, firstVertex.y, firstVertex.z);
476
+ // Current drag position
477
+ const dragPosition = new THREE.Vector3(e.x, e.y, e.z);
478
+ // Vector from plane point to drag position
479
+ const vecToPoint = new THREE.Vector3().subVectors(dragPosition, planePoint);
480
+ // Calculate distance from point to plane along normal
481
+ const distanceToPlane = vecToPoint.dot(wallNormal);
482
+ // Project point onto plane by removing the perpendicular component
483
+ const projectedPosition = new THREE.Vector3().subVectors(dragPosition, wallNormal.clone().multiplyScalar(distanceToPlane));
484
+ // Update e with constrained position (stays on wall plane)
485
+ e.x = projectedPosition.x;
486
+ e.y = projectedPosition.y;
487
+ e.z = projectedPosition.z;
488
+ }
489
+ }
433
490
  }
434
491
  this.mesh.position.set(e.x, e.y, e.z);
435
492
  //this.mesh.children[0].position.set(e.x, e.y, e.z)
@@ -453,6 +510,11 @@ export class Vertice {
453
510
  this.pointerIntersection = data;
454
511
  });
455
512
  }
513
+ // Cache wall normal for window mode
514
+ const drawingConfig = getDrawingConfig();
515
+ if (drawingConfig && drawingConfig.lineTypeComponentConfig.drawingMode === 'window') {
516
+ this.cachedWallNormal = this.calculateWallNormalFromVertices();
517
+ }
456
518
  //@ts-expect-error
457
519
  this.notify('changed', {
458
520
  index: this.inputs.index,
@@ -466,6 +528,8 @@ export class Vertice {
466
528
  this.mesh.scale.set(1, 1, 1);
467
529
  this.mpSdk.Pointer.setVisible(true);
468
530
  (_a = this.pointerSub) === null || _a === void 0 ? void 0 : _a.cancel();
531
+ // Clear cached wall normal
532
+ this.cachedWallNormal = null;
469
533
  //renderPolygonFromPath()
470
534
  //@ts-expect-error
471
535
  this.notify('changed', {
@@ -1209,9 +1273,11 @@ export class BufferGeometry {
1209
1273
  }
1210
1274
  // Calculate window area using the projected 2D coordinates
1211
1275
  const windowDimension = this.calculateWindowDimensions(windows[i].path);
1212
- let windowLabelText = windows[i].name ? `${windows[i].name}` : windowMesh.name;
1276
+ const windowLabel = windows[i].name.split(" ");
1277
+ const windowName = windowLabel[0] == 'Window' ? i18n.t('Window') + ' ' + windowLabel[1] : windows[i].name;
1278
+ let windowLabelText = windows[i].name ? `${windowName}` : windowMesh.name;
1213
1279
  windowLabelText = windows[i].material ? `${windowLabelText}_${windows[i].material}: ${windowDimension.area.toFixed(2)}m²` : `${windowLabelText}: ${windowDimension.area.toFixed(2)}m²`;
1214
- log.info("windowLabelText ", windowLabelText);
1280
+ log.info("windowLabelText ", windowLabelText, windows[i].name, windowMesh.name, i18n.t('Window'));
1215
1281
  const windowCanvas = this.createLabelCanvas(windowLabelText);
1216
1282
  const windowArea = Math.abs(twiceSignedArea * 0.5);
1217
1283
  const labelWidth = Math.max(0.5, Math.min(2, Math.sqrt(Math.max(0.0001, windowArea))));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "architwin",
3
- "version": "1.15.4",
3
+ "version": "1.15.6",
4
4
  "description": "ArchiTwin Library for Matterport",
5
5
  "main": "./lib/architwin.js",
6
6
  "types": "./lib/architwin.d.ts",
@@ -1262,7 +1262,7 @@
1262
1262
  height: 100%;
1263
1263
  background: rgba(0, 0, 0, 0.8);
1264
1264
  z-index: 1000;
1265
- justify-content: center;
1265
+ justify-content: flex-start;
1266
1266
  align-items: center;
1267
1267
  animation: at_fade-in 0.3s ease;
1268
1268
  }
@@ -1285,15 +1285,16 @@
1285
1285
  color: var(--text-color-light);
1286
1286
  border-radius: var(--border-radius);
1287
1287
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
1288
- width: 95vw;
1288
+ width: 66.5vw;
1289
1289
  height: 95vh;
1290
- max-width: 95vw;
1290
+ max-width: 66.5vw;
1291
1291
  max-height: 95vh;
1292
1292
  overflow: hidden;
1293
1293
  position: relative;
1294
1294
  animation: at_slide-up 0.4s cubic-bezier(.39, .575, .565, 1.000) both;
1295
1295
  display: flex;
1296
1296
  flex-direction: column;
1297
+ margin-left: 0.5vw;
1297
1298
  }
1298
1299
 
1299
1300
  @keyframes at_slide-up {
@@ -1386,6 +1387,76 @@
1386
1387
  flex-shrink: 0;
1387
1388
  }
1388
1389
 
1390
+ /* Resize handles for preview modal */
1391
+ .at_preview_modal-resize-handle {
1392
+ position: absolute;
1393
+ z-index: 10;
1394
+ }
1395
+
1396
+ .at_preview_modal-resize-handle--top,
1397
+ .at_preview_modal-resize-handle--bottom {
1398
+ left: 8px;
1399
+ right: 8px;
1400
+ height: 8px;
1401
+ cursor: ns-resize;
1402
+ }
1403
+
1404
+ .at_preview_modal-resize-handle--left,
1405
+ .at_preview_modal-resize-handle--right {
1406
+ top: 8px;
1407
+ bottom: 8px;
1408
+ width: 8px;
1409
+ cursor: ew-resize;
1410
+ }
1411
+
1412
+ .at_preview_modal-resize-handle--top {
1413
+ top: 0;
1414
+ }
1415
+
1416
+ .at_preview_modal-resize-handle--right {
1417
+ right: 0;
1418
+ }
1419
+
1420
+ .at_preview_modal-resize-handle--bottom {
1421
+ bottom: 0;
1422
+ }
1423
+
1424
+ .at_preview_modal-resize-handle--left {
1425
+ left: 0;
1426
+ }
1427
+
1428
+ .at_preview_modal-resize-handle--top-left,
1429
+ .at_preview_modal-resize-handle--top-right,
1430
+ .at_preview_modal-resize-handle--bottom-left,
1431
+ .at_preview_modal-resize-handle--bottom-right {
1432
+ width: 16px;
1433
+ height: 16px;
1434
+ }
1435
+
1436
+ .at_preview_modal-resize-handle--top-left {
1437
+ top: 0;
1438
+ left: 0;
1439
+ cursor: nwse-resize;
1440
+ }
1441
+
1442
+ .at_preview_modal-resize-handle--top-right {
1443
+ top: 0;
1444
+ right: 0;
1445
+ cursor: nesw-resize;
1446
+ }
1447
+
1448
+ .at_preview_modal-resize-handle--bottom-left {
1449
+ bottom: 0;
1450
+ left: 0;
1451
+ cursor: nesw-resize;
1452
+ }
1453
+
1454
+ .at_preview_modal-resize-handle--bottom-right {
1455
+ bottom: 0;
1456
+ right: 0;
1457
+ cursor: nwse-resize;
1458
+ }
1459
+
1389
1460
  @keyframes slide-down {
1390
1461
  from {
1391
1462
  transform: translateY(-100%);