@pascal-app/viewer 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/renderers/building/building-renderer.d.ts +5 -0
- package/dist/components/renderers/building/building-renderer.d.ts.map +1 -0
- package/dist/components/renderers/building/building-renderer.js +11 -0
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts +5 -0
- package/dist/components/renderers/ceiling/ceiling-renderer.d.ts.map +1 -0
- package/dist/components/renderers/ceiling/ceiling-renderer.js +24 -0
- package/dist/components/renderers/guide/guide-renderer.d.ts +5 -0
- package/dist/components/renderers/guide/guide-renderer.d.ts.map +1 -0
- package/dist/components/renderers/guide/guide-renderer.js +36 -0
- package/dist/components/renderers/item/item-renderer.d.ts +5 -0
- package/dist/components/renderers/item/item-renderer.d.ts.map +1 -0
- package/dist/components/renderers/item/item-renderer.js +70 -0
- package/dist/components/renderers/level/level-renderer.d.ts +5 -0
- package/dist/components/renderers/level/level-renderer.d.ts.map +1 -0
- package/dist/components/renderers/level/level-renderer.js +11 -0
- package/dist/components/renderers/node-renderer.d.ts +5 -0
- package/dist/components/renderers/node-renderer.d.ts.map +1 -0
- package/dist/components/renderers/node-renderer.js +19 -0
- package/dist/components/renderers/roof/roof-renderer.d.ts +5 -0
- package/dist/components/renderers/roof/roof-renderer.d.ts.map +1 -0
- package/dist/components/renderers/roof/roof-renderer.js +10 -0
- package/dist/components/renderers/scan/scan-renderer.d.ts +5 -0
- package/dist/components/renderers/scan/scan-renderer.d.ts.map +1 -0
- package/dist/components/renderers/scan/scan-renderer.js +50 -0
- package/dist/components/renderers/scene-renderer.d.ts +2 -0
- package/dist/components/renderers/scene-renderer.d.ts.map +1 -0
- package/dist/components/renderers/scene-renderer.js +8 -0
- package/dist/components/renderers/slab/slab-renderer.d.ts +5 -0
- package/dist/components/renderers/slab/slab-renderer.d.ts.map +1 -0
- package/dist/components/renderers/slab/slab-renderer.js +10 -0
- package/dist/components/renderers/wall/wall-renderer.d.ts +5 -0
- package/dist/components/renderers/wall/wall-renderer.d.ts.map +1 -0
- package/dist/components/renderers/wall/wall-renderer.js +11 -0
- package/dist/components/renderers/zone/zone-renderer.d.ts +5 -0
- package/dist/components/renderers/zone/zone-renderer.d.ts.map +1 -0
- package/dist/components/renderers/zone/zone-renderer.js +154 -0
- package/dist/components/viewer/index.d.ts +13 -0
- package/dist/components/viewer/index.d.ts.map +1 -0
- package/dist/components/viewer/index.js +29 -0
- package/dist/components/viewer/lights.d.ts +2 -0
- package/dist/components/viewer/lights.d.ts.map +1 -0
- package/dist/components/viewer/lights.js +10 -0
- package/dist/components/viewer/post-processing.d.ts +17 -0
- package/dist/components/viewer/post-processing.d.ts.map +1 -0
- package/dist/components/viewer/post-processing.js +139 -0
- package/dist/components/viewer/selection-manager.d.ts +2 -0
- package/dist/components/viewer/selection-manager.d.ts.map +1 -0
- package/dist/components/viewer/selection-manager.js +279 -0
- package/dist/components/viewer/viewer-camera.d.ts +2 -0
- package/dist/components/viewer/viewer-camera.d.ts.map +1 -0
- package/dist/components/viewer/viewer-camera.js +7 -0
- package/dist/hooks/use-asset-url.d.ts +6 -0
- package/dist/hooks/use-asset-url.d.ts.map +1 -0
- package/dist/hooks/use-asset-url.js +21 -0
- package/dist/hooks/use-gltf-ktx2.d.ts +4 -0
- package/dist/hooks/use-gltf-ktx2.d.ts.map +1 -0
- package/dist/hooks/use-gltf-ktx2.js +16 -0
- package/dist/hooks/use-grid-events.d.ts +12 -0
- package/dist/hooks/use-grid-events.d.ts.map +1 -0
- package/dist/hooks/use-grid-events.js +33 -0
- package/dist/hooks/use-node-events.d.ts +49 -0
- package/dist/hooks/use-node-events.d.ts.map +1 -0
- package/dist/hooks/use-node-events.js +38 -0
- package/dist/index.d.ts +4 -81
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -19168
- package/dist/store/use-viewer.d.ts +35 -0
- package/dist/store/use-viewer.d.ts.map +1 -0
- package/dist/store/use-viewer.js +46 -0
- package/dist/systems/guide/guide-system.d.ts +2 -0
- package/dist/systems/guide/guide-system.d.ts.map +1 -0
- package/dist/systems/guide/guide-system.js +16 -0
- package/dist/systems/level/level-system.d.ts +2 -0
- package/dist/systems/level/level-system.d.ts.map +1 -0
- package/dist/systems/level/level-system.js +23 -0
- package/dist/systems/scan/scan-system.d.ts +2 -0
- package/dist/systems/scan/scan-system.d.ts.map +1 -0
- package/dist/systems/scan/scan-system.js +16 -0
- package/dist/systems/wall/wall-cutout.d.ts +2 -0
- package/dist/systems/wall/wall-cutout.d.ts.map +1 -0
- package/dist/systems/wall/wall-cutout.js +103 -0
- package/package.json +36 -32
- package/dist/index.js.map +0 -1
- package/types.d.ts +0 -81
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { AnyNode, BaseNode, BuildingNode, LevelNode, ZoneNode } from "@pascal-app/core";
|
|
2
|
+
import type { Object3D } from "three";
|
|
3
|
+
type SelectionPath = {
|
|
4
|
+
buildingId: BuildingNode["id"] | null;
|
|
5
|
+
levelId: LevelNode["id"] | null;
|
|
6
|
+
zoneId: ZoneNode["id"] | null;
|
|
7
|
+
selectedIds: BaseNode["id"][];
|
|
8
|
+
};
|
|
9
|
+
type Outliner = {
|
|
10
|
+
selectedObjects: Object3D[];
|
|
11
|
+
hoveredObjects: Object3D[];
|
|
12
|
+
};
|
|
13
|
+
type ViewerState = {
|
|
14
|
+
selection: SelectionPath;
|
|
15
|
+
hoveredId: AnyNode['id'] | ZoneNode['id'] | null;
|
|
16
|
+
setHoveredId: (id: AnyNode['id'] | ZoneNode['id'] | null) => void;
|
|
17
|
+
cameraMode: 'perspective' | 'orthographic';
|
|
18
|
+
setCameraMode: (mode: 'perspective' | 'orthographic') => void;
|
|
19
|
+
levelMode: 'stacked' | 'exploded' | 'solo' | 'manual';
|
|
20
|
+
setLevelMode: (mode: 'stacked' | 'exploded' | 'solo' | 'manual') => void;
|
|
21
|
+
wallMode: 'up' | 'cutaway' | 'down';
|
|
22
|
+
setWallMode: (mode: 'up' | 'cutaway' | 'down') => void;
|
|
23
|
+
showScans: boolean;
|
|
24
|
+
setShowScans: (show: boolean) => void;
|
|
25
|
+
showGuides: boolean;
|
|
26
|
+
setShowGuides: (show: boolean) => void;
|
|
27
|
+
setSelection: (updates: Partial<SelectionPath>) => void;
|
|
28
|
+
resetSelection: () => void;
|
|
29
|
+
outliner: Outliner;
|
|
30
|
+
exportScene: (() => Promise<void>) | null;
|
|
31
|
+
setExportScene: (fn: (() => Promise<void>) | null) => void;
|
|
32
|
+
};
|
|
33
|
+
declare const useViewer: import("zustand").UseBoundStore<import("zustand").StoreApi<ViewerState>>;
|
|
34
|
+
export default useViewer;
|
|
35
|
+
//# sourceMappingURL=use-viewer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-viewer.d.ts","sourceRoot":"","sources":["../../src/store/use-viewer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,QAAQ,EACT,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAItC,KAAK,aAAa,GAAG;IACnB,UAAU,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACtC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;CAC/B,CAAC;AAEF,KAAK,QAAQ,GAAG;IACd,eAAe,EAAE,QAAQ,EAAE,CAAC;IAC5B,cAAc,EAAE,QAAQ,EAAE,CAAC;CAC5B,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,SAAS,EAAE,aAAa,CAAA;IACxB,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IAChD,YAAY,EAAE,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;IAEjE,UAAU,EAAE,aAAa,GAAG,cAAc,CAAA;IAC1C,aAAa,EAAE,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,KAAK,IAAI,CAAA;IAE7D,SAAS,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;IACrD,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,KAAK,IAAI,CAAA;IAExE,QAAQ,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,CAAA;IACnC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,MAAM,KAAK,IAAI,CAAA;IAEtD,SAAS,EAAE,OAAO,CAAA;IAClB,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAErC,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IAGtC,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,KAAK,IAAI,CAAA;IACvD,cAAc,EAAE,MAAM,IAAI,CAAA;IAE1B,QAAQ,EAAE,QAAQ,CAAA;IAGlB,WAAW,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAA;IACzC,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,IAAI,CAAA;CAC3D,CAAA;AAED,QAAA,MAAM,SAAS,0EAqDZ,CAAC;AAEJ,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { create } from "zustand";
|
|
3
|
+
const useViewer = create()((set, get) => ({
|
|
4
|
+
selection: { buildingId: null, levelId: null, zoneId: null, selectedIds: [] },
|
|
5
|
+
hoveredId: null,
|
|
6
|
+
setHoveredId: (id) => set({ hoveredId: id }),
|
|
7
|
+
cameraMode: "perspective",
|
|
8
|
+
setCameraMode: (mode) => set({ cameraMode: mode }),
|
|
9
|
+
levelMode: "stacked",
|
|
10
|
+
setLevelMode: (mode) => set({ levelMode: mode }),
|
|
11
|
+
wallMode: 'cutaway',
|
|
12
|
+
setWallMode: (mode) => set({ wallMode: mode }),
|
|
13
|
+
showScans: true,
|
|
14
|
+
setShowScans: (show) => set({ showScans: show }),
|
|
15
|
+
showGuides: true,
|
|
16
|
+
setShowGuides: (show) => set({ showGuides: show }),
|
|
17
|
+
setSelection: (updates) => set((state) => {
|
|
18
|
+
const newSelection = { ...state.selection, ...updates };
|
|
19
|
+
// Hierarchy Guard: If we change a high-level parent, reset the children
|
|
20
|
+
if (updates.buildingId !== undefined) {
|
|
21
|
+
newSelection.levelId = null;
|
|
22
|
+
newSelection.zoneId = null;
|
|
23
|
+
newSelection.selectedIds = [];
|
|
24
|
+
}
|
|
25
|
+
else if (updates.levelId !== undefined) {
|
|
26
|
+
newSelection.zoneId = null;
|
|
27
|
+
newSelection.selectedIds = [];
|
|
28
|
+
}
|
|
29
|
+
else if (updates.zoneId !== undefined) {
|
|
30
|
+
newSelection.selectedIds = [];
|
|
31
|
+
}
|
|
32
|
+
return { selection: newSelection };
|
|
33
|
+
}),
|
|
34
|
+
resetSelection: () => set({
|
|
35
|
+
selection: {
|
|
36
|
+
buildingId: null,
|
|
37
|
+
levelId: null,
|
|
38
|
+
zoneId: null,
|
|
39
|
+
selectedIds: [],
|
|
40
|
+
},
|
|
41
|
+
}),
|
|
42
|
+
outliner: { selectedObjects: [], hoveredObjects: [] },
|
|
43
|
+
exportScene: null,
|
|
44
|
+
setExportScene: (fn) => set({ exportScene: fn }),
|
|
45
|
+
}));
|
|
46
|
+
export default useViewer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide-system.d.ts","sourceRoot":"","sources":["../../../src/systems/guide/guide-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,YAavB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { sceneRegistry } from '@pascal-app/core';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import useViewer from '../../store/use-viewer';
|
|
4
|
+
export const GuideSystem = () => {
|
|
5
|
+
const showGuides = useViewer((state) => state.showGuides);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const guides = sceneRegistry.byType.guide || new Set();
|
|
8
|
+
guides.forEach((guideId) => {
|
|
9
|
+
const node = sceneRegistry.nodes.get(guideId);
|
|
10
|
+
if (node) {
|
|
11
|
+
node.visible = showGuides;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}, [showGuides]);
|
|
15
|
+
return null;
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"level-system.d.ts","sourceRoot":"","sources":["../../../src/systems/level/level-system.tsx"],"names":[],"mappings":"AAQA,eAAO,MAAM,WAAW,YAkBvB,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
|
+
import { lerp } from 'three/src/math/MathUtils.js';
|
|
4
|
+
import useViewer from '../../store/use-viewer';
|
|
5
|
+
const LEVEL_HEIGHT = 2.5;
|
|
6
|
+
const EXPLODED_GAP = 5;
|
|
7
|
+
export const LevelSystem = () => {
|
|
8
|
+
useFrame((_, delta) => {
|
|
9
|
+
const levelMode = useViewer.getState().levelMode;
|
|
10
|
+
const selectedLevel = useViewer.getState().selection.levelId;
|
|
11
|
+
sceneRegistry.byType.level.forEach((levelId) => {
|
|
12
|
+
const obj = sceneRegistry.nodes.get(levelId);
|
|
13
|
+
if (obj) {
|
|
14
|
+
const level = useScene.getState().nodes[levelId];
|
|
15
|
+
const targetY = (level.level || 0) *
|
|
16
|
+
(LEVEL_HEIGHT + (levelMode === 'exploded' ? EXPLODED_GAP : 0));
|
|
17
|
+
obj.position.y = lerp(obj.position.y, targetY, delta * 3);
|
|
18
|
+
obj.visible = levelMode !== 'solo' || level?.id === selectedLevel || !selectedLevel;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
return null;
|
|
23
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan-system.d.ts","sourceRoot":"","sources":["../../../src/systems/scan/scan-system.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,YAatB,CAAA"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { sceneRegistry } from '@pascal-app/core';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
import useViewer from '../../store/use-viewer';
|
|
4
|
+
export const ScanSystem = () => {
|
|
5
|
+
const showScans = useViewer((state) => state.showScans);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const scans = sceneRegistry.byType.scan || new Set();
|
|
8
|
+
scans.forEach((scanId) => {
|
|
9
|
+
const node = sceneRegistry.nodes.get(scanId);
|
|
10
|
+
if (node) {
|
|
11
|
+
node.visible = showScans;
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}, [showScans]);
|
|
15
|
+
return null;
|
|
16
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wall-cutout.d.ts","sourceRoot":"","sources":["../../../src/systems/wall/wall-cutout.tsx"],"names":[],"mappings":"AAgDA,eAAO,MAAM,UAAU,YAkEtB,CAAA"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { sceneRegistry, useScene } from '@pascal-app/core';
|
|
2
|
+
import { useFrame } from '@react-three/fiber';
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
import { Fn, float, fract, length, mix, positionLocal, smoothstep, step, vec2 } from 'three/tsl';
|
|
5
|
+
import { MeshStandardNodeMaterial, Vector3 } from 'three/webgpu';
|
|
6
|
+
import useViewer from '../../store/use-viewer';
|
|
7
|
+
const tmpVec = new Vector3();
|
|
8
|
+
const u = new Vector3();
|
|
9
|
+
const v = new Vector3();
|
|
10
|
+
// Dot pattern shader
|
|
11
|
+
const dotPattern = Fn(() => {
|
|
12
|
+
// Create a repeating grid pattern based on world position
|
|
13
|
+
const scale = float(0.1); // Dot grid spacing (10cm)
|
|
14
|
+
const dotSize = float(0.3); // Size of dots relative to grid
|
|
15
|
+
// Use XY coordinates for pattern on wall face
|
|
16
|
+
const uv = vec2(positionLocal.x, positionLocal.y).div(scale);
|
|
17
|
+
const gridUV = fract(uv);
|
|
18
|
+
// Distance from center of grid cell (creates circular dots)
|
|
19
|
+
const dist = length(gridUV.sub(0.5));
|
|
20
|
+
// Create dots: 1 where we want dots, 0 elsewhere
|
|
21
|
+
const dots = step(dist, dotSize.mul(0.5));
|
|
22
|
+
// Vertical fade: fade out as Y increases (from bottom to top)
|
|
23
|
+
const fadeHeight = float(2.5); // Fade over 2.5 meters
|
|
24
|
+
const yFade = float(1).sub(smoothstep(float(0), fadeHeight, positionLocal.y));
|
|
25
|
+
return dots.mul(yFade);
|
|
26
|
+
});
|
|
27
|
+
const invsibleWallMaterial = new MeshStandardNodeMaterial({
|
|
28
|
+
transparent: true,
|
|
29
|
+
opacityNode: mix(float(0.0), float(0.24), dotPattern()),
|
|
30
|
+
color: 'white',
|
|
31
|
+
depthWrite: false,
|
|
32
|
+
emissive: 'white',
|
|
33
|
+
});
|
|
34
|
+
const wallMaterial = new MeshStandardNodeMaterial({
|
|
35
|
+
color: 'white',
|
|
36
|
+
roughness: 1,
|
|
37
|
+
metalness: 0,
|
|
38
|
+
});
|
|
39
|
+
export const WallCutout = () => {
|
|
40
|
+
const lastCameraPosition = useRef(new Vector3());
|
|
41
|
+
const lastCameraTarget = useRef(new Vector3());
|
|
42
|
+
const lastUpdateTime = useRef(0);
|
|
43
|
+
const lastWallMode = useRef(useViewer.getState().wallMode);
|
|
44
|
+
const lastNumberOfWalls = useRef(0);
|
|
45
|
+
useFrame(({ camera, clock }) => {
|
|
46
|
+
const wallMode = useViewer.getState().wallMode;
|
|
47
|
+
const currentTime = clock.elapsedTime;
|
|
48
|
+
const currentCameraPosition = camera.position;
|
|
49
|
+
camera.getWorldDirection(tmpVec);
|
|
50
|
+
tmpVec.add(currentCameraPosition);
|
|
51
|
+
// Throttle: only update if camera moved significantly AND enough time passed
|
|
52
|
+
const distanceMoved = currentCameraPosition.distanceTo(lastCameraPosition.current);
|
|
53
|
+
const directionChanged = tmpVec.distanceTo(lastCameraTarget.current);
|
|
54
|
+
const timeSinceUpdate = currentTime - lastUpdateTime.current;
|
|
55
|
+
// Update if moved > 0.5m OR direction changed > 0.3 AND at least 100ms passed
|
|
56
|
+
if (((distanceMoved > 0.5 || directionChanged > 0.3) && timeSinceUpdate > 0.1) ||
|
|
57
|
+
lastWallMode.current !== wallMode ||
|
|
58
|
+
sceneRegistry.byType.wall.size !== lastNumberOfWalls.current) {
|
|
59
|
+
// Camera has moved, update cutout logic here
|
|
60
|
+
// Update last known positions and time
|
|
61
|
+
lastCameraPosition.current.copy(currentCameraPosition);
|
|
62
|
+
lastCameraTarget.current.copy(tmpVec);
|
|
63
|
+
lastUpdateTime.current = currentTime;
|
|
64
|
+
camera.getWorldDirection(u);
|
|
65
|
+
const walls = sceneRegistry.byType.wall;
|
|
66
|
+
walls.forEach((wallId) => {
|
|
67
|
+
const wallMesh = sceneRegistry.nodes.get(wallId);
|
|
68
|
+
if (!wallMesh)
|
|
69
|
+
return;
|
|
70
|
+
const wallNode = useScene.getState().nodes[wallId];
|
|
71
|
+
if (!wallNode || wallNode.type !== 'wall')
|
|
72
|
+
return;
|
|
73
|
+
let hideWall = wallNode.frontSide === 'interior' && wallNode.backSide === 'interior';
|
|
74
|
+
if (wallMode === 'up') {
|
|
75
|
+
hideWall = false;
|
|
76
|
+
}
|
|
77
|
+
else if (wallMode === 'down') {
|
|
78
|
+
hideWall = true;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
wallMesh.getWorldDirection(v);
|
|
82
|
+
if (v.dot(u) < 0) {
|
|
83
|
+
// Front side
|
|
84
|
+
if (wallNode.frontSide === 'exterior' && wallNode.backSide !== 'exterior') {
|
|
85
|
+
hideWall = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
// Back side
|
|
90
|
+
if (wallNode.backSide === 'exterior' && wallNode.frontSide !== 'exterior') {
|
|
91
|
+
hideWall = true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
;
|
|
96
|
+
wallMesh.material = hideWall ? invsibleWallMaterial : wallMaterial;
|
|
97
|
+
});
|
|
98
|
+
lastWallMode.current = wallMode;
|
|
99
|
+
lastNumberOfWalls.current = sceneRegistry.byType.wall.size;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return null;
|
|
103
|
+
};
|
package/package.json
CHANGED
|
@@ -1,51 +1,55 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pascal-app/viewer",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
5
|
-
"private": false,
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "3D viewer component for Pascal building editor",
|
|
6
5
|
"type": "module",
|
|
7
6
|
"main": "./dist/index.js",
|
|
8
|
-
"module": "./dist/index.js",
|
|
9
7
|
"types": "./dist/index.d.ts",
|
|
10
8
|
"exports": {
|
|
11
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
12
11
|
"import": "./dist/index.js",
|
|
13
|
-
"
|
|
12
|
+
"default": "./dist/index.js"
|
|
14
13
|
}
|
|
15
14
|
},
|
|
16
15
|
"files": [
|
|
17
16
|
"dist",
|
|
18
|
-
"
|
|
17
|
+
"README.md"
|
|
19
18
|
],
|
|
20
|
-
"sideEffects": false,
|
|
21
19
|
"scripts": {
|
|
22
|
-
"build": "
|
|
23
|
-
"
|
|
24
|
-
"typecheck": "tsc --noEmit"
|
|
25
|
-
},
|
|
26
|
-
"dependencies": {
|
|
27
|
-
"@react-spring/three": "^10.0.0",
|
|
28
|
-
"@react-three/csg": "^4.0.0",
|
|
29
|
-
"@react-three/uikit": "^1.0.0",
|
|
30
|
-
"clsx": "^2.1.1",
|
|
31
|
-
"immer": "^10.2.0",
|
|
32
|
-
"mitt": "^3.0.1",
|
|
33
|
-
"nanoid": "^5.1.6",
|
|
34
|
-
"tailwind-merge": "^3.4.0",
|
|
35
|
-
"three-custom-shader-material": "^6.1.0",
|
|
36
|
-
"zod": "^4.2.1",
|
|
37
|
-
"zustand": "^5.0.9"
|
|
20
|
+
"build": "tsc --declaration --emitDeclarationOnly && tsc",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
38
22
|
},
|
|
39
23
|
"peerDependencies": {
|
|
40
|
-
"
|
|
41
|
-
"react-
|
|
42
|
-
"three": "
|
|
43
|
-
"
|
|
44
|
-
"
|
|
24
|
+
"@pascal-app/core": "^0.1.3",
|
|
25
|
+
"@react-three/drei": "^10",
|
|
26
|
+
"@react-three/fiber": "^9",
|
|
27
|
+
"react": "^18 || ^19",
|
|
28
|
+
"three": "^0.182"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"zustand": "^5"
|
|
45
32
|
},
|
|
46
33
|
"devDependencies": {
|
|
47
|
-
"@
|
|
48
|
-
"@types/react": "^19.
|
|
49
|
-
"
|
|
50
|
-
|
|
34
|
+
"@repo/typescript-config": "*",
|
|
35
|
+
"@types/react": "^19.2.2",
|
|
36
|
+
"typescript": "5.9.2",
|
|
37
|
+
"@types/three": "^0.182.0"
|
|
38
|
+
},
|
|
39
|
+
"keywords": [
|
|
40
|
+
"3d",
|
|
41
|
+
"building",
|
|
42
|
+
"editor",
|
|
43
|
+
"viewer",
|
|
44
|
+
"architecture",
|
|
45
|
+
"webgpu",
|
|
46
|
+
"three.js",
|
|
47
|
+
"react-three-fiber"
|
|
48
|
+
],
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "https://github.com/your-username/pascal-editor.git",
|
|
52
|
+
"directory": "packages/viewer"
|
|
53
|
+
},
|
|
54
|
+
"license": "MIT"
|
|
51
55
|
}
|