added zone properties and also added zone view port updation

This commit is contained in:
2025-09-29 13:55:01 +05:30
parent a064244eaf
commit 9c0cf87dad
10 changed files with 170 additions and 208 deletions

View File

@@ -32,13 +32,13 @@ type DisplayComponent =
| "aisleProperties"
| "wallProperties"
| "floorProperties"
| "zoneProperties"
| "assetProperties"
| "selectedWallProperties"
| "selectedFloorProperties"
| "selectedDecalProperties"
| "selectedAisleProperties"
| "selectedZoneProperties"
| "zoneProperties"
| "simulations"
| "mechanics"
| "analysis"
@@ -140,7 +140,7 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("selectedZoneProperties");
return;
}
if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle) {
if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle && !selectedZone) {
if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties");
return;
@@ -153,16 +153,16 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("floorProperties");
return;
}
if (toolMode === "Zone") {
setDisplayComponent("zoneProperties");
return;
}
setDisplayComponent("globalProperties");
return;
}
}
if (subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation")) {
setDisplayComponent("zoneProperties");
return;
}
setDisplayComponent("none");
}, [viewVersionHistory, activeModule, subModule, isComparing, selectedAssets, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal, selectedZone]);

View File

@@ -2,11 +2,11 @@ import { useEffect, useState } from "react";
import InputToggle from "../../../ui/inputs/InputToggle";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import defaultTexture from '../../../../assets/textures/floor/white.png';
import flootTexture1 from '../../../../assets/textures/floor/factory wall texture.jpg';
import flootTexture2 from '../../../../assets/textures/floor/tex1/MI_FactoryConcreteFloor01_BaseColor.001.jpg';
import flootTexture3 from '../../../../assets/textures/floor/tex2/MI_FloorMats01_baseColor.png';
import flootTexture4 from '../../../../assets/textures/floor/tex3/metal_plate_diff_1k.jpg';
import defaultTexture from "../../../../assets/textures/floor/white.png";
import flootTexture1 from "../../../../assets/textures/floor/factory wall texture.jpg";
import flootTexture2 from "../../../../assets/textures/floor/tex1/MI_FactoryConcreteFloor01_BaseColor.001.jpg";
import flootTexture3 from "../../../../assets/textures/floor/tex2/MI_FloorMats01_baseColor.png";
import flootTexture4 from "../../../../assets/textures/floor/tex3/metal_plate_diff_1k.jpg";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
@@ -29,7 +29,7 @@ const FloorProperties = () => {
const [activeSurface, setActiveSurface] = useState<"top" | "side">("top");
const [selectedMaterials, setSelectedMaterials] = useState<{ top: Material | null; side: Material | null; }>({ top: null, side: null, });
const [selectedMaterials, setSelectedMaterials] = useState<{ top: Material | null; side: Material | null }>({ top: null, side: null });
useEffect(() => {
setSelectedMaterials({
@@ -61,30 +61,11 @@ const FloorProperties = () => {
return (
<div className="wall-properties-container">
<section className="wall-properties-section">
<div className="header">Floor</div>
<div className="header">Properties</div>
<div className="wall-properties">
<InputWithDropDown
label="Depth"
value={`${floorDepth}`}
min={0.1}
max={10}
step={0.1}
onChange={handleDepthChange}
/>
<InputToggle
value={isBeveled}
label="Beveled"
inputKey=""
onClick={() => handleIsBevelChange(!isBeveled)}
/>
<InputWithDropDown
label="Bevel Strength"
value={`${bevelStrength}`}
min={1}
max={10}
step={1}
onChange={handleBevelChange}
/>
<InputWithDropDown label="Depth" value={`${floorDepth}`} min={0.1} max={10} step={0.1} onChange={handleDepthChange} />
<InputToggle value={isBeveled} label="Beveled" inputKey="" onClick={() => handleIsBevelChange(!isBeveled)} />
<InputWithDropDown label="Bevel Strength" value={`${bevelStrength}`} min={1} max={10} step={1} onChange={handleBevelChange} />
</div>
</section>
@@ -95,47 +76,19 @@ const FloorProperties = () => {
<div className="material-preview">
<div className="sides-wrapper">
<button
className={`side-wrapper ${activeSurface === "top" ? "active" : ""}`}
onClick={() => setActiveSurface("top")}
>
<button className={`side-wrapper ${activeSurface === "top" ? "active" : ""}`} onClick={() => setActiveSurface("top")}>
<div className="label">Top</div>
<div className="texture-image">
{selectedMaterials.top && (
<img
draggable={false}
src={selectedMaterials.top.texture}
alt={selectedMaterials.top.textureName}
/>
)}
</div>
<div className="texture-image">{selectedMaterials.top && <img draggable={false} src={selectedMaterials.top.texture} alt={selectedMaterials.top.textureName} />}</div>
</button>
<button
className={`side-wrapper ${activeSurface === "side" ? "active" : ""}`}
onClick={() => setActiveSurface("side")}
>
<button className={`side-wrapper ${activeSurface === "side" ? "active" : ""}`} onClick={() => setActiveSurface("side")}>
<div className="label">Side</div>
<div className="texture-image">
{selectedMaterials.side && (
<img
draggable={false}
src={selectedMaterials.side.texture}
alt={selectedMaterials.side.textureName}
/>
)}
</div>
<div className="texture-image">{selectedMaterials.side && <img draggable={false} src={selectedMaterials.side.texture} alt={selectedMaterials.side.textureName} />}</div>
</button>
</div>
<div className="preview">
{selectedMaterials[activeSurface] && (
<img
draggable={false}
src={selectedMaterials[activeSurface]!.texture}
alt={selectedMaterials[activeSurface]!.textureName}
/>
)}
{selectedMaterials[activeSurface] && <img draggable={false} src={selectedMaterials[activeSurface]!.texture} alt={selectedMaterials[activeSurface]!.textureName} />}
</div>
</div>
@@ -155,11 +108,7 @@ const FloorProperties = () => {
>
<div className="material-property">
<div className="material-image">
<img
draggable={false}
src={material.texture}
alt={material.textureName}
/>
<img draggable={false} src={material.texture} alt={material.textureName} />
</div>
<div className="material-name">{material.textureName}</div>
</div>

View File

@@ -2,6 +2,8 @@ import { useState } from "react";
import { useParams } from "react-router-dom";
import { ArrowIcon } from "../../../icons/ExportCommonIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { useSocketStore } from "../../../../store/socket/useSocketStore";
@@ -17,10 +19,10 @@ interface TextureList {
}
export const zoneTextureList: TextureList[] = [
{ color: "blue", id: "#0000ff", zoneType: "" },
{ color: "red", id: "#ff0000", zoneType: "" },
{ color: "blue", id: "#0000FF", zoneType: "" },
{ color: "red", id: "#FF0000", zoneType: "" },
{ color: "yellow", id: "#FBE50E", zoneType: "" },
{ color: "white", id: "#ffffff", zoneType: "" },
{ color: "white", id: "#FFFFFF", zoneType: "" },
{ color: "green", id: "#43C06D", zoneType: "" },
{ color: "orange", id: "#FF711B", zoneType: "" },
{ color: "purple", id: "#AF52DE", zoneType: "" },
@@ -28,7 +30,7 @@ export const zoneTextureList: TextureList[] = [
function SelectedZoneProperties() {
const { projectId } = useParams();
const { selectedZone } = useBuilderStore();
const { selectedZone, editZoneViewPort, setEditZoneViewPort, zoneViewPort } = useBuilderStore();
const { zoneStore, versionStore } = useSceneContext();
const { selectedVersion } = versionStore();
const { builderSocket } = useSocketStore();
@@ -90,13 +92,45 @@ function SelectedZoneProperties() {
updateZoneToBackend(updatedZone);
};
const handleZoneNameCHange = (newName: string) => {
const updatedZone = peekUpdateZone(selectedZone.zoneData.zoneUuid, { zoneName: newName });
updateZoneToBackend(updatedZone);
};
const handleSetView = () => {
if (zoneViewPort) {
setEditZoneViewPort(false);
const updatedZone = peekUpdateZone(selectedZone.zoneData.zoneUuid, {
viewPortPosition: [zoneViewPort.position.x, zoneViewPort.position.y, zoneViewPort.position.z],
viewPortTarget: [zoneViewPort.target.x, zoneViewPort.target.y, zoneViewPort.target.z],
});
updateZoneToBackend(updatedZone);
}
};
return (
<div className="zone-properties-container">
<div className="header">Zone Properties</div>
<section>
<div className="header">
<RenameInput value={selectedZone.zoneData.zoneName} onRename={handleZoneNameCHange} />
<div className="button" onClick={() => setEditZoneViewPort(!editZoneViewPort)}>
{editZoneViewPort ? "Cancel" : "Edit"}
</div>
</div>
<Vector3Input onChange={() => {}} header="Viewport Target" value={selectedZone.zoneData.viewPortTarget} disabled={!editZoneViewPort} />
<Vector3Input onChange={() => {}} header="Viewport Position" value={selectedZone.zoneData.viewPortPosition} disabled={!editZoneViewPort} />
{editZoneViewPort && (
<div className="button-save" onClick={handleSetView}>
Set View
</div>
)}
</section>
{/* Basic Properties */}
<section className="zone-properties-section">
<div className="header">{selectedZone.zoneData.zoneName}</div>
<div className="zone-properties">
<InputWithDropDown label="Height" value={selectedZone.zoneData.zoneHeight.toString()} min={1} max={25} step={1} onChange={handleHeightChange} />
</div>

View File

@@ -58,7 +58,7 @@ const WallProperties = () => {
return (
<div className="wall-properties-container">
<section className="wall-properties-section">
<div className="header">Wall</div>
<div className="header">Properties</div>
<div className="wall-properties">
<InputWithDropDown
label="Height"

View File

@@ -1,132 +1,71 @@
import React, { useEffect } from "react";
import RenameInput from "../../../ui/inputs/RenameInput";
import Vector3Input from "../customInput/Vector3Input";
import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
import {
useEditPosition,
usezonePosition,
usezoneTarget,
} from "../../../../store/builder/store";
import { zoneCameraUpdate } from "../../../../services/visulization/zone/zoneCameraUpdation";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { useState } from "react";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { ArrowIcon } from "../../../icons/ExportCommonIcons";
interface TextureList {
color: string;
id: string;
zoneType: string;
}
const ZoneProperties: React.FC = () => {
const { Edit, setEdit } = useEditPosition();
const { selectedZone, setSelectedZone } = useSelectedZoneStore();
const { zonePosition, setZonePosition } = usezonePosition();
const { zoneTarget, setZoneTarget } = usezoneTarget();
const { zoneStore, versionStore } = useSceneContext();
const { selectedVersion } = versionStore();
const { zones, setZoneName } = zoneStore()
export const zoneTextureList: TextureList[] = [
{ color: "blue", id: "#0000FF", zoneType: "" },
{ color: "red", id: "#FF0000", zoneType: "" },
{ color: "yellow", id: "#FBE50E", zoneType: "" },
{ color: "white", id: "#FFFFFF", zoneType: "" },
{ color: "green", id: "#43C06D", zoneType: "" },
{ color: "orange", id: "#FF711B", zoneType: "" },
{ color: "purple", id: "#AF52DE", zoneType: "" },
];
const { projectId } = useParams();
const { organization } = getUserData();
function ZoneProperties() {
const { zoneHeight, zoneColor, setZoneHeight, setZoneColor } = useBuilderStore();
const [collapseTexture, setCollapseTexture] = useState(true);
useEffect(() => {
setZonePosition(selectedZone.zoneViewPortPosition);
setZoneTarget(selectedZone.zoneViewPortTarget);
}, [selectedZone?.zoneViewPortPosition, selectedZone?.zoneViewPortTarget]);
async function handleSetView() {
try {
let zonesdata = {
zoneUuid: selectedZone.zoneUuid,
viewPortPosition: zonePosition,
viewPortTarget: zoneTarget,
};
let response = await zoneCameraUpdate(zonesdata, organization, projectId, selectedVersion?.versionId || "");
//
if (response.message === "zone updated") {
setEdit(false);
} else {
//
}
} catch (error) {
echo.error("Failed to set zone view");
}
}
function handleEditView() {
setEdit(!Edit); // This will toggle the `Edit` state correctly
}
async function handleZoneNameChange(newName: string) {
const zonesdata = {
zoneUuid: selectedZone.zoneUuid,
zoneName: newName,
const handleHeightChange = (val: string) => {
const height = parseFloat(val);
if (!isNaN(height)) {
setZoneHeight(height);
}
};
// Call your API to update the zone
let response = await zoneCameraUpdate(zonesdata, organization, projectId, selectedVersion?.versionId || "");
if (response.message === "zone updated") {
setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
setZoneName(selectedZone.zoneUuid, newName)
// setZones((prevZones: any[]) =>
// prevZones.map((zone) =>
// zone.zoneUuid === selectedZone.zoneUuid
// ? { ...zone, zoneName: newName }
// : zone
// )
// );
} else {
//
}
}
function handleVectorChange(
key: "zoneViewPortTarget" | "zoneViewPortPosition",
newValue: [number, number, number]
) {
setSelectedZone((prev) => ({ ...prev, [key]: newValue }));
}
const checkZoneNameDuplicate = (name: string) => {
return zones.some(
(zone: any) =>
zone.zoneName?.trim().toLowerCase() === name?.trim().toLowerCase() &&
zone.zoneUuid !== selectedZone.zoneUuid
);
};
const handleColorChange = (val: string) => {
setZoneColor(val);
};
return (
<div className="zone-properties-container">
<section>
<div className="header">
<RenameInput
value={selectedZone.zoneName}
onRename={handleZoneNameChange}
checkDuplicate={checkZoneNameDuplicate}
/>
<div className="button" onClick={handleEditView}>
{Edit ? "Cancel" : "Edit"}
</div>
return (
<div className="zone-properties-container">
<div className="header">Properties</div>
{/* Basic Properties */}
<section className="zone-properties-section">
<div className="zone-properties">
<InputWithDropDown label="Height" value={zoneHeight.toString()} min={1} max={25} step={1} onChange={handleHeightChange} />
</div>
</section>
{/* Texture */}
<section>
<button className="header" onClick={() => setCollapseTexture(!collapseTexture)} aria-expanded={!collapseTexture}>
<div className="value">Zone Texture</div>
<div className="icon" style={{ rotate: collapseTexture ? "" : "-90deg" }}>
<ArrowIcon />
</div>
</button>
{collapseTexture && (
<div className="zone-texture-container">
{zoneTextureList.map((val) => (
<button key={val.id} className={`zone-list ${zoneColor === val.id ? "selected" : ""}`} onClick={() => handleColorChange(val.id)} aria-pressed={zoneColor === val.id}>
<div className={`texture-display ${val.id}`} style={{ background: val.id }}></div>
<div className="zone-color">{val.color}</div>
</button>
))}
<input type="color" className="custom-color-picker" value={zoneColor} onChange={(e) => handleColorChange(e.target.value)} />
</div>
)}
</section>
</div>
<Vector3Input
onChange={(value) => handleVectorChange("zoneViewPortTarget", value)}
header="Viewport Target"
value={zoneTarget as [number, number, number]}
disabled={!Edit}
/>
<Vector3Input
onChange={(value) =>
handleVectorChange("zoneViewPortPosition", value)
}
header="Viewport Position"
value={zonePosition as [number, number, number]}
disabled={!Edit}
/>
{Edit && (
<div className="button-save" onClick={handleSetView}>
Set View
</div>
)}
</section>
</div>
);
};
);
}
export default ZoneProperties;

View File

@@ -26,7 +26,6 @@ export const useZoneAssetHandlers = () => {
const handleSelectZone = useCallback(
async (id: string) => {
if (selectedZone?.zoneUuid === id || id === "unassigned-zone") return;
setSubModule("zoneProperties");
const response = await getZoneData(id, organization, projectId, selectedVersion?.versionId || "");
if (!response) return;

View File

@@ -1,5 +1,7 @@
import { useRef } from "react";
import { useEffect, useRef } from "react";
import { Group, Vector3 } from "three";
import { useThree } from "@react-three/fiber";
import { CameraControls } from "@react-three/drei";
import useModuleStore from "../../../../../store/ui/useModuleStore";
import { useToggleView } from "../../../../../store/builder/store";
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
@@ -9,6 +11,7 @@ import PolygonMaterial from "../../../wrappers/materials/polygonMaterial";
import ZoneCornerReference from "./zoneCornerReference";
function ZoneInstance({ zone }: { readonly zone: Zone }) {
const { controls }: { controls: CameraControls } = useThree();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { selectedZone, setSelectedZone } = useBuilderStore();

View File

@@ -1,8 +1,10 @@
import React, { useEffect, useMemo } from "react";
import { Vector3 } from "three";
import { Html } from "@react-three/drei";
import { useFrame, useThree } from "@react-three/fiber";
import { CameraControls, Html } from "@react-three/drei";
import { useSceneContext } from "../../../scene/sceneContext";
import { useToggleView } from "../../../../store/builder/store";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
import Line from "../../line/line";
import Point from "../../point/point";
import ZoneInstance from "./Instance/zoneInstance";
@@ -10,13 +12,31 @@ import Zone2DInstance from "./Instance/zone2DInstance";
function ZoneInstances() {
const { zoneStore } = useSceneContext();
const { controls }: { controls: CameraControls } = useThree();
const { zones } = zoneStore();
const { toggleView } = useToggleView();
const { selectedZone, editZoneViewPort, setZoneViewPort, zoneViewPort } = useBuilderStore();
useEffect(() => {
// console.log('zones: ', zones);
}, [zones]);
useEffect(() => {
if (selectedZone) {
controls.setLookAt(...selectedZone.zoneData.viewPortPosition, ...selectedZone.zoneData.viewPortTarget, true);
}
}, [selectedZone?.zoneMesh]);
useFrame(() => {
if (editZoneViewPort) {
const position = controls.getPosition(new Vector3());
const target = controls.getTarget(new Vector3());
setZoneViewPort({ position, target });
} else if (!editZoneViewPort && zoneViewPort) {
setZoneViewPort(null);
}
});
const allPoints = useMemo(() => {
const points: Point[] = [];
const seenUuids = new Set<string>();

View File

@@ -34,6 +34,8 @@ interface BuilderState {
// Zone Settings
selectedZone: { zoneMesh: Object3D | null; zoneData: Zone } | null;
editZoneViewPort: boolean;
zoneViewPort: { position: Vector3; target: Vector3 } | null;
zoneHeight: number;
zoneColor: string;
@@ -95,6 +97,8 @@ interface BuilderState {
// Setters - Zone
setSelectedZone: (zone: { zoneMesh: Object3D | null; zoneData: Zone } | null) => void;
setEditZoneViewPort: (edit: boolean) => void;
setZoneViewPort: (viewPort: { position: Vector3; target: Vector3 } | null) => void;
setZoneHeight: (height: number) => void;
setZoneColor: (color: string) => void;
@@ -153,8 +157,10 @@ export const useBuilderStore = create<BuilderState>()(
topMaterial: "Default Material",
selectedZone: null,
editZoneViewPort: false,
zoneViewPort: null,
zoneHeight: 7,
zoneColor: "blue",
zoneColor: "#0000FF",
selectedDecal: null,
deletableDecal: null,
@@ -298,6 +304,18 @@ export const useBuilderStore = create<BuilderState>()(
});
},
setEditZoneViewPort: (edit: boolean) => {
set((state) => {
state.editZoneViewPort = edit;
});
},
setZoneViewPort: (viewPort: { position: Vector3; target: Vector3 } | null) => {
set((state) => {
state.zoneViewPort = viewPort;
});
},
setZoneHeight: (height: number) => {
set((state) => {
state.zoneHeight = height;

View File

@@ -14,7 +14,7 @@ export default useModuleStore;
// New store for subModule
type SubModule = "properties" | "simulations" | "mechanics" | "analysis" | "zoneProperties" | "resourceManagement";
type SubModule = "properties" | "simulations" | "mechanics" | "analysis" | "resourceManagement";
interface SubModuleStore {
subModule: SubModule;