added box mateial wrapper
This commit is contained in:
@@ -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<THREE.ShaderMaterial>(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<THREE.Vector3 | null>(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}
|
||||
>
|
||||
<boxGeometry args={boxScale} />
|
||||
<shaderMaterial ref={materialRef} uniforms={uniforms} vertexShader={vertexShader} fragmentShader={fragmentShader} />
|
||||
<BoxMaterial
|
||||
variant="box1"
|
||||
uOuterColor={colors.defaultOuterColor}
|
||||
uInnerColor={colors.defaultInnerColor}
|
||||
uDeleteColor={colors.defaultDeleteColor}
|
||||
isHovered={isHovered}
|
||||
isDeleteHovered={isDeleteHovered}
|
||||
/>
|
||||
</mesh>
|
||||
</DragControls>
|
||||
) : (
|
||||
|
||||
@@ -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<THREE.ShaderMaterial>(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 (
|
||||
<mesh position={new THREE.Vector3(...point.position)} name={pointName} uuid={point.pointUuid} userData={point}>
|
||||
<boxGeometry args={boxScale} />
|
||||
<shaderMaterial ref={materialRef} uniforms={uniforms} vertexShader={vertexShader} fragmentShader={fragmentShader} />
|
||||
<BoxMaterial variant="box1" uOuterColor={colors.defaultOuterColor} uInnerColor={colors.defaultInnerColor} />
|
||||
</mesh>
|
||||
);
|
||||
}
|
||||
|
||||
107
app/src/modules/builder/wrappers/materials/boxMaterial.tsx
Normal file
107
app/src/modules/builder/wrappers/materials/boxMaterial.tsx
Normal file
@@ -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<BoxMaterialProps>) {
|
||||
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 <primitive object={basicMaterial} attach="material" />;
|
||||
if (variant === "box1" && boxMaterial1) return <primitive object={boxMaterial1} attach="material" />;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default BoxMaterial;
|
||||
@@ -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<ShaderMaterial | null>(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]);
|
||||
|
||||
|
||||
@@ -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<PolygonMaterialProps>) {
|
||||
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 <primitive object={basicMaterial} attach="material" />;
|
||||
if (variant === "edge" && edgeMaterial) return <primitive object={edgeMaterial} attach="material" />;
|
||||
|
||||
@@ -40,10 +40,10 @@ function ZoneInstance({ zone }: { readonly zone: Zone }) {
|
||||
<group key={index}>
|
||||
<mesh position={midpoint} rotation={[0, -angle, 0]}>
|
||||
<planeGeometry args={[planeWidth, planeHeight]} />
|
||||
<PlaneMaterial transparent depthWrite={false} depthTest={true} color={zone.zoneColor} variant="zone1" />
|
||||
<PlaneMaterial transparent depthWrite={false} depthTest={true} color={zone.zoneColor} variant="plane1" />
|
||||
</mesh>
|
||||
|
||||
<ZoneCornerReference showTop showBottom point={point} prevPoint={prevPoint} nextPoint={nextPoint} zone={zone} cornerThickness={0.25} />
|
||||
<ZoneCornerReference showTop={false} showBottom={false} point={point} prevPoint={prevPoint} nextPoint={nextPoint} zone={zone} cornerThickness={0.25} />
|
||||
</group>
|
||||
);
|
||||
})}
|
||||
|
||||
Reference in New Issue
Block a user