architwin 1.15.3 → 1.15.5

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.
@@ -387,14 +387,14 @@ i18n
387
387
  "SuccessPartitionDelete": "削除しました",
388
388
  "NoPartitionDeleted": "削除できる区画がありません",
389
389
  "Saving": "保存",
390
- "DeletePartition": "パーティション削除",
390
+ "DeletePartition": "区画削除",
391
391
  "ModifyPartition": "パーティションの変更",
392
392
  "InvalidNaN": "値が不正です。正しい数値を入力してくさい。",
393
393
  "CannotPlaceInArea": "ここには設定できません。位置を変えて試してください。",
394
394
  "SuccessWallHeight": "壁の高さが正常に更新されました",
395
395
  "Edge": "辺長",
396
396
  "Area": "面積",
397
- "DeleteWall": "ウォール削除",
397
+ "DeleteWall": "壁削除",
398
398
  "SuccessWallDelete": "削除しました",
399
399
  "WarnLowFloor": "Tマークされたエリアは、スペースの床よりも低い場合があります",
400
400
  "Settings": "BIM/CAD設定",
@@ -13,7 +13,7 @@ export function renderPreviewModal() {
13
13
  element.setAttribute('id', 'at-preview-modal-overlay');
14
14
  element.setAttribute('data-cy', 'at-preview-modal-overlay');
15
15
  element.innerHTML = `
16
- <div class="at_preview_modal">
16
+ <div class="at_preview_modal" id="at-preview-modal">
17
17
  <div class="at_preview_modal-header">
18
18
  <h2 class="at_preview_modal-title" id="at-preview-modal-content-heading" data-cy="at-preview-modal-content-heading"></h2>
19
19
  <button class="at_preview_modal-close-btn" data-cy="at-preview-modal-close-btn">&times;</button>
@@ -22,6 +22,14 @@ export function renderPreviewModal() {
22
22
  <div class="at_preview_modal-content" id="at-preview-modal-content-subheading" data-cy="at-preview-modal-content-subheading">
23
23
  </div>
24
24
  </div>
25
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--top" data-resize-direction="top"></div>
26
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--right" data-resize-direction="right"></div>
27
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--bottom" data-resize-direction="bottom"></div>
28
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--left" data-resize-direction="left"></div>
29
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--top-left" data-resize-direction="top-left"></div>
30
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--top-right" data-resize-direction="top-right"></div>
31
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--bottom-left" data-resize-direction="bottom-left"></div>
32
+ <div class="at_preview_modal-resize-handle at_preview_modal-resize-handle--bottom-right" data-resize-direction="bottom-right"></div>
25
33
  </div>
26
34
  `;
27
35
  document.body.appendChild(element);
@@ -1,4 +1,5 @@
1
- import { FORM_MODE, PartitionNode, PolygonData, IObjectData } from "../../../../types";
1
+ import { FORM_MODE, PartitionNode, PolygonData, WallPolyData, IObjectData } from "../../../../types";
2
+ export declare let isEditWindow: boolean;
2
3
  export declare function renderRoomFormPane(): HTMLDivElement;
3
4
  /**
4
5
  * Toggles the state of the partition drawing functionality.
@@ -29,6 +30,7 @@ export declare function displayPartitionFormMode(): void;
29
30
  * @param event - The click event from the edit button, used to identify which partition to edit
30
31
  */
31
32
  export declare function handlePartitionRowEditBtnClickEvent(partitions: Array<PartitionNode>, targetElement: HTMLElement): void;
33
+ export declare function displayWall(wall: WallPolyData): HTMLElement;
32
34
  /**
33
35
  * Clears the partition form by resetting UI elements and internal data.
34
36
  * - Navigates back to the partition list view.
@@ -102,6 +104,7 @@ export declare function getCurrentPolygonData(): PolygonData;
102
104
  * partition with its corresponding UUID, space UUID, and polygon data.
103
105
  */
104
106
  export declare function setCurrentPartitionData(): Promise<void>;
107
+ export declare function removeWindow(index?: number): void;
105
108
  export declare function getCurrentPartitionData(): PartitionNode;
106
109
  export declare function getNewlyAddedPartition(): Array<PartitionNode>;
107
110
  export declare function getDeletedSavedPartitionArray(): Array<PartitionNode>;
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import i18n from '../i18n';
11
11
  import { SPACE_EVENTS } from "../../../../types";
12
12
  import { batchAddEventListenerByClassName } from "../../../events";
13
- import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition, clearFloorBaseHeight } from '../../../../architwin';
13
+ import { startDraw, cancelDraw, disposeModel, _3DXObjects, getCurrentPolygon, dispatchSpaceEvent, enableVerticeControls, setCurrentPolygon, setMeshChildrenMaterialProperty, get3DXObjects, getChildrenOfModel, clearSelectedObject, renderPolygon, addUndoDrawActions, setWallBaseHeight, clearWallBaseHeight, setDrawingConfig, resetDrawingConfig, goToPosition, clearFloorBaseHeight, clearDrawActionHistory } from '../../../../architwin';
14
14
  import { generateUUID, extractUUID } from '../../../../utils';
