@pascal-app/core 0.7.0 → 0.8.0

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.
Files changed (76) hide show
  1. package/dist/events/bus.d.ts +9 -6
  2. package/dist/events/bus.d.ts.map +1 -1
  3. package/dist/events/bus.js +1 -1
  4. package/dist/lib/polygon-geometry.d.ts.map +1 -1
  5. package/dist/lib/space-detection.d.ts.map +1 -1
  6. package/dist/lib/space-detection.js +10 -8
  7. package/dist/material-library.d.ts.map +1 -1
  8. package/dist/material-library.js +20 -1
  9. package/dist/schema/asset-url.test.js +0 -4
  10. package/dist/schema/material.d.ts +2 -2
  11. package/dist/schema/nodes/ceiling.d.ts +1 -1
  12. package/dist/schema/nodes/column.d.ts +1 -1
  13. package/dist/schema/nodes/door.d.ts +1 -1
  14. package/dist/schema/nodes/fence.d.ts +2 -2
  15. package/dist/schema/nodes/fence.js +2 -2
  16. package/dist/schema/nodes/item.d.ts +12 -0
  17. package/dist/schema/nodes/item.d.ts.map +1 -1
  18. package/dist/schema/nodes/item.js +12 -0
  19. package/dist/schema/nodes/roof-segment.d.ts +3 -3
  20. package/dist/schema/nodes/roof.d.ts +6 -6
  21. package/dist/schema/nodes/roof.d.ts.map +1 -1
  22. package/dist/schema/nodes/roof.js +5 -5
  23. package/dist/schema/nodes/site.d.ts +6 -0
  24. package/dist/schema/nodes/site.d.ts.map +1 -1
  25. package/dist/schema/nodes/slab.d.ts +1 -1
  26. package/dist/schema/nodes/stair-segment.d.ts +1 -1
  27. package/dist/schema/nodes/stair.d.ts +6 -6
  28. package/dist/schema/nodes/stair.d.ts.map +1 -1
  29. package/dist/schema/nodes/stair.js +9 -7
  30. package/dist/schema/nodes/wall.d.ts +3 -3
  31. package/dist/schema/nodes/window.d.ts +1 -1
  32. package/dist/schema/types.d.ts +33 -21
  33. package/dist/schema/types.d.ts.map +1 -1
  34. package/dist/store/actions/node-actions.d.ts.map +1 -1
  35. package/dist/store/actions/node-actions.js +7 -5
  36. package/dist/store/use-scene.d.ts.map +1 -1
  37. package/dist/store/use-scene.js +11 -5
  38. package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
  39. package/dist/systems/stair/stair-opening-sync.js +17 -44
  40. package/dist/systems/stair/stair-opening-sync.test.js +0 -2
  41. package/dist/systems/wall/wall-curve.d.ts +1 -1
  42. package/dist/systems/wall/wall-curve.d.ts.map +1 -1
  43. package/dist/systems/wall/wall-curve.js +1 -1
  44. package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
  45. package/dist/systems/wall/wall-mitering.js +2 -6
  46. package/package.json +4 -3
  47. package/dist/materials.d.ts +0 -10
  48. package/dist/materials.d.ts.map +0 -1
  49. package/dist/materials.js +0 -22
  50. package/dist/systems/ceiling/ceiling-system.d.ts +0 -8
  51. package/dist/systems/ceiling/ceiling-system.d.ts.map +0 -1
  52. package/dist/systems/ceiling/ceiling-system.js +0 -92
  53. package/dist/systems/door/door-system.d.ts +0 -2
  54. package/dist/systems/door/door-system.d.ts.map +0 -1
  55. package/dist/systems/door/door-system.js +0 -195
  56. package/dist/systems/fence/fence-system.d.ts +0 -2
  57. package/dist/systems/fence/fence-system.d.ts.map +0 -1
  58. package/dist/systems/fence/fence-system.js +0 -187
  59. package/dist/systems/item/item-system.d.ts +0 -2
  60. package/dist/systems/item/item-system.d.ts.map +0 -1
  61. package/dist/systems/item/item-system.js +0 -48
  62. package/dist/systems/roof/roof-system.d.ts +0 -16
  63. package/dist/systems/roof/roof-system.d.ts.map +0 -1
  64. package/dist/systems/roof/roof-system.js +0 -797
  65. package/dist/systems/slab/slab-system.d.ts +0 -8
  66. package/dist/systems/slab/slab-system.d.ts.map +0 -1
  67. package/dist/systems/slab/slab-system.js +0 -214
  68. package/dist/systems/stair/stair-system.d.ts +0 -2
  69. package/dist/systems/stair/stair-system.d.ts.map +0 -1
  70. package/dist/systems/stair/stair-system.js +0 -776
  71. package/dist/systems/wall/wall-system.d.ts +0 -12
  72. package/dist/systems/wall/wall-system.d.ts.map +0 -1
  73. package/dist/systems/wall/wall-system.js +0 -455
  74. package/dist/systems/window/window-system.d.ts +0 -2
  75. package/dist/systems/window/window-system.d.ts.map +0 -1
  76. package/dist/systems/window/window-system.js +0 -131
