@pascal-app/core 1.0.0 → 1.0.3
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/capture/index.d.ts +2 -2
- package/dist/capture/index.js +2 -2
- package/dist/capture/schema.d.ts.map +1 -1
- package/dist/capture/schema.js +2 -0
- package/dist/capture/source.d.ts +1 -1
- package/dist/capture/source.js +1 -1
- package/dist/events/bus.d.ts +6 -3
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +263 -84
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +77 -13
- package/dist/hooks/spatial-grid/support-host-patch.d.ts +1 -1
- package/dist/hooks/spatial-grid/support-host-patch.js +6 -6
- package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
- package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
- package/dist/index.d.ts +77 -72
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -69
- package/dist/lib/door-operation.d.ts +1 -1
- package/dist/lib/item-polygon-overlap.d.ts +6 -0
- package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
- package/dist/lib/item-polygon-overlap.js +67 -0
- package/dist/lib/level-name.d.ts +1 -1
- package/dist/lib/measurement-geometry.d.ts +4 -4
- package/dist/lib/node-visibility.d.ts +12 -0
- package/dist/lib/node-visibility.d.ts.map +1 -0
- package/dist/lib/node-visibility.js +12 -0
- package/dist/lib/plan-footprint.d.ts +41 -0
- package/dist/lib/plan-footprint.d.ts.map +1 -0
- package/dist/lib/plan-footprint.js +58 -0
- package/dist/lib/room-topology-index.d.ts +1 -1
- package/dist/lib/room-topology-index.js +1 -1
- package/dist/lib/selection-proxy.d.ts +1 -1
- package/dist/lib/slab-polygon.d.ts +2 -2
- package/dist/lib/slab-polygon.js +2 -2
- package/dist/lib/space-detection.d.ts +1 -1
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +16 -11
- package/dist/lib/terrain-brush.d.ts +1 -1
- package/dist/lib/terrain-brush.js +1 -1
- package/dist/lib/terrain-codec.d.ts +2 -2
- package/dist/lib/terrain-codec.js +1 -1
- package/dist/lib/terrain-raycast.d.ts +1 -1
- package/dist/lib/terrain-raycast.js +1 -1
- package/dist/lib/terrain-source.d.ts +3 -3
- package/dist/lib/terrain-source.js +3 -3
- package/dist/lib/terrain-support.d.ts +1 -1
- package/dist/lib/terrain-support.js +3 -3
- package/dist/lib/unit-containment.d.ts +19 -0
- package/dist/lib/unit-containment.d.ts.map +1 -0
- package/dist/lib/unit-containment.js +158 -0
- package/dist/lib/unit-report.d.ts +19 -0
- package/dist/lib/unit-report.d.ts.map +1 -0
- package/dist/lib/unit-report.js +36 -0
- package/dist/lib/wall-distance.d.ts +2 -2
- package/dist/lib/wall-distance.js +1 -1
- package/dist/lib/zone-quantities.d.ts +1 -1
- package/dist/lib/zone-quantities.js +7 -7
- package/dist/material-library.d.ts +1 -1
- package/dist/material-library.js +1 -1
- package/dist/procedural-items/fixtures.d.ts +261 -0
- package/dist/procedural-items/fixtures.d.ts.map +1 -0
- package/dist/procedural-items/fixtures.js +349 -0
- package/dist/procedural-items/index.d.ts +10 -0
- package/dist/procedural-items/index.d.ts.map +1 -0
- package/dist/procedural-items/index.js +9 -0
- package/dist/procedural-items/integration.d.ts +92 -0
- package/dist/procedural-items/integration.d.ts.map +1 -0
- package/dist/procedural-items/integration.js +19 -0
- package/dist/procedural-items/library-colors.d.ts +56 -0
- package/dist/procedural-items/library-colors.d.ts.map +1 -0
- package/dist/procedural-items/library-colors.js +84 -0
- package/dist/procedural-items/materials.d.ts +5 -0
- package/dist/procedural-items/materials.d.ts.map +1 -0
- package/dist/procedural-items/materials.js +47 -0
- package/dist/procedural-items/node.d.ts +280 -0
- package/dist/procedural-items/node.d.ts.map +1 -0
- package/dist/procedural-items/node.js +71 -0
- package/dist/procedural-items/placement.d.ts +7 -0
- package/dist/procedural-items/placement.d.ts.map +1 -0
- package/dist/procedural-items/placement.js +48 -0
- package/dist/procedural-items/query.d.ts +51 -0
- package/dist/procedural-items/query.d.ts.map +1 -0
- package/dist/procedural-items/query.js +342 -0
- package/dist/procedural-items/recipe.d.ts +144 -0
- package/dist/procedural-items/recipe.d.ts.map +1 -0
- package/dist/procedural-items/recipe.js +372 -0
- package/dist/procedural-items/spatial.d.ts +19 -0
- package/dist/procedural-items/spatial.d.ts.map +1 -0
- package/dist/procedural-items/spatial.js +39 -0
- package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
- package/dist/registry/handles.d.ts +40 -5
- package/dist/registry/handles.d.ts.map +1 -1
- package/dist/registry/index.d.ts +6 -6
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +4 -4
- package/dist/registry/registry.d.ts +1 -1
- package/dist/registry/relations-resolver.d.ts +2 -2
- package/dist/registry/relations-resolver.js +1 -1
- package/dist/registry/scene-api.d.ts +2 -2
- package/dist/registry/scene-api.js +2 -2
- package/dist/registry/subtree.d.ts +1 -1
- package/dist/registry/subtree.d.ts.map +1 -1
- package/dist/registry/subtree.js +8 -2
- package/dist/registry/types.d.ts +32 -10
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/use-registry-version.js +1 -1
- package/dist/registry/validate-relations.d.ts +4 -0
- package/dist/registry/validate-relations.d.ts.map +1 -0
- package/dist/registry/validate-relations.js +22 -0
- package/dist/schema/__bench__/node-parsers.bench.js +3 -3
- package/dist/schema/__fixtures__/node-fixtures.d.ts +1 -1
- package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -1
- package/dist/schema/__fixtures__/node-fixtures.js +4 -2
- package/dist/schema/base.js +1 -1
- package/dist/schema/collections.d.ts +1 -1
- package/dist/schema/collections.js +1 -1
- package/dist/schema/compiled-node-parsers.d.ts +1 -1
- package/dist/schema/compiled-node-parsers.js +1 -1
- package/dist/schema/index.d.ts +74 -70
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +65 -61
- package/dist/schema/material.d.ts +1 -1
- package/dist/schema/material.js +1 -1
- package/dist/schema/nodes/automatic-downspout.d.ts +4 -4
- package/dist/schema/nodes/automatic-downspout.js +5 -5
- package/dist/schema/nodes/block.d.ts +3 -3
- package/dist/schema/nodes/block.d.ts.map +1 -1
- package/dist/schema/nodes/block.js +24 -12
- package/dist/schema/nodes/box-vent.js +2 -2
- package/dist/schema/nodes/building.d.ts +1 -1
- package/dist/schema/nodes/building.d.ts.map +1 -1
- package/dist/schema/nodes/building.js +8 -5
- package/dist/schema/nodes/cabinet.d.ts +4 -4
- package/dist/schema/nodes/cabinet.js +4 -4
- package/dist/schema/nodes/ceiling.d.ts +1 -1
- package/dist/schema/nodes/ceiling.js +5 -5
- package/dist/schema/nodes/chimney.js +2 -2
- package/dist/schema/nodes/column.d.ts +1 -0
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +3 -2
- package/dist/schema/nodes/construction-dimension.d.ts +3 -3
- package/dist/schema/nodes/construction-dimension.js +2 -2
- package/dist/schema/nodes/cupola.d.ts +1 -1
- package/dist/schema/nodes/cupola.js +2 -2
- package/dist/schema/nodes/curtain-wall.d.ts +129 -0
- package/dist/schema/nodes/curtain-wall.d.ts.map +1 -0
- package/dist/schema/nodes/curtain-wall.js +49 -0
- package/dist/schema/nodes/door.d.ts +2 -2
- package/dist/schema/nodes/door.js +2 -2
- package/dist/schema/nodes/dormer.d.ts +3 -3
- package/dist/schema/nodes/dormer.js +4 -4
- package/dist/schema/nodes/downspout.js +2 -2
- package/dist/schema/nodes/duct-fitting.js +1 -1
- package/dist/schema/nodes/duct-segment.js +2 -2
- package/dist/schema/nodes/duct-terminal.js +1 -1
- package/dist/schema/nodes/elevator.js +2 -2
- package/dist/schema/nodes/eyebrow-vent.js +2 -2
- package/dist/schema/nodes/fence.js +2 -2
- package/dist/schema/nodes/guide.js +2 -2
- package/dist/schema/nodes/gutter.d.ts +1 -1
- package/dist/schema/nodes/gutter.js +4 -4
- package/dist/schema/nodes/hvac-equipment.js +1 -1
- package/dist/schema/nodes/imported-mesh.d.ts +40 -0
- package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
- package/dist/schema/nodes/imported-mesh.js +27 -0
- package/dist/schema/nodes/item.d.ts +3 -3
- package/dist/schema/nodes/item.js +3 -3
- package/dist/schema/nodes/lean-to-extension.js +4 -4
- package/dist/schema/nodes/level.d.ts +1 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +1 -1
- package/dist/schema/nodes/lineset.js +1 -1
- package/dist/schema/nodes/liquid-line.js +1 -1
- package/dist/schema/nodes/measurement.js +2 -2
- package/dist/schema/nodes/pipe-fitting.d.ts +1 -1
- package/dist/schema/nodes/pipe-fitting.js +1 -1
- package/dist/schema/nodes/pipe-segment.d.ts +1 -1
- package/dist/schema/nodes/pipe-segment.js +2 -2
- package/dist/schema/nodes/pipe-trap.d.ts +1 -1
- package/dist/schema/nodes/pipe-trap.js +1 -1
- package/dist/schema/nodes/ridge-vent.d.ts +1 -1
- package/dist/schema/nodes/ridge-vent.js +3 -3
- package/dist/schema/nodes/roof-segment-shape.d.ts +1 -1
- package/dist/schema/nodes/roof-segment-shape.js +1 -1
- package/dist/schema/nodes/roof-segment-walls.d.ts +1 -1
- package/dist/schema/nodes/roof-segment-walls.js +1 -1
- package/dist/schema/nodes/roof-segment.d.ts +2 -2
- package/dist/schema/nodes/roof-segment.js +2 -2
- package/dist/schema/nodes/roof.d.ts +1 -1
- package/dist/schema/nodes/roof.js +3 -3
- package/dist/schema/nodes/scan.js +3 -3
- package/dist/schema/nodes/shelf.d.ts +1 -1
- package/dist/schema/nodes/shelf.d.ts.map +1 -1
- package/dist/schema/nodes/shelf.js +3 -4
- package/dist/schema/nodes/site.js +2 -2
- package/dist/schema/nodes/skylight.d.ts +4 -4
- package/dist/schema/nodes/skylight.js +2 -2
- package/dist/schema/nodes/slab.js +3 -3
- package/dist/schema/nodes/solar-panel.js +3 -3
- package/dist/schema/nodes/spawn.js +1 -1
- package/dist/schema/nodes/stair-segment.js +2 -2
- package/dist/schema/nodes/stair.d.ts +1 -1
- package/dist/schema/nodes/stair.js +3 -3
- package/dist/schema/nodes/structural-grid.js +1 -1
- package/dist/schema/nodes/turbine-vent.d.ts +1 -1
- package/dist/schema/nodes/turbine-vent.js +2 -2
- package/dist/schema/nodes/unit.d.ts +33 -0
- package/dist/schema/nodes/unit.d.ts.map +1 -0
- package/dist/schema/nodes/unit.js +13 -0
- package/dist/schema/nodes/wall.d.ts +75 -2
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +10 -6
- package/dist/schema/nodes/window.js +2 -2
- package/dist/schema/nodes/zone.js +1 -1
- package/dist/schema/scene-material.js +2 -2
- package/dist/schema/types.d.ts +417 -22
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +56 -49
- package/dist/services/__fixtures__/hosting.d.ts +3 -0
- package/dist/services/__fixtures__/hosting.d.ts.map +1 -0
- package/dist/services/__fixtures__/hosting.js +9 -0
- package/dist/services/__fixtures__/shelf-surface-rows.d.ts +4 -0
- package/dist/services/__fixtures__/shelf-surface-rows.d.ts.map +1 -0
- package/dist/services/__fixtures__/shelf-surface-rows.js +18 -0
- package/dist/services/alignment-anchors.d.ts +6 -11
- package/dist/services/alignment-anchors.d.ts.map +1 -1
- package/dist/services/alignment-anchors.js +7 -34
- package/dist/services/drag-session.d.ts +4 -4
- package/dist/services/drag-session.js +1 -1
- package/dist/services/hosting.d.ts +5 -8
- package/dist/services/hosting.d.ts.map +1 -1
- package/dist/services/hosting.js +25 -18
- package/dist/services/index.d.ts +16 -13
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +16 -13
- package/dist/services/level-height.d.ts +2 -2
- package/dist/services/level-height.js +3 -3
- package/dist/services/movement.d.ts +3 -3
- package/dist/services/movement.js +2 -2
- package/dist/services/port-connectivity.d.ts +1 -1
- package/dist/services/port-connectivity.js +1 -1
- package/dist/services/riser-diagram.d.ts +1 -1
- package/dist/services/shelf-board.d.ts +5 -0
- package/dist/services/shelf-board.d.ts.map +1 -0
- package/dist/services/shelf-board.js +15 -0
- package/dist/services/snap.d.ts +3 -0
- package/dist/services/snap.d.ts.map +1 -1
- package/dist/services/snap.js +11 -0
- package/dist/services/storey.d.ts +2 -2
- package/dist/services/storey.js +2 -2
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
- package/dist/services/surface-hosting.d.ts +92 -0
- package/dist/services/surface-hosting.d.ts.map +1 -0
- package/dist/services/surface-hosting.js +305 -0
- package/dist/services/surface-region.d.ts +8 -0
- package/dist/services/surface-region.d.ts.map +1 -0
- package/dist/services/surface-region.js +44 -0
- package/dist/services/system-graph.d.ts +2 -2
- package/dist/services/system-graph.js +2 -2
- package/dist/services/validate-dwv.d.ts +1 -1
- package/dist/services/validate-dwv.js +1 -1
- package/dist/store/actions/node-actions.d.ts +2 -2
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +50 -104
- package/dist/store/history-control.d.ts +3 -3
- package/dist/store/history-invalidation.d.ts +1 -1
- package/dist/store/history-invalidation.js +1 -1
- package/dist/store/use-interactive.d.ts +2 -2
- package/dist/store/use-live-terrain.d.ts +1 -1
- package/dist/store/use-scene.d.ts +4 -4
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +50 -32
- package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
- package/dist/systems/elevator/elevator-dispatch.js +1 -1
- package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.js +2 -2
- package/dist/systems/elevator/elevator-opening-system.js +3 -3
- package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
- package/dist/systems/elevator/elevator-runtime.js +3 -3
- package/dist/systems/elevator/elevator-service.d.ts +1 -1
- package/dist/systems/elevator/elevator-service.js +1 -1
- package/dist/systems/fence/fence-centerline.d.ts +2 -2
- package/dist/systems/fence/fence-centerline.js +2 -2
- package/dist/systems/fence/fence-spline.d.ts +2 -2
- package/dist/systems/roof/roof-elevation-system.js +3 -3
- package/dist/systems/roof/roof-elevation.d.ts +2 -2
- package/dist/systems/roof/roof-elevation.js +6 -6
- package/dist/systems/roof/roof-footprint.d.ts +1 -1
- package/dist/systems/roof/roof-footprint.js +3 -3
- package/dist/systems/slab/slab-placement.d.ts +1 -1
- package/dist/systems/slab/slab-support.d.ts +1 -1
- package/dist/systems/slab/slab-support.js +4 -4
- package/dist/systems/stair/stair-flight.d.ts +2 -2
- package/dist/systems/stair/stair-flight.js +2 -2
- package/dist/systems/stair/stair-footprint.d.ts +1 -1
- package/dist/systems/stair/stair-opening-preview.d.ts +248 -87
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-preview.js +2 -2
- package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
- package/dist/systems/stair/stair-opening-sync.js +6 -6
- package/dist/systems/stair/stair-opening-system.js +8 -8
- package/dist/systems/stair/stair-rise.d.ts +1 -1
- package/dist/systems/stair/stair-rise.js +3 -3
- package/dist/systems/wall/wall-curve.d.ts +2 -2
- package/dist/systems/wall/wall-footprint.d.ts +3 -3
- package/dist/systems/wall/wall-footprint.js +3 -3
- package/dist/systems/wall/wall-merge.d.ts +38 -0
- package/dist/systems/wall/wall-merge.d.ts.map +1 -0
- package/dist/systems/wall/wall-merge.js +240 -0
- package/dist/systems/wall/wall-mitering.d.ts +1 -1
- package/dist/systems/wall/wall-mitering.js +1 -1
- package/dist/systems/wall/wall-move.d.ts +1 -1
- package/dist/systems/wall/wall-operations.d.ts +28 -0
- package/dist/systems/wall/wall-operations.d.ts.map +1 -0
- package/dist/systems/wall/wall-operations.js +145 -0
- package/dist/systems/wall/wall-top.d.ts +1 -1
- package/dist/systems/wall/wall-topology.d.ts +9 -2
- package/dist/systems/wall/wall-topology.d.ts.map +1 -1
- package/dist/systems/wall/wall-topology.js +57 -9
- package/dist/utils/clone-scene-graph.d.ts +3 -3
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +9 -3
- package/dist/utils/scene-migrations.d.ts +3 -3
- package/dist/utils/scene-migrations.js +3 -3
- package/dist/utils/vertical-scene-migration.js +5 -5
- package/dist/validation/validate-build-json.d.ts +5 -2
- package/dist/validation/validate-build-json.d.ts.map +1 -1
- package/dist/validation/validate-build-json.js +57 -4
- package/package.json +15 -4
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import { getFloorPlacedFootprints } from '../hooks/spatial-grid/floor-placed-footprints.js';
|
|
2
|
+
import { itemOverlapsPolygon } from '../lib/item-polygon-overlap.js';
|
|
3
|
+
import { pointInPolygon as containsPoint, polygonsOverlap, } from '../lib/polygon-relations.js';
|
|
4
|
+
import { getRenderableSlabPolygon } from '../lib/slab-polygon.js';
|
|
5
|
+
import { levelBaseElevationAt } from '../lib/terrain-support.js';
|
|
6
|
+
import { nodeRegistry } from '../registry/registry.js';
|
|
7
|
+
import { getBlockFaceFrame } from '../schema/nodes/block.js';
|
|
8
|
+
import { getRoofWallFaceFrame, roofFacePointToSegment } from '../schema/nodes/roof-segment-walls.js';
|
|
9
|
+
import { resolveCeilingHeight } from '../services/level-height.js';
|
|
10
|
+
import { getStoredLevelHeight } from '../services/storey.js';
|
|
11
|
+
import { surfaceRegionContainsPoint } from '../services/surface-region.js';
|
|
12
|
+
import { computeWallSlabSupport, pointInPolygon } from '../systems/slab/slab-support.js';
|
|
13
|
+
import { getWallThickness } from '../systems/wall/wall-footprint.js';
|
|
14
|
+
import { evaluateRecipe } from './recipe.js';
|
|
15
|
+
import { boundsOf, boxCorners, composeFrames, frame, IDENTITY_FRAME, transformPoint, } from './spatial.js';
|
|
16
|
+
export function isProceduralItem(node) {
|
|
17
|
+
return Boolean(node && typeof node === 'object' && 'type' in node && node.type === 'procedural-item');
|
|
18
|
+
}
|
|
19
|
+
function levelSurfaces(nodes, levelId) {
|
|
20
|
+
const siblings = Object.values(nodes).filter((n) => n.parentId === levelId);
|
|
21
|
+
return {
|
|
22
|
+
slabs: siblings.filter((n) => n.type === 'slab'),
|
|
23
|
+
walls: siblings.filter((n) => n.type === 'wall'),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function proceduralLocalPose(node, nodes) {
|
|
27
|
+
const position = [...node.position], rotation = [...node.rotation];
|
|
28
|
+
if (node.recipe.mounting?.attachTo === 'ceiling' &&
|
|
29
|
+
node.parentId &&
|
|
30
|
+
nodes[node.parentId]?.type === 'ceiling') {
|
|
31
|
+
const reference = evaluateRecipe(node.recipe, node.parameters).surfaces.find((s) => s.id === node.recipe.mounting?.reference);
|
|
32
|
+
if (!reference)
|
|
33
|
+
throw new Error('Missing mounting reference');
|
|
34
|
+
const offset = transformPoint(frame([0, 0, 0], rotation), reference.position);
|
|
35
|
+
for (let i = 0; i < 3; i++)
|
|
36
|
+
position[i] = position[i] - offset[i];
|
|
37
|
+
return { position, rotation };
|
|
38
|
+
}
|
|
39
|
+
if (!node.wallId)
|
|
40
|
+
return { position, rotation };
|
|
41
|
+
const wall = nodes[node.wallId];
|
|
42
|
+
if (wall?.type !== 'wall')
|
|
43
|
+
throw new Error('Missing wall host');
|
|
44
|
+
const reference = evaluateRecipe(node.recipe, node.parameters).surfaces.find((s) => s.id === node.recipe.mounting?.reference);
|
|
45
|
+
if (!reference)
|
|
46
|
+
throw new Error('Missing mounting reference');
|
|
47
|
+
const sign = node.side === 'back' ? -1 : 1;
|
|
48
|
+
rotation[1] = sign < 0 ? Math.PI : 0;
|
|
49
|
+
position[0] -= reference.position[0] * sign;
|
|
50
|
+
position[1] -= reference.position[1];
|
|
51
|
+
position[2] = sign * (getWallThickness(wall) / 2 - reference.position[2] + node.position[2]);
|
|
52
|
+
return { position, rotation };
|
|
53
|
+
}
|
|
54
|
+
export function proceduralFootprint(node) {
|
|
55
|
+
const e = evaluateRecipe(node.recipe, node.parameters);
|
|
56
|
+
const center = e.min.map((v, i) => (v + e.max[i]) / 2);
|
|
57
|
+
const position = transformPoint(frame(node.position, node.rotation), center);
|
|
58
|
+
return { position, rotation: node.rotation, dimensions: e.dimensions };
|
|
59
|
+
}
|
|
60
|
+
function floorLift(node, nodes) {
|
|
61
|
+
if (!node.parentId || nodes[node.parentId]?.type !== 'level' || !('position' in node))
|
|
62
|
+
return 0;
|
|
63
|
+
const position = node.position;
|
|
64
|
+
const supportSlabId = node.supportSlabId;
|
|
65
|
+
const capability = nodeRegistry.get(node.type)?.capabilities.floorPlaced;
|
|
66
|
+
const { slabs, walls } = levelSurfaces(nodes, node.parentId);
|
|
67
|
+
const ground = levelBaseElevationAt(nodes, node.parentId, position[0], position[2]);
|
|
68
|
+
if (supportSlabId === 'ground')
|
|
69
|
+
return ground;
|
|
70
|
+
if (capability || node.type === 'cabinet' || node.type === 'cabinet-module') {
|
|
71
|
+
const footprints = capability
|
|
72
|
+
? getFloorPlacedFootprints(capability, node, { nodes: nodes })
|
|
73
|
+
: [];
|
|
74
|
+
const candidatesFor = (footprint) => slabs.filter((slab) => {
|
|
75
|
+
const footprintPosition = footprint.position ?? position;
|
|
76
|
+
return (itemOverlapsPolygon(footprintPosition, footprint.dimensions, footprint.rotation, getRenderableSlabPolygon(slab, { walls, siblingSlabs: slabs }), 0.005) &&
|
|
77
|
+
!(slab.holes ?? []).some((hole) => pointInPolygon(footprintPosition[0], footprintPosition[2], hole)));
|
|
78
|
+
});
|
|
79
|
+
const candidates = footprints.map(candidatesFor);
|
|
80
|
+
const pinned = candidates.flat().find((slab) => slab.id === supportSlabId);
|
|
81
|
+
if (pinned)
|
|
82
|
+
return pinned.elevation ?? 0.05;
|
|
83
|
+
return candidates.length
|
|
84
|
+
? Math.max(...candidates.map((slabs) => slabs.length ? Math.max(...slabs.map((slab) => slab.elevation ?? 0.05)) : ground))
|
|
85
|
+
: ground;
|
|
86
|
+
}
|
|
87
|
+
if (!(isProceduralItem(node) || node.type === 'item' || node.type === 'shelf'))
|
|
88
|
+
return 0;
|
|
89
|
+
const footprint = isProceduralItem(node)
|
|
90
|
+
? proceduralFootprint(node)
|
|
91
|
+
: {
|
|
92
|
+
position: position,
|
|
93
|
+
dimensions: node.type === 'shelf'
|
|
94
|
+
? [node.width, node.height, node.depth]
|
|
95
|
+
: node.asset.dimensions.map((v, i) => v * node.scale[i]),
|
|
96
|
+
rotation: node.rotation,
|
|
97
|
+
};
|
|
98
|
+
const candidates = slabs.filter((s) => {
|
|
99
|
+
const polygon = getRenderableSlabPolygon(s, { walls, siblingSlabs: slabs });
|
|
100
|
+
return (itemOverlapsPolygon(footprint.position, footprint.dimensions, footprint.rotation, polygon, 0.005) &&
|
|
101
|
+
!(s.holes ?? []).some((h) => pointInPolygon(footprint.position[0], footprint.position[2], h)));
|
|
102
|
+
});
|
|
103
|
+
const pinned = candidates.find((s) => s.id === supportSlabId);
|
|
104
|
+
return pinned
|
|
105
|
+
? (pinned.elevation ?? 0.05)
|
|
106
|
+
: candidates.length
|
|
107
|
+
? Math.max(...candidates.map((s) => s.elevation ?? 0.05))
|
|
108
|
+
: ground;
|
|
109
|
+
}
|
|
110
|
+
function nodeParentFrame(node, nodes, seen) {
|
|
111
|
+
if (!node.parentId)
|
|
112
|
+
return IDENTITY_FRAME;
|
|
113
|
+
let parentFrame = nodeLevelFrame(node.parentId, nodes, seen);
|
|
114
|
+
const parent = nodes[node.parentId];
|
|
115
|
+
if (isProceduralItem(parent) && parent.attachments[node.id] !== undefined) {
|
|
116
|
+
const surface = evaluateRecipe(parent.recipe, parent.parameters).surfaces.find((s) => s.id === parent.attachments[node.id]);
|
|
117
|
+
if (!surface)
|
|
118
|
+
throw new Error('Missing attachment surface');
|
|
119
|
+
parentFrame = composeFrames(parentFrame, frame(surface.position, surface.rotation));
|
|
120
|
+
}
|
|
121
|
+
return parentFrame;
|
|
122
|
+
}
|
|
123
|
+
export function nodeLevelFrame(id, nodes, seen = new Set()) {
|
|
124
|
+
if (seen.has(id) || seen.size > 32)
|
|
125
|
+
throw new Error('Cyclic or excessively deep hosting graph');
|
|
126
|
+
const node = nodes[id];
|
|
127
|
+
if (!node)
|
|
128
|
+
throw new Error(`Missing node ${id}`);
|
|
129
|
+
if (node.type === 'level')
|
|
130
|
+
return IDENTITY_FRAME;
|
|
131
|
+
seen.add(id);
|
|
132
|
+
if (node.type === 'ceiling') {
|
|
133
|
+
// Match the ceiling renderer's underside frame, including its 1 cm inset.
|
|
134
|
+
return frame([0, resolveCeilingHeight(node, nodes) - 0.01, 0], [0, 0, 0]);
|
|
135
|
+
}
|
|
136
|
+
if (node.type === 'wall') {
|
|
137
|
+
const { slabs, walls } = levelSurfaces(nodes, node.parentId ?? '');
|
|
138
|
+
const ground = levelBaseElevationAt(nodes, node.parentId ?? '', node.start[0], node.start[1]);
|
|
139
|
+
const support = computeWallSlabSupport(node, slabs, walls, node.supportSlabId, undefined, ground);
|
|
140
|
+
return frame([node.start[0], support.elevation + (node.supportOffset ?? 0), node.start[1]], [0, -Math.atan2(node.end[1] - node.start[1], node.end[0] - node.start[0]), 0]);
|
|
141
|
+
}
|
|
142
|
+
if (!(isProceduralItem(node) ||
|
|
143
|
+
node.type === 'item' ||
|
|
144
|
+
node.type === 'shelf' ||
|
|
145
|
+
node.type === 'cabinet' ||
|
|
146
|
+
node.type === 'cabinet-module')) {
|
|
147
|
+
const transform = node;
|
|
148
|
+
const rotation = typeof transform.rotation === 'number'
|
|
149
|
+
? [0, transform.rotation, 0]
|
|
150
|
+
: transform.rotation;
|
|
151
|
+
const position = [...(transform.position ?? [0, 0, 0])];
|
|
152
|
+
const capability = nodeRegistry.get(node.type)?.capabilities.floorPlaced;
|
|
153
|
+
if (!capability?.applies || capability.applies(node)) {
|
|
154
|
+
position[1] += floorLift(node, nodes);
|
|
155
|
+
}
|
|
156
|
+
const local = node.type === 'slab' ? IDENTITY_FRAME : frame(position, rotation ?? [0, 0, 0]);
|
|
157
|
+
return node.parentId ? composeFrames(nodeParentFrame(node, nodes, seen), local) : local;
|
|
158
|
+
}
|
|
159
|
+
const pose = isProceduralItem(node)
|
|
160
|
+
? proceduralLocalPose(node, nodes)
|
|
161
|
+
: {
|
|
162
|
+
position: [...node.position],
|
|
163
|
+
rotation: typeof node.rotation === 'number' ? [0, node.rotation, 0] : node.rotation,
|
|
164
|
+
};
|
|
165
|
+
const parent = node.parentId ? nodes[node.parentId] : undefined;
|
|
166
|
+
if (!node.parentId)
|
|
167
|
+
return frame(pose.position, pose.rotation);
|
|
168
|
+
if (node.type === 'item' && parent?.type === 'roof-segment' && node.roofFace) {
|
|
169
|
+
const face = getRoofWallFaceFrame(parent, node.roofFace);
|
|
170
|
+
const local = frame(roofFacePointToSegment(parent, node.roofFace, pose.position), pose.rotation);
|
|
171
|
+
local.axes = composeFrames(frame([0, 0, 0], [0, face.yaw, 0]), frame([0, 0, 0], pose.rotation)).axes;
|
|
172
|
+
return composeFrames(nodeLevelFrame(parent.id, nodes, seen), local);
|
|
173
|
+
}
|
|
174
|
+
if (node.type === 'item' && parent?.type === 'block' && node.blockFaceId) {
|
|
175
|
+
const face = getBlockFaceFrame(parent.topology, node.blockFaceId);
|
|
176
|
+
if (face) {
|
|
177
|
+
const host = nodeLevelFrame(parent.id, nodes, seen);
|
|
178
|
+
return composeFrames(host, composeFrames({ position: face.origin, axes: [face.xAxis, face.yAxis, face.normal] }, frame(pose.position, pose.rotation)));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const parentFrame = nodeParentFrame(node, nodes, seen);
|
|
182
|
+
if (parent?.type === 'level')
|
|
183
|
+
pose.position[1] += floorLift(node, nodes);
|
|
184
|
+
return composeFrames(parentFrame, frame(pose.position, pose.rotation));
|
|
185
|
+
}
|
|
186
|
+
function localBounds(node) {
|
|
187
|
+
if (isProceduralItem(node))
|
|
188
|
+
return evaluateRecipe(node.recipe, node.parameters);
|
|
189
|
+
const d = node.asset.dimensions.map((v, i) => v * node.scale[i]);
|
|
190
|
+
return { min: [-d[0] / 2, 0, -d[2] / 2], max: [d[0] / 2, d[1], d[2] / 2] };
|
|
191
|
+
}
|
|
192
|
+
export function attachmentBounds(child) {
|
|
193
|
+
const b = localBounds(child);
|
|
194
|
+
return boundsOf(boxCorners(b.min, b.max).map((p) => transformPoint(frame(child.position, child.rotation), p)));
|
|
195
|
+
}
|
|
196
|
+
export function attachmentRegionsOverlap(a, b) {
|
|
197
|
+
return (a.min[0] < b.max[0] - 1e-6 &&
|
|
198
|
+
a.max[0] > b.min[0] + 1e-6 &&
|
|
199
|
+
a.min[2] < b.max[2] - 1e-6 &&
|
|
200
|
+
a.max[2] > b.min[2] + 1e-6);
|
|
201
|
+
}
|
|
202
|
+
function ceilingContainsFootprint(outer, footprint) {
|
|
203
|
+
if (!footprint.every((p) => containsPoint(p, outer)))
|
|
204
|
+
return false;
|
|
205
|
+
// A concave boundary can cross a footprint whose corners all lie inside.
|
|
206
|
+
// Clip each boundary segment against the open, convex footprint interior.
|
|
207
|
+
return !outer.some((a, i) => {
|
|
208
|
+
const b = outer[(i + 1) % outer.length];
|
|
209
|
+
let enter = 0;
|
|
210
|
+
let exit = 1;
|
|
211
|
+
for (let j = 0; j < footprint.length; j++) {
|
|
212
|
+
const c = footprint[j], d = footprint[(j + 1) % footprint.length];
|
|
213
|
+
const distance = (p) => ((d[0] - c[0]) * (p[1] - c[1]) - (d[1] - c[1]) * (p[0] - c[0])) /
|
|
214
|
+
Math.hypot(d[0] - c[0], d[1] - c[1]) -
|
|
215
|
+
1e-6;
|
|
216
|
+
const start = distance(a), end = distance(b);
|
|
217
|
+
if (start <= 0 && end <= 0)
|
|
218
|
+
return false;
|
|
219
|
+
if (start <= 0)
|
|
220
|
+
enter = Math.max(enter, -start / (end - start));
|
|
221
|
+
else if (end <= 0)
|
|
222
|
+
exit = Math.min(exit, start / (start - end));
|
|
223
|
+
if (enter >= exit)
|
|
224
|
+
return false;
|
|
225
|
+
}
|
|
226
|
+
return enter < exit;
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
export function validateProceduralRelations(raw, nodes) {
|
|
230
|
+
if (!isProceduralItem(raw))
|
|
231
|
+
return;
|
|
232
|
+
const node = raw, evaluation = evaluateRecipe(node.recipe, node.parameters);
|
|
233
|
+
const draft = node.metadata;
|
|
234
|
+
const awaitingHost = (draft?.isNew || draft?.isTransient) &&
|
|
235
|
+
!node.wallId &&
|
|
236
|
+
node.parentId &&
|
|
237
|
+
nodes[node.parentId]?.type === 'level';
|
|
238
|
+
if (node.recipe.mounting?.attachTo === 'ceiling' && !awaitingHost) {
|
|
239
|
+
const ceiling = node.parentId ? nodes[node.parentId] : undefined;
|
|
240
|
+
if (ceiling?.type !== 'ceiling' || node.wallId || node.side)
|
|
241
|
+
throw new Error('This design needs a ceiling host');
|
|
242
|
+
if (Math.abs(node.rotation[0]) > 1e-8 || Math.abs(node.rotation[2]) > 1e-8)
|
|
243
|
+
throw new Error('Ceiling designs allow Y rotation only');
|
|
244
|
+
if (Math.abs(node.position[1]) > 1e-6)
|
|
245
|
+
throw new Error('The top reference must be flush with the ceiling');
|
|
246
|
+
const pose = proceduralLocalPose(node, nodes);
|
|
247
|
+
const f = frame(pose.position, pose.rotation);
|
|
248
|
+
const b = boundsOf(boxCorners(evaluation.min, evaluation.max).map((p) => transformPoint(f, p)));
|
|
249
|
+
const height = nodeLevelFrame(ceiling.id, nodes).position[1];
|
|
250
|
+
const level = ceiling.parentId ? nodes[ceiling.parentId] : undefined;
|
|
251
|
+
if (b.min[1] + height < -1e-6 ||
|
|
252
|
+
b.max[1] > 1e-6 ||
|
|
253
|
+
b.max[1] + height > getStoredLevelHeight(level?.type === 'level' ? level : {}) + 1e-6)
|
|
254
|
+
throw new Error('The hanging design must fit below the ceiling within the level height');
|
|
255
|
+
const footprint = [
|
|
256
|
+
[evaluation.min[0], evaluation.min[2]],
|
|
257
|
+
[evaluation.max[0], evaluation.min[2]],
|
|
258
|
+
[evaluation.max[0], evaluation.max[2]],
|
|
259
|
+
[evaluation.min[0], evaluation.max[2]],
|
|
260
|
+
].map(([x, z]) => {
|
|
261
|
+
const p = transformPoint(f, [x, 0, z]);
|
|
262
|
+
return [p[0], p[2]];
|
|
263
|
+
});
|
|
264
|
+
if (!ceilingContainsFootprint(ceiling.polygon, footprint) ||
|
|
265
|
+
ceiling.holes.some((hole) => polygonsOverlap(hole, footprint)))
|
|
266
|
+
throw new Error('The hanging design must fit inside the ceiling, outside its holes');
|
|
267
|
+
}
|
|
268
|
+
else if (node.recipe.mounting?.attachTo === 'wall-side' && !awaitingHost) {
|
|
269
|
+
const wall = node.wallId ? nodes[node.wallId] : undefined;
|
|
270
|
+
if (wall?.type !== 'wall' || node.parentId !== wall.id)
|
|
271
|
+
throw new Error('This design needs a wall host');
|
|
272
|
+
if (wall.curveOffset)
|
|
273
|
+
throw new Error('Curved wall mounting is not supported yet');
|
|
274
|
+
if (node.rotation.some((v) => Math.abs(v) > 1e-8))
|
|
275
|
+
throw new Error('Move the item onto a wall face or press R to flip it');
|
|
276
|
+
const pose = proceduralLocalPose(node, nodes);
|
|
277
|
+
const b = boundsOf(boxCorners(evaluation.min, evaluation.max).map((p) => transformPoint(frame(pose.position, pose.rotation), p)));
|
|
278
|
+
const length = Math.hypot(wall.end[0] - wall.start[0], wall.end[1] - wall.start[1]);
|
|
279
|
+
const level = wall.parentId ? nodes[wall.parentId] : undefined;
|
|
280
|
+
const height = wall.height ?? (level?.type === 'level' ? level.height : 2.5) ?? 2.5;
|
|
281
|
+
if (b.min[0] < -1e-6 ||
|
|
282
|
+
b.max[0] > length + 1e-6 ||
|
|
283
|
+
b.min[1] < -1e-6 ||
|
|
284
|
+
b.max[1] > height + 1e-6 ||
|
|
285
|
+
node.position[2] < 0)
|
|
286
|
+
throw new Error('The mounted item must fit on the wall');
|
|
287
|
+
}
|
|
288
|
+
else if (node.wallId ||
|
|
289
|
+
(node.parentId && ['wall', 'ceiling'].includes(nodes[node.parentId]?.type ?? '')))
|
|
290
|
+
throw new Error('A floor design cannot be attached to a wall or ceiling');
|
|
291
|
+
const regions = new Map();
|
|
292
|
+
for (const childId of node.children) {
|
|
293
|
+
const child = nodes[childId];
|
|
294
|
+
if (!child || child.parentId !== node.id)
|
|
295
|
+
throw new Error('Invalid hosted child link');
|
|
296
|
+
if (!(isProceduralItem(child) || child.type === 'item'))
|
|
297
|
+
throw new Error('Unsupported hosted child');
|
|
298
|
+
if (node.attachments[childId] === undefined)
|
|
299
|
+
continue;
|
|
300
|
+
const surface = evaluation.surfaces.find((s) => s.id === node.attachments[childId]);
|
|
301
|
+
if (!surface)
|
|
302
|
+
throw new Error('Choose a named attachment surface for the child');
|
|
303
|
+
const b = attachmentBounds(child);
|
|
304
|
+
if (!surfaceRegionContainsPoint({ kind: 'rect', size: [surface.size[0] / 2, surface.size[1] / 2] }, [(b.min[0] + b.max[0]) / 2, (b.min[2] + b.max[2]) / 2]) ||
|
|
305
|
+
Math.abs(b.min[1]) > 1e-6)
|
|
306
|
+
throw new Error(`The hosted item does not fit on ${surface.label}`);
|
|
307
|
+
// A fresh duplicate initially overlaps its source; only committed children occupy a surface.
|
|
308
|
+
if (child.metadata?.isNew === true)
|
|
309
|
+
continue;
|
|
310
|
+
const occupied = regions.get(surface.id) ?? [];
|
|
311
|
+
if (occupied.some((a) => attachmentRegionsOverlap(a, b)))
|
|
312
|
+
throw new Error(`Another item occupies ${surface.label}`);
|
|
313
|
+
occupied.push(b);
|
|
314
|
+
regions.set(surface.id, occupied);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
export function queryProceduralItem(node, nodes) {
|
|
318
|
+
const e = evaluateRecipe(node.recipe, node.parameters), f = nodeLevelFrame(node.id, nodes[node.id] === node ? nodes : { ...nodes, [node.id]: node });
|
|
319
|
+
const bounds = boundsOf(boxCorners(e.min, e.max).map((p) => transformPoint(f, p)));
|
|
320
|
+
return {
|
|
321
|
+
id: node.id,
|
|
322
|
+
kind: node.type,
|
|
323
|
+
classification: node.recipe.classification ?? null,
|
|
324
|
+
hostId: node.parentId,
|
|
325
|
+
wallId: node.wallId ?? null,
|
|
326
|
+
parameters: e.parameters,
|
|
327
|
+
localBounds: { min: e.min, max: e.max, dimensions: e.dimensions },
|
|
328
|
+
levelBounds: bounds,
|
|
329
|
+
frame: f,
|
|
330
|
+
footprint: [
|
|
331
|
+
[bounds.min[0], bounds.min[2]],
|
|
332
|
+
[bounds.max[0], bounds.min[2]],
|
|
333
|
+
[bounds.max[0], bounds.max[2]],
|
|
334
|
+
[bounds.min[0], bounds.max[2]],
|
|
335
|
+
],
|
|
336
|
+
surfaces: e.surfaces.map((s) => ({
|
|
337
|
+
...s,
|
|
338
|
+
frame: composeFrames(f, frame(s.position, s.rotation)),
|
|
339
|
+
})),
|
|
340
|
+
children: node.children,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export type Expr = number | string | {
|
|
3
|
+
op: 'add' | 'sub' | 'mul' | 'div' | 'min' | 'max';
|
|
4
|
+
args: Expr[];
|
|
5
|
+
} | {
|
|
6
|
+
op: 'floor' | 'ceil' | 'round' | 'abs';
|
|
7
|
+
args: [Expr];
|
|
8
|
+
} | {
|
|
9
|
+
op: 'mod';
|
|
10
|
+
args: [Expr, Expr];
|
|
11
|
+
};
|
|
12
|
+
export type Vec3 = [number, number, number];
|
|
13
|
+
export declare const RecipeSchema: z.ZodObject<{
|
|
14
|
+
version: z.ZodLiteral<1>;
|
|
15
|
+
name: z.ZodString;
|
|
16
|
+
description: z.ZodString;
|
|
17
|
+
classification: z.ZodOptional<z.ZodObject<{
|
|
18
|
+
category: z.ZodString;
|
|
19
|
+
functionTags: z.ZodArray<z.ZodString>;
|
|
20
|
+
tags: z.ZodArray<z.ZodString>;
|
|
21
|
+
}, z.core.$strict>>;
|
|
22
|
+
mounting: z.ZodOptional<z.ZodObject<{
|
|
23
|
+
attachTo: z.ZodEnum<{
|
|
24
|
+
ceiling: "ceiling";
|
|
25
|
+
"wall-side": "wall-side";
|
|
26
|
+
}>;
|
|
27
|
+
reference: z.ZodString;
|
|
28
|
+
}, z.core.$strict>>;
|
|
29
|
+
surfaces: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
30
|
+
id: z.ZodString;
|
|
31
|
+
label: z.ZodString;
|
|
32
|
+
part: z.ZodOptional<z.ZodString>;
|
|
33
|
+
position: z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>;
|
|
34
|
+
rotation: z.ZodOptional<z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>>;
|
|
35
|
+
size: z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>;
|
|
36
|
+
}, z.core.$strict>>>;
|
|
37
|
+
parameters: z.ZodArray<z.ZodObject<{
|
|
38
|
+
id: z.ZodString;
|
|
39
|
+
label: z.ZodString;
|
|
40
|
+
default: z.ZodNumber;
|
|
41
|
+
min: z.ZodNumber;
|
|
42
|
+
max: z.ZodNumber;
|
|
43
|
+
step: z.ZodNumber;
|
|
44
|
+
unit: z.ZodEnum<{
|
|
45
|
+
count: "count";
|
|
46
|
+
m: "m";
|
|
47
|
+
rad: "rad";
|
|
48
|
+
}>;
|
|
49
|
+
part: z.ZodOptional<z.ZodString>;
|
|
50
|
+
axis: z.ZodOptional<z.ZodEnum<{
|
|
51
|
+
x: "x";
|
|
52
|
+
y: "y";
|
|
53
|
+
z: "z";
|
|
54
|
+
}>>;
|
|
55
|
+
}, z.core.$strict>>;
|
|
56
|
+
slots: z.ZodArray<z.ZodObject<{
|
|
57
|
+
id: z.ZodString;
|
|
58
|
+
label: z.ZodString;
|
|
59
|
+
color: z.ZodString;
|
|
60
|
+
finish: z.ZodOptional<z.ZodEnum<{
|
|
61
|
+
wood: "wood";
|
|
62
|
+
glass: "glass";
|
|
63
|
+
metal: "metal";
|
|
64
|
+
}>>;
|
|
65
|
+
}, z.core.$strict>>;
|
|
66
|
+
parts: z.ZodArray<z.ZodObject<{
|
|
67
|
+
id: z.ZodString;
|
|
68
|
+
label: z.ZodString;
|
|
69
|
+
count: z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>;
|
|
70
|
+
shapes: z.ZodArray<z.ZodObject<{
|
|
71
|
+
id: z.ZodString;
|
|
72
|
+
primitive: z.ZodEnum<{
|
|
73
|
+
box: "box";
|
|
74
|
+
roundedBox: "roundedBox";
|
|
75
|
+
cylinder: "cylinder";
|
|
76
|
+
}>;
|
|
77
|
+
slot: z.ZodString;
|
|
78
|
+
size: z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>;
|
|
79
|
+
position: z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>;
|
|
80
|
+
rotation: z.ZodOptional<z.ZodTuple<[z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>, z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>], null>>;
|
|
81
|
+
radius: z.ZodOptional<z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>>;
|
|
82
|
+
support: z.ZodOptional<z.ZodBoolean>;
|
|
83
|
+
}, z.core.$strict>>;
|
|
84
|
+
}, z.core.$strict>>;
|
|
85
|
+
constraints: z.ZodArray<z.ZodObject<{
|
|
86
|
+
left: z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>;
|
|
87
|
+
relation: z.ZodEnum<{
|
|
88
|
+
lte: "lte";
|
|
89
|
+
gte: "gte";
|
|
90
|
+
}>;
|
|
91
|
+
right: z.ZodType<Expr, unknown, z.core.$ZodTypeInternals<Expr, unknown>>;
|
|
92
|
+
message: z.ZodString;
|
|
93
|
+
}, z.core.$strict>>;
|
|
94
|
+
}, z.core.$strict>;
|
|
95
|
+
export type Recipe = z.infer<typeof RecipeSchema>;
|
|
96
|
+
export type EvaluatedShape = {
|
|
97
|
+
id: string;
|
|
98
|
+
partId: string;
|
|
99
|
+
primitive: 'box' | 'roundedBox' | 'cylinder';
|
|
100
|
+
slot: string;
|
|
101
|
+
size: Vec3;
|
|
102
|
+
position: Vec3;
|
|
103
|
+
rotation: Vec3;
|
|
104
|
+
radius: number;
|
|
105
|
+
};
|
|
106
|
+
export type Surface = {
|
|
107
|
+
id: string;
|
|
108
|
+
label: string;
|
|
109
|
+
position: Vec3;
|
|
110
|
+
rotation: Vec3;
|
|
111
|
+
normal: Vec3;
|
|
112
|
+
size: [number, number];
|
|
113
|
+
};
|
|
114
|
+
export type Evaluation = {
|
|
115
|
+
shapes: EvaluatedShape[];
|
|
116
|
+
surfaces: Surface[];
|
|
117
|
+
min: Vec3;
|
|
118
|
+
max: Vec3;
|
|
119
|
+
dimensions: Vec3;
|
|
120
|
+
parameters: Record<string, number>;
|
|
121
|
+
triangles: number;
|
|
122
|
+
};
|
|
123
|
+
export declare const RECIPE_LIMITS: {
|
|
124
|
+
readonly bytes: 131072;
|
|
125
|
+
readonly depth: 24;
|
|
126
|
+
readonly expressions: 50000;
|
|
127
|
+
readonly shapes: 256;
|
|
128
|
+
readonly triangles: 100000;
|
|
129
|
+
readonly dimension: 30;
|
|
130
|
+
};
|
|
131
|
+
export declare function parseRecipe(input: unknown): Recipe;
|
|
132
|
+
export declare function evaluateRecipe(recipe: Recipe, values?: Record<string, number>): Evaluation;
|
|
133
|
+
export declare function sweepRecipe(recipe: Recipe): ({
|
|
134
|
+
index: number;
|
|
135
|
+
values: Record<string, number>;
|
|
136
|
+
valid: boolean;
|
|
137
|
+
error: null;
|
|
138
|
+
} | {
|
|
139
|
+
index: number;
|
|
140
|
+
values: Record<string, number>;
|
|
141
|
+
valid: boolean;
|
|
142
|
+
error: string;
|
|
143
|
+
})[];
|
|
144
|
+
//# sourceMappingURL=recipe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recipe.d.ts","sourceRoot":"","sources":["../../src/procedural-items/recipe.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,MAAM,MAAM,IAAI,GACZ,MAAM,GACN,MAAM,GACN;IAAE,EAAE,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,IAAI,EAAE,CAAA;CAAE,GACnE;IAAE,EAAE,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,CAAC;IAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAA;CAAE,GACxD;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;CAAE,CAAA;AACrC,MAAM,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAsB3C,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAyFvB,CAAA;AACF,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AACjD,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,KAAK,GAAG,YAAY,GAAG,UAAU,CAAA;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,IAAI,CAAA;IACd,QAAQ,EAAE,IAAI,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AACD,MAAM,MAAM,OAAO,GAAG;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,IAAI,CAAA;IACd,QAAQ,EAAE,IAAI,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;IACZ,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACvB,CAAA;AACD,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,cAAc,EAAE,CAAA;IACxB,QAAQ,EAAE,OAAO,EAAE,CAAA;IACnB,GAAG,EAAE,IAAI,CAAA;IACT,GAAG,EAAE,IAAI,CAAA;IACT,UAAU,EAAE,IAAI,CAAA;IAChB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AACD,eAAO,MAAM,aAAa;;;;;;;CAOhB,CAAA;AAYV,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAsClD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAAG,UAAU,CAqL9F;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;KA0BzC"}
|