15
15
  import { getCurrentEditRoomData } from './roomTreePane';
16
16
  import { toggleModal, setModalAction } from "../modal";
@@ -41,7 +41,7 @@ let inputFloorMaterial;
41
41
  let floorMaterial = '';
42
42
  let inputWallMaterial;
43
43
  let wallMaterial = '';
44
- let isEditWindow = false;
44
+ export let isEditWindow = false;
45
45
  let currentEditWindowIndex = null;
46
46
  let tempCurrentEditRoom = null;
47
47
  export function renderRoomFormPane() {
@@ -241,12 +241,14 @@ export function toggleDrawWindowButton() {
241
241
  isDrawing = true;
242
242
  drawingMode = 'window';
243
243
  // clearSelectedObject()
244
- addDoorButton.classList.remove('at_add_window_door_btn');
245
- addDoorButton.classList.add('at_add_window_door_btn_active');
246
- addDoorButton.innerHTML = `
247
- ${i18n.t('DoneDrawing')}
248
- <span class="mdi mdi-check-bold"></span>
249
- `;
244
+ if (!isEditWindow) {
245
+ addDoorButton.classList.remove('at_add_window_door_btn');
246
+ addDoorButton.classList.add('at_add_window_door_btn_active');
247
+ addDoorButton.innerHTML = `
248
+ ${i18n.t('DoneDrawing')}
249
+ <span class="mdi mdi-check-bold"></span>
250
+ `;
251
+ }
250
252
  const objectIndex = _3DXObjects.findIndex(obj => obj.object.id == currentObject.object.id);
251
253
  log.info("objectIndex", objectIndex);
252
254
  clearFloorBaseHeight();
@@ -796,7 +798,7 @@ function displayFaces(polygon) {
796
798
  wallConfirmMaterial.style.display = "inline-flex";
797
799
  });
798
800
  }
799
- function displayWall(wall) {
801
+ export function displayWall(wall) {
800
802
  log.info("displayWall()", wall);
801
803
  // Extract the wall name from the format "_wall-{number}" using regex
802
804
  const match = wall.name.match(/wall-(\d+)$/);
@@ -941,16 +943,28 @@ function setupEditWindow(element, window) {
941
943
  inputName.focus();
942
944
  isEditWindow = true;
943
945
  currentEditWindowIndex = window.index;
944
- // toggleDrawWindowButton()
946
+ drawingMode = 'window';
947
+ toggleDrawWindowButton();
948
+ log.info("currentObject ", currentObject);
949
+ setCurrentPolygon(currentObject);
950
+ const drawConfig = {
951
+ lineTypeComponentConfig: {
952
+ renderPolygonOnAdd: false,
953
+ drawingMode: drawingMode,
954
+ polygonData: currentObject.object.object_data.json_data,
955
+ targetUUID: currentWall.uuid,
956
+ targetIndex: currentEditWindowIndex
957
+ }
958
+ };
959
+ setDrawingConfig(drawConfig);
945
960
  // @ts-ignore
946
961
  const windowComponent = {
947
962
  inputs: {
948
963
  path: window.path
949
964
  }
950
965
  };
951
- log.info("currentObject ", currentObject);
952
- // setCurrentPolygon(currentObject)
953
- // enableVerticeControls(windowComponent)
966
+ enableVerticeControls(windowComponent);
967
+ isDrawing = true;
954
968
  });
955
969
  // // Confirm edit name and material
956
970
  confirmBtn.addEventListener("click", () => {
@@ -979,8 +993,11 @@ function setupEditWindow(element, window) {
979
993
  }
980
994
  }));
981
995
  }
