@pascal-app/core 1.1.0 → 1.1.2
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/agent-operations/__fixtures__/cases.d.ts +3 -2
- package/dist/agent-operations/__fixtures__/cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/place-items-cases.d.ts.map +1 -1
- package/dist/agent-operations/__fixtures__/place-items-cases.js +28 -0
- package/dist/agent-operations/__fixtures__/roof-bearing-cases.d.ts +2618 -2618
- package/dist/agent-operations/asset-catalog.d.ts +21 -11
- package/dist/agent-operations/asset-catalog.d.ts.map +1 -1
- package/dist/agent-operations/asset-catalog.js +28 -10
- package/dist/agent-operations/asset-views.d.ts +8 -3
- package/dist/agent-operations/asset-views.d.ts.map +1 -1
- package/dist/agent-operations/asset-views.js +19 -3
- package/dist/agent-operations/batch.d.ts +4 -2
- package/dist/agent-operations/batch.d.ts.map +1 -1
- package/dist/agent-operations/batch.js +9 -6
- package/dist/agent-operations/catalog-asset.d.ts +15 -0
- package/dist/agent-operations/catalog-asset.d.ts.map +1 -0
- package/dist/agent-operations/catalog-asset.js +4 -0
- package/dist/agent-operations/circulation-spaces.d.ts +585 -585
- package/dist/agent-operations/design-brief.d.ts.map +1 -1
- package/dist/agent-operations/design-brief.js +2 -0
- package/dist/agent-operations/furnish-room.d.ts.map +1 -1
- package/dist/agent-operations/furnish-room.js +2 -1
- package/dist/agent-operations/index.d.ts +5716 -7
- package/dist/agent-operations/index.d.ts.map +1 -1
- package/dist/agent-operations/index.js +17 -3
- package/dist/agent-operations/level-reads.d.ts.map +1 -1
- package/dist/agent-operations/level-reads.js +4 -1
- package/dist/agent-operations/place-in-room.d.ts.map +1 -1
- package/dist/agent-operations/place-in-room.js +2 -1
- package/dist/agent-operations/place-items.d.ts.map +1 -1
- package/dist/agent-operations/place-items.js +2 -1
- package/dist/agent-operations/scene-queries.d.ts +3818 -3818
- package/dist/agent-operations/scene-view.d.ts.map +1 -1
- package/dist/agent-operations/scene-view.js +38 -13
- package/dist/agent-operations/search-assets.d.ts.map +1 -1
- package/dist/agent-operations/search-assets.js +6 -0
- package/dist/agent-operations/types.d.ts +10 -2
- package/dist/agent-operations/types.d.ts.map +1 -1
- package/dist/agent-operations/usage-checks.js +18 -3
- package/dist/agent-operations/verify-scene.d.ts +7 -3
- package/dist/agent-operations/verify-scene.d.ts.map +1 -1
- package/dist/agent-operations/verify-scene.js +15 -7
- package/dist/agent-tools/assets.js +1 -1
- package/dist/building/__fixtures__/wall-opening-cases.d.ts +30 -30
- package/dist/building/level-duplication.d.ts +3409 -3409
- package/dist/building/level-duplication.d.ts.map +1 -1
- package/dist/building/level-duplication.js +3 -1
- package/dist/building/wall-openings.d.ts +75 -75
- package/dist/commands/structure/shared.d.ts +3407 -3407
- package/dist/commands/structure/zone-wall-merge.d.ts +652 -652
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +3818 -3818
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lib/__fixtures__/mezzanine.d.ts +2003 -2003
- package/dist/lib/absorb-wall-separators.d.ts +1032 -1032
- package/dist/lib/asset-storage.d.ts.map +1 -1
- package/dist/lib/asset-storage.js +3 -0
- package/dist/lib/floor-foundation-datum.d.ts.map +1 -1
- package/dist/lib/floor-foundation-datum.js +5 -1
- package/dist/lib/floorplan/context.d.ts +95 -0
- package/dist/lib/floorplan/context.d.ts.map +1 -0
- package/dist/lib/floorplan/context.js +155 -0
- package/dist/lib/floorplan/index.d.ts +6 -0
- package/dist/lib/floorplan/index.d.ts.map +1 -0
- package/dist/lib/floorplan/index.js +5 -0
- package/dist/lib/floorplan/marks.d.ts +71 -0
- package/dist/lib/floorplan/marks.d.ts.map +1 -0
- package/dist/lib/floorplan/marks.js +157 -0
- package/dist/lib/floorplan/plan-math.d.ts +18 -0
- package/dist/lib/floorplan/plan-math.d.ts.map +1 -0
- package/dist/lib/floorplan/plan-math.js +82 -0
- package/dist/lib/floorplan/svg-paths.d.ts +17 -0
- package/dist/lib/floorplan/svg-paths.d.ts.map +1 -0
- package/dist/lib/floorplan/svg-paths.js +92 -0
- package/dist/lib/floorplan/wall-affordances.d.ts +31 -0
- package/dist/lib/floorplan/wall-affordances.d.ts.map +1 -0
- package/dist/lib/floorplan/wall-affordances.js +24 -0
- package/dist/lib/steps.d.ts +8 -0
- package/dist/lib/steps.d.ts.map +1 -0
- package/dist/lib/steps.js +7 -0
- package/dist/registry/__fixtures__/roof-planes.d.ts +69 -0
- package/dist/registry/__fixtures__/roof-planes.d.ts.map +1 -0
- package/dist/registry/__fixtures__/roof-planes.js +59 -0
- package/dist/registry/index.d.ts +2 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -0
- package/dist/registry/roofs.d.ts +34 -0
- package/dist/registry/roofs.d.ts.map +1 -0
- package/dist/registry/roofs.js +61 -0
- package/dist/registry/types.d.ts +30 -0
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/validate-relations.d.ts +5 -1
- package/dist/registry/validate-relations.d.ts.map +1 -1
- package/dist/registry/validate-relations.js +6 -2
- package/dist/schema/asset-url.d.ts +8 -0
- package/dist/schema/asset-url.d.ts.map +1 -1
- package/dist/schema/asset-url.js +17 -0
- package/dist/schema/nodes/roof.d.ts +1 -1
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +13 -8
- package/dist/schema/types.d.ts +1 -1
- package/dist/services/roof-level.d.ts.map +1 -1
- package/dist/services/roof-level.js +12 -2
- package/dist/services/roof-move.d.ts +4 -2
- package/dist/services/roof-move.d.ts.map +1 -1
- package/dist/services/roof-move.js +21 -9
- package/dist/spatial/usage-field/findings.d.ts +10 -1
- package/dist/spatial/usage-field/findings.d.ts.map +1 -1
- package/dist/spatial/usage-field/findings.js +56 -12
- package/dist/spatial/usage-field/measure.d.ts +3 -1
- package/dist/spatial/usage-field/measure.d.ts.map +1 -1
- package/dist/spatial/usage-field/measure.js +7 -2
- package/dist/spatial/usage-field/path.d.ts.map +1 -1
- package/dist/spatial/usage-field/path.js +28 -18
- package/dist/store/actions/node-actions.d.ts +2380 -2380
- package/dist/store/scene-annotations.d.ts +1279 -1279
- package/dist/systems/document-reconcile.d.ts.map +1 -1
- package/dist/systems/document-reconcile.js +1 -2
- package/dist/systems/roof/roof-elevation.d.ts +11 -6
- package/dist/systems/roof/roof-elevation.d.ts.map +1 -1
- package/dist/systems/roof/roof-elevation.js +24 -11
- package/dist/systems/slab/__fixtures__/floor-step.d.ts +2381 -2381
- package/dist/systems/slab/__fixtures__/raised-room.d.ts +3818 -3818
- package/dist/systems/stair/stair-opening-preview.d.ts +900 -900
- package/dist/utils/ensure-scene-openings.d.ts +4815 -4815
- package/dist/utils/floor-plate-migration.d.ts +1032 -1032
- package/dist/utils/owned-floor-opening-migration.d.ts +1032 -1032
- package/dist/utils/reconcile-structure-on-load.d.ts +2380 -2380
- package/dist/utils/scene-bounds.d.ts +32 -0
- package/dist/utils/scene-bounds.d.ts.map +1 -0
- package/dist/utils/scene-bounds.js +201 -0
- package/package.json +1 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getWallFaceOffsets } from '../../systems/wall/wall-frame.js';
|
|
2
|
+
// Baseline rotation (deg) that orients the plan-local scene "north up" on
|
|
3
|
+
// screen. The on-screen floor-plan scene `<g>` is rotated by
|
|
4
|
+
// `FLOORPLAN_VIEW_ROTATION_DEG + userRotation - buildingRotation`; PDF export
|
|
5
|
+
// uses the same user rotation so its orientation matches the live plan.
|
|
6
|
+
//
|
|
7
|
+
// North is world −Z: with a 0 baseline a rotation-0 reference image (top =
|
|
8
|
+
// −Z) reads upright in the north-aligned view, and "align north" maps to a
|
|
9
|
+
// 3D camera azimuth of 0. The old 90° baseline made north world −X, so
|
|
10
|
+
// north-up floorplan scans displayed sideways whenever the compass claimed
|
|
11
|
+
// the view was aligned.
|
|
12
|
+
export const FLOORPLAN_VIEW_ROTATION_DEG = 0;
|
|
13
|
+
export function clampPlanValue(value, min, max) {
|
|
14
|
+
return Math.min(Math.max(value, min), max);
|
|
15
|
+
}
|
|
16
|
+
export function rotatePlanVector(x, y, rotation) {
|
|
17
|
+
const cos = Math.cos(rotation);
|
|
18
|
+
const sin = Math.sin(rotation);
|
|
19
|
+
return [x * cos + y * sin, -x * sin + y * cos];
|
|
20
|
+
}
|
|
21
|
+
// Converts a world X/Z point into the floor-plan-local (building-local)
|
|
22
|
+
// frame used by the SVG scene `<g>` and every stored node position. The
|
|
23
|
+
// inverse of `floorplanLocalToWorldPoint`. Shared so the floor-plan panel
|
|
24
|
+
// and the 2D move overlay resolve the same frame — feeding a world-space
|
|
25
|
+
// `original` into a local-space cursor solver lands the drop off by the
|
|
26
|
+
// building's world X/Z (worse for an off-origin building).
|
|
27
|
+
export function worldToFloorplanLocalPoint(worldX, worldZ, buildingPosition, buildingRotationY) {
|
|
28
|
+
const dx = worldX - buildingPosition[0];
|
|
29
|
+
const dz = worldZ - buildingPosition[2];
|
|
30
|
+
const cos = Math.cos(buildingRotationY);
|
|
31
|
+
const sin = Math.sin(buildingRotationY);
|
|
32
|
+
return {
|
|
33
|
+
x: dx * cos - dz * sin,
|
|
34
|
+
y: dx * sin + dz * cos,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
// Inverse of `worldToFloorplanLocalPoint`: floor-plan-local X/Y → world X/Z.
|
|
38
|
+
export function floorplanLocalToWorldPoint(point, buildingPosition, buildingRotationY) {
|
|
39
|
+
const localX = Array.isArray(point) ? point[0] : point.x;
|
|
40
|
+
const localY = Array.isArray(point) ? point[1] : point.y;
|
|
41
|
+
const cos = Math.cos(buildingRotationY);
|
|
42
|
+
const sin = Math.sin(buildingRotationY);
|
|
43
|
+
return {
|
|
44
|
+
x: buildingPosition[0] + localX * cos + localY * sin,
|
|
45
|
+
z: buildingPosition[2] - localX * sin + localY * cos,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function interpolatePlanPoint(start, end, t) {
|
|
49
|
+
return {
|
|
50
|
+
x: start.x + (end.x - start.x) * t,
|
|
51
|
+
y: start.y + (end.y - start.y) * t,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export function getPlanPointDistance(start, end) {
|
|
55
|
+
return Math.hypot(end.x - start.x, end.y - start.y);
|
|
56
|
+
}
|
|
57
|
+
export function movePlanPointTowards(start, end, distance) {
|
|
58
|
+
const totalDistance = getPlanPointDistance(start, end);
|
|
59
|
+
if (totalDistance <= Number.EPSILON || distance <= 0) {
|
|
60
|
+
return start;
|
|
61
|
+
}
|
|
62
|
+
return interpolatePlanPoint(start, end, Math.min(1, distance / totalDistance));
|
|
63
|
+
}
|
|
64
|
+
export function getThickPlanLinePolygon(line, thickness, justification) {
|
|
65
|
+
const dx = line.end.x - line.start.x;
|
|
66
|
+
const dy = line.end.y - line.start.y;
|
|
67
|
+
const length = Math.hypot(dx, dy);
|
|
68
|
+
if (length <= Number.EPSILON || thickness <= 0) {
|
|
69
|
+
return [line.start, line.end, line.end, line.start];
|
|
70
|
+
}
|
|
71
|
+
const { a, b } = getWallFaceOffsets({ thickness, justification });
|
|
72
|
+
const normalX = (-dy / length) * a;
|
|
73
|
+
const normalY = (dx / length) * a;
|
|
74
|
+
const backX = (-dy / length) * -b;
|
|
75
|
+
const backY = (dx / length) * -b;
|
|
76
|
+
return [
|
|
77
|
+
{ x: line.start.x + normalX, y: line.start.y + normalY },
|
|
78
|
+
{ x: line.end.x + normalX, y: line.end.y + normalY },
|
|
79
|
+
{ x: line.end.x - backX, y: line.end.y - backY },
|
|
80
|
+
{ x: line.start.x - backX, y: line.start.y - backY },
|
|
81
|
+
];
|
|
82
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Point2D } from '../../systems/wall/wall-mitering.js';
|
|
2
|
+
export declare function formatPolygonPath(points: Point2D[], holes?: Point2D[][]): string;
|
|
3
|
+
export declare function buildSvgPolylinePath(points: Point2D[]): string | null;
|
|
4
|
+
export declare function getArcPlanPoint(center: Point2D, radius: number, angle: number): Point2D;
|
|
5
|
+
export declare function buildSvgArcPath(center: Point2D, radius: number, startAngle: number, endAngle: number): string;
|
|
6
|
+
export declare function buildSvgAnnularSectorPath(center: Point2D, innerRadius: number, outerRadius: number, startAngle: number, endAngle: number): string;
|
|
7
|
+
export declare function formatSvgPolygonPoints(points: Point2D[]): string;
|
|
8
|
+
/**
|
|
9
|
+
* Three points defining an arrow head — tip + two trailing barbs.
|
|
10
|
+
* Returned as plain `Point2D` objects so consumers can either feed them
|
|
11
|
+
* straight into `formatSvgPolygonPoints` (for SVG `points=""`) or push
|
|
12
|
+
* them onto a `FloorplanGeometry.polygon.points` array. Mixing both
|
|
13
|
+
* downstream paths through a string-returning helper was awkward — see
|
|
14
|
+
* `nodes/src/stair/floorplan.ts` which needs the points as objects.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildSvgArrowHeadPoints(point: Point2D, angle: number, size: number): Point2D[];
|
|
17
|
+
//# sourceMappingURL=svg-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"svg-paths.d.ts","sourceRoot":"","sources":["../../../src/lib/floorplan/svg-paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kCAAkC,CAAA;AAiB/D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,KAAK,GAAE,OAAO,EAAE,EAAO,UAoB3E;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,iBAWrD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKvF;AAED,wBAAgB,eAAe,CAC7B,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,UAIjB;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,OAAO,EACf,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,UAWjB;AAWD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,UAEvD;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAW9F"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
function toSvgX(value) {
|
|
2
|
+
return value;
|
|
3
|
+
}
|
|
4
|
+
function toSvgY(value) {
|
|
5
|
+
return value;
|
|
6
|
+
}
|
|
7
|
+
function toSvgPoint(point) {
|
|
8
|
+
return {
|
|
9
|
+
x: toSvgX(point.x),
|
|
10
|
+
y: toSvgY(point.y),
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export function formatPolygonPath(points, holes = []) {
|
|
14
|
+
const formatSubpath = (subpathPoints) => {
|
|
15
|
+
const [firstPoint, ...restPoints] = subpathPoints;
|
|
16
|
+
if (!firstPoint) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const firstSvgPoint = toSvgPoint(firstPoint);
|
|
20
|
+
return [
|
|
21
|
+
`M ${firstSvgPoint.x} ${firstSvgPoint.y}`,
|
|
22
|
+
...restPoints.map((point) => {
|
|
23
|
+
const svgPoint = toSvgPoint(point);
|
|
24
|
+
return `L ${svgPoint.x} ${svgPoint.y}`;
|
|
25
|
+
}),
|
|
26
|
+
'Z',
|
|
27
|
+
].join(' ');
|
|
28
|
+
};
|
|
29
|
+
return [points, ...holes].map(formatSubpath).filter(Boolean).join(' ');
|
|
30
|
+
}
|
|
31
|
+
export function buildSvgPolylinePath(points) {
|
|
32
|
+
if (points.length < 2) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return points
|
|
36
|
+
.map((point, index) => {
|
|
37
|
+
const svgPoint = toSvgPoint(point);
|
|
38
|
+
return `${index === 0 ? 'M' : 'L'} ${svgPoint.x} ${svgPoint.y}`;
|
|
39
|
+
})
|
|
40
|
+
.join(' ');
|
|
41
|
+
}
|
|
42
|
+
export function getArcPlanPoint(center, radius, angle) {
|
|
43
|
+
return {
|
|
44
|
+
x: center.x + Math.cos(angle) * radius,
|
|
45
|
+
y: center.y + Math.sin(angle) * radius,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function buildSvgArcPath(center, radius, startAngle, endAngle) {
|
|
49
|
+
const start = getArcPlanPoint(center, radius, startAngle);
|
|
50
|
+
return `M ${toSvgX(start.x)} ${toSvgY(start.y)} ${svgArcCommands(center, radius, startAngle, endAngle)}`;
|
|
51
|
+
}
|
|
52
|
+
export function buildSvgAnnularSectorPath(center, innerRadius, outerRadius, startAngle, endAngle) {
|
|
53
|
+
const outerStart = getArcPlanPoint(center, outerRadius, startAngle);
|
|
54
|
+
const innerEnd = getArcPlanPoint(center, innerRadius, endAngle);
|
|
55
|
+
return [
|
|
56
|
+
`M ${toSvgX(outerStart.x)} ${toSvgY(outerStart.y)}`,
|
|
57
|
+
svgArcCommands(center, outerRadius, startAngle, endAngle),
|
|
58
|
+
`L ${toSvgX(innerEnd.x)} ${toSvgY(innerEnd.y)}`,
|
|
59
|
+
svgArcCommands(center, innerRadius, endAngle, startAngle),
|
|
60
|
+
'Z',
|
|
61
|
+
].join(' ');
|
|
62
|
+
}
|
|
63
|
+
function svgArcCommands(center, radius, startAngle, endAngle) {
|
|
64
|
+
const delta = endAngle - startAngle;
|
|
65
|
+
const count = Math.max(1, Math.ceil(Math.abs(delta) / Math.PI));
|
|
66
|
+
return Array.from({ length: count }, (_, index) => {
|
|
67
|
+
const end = getArcPlanPoint(center, radius, startAngle + (delta * (index + 1)) / count);
|
|
68
|
+
return `A ${radius} ${radius} 0 0 ${delta >= 0 ? 1 : 0} ${toSvgX(end.x)} ${toSvgY(end.y)}`;
|
|
69
|
+
}).join(' ');
|
|
70
|
+
}
|
|
71
|
+
export function formatSvgPolygonPoints(points) {
|
|
72
|
+
return points.map((point) => `${toSvgX(point.x)},${toSvgY(point.y)}`).join(' ');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Three points defining an arrow head — tip + two trailing barbs.
|
|
76
|
+
* Returned as plain `Point2D` objects so consumers can either feed them
|
|
77
|
+
* straight into `formatSvgPolygonPoints` (for SVG `points=""`) or push
|
|
78
|
+
* them onto a `FloorplanGeometry.polygon.points` array. Mixing both
|
|
79
|
+
* downstream paths through a string-returning helper was awkward — see
|
|
80
|
+
* `nodes/src/stair/floorplan.ts` which needs the points as objects.
|
|
81
|
+
*/
|
|
82
|
+
export function buildSvgArrowHeadPoints(point, angle, size) {
|
|
83
|
+
const left = {
|
|
84
|
+
x: point.x - size * Math.cos(angle - Math.PI / 6),
|
|
85
|
+
y: point.y - size * Math.sin(angle - Math.PI / 6),
|
|
86
|
+
};
|
|
87
|
+
const right = {
|
|
88
|
+
x: point.x - size * Math.cos(angle + Math.PI / 6),
|
|
89
|
+
y: point.y - size * Math.sin(angle + Math.PI / 6),
|
|
90
|
+
};
|
|
91
|
+
return [point, left, right];
|
|
92
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { WallNode } from '../../schema/index.js';
|
|
2
|
+
import type { WallPlanPoint } from '../../systems/wall/wall-move.js';
|
|
3
|
+
/** The floor plan's affordance id for a wall end's pull grip (a `move-arrow`, variant `pull`). */
|
|
4
|
+
export declare const WALL_PULL_AFFORDANCE = "wall-pull";
|
|
5
|
+
/** What a pull grip carries: the wall, and which of its ends it pulls from. */
|
|
6
|
+
export type WallPullGripPayload = {
|
|
7
|
+
wallId: string;
|
|
8
|
+
endpoint: 'start' | 'end';
|
|
9
|
+
};
|
|
10
|
+
/** The grip's tooltip, in both views. */
|
|
11
|
+
export declare const WALL_PULL_GRIP_TITLE = "Drag to draw the next wall";
|
|
12
|
+
/**
|
|
13
|
+
* The pulled end of `wall` and the direction out of it: along the wall for a
|
|
14
|
+
* straight one, along its tangent for a curved one.
|
|
15
|
+
*/
|
|
16
|
+
export declare function wallPullSeed(wall: Pick<WallNode, 'start' | 'end' | 'curveOffset'>, endpoint: 'start' | 'end'): {
|
|
17
|
+
start: WallPlanPoint;
|
|
18
|
+
reference: WallPlanPoint;
|
|
19
|
+
} | null;
|
|
20
|
+
/**
|
|
21
|
+
* The affordance a floor-plan `move-arrow` carries to be a wall push arrow;
|
|
22
|
+
* its payload is a `WallPushArrowPayload`. The editor's floor plan runs its
|
|
23
|
+
* wall push for it instead of a registry affordance session.
|
|
24
|
+
*/
|
|
25
|
+
export declare const WALL_PUSH_AFFORDANCE = "wall-push";
|
|
26
|
+
/** A wall's or an invisible wall's side arrow: `wallId` is either. */
|
|
27
|
+
export type WallPushArrowPayload = {
|
|
28
|
+
wallId: string;
|
|
29
|
+
side: 'a' | 'b';
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=wall-affordances.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wall-affordances.d.ts","sourceRoot":"","sources":["../../../src/lib/floorplan/wall-affordances.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE5C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AAEjE,kGAAkG;AAClG,eAAO,MAAM,oBAAoB,cAAc,CAAA;AAE/C,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAA;CAAE,CAAA;AAE/E,yCAAyC;AACzC,eAAO,MAAM,oBAAoB,+BAA+B,CAAA;AAEhE;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,KAAK,GAAG,aAAa,CAAC,EACrD,QAAQ,EAAE,OAAO,GAAG,KAAK,GACxB;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,aAAa,CAAA;CAAE,GAAG,IAAI,CAQ3D;AAED;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,cAAc,CAAA;AAE/C,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,GAAG,GAAG,GAAG,CAAA;CAAE,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getWallCurveFrameAt } from '../../systems/wall/wall-curve.js';
|
|
2
|
+
/** The floor plan's affordance id for a wall end's pull grip (a `move-arrow`, variant `pull`). */
|
|
3
|
+
export const WALL_PULL_AFFORDANCE = 'wall-pull';
|
|
4
|
+
/** The grip's tooltip, in both views. */
|
|
5
|
+
export const WALL_PULL_GRIP_TITLE = 'Drag to draw the next wall';
|
|
6
|
+
/**
|
|
7
|
+
* The pulled end of `wall` and the direction out of it: along the wall for a
|
|
8
|
+
* straight one, along its tangent for a curved one.
|
|
9
|
+
*/
|
|
10
|
+
export function wallPullSeed(wall, endpoint) {
|
|
11
|
+
const start = endpoint === 'start' ? [wall.start[0], wall.start[1]] : [wall.end[0], wall.end[1]];
|
|
12
|
+
const tangent = getWallCurveFrameAt(wall, endpoint === 'start' ? 0 : 1).tangent;
|
|
13
|
+
const sign = endpoint === 'start' ? -1 : 1;
|
|
14
|
+
const length = Math.hypot(tangent.x, tangent.y);
|
|
15
|
+
if (!(length > 1e-9))
|
|
16
|
+
return null;
|
|
17
|
+
return { start, reference: [(tangent.x / length) * sign, (tangent.y / length) * sign] };
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The affordance a floor-plan `move-arrow` carries to be a wall push arrow;
|
|
21
|
+
* its payload is a `WallPushArrowPayload`. The editor's floor plan runs its
|
|
22
|
+
* wall push for it instead of a registry affordance session.
|
|
23
|
+
*/
|
|
24
|
+
export const WALL_PUSH_AFFORDANCE = 'wall-push';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work in steps: each resume runs the next piece, and the last returns the result. A long
|
|
3
|
+
* computation written this way can be resumed one piece at a time by a caller that lets other work
|
|
4
|
+
* run in between; `inOneGo` runs it through.
|
|
5
|
+
*/
|
|
6
|
+
export type Steps<Result> = Generator<void, Result, void>;
|
|
7
|
+
export declare function inOneGo<Result>(steps: Steps<Result>): Result;
|
|
8
|
+
//# sourceMappingURL=steps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"steps.d.ts","sourceRoot":"","sources":["../../src/lib/steps.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,KAAK,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;AAEzD,wBAAgB,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM,CAK5D"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { AnyNode } from '../../schema/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* A plugin's solved roof plane, as an architect's roof holds it (`capabilities.roofs`): an outline
|
|
5
|
+
* in its roof's plan, rising from a baseline at a pitch (rise per 12 of run).
|
|
6
|
+
*/
|
|
7
|
+
export declare const RoofPlane: z.ZodObject<{
|
|
8
|
+
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
9
|
+
name: z.ZodOptional<z.ZodString>;
|
|
10
|
+
parentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
11
|
+
visible: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
12
|
+
camera: z.ZodOptional<z.ZodObject<{
|
|
13
|
+
position: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
14
|
+
target: z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>;
|
|
15
|
+
mode: z.ZodDefault<z.ZodEnum<{
|
|
16
|
+
orthographic: "orthographic";
|
|
17
|
+
perspective: "perspective";
|
|
18
|
+
}>>;
|
|
19
|
+
fov: z.ZodOptional<z.ZodNumber>;
|
|
20
|
+
zoom: z.ZodOptional<z.ZodNumber>;
|
|
21
|
+
}, z.core.$strip>>;
|
|
22
|
+
metadata: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
23
|
+
provenance: z.ZodOptional<z.ZodObject<{
|
|
24
|
+
refs: z.ZodArray<z.ZodObject<{
|
|
25
|
+
ns: z.ZodOptional<z.ZodString>;
|
|
26
|
+
id: z.ZodString;
|
|
27
|
+
role: z.ZodOptional<z.ZodEnum<{
|
|
28
|
+
absorbed: "absorbed";
|
|
29
|
+
alias: "alias";
|
|
30
|
+
derived: "derived";
|
|
31
|
+
piece: "piece";
|
|
32
|
+
primary: "primary";
|
|
33
|
+
}>>;
|
|
34
|
+
}, z.core.$strip>>;
|
|
35
|
+
lineage: z.ZodOptional<z.ZodObject<{
|
|
36
|
+
op: z.ZodEnum<{
|
|
37
|
+
attach: "attach";
|
|
38
|
+
convert: "convert";
|
|
39
|
+
duplicate: "duplicate";
|
|
40
|
+
import: "import";
|
|
41
|
+
"make-independent": "make-independent";
|
|
42
|
+
merge: "merge";
|
|
43
|
+
promote: "promote";
|
|
44
|
+
split: "split";
|
|
45
|
+
}>;
|
|
46
|
+
fromIds: z.ZodArray<z.ZodString>;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
}, z.core.$strip>>;
|
|
49
|
+
id: z.ZodDefault<z.ZodTemplateLiteral<`roofplane_${string}`>>;
|
|
50
|
+
type: z.ZodDefault<z.ZodLiteral<"test:roof-plane">>;
|
|
51
|
+
polygon: z.ZodArray<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
52
|
+
baseline: z.ZodTuple<[z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>, z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>], null>;
|
|
53
|
+
baseHeight: z.ZodNumber;
|
|
54
|
+
pitch: z.ZodNumber;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
export type RoofPlane = z.infer<typeof RoofPlane>;
|
|
57
|
+
/** The plane's surface over its roof's origin at a plan point: its eave, plus the rise of the run off it. */
|
|
58
|
+
export declare function roofPlaneHeightAt(plane: RoofPlane, x: number, z: number): number;
|
|
59
|
+
/** Registers the planes' kind; the test setup restores the registry after each test. */
|
|
60
|
+
export declare function registerRoofPlanes(): void;
|
|
61
|
+
/**
|
|
62
|
+
* A plane over the plan rectangle [x0, z0] to [x1, z1] of its roof, its eave along z0 at `eave`,
|
|
63
|
+
* rising toward z1 at `pitch` in 12.
|
|
64
|
+
*/
|
|
65
|
+
export declare function roofPlane(id: string, [x0, z0, x1, z1]: [number, number, number, number], eave: number, { pitch, parentId }?: {
|
|
66
|
+
pitch?: number;
|
|
67
|
+
parentId?: string | null;
|
|
68
|
+
}): AnyNode;
|
|
69
|
+
//# sourceMappingURL=roof-planes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roof-planes.d.ts","sourceRoot":"","sources":["../../../src/registry/__fixtures__/roof-planes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA;AAMjD;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAOpB,CAAA;AACF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAA;AAEjD,6GAA6G;AAC7G,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAIhF;AAOD,wFAAwF;AACxF,wBAAgB,kBAAkB,IAAI,IAAI,CASzC;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAClD,IAAI,EAAE,MAAM,EACZ,EAAE,KAAS,EAAE,QAAe,EAAE,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAChF,OAAO,CAiBT"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { BaseNode, nodeType, objectId } from '../../schema/base.js';
|
|
3
|
+
import { registerNode } from '../registry.js';
|
|
4
|
+
const Pt = z.tuple([z.number(), z.number()]);
|
|
5
|
+
/**
|
|
6
|
+
* A plugin's solved roof plane, as an architect's roof holds it (`capabilities.roofs`): an outline
|
|
7
|
+
* in its roof's plan, rising from a baseline at a pitch (rise per 12 of run).
|
|
8
|
+
*/
|
|
9
|
+
export const RoofPlane = BaseNode.extend({
|
|
10
|
+
id: objectId('roofplane'),
|
|
11
|
+
type: nodeType('test:roof-plane'),
|
|
12
|
+
polygon: z.array(Pt),
|
|
13
|
+
baseline: z.tuple([Pt, Pt]),
|
|
14
|
+
baseHeight: z.number(),
|
|
15
|
+
pitch: z.number(),
|
|
16
|
+
});
|
|
17
|
+
/** The plane's surface over its roof's origin at a plan point: its eave, plus the rise of the run off it. */
|
|
18
|
+
export function roofPlaneHeightAt(plane, x, z) {
|
|
19
|
+
const [[ax, az], [bx, bz]] = plane.baseline;
|
|
20
|
+
const run = Math.abs((x - ax) * (bz - az) - (z - az) * (bx - ax)) / Math.hypot(bx - ax, bz - az);
|
|
21
|
+
return plane.baseHeight + (run * plane.pitch) / 12;
|
|
22
|
+
}
|
|
23
|
+
const roofs = {
|
|
24
|
+
outline: (node) => node.polygon,
|
|
25
|
+
heightAt: (node, x, z) => roofPlaneHeightAt(node, x, z),
|
|
26
|
+
};
|
|
27
|
+
/** Registers the planes' kind; the test setup restores the registry after each test. */
|
|
28
|
+
export function registerRoofPlanes() {
|
|
29
|
+
registerNode({
|
|
30
|
+
kind: 'test:roof-plane',
|
|
31
|
+
schemaVersion: 1,
|
|
32
|
+
schema: RoofPlane,
|
|
33
|
+
category: 'structure',
|
|
34
|
+
defaults: () => ({}),
|
|
35
|
+
capabilities: { roofs },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* A plane over the plan rectangle [x0, z0] to [x1, z1] of its roof, its eave along z0 at `eave`,
|
|
40
|
+
* rising toward z1 at `pitch` in 12.
|
|
41
|
+
*/
|
|
42
|
+
export function roofPlane(id, [x0, z0, x1, z1], eave, { pitch = 6, parentId = null } = {}) {
|
|
43
|
+
return RoofPlane.parse({
|
|
44
|
+
id,
|
|
45
|
+
parentId,
|
|
46
|
+
polygon: [
|
|
47
|
+
[x0, z0],
|
|
48
|
+
[x1, z0],
|
|
49
|
+
[x1, z1],
|
|
50
|
+
[x0, z1],
|
|
51
|
+
],
|
|
52
|
+
baseline: [
|
|
53
|
+
[x0, z0],
|
|
54
|
+
[x1, z0],
|
|
55
|
+
],
|
|
56
|
+
baseHeight: eave,
|
|
57
|
+
pitch,
|
|
58
|
+
});
|
|
59
|
+
}
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -2,8 +2,9 @@ export type { ArcResizeHandle, CornerRadiusHandle, Cursor, EditorApi, EndpointMo
|
|
|
2
2
|
export { nodeMechanism, nodeMechanismParts, toggleMechanism, toggleMechanismPart, toggleNodeMechanism, } from './mechanism.js';
|
|
3
3
|
export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeDuplicable, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, type PluginDiscovery, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
|
|
4
4
|
export { type CascadeContext, type ChildQuery, cascadeDirty, collectDescendants, type SpatialQuery, } from './relations-resolver.js';
|
|
5
|
+
export { type RoofFaceShape, roofFaceOf, roofFaceShapes, validateRoofRelations } from './roofs.js';
|
|
5
6
|
export { createSceneApi, type SceneStoreLike, type SceneToolHost } from './scene-api.js';
|
|
6
7
|
export { type CloneNodesIntoOptions, type CloneNodesIntoResult, cloneNodesInto, collectSubtree, type Subtree, withoutSourceIdentity, } from './subtree.js';
|
|
7
|
-
export type { Affordance, AlignmentFootprint, AlignmentFootprintConfig, AnyNodeDefinition, AssemblyHostConfig, AssemblyReference, AssetRef, BakeGeometryAsyncBuilder, BakeGeometryBuilder, BakePolicy, BakeReplaceRenderer, BatchableConfig, Capabilities, CapabilityCtx, CutsContext, CuttableConfig, DimensionTerminator, DimensionTextPosition, DistributionRole, DragAction, DuplicableConfig, DuplicateSubtreeCloneArgs, DuplicateSubtreeCloneResult, EditorCtx, EvaluationContext, ExportAnimationContext, ExportProfile, FaceHostCapability, FaceHostPlacementArgs, FaceHostPlacementResult, FaceHostStoredPlacementArgs, FaceHostStoredValidityArgs, FloorPlacedConfig, FloorPlacedFootprint, FloorPlacedFootprintContext, FloorPlacedFootprintResolver, FloorPlacedFootprintsResolver, FloorplanAffordance, FloorplanAffordanceModifiers, FloorplanAffordancePoint, FloorplanAffordanceSession, FloorplanGeometry, FloorplanMoveTarget, FloorplanMoveTargetSession, FloorplanPalette, FloorplanPoint, FloorplanScope, FloorplanStyle, GeometryContext, GridSnapPositionArgs, GroupMoveSnapArgs, GroupMoveSnapResult, HostableConfig, IconRef, InspectorExtension, Issue, KeyboardAction, KeyboardActions, LazyComponent, LiveTransformLike, McpOverrides, MeasurementContribution, MeasurementFeature, MeasurementFeatureBinding, MeasurementFeatureGeometry, MeasurementSnapKind, MechanismCapability, MechanismPart, Modifiers, MovableConfig, MovableParentFrame, NodeCategory, NodeDefinition, NodePort, NodeQuickAction, NodeQuickActionIcon, NodeQuickActionNodeScope, NodeQuickActionProvider, NodeQuickActionResult, NodeRegistry, PaintCapability, PaintEffectiveMaterialArgs, PaintPatchArgs, PaintPreviewArgs, PaintResolveArgs, PaintScopeId, PaintSurfaceScopes, ParamAction, ParametricDescriptor, ParamField, ParamGroup, ParentFrameSnapMatch, PascalBakeExtras, PascalPartTag, PlacementNotice, Plugin, PortRef, Presentation, QuickMeasurementMetric, QuickMeasurementQuantity, QuickMeasurementReport, ReferenceDeclaration, ReferenceDeletePolicy, ReferenceNamespace, ReferencePath, ReferencePresetPolicy, ReferenceRole, Relations, RendererSource, RevealClears, RevealConfig, RevealLayout, RevealPhase, RevealPlanPoint, RevealStyle, RoofAccessoryConfig, RotatableConfig, ScalableConfig, SceneActionCapability, SceneApi, SelectableConfig, SlotDeclaration, SnapPointKind, SnapProfile, SnappableConfig, SnapServicesLike, SurfacePoint, SurfaceQuery, SurfaceRole, SurfacesConfig, SystemContribution, ToolHint, ToolHintChip, ToolOption, ToolOptionChoice, Vec2, } from './types.js';
|
|
8
|
+
export type { Affordance, AlignmentFootprint, AlignmentFootprintConfig, AnyNodeDefinition, AssemblyHostConfig, AssemblyReference, AssetRef, BakeGeometryAsyncBuilder, BakeGeometryBuilder, BakePolicy, BakeReplaceRenderer, BatchableConfig, Capabilities, CapabilityCtx, CutsContext, CuttableConfig, DimensionTerminator, DimensionTextPosition, DistributionRole, DragAction, DuplicableConfig, DuplicateSubtreeCloneArgs, DuplicateSubtreeCloneResult, EditorCtx, EvaluationContext, ExportAnimationContext, ExportProfile, FaceHostCapability, FaceHostPlacementArgs, FaceHostPlacementResult, FaceHostStoredPlacementArgs, FaceHostStoredValidityArgs, FloorPlacedConfig, FloorPlacedFootprint, FloorPlacedFootprintContext, FloorPlacedFootprintResolver, FloorPlacedFootprintsResolver, FloorplanAffordance, FloorplanAffordanceModifiers, FloorplanAffordancePoint, FloorplanAffordanceSession, FloorplanGeometry, FloorplanMoveTarget, FloorplanMoveTargetSession, FloorplanPalette, FloorplanPoint, FloorplanScope, FloorplanStyle, GeometryContext, GridSnapPositionArgs, GroupMoveSnapArgs, GroupMoveSnapResult, HostableConfig, IconRef, InspectorExtension, Issue, KeyboardAction, KeyboardActions, LazyComponent, LiveTransformLike, McpOverrides, MeasurementContribution, MeasurementFeature, MeasurementFeatureBinding, MeasurementFeatureGeometry, MeasurementSnapKind, MechanismCapability, MechanismPart, Modifiers, MovableConfig, MovableParentFrame, NodeCategory, NodeDefinition, NodePort, NodeQuickAction, NodeQuickActionIcon, NodeQuickActionNodeScope, NodeQuickActionProvider, NodeQuickActionResult, NodeRegistry, PaintCapability, PaintEffectiveMaterialArgs, PaintPatchArgs, PaintPreviewArgs, PaintResolveArgs, PaintScopeId, PaintSurfaceScopes, ParamAction, ParametricDescriptor, ParamField, ParamGroup, ParentFrameSnapMatch, PascalBakeExtras, PascalPartTag, PlacementNotice, Plugin, PortRef, Presentation, QuickMeasurementMetric, QuickMeasurementQuantity, QuickMeasurementReport, ReferenceDeclaration, ReferenceDeletePolicy, ReferenceNamespace, ReferencePath, ReferencePresetPolicy, ReferenceRole, Relations, RendererSource, RevealClears, RevealConfig, RevealLayout, RevealPhase, RevealPlanPoint, RevealStyle, RoofAccessoryConfig, RoofsCapability, RotatableConfig, ScalableConfig, SceneActionCapability, SceneApi, SelectableConfig, SlotDeclaration, SnapPointKind, SnapProfile, SnappableConfig, SnapServicesLike, SurfacePoint, SurfaceQuery, SurfaceRole, SurfacesConfig, SystemContribution, ToolHint, ToolHintChip, ToolOption, ToolOptionChoice, Vec2, } from './types.js';
|
|
8
9
|
export { validateNodeRelations } from './validate-relations.js';
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/registry/index.ts"],"names":[],"mappings":"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"}
|
package/dist/registry/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { nodeMechanism, nodeMechanismParts, toggleMechanism, toggleMechanismPart, toggleNodeMechanism, } from './mechanism.js';
|
|
2
2
|
export { bakePolicyOf, discoverPlugins, extendPluginDiscovery, floorPlacedCollides, getHostRefFields, getInspectorExtensions, getNodePluginId, getRegistryVersion, getSelectableKinds, hasRegistry3DMoveTool, isDrawnViaTool, isDrawnViaToolKind, isNodeDuplicable, isNodeKindEnabled, isPresettable, isPresettableKind, isRegistryMovable, isRegistrySelectable, isSelectionHighlightEnabled, kindsWithBakePolicy, kindsWithFloorplanScope, loadPlugin, nodeRegistry, onRegistryChange, registerNode, resolveFacingIndicator, setPluginDiscovery, } from './registry.js';
|
|
3
3
|
export { cascadeDirty, collectDescendants, } from './relations-resolver.js';
|
|
4
|
+
export { roofFaceOf, roofFaceShapes, validateRoofRelations } from './roofs.js';
|
|
4
5
|
export { createSceneApi } from './scene-api.js';
|
|
5
6
|
export { cloneNodesInto, collectSubtree, withoutSourceIdentity, } from './subtree.js';
|
|
6
7
|
export { validateNodeRelations } from './validate-relations.js';
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { AnyNode, RoofNode } from '../schema/index.js';
|
|
2
|
+
import type { RoofsCapability } from './types.js';
|
|
3
|
+
type Nodes = Readonly<Record<string, AnyNode | undefined>>;
|
|
4
|
+
type Pt = [number, number];
|
|
5
|
+
/**
|
|
6
|
+
* The node's `roofs` capability, when its kind declares one: the node is a face of the roof holding
|
|
7
|
+
* it. Undefined for a roof's segments, which are its masses, and for kinds this runtime has not
|
|
8
|
+
* registered.
|
|
9
|
+
*/
|
|
10
|
+
export declare function roofFaceOf(node: AnyNode | undefined): RoofsCapability | undefined;
|
|
11
|
+
/** A face of a roof in the frame of what holds the roof: its level's metres. */
|
|
12
|
+
export type RoofFaceShape = {
|
|
13
|
+
id: string;
|
|
14
|
+
/** The face's outline in that plan, `[x, z]` corners. */
|
|
15
|
+
outline: Pt[];
|
|
16
|
+
/** Its surface at its lowest corner (the eave) and at its highest, over that frame's floor. */
|
|
17
|
+
low: number;
|
|
18
|
+
high: number;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* A roof's faces (`capabilities.roofs`), in `children` order, each in the plan and heights of what
|
|
22
|
+
* holds the roof: the roof's turn and position applied to the face's own frame. A face of a kind
|
|
23
|
+
* this runtime has not registered, or one with no area, is not read.
|
|
24
|
+
*/
|
|
25
|
+
export declare function roofFaceShapes(roof: RoofNode, nodes: Nodes): RoofFaceShape[];
|
|
26
|
+
/**
|
|
27
|
+
* A roof holds its segments and faces of other kinds (`capabilities.roofs`), nothing else: a child
|
|
28
|
+
* a write adds to it, of a registered kind that is neither, is refused. What it held before stays,
|
|
29
|
+
* so a roof saved before the rule still edits, and so does a kind this runtime has not registered
|
|
30
|
+
* (a plugin loaded elsewhere).
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateRoofRelations(roof: AnyNode, nodes: Nodes, before?: Nodes): void;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=roofs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roofs.d.ts","sourceRoot":"","sources":["../../src/registry/roofs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAElD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,KAAK,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC,CAAC,CAAA;AAC1D,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;AAE1B;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,eAAe,GAAG,SAAS,CAEjF;AAED,gFAAgF;AAChF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,yDAAyD;IACzD,OAAO,EAAE,EAAE,EAAE,CAAA;IACb,+FAA+F;IAC/F,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,GAAG,aAAa,EAAE,CA0B5E;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,CAavF"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { nodeRegistry } from './registry.js';
|
|
2
|
+
/**
|
|
3
|
+
* The node's `roofs` capability, when its kind declares one: the node is a face of the roof holding
|
|
4
|
+
* it. Undefined for a roof's segments, which are its masses, and for kinds this runtime has not
|
|
5
|
+
* registered.
|
|
6
|
+
*/
|
|
7
|
+
export function roofFaceOf(node) {
|
|
8
|
+
return node ? nodeRegistry.get(node.type)?.capabilities.roofs : undefined;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A roof's faces (`capabilities.roofs`), in `children` order, each in the plan and heights of what
|
|
12
|
+
* holds the roof: the roof's turn and position applied to the face's own frame. A face of a kind
|
|
13
|
+
* this runtime has not registered, or one with no area, is not read.
|
|
14
|
+
*/
|
|
15
|
+
export function roofFaceShapes(roof, nodes) {
|
|
16
|
+
// The roof's turn about +Y, as three.js turns its group: local +z toward +x.
|
|
17
|
+
const cos = Math.cos(roof.rotation ?? 0);
|
|
18
|
+
const sin = Math.sin(roof.rotation ?? 0);
|
|
19
|
+
const [x0, y0, z0] = roof.position;
|
|
20
|
+
return (roof.children ?? []).flatMap((id) => {
|
|
21
|
+
const face = nodes[id];
|
|
22
|
+
const roofs = roofFaceOf(face);
|
|
23
|
+
if (!(face && roofs))
|
|
24
|
+
return [];
|
|
25
|
+
const corners = roofs.outline(face);
|
|
26
|
+
const heights = corners.map(([x, z]) => roofs.heightAt(face, x, z));
|
|
27
|
+
if (corners.length < 3 ||
|
|
28
|
+
!corners.every(([x, z]) => Number.isFinite(x) && Number.isFinite(z)) ||
|
|
29
|
+
!heights.every(Number.isFinite))
|
|
30
|
+
return [];
|
|
31
|
+
return [
|
|
32
|
+
{
|
|
33
|
+
id: face.id,
|
|
34
|
+
outline: corners.map(([x, z]) => [x0 + x * cos + z * sin, z0 - x * sin + z * cos]),
|
|
35
|
+
low: y0 + Math.min(...heights),
|
|
36
|
+
high: y0 + Math.max(...heights),
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A roof holds its segments and faces of other kinds (`capabilities.roofs`), nothing else: a child
|
|
43
|
+
* a write adds to it, of a registered kind that is neither, is refused. What it held before stays,
|
|
44
|
+
* so a roof saved before the rule still edits, and so does a kind this runtime has not registered
|
|
45
|
+
* (a plugin loaded elsewhere).
|
|
46
|
+
*/
|
|
47
|
+
export function validateRoofRelations(roof, nodes, before) {
|
|
48
|
+
if (roof.type !== 'roof')
|
|
49
|
+
return;
|
|
50
|
+
const prior = before?.[roof.id];
|
|
51
|
+
const held = new Set(prior?.type === 'roof' ? (prior.children ?? []) : []);
|
|
52
|
+
for (const id of roof.children ?? []) {
|
|
53
|
+
const child = nodes[id];
|
|
54
|
+
if (!child || held.has(id) || child.type === 'roof-segment')
|
|
55
|
+
continue;
|
|
56
|
+
const definition = nodeRegistry.get(child.type);
|
|
57
|
+
if (!definition || definition.capabilities.roofs)
|
|
58
|
+
continue;
|
|
59
|
+
throw new Error(`roof ${roof.id} holds its segments and faces of kinds that roof (capabilities.roofs): ${child.type} ${id} is neither.`);
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/registry/types.d.ts
CHANGED
|
@@ -1165,6 +1165,12 @@ export type NodeDefinition<S extends ZodObject<any>> = {
|
|
|
1165
1165
|
* into the active building's plan coordinates below level architecture.
|
|
1166
1166
|
*/
|
|
1167
1167
|
floorplanScope?: FloorplanScope;
|
|
1168
|
+
/**
|
|
1169
|
+
* Levels other than its own whose plans also draw this node: a stair that
|
|
1170
|
+
* climbs to an upper floor shows on that floor's plan too. The plan builds
|
|
1171
|
+
* it with `ctx.parent` set to the drawn level.
|
|
1172
|
+
*/
|
|
1173
|
+
floorplanLinkedLevelIds?: (node: z.infer<S>) => readonly AnyNodeId[];
|
|
1168
1174
|
/**
|
|
1169
1175
|
* 2D drag affordances keyed by the string identifier emitted on
|
|
1170
1176
|
* `endpoint-handle` (and similar interactive floor-plan primitives) via
|
|
@@ -1675,6 +1681,15 @@ export type Capabilities = {
|
|
|
1675
1681
|
centerY?: number;
|
|
1676
1682
|
};
|
|
1677
1683
|
roofAccessory?: RoofAccessoryConfig;
|
|
1684
|
+
/**
|
|
1685
|
+
* The kind roofs: a node of it is one face of the roof that holds it (a plugin's solved roof
|
|
1686
|
+
* plane), as a segment is one of the roof's masses. A roof lists it in `children` beside its
|
|
1687
|
+
* segments and renders it through the kind's own renderer under the roof's transform, so hiding,
|
|
1688
|
+
* selecting or deleting the roof takes its faces with it; the readers of a roof's extent and
|
|
1689
|
+
* heights (the storey it covers, the walls it stands on, a view's frame) count it through
|
|
1690
|
+
* `outline` and `heightAt`. See `RoofsCapability`.
|
|
1691
|
+
*/
|
|
1692
|
+
roofs?: RoofsCapability;
|
|
1678
1693
|
/**
|
|
1679
1694
|
* Kind cuts a hole in the ceiling surface it is attached to (e.g. recessed
|
|
1680
1695
|
* downlights). The viewer's `CeilingSystem` calls this for each child of a
|
|
@@ -2082,6 +2097,21 @@ export type RoofAccessoryConfig = {
|
|
|
2082
2097
|
*/
|
|
2083
2098
|
dirtyHandledByOwnSystem?: boolean;
|
|
2084
2099
|
};
|
|
2100
|
+
/**
|
|
2101
|
+
* One face of the roof holding the node, in that roof's frame: metres, `[x, z]` in its plan and
|
|
2102
|
+
* heights up from its origin. A roof standing unturned at its level's origin holds its faces in
|
|
2103
|
+
* the level's frame.
|
|
2104
|
+
*/
|
|
2105
|
+
export type RoofsCapability = {
|
|
2106
|
+
/** The face's outline in its roof's plan, corners in order. */
|
|
2107
|
+
outline: (node: AnyNode) => readonly (readonly [x: number, z: number])[];
|
|
2108
|
+
/**
|
|
2109
|
+
* The height of the face's top surface over its roof's origin at a point of its outline. Readers
|
|
2110
|
+
* take a face's lowest and highest points at the outline's corners, so a curved face gives an
|
|
2111
|
+
* outline dense enough to hold them.
|
|
2112
|
+
*/
|
|
2113
|
+
heightAt: (node: AnyNode, x: number, z: number) => number;
|
|
2114
|
+
};
|
|
2085
2115
|
/**
|
|
2086
2116
|
* Capability for kinds that cut a hole in their host ceiling when the node is
|
|
2087
2117
|
* attached to a ceiling surface (e.g. recessed downlights). The viewer's
|