diff --git a/app/src/assets/shaders/point/point.frag.glsl b/app/src/assets/shaders/box/box1.frag.glsl similarity index 100% rename from app/src/assets/shaders/point/point.frag.glsl rename to app/src/assets/shaders/box/box1.frag.glsl diff --git a/app/src/assets/shaders/point/point.vert.glsl b/app/src/assets/shaders/box/box1.vert.glsl similarity index 100% rename from app/src/assets/shaders/point/point.vert.glsl rename to app/src/assets/shaders/box/box1.vert.glsl diff --git a/app/src/assets/shaders/zone/zone1.frag.glsl b/app/src/assets/shaders/plane/plane1.frag.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone1.frag.glsl rename to app/src/assets/shaders/plane/plane1.frag.glsl diff --git a/app/src/assets/shaders/zone/zone1.vert.glsl b/app/src/assets/shaders/plane/plane1.vert.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone1.vert.glsl rename to app/src/assets/shaders/plane/plane1.vert.glsl diff --git a/app/src/assets/shaders/zone/zone2.frag.glsl b/app/src/assets/shaders/plane/plane2.frag.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone2.frag.glsl rename to app/src/assets/shaders/plane/plane2.frag.glsl diff --git a/app/src/assets/shaders/zone/zone2.vert.glsl b/app/src/assets/shaders/plane/plane2.vert.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone2.vert.glsl rename to app/src/assets/shaders/plane/plane2.vert.glsl diff --git a/app/src/assets/shaders/zone/zone3.frag.glsl b/app/src/assets/shaders/plane/plane3.frag.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone3.frag.glsl rename to app/src/assets/shaders/plane/plane3.frag.glsl diff --git a/app/src/assets/shaders/zone/zone3.vert.glsl b/app/src/assets/shaders/plane/plane3.vert.glsl similarity index 100% rename from app/src/assets/shaders/zone/zone3.vert.glsl rename to app/src/assets/shaders/plane/plane3.vert.glsl diff --git a/app/src/assets/shaders/edge/edge-fade.frag.glsl b/app/src/assets/shaders/polygon/edge-fade1.frag.glsl similarity index 100% rename from app/src/assets/shaders/edge/edge-fade.frag.glsl rename to app/src/assets/shaders/polygon/edge-fade1.frag.glsl diff --git a/app/src/assets/shaders/edge/edge-fade.vert.glsl b/app/src/assets/shaders/polygon/edge-fade1.vert.glsl similarity index 100% rename from app/src/assets/shaders/edge/edge-fade.vert.glsl rename to app/src/assets/shaders/polygon/edge-fade1.vert.glsl diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx index 2d4c6a0..3b32d5b 100644 --- a/app/src/modules/builder/point/point.tsx +++ b/app/src/modules/builder/point/point.tsx @@ -1,18 +1,16 @@ import * as THREE from "three"; import * as Constants from "../../../types/world/worldConstants"; -import { useRef, useState, useEffect, useMemo } from "react"; +import { useState, useEffect, useMemo } from "react"; import { useSocketStore, useToolMode } from "../../../store/builder/store"; import { DragControls } from "@react-three/drei"; import { useThree } from "@react-three/fiber"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useSelectedPoints } from "../../../store/simulation/useSimulationStore"; import { usePointSnapping } from "./helpers/usePointSnapping"; -import useShaderReader from "../../../utils/scene/useShaderReader"; import { useParams } from "react-router-dom"; import { useSceneContext } from "../../scene/sceneContext"; -import vertexShaderUrl from "../../../assets/shaders/point/point.vert.glsl"; -import fragmentShaderUrl from "../../../assets/shaders/point/point.frag.glsl"; +import BoxMaterial from "../wrappers/materials/boxMaterial"; import { upsertAisleApi } from "../../../services/factoryBuilder/aisle/upsertAisleApi"; import { deleteAisleApi } from "../../../services/factoryBuilder/aisle/deleteAisleApi"; @@ -30,12 +28,10 @@ import { handleCanvasCursors } from "../../../utils/mouseUtils/handleCanvasCurso import { calculateAssetTransformationOnWall } from "../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall"; function Point({ point }: { readonly point: Point }) { - const materialRef = useRef(null); - const vertexShader = useShaderReader(vertexShaderUrl); - const fragmentShader = useShaderReader(fragmentShaderUrl); const { raycaster, camera, pointer } = useThree(); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const [isHovered, setIsHovered] = useState(false); + const [isDeleteHovered, setIsDeleteHovered] = useState(false); const [isSelected, setIsSelected] = useState(false); const [dragOffset, setDragOffset] = useState(null); const { socket } = useSocketStore(); @@ -105,35 +101,6 @@ function Point({ point }: { readonly point: Point }) { } } - useEffect(() => { - if (materialRef.current && (toolMode === "move" || toolMode === "2D-Delete")) { - let innerColor; - let outerColor; - if (isHovered) { - innerColor = toolMode === "2D-Delete" ? colors.defaultDeleteColor : colors.defaultOuterColor; - outerColor = toolMode === "2D-Delete" ? colors.defaultDeleteColor : colors.defaultOuterColor; - } else { - innerColor = colors.defaultInnerColor; - outerColor = colors.defaultOuterColor; - } - materialRef.current.uniforms.uInnerColor.value.set(innerColor); - materialRef.current.uniforms.uOuterColor.value.set(outerColor); - materialRef.current.uniformsNeedUpdate = true; - } else if (materialRef.current && toolMode !== "move") { - materialRef.current.uniforms.uInnerColor.value.set(colors.defaultInnerColor); - materialRef.current.uniforms.uOuterColor.value.set(colors.defaultOuterColor); - materialRef.current.uniformsNeedUpdate = true; - } - }, [isHovered, colors.defaultInnerColor, colors.defaultOuterColor, colors.defaultDeleteColor, toolMode]); - - const uniforms = useMemo( - () => ({ - uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) }, - uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) }, - }), - [colors.defaultInnerColor, colors.defaultOuterColor] - ); - const handleDrag = (point: Point) => { if (toolMode === "move" && isHovered && dragOffset) { raycaster.setFromCamera(pointer, camera); @@ -705,8 +672,6 @@ function Point({ point }: { readonly point: Point }) { } }, [selectedPoints]); - if (!point || !vertexShader || !fragmentShader) return null; - return ( <> {!isSelected ? ( @@ -723,25 +688,36 @@ function Point({ point }: { readonly point: Point }) { onPointerOver={(e) => { if (!hoveredPoint && selectedPoints.length === 0 && e.buttons === 0 && !e.ctrlKey) { setHoveredPoint(point); - setIsHovered(true); if (toolMode === "move") { + setIsHovered(true); handleCanvasCursors("grab"); + } else if (toolMode === "2D-Delete") { + setIsDeleteHovered(true); } } }} onPointerOut={() => { if (hoveredPoint) { + handleCanvasCursors("default"); setHoveredPoint(null); if (!hoveredLine) { handleCanvasCursors("default"); } } setIsHovered(false); + setIsDeleteHovered(false); }} userData={point} > - + ) : ( diff --git a/app/src/modules/builder/point/reference/referencePoint.tsx b/app/src/modules/builder/point/reference/referencePoint.tsx index c577ee2..2884a56 100644 --- a/app/src/modules/builder/point/reference/referencePoint.tsx +++ b/app/src/modules/builder/point/reference/referencePoint.tsx @@ -1,16 +1,9 @@ import * as THREE from "three"; -import { useRef, useMemo } from "react"; import * as Constants from "../../../../types/world/worldConstants"; -import useShaderReader from "../../../../utils/scene/useShaderReader"; -import vertexShaderUrl from "../../../../assets/shaders/point/point.vert.glsl"; -import fragmentShaderUrl from "../../../../assets/shaders/point/point.frag.glsl"; +import BoxMaterial from "../../wrappers/materials/boxMaterial"; function ReferencePoint({ point }: { readonly point: Point }) { - const materialRef = useRef(null); - const vertexShader = useShaderReader(vertexShaderUrl); - const fragmentShader = useShaderReader(fragmentShaderUrl); - const boxScale: [number, number, number] = Constants.pointConfig.boxScale; const colors = { defaultInnerColor: Constants.pointConfig.defaultInnerColor, @@ -18,14 +11,6 @@ function ReferencePoint({ point }: { readonly point: Point }) { defaultDeleteColor: Constants.pointConfig.deleteColor, }; - const uniforms = useMemo( - () => ({ - uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) }, - uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) }, - }), - [colors.defaultInnerColor, colors.defaultOuterColor, colors.defaultDeleteColor] - ); - if (!point) { return null; } @@ -41,12 +26,12 @@ function ReferencePoint({ point }: { readonly point: Point }) { pointName = "Zone-Point"; } - if (!point || !vertexShader || !fragmentShader) return null; + if (!point) return null; return ( - + ); } diff --git a/app/src/modules/builder/wrappers/materials/boxMaterial.tsx b/app/src/modules/builder/wrappers/materials/boxMaterial.tsx new file mode 100644 index 0000000..65f4a84 --- /dev/null +++ b/app/src/modules/builder/wrappers/materials/boxMaterial.tsx @@ -0,0 +1,107 @@ +import { useMemo } from "react"; +import * as Constants from "../../../../types/world/worldConstants"; +import { Color, DoubleSide, ShaderMaterial, MeshStandardMaterial } from "three"; +import useShaderReader from "../../../../utils/scene/useShaderReader"; + +import edgeVertex from "../../../../assets/shaders/box/box1.vert.glsl"; +import edgeFragment from "../../../../assets/shaders/box/box1.frag.glsl"; + +type BoxMaterialProps = { + color?: string; + transparent?: boolean; + depthWrite?: boolean; + depthTest?: boolean; + opacity?: number; + polygonOffset?: boolean; + polygonOffsetFactor?: number; + polygonOffsetUnits?: number; + variant?: "box1" | "none"; + isHovered?: boolean; +} & ( + | { + variant?: "none"; + } + | { + variant: "box1"; + uOuterColor?: string; + uInnerColor?: string; + uDeleteColor?: string; + isDeleteHovered?: boolean; + } +); + +function BoxMaterial({ + color = "white", + transparent = false, + depthWrite = true, + depthTest = true, + opacity = 1, + polygonOffset = false, + polygonOffsetFactor, + polygonOffsetUnits, + variant = "none", + isHovered = false, + ...rest +}: Readonly) { + const vertexShader = useShaderReader(edgeVertex); + const fragmentShader = useShaderReader(edgeFragment); + + const box1Props = variant === "box1" ? (rest as { uOuterColor?: string; uInnerColor?: string; uDeleteColor: string; isDeleteHovered?: boolean }) : null; + + const uOuterColor = box1Props?.uOuterColor ?? Constants.pointConfig.defaultOuterColor; + const uInnerColor = box1Props?.uInnerColor ?? Constants.pointConfig.defaultInnerColor; + const uDeleteColor = box1Props?.uDeleteColor ?? Constants.pointConfig.deleteColor; + const isDeleteHovered = box1Props?.isDeleteHovered ?? false; + + const finalOuterColor = isDeleteHovered ? uDeleteColor : uOuterColor; + const finalInnerColor = isDeleteHovered ? uDeleteColor : isHovered ? uOuterColor : uInnerColor; + const finalColor = isDeleteHovered ? uDeleteColor : color; + + const polygonOffsetProps = polygonOffset + ? { + polygonOffsetFactor: polygonOffsetFactor ?? -1, + polygonOffsetUnits: polygonOffsetUnits ?? -1, + } + : {}; + + const basicMaterial = useMemo(() => { + if (variant !== "none") return null; + return new MeshStandardMaterial({ + color: new Color(finalColor), + side: DoubleSide, + transparent, + depthWrite, + depthTest, + polygonOffset, + ...polygonOffsetProps, + opacity, + }); + }, [finalColor, transparent, depthWrite, depthTest, polygonOffset, polygonOffsetProps, opacity, variant]); + + const boxMaterial1 = useMemo(() => { + if (!vertexShader || !fragmentShader || variant !== "box1") return null; + + return new ShaderMaterial({ + side: DoubleSide, + vertexShader, + fragmentShader, + uniforms: { + uOuterColor: { value: new Color(finalOuterColor) }, + uInnerColor: { value: new Color(finalInnerColor) }, + }, + transparent, + depthWrite, + depthTest, + polygonOffset, + ...polygonOffsetProps, + opacity, + }); + }, [finalOuterColor, finalInnerColor, vertexShader, fragmentShader, transparent, depthWrite, depthTest, polygonOffset, polygonOffsetProps, opacity, variant]); + + if (variant === "none" && basicMaterial) return ; + if (variant === "box1" && boxMaterial1) return ; + + return null; +} + +export default BoxMaterial; diff --git a/app/src/modules/builder/wrappers/materials/planeMaterial.tsx b/app/src/modules/builder/wrappers/materials/planeMaterial.tsx index ae260ae..243f37f 100644 --- a/app/src/modules/builder/wrappers/materials/planeMaterial.tsx +++ b/app/src/modules/builder/wrappers/materials/planeMaterial.tsx @@ -4,18 +4,18 @@ import { useFrame } from "@react-three/fiber"; import { useSceneStore } from "../../../../store/scene/useSceneStore"; import useShaderReader from "../../../../utils/scene/useShaderReader"; -import zone1Vertex from "../../../../assets/shaders/zone/zone1.vert.glsl"; -import zone1Fragment from "../../../../assets/shaders/zone/zone1.frag.glsl"; +import plane1Vertex from "../../../../assets/shaders/plane/plane1.vert.glsl"; +import plane1Fragment from "../../../../assets/shaders/plane/plane1.frag.glsl"; -import zone2Vertex from "../../../../assets/shaders/zone/zone2.vert.glsl"; -import zone2Fragment from "../../../../assets/shaders/zone/zone2.frag.glsl"; +import plane2Vertex from "../../../../assets/shaders/plane/plane2.vert.glsl"; +import plane2Fragment from "../../../../assets/shaders/plane/plane2.frag.glsl"; -import zone3Vertex from "../../../../assets/shaders/zone/zone3.vert.glsl"; -import zone3Fragment from "../../../../assets/shaders/zone/zone3.frag.glsl"; +import plane3Vertex from "../../../../assets/shaders/plane/plane3.vert.glsl"; +import plane3Fragment from "../../../../assets/shaders/plane/plane3.frag.glsl"; type PlaneMaterialProps = { color?: string; - variant?: "zone1" | "zone2" | "zone3"; + variant?: "plane1" | "plane2" | "plane3"; transparent?: boolean; opacity?: number; depthWrite?: boolean; @@ -27,11 +27,11 @@ type PlaneMaterialProps = { function PlaneMaterial({ color = "white", - variant = "zone1", + variant = "plane1", transparent = false, opacity = 1, - depthWrite, - depthTest, + depthWrite = true, + depthTest = true, polygonOffset = false, polygonOffsetFactor, polygonOffsetUnits, @@ -39,13 +39,20 @@ function PlaneMaterial({ const { limitFps } = useSceneStore(); const materialRef = useRef(null); - const vertexShaderUrl = variant === "zone1" ? zone1Vertex : variant === "zone2" ? zone2Vertex : variant === "zone3" ? zone3Vertex : zone1Vertex; + const vertexShaderUrl = variant === "plane1" ? plane1Vertex : variant === "plane2" ? plane2Vertex : variant === "plane3" ? plane3Vertex : plane1Vertex; - const fragmentShaderUrl = variant === "zone1" ? zone1Fragment : variant === "zone2" ? zone2Fragment : variant === "zone3" ? zone3Fragment : zone1Fragment; + const fragmentShaderUrl = variant === "plane1" ? plane1Fragment : variant === "plane2" ? plane2Fragment : variant === "plane3" ? plane3Fragment : plane1Fragment; const vertexShader = useShaderReader(vertexShaderUrl); const fragmentShader = useShaderReader(fragmentShaderUrl); + const polygonOffsetProps = polygonOffset + ? { + polygonOffsetFactor: polygonOffsetFactor ?? -1, + polygonOffsetUnits: polygonOffsetUnits ?? -1, + } + : {}; + const material = useMemo(() => { if (!vertexShader || !fragmentShader) return null; @@ -62,8 +69,7 @@ function PlaneMaterial({ depthWrite, depthTest, polygonOffset, - polygonOffsetFactor, - polygonOffsetUnits, + ...polygonOffsetProps, }); }, [color, vertexShader, fragmentShader, transparent, opacity, depthWrite, depthTest, polygonOffset, polygonOffsetFactor, polygonOffsetUnits]); diff --git a/app/src/modules/builder/wrappers/materials/polygonMaterial.tsx b/app/src/modules/builder/wrappers/materials/polygonMaterial.tsx index 2fa863f..73a3d1c 100644 --- a/app/src/modules/builder/wrappers/materials/polygonMaterial.tsx +++ b/app/src/modules/builder/wrappers/materials/polygonMaterial.tsx @@ -2,8 +2,8 @@ import { useMemo } from "react"; import { Color, DoubleSide, ShaderMaterial, Vector3, MeshStandardMaterial } from "three"; import useShaderReader from "../../../../utils/scene/useShaderReader"; -import edgeVertex from "../../../../assets/shaders/edge/edge-fade.vert.glsl"; -import edgeFragment from "../../../../assets/shaders/edge/edge-fade.frag.glsl"; +import edgeVertex from "../../../../assets/shaders/polygon/edge-fade1.vert.glsl"; +import edgeFragment from "../../../../assets/shaders/polygon/edge-fade1.frag.glsl"; type PolygonMaterialProps = { points: { position: [number, number, number] }[]; @@ -15,26 +15,36 @@ type PolygonMaterialProps = { polygonOffset?: boolean; polygonOffsetFactor?: number; polygonOffsetUnits?: number; - fadeDistance?: number; variant?: "edge" | "none"; -}; +} & ( + | { + variant?: "none"; + } + | { + variant: "edge"; + fadeDistance?: number; + } +); function PolygonMaterial({ points, color = "white", transparent = false, - depthWrite, - depthTest, + depthWrite = true, + depthTest = true, opacity = 1, polygonOffset = false, polygonOffsetFactor, polygonOffsetUnits, - fadeDistance = 2.0, variant = "none", + ...rest }: Readonly) { const vertexShader = useShaderReader(edgeVertex); const fragmentShader = useShaderReader(edgeFragment); + const edgeProps = variant === "edge" ? (rest as { fadeDistance?: number }) : null; + const fadeDistance = edgeProps?.fadeDistance ?? 2.0; + const edges = useMemo(() => { return points.map((p, i) => { const next = points[(i + 1) % points.length]; @@ -42,6 +52,27 @@ function PolygonMaterial({ }); }, [points]); + const polygonOffsetProps = polygonOffset + ? { + polygonOffsetFactor: polygonOffsetFactor ?? -1, + polygonOffsetUnits: polygonOffsetUnits ?? -1, + } + : {}; + + const basicMaterial = useMemo(() => { + if (variant !== "none") return null; + return new MeshStandardMaterial({ + color: new Color(color), + side: DoubleSide, + transparent, + depthWrite, + depthTest, + polygonOffset, + ...polygonOffsetProps, + opacity, + }); + }, [color, transparent, depthWrite, depthTest, polygonOffset, polygonOffsetProps, opacity, variant]); + const edgeMaterial = useMemo(() => { if (!vertexShader || !fragmentShader || variant !== "edge") return null; @@ -64,26 +95,10 @@ function PolygonMaterial({ depthWrite, depthTest, polygonOffset, - polygonOffsetFactor, - polygonOffsetUnits, + ...polygonOffsetProps, opacity, }); - }, [color, fadeDistance, vertexShader, fragmentShader, edges]); - - const basicMaterial = useMemo(() => { - if (variant !== "none") return null; - return new MeshStandardMaterial({ - color: new Color(color), - side: DoubleSide, - transparent, - depthWrite, - depthTest, - polygonOffset, - polygonOffsetFactor, - polygonOffsetUnits, - opacity, - }); - }, [color]); + }, [color, fadeDistance, vertexShader, fragmentShader, edges, transparent, depthWrite, depthTest, polygonOffset, polygonOffsetProps, opacity, variant]); if (variant === "none" && basicMaterial) return ; if (variant === "edge" && edgeMaterial) return ; diff --git a/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx index 04f5a14..aa730c0 100644 --- a/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx +++ b/app/src/modules/builder/zone/Instances/Instance/zoneInstance.tsx @@ -40,10 +40,10 @@ function ZoneInstance({ zone }: { readonly zone: Zone }) { - + - + ); })}