982
- // toggleDrawWindowButton()
996
+ // cancelDraw()
997
+ toggleDrawWindowButton();
983
998
  saveWallChanges();
999
+ isDrawing = false;
1000
+ isEditWindow = false;
984
1001
  });
985
1002
  }
986
1003
  function saveWallChanges() {
@@ -1144,7 +1161,7 @@ function displayFloor(floor, walls, floorModel) {
1144
1161
  <span class="mdi mdi-chevron-up" id="at-expand-btn-${floor.uuid}" data-cy="at-expand-btn-${floor.uuid}" model-id="${floorModelUUID}"></span>
1145
1162
  </div>
1146
1163
  <div class="at_subitem_right">
1147
- <span class="mdi mdi-delete-outline"></span>
1164
+ <!-- <span class="mdi mdi-delete-outline"></span> -->
1148
1165
  </div>
1149
1166
  </div>
1150
1167
 
@@ -1505,6 +1522,7 @@ export function setCurrentPartitionData() {
1505
1522
  if (drawingMode === 'partition') {
1506
1523
  displayFaceLists();
1507
1524
  currentObject = currentObjectData;
1525
+ log.info("currentObject", currentObject);
1508
1526
  }
1509
1527
  }, 50); // Check every 50ms
1510
1528
  });
@@ -1536,6 +1554,7 @@ export function setCurrentPartitionData() {
1536
1554
  }
1537
1555
  else if (drawingMode === 'window') {
1538
1556
  // Update current edit wall display
1557
+ currentObject.object.object_data.json_data = currentPolygonData;
1539
1558
  currentWall = currentPolygonData.walls.find(wall => wall.uuid == currentWall.uuid);
1540
1559
  log.info("current wall", currentWall, currentPolygonData);
1541
1560
  const faceVertexContainer = document.getElementById('at-face-vertex-container');
@@ -1558,7 +1577,7 @@ export function setCurrentPartitionData() {
1558
1577
  });
1559
1578
  }
1560
1579
  function updatePartitionDataArray(payload, currentPartitionDataArray) {
1561
- log.info("updatePartitionDataArray", payload, currentPartitionDataArray);
1580
+ log.info("updatePartitionDataArray", payload, currentPartitionDataArray, drawingMode);
1562
1581
  if (drawingMode === 'partition') {
1563
1582
  // Find the index of the partition with the same uuid
1564
1583
  const existingIndex = currentPartitionDataArray.findIndex((partition) => partition.uuid === payload.uuid);
@@ -1609,10 +1628,6 @@ function onModeDetectFloorInput(event) {
1609
1628
  floorConfirmMaterial.style.display = "none";
1610
1629
  }
1611
1630
  }
1612
- function setFloorMaterial(material) {
1613
- console.log('setFloorMaterial()', material);
1614
- floorMaterial = material;
1615
- }
1616
1631
  function onModeDetectWallInput(event) {
1617
1632
  console.log('onModeDetectWallInput()', event);
1618
1633
  const target = event.target;
@@ -1629,6 +1644,21 @@ function onModeDetectWallInput(event) {
1629
1644
  wallConfirmMaterial.style.display = "none";
1630
1645
  }
1631
1646
  }
1647
+ export function removeWindow(index = -1) {
1648
+ if (index <= -1) {
1649
+ currentWall.windows.pop();
1650
+ }
1651
+ else {
1652
+ currentWall.windows.splice(index, 1);
1653
+ }
1654
+ const faceVertexContainer = document.getElementById('at-face-vertex-container');
1655
+ faceVertexContainer.innerHTML = '';
1656
+ faceVertexContainer.append(displayWall(currentWall));
1657
+ }
1658
+ function setFloorMaterial(material) {
1659
+ console.log('setFloorMaterial()', material);
1660
+ floorMaterial = material;
1661
+ }
1632
1662
  function setWallMaterial(material) {
1633
1663
  console.log('setWallMaterial()');
1634
1664
  wallMaterial = material;
@@ -1755,6 +1785,7 @@ export function handlePartitionWallEditBtn(wallUuid) {
1755
1785
  currentPolygonData = JSON.parse(currentPartitionData.polygon_json);
1756
1786
  setDrawingMode(false);
1757
1787
  cancelDrawing();
1788
+ clearDrawActionHistory();
1758
1789
  });
1759
1790
  }
