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.
- package/lib/actionPartitionHistory.d.ts +17 -0
- package/lib/actionPartitionHistory.js +62 -0
- package/lib/actionPathHistory.js +2 -2
- package/lib/architwin.d.ts +8 -4
- package/lib/architwin.js +1 -1
- package/lib/atwinui/components/toolbar/i18n.js +2 -2
- package/lib/atwinui/components/toolbar/previewModal.js +9 -1
- package/lib/atwinui/components/toolbar/spacePartition/roomFormPane.d.ts +7 -1
- package/lib/atwinui/components/toolbar/spacePartition/roomFormPane.js +64 -27
- package/lib/atwinui/events.js +122 -43
- package/lib/loaders/polydrawerLoader.d.ts +2 -0
- package/lib/loaders/polydrawerLoader.js +75 -9
- package/package.json +1 -1
- package/static/atwinui.css +74 -3
|
@@ -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
|
|
428
|
-
|
|
429
|
-
|
|
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
|
-
|
|
432
|
-
|
|
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
|
-
|
|
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
package/static/atwinui.css
CHANGED
|
@@ -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:
|
|
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:
|
|
1288
|
+
width: 66.5vw;
|
|
1289
1289
|
height: 95vh;
|
|
1290
|
-
max-width:
|
|
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%);
|