bug fix in wall, wall Asset, floor , and decal selection and unselection, added decal deletion

This commit is contained in:
2025-08-26 14:43:38 +05:30
parent 0387d7a932
commit 547fd1af12
21 changed files with 558 additions and 435 deletions

View File

@@ -127,6 +127,7 @@ const Assets: React.FC = () => {
]; ];
const { selectedSubCategory, setSelectedSubCategory } = useDecalStore(); const { selectedSubCategory, setSelectedSubCategory } = useDecalStore();
return ( return (
<div className="assets-container-main"> <div className="assets-container-main">
<Search onChange={handleSearchChange} /> <Search onChange={handleSearchChange} />
@@ -208,8 +209,7 @@ const Assets: React.FC = () => {
{activeSubcategories.map((cat, index) => ( {activeSubcategories.map((cat, index) => (
<div <div
key={index} key={index}
className={`catogory-asset-filter-wrapper ${ className={`catogory-asset-filter-wrapper ${selectedSubCategory === cat.name ? "active" : ""
selectedSubCategory === cat.name ? "active" : ""
}`} }`}
onClick={() => setSelectedSubCategory(cat.name)} onClick={() => setSelectedSubCategory(cat.name)}
> >

View File

@@ -1,29 +1,13 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Header from "./Header"; import Header from "./Header";
import useModuleStore, { import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
useSubModuleStore, import { AnalysisIcon, FilePackageIcon, MechanicsIcon, PropertiesIcon, SimulationIcon, } from "../../icons/SimulationIcons";
} from "../../../store/useModuleStore";
import {
AnalysisIcon,
FilePackageIcon,
MechanicsIcon,
PropertiesIcon,
SimulationIcon,
} from "../../icons/SimulationIcons";
import { useToggleStore } from "../../../store/useUIToggleStore"; import { useToggleStore } from "../../../store/useUIToggleStore";
import Visualization from "./visualization/Visualization"; import Visualization from "./visualization/Visualization";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; import Simulations from "./simulation/Simulations";
import useVersionHistoryVisibleStore, { import useVersionHistoryVisibleStore, { useDecalStore, useSaveVersion, useSelectedFloorItem, useToolMode, } from "../../../store/builder/store";
useDecalStore, import { useSelectedEventData, useSelectedEventSphere, } from "../../../store/simulation/useSimulationStore";
useSaveVersion,
useSelectedFloorItem,
useToolMode,
} from "../../../store/builder/store";
import {
useSelectedEventData,
useSelectedEventSphere,
} from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import GlobalProperties from "./properties/GlobalProperties"; import GlobalProperties from "./properties/GlobalProperties";
import AssetProperties from "./properties/AssetProperties"; import AssetProperties from "./properties/AssetProperties";
@@ -36,7 +20,7 @@ import FloorProperties from "./properties/FloorProperties";
import SelectedWallProperties from "./properties/SelectedWallProperties"; import SelectedWallProperties from "./properties/SelectedWallProperties";
import SelectedFloorProperties from "./properties/SelectedFloorProperties"; import SelectedFloorProperties from "./properties/SelectedFloorProperties";
import ResourceManagement from "./resourceManagement/ResourceManagement"; import ResourceManagement from "./resourceManagement/ResourceManagement";
import DecalProperties from "./properties/DecalProperties"; import SelectedDecalProperties from "./properties/SelectedDecalProperties";
type DisplayComponent = type DisplayComponent =
| "versionHistory" | "versionHistory"
@@ -57,6 +41,7 @@ type DisplayComponent =
| "none"; | "none";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { selectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { toggleUIRight } = useToggleStore(); const { toggleUIRight } = useToggleStore();
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
@@ -65,13 +50,10 @@ const SideBarRight: React.FC = () => {
const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore(); const { selectedWall, selectedFloor, selectedAisle } = useBuilderStore();
const { selectedEventData } = useSelectedEventData(); const { selectedEventData } = useSelectedEventData();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { viewVersionHistory, setVersionHistoryVisible } = const { viewVersionHistory, setVersionHistoryVisible } = useVersionHistoryVisibleStore();
useVersionHistoryVisibleStore();
const { isVersionSaved } = useSaveVersion(); const { isVersionSaved } = useSaveVersion();
const { selectedSubCategory } = useDecalStore();
const [displayComponent, setDisplayComponent] = const [displayComponent, setDisplayComponent] = useState<DisplayComponent>("none");
useState<DisplayComponent>("none");
useEffect(() => { useEffect(() => {
if (activeModule !== "simulation") setSubModule("properties"); if (activeModule !== "simulation") setSubModule("properties");
@@ -79,11 +61,7 @@ const SideBarRight: React.FC = () => {
}, [activeModule, setSubModule]); }, [activeModule, setSubModule]);
useEffect(() => { useEffect(() => {
if ( if (activeModule !== "mechanics" && selectedEventData && selectedEventSphere) {
activeModule !== "mechanics" &&
selectedEventData &&
selectedEventSphere
) {
setSubModule("mechanics"); setSubModule("mechanics");
} else if (!selectedEventData && !selectedEventSphere) { } else if (!selectedEventData && !selectedEventSphere) {
if (activeModule === "simulation") { if (activeModule === "simulation") {
@@ -132,21 +110,11 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("assetProperties"); setDisplayComponent("assetProperties");
return; return;
} }
if ( if (!selectedFloorItem && !selectedFloor && !selectedAisle && selectedWall) {
!selectedFloorItem &&
!selectedFloor &&
!selectedAisle &&
selectedWall
) {
setDisplayComponent("selectedWallProperties"); setDisplayComponent("selectedWallProperties");
return; return;
} }
if ( if (!selectedFloorItem && !selectedWall && !selectedAisle && selectedFloor) {
!selectedFloorItem &&
!selectedWall &&
!selectedAisle &&
selectedFloor
) {
setDisplayComponent("selectedFloorProperties"); setDisplayComponent("selectedFloorProperties");
return; return;
} }
@@ -154,16 +122,11 @@ const SideBarRight: React.FC = () => {
setDisplayComponent("versionHistory"); setDisplayComponent("versionHistory");
return; return;
} }
if (selectedSubCategory) { if (selectedDecal) {
setDisplayComponent("selectedDecalProperties"); setDisplayComponent("selectedDecalProperties");
return; return;
} }
if ( if (!selectedFloorItem && !selectedFloor && !selectedWall && !selectedDecal) {
!selectedFloorItem &&
!selectedFloor &&
!selectedWall &&
!selectedSubCategory
) {
if (toolMode === "Aisle") { if (toolMode === "Aisle") {
setDisplayComponent("aisleProperties"); setDisplayComponent("aisleProperties");
return; return;
@@ -181,27 +144,13 @@ const SideBarRight: React.FC = () => {
} }
} }
if ( if (subModule === "zoneProperties" && (activeModule === "builder" || activeModule === "simulation")) {
subModule === "zoneProperties" &&
(activeModule === "builder" || activeModule === "simulation")
) {
setDisplayComponent("zoneProperties"); setDisplayComponent("zoneProperties");
return; return;
} }
setDisplayComponent("none"); setDisplayComponent("none");
}, [ }, [viewVersionHistory, activeModule, subModule, isVersionSaved, selectedFloorItem, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal]);
viewVersionHistory,
activeModule,
subModule,
isVersionSaved,
selectedFloorItem,
selectedWall,
selectedFloor,
selectedAisle,
toolMode,
selectedSubCategory,
]);
const renderComponent = () => { const renderComponent = () => {
switch (displayComponent) { switch (displayComponent) {
@@ -232,7 +181,7 @@ const SideBarRight: React.FC = () => {
case "visualization": case "visualization":
return <Visualization />; return <Visualization />;
case "selectedDecalProperties": case "selectedDecalProperties":
return <DecalProperties />; return <SelectedDecalProperties />;
case "resourceManagement": case "resourceManagement":
return <ResourceManagement />; return <ResourceManagement />;
default: default:
@@ -241,13 +190,7 @@ const SideBarRight: React.FC = () => {
}; };
return ( return (
<div <div className={`sidebar-right-wrapper ${toggleUIRight && (!isVersionSaved || activeModule !== "simulation") ? "open" : "closed"}`}>
className={`sidebar-right-wrapper ${
toggleUIRight && (!isVersionSaved || activeModule !== "simulation")
? "open"
: "closed"
}`}
>
<Header /> <Header />
{toggleUIRight && ( {toggleUIRight && (
<> <>
@@ -257,8 +200,7 @@ const SideBarRight: React.FC = () => {
<> <>
<button <button
id="sidebar-action-list-properties" id="sidebar-action-list-properties"
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
subModule === "properties" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setSubModule("properties"); setSubModule("properties");
@@ -275,8 +217,7 @@ const SideBarRight: React.FC = () => {
<> <>
<button <button
id="sidebar-action-list-simulation" id="sidebar-action-list-simulation"
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
subModule === "simulations" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setSubModule("simulations"); setSubModule("simulations");
@@ -288,8 +229,7 @@ const SideBarRight: React.FC = () => {
</button> </button>
<button <button
id="sidebar-action-list-mechanics" id="sidebar-action-list-mechanics"
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
subModule === "mechanics" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setSubModule("mechanics"); setSubModule("mechanics");
@@ -301,8 +241,7 @@ const SideBarRight: React.FC = () => {
</button> </button>
<button <button
id="sidebar-action-list-analysis" id="sidebar-action-list-analysis"
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
subModule === "analysis" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setSubModule("analysis"); setSubModule("analysis");
@@ -319,8 +258,7 @@ const SideBarRight: React.FC = () => {
activeModule === "simulation") && ( activeModule === "simulation") && (
<button <button
id="sidebar-action-list-properties" id="sidebar-action-list-properties"
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "resourceManagement" ? "active" : ""
subModule === "resourceManagement" ? "active" : ""
}`} }`}
onClick={() => { onClick={() => {
setSubModule("resourceManagement"); setSubModule("resourceManagement");

View File

@@ -1,30 +1,37 @@
import React from "react"; import React from "react";
interface RotationInputProps { interface RotationInputProps {
heading?: string; // Optional label for the input
label?: string; // Optional label for the input
onChange: (value: string) => void; // Callback for value change onChange: (value: string) => void; // Callback for value change
placeholder?: string; // Optional placeholder placeholder?: string; // Optional placeholder
type?: string; // Input type (e.g., text, number, email) type?: string; // Input type (e.g., text, number, email)
value?: number; value?: number;
disabled?: boolean; // Disable the input if true
} }
const RotationInput: React.FC<RotationInputProps> = ({ const RotationInput: React.FC<RotationInputProps> = ({
label = "Rotate :", // Default label
heading = "Rotation", // Default heading
onChange, onChange,
placeholder = "Enter value", // Default placeholder placeholder = "Enter value", // Default placeholder
type = "number", // Default type type = "number", // Default type
value = "number", value = "number",
disabled = false,
}) => { }) => {
return ( return (
<div className="custom-input-container"> <div className="custom-input-container">
<div className="header">Rotation</div> <div className="header">{heading}</div>
<div className="inputs-container" style={{ display: "block" }}> <div className="inputs-container" style={{ display: "block" }}>
<div className="input-container"> <div className="input-container">
<div className="custom-input-label">Rotate : </div> <div className="custom-input-label">{label}</div>
<input <input
className="custom-input-field" className="custom-input-field"
type={type} type={type}
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}
placeholder={placeholder} placeholder={placeholder}
value={value} value={value}
disabled={disabled}
/> />
</div> </div>
</div> </div>

View File

@@ -57,6 +57,7 @@ const AssetProperties: React.FC = () => {
<section> <section>
{objectPosition && ( {objectPosition && (
<PositionInput <PositionInput
disabled={true}
onChange={() => { }} onChange={() => { }}
value1={parseFloat(objectPosition.x.toFixed(5))} value1={parseFloat(objectPosition.x.toFixed(5))}
value2={parseFloat(objectPosition.z.toFixed(5))} value2={parseFloat(objectPosition.z.toFixed(5))}
@@ -64,6 +65,7 @@ const AssetProperties: React.FC = () => {
)} )}
{objectRotation && ( {objectRotation && (
<RotationInput <RotationInput
disabled={true}
onChange={() => { }} onChange={() => { }}
value={parseFloat(objectRotation.y.toFixed(5))} value={parseFloat(objectRotation.y.toFixed(5))}
/> />

View File

@@ -1,53 +0,0 @@
import {
LayeringBottomIcon,
LayeringTopIcon,
} from "../../../icons/ExportCommonIcons";
import InputRange from "../../../ui/inputs/InputRange";
import RotationInput from "../customInput/RotationInput";
import Vector3Input from "../customInput/Vector3Input";
const DecalProperties = () => {
return (
<div className="decal-transformation-container">
<div className="header">Decal Propertis</div>
<section>
<RotationInput
onChange={() => {}}
value={10}
/>
<Vector3Input
onChange={(value) => console.log(value)}
header="Scale"
value={[0, 0, 0] as [number, number, number]}
/>
</section>
<section>
<InputRange
label="Opacity"
value={1}
min={0}
step={0.1}
max={1}
onChange={(value: number) => console.log(value)}
key={"6"}
/>
<div className="transformation-wrapper opacity">
<div className="transformation-header">Layering</div>
<div className="layers-list">
<button className="layer-move-btn">
<LayeringBottomIcon />
</button>
<button className="layer-move-btn">
<LayeringTopIcon />
</button>
</div>
</div>
</section>
</div>
);
};
export default DecalProperties;

View File

@@ -0,0 +1,49 @@
import { LayeringBottomIcon, LayeringTopIcon } from "../../../icons/ExportCommonIcons";
import InputRange from "../../../ui/inputs/InputRange";
import RotationInput from "../customInput/RotationInput";
const SelectedDecalProperties = () => {
return (
<div className="decal-transformation-container">
<div className="header">Decal Properties</div>
<section>
<RotationInput
onChange={() => { }}
value={10}
/>
<RotationInput
heading="Scaling"
label="Scale :"
onChange={() => { }}
value={10}
/>
</section>
<section>
<InputRange
label="Opacity"
value={1}
min={0}
step={0.1}
max={1}
onChange={(value: number) => console.log(value)}
/>
<div className="transformation-wrapper opacity">
<div className="transformation-header">Layering</div>
<div className="layers-list">
<button className="layer-move-btn">
<LayeringBottomIcon />
</button>
<button className="layer-move-btn">
<LayeringTopIcon />
</button>
</div>
</div>
</section>
</div>
);
};
export default SelectedDecalProperties;

View File

@@ -1,33 +1,132 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { Decal } from '@react-three/drei' import { Decal } from '@react-three/drei'
import { useLoader } from '@react-three/fiber'; import { useLoader } from '@react-three/fiber';
import { useToggleView } from '../../../store/builder/store'; import { useSocketStore, useToggleView, useToolMode } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import defaultMaterial from '../../../assets/textures/floor/wall-tex.png'; import defaultMaterial from '../../../assets/textures/floor/wall-tex.png';
import useModuleStore from '../../../store/useModuleStore'; import useModuleStore from '../../../store/useModuleStore';
import { useSceneContext } from '../../scene/sceneContext';
import { useEffect } from 'react';
import { getUserData } from '../../../functions/getUserData';
import { useVersionContext } from '../version/versionContext';
import { useParams } from 'react-router-dom';
function DecalInstance({ visible = true, decal, zPosition = decal.decalPosition[2] }: { visible?: boolean, decal: Decal, zPosition?: number }) { // import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
const { setSelectedWall, setSelectedFloor, selectedDecal, setSelectedDecal } = useBuilderStore(); // import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
const { togglView } = useToggleView();
function DecalInstance({ parent, visible = true, decal, zPosition = decal.decalPosition[2] }: { parent: Wall | Floor; visible?: boolean, decal: Decal, zPosition?: number }) {
const { setSelectedWall, setSelectedFloor, selectedDecal, deletableDecal, setSelectedDecal, setDeletableDecal } = useBuilderStore();
const { wallStore, floorStore } = useSceneContext();
const { removeDecal: removeDecalFromWall } = wallStore();
const { removeDecal: removeDecalFromFloor } = floorStore();
const { toolMode } = useToolMode();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { userId, organization } = getUserData();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const { socket } = useSocketStore();
const material = useLoader(THREE.TextureLoader, defaultMaterial); const material = useLoader(THREE.TextureLoader, defaultMaterial);
useEffect(() => {
if (!toggleView && activeModule === 'builder') {
if (toolMode !== 'cursor') {
if (selectedDecal) setSelectedDecal(null);
}
if (toolMode !== '3D-Delete') {
if (deletableDecal) setDeletableDecal(null);
}
} else {
if (selectedDecal) setSelectedDecal(null);
if (deletableDecal) setDeletableDecal(null);
}
}, [toggleView, toolMode, activeModule, selectedDecal, deletableDecal]);
const deleteDecal = (decalUuid: string, parent: Wall | Floor) => {
if ('wallUuid' in parent) {
const updatedWall = removeDecalFromWall(decalUuid);
if (projectId && updatedWall) {
// API
// upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Wall:add', data);
}
} else if ('floorUuid' in parent) {
const updatedFloor = removeDecalFromFloor(decalUuid);
if (projectId && updatedFloor) {
// API
// upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
versionId: selectedVersion?.versionId || '',
userId: userId,
organization: organization
}
socket.emit('v1:model-Floor:add', data);
}
}
}
return ( return (
<Decal <Decal
// debug // debug
visible={visible} visible={visible}
position={[decal.decalPosition[0], decal.decalPosition[1], zPosition]} position={[decal.decalPosition[0], decal.decalPosition[1], zPosition]}
rotation={[0, 0, decal.decalRotation]} rotation={[0, 0, 0]}
scale={[decal.decalScale, decal.decalScale, 0.01]} scale={[decal.decalScale, decal.decalScale, 0.01]}
userData={decal} userData={decal}
onClick={(e) => { onClick={(e) => {
if (visible && !togglView && activeModule === 'builder') { if (visible && !toggleView && activeModule === 'builder') {
if (e.object.userData.decalUuid) { if (e.object.userData.decalUuid) {
e.stopPropagation(); e.stopPropagation();
if (toolMode === 'cursor') {
setSelectedDecal(e.object); setSelectedDecal(e.object);
setSelectedWall(null); setSelectedWall(null);
setSelectedFloor(null); setSelectedFloor(null);
} else if (toolMode === '3D-Delete') {
deleteDecal(e.object.userData.decalUuid, parent);
}
}
}
}}
onPointerEnter={(e) => {
if (visible && !toggleView && activeModule === 'builder') {
if (e.object.userData.decalUuid) {
e.stopPropagation();
if (toolMode === '3D-Delete') {
setDeletableDecal(e.object);
}
}
}
}}
onPointerLeave={(e) => {
if (visible && !toggleView && activeModule === 'builder') {
if (e.object.userData.decalUuid) {
e.stopPropagation();
if (toolMode === '3D-Delete' && deletableDecal && deletableDecal?.userData.decalUuid === e.object.userData.decalUuid) {
setDeletableDecal(null);
}
} }
} }
}} }}

View File

@@ -28,7 +28,7 @@ import material4MetalicMap from "../../../../../assets/textures/floor/tex3/metal
import material4NormalMap from "../../../../../assets/textures/floor/tex3/metal_plate_nor_gl_1k.png"; import material4NormalMap from "../../../../../assets/textures/floor/tex3/metal_plate_nor_gl_1k.png";
function FloorInstance({ floor }: { floor: Floor }) { function FloorInstance({ floor }: { floor: Floor }) {
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { selectedFloor, setSelectedFloor, setSelectedDecal } = useBuilderStore(); const { selectedFloor, setSelectedFloor, setSelectedDecal } = useBuilderStore();
const savedTheme = localStorage.getItem("theme"); const savedTheme = localStorage.getItem("theme");
@@ -159,7 +159,7 @@ function FloorInstance({ floor }: { floor: Floor }) {
position={[0, !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, 0,]} position={[0, !floor.isBeveled ? floor.floorDepth - 0.1 : floor.floorDepth - 0.2, 0,]}
userData={floor} userData={floor}
onDoubleClick={(e) => { onDoubleClick={(e) => {
if (!togglView && activeModule === "builder") { if (!toggleView && activeModule === "builder") {
if (e.object.userData.floorUuid) { if (e.object.userData.floorUuid) {
e.stopPropagation(); e.stopPropagation();
setSelectedFloor(e.object); setSelectedFloor(e.object);

View File

@@ -2,21 +2,36 @@ import React, { useEffect, useMemo } from 'react';
import { Vector3 } from 'three'; import { Vector3 } from 'three';
import { Html } from '@react-three/drei'; import { Html } from '@react-three/drei';
import { useSceneContext } from '../../../scene/sceneContext'; import { useSceneContext } from '../../../scene/sceneContext';
import { useToggleView } from '../../../../store/builder/store'; import { useToggleView, useToolMode } from '../../../../store/builder/store';
import Line from '../../line/line'; import Line from '../../line/line';
import Point from '../../point/point'; import Point from '../../point/point';
import FloorInstance from './Instance/floorInstance'; import FloorInstance from './Instance/floorInstance';
import Floor2DInstance from './Instance/floor2DInstance'; import Floor2DInstance from './Instance/floor2DInstance';
import useModuleStore from '../../../../store/useModuleStore';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
function FloorInstances() { function FloorInstances() {
const { floorStore } = useSceneContext(); const { floorStore } = useSceneContext();
const { floors } = floorStore(); const { floors } = floorStore();
const { setSelectedFloor, selectedFloor } = useBuilderStore();
const { toolMode } = useToolMode();
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
useEffect(() => { useEffect(() => {
// console.log('floors: ', floors); // console.log('floors: ', floors);
}, [floors]) }, [floors])
useEffect(() => {
if (!toggleView && activeModule === 'builder') {
if (toolMode !== 'cursor') {
if (selectedFloor) setSelectedFloor(null);
}
} else {
if (selectedFloor) setSelectedFloor(null);
}
}, [toggleView, toolMode, activeModule, selectedFloor]);
const allPoints = useMemo(() => { const allPoints = useMemo(() => {
const points: Point[] = []; const points: Point[] = [];
const seenUuids = new Set<string>(); const seenUuids = new Set<string>();

View File

@@ -10,7 +10,7 @@ import FloorInstances from './Instances/floorInstances';
import { getFloorsApi } from '../../../services/factoryBuilder/floor/getFloorsApi'; import { getFloorsApi } from '../../../services/factoryBuilder/floor/getFloorsApi';
function FloorGroup() { function FloorGroup() {
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { setSelectedFloor, setSelectedDecal } = useBuilderStore(); const { setSelectedFloor, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
@@ -21,11 +21,11 @@ function FloorGroup() {
const { projectId } = useParams(); const { projectId } = useParams();
useEffect(() => { useEffect(() => {
if (togglView || activeModule !== 'builder') { if (toggleView || activeModule !== 'builder') {
setSelectedFloor(null); setSelectedFloor(null);
setSelectedDecal(null); setSelectedDecal(null);
} }
}, [togglView, activeModule, activeTool]) }, [toggleView, activeModule, activeTool])
useEffect(() => { useEffect(() => {
if (projectId && selectedVersion) { if (projectId && selectedVersion) {

View File

@@ -17,11 +17,11 @@ import material1 from '../../../../../assets/textures/floor/factory wall texture
function Wall({ wall }: { readonly wall: Wall }) { function Wall({ wall }: { readonly wall: Wall }) {
const { wallStore, wallAssetStore } = useSceneContext(); const { wallStore, wallAssetStore } = useSceneContext();
const { walls } = wallStore(); const { walls, addDecal } = wallStore();
const { wallAssets, getWallAssetsByWall, setVisibility } = wallAssetStore(); const { wallAssets, getWallAssetsByWall, setVisibility } = wallAssetStore();
const assets = getWallAssetsByWall(wall.wallUuid); const assets = getWallAssetsByWall(wall.wallUuid);
const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore(); const { selectedWall, setSelectedWall, setSelectedDecal } = useBuilderStore();
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { camera } = useThree(); const { camera } = useThree();
const { wallVisibility } = useWallVisibility(); const { wallVisibility } = useWallVisibility();
@@ -154,11 +154,23 @@ function Wall({ wall }: { readonly wall: Wall }) {
userData={wall} userData={wall}
name={`WallReference_${wall.wallUuid}`} name={`WallReference_${wall.wallUuid}`}
onDoubleClick={(e) => { onDoubleClick={(e) => {
if (visible && !togglView && activeModule === 'builder') { if (visible && !toggleView && activeModule === 'builder') {
if (e.object.userData.wallUuid) { if (e.object.userData.wallUuid) {
e.stopPropagation(); e.stopPropagation();
setSelectedWall(e.object); setSelectedWall(e.object);
setSelectedDecal(null); setSelectedDecal(null);
if (wall.decals.length > 0) return;
const decal: Decal = {
decalUuid: THREE.MathUtils.generateUUID(),
decalName: 'Decal',
decalId: 'Default Decal',
decalPosition: [0, 0, wall.wallThickness / 2 + 0.001],
decalRotation: 0,
decalScale: 1,
decalType: { type: 'Wall', wallUuid: wall.wallUuid }
}
addDecal(wall.wallUuid, decal);
} }
} }
}} }}
@@ -171,7 +183,7 @@ function Wall({ wall }: { readonly wall: Wall }) {
<MeshDiscardMaterial /> <MeshDiscardMaterial />
{wall.decals.map((decal) => ( {wall.decals.map((decal) => (
<DecalInstance zPosition={wall.wallThickness / 2 + 0.001} visible={visible} key={decal.decalUuid} decal={decal} /> <DecalInstance parent={wall} zPosition={wall.wallThickness / 2 + 0.001} visible={visible} key={decal.decalUuid} decal={decal} />
))} ))}
</mesh> </mesh>
</mesh> </mesh>

View File

@@ -2,8 +2,9 @@ import React, { useEffect, useMemo } from 'react';
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three'; import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
import { Html, Extrude } from '@react-three/drei'; import { Html, Extrude } from '@react-three/drei';
import { useLoader } from '@react-three/fiber'; import { useLoader } from '@react-three/fiber';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import { useSceneContext } from '../../../scene/sceneContext'; import { useSceneContext } from '../../../scene/sceneContext';
import { useToggleView } from '../../../../store/builder/store'; import { useToggleView, useToolMode } from '../../../../store/builder/store';
import { useWallClassification } from './instance/helpers/useWallClassification'; import { useWallClassification } from './instance/helpers/useWallClassification';
import Line from '../../line/line'; import Line from '../../line/line';
import Point from '../../point/point'; import Point from '../../point/point';
@@ -12,17 +13,31 @@ import * as Constants from '../../../../types/world/worldConstants';
import texturePath from "../../../../assets/textures/floor/white.png"; import texturePath from "../../../../assets/textures/floor/white.png";
import texturePathDark from "../../../../assets/textures/floor/black.png"; import texturePathDark from "../../../../assets/textures/floor/black.png";
import useModuleStore from '../../../../store/useModuleStore';
function WallInstances() { function WallInstances() {
const { wallStore } = useSceneContext(); const { wallStore } = useSceneContext();
const { setSelectedWall, selectedWall } = useBuilderStore();
const { toolMode } = useToolMode();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { walls } = wallStore(); const { walls } = wallStore();
const { rooms } = useWallClassification(walls); const { rooms } = useWallClassification(walls);
const { toggleView } = useToggleView();
useEffect(() => { useEffect(() => {
// console.log('walls: ', walls); // console.log('walls: ', walls);
}, [walls]) }, [walls])
useEffect(() => {
if (!toggleView && activeModule === 'builder') {
if (toolMode !== 'cursor') {
if (selectedWall) setSelectedWall(null);
}
} else {
if (selectedWall) setSelectedWall(null);
}
}, [toggleView, toolMode, activeModule, selectedWall]);
const allPoints = useMemo(() => { const allPoints = useMemo(() => {
const points: Point[] = []; const points: Point[] = [];
const seenUuids = new Set<string>(); const seenUuids = new Set<string>();

View File

@@ -11,7 +11,7 @@ import WallInstances from './Instances/wallInstances';
import { getWallsApi } from '../../../services/factoryBuilder/wall/getWallsApi'; import { getWallsApi } from '../../../services/factoryBuilder/wall/getWallsApi';
function WallGroup() { function WallGroup() {
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { setSelectedWall, setSelectedDecal } = useBuilderStore(); const { setSelectedWall, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
@@ -22,11 +22,11 @@ function WallGroup() {
const { projectId } = useParams(); const { projectId } = useParams();
useEffect(() => { useEffect(() => {
if (togglView || activeModule !== 'builder') { if (toggleView || activeModule !== 'builder') {
setSelectedWall(null); setSelectedWall(null);
setSelectedDecal(null); setSelectedDecal(null);
} }
}, [togglView, activeModule, activeTool]) }, [toggleView, activeModule, activeTool])
useEffect(() => { useEffect(() => {
if (projectId && selectedVersion) { if (projectId && selectedVersion) {

View File

@@ -14,7 +14,7 @@ import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegm
function WallAssetCreator() { function WallAssetCreator() {
const { socket } = useSocketStore(); const { socket } = useSocketStore();
const { pointer, camera, raycaster, scene, gl } = useThree(); const { pointer, camera, raycaster, scene, gl } = useThree();
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { wallAssetStore } = useSceneContext(); const { wallAssetStore } = useSceneContext();
const { addWallAsset } = wallAssetStore(); const { addWallAsset } = wallAssetStore();
@@ -84,7 +84,7 @@ function WallAssetCreator() {
} }
}; };
if (!togglView && activeModule === 'builder') { if (!toggleView && activeModule === 'builder') {
canvasElement.addEventListener('drop', onDrop); canvasElement.addEventListener('drop', onDrop);
} }
@@ -92,7 +92,7 @@ function WallAssetCreator() {
canvasElement.removeEventListener('drop', onDrop); canvasElement.removeEventListener('drop', onDrop);
}; };
}, [gl, camera, togglView, activeModule, socket, selectedItem, setSelectedItem]); }, [gl, camera, toggleView, activeModule, socket, selectedItem, setSelectedItem]);
return ( return (
<> <>

View File

@@ -1,5 +1,5 @@
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useActiveTool, useToggleView } from '../../../store/builder/store'; import { useToggleView, useToolMode } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore'; import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useVersionContext } from '../version/versionContext'; import { useVersionContext } from '../version/versionContext';
import { useSceneContext } from '../../scene/sceneContext'; import { useSceneContext } from '../../scene/sceneContext';
@@ -10,10 +10,10 @@ import WallAssetInstances from './Instances/wallAssetInstances'
import { getWallAssetsApi } from '../../../services/factoryBuilder/asset/wallAsset/getWallAssetsApi'; import { getWallAssetsApi } from '../../../services/factoryBuilder/asset/wallAsset/getWallAssetsApi';
function WallAssetGroup() { function WallAssetGroup() {
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { setSelectedFloorAsset, setDeletableWallAsset } = useBuilderStore(); const { setSelectedWallAsset, setDeletableWallAsset } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool(); const { toolMode } = useToolMode();
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const { wallAssetStore } = useSceneContext(); const { wallAssetStore } = useSceneContext();
@@ -21,11 +21,11 @@ function WallAssetGroup() {
const { projectId } = useParams(); const { projectId } = useParams();
useEffect(() => { useEffect(() => {
if (togglView || activeModule !== 'builder') { if (toggleView || activeModule !== 'builder' || toolMode !== 'cursor') {
setSelectedFloorAsset(null); setSelectedWallAsset(null);
} }
setDeletableWallAsset(null); setDeletableWallAsset(null);
}, [togglView, activeModule, activeTool]) }, [toggleView, activeModule, toolMode])
useEffect(() => { useEffect(() => {
if (projectId && selectedVersion) { if (projectId && selectedVersion) {

View File

@@ -11,7 +11,7 @@ import ZoneInstances from './Instances/zoneInstances';
import { getZonesApi } from '../../../services/factoryBuilder/zone/getZonesApi'; import { getZonesApi } from '../../../services/factoryBuilder/zone/getZonesApi';
function ZoneGroup() { function ZoneGroup() {
const { togglView } = useToggleView(); const { toggleView } = useToggleView();
const { setSelectedZone } = useBuilderStore(); const { setSelectedZone } = useBuilderStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
@@ -22,10 +22,10 @@ function ZoneGroup() {
const { projectId } = useParams(); const { projectId } = useParams();
useEffect(() => { useEffect(() => {
if (togglView || activeModule !== 'builder') { if (toggleView || activeModule !== 'builder') {
setSelectedZone(null); setSelectedZone(null);
} }
}, [togglView, activeModule, activeTool]) }, [toggleView, activeModule, activeTool])
useEffect(() => { useEffect(() => {
if (projectId && selectedVersion) { if (projectId && selectedVersion) {

View File

@@ -1,25 +1,19 @@
import { DepthOfField, Bloom, EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
import { useThree } from "@react-three/fiber";
import { BlendFunction } from "postprocessing";
import {
useDeletableFloorItem,
useSelectedWallItem,
useSelectedFloorItem,
} from "../../../store/builder/store";
import * as CONSTANTS from "../../../types/world/worldConstants";
import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore";
import { useEffect } from "react"; import { useEffect } from "react";
import { BlendFunction } from "postprocessing";
import { DepthOfField, Bloom, EffectComposer, N8AO, Outline } from "@react-three/postprocessing";
import { useDeletableFloorItem, useSelectedWallItem, useSelectedFloorItem, } from "../../../store/builder/store";
import { useDeletableEventSphere, useSelectedEventSphere, useSelectedPoints } from "../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore";
import * as CONSTANTS from "../../../types/world/worldConstants";
export default function PostProcessing() { export default function PostProcessing() {
const { scene } = useThree();
const { selectedPoints } = useSelectedPoints(); const { selectedPoints } = useSelectedPoints();
const { deletableFloorItem } = useDeletableFloorItem(); const { deletableFloorItem } = useDeletableFloorItem();
const { selectedWallItem } = useSelectedWallItem(); const { selectedWallItem } = useSelectedWallItem();
const { selectedFloorItem } = useSelectedFloorItem(); const { selectedFloorItem } = useSelectedFloorItem();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedEventSphere } = useSelectedEventSphere();
const { deletableEventSphere } = useDeletableEventSphere(); const { deletableEventSphere } = useDeletableEventSphere();
const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset } = useBuilderStore(); const { selectedAisle, selectedWall, selectedDecal, selectedFloor, selectedWallAsset, deletableWallAsset, deletableDecal } = useBuilderStore();
function flattenChildren(children: any[]) { function flattenChildren(children: any[]) {
const allChildren: any[] = []; const allChildren: any[] = [];
@@ -68,6 +62,10 @@ export default function PostProcessing() {
// console.log('selectedPoints: ', selectedPoints); // console.log('selectedPoints: ', selectedPoints);
}, [selectedPoints]) }, [selectedPoints])
useEffect(() => {
// console.log('deletableDecal: ', deletableDecal);
}, [deletableDecal])
return ( return (
<EffectComposer autoClear={false}> <EffectComposer autoClear={false}>
<N8AO <N8AO
@@ -180,6 +178,21 @@ export default function PostProcessing() {
xRay={true} xRay={true}
/> />
)} )}
{deletableDecal && (
<Outline
selection={deletableDecal}
selectionLayer={10}
width={3000}
blendFunction={BlendFunction.ALPHA}
edgeStrength={5}
resolutionScale={2}
pulseSpeed={0}
visibleEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
hiddenEdgeColor={CONSTANTS.outlineConfig.assetDeleteColor}
blur={true}
xRay={true}
/>
)}
{deletableFloorItem && ( {deletableFloorItem && (
<Outline <Outline
selection={flattenChildren(deletableFloorItem.children)} selection={flattenChildren(deletableFloorItem.children)}

View File

@@ -128,6 +128,7 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
// }); // });
// }, // },
// })); // }));
export const useLoadingProgress = create<{ export const useLoadingProgress = create<{
loadingProgress: number; loadingProgress: number;
setLoadingProgress: (x: number) => void; setLoadingProgress: (x: number) => void;

View File

@@ -39,6 +39,7 @@ interface BuilderState {
// Decal Settings // Decal Settings
selectedDecal: Object3D | null; selectedDecal: Object3D | null;
deletableDecal: Object3D | null;
// Aisle General // Aisle General
selectedAisle: Object3D | null; selectedAisle: Object3D | null;
@@ -87,6 +88,7 @@ interface BuilderState {
// Setters - Decal // Setters - Decal
setSelectedDecal: (decal: Object3D | null) => void; setSelectedDecal: (decal: Object3D | null) => void;
setDeletableDecal: (decal: Object3D | null) => void;
// Setters - Aisle General // Setters - Aisle General
setSelectedAisle: (aisle: Object3D | null) => void; setSelectedAisle: (aisle: Object3D | null) => void;
@@ -140,6 +142,7 @@ export const useBuilderStore = create<BuilderState>()(
zoneColor: 'blue', zoneColor: 'blue',
selectedDecal: null, selectedDecal: null,
deletableDecal: null,
selectedAisle: null, selectedAisle: null,
aisleType: 'solid-aisle', aisleType: 'solid-aisle',
@@ -293,6 +296,12 @@ export const useBuilderStore = create<BuilderState>()(
}) })
}, },
setDeletableDecal: (decal: Object3D | null) => {
set((state) => {
state.deletableDecal = decal;
})
},
// === Setters: Aisle General === // === Setters: Aisle General ===
setSelectedAisle: (aisle: Object3D | null) => { setSelectedAisle: (aisle: Object3D | null) => {

View File

@@ -21,7 +21,7 @@ interface FloorStore {
setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void; setMaterial: (uuid: string, sideMaterial: string, topMaterial: string) => void;
addDecal: (floors: string, decal: Decal) => void; addDecal: (floors: string, decal: Decal) => void;
updateDecal: (decalUuid: string, decal: Decal) => void; updateDecal: (decalUuid: string, decal: Decal) => void;
removeDecal: (decalUuid: string) => void; removeDecal: (decalUuid: string) => Floor | undefined;
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
updateDecalRotation: (decalUuid: string, rotation: number) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void;
updateDecalScale: (decalUuid: string, scale: number) => void; updateDecalScale: (decalUuid: string, scale: number) => void;
@@ -213,11 +213,19 @@ export const createFloorStore = () => {
} }
}), }),
removeDecal: (decalUuid) => set(state => { removeDecal: (decalUuid) => {
let affectedFloor: Floor | undefined;
set(state => {
for (const floor of state.floors) { for (const floor of state.floors) {
const hasDecal = floor.decals.some(d => d.decalUuid === decalUuid);
if (hasDecal) {
floor.decals = floor.decals.filter(d => d.decalUuid !== decalUuid); floor.decals = floor.decals.filter(d => d.decalUuid !== decalUuid);
affectedFloor = JSON.parse(JSON.stringify(floor));
} }
}), }
});
return affectedFloor;
},
updateDecalPosition: (decalUuid, position) => set(state => { updateDecalPosition: (decalUuid, position) => set(state => {
for (const floor of state.floors) { for (const floor of state.floors) {

View File

@@ -11,7 +11,7 @@ interface WallStore {
removeWallByPoints: (Points: [Point, Point]) => Wall | undefined; removeWallByPoints: (Points: [Point, Point]) => Wall | undefined;
addDecal: (wallUuid: string, decal: Decal) => void; addDecal: (wallUuid: string, decal: Decal) => void;
updateDecal: (decalUuid: string, decal: Decal) => void; updateDecal: (decalUuid: string, decal: Decal) => void;
removeDecal: (decalUuid: string) => void; removeDecal: (decalUuid: string) => Wall | undefined;
updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void; updateDecalPosition: (decalUuid: string, position: [number, number, number]) => void;
updateDecalRotation: (decalUuid: string, rotation: number) => void; updateDecalRotation: (decalUuid: string, rotation: number) => void;
updateDecalScale: (decalUuid: string, scale: number) => void; updateDecalScale: (decalUuid: string, scale: number) => void;
@@ -99,11 +99,19 @@ export const createWallStore = () => {
} }
}), }),
removeDecal: (decalUuid) => set((state) => { removeDecal: (decalUuid) => {
let affectedWall: Wall | undefined;
set((state) => {
for (const wall of state.walls) { for (const wall of state.walls) {
const hasDecal = wall.decals.some(d => d.decalUuid === decalUuid);
if (hasDecal) {
wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid); wall.decals = wall.decals.filter(d => d.decalUuid !== decalUuid);
affectedWall = JSON.parse(JSON.stringify(wall));
} }
}), }
});
return affectedWall;
},
updateDecalPosition: (decalUuid, position) => set((state) => { updateDecalPosition: (decalUuid, position) => set((state) => {
for (const wall of state.walls) { for (const wall of state.walls) {