1760
1791
  export function getTempCurrentRoomEditData() {
@@ -38,20 +38,20 @@ export function renderTagIOTFormPane() {
38
38
 
39
39
  <div class="at_form_container at_scrollable_container at_h-min-70">
40
40
  <label for="">${i18n.t('LinkedSystems')}</label>
41
- <div class="at_gap_2" style="display: inline-flex">
42
- <label class="at_flex at_align_center at_text_xs at_gap_1">
43
- <input type="radio" id="at-linked-radio-bemac" name="iot-link-system" checked value=${IOT_LINKED_SYSTEMS.BEMAC} selected />
44
- ${i18n.t("BEMAC")}
45
- </label>
46
- <label class="at_flex at_align_center at_text_xs at_gap_1">
47
- <input type="radio" id="at-linked-radio-hanasys" name="iot-link-system" value=${IOT_LINKED_SYSTEMS.HANASYS} />
48
- ${i18n.t("HANASYS")}
49
- </label>
50
- <label class="at_flex at_align_center at_text_xs at_gap_1">
51
- <input type="radio" id="at-linked-radio-link" name="iot-link-system" value=${IOT_LINKED_SYSTEMS.URL_LINK} />
52
- ${i18n.t("URLLink")}
53
- </label>
54
- </div>
41
+ <div class="at_linked_systems_options_contianer at_gap_2" style="display: inline-flex">
42
+ <label class="at_flex at_align_center at_text_xs at_gap_1">
43
+ <input type="radio" id="at-linked-radio-bemac" name="iot-link-system" checked value=${IOT_LINKED_SYSTEMS.BEMAC} selected />
44
+ ${i18n.t("BEMAC")}
45
+ </label>
46
+ <label class="at_flex at_align_center at_text_xs at_gap_1">
47
+ <input type="radio" id="at-linked-radio-hanasys" name="iot-link-system" value=${IOT_LINKED_SYSTEMS.HANASYS} />
48
+ ${i18n.t("HANASYS")}
49
+ </label>
50
+ <label class="at_flex at_align_center at_text_xs at_gap_1">
51
+ <input type="radio" id="at-linked-radio-link" name="iot-link-system" value=${IOT_LINKED_SYSTEMS.URL_LINK} />
52
+ ${i18n.t("URLLink")}
53
+ </label>
54
+ </div>
55
55
 
56
56
  <div class="at_field at_flex_column">
57
57
  <label for="">${i18n.t('Category')}</label>
@@ -349,7 +349,9 @@ export function renderTagRow(tag, tagIconUrl, tag_type = null) {
349
349
  </div>
350
350
  </td>
351
351
  <td id="at-tag-row-${tag.id}" data-cy="at-tag-row-${tag.id}" tag-id="${tag.id}">
352
- <span>${tag.label}</span>
352
+ <div class="at-iot-tag-row-name">
353
+ <span title="${tag.label.length > 12 ? tag.label : ''}">${tag.label}</span>
354
+ </div>
353
355
  </td>
354
356
  <td class="at_table_button_row">
355
357
  <span class="mdi mdi-pencil at_edit_tag_btn ${isTagReadOnly ? 'at_disabled' : ''}" id="at-edit-tag-${tag.id}" data-cy="at-edit-tag-${tag.id}" tag-id="${tag.id}" target-pane=${tag_type === TAG_TYPE.IOT ? "at-tag-iot-form-pane" : "at-tag-form-pane"}></span>
@@ -530,6 +530,7 @@ function setupIndividualEventListeners() {
530
530
  handlePipeForm();
531
531
  handlePipeList();
532
532
  handleResponsiveChanges();
533
+ handlePreviewModalResize();
533
534
  }
534
535
  //================ OBJECT EVENT HANDLERS ===============//s
535
536
  function handleResponsiveChanges() {
@@ -1586,7 +1587,7 @@ function handleDragEnd(payload) {
1586
1587
  setCurrentTransformationValues(transformValues);
1587
1588
  }
1588
1589
  function handleDrawHistory(payload) {
1589
- console.log("payload", payload);
1590
+ console.log("handleDrawHistory", payload);
1590
1591
  const undoCount = (payload.undoDrawActions).length;
1591
1592
  const redoCount = (payload.redoDrawActions).length;
1592
1593
  if (undoCount == 0) {
@@ -3896,6 +3897,94 @@ function clearActivePane() {
3896
3897
  paneElement.style.display = 'none';
3897
3898
  }
3898
3899
  }
3900
+ function handlePreviewModalResize() {
3901
+ const modal = document.getElementById('at-preview-modal');
3902
+ const resizeHandles = document.querySelectorAll('.at_preview_modal-resize-handle');
3903
+ if (!modal || !resizeHandles.length)
3904
+ return;
3905
+ let isResizing = false;
3906
+ let currentHandle = null;
3907
+ let startX = 0;
3908
+ let startY = 0;
3909
+ let startWidth = 0;
3910
+ let startHeight = 0;
3911
+ let startLeft = 0;
3912
+ let startTop = 0;
3913
+ const minWidth = 400;
3914
+ const minHeight = 300;
3915
+ const maxWidth = window.innerWidth * 0.95;
3916
+ const maxHeight = window.innerHeight * 0.95;
3917
+ resizeHandles.forEach((handle) => {
3918
+ handle.addEventListener('mousedown', (e) => {
3919
+ e.preventDefault();
3920
+ e.stopPropagation();
3921
+ isResizing = true;
3922
+ currentHandle = handle;
3923
+ startX = e.clientX;
3924
+ startY = e.clientY;
3925
+ const rect = modal.getBoundingClientRect();
3926
+ startWidth = rect.width;
3927
+ startHeight = rect.height;
3928
+ startLeft = rect.left;
3929
+ startTop = rect.top;
3930
+ document.body.style.cursor = window.getComputedStyle(handle).cursor;
3931
+ document.body.style.userSelect = 'none';
3932
+ });
3933
+ });
3934
+ document.addEventListener('mousemove', (e) => {
3935
+ if (!isResizing || !currentHandle)
3936
+ return;
3937
+ const direction = currentHandle.getAttribute('data-resize-direction');
3938
+ const deltaX = e.clientX - startX;
3939
+ const deltaY = e.clientY - startY;
3940
+ let newWidth = startWidth;
3941
+ let newHeight = startHeight;
3942
+ let newLeft = startLeft;
3943
+ let newTop = startTop;
3944
+ // Handle horizontal resizing
3945
+ if (direction === null || direction === void 0 ? void 0 : direction.includes('right')) {
3946
+ newWidth = Math.max(minWidth, Math.min(maxWidth, startWidth + deltaX));
3947
+ }
3948
+ else if (direction === null || direction === void 0 ? void 0 : direction.includes('left')) {
3949
+ const potentialWidth = startWidth - deltaX;
3950
+ if (potentialWidth >= minWidth && potentialWidth <= maxWidth) {
3951
+ newWidth = potentialWidth;
3952
+ newLeft = startLeft + deltaX;
3953
+ }
3954
+ }
3955
+ // Handle vertical resizing
3956
+ if (direction === null || direction === void 0 ? void 0 : direction.includes('bottom')) {
3957
+ newHeight = Math.max(minHeight, Math.min(maxHeight, startHeight + deltaY));
3958
+ }
3959
+ else if (direction === null || direction === void 0 ? void 0 : direction.includes('top')) {
3960
+ const potentialHeight = startHeight - deltaY;
3961
+ if (potentialHeight >= minHeight && potentialHeight <= maxHeight) {
3962
+ newHeight = potentialHeight;
3963
+ newTop = startTop + deltaY;
3964
+ }
3965
+ }
3966
+ // Apply new dimensions
3967
+ modal.style.width = `${newWidth}px`;
3968
+ modal.style.height = `${newHeight}px`;
3969
+ modal.style.maxWidth = `${newWidth}px`;
3970
+ modal.style.maxHeight = `${newHeight}px`;
3971
+ // For top/left resizing, we need to reposition the modal
3972
+ if ((direction === null || direction === void 0 ? void 0 : direction.includes('left')) || (direction === null || direction === void 0 ? void 0 : direction.includes('top'))) {
3973
+ modal.style.position = 'fixed';
3974
+ modal.style.left = `${newLeft}px`;
3975
+ modal.style.top = `${newTop}px`;
3976
+ modal.style.transform = 'none';
3977
+ }
3978
+ });
3979
+ document.addEventListener('mouseup', () => {
3980
+ if (isResizing) {
3981
+ isResizing = false;
3982
+ currentHandle = null;
3983
+ document.body.style.cursor = '';
3984
+ document.body.style.userSelect = '';
3985
+ }
3986
+ });
3987
+ }
3899
3988
  export {
3900
3989
  //state
3901
3990
  activeToolbarItem, activeActionItem, cancelModelPlacementPrompt, isCustomMapControlsVisible, pipeColor,
@@ -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";
@@ -85,6 +85,7 @@ export class TubeLine {
85
85
  this.renderTubeLine();
86
86
  console.log("paths ", this.inputs.path);
87
87
  if (isToolbarFeatureEnabled('roomCreation') && this.inputs.path.length >= 3 && this.inputs.drawingMode == 'window') {
88
+ console.log("tubeline drawing mode ", this.inputs.drawingMode);
88
89
  const options = {
89
90
  drawingMode: this.inputs.drawingMode,
90
91
  targetIndex: this.inputs.targetIndex,
@@ -372,7 +373,7 @@ export class Vertice {
372
373
  position: null,
373
374
  fillColor: 'rgb(0,255,0)',
374
375
  hoverColor: 'rgb(255,0,0)',
375
- ringVisibility: false
376
+ ringVisibility: false,
376
377
  };
377
378
  this.emits = {
378
379
  active: true,
@@ -423,12 +424,39 @@ export class Vertice {
423
424
  //this.pointerIntersection.object === 'intersectedobject.model'
424
425
  if (this.pointerIntersection.object) {
425
426
  let e = Object.assign({}, this.pointerIntersection.position);
426
- const floorLevel = getFloorBaseHeight();
427
- if (floorLevel != undefined) {
428
- e.y = floorLevel;
427
+ const drawingConfig = getDrawingConfig();
428
+ // Apply floor level constraint only for non-window modes
429
+ if (!drawingConfig || drawingConfig.lineTypeComponentConfig.drawingMode !== 'window') {
430
+ const floorLevel = getFloorBaseHeight();
431
+ if (floorLevel != undefined) {
432
+ e.y = floorLevel;
433
+ }
434
+ else {
435
+ e.y = this.mesh.position.y;
436
+ }
429
437
  }
430
- else {
431
- e.y = this.mesh.position.y;
438
+ if (drawingConfig && drawingConfig.lineTypeComponentConfig.drawingMode == 'window') {
439
+ const firstVertex = getVertexPath()[0];
440
+ // Skip constraint for first vertex (index 0) - it defines the wall plane
441
+ if (this.inputs.index !== 0 && firstVertex && this.pointerIntersection.normal) {
442
+ const THREE = this.context.three;
443
+ // Get wall normal from pointer intersection
444
+ const wallNormal = new THREE.Vector3(this.pointerIntersection.normal.x, this.pointerIntersection.normal.y, this.pointerIntersection.normal.z).normalize();
445
+ // First vertex position defines a point on the wall plane
446
+ const planePoint = new THREE.Vector3(firstVertex.x, firstVertex.y, firstVertex.z);
447
+ // Current drag position
448
+ const dragPosition = new THREE.Vector3(e.x, e.y, e.z);
449
+ // Vector from plane point to drag position
450
+ const vecToPoint = new THREE.Vector3().subVectors(dragPosition, planePoint);
451
+ // Calculate distance from point to plane along normal
452
+ const distanceToPlane = vecToPoint.dot(wallNormal);
453
+ // Project point onto plane by removing the perpendicular component
454
+ const projectedPosition = new THREE.Vector3().subVectors(dragPosition, wallNormal.clone().multiplyScalar(distanceToPlane));
455
+ // Update e with constrained position (stays on wall plane)
456
+ e.x = projectedPosition.x;
457
+ e.y = projectedPosition.y;
458
+ e.z = projectedPosition.z;
459
+ }
432
460
  }
433
461
  this.mesh.position.set(e.x, e.y, e.z);
434
462
  //this.mesh.children[0].position.set(e.x, e.y, e.z)
@@ -1208,9 +1236,11 @@ export class BufferGeometry {
1208
1236
  }
1209
1237
  // Calculate window area using the projected 2D coordinates
1210
1238
  const windowDimension = this.calculateWindowDimensions(windows[i].path);
1211
- let windowLabelText = windows[i].name ? `${windows[i].name}` : windowMesh.name;
1239
+ const windowLabel = windows[i].name.split(" ");
1240
+ const windowName = windowLabel[0] == 'Window' ? i18n.t('Window') + ' ' + windowLabel[1] : windows[i].name;
1241
+ let windowLabelText = windows[i].name ? `${windowName}` : windowMesh.name;
1212
1242
  windowLabelText = windows[i].material ? `${windowLabelText}_${windows[i].material}: ${windowDimension.area.toFixed(2)}m²` : `${windowLabelText}: ${windowDimension.area.toFixed(2)}m²`;
1213
- log.info("windowLabelText ", windowLabelText);
1243
+ log.info("windowLabelText ", windowLabelText, windows[i].name, windowMesh.name, i18n.t('Window'));
1214
1244
  const windowCanvas = this.createLabelCanvas(windowLabelText);
1215
1245
  const windowArea = Math.abs(twiceSignedArea * 0.5);
1216
1246
  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.3",
3
+ "version": "1.15.5",
4
4
  "description": "ArchiTwin Library for Matterport",
5
5
  "main": "./lib/architwin.js",
6
6
  "types": "./lib/architwin.d.ts",
@@ -1386,6 +1386,76 @@
1386
1386
  flex-shrink: 0;
1387
1387
  }
1388
1388
 
1389
+ /* Resize handles for preview modal */
1390
+ .at_preview_modal-resize-handle {
1391
+ position: absolute;
1392
+ z-index: 10;
1393
+ }
1394
+
1395
+ .at_preview_modal-resize-handle--top,
1396
+ .at_preview_modal-resize-handle--bottom {
1397
+ left: 8px;
1398
+ right: 8px;
1399
+ height: 8px;
1400
+ cursor: ns-resize;
1401
+ }
1402
+
1403
+ .at_preview_modal-resize-handle--left,
1404
+ .at_preview_modal-resize-handle--right {
1405
+ top: 8px;
1406
+ bottom: 8px;
1407
+ width: 8px;
1408
+ cursor: ew-resize;
1409
+ }
1410
+
1411
+ .at_preview_modal-resize-handle--top {
1412
+ top: 0;
1413
+ }
1414
+
1415
+ .at_preview_modal-resize-handle--right {
1416
+ right: 0;
1417
+ }
1418
+
1419
+ .at_preview_modal-resize-handle--bottom {
1420
+ bottom: 0;
1421
+ }
1422
+
1423
+ .at_preview_modal-resize-handle--left {
1424
+ left: 0;
1425
+ }
1426
+
1427
+ .at_preview_modal-resize-handle--top-left,
1428
+ .at_preview_modal-resize-handle--top-right,
1429
+ .at_preview_modal-resize-handle--bottom-left,
1430
+ .at_preview_modal-resize-handle--bottom-right {
1431
+ width: 16px;
1432
+ height: 16px;
1433
+ }
1434
+
1435
+ .at_preview_modal-resize-handle--top-left {
1436
+ top: 0;
1437
+ left: 0;
1438
+ cursor: nwse-resize;
1439
+ }
1440
+
1441
+ .at_preview_modal-resize-handle--top-right {
1442
+ top: 0;
1443
+ right: 0;
1444
+ cursor: nesw-resize;
1445
+ }
1446
+
1447
+ .at_preview_modal-resize-handle--bottom-left {
1448
+ bottom: 0;
1449
+ left: 0;
1450
+ cursor: nesw-resize;
1451
+ }
1452
+
1453
+ .at_preview_modal-resize-handle--bottom-right {
1454
+ bottom: 0;
1455
+ right: 0;
1456
+ cursor: nwse-resize;
1457
+ }
1458
+
1389
1459
  @keyframes slide-down {
1390
1460
  from {
1391
1461
  transform: translateY(-100%);
@@ -2858,3 +2928,26 @@ span.at_room_name_text.toggle.selectable.selected {
2858
2928
  span.at_partition_name_text.toggle.selectable.selected {
2859
2929
  border: none !important;
2860
2930
  }
2931
+
2932
+
2933
+ .at-iot-tag-row-name {
2934
+ max-width: 100px;
2935
+ white-space: nowrap;
2936
+ overflow: hidden;
2937
+ text-overflow: ellipsis;
2938
+ }
2939
+
2940
+ .at-iot-tag-row-name span {
2941
+ display: block;
2942
+ white-space: nowrap;
2943
+ overflow: hidden;
2944
+ text-overflow: ellipsis;
2945
+ }
2946
+
2947
+ .at_linked_systems_options_contianer label {
2948
+ cursor: pointer;
2949
+ }
2950
+
2951
+ .at_linked_systems_options_contianer input {
2952
+ cursor: pointer;
2953
+ }