@pascal-app/viewer 0.5.1 → 0.7.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 (121) hide show
  1. package/dist/components/error-boundary.d.ts +7 -3
  2. package/dist/components/error-boundary.d.ts.map +1 -1
  3. package/dist/components/error-boundary.js +3 -1
  4. package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -1
  5. package/dist/components/renderers/ceiling/ceiling-renderer.js +21 -4
  6. package/dist/components/renderers/column/column-renderer.d.ts +5 -0
  7. package/dist/components/renderers/column/column-renderer.d.ts.map +1 -0
  8. package/dist/components/renderers/column/column-renderer.js +594 -0
  9. package/dist/components/renderers/door/door-renderer.d.ts.map +1 -1
  10. package/dist/components/renderers/door/door-renderer.js +8 -10
  11. package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -1
  12. package/dist/components/renderers/fence/fence-renderer.js +16 -2
  13. package/dist/components/renderers/guide/guide-renderer.js +1 -1
  14. package/dist/components/renderers/item/item-renderer.d.ts.map +1 -1
  15. package/dist/components/renderers/item/item-renderer.js +2 -1
  16. package/dist/components/renderers/node-renderer.d.ts.map +1 -1
  17. package/dist/components/renderers/node-renderer.js +3 -1
  18. package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -1
  19. package/dist/components/renderers/roof/roof-renderer.js +19 -9
  20. package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +1 -1
  21. package/dist/components/renderers/roof-segment/roof-segment-renderer.js +27 -8
  22. package/dist/components/renderers/site/site-renderer.d.ts.map +1 -1
  23. package/dist/components/renderers/site/site-renderer.js +7 -1
  24. package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -1
  25. package/dist/components/renderers/slab/slab-renderer.js +48 -7
  26. package/dist/components/renderers/spawn/spawn-renderer.d.ts +5 -0
  27. package/dist/components/renderers/spawn/spawn-renderer.d.ts.map +1 -0
  28. package/dist/components/renderers/spawn/spawn-renderer.js +32 -0
  29. package/dist/components/renderers/stair/stair-renderer.d.ts.map +1 -1
  30. package/dist/components/renderers/stair/stair-renderer.js +154 -39
  31. package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
  32. package/dist/components/renderers/stair-segment/stair-segment-renderer.js +22 -10
  33. package/dist/components/renderers/wall/wall-renderer.d.ts.map +1 -1
  34. package/dist/components/renderers/wall/wall-renderer.js +4 -9
  35. package/dist/components/renderers/window/window-renderer.d.ts.map +1 -1
  36. package/dist/components/renderers/window/window-renderer.js +5 -2
  37. package/dist/components/viewer/frame-limiter.d.ts +6 -0
  38. package/dist/components/viewer/frame-limiter.d.ts.map +1 -0
  39. package/dist/components/viewer/frame-limiter.js +31 -0
  40. package/dist/components/viewer/ground-occluder.d.ts.map +1 -1
  41. package/dist/components/viewer/ground-occluder.js +5 -1
  42. package/dist/components/viewer/index.d.ts +2 -0
  43. package/dist/components/viewer/index.d.ts.map +1 -1
  44. package/dist/components/viewer/index.js +90 -20
  45. package/dist/components/viewer/post-processing.d.ts +13 -1
  46. package/dist/components/viewer/post-processing.d.ts.map +1 -1
  47. package/dist/components/viewer/post-processing.js +98 -44
  48. package/dist/components/viewer/selection-manager.d.ts.map +1 -1
  49. package/dist/components/viewer/selection-manager.js +31 -3
  50. package/dist/hooks/use-node-events.d.ts +9 -1
  51. package/dist/hooks/use-node-events.d.ts.map +1 -1
  52. package/dist/hooks/use-node-events.js +2 -0
  53. package/dist/index.d.ts +6 -2
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +5 -2
  56. package/dist/lib/materials.d.ts +7 -1
  57. package/dist/lib/materials.d.ts.map +1 -1
  58. package/dist/lib/materials.js +192 -2
  59. package/dist/lib/merged-outline-node.d.ts +2 -0
  60. package/dist/lib/merged-outline-node.d.ts.map +1 -1
  61. package/dist/lib/merged-outline-node.js +36 -9
  62. package/dist/store/use-viewer.d.ts +6 -6
  63. package/dist/store/use-viewer.d.ts.map +1 -1
  64. package/dist/store/use-viewer.js +2 -2
  65. package/dist/systems/ceiling/ceiling-system.d.ts +8 -0
  66. package/dist/systems/ceiling/ceiling-system.d.ts.map +1 -0
  67. package/dist/systems/ceiling/ceiling-system.js +91 -0
  68. package/dist/systems/column/column-geometry.d.ts +22 -0
  69. package/dist/systems/column/column-geometry.d.ts.map +1 -0
  70. package/dist/systems/column/column-geometry.js +108 -0
  71. package/dist/systems/door/door-animation-system.d.ts +2 -0
  72. package/dist/systems/door/door-animation-system.d.ts.map +1 -0
  73. package/dist/systems/door/door-animation-system.js +53 -0
  74. package/dist/systems/door/door-system.d.ts +2 -0
  75. package/dist/systems/door/door-system.d.ts.map +1 -0
  76. package/dist/systems/door/door-system.js +867 -0
  77. package/dist/systems/fence/fence-system.d.ts +2 -0
  78. package/dist/systems/fence/fence-system.d.ts.map +1 -0
  79. package/dist/systems/fence/fence-system.js +185 -0
  80. package/dist/systems/item/item-system.d.ts +2 -0
  81. package/dist/systems/item/item-system.d.ts.map +1 -0
  82. package/dist/systems/item/item-system.js +44 -0
  83. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts +14 -0
  84. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.d.ts.map +1 -0
  85. package/dist/systems/item-mesh-metadata/compute-item-mesh-metadata.js +155 -0
  86. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts +6 -0
  87. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.d.ts.map +1 -0
  88. package/dist/systems/item-mesh-metadata/item-mesh-metadata-system.js +75 -0
  89. package/dist/systems/item-mesh-metadata/sync-request.d.ts +7 -0
  90. package/dist/systems/item-mesh-metadata/sync-request.d.ts.map +1 -0
  91. package/dist/systems/item-mesh-metadata/sync-request.js +25 -0
  92. package/dist/systems/roof/roof-materials.d.ts +5 -0
  93. package/dist/systems/roof/roof-materials.d.ts.map +1 -0
  94. package/dist/systems/roof/roof-materials.js +46 -0
  95. package/dist/systems/roof/roof-system.d.ts +16 -0
  96. package/dist/systems/roof/roof-system.d.ts.map +1 -0
  97. package/dist/systems/roof/roof-system.js +797 -0
  98. package/dist/systems/slab/slab-system.d.ts +8 -0
  99. package/dist/systems/slab/slab-system.d.ts.map +1 -0
  100. package/dist/systems/slab/slab-system.js +155 -0
  101. package/dist/systems/stair/stair-materials.d.ts +7 -0
  102. package/dist/systems/stair/stair-materials.d.ts.map +1 -0
  103. package/dist/systems/stair/stair-materials.js +56 -0
  104. package/dist/systems/stair/stair-system.d.ts +2 -0
  105. package/dist/systems/stair/stair-system.d.ts.map +1 -0
  106. package/dist/systems/stair/stair-system.js +772 -0
  107. package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
  108. package/dist/systems/wall/wall-cutout.js +4 -123
  109. package/dist/systems/wall/wall-materials.d.ts +16 -0
  110. package/dist/systems/wall/wall-materials.d.ts.map +1 -0
  111. package/dist/systems/wall/wall-materials.js +148 -0
  112. package/dist/systems/wall/wall-system.d.ts +11 -0
  113. package/dist/systems/wall/wall-system.d.ts.map +1 -0
  114. package/dist/systems/wall/wall-system.js +592 -0
  115. package/dist/systems/window/window-animation-system.d.ts +2 -0
  116. package/dist/systems/window/window-animation-system.d.ts.map +1 -0
  117. package/dist/systems/window/window-animation-system.js +135 -0
  118. package/dist/systems/window/window-system.d.ts +12 -0
  119. package/dist/systems/window/window-system.d.ts.map +1 -0
  120. package/dist/systems/window/window-system.js +1430 -0
  121. package/package.json +6 -4
