@pascal-app/core 0.7.0 → 0.9.1
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/events/bus.d.ts +47 -18
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +1 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts +6 -22
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +33 -26
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +14 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +51 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +2 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +273 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +13 -2
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +95 -9
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +28 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +91 -18
- package/dist/index.d.ts +22 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/lib/polygon-geometry.d.ts.map +1 -1
- package/dist/lib/polygon-relations.d.ts +10 -0
- package/dist/lib/polygon-relations.d.ts.map +1 -0
- package/dist/lib/polygon-relations.js +73 -0
- package/dist/lib/space-detection-pause.test.d.ts +2 -0
- package/dist/lib/space-detection-pause.test.d.ts.map +1 -0
- package/dist/lib/space-detection-pause.test.js +42 -0
- package/dist/lib/space-detection.d.ts +30 -1
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +222 -41
- package/dist/lib/space-detection.test.d.ts +2 -0
- package/dist/lib/space-detection.test.d.ts.map +1 -0
- package/dist/lib/space-detection.test.js +77 -0
- package/dist/material-library.d.ts +1 -1
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +1957 -141
- package/dist/registry/__bench__/relations-resolver.bench.d.ts +15 -0
- package/dist/registry/__bench__/relations-resolver.bench.d.ts.map +1 -0
- package/dist/registry/__bench__/relations-resolver.bench.js +170 -0
- package/dist/registry/handles.d.ts +321 -0
- package/dist/registry/handles.d.ts.map +1 -0
- package/dist/registry/handles.js +24 -0
- package/dist/registry/index.d.ts +7 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +4 -0
- package/dist/registry/registry.d.ts +93 -0
- package/dist/registry/registry.d.ts.map +1 -0
- package/dist/registry/registry.js +201 -0
- package/dist/registry/registry.test.d.ts +2 -0
- package/dist/registry/registry.test.d.ts.map +1 -0
- package/dist/registry/registry.test.js +183 -0
- package/dist/registry/relations-resolver.d.ts +42 -0
- package/dist/registry/relations-resolver.d.ts.map +1 -0
- package/dist/registry/relations-resolver.js +77 -0
- package/dist/registry/relations-resolver.test.d.ts +2 -0
- package/dist/registry/relations-resolver.test.d.ts.map +1 -0
- package/dist/registry/relations-resolver.test.js +183 -0
- package/dist/registry/scene-api.d.ts +44 -0
- package/dist/registry/scene-api.d.ts.map +1 -0
- package/dist/registry/scene-api.js +111 -0
- package/dist/registry/scene-api.test.d.ts +2 -0
- package/dist/registry/scene-api.test.d.ts.map +1 -0
- package/dist/registry/scene-api.test.js +183 -0
- package/dist/registry/subtree.d.ts +67 -0
- package/dist/registry/subtree.d.ts.map +1 -0
- package/dist/registry/subtree.js +119 -0
- package/dist/registry/subtree.test.d.ts +2 -0
- package/dist/registry/subtree.test.d.ts.map +1 -0
- package/dist/registry/subtree.test.js +133 -0
- package/dist/registry/types.d.ts +1420 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +1 -0
- package/dist/schema/asset-url.test.js +0 -4
- package/dist/schema/index.d.ts +17 -2
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +17 -3
- package/dist/schema/material.d.ts +12 -2
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +10 -0
- package/dist/schema/nodes/box-vent.d.ts +74 -0
- package/dist/schema/nodes/box-vent.d.ts.map +1 -0
- package/dist/schema/nodes/box-vent.js +63 -0
- 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 +3 -2
- package/dist/schema/nodes/ceiling.d.ts +3 -1
- package/dist/schema/nodes/ceiling.d.ts.map +1 -1
- package/dist/schema/nodes/ceiling.js +1 -1
- package/dist/schema/nodes/chimney.d.ts +158 -0
- package/dist/schema/nodes/chimney.d.ts.map +1 -0
- package/dist/schema/nodes/chimney.js +67 -0
- package/dist/schema/nodes/column.d.ts +598 -6
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +586 -6
- package/dist/schema/nodes/cupola.d.ts +66 -0
- package/dist/schema/nodes/cupola.d.ts.map +1 -0
- package/dist/schema/nodes/cupola.js +28 -0
- package/dist/schema/nodes/door.d.ts +1 -1
- package/dist/schema/nodes/dormer.d.ts +228 -0
- package/dist/schema/nodes/dormer.d.ts.map +1 -0
- package/dist/schema/nodes/dormer.js +119 -0
- package/dist/schema/nodes/downspout.d.ts +75 -0
- package/dist/schema/nodes/downspout.d.ts.map +1 -0
- package/dist/schema/nodes/downspout.js +63 -0
- package/dist/schema/nodes/elevator.d.ts +105 -0
- package/dist/schema/nodes/elevator.d.ts.map +1 -0
- package/dist/schema/nodes/elevator.js +54 -0
- package/dist/schema/nodes/eyebrow-vent.d.ts +68 -0
- package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -0
- package/dist/schema/nodes/eyebrow-vent.js +40 -0
- package/dist/schema/nodes/fence.d.ts +3 -2
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +4 -2
- package/dist/schema/nodes/gutter.d.ts +84 -0
- package/dist/schema/nodes/gutter.d.ts.map +1 -0
- package/dist/schema/nodes/gutter.js +76 -0
- package/dist/schema/nodes/item.d.ts +16 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +21 -0
- 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 +2 -0
- package/dist/schema/nodes/ridge-vent.d.ts +67 -0
- package/dist/schema/nodes/ridge-vent.d.ts.map +1 -0
- package/dist/schema/nodes/ridge-vent.js +30 -0
- package/dist/schema/nodes/roof-segment.d.ts +198 -4
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +254 -3
- package/dist/schema/nodes/roof.d.ts +6 -6
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +9 -21
- package/dist/schema/nodes/shelf.d.ts +105 -0
- package/dist/schema/nodes/shelf.d.ts.map +1 -0
- package/dist/schema/nodes/shelf.js +84 -0
- package/dist/schema/nodes/site.d.ts +1 -116
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/site.js +2 -6
- package/dist/schema/nodes/skylight.d.ts +279 -0
- package/dist/schema/nodes/skylight.d.ts.map +1 -0
- package/dist/schema/nodes/skylight.js +152 -0
- package/dist/schema/nodes/slab.d.ts +3 -1
- package/dist/schema/nodes/slab.d.ts.map +1 -1
- package/dist/schema/nodes/slab.js +1 -1
- package/dist/schema/nodes/solar-panel.d.ts +117 -0
- package/dist/schema/nodes/solar-panel.d.ts.map +1 -0
- package/dist/schema/nodes/solar-panel.js +47 -0
- package/dist/schema/nodes/stair-segment.d.ts +1 -1
- package/dist/schema/nodes/stair.d.ts +6 -6
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +9 -7
- package/dist/schema/nodes/surface-hole-metadata.d.ts +2 -0
- package/dist/schema/nodes/surface-hole-metadata.d.ts.map +1 -1
- package/dist/schema/nodes/surface-hole-metadata.js +3 -1
- package/dist/schema/nodes/turbine-vent.d.ts +68 -0
- package/dist/schema/nodes/turbine-vent.d.ts.map +1 -0
- package/dist/schema/nodes/turbine-vent.js +41 -0
- package/dist/schema/nodes/wall.d.ts +3 -3
- package/dist/schema/nodes/window.d.ts +1 -1
- package/dist/schema/types.d.ts +1448 -236
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +26 -0
- package/dist/services/alignment-anchors.d.ts +100 -0
- package/dist/services/alignment-anchors.d.ts.map +1 -0
- package/dist/services/alignment-anchors.js +283 -0
- package/dist/services/alignment-anchors.test.d.ts +2 -0
- package/dist/services/alignment-anchors.test.d.ts.map +1 -0
- package/dist/services/alignment-anchors.test.js +383 -0
- package/dist/services/alignment.d.ts +126 -0
- package/dist/services/alignment.d.ts.map +1 -0
- package/dist/services/alignment.js +169 -0
- package/dist/services/alignment.test.d.ts +2 -0
- package/dist/services/alignment.test.d.ts.map +1 -0
- package/dist/services/alignment.test.js +92 -0
- package/dist/services/drag-session.d.ts +47 -0
- package/dist/services/drag-session.d.ts.map +1 -0
- package/dist/services/drag-session.js +100 -0
- package/dist/services/drag-session.test.d.ts +2 -0
- package/dist/services/drag-session.test.d.ts.map +1 -0
- package/dist/services/drag-session.test.js +219 -0
- package/dist/services/hosting.d.ts +80 -0
- package/dist/services/hosting.d.ts.map +1 -0
- package/dist/services/hosting.js +122 -0
- package/dist/services/hosting.test.d.ts +2 -0
- package/dist/services/hosting.test.d.ts.map +1 -0
- package/dist/services/hosting.test.js +199 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +6 -0
- package/dist/services/movement.d.ts +48 -0
- package/dist/services/movement.d.ts.map +1 -0
- package/dist/services/movement.js +65 -0
- package/dist/services/movement.test.d.ts +2 -0
- package/dist/services/movement.test.d.ts.map +1 -0
- package/dist/services/movement.test.js +133 -0
- package/dist/services/single-undo-dance.test.d.ts +2 -0
- package/dist/services/single-undo-dance.test.d.ts.map +1 -0
- package/dist/services/single-undo-dance.test.js +210 -0
- package/dist/services/snap.d.ts +72 -0
- package/dist/services/snap.d.ts.map +1 -0
- package/dist/services/snap.js +120 -0
- package/dist/services/snap.test.d.ts +2 -0
- package/dist/services/snap.test.d.ts.map +1 -0
- package/dist/services/snap.test.js +95 -0
- package/dist/solar-panel-presets.d.ts +17 -0
- package/dist/solar-panel-presets.d.ts.map +1 -0
- package/dist/solar-panel-presets.js +43 -0
- package/dist/store/actions/node-actions.d.ts +14 -2
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +499 -20
- package/dist/store/actions/node-mutation-sanitize.test.d.ts +2 -0
- package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +1 -0
- package/dist/store/actions/node-mutation-sanitize.test.js +147 -0
- package/dist/store/actions/reparent.test.d.ts +2 -0
- package/dist/store/actions/reparent.test.d.ts.map +1 -0
- package/dist/store/actions/reparent.test.js +212 -0
- package/dist/store/use-interactive.d.ts +39 -0
- package/dist/store/use-interactive.d.ts.map +1 -1
- package/dist/store/use-interactive.js +75 -0
- package/dist/store/use-live-node-overrides.d.ts +22 -0
- package/dist/store/use-live-node-overrides.d.ts.map +1 -0
- package/dist/store/use-live-node-overrides.js +59 -0
- package/dist/store/use-scene-elevator-migration.test.d.ts +2 -0
- package/dist/store/use-scene-elevator-migration.test.d.ts.map +1 -0
- package/dist/store/use-scene-elevator-migration.test.js +109 -0
- package/dist/store/use-scene.d.ts +11 -0
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +207 -11
- package/dist/systems/elevator/elevator-dispatch.d.ts +12 -0
- package/dist/systems/elevator/elevator-dispatch.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-dispatch.js +57 -0
- package/dist/systems/elevator/elevator-geometry.d.ts +15 -0
- package/dist/systems/elevator/elevator-geometry.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-geometry.js +50 -0
- package/dist/systems/elevator/elevator-opening-sync.d.ts +6 -0
- package/dist/systems/elevator/elevator-opening-sync.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-sync.js +218 -0
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts +2 -0
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-sync.test.js +146 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-opening-system.js +48 -0
- package/dist/systems/elevator/elevator-runtime-system.d.ts +2 -0
- package/dist/systems/elevator/elevator-runtime-system.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime-system.js +8 -0
- package/dist/systems/elevator/elevator-runtime.d.ts +18 -0
- package/dist/systems/elevator/elevator-runtime.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime.js +225 -0
- package/dist/systems/elevator/elevator-runtime.test.d.ts +2 -0
- package/dist/systems/elevator/elevator-runtime.test.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-runtime.test.js +64 -0
- package/dist/systems/elevator/elevator-service.d.ts +19 -0
- package/dist/systems/elevator/elevator-service.d.ts.map +1 -0
- package/dist/systems/elevator/elevator-service.js +111 -0
- package/dist/systems/stair/stair-footprint.d.ts +44 -0
- package/dist/systems/stair/stair-footprint.d.ts.map +1 -0
- package/dist/systems/stair/stair-footprint.js +168 -0
- package/dist/systems/stair/stair-opening-preview.d.ts +1777 -0
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-preview.js +93 -0
- package/dist/systems/stair/stair-opening-preview.test.d.ts +2 -0
- package/dist/systems/stair/stair-opening-preview.test.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-preview.test.js +80 -0
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.js +183 -185
- package/dist/systems/stair/stair-opening-sync.test.js +385 -4
- package/dist/systems/stair/stair-opening-system.d.ts +2 -0
- package/dist/systems/stair/stair-opening-system.d.ts.map +1 -0
- package/dist/systems/stair/stair-opening-system.js +104 -0
- package/dist/systems/wall/wall-curve.d.ts +1 -1
- package/dist/systems/wall/wall-curve.d.ts.map +1 -1
- package/dist/systems/wall/wall-curve.js +1 -1
- package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
- package/dist/systems/wall/wall-mitering.js +2 -6
- package/dist/systems/wall/wall-move.d.ts +48 -0
- package/dist/systems/wall/wall-move.d.ts.map +1 -0
- package/dist/systems/wall/wall-move.js +193 -0
- package/dist/utils/clone-scene-graph.d.ts +6 -4
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +6 -4
- package/dist/utils/clone-scene-graph.test.d.ts +2 -0
- package/dist/utils/clone-scene-graph.test.d.ts.map +1 -0
- package/dist/utils/clone-scene-graph.test.js +59 -0
- package/dist/validation/validate-build-json.d.ts +43 -0
- package/dist/validation/validate-build-json.d.ts.map +1 -0
- package/dist/validation/validate-build-json.js +227 -0
- package/package.json +11 -3
- package/dist/materials.d.ts +0 -10
- package/dist/materials.d.ts.map +0 -1
- package/dist/materials.js +0 -22
- package/dist/systems/ceiling/ceiling-system.d.ts +0 -8
- package/dist/systems/ceiling/ceiling-system.d.ts.map +0 -1
- package/dist/systems/ceiling/ceiling-system.js +0 -92
- package/dist/systems/door/door-system.d.ts +0 -2
- package/dist/systems/door/door-system.d.ts.map +0 -1
- package/dist/systems/door/door-system.js +0 -195
- package/dist/systems/fence/fence-system.d.ts +0 -2
- package/dist/systems/fence/fence-system.d.ts.map +0 -1
- package/dist/systems/fence/fence-system.js +0 -187
- package/dist/systems/item/item-system.d.ts +0 -2
- package/dist/systems/item/item-system.d.ts.map +0 -1
- package/dist/systems/item/item-system.js +0 -48
- package/dist/systems/roof/roof-system.d.ts +0 -16
- package/dist/systems/roof/roof-system.d.ts.map +0 -1
- package/dist/systems/roof/roof-system.js +0 -797
- package/dist/systems/slab/slab-system.d.ts +0 -8
- package/dist/systems/slab/slab-system.d.ts.map +0 -1
- package/dist/systems/slab/slab-system.js +0 -214
- package/dist/systems/stair/stair-system.d.ts +0 -2
- package/dist/systems/stair/stair-system.d.ts.map +0 -1
- package/dist/systems/stair/stair-system.js +0 -776
- package/dist/systems/wall/wall-system.d.ts +0 -12
- package/dist/systems/wall/wall-system.d.ts.map +0 -1
- package/dist/systems/wall/wall-system.js +0 -455
- package/dist/systems/window/window-system.d.ts +0 -2
- package/dist/systems/window/window-system.d.ts.map +0 -1
- package/dist/systems/window/window-system.js +0 -131
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import type { MaterialSchema as MaterialSchemaType } from '../material';
|
|
2
3
|
export declare const RoofType: z.ZodEnum<{
|
|
4
|
+
flat: "flat";
|
|
3
5
|
hip: "hip";
|
|
4
6
|
gable: "gable";
|
|
5
7
|
shed: "shed";
|
|
6
8
|
gambrel: "gambrel";
|
|
7
9
|
dutch: "dutch";
|
|
8
10
|
mansard: "mansard";
|
|
9
|
-
flat: "flat";
|
|
10
11
|
}>;
|
|
11
12
|
export type RoofType = z.infer<typeof RoofType>;
|
|
13
|
+
export declare const ROOF_SHAPE_DEFAULTS: {
|
|
14
|
+
/** Gambrel: lower (steep) face occupies this fraction of the horizontal half-depth. */
|
|
15
|
+
readonly gambrelLowerWidthRatio: 0.5;
|
|
16
|
+
/** Gambrel: lower (steep) face rises this fraction of the way to the peak. */
|
|
17
|
+
readonly gambrelLowerHeightRatio: 0.6;
|
|
18
|
+
/** Mansard: steep face occupies this fraction of `min(width, depth)`. */
|
|
19
|
+
readonly mansardSteepWidthRatio: 0.15;
|
|
20
|
+
/** Mansard: steep face rises this fraction of the way to the peak. */
|
|
21
|
+
readonly mansardSteepHeightRatio: 0.7;
|
|
22
|
+
/** Dutch: hip face occupies this fraction of `min(width, depth)`. */
|
|
23
|
+
readonly dutchHipWidthRatio: 0.25;
|
|
24
|
+
/** Dutch: hip face rises this fraction of the way to the peak. */
|
|
25
|
+
readonly dutchHipHeightRatio: 0.5;
|
|
26
|
+
};
|
|
12
27
|
export declare const RoofSegmentNode: z.ZodObject<{
|
|
13
28
|
object: z.ZodDefault<z.ZodLiteral<"node">>;
|
|
14
29
|
name: z.ZodOptional<z.ZodString>;
|
|
@@ -30,6 +45,7 @@ export declare const RoofSegmentNode: z.ZodObject<{
|
|
|
30
45
|
material: z.ZodOptional<z.ZodObject<{
|
|
31
46
|
id: z.ZodOptional<z.ZodString>;
|
|
32
47
|
preset: z.ZodOptional<z.ZodEnum<{
|
|
48
|
+
custom: "custom";
|
|
33
49
|
white: "white";
|
|
34
50
|
brick: "brick";
|
|
35
51
|
concrete: "concrete";
|
|
@@ -39,7 +55,6 @@ export declare const RoofSegmentNode: z.ZodObject<{
|
|
|
39
55
|
plaster: "plaster";
|
|
40
56
|
tile: "tile";
|
|
41
57
|
marble: "marble";
|
|
42
|
-
custom: "custom";
|
|
43
58
|
}>>;
|
|
44
59
|
properties: z.ZodOptional<z.ZodObject<{
|
|
45
60
|
color: z.ZodDefault<z.ZodString>;
|
|
@@ -60,25 +75,204 @@ export declare const RoofSegmentNode: z.ZodObject<{
|
|
|
60
75
|
}, z.core.$strip>>;
|
|
61
76
|
}, z.core.$strip>>;
|
|
62
77
|
materialPreset: z.ZodOptional<z.ZodString>;
|
|
78
|
+
topMaterial: z.ZodOptional<z.ZodObject<{
|
|
79
|
+
id: z.ZodOptional<z.ZodString>;
|
|
80
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
81
|
+
custom: "custom";
|
|
82
|
+
white: "white";
|
|
83
|
+
brick: "brick";
|
|
84
|
+
concrete: "concrete";
|
|
85
|
+
wood: "wood";
|
|
86
|
+
glass: "glass";
|
|
87
|
+
metal: "metal";
|
|
88
|
+
plaster: "plaster";
|
|
89
|
+
tile: "tile";
|
|
90
|
+
marble: "marble";
|
|
91
|
+
}>>;
|
|
92
|
+
properties: z.ZodOptional<z.ZodObject<{
|
|
93
|
+
color: z.ZodDefault<z.ZodString>;
|
|
94
|
+
roughness: z.ZodDefault<z.ZodNumber>;
|
|
95
|
+
metalness: z.ZodDefault<z.ZodNumber>;
|
|
96
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
97
|
+
transparent: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
side: z.ZodDefault<z.ZodEnum<{
|
|
99
|
+
front: "front";
|
|
100
|
+
back: "back";
|
|
101
|
+
double: "double";
|
|
102
|
+
}>>;
|
|
103
|
+
}, z.core.$strip>>;
|
|
104
|
+
texture: z.ZodOptional<z.ZodObject<{
|
|
105
|
+
url: z.ZodString;
|
|
106
|
+
repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
107
|
+
scale: z.ZodOptional<z.ZodNumber>;
|
|
108
|
+
}, z.core.$strip>>;
|
|
109
|
+
}, z.core.$strip>>;
|
|
110
|
+
topMaterialPreset: z.ZodOptional<z.ZodString>;
|
|
111
|
+
edgeMaterial: z.ZodOptional<z.ZodObject<{
|
|
112
|
+
id: z.ZodOptional<z.ZodString>;
|
|
113
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
114
|
+
custom: "custom";
|
|
115
|
+
white: "white";
|
|
116
|
+
brick: "brick";
|
|
117
|
+
concrete: "concrete";
|
|
118
|
+
wood: "wood";
|
|
119
|
+
glass: "glass";
|
|
120
|
+
metal: "metal";
|
|
121
|
+
plaster: "plaster";
|
|
122
|
+
tile: "tile";
|
|
123
|
+
marble: "marble";
|
|
124
|
+
}>>;
|
|
125
|
+
properties: z.ZodOptional<z.ZodObject<{
|
|
126
|
+
color: z.ZodDefault<z.ZodString>;
|
|
127
|
+
roughness: z.ZodDefault<z.ZodNumber>;
|
|
128
|
+
metalness: z.ZodDefault<z.ZodNumber>;
|
|
129
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
130
|
+
transparent: z.ZodDefault<z.ZodBoolean>;
|
|
131
|
+
side: z.ZodDefault<z.ZodEnum<{
|
|
132
|
+
front: "front";
|
|
133
|
+
back: "back";
|
|
134
|
+
double: "double";
|
|
135
|
+
}>>;
|
|
136
|
+
}, z.core.$strip>>;
|
|
137
|
+
texture: z.ZodOptional<z.ZodObject<{
|
|
138
|
+
url: z.ZodString;
|
|
139
|
+
repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
140
|
+
scale: z.ZodOptional<z.ZodNumber>;
|
|
141
|
+
}, z.core.$strip>>;
|
|
142
|
+
}, z.core.$strip>>;
|
|
143
|
+
edgeMaterialPreset: z.ZodOptional<z.ZodString>;
|
|
144
|
+
wallMaterial: z.ZodOptional<z.ZodObject<{
|
|
145
|
+
id: z.ZodOptional<z.ZodString>;
|
|
146
|
+
preset: z.ZodOptional<z.ZodEnum<{
|
|
147
|
+
custom: "custom";
|
|
148
|
+
white: "white";
|
|
149
|
+
brick: "brick";
|
|
150
|
+
concrete: "concrete";
|
|
151
|
+
wood: "wood";
|
|
152
|
+
glass: "glass";
|
|
153
|
+
metal: "metal";
|
|
154
|
+
plaster: "plaster";
|
|
155
|
+
tile: "tile";
|
|
156
|
+
marble: "marble";
|
|
157
|
+
}>>;
|
|
158
|
+
properties: z.ZodOptional<z.ZodObject<{
|
|
159
|
+
color: z.ZodDefault<z.ZodString>;
|
|
160
|
+
roughness: z.ZodDefault<z.ZodNumber>;
|
|
161
|
+
metalness: z.ZodDefault<z.ZodNumber>;
|
|
162
|
+
opacity: z.ZodDefault<z.ZodNumber>;
|
|
163
|
+
transparent: z.ZodDefault<z.ZodBoolean>;
|
|
164
|
+
side: z.ZodDefault<z.ZodEnum<{
|
|
165
|
+
front: "front";
|
|
166
|
+
back: "back";
|
|
167
|
+
double: "double";
|
|
168
|
+
}>>;
|
|
169
|
+
}, z.core.$strip>>;
|
|
170
|
+
texture: z.ZodOptional<z.ZodObject<{
|
|
171
|
+
url: z.ZodString;
|
|
172
|
+
repeat: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber], null>>;
|
|
173
|
+
scale: z.ZodOptional<z.ZodNumber>;
|
|
174
|
+
}, z.core.$strip>>;
|
|
175
|
+
}, z.core.$strip>>;
|
|
176
|
+
wallMaterialPreset: z.ZodOptional<z.ZodString>;
|
|
63
177
|
position: z.ZodDefault<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
|
|
64
178
|
rotation: z.ZodDefault<z.ZodNumber>;
|
|
65
179
|
roofType: z.ZodDefault<z.ZodEnum<{
|
|
180
|
+
flat: "flat";
|
|
66
181
|
hip: "hip";
|
|
67
182
|
gable: "gable";
|
|
68
183
|
shed: "shed";
|
|
69
184
|
gambrel: "gambrel";
|
|
70
185
|
dutch: "dutch";
|
|
71
186
|
mansard: "mansard";
|
|
72
|
-
flat: "flat";
|
|
73
187
|
}>>;
|
|
74
188
|
width: z.ZodDefault<z.ZodNumber>;
|
|
75
189
|
depth: z.ZodDefault<z.ZodNumber>;
|
|
76
190
|
wallHeight: z.ZodDefault<z.ZodNumber>;
|
|
77
|
-
|
|
191
|
+
pitch: z.ZodDefault<z.ZodNumber>;
|
|
78
192
|
wallThickness: z.ZodDefault<z.ZodNumber>;
|
|
79
193
|
deckThickness: z.ZodDefault<z.ZodNumber>;
|
|
80
194
|
overhang: z.ZodDefault<z.ZodNumber>;
|
|
81
195
|
shingleThickness: z.ZodDefault<z.ZodNumber>;
|
|
196
|
+
gambrelLowerWidthRatio: z.ZodDefault<z.ZodNumber>;
|
|
197
|
+
gambrelLowerHeightRatio: z.ZodDefault<z.ZodNumber>;
|
|
198
|
+
mansardSteepWidthRatio: z.ZodDefault<z.ZodNumber>;
|
|
199
|
+
mansardSteepHeightRatio: z.ZodDefault<z.ZodNumber>;
|
|
200
|
+
dutchHipWidthRatio: z.ZodDefault<z.ZodNumber>;
|
|
201
|
+
dutchHipHeightRatio: z.ZodDefault<z.ZodNumber>;
|
|
202
|
+
children: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
82
203
|
}, z.core.$strip>;
|
|
83
204
|
export type RoofSegmentNode = z.infer<typeof RoofSegmentNode>;
|
|
205
|
+
/** Shape of the per-type ratios consumed by the slope helpers. */
|
|
206
|
+
type ShapeRatios = {
|
|
207
|
+
gambrelLowerWidthRatio: number;
|
|
208
|
+
gambrelLowerHeightRatio: number;
|
|
209
|
+
mansardSteepWidthRatio: number;
|
|
210
|
+
mansardSteepHeightRatio: number;
|
|
211
|
+
dutchHipWidthRatio: number;
|
|
212
|
+
dutchHipHeightRatio: number;
|
|
213
|
+
};
|
|
214
|
+
type PitchInputs = {
|
|
215
|
+
roofType: RoofType;
|
|
216
|
+
width: number;
|
|
217
|
+
depth: number;
|
|
218
|
+
} & Partial<ShapeRatios>;
|
|
219
|
+
export type SegmentSlopeFrame = {
|
|
220
|
+
/** Horizontal half-span of the primary slope face (eave-to-ridge). */
|
|
221
|
+
run: number;
|
|
222
|
+
/** Vertical height of the primary slope face. */
|
|
223
|
+
rise: number;
|
|
224
|
+
/** tan(pitch). 0 for flat or zero-pitch segments. */
|
|
225
|
+
tanTheta: number;
|
|
226
|
+
/** cos(pitch). 1 for flat or zero-pitch segments. */
|
|
227
|
+
cosTheta: number;
|
|
228
|
+
/** sin(pitch). 0 for flat or zero-pitch segments. */
|
|
229
|
+
sinTheta: number;
|
|
230
|
+
/** Overall eave-to-peak height of the assembled roof. */
|
|
231
|
+
activeRh: number;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* One stop for the slope math every roof-segment consumer needs. Builds
|
|
235
|
+
* `run`, `rise`, the trig triple, and the overall peak height from the
|
|
236
|
+
* segment's pitch + footprint + roofType. Before this helper existed,
|
|
237
|
+
* the table was duplicated in three places (the brush builder, the
|
|
238
|
+
* skylight surface-frame routine, and the segment-hit raycaster) and
|
|
239
|
+
* silently drifted when a new roof type was added.
|
|
240
|
+
*/
|
|
241
|
+
export declare function getSegmentSlopeFrame(node: Pick<RoofSegmentNode, 'roofType' | 'pitch' | 'width' | 'depth'> & Partial<ShapeRatios>): SegmentSlopeFrame;
|
|
242
|
+
/**
|
|
243
|
+
* The eave-to-peak height of the assembled segment, derived from pitch +
|
|
244
|
+
* footprint + roofType. Replaces the legacy `roofHeight` field on the node.
|
|
245
|
+
*/
|
|
246
|
+
export declare function getActiveRoofHeight(node: Parameters<typeof getSegmentSlopeFrame>[0]): number;
|
|
247
|
+
/** Segment-local surface height used by roof accessory placement and hit disambiguation. */
|
|
248
|
+
export declare function getRoofSegmentSurfaceY(node: Pick<RoofSegmentNode, 'roofType' | 'width' | 'depth' | 'wallHeight'> & Parameters<typeof getSegmentSlopeFrame>[0], localX: number, localZ: number): number;
|
|
249
|
+
/**
|
|
250
|
+
* Inverse of `getActiveRoofHeight` — recover the pitch a legacy
|
|
251
|
+
* `roofHeight` value would correspond to. Used by the scene migration.
|
|
252
|
+
* Ratio overrides are optional and default to the shape defaults.
|
|
253
|
+
*/
|
|
254
|
+
export declare function getPitchFromActiveRoofHeight(input: PitchInputs & {
|
|
255
|
+
roofHeight: number;
|
|
256
|
+
}): number;
|
|
257
|
+
export type RoofSegmentSurfaceMaterialRole = 'top' | 'edge' | 'wall';
|
|
258
|
+
export type RoofSegmentSurfaceMaterialSpec = {
|
|
259
|
+
material?: MaterialSchemaType;
|
|
260
|
+
materialPreset?: string;
|
|
261
|
+
};
|
|
262
|
+
/**
|
|
263
|
+
* Resolve the segment-level material for one of the three surface roles.
|
|
264
|
+
* Falls back through: role-specific field → catch-all `material`. Pass the
|
|
265
|
+
* parent roof to `parentFallback` when you want the roof's role material
|
|
266
|
+
* to fill in for an unset segment slot — typical from the renderer.
|
|
267
|
+
*/
|
|
268
|
+
export declare function getEffectiveSegmentSurfaceMaterial(node: RoofSegmentNode, role: RoofSegmentSurfaceMaterialRole, parentFallback?: RoofSegmentSurfaceMaterialSpec): RoofSegmentSurfaceMaterialSpec;
|
|
269
|
+
/**
|
|
270
|
+
* Returns true when the segment has any segment-level material override —
|
|
271
|
+
* either the legacy catch-all or any of the three role-specific fields.
|
|
272
|
+
* Used by `RoofRenderer` and `updateMergedRoofGeometry` to decide whether
|
|
273
|
+
* the segment should be drawn as its own mesh or folded into the merged
|
|
274
|
+
* shell.
|
|
275
|
+
*/
|
|
276
|
+
export declare function hasSegmentMaterialOverride(node: RoofSegmentNode): boolean;
|
|
277
|
+
export {};
|
|
84
278
|
//# sourceMappingURL=roof-segment.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roof-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;
|
|
1
|
+
{"version":3,"file":"roof-segment.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof-segment.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,11 +3,40 @@ import { z } from 'zod';
|
|
|
3
3
|
import { BaseNode, nodeType, objectId } from '../base';
|
|
4
4
|
import { MaterialSchema } from '../material';
|
|
5
5
|
export const RoofType = z.enum(['hip', 'gable', 'shed', 'gambrel', 'dutch', 'mansard', 'flat']);
|
|
6
|
+
// Default shape ratios. Tuning these used to require editing the geometry
|
|
7
|
+
// code in two places; they are now schema fields with these defaults.
|
|
8
|
+
export const ROOF_SHAPE_DEFAULTS = {
|
|
9
|
+
/** Gambrel: lower (steep) face occupies this fraction of the horizontal half-depth. */
|
|
10
|
+
gambrelLowerWidthRatio: 0.5,
|
|
11
|
+
/** Gambrel: lower (steep) face rises this fraction of the way to the peak. */
|
|
12
|
+
gambrelLowerHeightRatio: 0.6,
|
|
13
|
+
/** Mansard: steep face occupies this fraction of `min(width, depth)`. */
|
|
14
|
+
mansardSteepWidthRatio: 0.15,
|
|
15
|
+
/** Mansard: steep face rises this fraction of the way to the peak. */
|
|
16
|
+
mansardSteepHeightRatio: 0.7,
|
|
17
|
+
/** Dutch: hip face occupies this fraction of `min(width, depth)`. */
|
|
18
|
+
dutchHipWidthRatio: 0.25,
|
|
19
|
+
/** Dutch: hip face rises this fraction of the way to the peak. */
|
|
20
|
+
dutchHipHeightRatio: 0.5,
|
|
21
|
+
};
|
|
6
22
|
export const RoofSegmentNode = BaseNode.extend({
|
|
7
23
|
id: objectId('rseg'),
|
|
8
24
|
type: nodeType('roof-segment'),
|
|
25
|
+
// Catch-all material — splatted across all 4 slots in the renderer
|
|
26
|
+
// when no role-specific override is set. Kept for back-compat with
|
|
27
|
+
// older scenes; new paint operations should prefer the role fields.
|
|
9
28
|
material: MaterialSchema.optional(),
|
|
10
29
|
materialPreset: z.string().optional(),
|
|
30
|
+
// Role-specific overrides mirror the parent roof's surface roles.
|
|
31
|
+
// When set they win over the segment's catch-all `material` and over
|
|
32
|
+
// the parent roof's role / catch-all materials. Resolution order:
|
|
33
|
+
// segment role → segment catch-all → roof role → roof catch-all.
|
|
34
|
+
topMaterial: MaterialSchema.optional(),
|
|
35
|
+
topMaterialPreset: z.string().optional(),
|
|
36
|
+
edgeMaterial: MaterialSchema.optional(),
|
|
37
|
+
edgeMaterialPreset: z.string().optional(),
|
|
38
|
+
wallMaterial: MaterialSchema.optional(),
|
|
39
|
+
wallMaterialPreset: z.string().optional(),
|
|
11
40
|
position: z.tuple([z.number(), z.number(), z.number()]).default([0, 0, 0]),
|
|
12
41
|
// Rotation around Y axis in radians
|
|
13
42
|
rotation: z.number().default(0),
|
|
@@ -16,14 +45,60 @@ export const RoofSegmentNode = BaseNode.extend({
|
|
|
16
45
|
// Footprint dimensions
|
|
17
46
|
width: z.number().default(8),
|
|
18
47
|
depth: z.number().default(6),
|
|
19
|
-
//
|
|
48
|
+
// Wall height beneath the roof
|
|
20
49
|
wallHeight: z.number().default(0.5),
|
|
21
|
-
|
|
50
|
+
// Roof pitch in degrees — angle of the primary slope face.
|
|
51
|
+
// For gable/hip/shed this is the only slope; for gambrel/mansard/dutch
|
|
52
|
+
// it is the steep (lower) slope. The overall peak height is derived
|
|
53
|
+
// from pitch + footprint + roofType via getActiveRoofHeight().
|
|
54
|
+
pitch: z.number().min(0).max(85).default(40),
|
|
22
55
|
// Structure thicknesses
|
|
23
56
|
wallThickness: z.number().default(0.1),
|
|
24
57
|
deckThickness: z.number().default(0.1),
|
|
25
58
|
overhang: z.number().default(0.3),
|
|
26
59
|
shingleThickness: z.number().default(0.05),
|
|
60
|
+
// Shape-specific ratios. Only the pair matching `roofType` is read; the
|
|
61
|
+
// rest are inert. Defined on every segment so the panel can flip
|
|
62
|
+
// roofType without losing the previous shape's tuning.
|
|
63
|
+
gambrelLowerWidthRatio: z
|
|
64
|
+
.number()
|
|
65
|
+
.min(0.1)
|
|
66
|
+
.max(0.9)
|
|
67
|
+
.default(ROOF_SHAPE_DEFAULTS.gambrelLowerWidthRatio),
|
|
68
|
+
gambrelLowerHeightRatio: z
|
|
69
|
+
.number()
|
|
70
|
+
.min(0.1)
|
|
71
|
+
.max(0.9)
|
|
72
|
+
.default(ROOF_SHAPE_DEFAULTS.gambrelLowerHeightRatio),
|
|
73
|
+
mansardSteepWidthRatio: z
|
|
74
|
+
.number()
|
|
75
|
+
.min(0.05)
|
|
76
|
+
.max(0.45)
|
|
77
|
+
.default(ROOF_SHAPE_DEFAULTS.mansardSteepWidthRatio),
|
|
78
|
+
mansardSteepHeightRatio: z
|
|
79
|
+
.number()
|
|
80
|
+
.min(0.1)
|
|
81
|
+
.max(0.9)
|
|
82
|
+
.default(ROOF_SHAPE_DEFAULTS.mansardSteepHeightRatio),
|
|
83
|
+
dutchHipWidthRatio: z
|
|
84
|
+
.number()
|
|
85
|
+
.min(0.05)
|
|
86
|
+
.max(0.45)
|
|
87
|
+
.default(ROOF_SHAPE_DEFAULTS.dutchHipWidthRatio),
|
|
88
|
+
dutchHipHeightRatio: z
|
|
89
|
+
.number()
|
|
90
|
+
.min(0.1)
|
|
91
|
+
.max(0.9)
|
|
92
|
+
.default(ROOF_SHAPE_DEFAULTS.dutchHipHeightRatio),
|
|
93
|
+
// Hosted accessories — chimney, dormer, skylight, box-vent,
|
|
94
|
+
// ridge-vent, solar-panel, gutter. Each accessory's `parentId` points back
|
|
95
|
+
// here; the segment renderer mounts them recursively via
|
|
96
|
+
// `<NodeRenderer>` so they inherit the segment's transform stack.
|
|
97
|
+
// Required for `createNode(child, segmentId)` to append the child
|
|
98
|
+
// to this array — see
|
|
99
|
+
// `wiki/architecture/node-definitions.md` ("Host kinds need a
|
|
100
|
+
// `children` field on the schema").
|
|
101
|
+
children: z.array(z.string()).default([]),
|
|
27
102
|
}).describe(dedent `
|
|
28
103
|
Roof segment node - an individual roof module within a roof group.
|
|
29
104
|
Each segment generates a complete architectural volume (walls + roof).
|
|
@@ -31,8 +106,184 @@ export const RoofSegmentNode = BaseNode.extend({
|
|
|
31
106
|
- roofType: hip, gable, shed, gambrel, dutch, mansard, flat
|
|
32
107
|
- width/depth: footprint dimensions
|
|
33
108
|
- wallHeight: height of walls below the roof
|
|
34
|
-
-
|
|
109
|
+
- pitch: roof slope in degrees (angle of the primary slope face)
|
|
35
110
|
- wallThickness/deckThickness: structural thicknesses
|
|
36
111
|
- overhang: eave overhang distance
|
|
37
112
|
- shingleThickness: outer shingle layer thickness
|
|
113
|
+
- gambrelLowerWidthRatio / gambrelLowerHeightRatio: kink position on gambrel roofs
|
|
114
|
+
- mansardSteepWidthRatio / mansardSteepHeightRatio: waist position on mansard roofs
|
|
115
|
+
- dutchHipWidthRatio / dutchHipHeightRatio: hip-to-gable split on dutch roofs
|
|
38
116
|
`);
|
|
117
|
+
function withRatioDefaults(input) {
|
|
118
|
+
return {
|
|
119
|
+
...input,
|
|
120
|
+
gambrelLowerWidthRatio: input.gambrelLowerWidthRatio ?? ROOF_SHAPE_DEFAULTS.gambrelLowerWidthRatio,
|
|
121
|
+
gambrelLowerHeightRatio: input.gambrelLowerHeightRatio ?? ROOF_SHAPE_DEFAULTS.gambrelLowerHeightRatio,
|
|
122
|
+
mansardSteepWidthRatio: input.mansardSteepWidthRatio ?? ROOF_SHAPE_DEFAULTS.mansardSteepWidthRatio,
|
|
123
|
+
mansardSteepHeightRatio: input.mansardSteepHeightRatio ?? ROOF_SHAPE_DEFAULTS.mansardSteepHeightRatio,
|
|
124
|
+
dutchHipWidthRatio: input.dutchHipWidthRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipWidthRatio,
|
|
125
|
+
dutchHipHeightRatio: input.dutchHipHeightRatio ?? ROOF_SHAPE_DEFAULTS.dutchHipHeightRatio,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function getPrimarySlopeRun(input) {
|
|
129
|
+
const min = Math.min(input.width, input.depth);
|
|
130
|
+
switch (input.roofType) {
|
|
131
|
+
case 'shed':
|
|
132
|
+
return input.depth;
|
|
133
|
+
case 'gable':
|
|
134
|
+
return input.depth / 2;
|
|
135
|
+
case 'gambrel':
|
|
136
|
+
return (input.depth / 2) * input.gambrelLowerWidthRatio;
|
|
137
|
+
case 'mansard':
|
|
138
|
+
return min * input.mansardSteepWidthRatio;
|
|
139
|
+
case 'dutch':
|
|
140
|
+
return min * input.dutchHipWidthRatio;
|
|
141
|
+
default:
|
|
142
|
+
return min / 2;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Fraction of the overall peak height that is taken up by the primary slope.
|
|
146
|
+
function getPrimarySlopeRiseFraction(input) {
|
|
147
|
+
switch (input.roofType) {
|
|
148
|
+
case 'gambrel':
|
|
149
|
+
return input.gambrelLowerHeightRatio;
|
|
150
|
+
case 'mansard':
|
|
151
|
+
return input.mansardSteepHeightRatio;
|
|
152
|
+
case 'dutch':
|
|
153
|
+
return input.dutchHipHeightRatio;
|
|
154
|
+
default:
|
|
155
|
+
return 1;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* One stop for the slope math every roof-segment consumer needs. Builds
|
|
160
|
+
* `run`, `rise`, the trig triple, and the overall peak height from the
|
|
161
|
+
* segment's pitch + footprint + roofType. Before this helper existed,
|
|
162
|
+
* the table was duplicated in three places (the brush builder, the
|
|
163
|
+
* skylight surface-frame routine, and the segment-hit raycaster) and
|
|
164
|
+
* silently drifted when a new roof type was added.
|
|
165
|
+
*/
|
|
166
|
+
export function getSegmentSlopeFrame(node) {
|
|
167
|
+
const ratios = withRatioDefaults(node);
|
|
168
|
+
const run = getPrimarySlopeRun(ratios);
|
|
169
|
+
// `!(pitch > 0)` (not `pitch <= 0`) so a missing/NaN pitch — e.g. a segment
|
|
170
|
+
// from an older migration that only set `roofHeight`, or stale persisted data —
|
|
171
|
+
// resolves to a flat frame instead of computing `Math.tan(NaN)` → NaN geometry,
|
|
172
|
+
// which poisons the merged-roof CSG ("Coplanar clip not handled" + NaN positions).
|
|
173
|
+
if (node.roofType === 'flat' || !(node.pitch > 0)) {
|
|
174
|
+
return { run, rise: 0, tanTheta: 0, cosTheta: 1, sinTheta: 0, activeRh: 0 };
|
|
175
|
+
}
|
|
176
|
+
const pitchRad = (node.pitch * Math.PI) / 180;
|
|
177
|
+
const tanTheta = Math.tan(pitchRad);
|
|
178
|
+
const cosTheta = Math.cos(pitchRad) || 1;
|
|
179
|
+
const sinTheta = Math.sin(pitchRad);
|
|
180
|
+
const rise = run * tanTheta;
|
|
181
|
+
const activeRh = rise / getPrimarySlopeRiseFraction(ratios);
|
|
182
|
+
return { run, rise, tanTheta, cosTheta, sinTheta, activeRh };
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* The eave-to-peak height of the assembled segment, derived from pitch +
|
|
186
|
+
* footprint + roofType. Replaces the legacy `roofHeight` field on the node.
|
|
187
|
+
*/
|
|
188
|
+
export function getActiveRoofHeight(node) {
|
|
189
|
+
return getSegmentSlopeFrame(node).activeRh;
|
|
190
|
+
}
|
|
191
|
+
/** Segment-local surface height used by roof accessory placement and hit disambiguation. */
|
|
192
|
+
export function getRoofSegmentSurfaceY(node, localX, localZ) {
|
|
193
|
+
const activeRh = getActiveRoofHeight(node);
|
|
194
|
+
const peakY = node.wallHeight + activeRh;
|
|
195
|
+
if (activeRh === 0)
|
|
196
|
+
return node.wallHeight;
|
|
197
|
+
if (node.roofType === 'gable' ||
|
|
198
|
+
node.roofType === 'gambrel' ||
|
|
199
|
+
node.roofType === 'mansard' ||
|
|
200
|
+
node.roofType === 'dutch') {
|
|
201
|
+
const t = node.depth > 0 ? Math.abs(localZ) / (node.depth / 2) : 0;
|
|
202
|
+
return peakY - t * activeRh;
|
|
203
|
+
}
|
|
204
|
+
if (node.roofType === 'shed') {
|
|
205
|
+
const t = (localZ + node.depth / 2) / (node.depth || 1);
|
|
206
|
+
return peakY - t * activeRh;
|
|
207
|
+
}
|
|
208
|
+
if (node.roofType === 'hip') {
|
|
209
|
+
const fx = node.width > 0 ? Math.abs(localX) / (node.width / 2) : 0;
|
|
210
|
+
const fz = node.depth > 0 ? Math.abs(localZ) / (node.depth / 2) : 0;
|
|
211
|
+
return peakY - Math.max(fx, fz) * activeRh;
|
|
212
|
+
}
|
|
213
|
+
const t = node.depth > 0 ? Math.abs(localZ) / (node.depth / 2) : 0;
|
|
214
|
+
return peakY - t * activeRh;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Inverse of `getActiveRoofHeight` — recover the pitch a legacy
|
|
218
|
+
* `roofHeight` value would correspond to. Used by the scene migration.
|
|
219
|
+
* Ratio overrides are optional and default to the shape defaults.
|
|
220
|
+
*/
|
|
221
|
+
export function getPitchFromActiveRoofHeight(input) {
|
|
222
|
+
if (input.roofType === 'flat' || input.roofHeight <= 0)
|
|
223
|
+
return 0;
|
|
224
|
+
const ratios = withRatioDefaults(input);
|
|
225
|
+
const run = getPrimarySlopeRun(ratios);
|
|
226
|
+
if (run <= 0)
|
|
227
|
+
return 0;
|
|
228
|
+
const rise = input.roofHeight * getPrimarySlopeRiseFraction(ratios);
|
|
229
|
+
return (Math.atan2(rise, run) * 180) / Math.PI;
|
|
230
|
+
}
|
|
231
|
+
function getLegacyRoofSegmentSurfaceMaterial(node) {
|
|
232
|
+
return {
|
|
233
|
+
material: node.material,
|
|
234
|
+
materialPreset: typeof node.materialPreset === 'string' ? node.materialPreset : undefined,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Resolve the segment-level material for one of the three surface roles.
|
|
239
|
+
* Falls back through: role-specific field → catch-all `material`. Pass the
|
|
240
|
+
* parent roof to `parentFallback` when you want the roof's role material
|
|
241
|
+
* to fill in for an unset segment slot — typical from the renderer.
|
|
242
|
+
*/
|
|
243
|
+
export function getEffectiveSegmentSurfaceMaterial(node, role, parentFallback) {
|
|
244
|
+
if (role === 'top') {
|
|
245
|
+
if (node.topMaterial !== undefined || typeof node.topMaterialPreset === 'string') {
|
|
246
|
+
return {
|
|
247
|
+
material: node.topMaterial,
|
|
248
|
+
materialPreset: typeof node.topMaterialPreset === 'string' ? node.topMaterialPreset : undefined,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
else if (role === 'edge') {
|
|
253
|
+
if (node.edgeMaterial !== undefined || typeof node.edgeMaterialPreset === 'string') {
|
|
254
|
+
return {
|
|
255
|
+
material: node.edgeMaterial,
|
|
256
|
+
materialPreset: typeof node.edgeMaterialPreset === 'string' ? node.edgeMaterialPreset : undefined,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
else if (role === 'wall') {
|
|
261
|
+
if (node.wallMaterial !== undefined || typeof node.wallMaterialPreset === 'string') {
|
|
262
|
+
return {
|
|
263
|
+
material: node.wallMaterial,
|
|
264
|
+
materialPreset: typeof node.wallMaterialPreset === 'string' ? node.wallMaterialPreset : undefined,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
const legacy = getLegacyRoofSegmentSurfaceMaterial(node);
|
|
269
|
+
if (legacy.material !== undefined || legacy.materialPreset !== undefined)
|
|
270
|
+
return legacy;
|
|
271
|
+
return parentFallback ?? { material: undefined, materialPreset: undefined };
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Returns true when the segment has any segment-level material override —
|
|
275
|
+
* either the legacy catch-all or any of the three role-specific fields.
|
|
276
|
+
* Used by `RoofRenderer` and `updateMergedRoofGeometry` to decide whether
|
|
277
|
+
* the segment should be drawn as its own mesh or folded into the merged
|
|
278
|
+
* shell.
|
|
279
|
+
*/
|
|
280
|
+
export function hasSegmentMaterialOverride(node) {
|
|
281
|
+
return (node.material !== undefined ||
|
|
282
|
+
typeof node.materialPreset === 'string' ||
|
|
283
|
+
node.topMaterial !== undefined ||
|
|
284
|
+
typeof node.topMaterialPreset === 'string' ||
|
|
285
|
+
node.edgeMaterial !== undefined ||
|
|
286
|
+
typeof node.edgeMaterialPreset === 'string' ||
|
|
287
|
+
node.wallMaterial !== undefined ||
|
|
288
|
+
typeof node.wallMaterialPreset === 'string');
|
|
289
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import {
|
|
2
|
+
import type { MaterialSchema as MaterialSchemaType } from '../material';
|
|
3
3
|
export type RoofSurfaceMaterialRole = 'top' | 'edge' | 'wall';
|
|
4
4
|
export type RoofSurfaceMaterialSpec = {
|
|
5
|
-
material?:
|
|
5
|
+
material?: MaterialSchemaType;
|
|
6
6
|
materialPreset?: string;
|
|
7
7
|
};
|
|
8
8
|
export declare const RoofNode: z.ZodObject<{
|
|
@@ -26,6 +26,7 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
26
26
|
material: z.ZodOptional<z.ZodObject<{
|
|
27
27
|
id: z.ZodOptional<z.ZodString>;
|
|
28
28
|
preset: z.ZodOptional<z.ZodEnum<{
|
|
29
|
+
custom: "custom";
|
|
29
30
|
white: "white";
|
|
30
31
|
brick: "brick";
|
|
31
32
|
concrete: "concrete";
|
|
@@ -35,7 +36,6 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
35
36
|
plaster: "plaster";
|
|
36
37
|
tile: "tile";
|
|
37
38
|
marble: "marble";
|
|
38
|
-
custom: "custom";
|
|
39
39
|
}>>;
|
|
40
40
|
properties: z.ZodOptional<z.ZodObject<{
|
|
41
41
|
color: z.ZodDefault<z.ZodString>;
|
|
@@ -59,6 +59,7 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
59
59
|
topMaterial: z.ZodOptional<z.ZodObject<{
|
|
60
60
|
id: z.ZodOptional<z.ZodString>;
|
|
61
61
|
preset: z.ZodOptional<z.ZodEnum<{
|
|
62
|
+
custom: "custom";
|
|
62
63
|
white: "white";
|
|
63
64
|
brick: "brick";
|
|
64
65
|
concrete: "concrete";
|
|
@@ -68,7 +69,6 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
68
69
|
plaster: "plaster";
|
|
69
70
|
tile: "tile";
|
|
70
71
|
marble: "marble";
|
|
71
|
-
custom: "custom";
|
|
72
72
|
}>>;
|
|
73
73
|
properties: z.ZodOptional<z.ZodObject<{
|
|
74
74
|
color: z.ZodDefault<z.ZodString>;
|
|
@@ -92,6 +92,7 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
92
92
|
edgeMaterial: z.ZodOptional<z.ZodObject<{
|
|
93
93
|
id: z.ZodOptional<z.ZodString>;
|
|
94
94
|
preset: z.ZodOptional<z.ZodEnum<{
|
|
95
|
+
custom: "custom";
|
|
95
96
|
white: "white";
|
|
96
97
|
brick: "brick";
|
|
97
98
|
concrete: "concrete";
|
|
@@ -101,7 +102,6 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
101
102
|
plaster: "plaster";
|
|
102
103
|
tile: "tile";
|
|
103
104
|
marble: "marble";
|
|
104
|
-
custom: "custom";
|
|
105
105
|
}>>;
|
|
106
106
|
properties: z.ZodOptional<z.ZodObject<{
|
|
107
107
|
color: z.ZodDefault<z.ZodString>;
|
|
@@ -125,6 +125,7 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
125
125
|
wallMaterial: z.ZodOptional<z.ZodObject<{
|
|
126
126
|
id: z.ZodOptional<z.ZodString>;
|
|
127
127
|
preset: z.ZodOptional<z.ZodEnum<{
|
|
128
|
+
custom: "custom";
|
|
128
129
|
white: "white";
|
|
129
130
|
brick: "brick";
|
|
130
131
|
concrete: "concrete";
|
|
@@ -134,7 +135,6 @@ export declare const RoofNode: z.ZodObject<{
|
|
|
134
135
|
plaster: "plaster";
|
|
135
136
|
tile: "tile";
|
|
136
137
|
marble: "marble";
|
|
137
|
-
custom: "custom";
|
|
138
138
|
}>>;
|
|
139
139
|
properties: z.ZodOptional<z.ZodObject<{
|
|
140
140
|
color: z.ZodDefault<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roof.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"roof.d.ts","sourceRoot":"","sources":["../../../src/schema/nodes/roof.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,OAAO,KAAK,EAAE,cAAc,IAAI,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAIvE,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAA;AAC7D,MAAM,MAAM,uBAAuB,GAAG;IACpC,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAyBpB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAS/C,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,uBAAuB,GAC5B,uBAAuB,CAoCzB"}
|