decal boundary added based on the wall and floor movement
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import * as THREE from "three";
|
||||
import { Decal } from "@react-three/drei";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useToggleView, useToolMode } from "../../../../store/builder/store";
|
||||
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
|
||||
import { retrieveImage, storeImage } from "../../../../utils/indexDB/idbUtils";
|
||||
@@ -7,11 +8,16 @@ import deepEqual from "../../../../functions/objectDeepEqual";
|
||||
|
||||
import defaultMaterial from "../../../../assets/image/fallback/fallback decal 1.png";
|
||||
import useModuleStore from "../../../../store/ui/useModuleStore";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import { useDecalEventHandlers } from "../eventHandler/useDecalEventHandlers";
|
||||
|
||||
function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalPosition[2] }: Readonly<{ parent: Wall | Floor; visible?: boolean; decal: Decal; zPosition?: number }>) {
|
||||
function DecalInstance({
|
||||
parent,
|
||||
visible = true,
|
||||
decal,
|
||||
zPosition = decal.decalPosition[2],
|
||||
overWritePosition = null,
|
||||
}: Readonly<{ parent: Wall | Floor; visible?: boolean; decal: Decal; zPosition?: number; overWritePosition?: [number, number, number] | null }>) {
|
||||
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
const { selectedDecal, deletableDecal, setSelectedDecal, setDeletableDecal } = useBuilderStore();
|
||||
const { toolMode } = useToolMode();
|
||||
@@ -155,10 +161,10 @@ function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalP
|
||||
|
||||
return (
|
||||
<Decal
|
||||
// debug
|
||||
debug
|
||||
visible={visible}
|
||||
ref={decalRef}
|
||||
position={[decal.decalPosition[0], decal.decalPosition[1], zPosition]}
|
||||
position={overWritePosition ? [overWritePosition[0], overWritePosition[1], zPosition] : [decal.decalPosition[0], decal.decalPosition[1], zPosition]}
|
||||
rotation={[0, 0, decal.decalRotation * (Math.PI / 180)]}
|
||||
scale={[decal.decalType.type === "Floor" || zPosition < 0 ? -decal.decalScale : decal.decalScale, decal.decalScale, 0.01]}
|
||||
userData={decal}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as THREE from "three";
|
||||
import { MathUtils, Vector2, Vector3 } from "three";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { CameraControls } from "@react-three/drei";
|
||||
@@ -7,6 +7,7 @@ import { useToggleView, useToolMode } from "../../../../store/builder/store";
|
||||
import { useSocketStore } from "../../../../store/socket/useSocketStore";
|
||||
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
|
||||
import { useSceneContext } from "../../../scene/sceneContext";
|
||||
import { useWallClassification } from "../../wall/Instances/instance/helpers/useWallClassification";
|
||||
import useModuleStore from "../../../../store/ui/useModuleStore";
|
||||
import useWallResponseHandler from "../../../collaboration/responseHandler/useWallResponseHandler";
|
||||
import useFloorResponseHandler from "../../../collaboration/responseHandler/useFloorResponseHandler";
|
||||
@@ -20,10 +21,11 @@ import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsert
|
||||
|
||||
export function useDecalEventHandlers({ parent, decal, visible }: { parent: Wall | Floor; decal: Decal; visible: boolean }) {
|
||||
const { wallStore, floorStore, versionStore } = useSceneContext();
|
||||
const { removeDecal: removeDecalInWall, updateDecalPosition: updateDecalPositionInWall, getWallById, addDecal: addDecalToWall } = wallStore();
|
||||
const { removeDecal: removeDecalInFloor, updateDecalPosition: updateDecalPositionInFloor, getFloorById, addDecal: addDecalToFloor } = floorStore();
|
||||
const { walls, removeDecal: removeDecalInWall, updateDecalPosition: updateDecalPositionInWall, getWallById, addDecal: addDecalToWall, getDecalById: getDecalOnWall } = wallStore();
|
||||
const { removeDecal: removeDecalInFloor, updateDecalPosition: updateDecalPositionInFloor, getFloorById, addDecal: addDecalToFloor, getDecalById: getDecalOnFloor } = floorStore();
|
||||
const { setSelectedWall, setSelectedFloor, setSelectedDecal, setDeletableDecal, deletableDecal, selectedDecal, setDecalDragState, decalDragState } = useBuilderStore();
|
||||
const { updateWallInScene } = useWallResponseHandler();
|
||||
const { isWallFlipped } = useWallClassification(walls);
|
||||
const { updateFloorInScene } = useFloorResponseHandler();
|
||||
const { toolMode } = useToolMode();
|
||||
const { toggleView } = useToggleView();
|
||||
@@ -44,7 +46,7 @@ export function useDecalEventHandlers({ parent, decal, visible }: { parent: Wall
|
||||
const wallIntersect = intersects.find((i) => i.object.userData?.wallUuid);
|
||||
const floorIntersect = intersects.find((i) => i.object.userData?.floorUuid);
|
||||
|
||||
let offset = decalDragState.dragOffset || new THREE.Vector3(0, 0, 0);
|
||||
let offset = decalDragState.dragOffset || new Vector3(0, 0, 0);
|
||||
|
||||
if (wallIntersect) {
|
||||
const wallUuid = wallIntersect.object.userData.wallUuid;
|
||||
@@ -59,7 +61,30 @@ export function useDecalEventHandlers({ parent, decal, visible }: { parent: Wall
|
||||
}
|
||||
|
||||
if ("wallUuid" in parent && parent.wallUuid === wallUuid && decal.decalType.type === "Wall") {
|
||||
updateDecalPositionInWall(decal.decalUuid, [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]]);
|
||||
const wall = getWallById(wallUuid);
|
||||
const decalData = getDecalOnWall(decal.decalUuid);
|
||||
if (!decalData || !wall) return;
|
||||
const wallFlipped = isWallFlipped(wall);
|
||||
const [rawStart, rawEnd] = wall.points;
|
||||
const [startPoint, endPoint] = wallFlipped ? [rawStart, rawEnd] : [rawEnd, rawStart];
|
||||
|
||||
const startX = startPoint.position[0];
|
||||
const startZ = startPoint.position[2];
|
||||
const endX = endPoint.position[0];
|
||||
const endZ = endPoint.position[2];
|
||||
|
||||
const wallLength = Math.sqrt((endX - startX) ** 2 + (endZ - startZ) ** 2);
|
||||
|
||||
function clampDecalPosition(decal: Decal, wallLength: number, wallHeight: number) {
|
||||
const localPos = new Vector3(...decal.decalPosition);
|
||||
localPos.x = MathUtils.clamp(localPos.x, -wallLength / 2, wallLength / 2);
|
||||
localPos.y = MathUtils.clamp(localPos.y, -wallHeight / 2, wallHeight / 2);
|
||||
return localPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
const clampedPosition = clampDecalPosition({ ...decalData, decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]] }, wallLength, wall.wallHeight);
|
||||
|
||||
updateDecalPositionInWall(decalData.decalUuid, clampedPosition);
|
||||
} else if (decal.decalType.type === "Wall" && wallUuid) {
|
||||
deleteDecal(decal.decalUuid, parent);
|
||||
|
||||
@@ -100,7 +125,60 @@ export function useDecalEventHandlers({ parent, decal, visible }: { parent: Wall
|
||||
}
|
||||
|
||||
if ("floorUuid" in parent && parent.floorUuid === floorUuid && decal.decalType.type === "Floor") {
|
||||
updateDecalPositionInFloor(decal.decalUuid, [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]]);
|
||||
function isPointInPolygon(point: Vector2, polygon: Vector2[]): boolean {
|
||||
let inside = false;
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i].x,
|
||||
yi = polygon[i].y;
|
||||
const xj = polygon[j].x,
|
||||
yj = polygon[j].y;
|
||||
|
||||
const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
function clampToPolygon(point: Vector2, polygon: Vector2[]): Vector2 {
|
||||
let closestPoint = point.clone();
|
||||
let minDist = Infinity;
|
||||
|
||||
for (let i = 0; i < polygon.length; i++) {
|
||||
const a = polygon[i];
|
||||
const b = polygon[(i + 1) % polygon.length];
|
||||
|
||||
const ab = new Vector2().subVectors(b, a);
|
||||
const t = Math.max(0, Math.min(1, point.clone().sub(a).dot(ab) / ab.lengthSq()));
|
||||
const proj = a.clone().add(ab.multiplyScalar(t));
|
||||
|
||||
const dist = proj.distanceTo(point);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closestPoint = proj;
|
||||
}
|
||||
}
|
||||
return closestPoint;
|
||||
}
|
||||
|
||||
function clampDecalPosition(decal: Decal, floor: Floor): [number, number, number] {
|
||||
const pos = new Vector3(...decal.decalPosition);
|
||||
const polygon2D = floor.points.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
const p2 = new Vector2(pos.x, pos.y);
|
||||
|
||||
let final2D: Vector2;
|
||||
if (isPointInPolygon(p2, polygon2D)) {
|
||||
final2D = p2;
|
||||
} else {
|
||||
final2D = clampToPolygon(p2, polygon2D);
|
||||
}
|
||||
|
||||
const clampedPos = new Vector3(final2D.x, final2D.y, pos.z);
|
||||
return clampedPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
const clampedPosition = clampDecalPosition({ ...decal, decalPosition: [finalPos.x + offset.x, finalPos.y + offset.y, decal.decalPosition[2]] }, parent);
|
||||
|
||||
updateDecalPositionInFloor(decal.decalUuid, clampedPosition);
|
||||
} else if (decal.decalType.type === "Floor" && floorUuid) {
|
||||
deleteDecal(decal.decalUuid, parent);
|
||||
|
||||
@@ -299,7 +377,87 @@ export function useDecalEventHandlers({ parent, decal, visible }: { parent: Wall
|
||||
setSelectedFloor(null);
|
||||
|
||||
const localIntersect = e.object.worldToLocal(e.point.clone());
|
||||
let dragOffset = new THREE.Vector3(decal.decalPosition[0] - localIntersect.x, decal.decalPosition[1] - localIntersect.y, 0);
|
||||
|
||||
let clampedDecalPosition;
|
||||
|
||||
if (decal.decalType.type === "Wall" && "wallUuid" in parent) {
|
||||
const wallFlipped = isWallFlipped(parent);
|
||||
const [rawStart, rawEnd] = parent.points;
|
||||
const [startPoint, endPoint] = wallFlipped ? [rawStart, rawEnd] : [rawEnd, rawStart];
|
||||
|
||||
const startX = startPoint.position[0];
|
||||
const startZ = startPoint.position[2];
|
||||
const endX = endPoint.position[0];
|
||||
const endZ = endPoint.position[2];
|
||||
|
||||
const wallLength = Math.sqrt((endX - startX) ** 2 + (endZ - startZ) ** 2);
|
||||
|
||||
function clampDecalPosition(decal: Decal, wallLength: number, wallHeight: number) {
|
||||
const localPos = new Vector3(...decal.decalPosition);
|
||||
localPos.x = MathUtils.clamp(localPos.x, -wallLength / 2, wallLength / 2);
|
||||
localPos.y = MathUtils.clamp(localPos.y, -wallHeight / 2, wallHeight / 2);
|
||||
return localPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
clampedDecalPosition = clampDecalPosition(decal, wallLength, parent.wallHeight);
|
||||
} else if (decal.decalType.type === "Floor" && "floorUuid" in parent) {
|
||||
function isPointInPolygon(point: Vector2, polygon: Vector2[]): boolean {
|
||||
let inside = false;
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i].x,
|
||||
yi = polygon[i].y;
|
||||
const xj = polygon[j].x,
|
||||
yj = polygon[j].y;
|
||||
|
||||
const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
function clampToPolygon(point: Vector2, polygon: Vector2[]): Vector2 {
|
||||
let closestPoint = point.clone();
|
||||
let minDist = Infinity;
|
||||
|
||||
for (let i = 0; i < polygon.length; i++) {
|
||||
const a = polygon[i];
|
||||
const b = polygon[(i + 1) % polygon.length];
|
||||
|
||||
const ab = new Vector2().subVectors(b, a);
|
||||
const t = Math.max(0, Math.min(1, point.clone().sub(a).dot(ab) / ab.lengthSq()));
|
||||
const proj = a.clone().add(ab.multiplyScalar(t));
|
||||
|
||||
const dist = proj.distanceTo(point);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closestPoint = proj;
|
||||
}
|
||||
}
|
||||
return closestPoint;
|
||||
}
|
||||
|
||||
function clampDecalPosition(decal: Decal, floor: Floor): [number, number, number] {
|
||||
const pos = new Vector3(...decal.decalPosition);
|
||||
const polygon2D = floor.points.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
const p2 = new Vector2(pos.x, pos.y);
|
||||
|
||||
let final2D: Vector2;
|
||||
if (isPointInPolygon(p2, polygon2D)) {
|
||||
final2D = p2;
|
||||
} else {
|
||||
final2D = clampToPolygon(p2, polygon2D);
|
||||
}
|
||||
|
||||
const clampedPos = new Vector3(final2D.x, final2D.y, pos.z);
|
||||
return clampedPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
clampedDecalPosition = clampDecalPosition(decal, parent);
|
||||
} else {
|
||||
clampedDecalPosition = decal.decalPosition;
|
||||
}
|
||||
|
||||
let dragOffset = new Vector3(clampedDecalPosition[0] - localIntersect.x, clampedDecalPosition[1] - localIntersect.y, 0);
|
||||
setDecalDragState(true, decal.decalUuid, dragOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace, NoColorSpace } from "three";
|
||||
import { DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace, NoColorSpace, Vector2, Vector3 } from "three";
|
||||
import { useLoader } from "@react-three/fiber";
|
||||
import useModuleStore from "../../../../../store/ui/useModuleStore";
|
||||
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
|
||||
@@ -123,6 +123,57 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
bevelThickness: 0.1,
|
||||
};
|
||||
|
||||
function isPointInPolygon(point: Vector2, polygon: Vector2[]): boolean {
|
||||
let inside = false;
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i].x,
|
||||
yi = polygon[i].y;
|
||||
const xj = polygon[j].x,
|
||||
yj = polygon[j].y;
|
||||
|
||||
const intersect = yi > point.y !== yj > point.y && point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
function clampToPolygon(point: Vector2, polygon: Vector2[]): Vector2 {
|
||||
let closestPoint = point.clone();
|
||||
let minDist = Infinity;
|
||||
|
||||
for (let i = 0; i < polygon.length; i++) {
|
||||
const a = polygon[i];
|
||||
const b = polygon[(i + 1) % polygon.length];
|
||||
|
||||
const ab = new Vector2().subVectors(b, a);
|
||||
const t = Math.max(0, Math.min(1, point.clone().sub(a).dot(ab) / ab.lengthSq()));
|
||||
const proj = a.clone().add(ab.multiplyScalar(t));
|
||||
|
||||
const dist = proj.distanceTo(point);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
closestPoint = proj;
|
||||
}
|
||||
}
|
||||
return closestPoint;
|
||||
}
|
||||
|
||||
function clampDecalPosition(decal: Decal, floor: Floor): [number, number, number] {
|
||||
const pos = new Vector3(...decal.decalPosition);
|
||||
const polygon2D = floor.points.map((p) => new Vector2(p.position[0], p.position[2]));
|
||||
const p2 = new Vector2(pos.x, pos.y);
|
||||
|
||||
let final2D: Vector2;
|
||||
if (isPointInPolygon(p2, polygon2D)) {
|
||||
final2D = p2;
|
||||
} else {
|
||||
final2D = clampToPolygon(p2, polygon2D);
|
||||
}
|
||||
|
||||
const clampedPos = new Vector3(final2D.x, final2D.y, pos.z);
|
||||
return clampedPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
return (
|
||||
<ExtrudePolygon
|
||||
castShadow
|
||||
@@ -171,7 +222,7 @@ function FloorInstance({ floor }: { readonly floor: Floor }) {
|
||||
/>
|
||||
|
||||
{floor.decals.map((decal) => (
|
||||
<DecalInstance parent={floor} key={decal.decalUuid} decal={decal} />
|
||||
<DecalInstance parent={floor} key={decal.decalUuid} decal={decal} overWritePosition={clampDecalPosition(decal, floor)} />
|
||||
))}
|
||||
</ExtrudePolygon>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import * as THREE from "three";
|
||||
import { BoxGeometry, DoubleSide, MathUtils, MeshStandardMaterial, RepeatWrapping, SRGBColorSpace, TextureLoader, Vector3 } from "three";
|
||||
import { Base } from "@react-three/csg";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { MeshDiscardMaterial } from "@react-three/drei";
|
||||
@@ -48,47 +48,47 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
const centerZ = (startZ + endZ) / 2;
|
||||
const centerY = wall.wallHeight / 2;
|
||||
|
||||
const textureLoader = new THREE.TextureLoader();
|
||||
const textureLoader = new TextureLoader();
|
||||
|
||||
const [defaultWallTexture, material1WallTexture] = useMemo(() => {
|
||||
const inside = textureLoader.load(defaultMaterial);
|
||||
inside.wrapS = inside.wrapT = THREE.RepeatWrapping;
|
||||
inside.wrapS = inside.wrapT = RepeatWrapping;
|
||||
inside.repeat.set(wallLength / 10, wall.wallHeight / 10);
|
||||
inside.colorSpace = THREE.SRGBColorSpace;
|
||||
inside.colorSpace = SRGBColorSpace;
|
||||
|
||||
const outside = textureLoader.load(material1);
|
||||
outside.wrapS = outside.wrapT = THREE.RepeatWrapping;
|
||||
outside.wrapS = outside.wrapT = RepeatWrapping;
|
||||
outside.repeat.set(wallLength / 10, wall.wallHeight / 10);
|
||||
outside.colorSpace = THREE.SRGBColorSpace;
|
||||
outside.colorSpace = SRGBColorSpace;
|
||||
|
||||
return [inside, outside];
|
||||
}, [wallLength, wall.wallHeight]);
|
||||
|
||||
const materials = useMemo(() => {
|
||||
return [
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Left
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Right
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Top
|
||||
new THREE.MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: THREE.DoubleSide, visible: visible, clipShadows: true }), // Bottom
|
||||
new THREE.MeshStandardMaterial({
|
||||
new MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: DoubleSide, visible: visible, clipShadows: true }), // Left
|
||||
new MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: DoubleSide, visible: visible, clipShadows: true }), // Right
|
||||
new MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: DoubleSide, visible: visible, clipShadows: true }), // Top
|
||||
new MeshStandardMaterial({ color: Constants.wallConfig.defaultColor, side: DoubleSide, visible: visible, clipShadows: true }), // Bottom
|
||||
new MeshStandardMaterial({
|
||||
color: Constants.wallConfig.defaultColor,
|
||||
side: THREE.DoubleSide,
|
||||
side: DoubleSide,
|
||||
map: wall.insideMaterial === "Default Material" ? defaultWallTexture : material1WallTexture,
|
||||
}),
|
||||
new THREE.MeshStandardMaterial({
|
||||
new MeshStandardMaterial({
|
||||
color: Constants.wallConfig.defaultColor,
|
||||
side: THREE.DoubleSide,
|
||||
side: DoubleSide,
|
||||
map: wall.outsideMaterial === "Default Material" ? defaultWallTexture : material1WallTexture,
|
||||
}),
|
||||
];
|
||||
}, [defaultWallTexture, material1WallTexture, wall, visible]);
|
||||
|
||||
const geometry = useMemo(() => new THREE.BoxGeometry(wallLength, wall.wallHeight, wall.wallThickness), [wallLength, wall.wallHeight, wall.wallThickness]);
|
||||
const geometry = useMemo(() => new BoxGeometry(wallLength, wall.wallHeight, wall.wallThickness), [wallLength, wall.wallHeight, wall.wallThickness]);
|
||||
|
||||
useFrame(() => {
|
||||
if (!meshRef.current) return;
|
||||
const v = new THREE.Vector3();
|
||||
const u = new THREE.Vector3();
|
||||
const v = new Vector3();
|
||||
const u = new Vector3();
|
||||
|
||||
let nextVisible = true;
|
||||
|
||||
@@ -108,6 +108,13 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
}
|
||||
});
|
||||
|
||||
function clampDecalPosition(decal: Decal, wallLength: number, wallHeight: number) {
|
||||
const localPos = new Vector3(...decal.decalPosition);
|
||||
localPos.x = MathUtils.clamp(localPos.x, -wallLength / 2, wallLength / 2);
|
||||
localPos.y = MathUtils.clamp(localPos.y, -wallHeight / 2, wallHeight / 2);
|
||||
return localPos.toArray() as [number, number, number];
|
||||
}
|
||||
|
||||
return (
|
||||
<mesh castShadow receiveShadow name={`Wall-${wall.wallUuid}`} key={wall.wallUuid} userData={wall}>
|
||||
{assets.length > 0 || (walls[0].wallUuid === wall.wallUuid && wallAssets.length > 0) ? (
|
||||
@@ -116,7 +123,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
castShadow
|
||||
receiveShadow
|
||||
ref={meshRef}
|
||||
geometry={visible ? geometry : new THREE.BoxGeometry(0.00001, 0.00001)}
|
||||
geometry={visible ? geometry : new BoxGeometry(0.00001, 0.00001)}
|
||||
position={[centerX, centerY, centerZ]}
|
||||
rotation={[0, -angle, 0]}
|
||||
userData={wall}
|
||||
@@ -158,7 +165,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
|
||||
<MeshDiscardMaterial />
|
||||
|
||||
{wall.decals.map((decal) => (
|
||||
<DecalInstance parent={wall} visible={visible} key={decal.decalUuid} decal={decal} />
|
||||
<DecalInstance parent={wall} visible={visible} key={decal.decalUuid} decal={decal} overWritePosition={clampDecalPosition(decal, wallLength, wall.wallHeight)} />
|
||||
))}
|
||||
</mesh>
|
||||
</mesh>
|
||||
|
||||
@@ -33,6 +33,7 @@ interface FloorStore {
|
||||
getFloorsByPoints: (points: [Point, Point]) => Floor[] | [];
|
||||
getFloorPointById: (uuid: string) => Point | undefined;
|
||||
getConnectedPoints: (uuid: string) => Point[];
|
||||
getDecalById: (uuid: string) => Decal | undefined;
|
||||
}
|
||||
|
||||
export const createFloorStore = () => {
|
||||
@@ -431,6 +432,14 @@ export const createFloorStore = () => {
|
||||
}
|
||||
return connected;
|
||||
},
|
||||
|
||||
getDecalById: (decalUuid: string): Decal | undefined => {
|
||||
for (const floor of get().floors) {
|
||||
const decal = floor.decals.find((d) => d.decalUuid === decalUuid);
|
||||
if (decal) return JSON.parse(JSON.stringify(decal));
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
@@ -32,6 +32,7 @@ interface WallStore {
|
||||
getWallPointById: (wallUuid: string) => Point | undefined;
|
||||
getConnectedPoints: (wallUuid: string) => Point[];
|
||||
getConnectedWallsByWallId: (wallUuid: string, skipSelf: boolean) => Walls;
|
||||
getDecalById: (decalUuid: string) => Decal | undefined;
|
||||
}
|
||||
|
||||
export const createWallStore = () => {
|
||||
@@ -312,6 +313,14 @@ export const createWallStore = () => {
|
||||
return w.points.some((p) => pointUuids.includes(p.pointUuid));
|
||||
});
|
||||
},
|
||||
|
||||
getDecalById: (decalUuid: string): Decal | undefined => {
|
||||
for (const wall of get().walls) {
|
||||
const decal = wall.decals.find((d) => d.decalUuid === decalUuid);
|
||||
if (decal) return JSON.parse(JSON.stringify(decal));
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
}))
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user