@pascal-app/viewer 0.5.0 → 0.6.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.
- package/dist/components/renderers/building/building-renderer.d.ts.map +1 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -1
- package/dist/components/renderers/ceiling/ceiling-renderer.js +4 -3
- package/dist/components/renderers/door/door-renderer.d.ts.map +1 -1
- package/dist/components/renderers/door/door-renderer.js +5 -2
- package/dist/components/renderers/fence/fence-renderer.d.ts +5 -0
- package/dist/components/renderers/fence/fence-renderer.d.ts.map +1 -0
- package/dist/components/renderers/fence/fence-renderer.js +29 -0
- package/dist/components/renderers/node-renderer.d.ts.map +1 -1
- package/dist/components/renderers/node-renderer.js +2 -1
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof/roof-renderer.js +31 -9
- package/dist/components/renderers/roof-segment/roof-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/roof-segment/roof-segment-renderer.js +42 -8
- package/dist/components/renderers/site/site-renderer.d.ts.map +1 -1
- package/dist/components/renderers/site/site-renderer.js +7 -1
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -1
- package/dist/components/renderers/slab/slab-renderer.js +37 -8
- package/dist/components/renderers/stair/stair-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair/stair-renderer.js +605 -5
- package/dist/components/renderers/stair-segment/stair-segment-renderer.d.ts.map +1 -1
- package/dist/components/renderers/stair-segment/stair-segment-renderer.js +37 -8
- package/dist/components/renderers/wall/wall-renderer.d.ts.map +1 -1
- package/dist/components/renderers/wall/wall-renderer.js +4 -9
- package/dist/components/renderers/window/window-renderer.d.ts.map +1 -1
- package/dist/components/renderers/window/window-renderer.js +5 -2
- package/dist/components/viewer/frame-limiter.d.ts +6 -0
- package/dist/components/viewer/frame-limiter.d.ts.map +1 -0
- package/dist/components/viewer/frame-limiter.js +31 -0
- package/dist/components/viewer/ground-occluder.d.ts.map +1 -1
- package/dist/components/viewer/ground-occluder.js +5 -1
- package/dist/components/viewer/index.d.ts.map +1 -1
- package/dist/components/viewer/index.js +12 -12
- package/dist/components/viewer/post-processing.d.ts.map +1 -1
- package/dist/components/viewer/post-processing.js +72 -28
- package/dist/components/viewer/selection-manager.d.ts.map +1 -1
- package/dist/components/viewer/selection-manager.js +21 -2
- package/dist/hooks/use-node-events.d.ts +5 -1
- package/dist/hooks/use-node-events.d.ts.map +1 -1
- package/dist/hooks/use-node-events.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/lib/materials.d.ts +4 -1
- package/dist/lib/materials.d.ts.map +1 -1
- package/dist/lib/materials.js +178 -2
- package/dist/lib/merged-outline-node.d.ts.map +1 -1
- package/dist/lib/merged-outline-node.js +11 -4
- package/dist/store/use-viewer.d.ts +2 -2
- package/dist/systems/guide/guide-system.d.ts.map +1 -1
- package/dist/systems/guide/guide-system.js +26 -1
- package/dist/systems/roof/roof-materials.d.ts +5 -0
- package/dist/systems/roof/roof-materials.d.ts.map +1 -0
- package/dist/systems/roof/roof-materials.js +29 -0
- package/dist/systems/scan/scan-system.d.ts.map +1 -1
- package/dist/systems/scan/scan-system.js +26 -1
- package/dist/systems/stair/stair-materials.d.ts +7 -0
- package/dist/systems/stair/stair-materials.d.ts.map +1 -0
- package/dist/systems/stair/stair-materials.js +33 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -1
- package/dist/systems/wall/wall-cutout.js +39 -124
- package/dist/systems/wall/wall-materials.d.ts +16 -0
- package/dist/systems/wall/wall-materials.d.ts.map +1 -0
- package/dist/systems/wall/wall-materials.js +148 -0
- package/package.json +4 -4
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { baseMaterial, getEffectiveWallSurfaceMaterial, getMaterialPresetByRef, getWallSurfaceMaterialSignature, resolveMaterial, } from '@pascal-app/core';
|
|
2
|
+
import { Color } from 'three';
|
|
3
|
+
import { Fn, float, fract, length, mix, positionLocal, smoothstep, step, vec2 } from 'three/tsl';
|
|
4
|
+
import { MeshStandardNodeMaterial } from 'three/webgpu';
|
|
5
|
+
import { createMaterial, createMaterialFromPresetRef } from '../../lib/materials';
|
|
6
|
+
const DEFAULT_WALL_COLOR = '#f2f0ed';
|
|
7
|
+
const WALL_HIGHLIGHT_PROFILES = {
|
|
8
|
+
delete: {
|
|
9
|
+
color: new Color('#dc2626'),
|
|
10
|
+
blend: 0.76,
|
|
11
|
+
emissiveBlend: 0.92,
|
|
12
|
+
emissiveIntensity: 0.46,
|
|
13
|
+
},
|
|
14
|
+
selection: {
|
|
15
|
+
color: new Color('#818cf8'),
|
|
16
|
+
blend: 0.32,
|
|
17
|
+
emissiveBlend: 0.7,
|
|
18
|
+
emissiveIntensity: 0.42,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
const wallMaterialCache = new Map();
|
|
22
|
+
const dotPattern = Fn(() => {
|
|
23
|
+
const scale = float(0.1);
|
|
24
|
+
const dotSize = float(0.3);
|
|
25
|
+
const uv = vec2(positionLocal.x, positionLocal.y).div(scale);
|
|
26
|
+
const gridUV = fract(uv);
|
|
27
|
+
const dist = length(gridUV.sub(0.5));
|
|
28
|
+
const dots = step(dist, dotSize.mul(0.5));
|
|
29
|
+
const fadeHeight = float(2.5);
|
|
30
|
+
const yFade = float(1).sub(smoothstep(float(0), fadeHeight, positionLocal.y));
|
|
31
|
+
return dots.mul(yFade);
|
|
32
|
+
});
|
|
33
|
+
function getSurfaceVisibleMaterial(spec) {
|
|
34
|
+
if (spec.materialPreset) {
|
|
35
|
+
return createMaterialFromPresetRef(spec.materialPreset) ?? baseMaterial;
|
|
36
|
+
}
|
|
37
|
+
if (spec.material) {
|
|
38
|
+
return createMaterial(spec.material);
|
|
39
|
+
}
|
|
40
|
+
return baseMaterial;
|
|
41
|
+
}
|
|
42
|
+
function getSurfaceColor(spec, fallback = DEFAULT_WALL_COLOR) {
|
|
43
|
+
const preset = getMaterialPresetByRef(spec.materialPreset);
|
|
44
|
+
if (preset?.mapProperties?.color) {
|
|
45
|
+
return preset.mapProperties.color;
|
|
46
|
+
}
|
|
47
|
+
if (spec.material) {
|
|
48
|
+
return resolveMaterial(spec.material).color;
|
|
49
|
+
}
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
function getHighlightedColor(color, kind) {
|
|
53
|
+
const profile = WALL_HIGHLIGHT_PROFILES[kind];
|
|
54
|
+
return color.clone().lerp(profile.color, profile.blend);
|
|
55
|
+
}
|
|
56
|
+
function createHighlightedWallMaterial(material, kind) {
|
|
57
|
+
const highlightedMaterial = material.clone();
|
|
58
|
+
const profile = WALL_HIGHLIGHT_PROFILES[kind];
|
|
59
|
+
if ('color' in highlightedMaterial && highlightedMaterial.color) {
|
|
60
|
+
highlightedMaterial.color = getHighlightedColor(highlightedMaterial.color, kind);
|
|
61
|
+
}
|
|
62
|
+
if ('emissive' in highlightedMaterial && highlightedMaterial.emissive) {
|
|
63
|
+
highlightedMaterial.emissive = highlightedMaterial.emissive
|
|
64
|
+
.clone()
|
|
65
|
+
.lerp(profile.color, profile.emissiveBlend);
|
|
66
|
+
}
|
|
67
|
+
if ('emissiveIntensity' in highlightedMaterial) {
|
|
68
|
+
highlightedMaterial.emissiveIntensity = Math.max(highlightedMaterial.emissiveIntensity ?? 0, profile.emissiveIntensity);
|
|
69
|
+
}
|
|
70
|
+
highlightedMaterial.needsUpdate = true;
|
|
71
|
+
return highlightedMaterial;
|
|
72
|
+
}
|
|
73
|
+
function createInvisibleWallMaterial(color) {
|
|
74
|
+
return new MeshStandardNodeMaterial({
|
|
75
|
+
transparent: true,
|
|
76
|
+
opacityNode: mix(float(0.0), float(0.24), dotPattern()),
|
|
77
|
+
color,
|
|
78
|
+
depthWrite: false,
|
|
79
|
+
emissive: color,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function mapWallMaterialArray(materials, iteratee) {
|
|
83
|
+
return materials.map(iteratee);
|
|
84
|
+
}
|
|
85
|
+
function disposeOwnedMaterials(materials) {
|
|
86
|
+
const owned = new Set();
|
|
87
|
+
materials.forEach((entry) => {
|
|
88
|
+
entry.forEach((material) => {
|
|
89
|
+
owned.add(material);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
owned.forEach((material) => {
|
|
93
|
+
material.dispose();
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
export function getWallMaterialHash(wallNode) {
|
|
97
|
+
return JSON.stringify({
|
|
98
|
+
interior: getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(wallNode, 'interior')),
|
|
99
|
+
exterior: getWallSurfaceMaterialSignature(getEffectiveWallSurfaceMaterial(wallNode, 'exterior')),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
export function getMaterialsForWall(wallNode) {
|
|
103
|
+
const cacheKey = wallNode.id;
|
|
104
|
+
const materialHash = getWallMaterialHash(wallNode);
|
|
105
|
+
const existing = wallMaterialCache.get(cacheKey);
|
|
106
|
+
if (existing && existing.materialHash === materialHash) {
|
|
107
|
+
return existing;
|
|
108
|
+
}
|
|
109
|
+
if (existing) {
|
|
110
|
+
disposeOwnedMaterials([
|
|
111
|
+
existing.invisible,
|
|
112
|
+
existing.deleteVisible,
|
|
113
|
+
existing.deleteInvisible,
|
|
114
|
+
existing.highlightedVisible,
|
|
115
|
+
existing.highlightedInvisible,
|
|
116
|
+
]);
|
|
117
|
+
}
|
|
118
|
+
const interiorSpec = getEffectiveWallSurfaceMaterial(wallNode, 'interior');
|
|
119
|
+
const exteriorSpec = getEffectiveWallSurfaceMaterial(wallNode, 'exterior');
|
|
120
|
+
const visible = [
|
|
121
|
+
baseMaterial,
|
|
122
|
+
getSurfaceVisibleMaterial(interiorSpec),
|
|
123
|
+
getSurfaceVisibleMaterial(exteriorSpec),
|
|
124
|
+
];
|
|
125
|
+
const invisible = [
|
|
126
|
+
createInvisibleWallMaterial(DEFAULT_WALL_COLOR),
|
|
127
|
+
createInvisibleWallMaterial(getSurfaceColor(interiorSpec, DEFAULT_WALL_COLOR)),
|
|
128
|
+
createInvisibleWallMaterial(getSurfaceColor(exteriorSpec, DEFAULT_WALL_COLOR)),
|
|
129
|
+
];
|
|
130
|
+
const highlightedVisible = mapWallMaterialArray(visible, (material) => createHighlightedWallMaterial(material, 'selection'));
|
|
131
|
+
const highlightedInvisible = mapWallMaterialArray(invisible, (material) => createHighlightedWallMaterial(material, 'selection'));
|
|
132
|
+
const deleteVisible = mapWallMaterialArray(visible, (material) => createHighlightedWallMaterial(material, 'delete'));
|
|
133
|
+
const deleteInvisible = mapWallMaterialArray(invisible, (material) => createHighlightedWallMaterial(material, 'delete'));
|
|
134
|
+
const result = {
|
|
135
|
+
visible,
|
|
136
|
+
invisible,
|
|
137
|
+
deleteVisible,
|
|
138
|
+
deleteInvisible,
|
|
139
|
+
highlightedVisible,
|
|
140
|
+
highlightedInvisible,
|
|
141
|
+
materialHash,
|
|
142
|
+
};
|
|
143
|
+
wallMaterialCache.set(cacheKey, result);
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
export function getVisibleWallMaterials(wallNode) {
|
|
147
|
+
return getMaterialsForWall(wallNode).visible;
|
|
148
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pascal-app/viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "3D viewer component for Pascal building editor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
"prepublishOnly": "npm run build"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@pascal-app/core": "^0.
|
|
25
|
+
"@pascal-app/core": "^0.6.0",
|
|
26
26
|
"@react-three/drei": "^10",
|
|
27
27
|
"@react-three/fiber": "^9",
|
|
28
28
|
"react": "^18 || ^19",
|
|
29
|
-
"three": "^0.
|
|
29
|
+
"three": "^0.184"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"polygon-clipping": "^0.15.7",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@pascal/typescript-config": "*",
|
|
37
37
|
"@types/node": "^25.5.0",
|
|
38
38
|
"@types/react": "^19.2.2",
|
|
39
|
-
"@types/three": "^0.
|
|
39
|
+
"@types/three": "^0.184.0",
|
|
40
40
|
"typescript": "5.9.3"
|
|
41
41
|
},
|
|
42
42
|
"keywords": [
|