@@ -0,0 +1,8 @@
1
+ import { type SlabNode } from '@pascal-app/core';
2
+ import * as THREE from 'three';
3
+ export declare const SlabSystem: () => null;
4
+ /**
5
+ * Generates extruded slab geometry from polygon
6
+ */
7
+ export declare function generateSlabGeometry(slabNode: SlabNode): THREE.BufferGeometry;
8
+ //# sourceMappingURL=slab-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slab-system.d.ts","sourceRoot":"","sources":["../../../src/systems/slab/slab-system.tsx"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,QAAQ,EAEd,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAa9B,eAAO,MAAM,UAAU,YAwBtB,CAAA;AAkBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,GAAG,KAAK,CAAC,cAAc,CAG7E"}
@@ -0,0 +1,155 @@
1
+ import { useFrame } from '@react-three/fiber';
2
+ import { getRenderableSlabPolygon, sceneRegistry, useScene, } from '@pascal-app/core';
3
+ import * as THREE from 'three';
4
+ function ensureUv2Attribute(geometry) {
5
+ const uv = geometry.getAttribute('uv');
6
+ if (!uv)
7
+ return;
8
+ geometry.setAttribute('uv2', new THREE.Float32BufferAttribute(Array.from(uv.array), 2));
9
+ }
10
+ // ============================================================================
11
+ // SLAB SYSTEM
12
+ // ============================================================================
13
+ export const SlabSystem = () => {
14
+ const dirtyNodes = useScene((state) => state.dirtyNodes);
15
+ const clearDirty = useScene((state) => state.clearDirty);
16
+ useFrame(() => {
17
+ if (dirtyNodes.size === 0)
18
+ return;
19
+ const nodes = useScene.getState().nodes;
20
+ // Process dirty slabs
21
+ dirtyNodes.forEach((id) => {
22
+ const node = nodes[id];
23
+ if (!node || node.type !== 'slab')
24
+ return;
25
+ const mesh = sceneRegistry.nodes.get(id);
26
+ if (mesh) {
27
+ updateSlabGeometry(node, mesh);
28
+ clearDirty(id);
29
+ }
30
+ // If mesh not found, keep it dirty for next frame
31
+ });
32
+ }, 1);
33
+ return null;
34
+ };
35
+ /**
36
+ * Updates the geometry for a single slab
37
+ */
38
+ function updateSlabGeometry(node, mesh) {
39
+ const newGeo = generateSlabGeometry(node);
40
+ ensureUv2Attribute(newGeo);
41
+ mesh.geometry.dispose();
42
+ mesh.geometry = newGeo;
43
+ // For negative elevation, shift the mesh down so the top face sits at Y=elevation
44
+ // rather than at Y=0. Positive elevation stays at Y=0 (slab sits at floor level).
45
+ const elevation = node.elevation ?? 0.05;
46
+ mesh.position.y = elevation < 0 ? elevation : 0;
47
+ }
48
+ /**
49
+ * Generates extruded slab geometry from polygon
50
+ */
51
+ export function generateSlabGeometry(slabNode) {
52
+ const elevation = slabNode.elevation ?? 0.05;
53
+ return elevation < 0 ? generatePoolGeometry(slabNode) : generatePositiveSlabGeometry(slabNode);
54
+ }
55
+ /**
56
+ * Standard slab: flat extrusion upward from Y=0 by elevation thickness.
57
+ */
58
+ function generatePositiveSlabGeometry(slabNode) {
59
+ const polygon = getRenderableSlabPolygon(slabNode);
60
+ const elevation = slabNode.elevation ?? 0.05;
61
+ if (polygon.length < 3)
62
+ return new THREE.BufferGeometry();
63
+ const shape = new THREE.Shape();
64
+ shape.moveTo(polygon[0][0], -polygon[0][1]);
65
+ for (let i = 1; i < polygon.length; i++)
66
+ shape.lineTo(polygon[i][0], -polygon[i][1]);
67
+ shape.closePath();
68
+ for (const holePolygon of slabNode.holes ?? []) {
69
+ if (holePolygon.length < 3)
70
+ continue;
71
+ const holePath = new THREE.Path();
72
+ holePath.moveTo(holePolygon[0][0], -holePolygon[0][1]);
73
+ for (let i = 1; i < holePolygon.length; i++)
74
+ holePath.lineTo(holePolygon[i][0], -holePolygon[i][1]);
75
+ holePath.closePath();
76
+ shape.holes.push(holePath);
77
+ }
78
+ const geometry = new THREE.ExtrudeGeometry(shape, { depth: elevation, bevelEnabled: false });
79
+ geometry.rotateX(-Math.PI / 2);
80
+ geometry.computeVertexNormals();
81
+ return geometry;
82
+ }
83
+ /**
84
+ * Pool / recessed slab: floor cap at Y=0 (local) + inner walls up to Y=|elevation|.
85
+ * No top cap — the opening at ground level is handled by the ground occluder hole.
86
+ * mesh.position.y must be set to elevation so the floor sits at the correct world Y.
87
+ *
88
+ * Geometry is built directly in 3D (Y-up) to avoid rotation confusion:
89
+ * - floor in XZ plane at Y=0, normals pointing +Y (visible when looking down into pool)
90
+ * - walls from Y=0 to Y=depth, inward-facing normals (visible from inside pool)
91
+ */
92
+ function generatePoolGeometry(slabNode) {
93
+ const polygon = getRenderableSlabPolygon(slabNode);
94
+ const depth = Math.abs(slabNode.elevation ?? 0.05);
95
+ if (polygon.length < 3)
96
+ return new THREE.BufferGeometry();
97
+ const positions = [];
98
+ const uvs = [];
99
+ const indices = [];
100
+ const n = polygon.length;
101
+ const bounds = new THREE.Box2();
102
+ for (const [x, z] of polygon) {
103
+ bounds.expandByPoint(new THREE.Vector2(x, z));
104
+ }
105
+ for (const hole of slabNode.holes ?? []) {
106
+ for (const [x, z] of hole) {
107
+ bounds.expandByPoint(new THREE.Vector2(x, z));
108
+ }
109
+ }
110
+ const floorWidth = Math.max(bounds.max.x - bounds.min.x, 0.001);
111
+ const floorHeight = Math.max(bounds.max.y - bounds.min.y, 0.001);
112
+ const pushFloorVertex = (x, y, z) => {
113
+ positions.push(x, y, z);
114
+ uvs.push((x - bounds.min.x) / floorWidth, (z - bounds.min.y) / floorHeight);
115
+ };
116
+ const pushWallVertex = (x, y, z, u, v) => {
117
+ positions.push(x, y, z);
118
+ uvs.push(u, v);
119
+ };
120
+ // --- Floor at Y=0 ---
121
+ for (const [x, z] of polygon)
122
+ pushFloorVertex(x, 0, z);
123
+ const pts2d = polygon.map(([x, z]) => new THREE.Vector2(x, z));
124
+ const holesPts2d = (slabNode.holes ?? []).map((h) => h.map(([x, z]) => new THREE.Vector2(x, z)));
125
+ for (const hole of slabNode.holes ?? []) {
126
+ for (const [x, z] of hole)
127
+ pushFloorVertex(x, 0, z);
128
+ }
129
+ const floorTris = THREE.ShapeUtils.triangulateShape(pts2d, holesPts2d);
130
+ for (const tri of floorTris) {
131
+ // Reversed winding → normals point +Y (upward) in XZ plane
132
+ indices.push(tri[0], tri[2], tri[1]);
133
+ }
134
+ // --- Inner walls (no top cap at Y=depth) ---
135
+ // Standard winding on a CCW polygon in XZ gives inward-facing normals.
136
+ for (let i = 0; i < n; i++) {
137
+ const j = (i + 1) % n;
138
+ const [x0, z0] = polygon[i];
139
+ const [x1, z1] = polygon[j];
140
+ const vBase = positions.length / 3;
141
+ const segmentLength = Math.max(Math.hypot(x1 - x0, z1 - z0), 0.001);
142
+ pushWallVertex(x0, 0, z0, 0, 0); // v0 — floor level
143
+ pushWallVertex(x1, 0, z1, segmentLength, 0); // v1 — floor level
144
+ pushWallVertex(x1, depth, z1, segmentLength, depth); // v2 — ground level
145
+ pushWallVertex(x0, depth, z0, 0, depth); // v3 — ground level
146
+ indices.push(vBase, vBase + 1, vBase + 2);
147
+ indices.push(vBase, vBase + 2, vBase + 3);
148
+ }
149
+ const geo = new THREE.BufferGeometry();
150
+ geo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
151
+ geo.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));
152
+ geo.setIndex(indices);
153
+ geo.computeVertexNormals();
154
+ return geo;
155
+ }
@@ -0,0 +1,7 @@
1
+ import { type StairNode, type StairSegmentNode } from '@pascal-app/core';
2
+ import type * as THREE from 'three';
3
+ export type StairBodyMaterials = [THREE.Material, THREE.Material];
4
+ export declare function getStairBodyMaterials(stair: StairNode): StairBodyMaterials;
5
+ export declare function getStairRailingMaterial(stair: StairNode): THREE.Material;
6
+ export declare function getStraightStairSegmentBodyMaterials(segment: StairSegmentNode, parentNode?: StairNode): StairBodyMaterials;
7
+ //# sourceMappingURL=stair-materials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stair-materials.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-materials.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAOnC,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAA;AA6BjE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,kBAAkB,CAkB1E;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,CAAC,QAAQ,CASxE;AAED,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,gBAAgB,EACzB,UAAU,CAAC,EAAE,SAAS,GACrB,kBAAkB,CAWpB"}
@@ -0,0 +1,56 @@
1
+ import { getEffectiveStairSurfaceMaterial, } from '@pascal-app/core';
2
+ import { createMaterial, createMaterialFromPresetRef, DEFAULT_STAIR_MATERIAL, } from '../../lib/materials';
3
+ const stairBodyMaterialCache = new Map();
4
+ const stairRailingMaterialCache = new Map();
5
+ function getSurfaceMaterialSignature(spec) {
6
+ return JSON.stringify({
7
+ material: spec.material ?? null,
8
+ materialPreset: spec.materialPreset ?? null,
9
+ });
10
+ }
11
+ function createResolvedMaterial(material, materialPreset) {
12
+ if (materialPreset) {
13
+ return createMaterialFromPresetRef(materialPreset) ?? DEFAULT_STAIR_MATERIAL;
14
+ }
15
+ if (material) {
16
+ return createMaterial(material);
17
+ }
18
+ return DEFAULT_STAIR_MATERIAL;
19
+ }
20
+ export function getStairBodyMaterials(stair) {
21
+ const tread = getEffectiveStairSurfaceMaterial(stair, 'tread');
22
+ const side = getEffectiveStairSurfaceMaterial(stair, 'side');
23
+ const cacheKey = JSON.stringify({
24
+ tread: getSurfaceMaterialSignature(tread),
25
+ side: getSurfaceMaterialSignature(side),
26
+ });
27
+ const cached = stairBodyMaterialCache.get(cacheKey);
28
+ if (cached)
29
+ return cached;
30
+ const materials = [
31
+ createResolvedMaterial(tread.material, tread.materialPreset),
32
+ createResolvedMaterial(side.material, side.materialPreset),
33
+ ];
34
+ stairBodyMaterialCache.set(cacheKey, materials);
35
+ return materials;
36
+ }
37
+ export function getStairRailingMaterial(stair) {
38
+ const railing = getEffectiveStairSurfaceMaterial(stair, 'railing');
39
+ const cacheKey = getSurfaceMaterialSignature(railing);
40
+ const cached = stairRailingMaterialCache.get(cacheKey);
41
+ if (cached)
42
+ return cached;
43
+ const material = createResolvedMaterial(railing.material, railing.materialPreset);
44
+ stairRailingMaterialCache.set(cacheKey, material);
45
+ return material;
46
+ }
47
+ export function getStraightStairSegmentBodyMaterials(segment, parentNode) {
48
+ if (segment.material !== undefined || typeof segment.materialPreset === 'string') {
49
+ const override = createResolvedMaterial(segment.material, segment.materialPreset);
50
+ return [override, override];
51
+ }
52
+ if (parentNode) {
53
+ return getStairBodyMaterials(parentNode);
54
+ }
55
+ return [DEFAULT_STAIR_MATERIAL, DEFAULT_STAIR_MATERIAL];
56
+ }
@@ -0,0 +1,2 @@
1
+ export declare const StairSystem: () => null;
2
+ //# sourceMappingURL=stair-system.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stair-system.d.ts","sourceRoot":"","sources":["../../../src/systems/stair/stair-system.tsx"],"names":[],"mappings":"AA4BA,eAAO,MAAM,WAAW,YAgHvB,CAAA"}