@@ -1,187 +0,0 @@
1
- import { useFrame } from '@react-three/fiber';
2
- import * as THREE from 'three';
3
- import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
4
- import { sceneRegistry } from '../../hooks/scene-registry/scene-registry';
5
- import useScene from '../../store/use-scene';
6
- import { getWallCurveFrameAt, getWallCurveLength } from '../wall/wall-curve';
7
- const MIN_CURVE_SEGMENT_LENGTH = 0.18;
8
- function createFencePartGeometry(part) {
9
- const geometry = new THREE.BoxGeometry(1, 1, 1);
10
- geometry.scale(part.scale[0], part.scale[1], part.scale[2]);
11
- if (part.rotationY) {
12
- geometry.rotateY(part.rotationY);
13
- }
14
- geometry.translate(part.position[0], part.position[1], part.position[2]);
15
- applyFenceUVs(geometry);
16
- return geometry;
17
- }
18
- function getFencePointAt(fence, t) {
19
- const frame = getWallCurveFrameAt(fence, t);
20
- return {
21
- point: frame.point,
22
- tangentAngle: Math.atan2(frame.tangent.y, frame.tangent.x),
23
- };
24
- }
25
- function createStraightFenceSpanPart(start, end, centerY, height, depth) {
26
- const dx = end[0] - start[0];
27
- const dz = end[1] - start[1];
28
- const length = Math.hypot(dx, dz);
29
- if (length <= 1e-4) {
30
- return null;
31
- }
32
- return {
33
- position: [(start[0] + end[0]) / 2, centerY, (start[1] + end[1]) / 2],
34
- rotationY: -Math.atan2(dz, dx),
35
- scale: [length, height, depth],
36
- };
37
- }
38
- function createFenceCurveSpanParts(fence, startT, endT, centerY, height, depth) {
39
- const parts = [];
40
- const frameCount = Math.max(1, Math.ceil((getWallCurveLength(fence) * Math.max(1e-4, endT - startT)) / MIN_CURVE_SEGMENT_LENGTH));
41
- let previous = getFencePointAt(fence, startT);
42
- for (let index = 1; index <= frameCount; index += 1) {
43
- const t = startT + (endT - startT) * (index / frameCount);
44
- const current = getFencePointAt(fence, t);
45
- const segment = createStraightFenceSpanPart([previous.point.x, previous.point.y], [current.point.x, current.point.y], centerY, height, depth);
46
- if (segment) {
47
- parts.push(segment);
48
- }
49
- previous = current;
50
- }
51
- return parts;
52
- }
53
- function applyFenceUVs(geometry) {
54
- const position = geometry.getAttribute('position');
55
- const normal = geometry.getAttribute('normal');
56
- if (!(position && normal))
57
- return;
58
- const uvs = new Float32Array(position.count * 2);
59
- let minX = Number.POSITIVE_INFINITY;
60
- let minY = Number.POSITIVE_INFINITY;
61
- let minZ = Number.POSITIVE_INFINITY;
62
- for (let index = 0; index < position.count; index += 1) {
63
- minX = Math.min(minX, position.getX(index));
64
- minY = Math.min(minY, position.getY(index));
65
- minZ = Math.min(minZ, position.getZ(index));
66
- }
67
- for (let index = 0; index < position.count; index += 1) {
68
- const px = position.getX(index);
69
- const py = position.getY(index);
70
- const pz = position.getZ(index);
71
- const nx = Math.abs(normal.getX(index));
72
- const ny = Math.abs(normal.getY(index));
73
- const nz = Math.abs(normal.getZ(index));
74
- let u = 0;
75
- let v = 0;
76
- if (ny >= nx && ny >= nz) {
77
- u = px - minX;
78
- v = pz - minZ;
79
- }
80
- else if (nx >= nz) {
81
- u = pz - minZ;
82
- v = py - minY;
83
- }
84
- else {
85
- u = px - minX;
86
- v = py - minY;
87
- }
88
- uvs[index * 2] = u;
89
- uvs[index * 2 + 1] = v;
90
- }
91
- geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
92
- geometry.setAttribute('uv2', new THREE.Float32BufferAttribute(uvs.slice(), 2));
93
- }
94
- function getStyleDefaults(style) {
95
- if (style === 'privacy') {
96
- return { spacingFactor: 0.42, postFactor: 1.35, baseFactor: 1.2, topFactor: 1.2 };
97
- }
98
- if (style === 'rail') {
99
- return { spacingFactor: 0.68, postFactor: 0.8, baseFactor: 0.85, topFactor: 0.85 };
100
- }
101
- return { spacingFactor: 0.3, postFactor: 0.55, baseFactor: 1, topFactor: 0.75 };
102
- }
103
- function createFenceParts(fence) {
104
- const parts = [];
105
- const length = Math.max(getWallCurveLength(fence), 0.01);
106
- const panelDepth = Math.max(fence.thickness, 0.03);
107
- const clearance = Math.max(fence.groundClearance, 0);
108
- const styleDefaults = getStyleDefaults(fence.style);
109
- const baseHeight = Math.max(fence.baseHeight * styleDefaults.baseFactor, 0.04);
110
- const topRailHeight = Math.max(fence.topRailHeight * styleDefaults.topFactor, 0.01);
111
- const verticalHeight = Math.max(fence.height - baseHeight - topRailHeight, 0.08);
112
- const postWidth = Math.max(fence.postSize * styleDefaults.postFactor, 0.01);
113
- const spacing = Math.max(fence.postSpacing * styleDefaults.spacingFactor, postWidth * 1.2);
114
- const edgeInset = Math.max(fence.edgeInset ?? 0.015, 0.005);
115
- const isFloating = fence.baseStyle === 'floating';
116
- const baseY = isFloating ? clearance : 0;
117
- const effectiveBaseHeight = baseHeight;
118
- const startInsetT = Math.min(0.499, edgeInset / length);
119
- const endInsetT = Math.max(0.501, 1 - edgeInset / length);
120
- if (!isFloating) {
121
- parts.push(...createFenceCurveSpanParts(fence, 0, 1, baseY + effectiveBaseHeight / 2, effectiveBaseHeight, panelDepth * 1.05));
122
- parts.push(...createFenceCurveSpanParts(fence, 0, 1, baseY + effectiveBaseHeight + verticalHeight * 0.15, topRailHeight * 0.8, panelDepth * 0.35));
123
- }
124
- const count = Math.max(2, Math.floor((length - edgeInset * 2) / spacing) + 1);
125
- const verticalY = baseY + effectiveBaseHeight + verticalHeight / 2;
126
- for (let index = 0; index < count; index += 1) {
127
- const t = count === 1 ? 0.5 : startInsetT + (endInsetT - startInsetT) * (index / (count - 1));
128
- const frame = getFencePointAt(fence, t);
129
- const isEdgePost = index === 0 || index === count - 1;
130
- const postHeight = isFloating && isEdgePost
131
- ? effectiveBaseHeight + verticalHeight + topRailHeight + clearance
132
- : verticalHeight;
133
- const postY = isFloating && isEdgePost ? postHeight / 2 : verticalY;
134
- parts.push({
135
- position: [frame.point.x, postY, frame.point.y],
136
- rotationY: -frame.tangentAngle,
137
- scale: [postWidth, postHeight, Math.max(panelDepth * 0.35, 0.012)],
138
- });
139
- }
140
- parts.push(...createFenceCurveSpanParts(fence, 0, 1, baseY + effectiveBaseHeight + verticalHeight + topRailHeight / 2, topRailHeight, Math.max(panelDepth * 0.55, 0.018)));
141
- if (isFloating) {
142
- parts.push(...createFenceCurveSpanParts(fence, 0, 1, baseY + effectiveBaseHeight + topRailHeight / 2, topRailHeight, Math.max(panelDepth * 0.55, 0.018)));
143
- }
144
- return parts;
145
- }
146
- function generateFenceGeometry(fence) {
147
- const parts = createFenceParts(fence);
148
- const geometries = parts.map(createFencePartGeometry);
149
- const merged = mergeGeometries(geometries, false) ?? new THREE.BufferGeometry();
150
- geometries.forEach((geometry) => geometry.dispose());
151
- const mergedUv = merged.getAttribute('uv');
152
- if (mergedUv) {
153
- merged.setAttribute('uv2', new THREE.Float32BufferAttribute(Array.from(mergedUv.array), 2));
154
- }
155
- merged.computeVertexNormals();
156
- return merged;
157
- }
158
- function updateFenceGeometry(fenceId) {
159
- const node = useScene.getState().nodes[fenceId];
160
- if (!node || node.type !== 'fence')
161
- return;
162
- const mesh = sceneRegistry.nodes.get(fenceId);
163
- if (!mesh)
164
- return;
165
- const newGeometry = generateFenceGeometry(node);
166
- mesh.geometry.dispose();
167
- mesh.geometry = newGeometry;
168
- mesh.position.set(0, 0, 0);
169
- mesh.rotation.set(0, 0, 0);
170
- }
171
- export const FenceSystem = () => {
172
- const dirtyNodes = useScene((state) => state.dirtyNodes);
173
- const clearDirty = useScene((state) => state.clearDirty);
174
- useFrame(() => {
175
- if (dirtyNodes.size === 0)
176
- return;
177
- const nodes = useScene.getState().nodes;
178
- dirtyNodes.forEach((id) => {
179
- const node = nodes[id];
180
- if (!node || node.type !== 'fence')
181
- return;
182
- updateFenceGeometry(id);
183
- clearDirty(id);
184
- });
185
- }, 4);
186
- return null;
187
- };
@@ -1,2 +0,0 @@
1
- export declare const ItemSystem: () => null;
2
- //# sourceMappingURL=item-system.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"item-system.d.ts","sourceRoot":"","sources":["../../../src/systems/item/item-system.tsx"],"names":[],"mappings":"AAYA,eAAO,MAAM,UAAU,YA6CtB,CAAA"}
@@ -1,48 +0,0 @@
1
- import { useFrame } from '@react-three/fiber';
2
- import { sceneRegistry } from '../../hooks/scene-registry/scene-registry';
3
- import { spatialGridManager } from '../../hooks/spatial-grid/spatial-grid-manager';
4
- import { resolveLevelId } from '../../hooks/spatial-grid/spatial-grid-sync';
5
- import { getScaledDimensions } from '../../schema';
6
- import useScene from '../../store/use-scene';
7
- // ============================================================================
8
- // ITEM SYSTEM
9
- // ============================================================================
10
- export const ItemSystem = () => {
11
- const dirtyNodes = useScene((state) => state.dirtyNodes);
12
- const clearDirty = useScene((state) => state.clearDirty);
13
- useFrame(() => {
14
- if (dirtyNodes.size === 0)
15
- return;
16
- const nodes = useScene.getState().nodes;
17
- dirtyNodes.forEach((id) => {
18
- const node = nodes[id];
19
- if (!node || node.type !== 'item')
20
- return;
21
- const item = node;
22
- const mesh = sceneRegistry.nodes.get(id);
23
- if (!mesh)
24
- return;
25
- if (item.asset.attachTo === 'wall-side') {
26
- // Wall-attached item: offset Z by half the parent wall's thickness
27
- const parentWall = item.parentId ? nodes[item.parentId] : undefined;
28
- if (parentWall && parentWall.type === 'wall') {
29
- const wallThickness = parentWall.thickness ?? 0.1;
30
- const side = item.side === 'front' ? 1 : -1;
31
- mesh.position.z = (wallThickness / 2) * side;
32
- }
33
- }
34
- else if (!item.asset.attachTo) {
35
- // If parented to another item (surface placement), R3F handles positioning via the hierarchy
36
- const parentNode = item.parentId ? nodes[item.parentId] : undefined;
37
- if (parentNode?.type !== 'item') {
38
- // Floor item: elevate by slab height (using full footprint overlap)
39
- const levelId = resolveLevelId(item, nodes);
40
- const slabElevation = spatialGridManager.getSlabElevationForItem(levelId, item.position, getScaledDimensions(item), item.rotation);
41
- mesh.position.y = slabElevation + item.position[1];
42
- }
43
- }
44
- clearDirty(id);
45
- });
46
- }, 2);
47
- return null;
48
- };
@@ -1,16 +0,0 @@
1
- import * as THREE from 'three';
2
- import { Brush } from 'three-bvh-csg';
3
- import type { RoofSegmentNode } from '../../schema';
4
- export declare const RoofSystem: () => null;
5
- /**
6
- * Generate complete hollow-shell geometry for a roof segment.
7
- * Ports the prototype's CSG approach using three-bvh-csg.
8
- */
9
- export declare function getRoofSegmentBrushes(node: RoofSegmentNode): {
10
- deckSlab: Brush;
11
- shinSlab: Brush;
12
- wallBrush: Brush;
13
- innerBrush: Brush;
14
- } | null;
15
- export declare function generateRoofSegmentGeometry(node: RoofSegmentNode): THREE.BufferGeometry;
16
- //# sourceMappingURL=roof-system.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"roof-system.d.ts","sourceRoot":"","sources":["../../../src/systems/roof/roof-system.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAY,KAAK,EAA0B,MAAM,eAAe,CAAA;AAGvE,OAAO,KAAK,EAAgC,eAAe,EAAE,MAAM,cAAc,CAAA;AAgCjF,eAAO,MAAM,UAAU,YAuFtB,CAAA;AAwLD;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,eAAe,GACpB;IAAE,QAAQ,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,KAAK,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC;IAAC,UAAU,EAAE,KAAK,CAAA;CAAE,GAAG,IAAI,CAsRlF;AAED,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,eAAe,GAAG,KAAK,CAAC,cAAc,CAqDvF"}