add new features and optimizations to simulation and builder modules

This commit is contained in:
Jerald-Golden-B 2025-03-25 16:35:54 +05:30
parent 2303682a15
commit 1259b5fcc8
18 changed files with 601 additions and 178 deletions

View File

@ -1,6 +1,6 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Header from "./Header"; import Header from "./Header";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore, { useSubModuleStore } from "../../../store/useModuleStore";
import { import {
AnalysisIcon, AnalysisIcon,
MechanicsIcon, MechanicsIcon,
@ -14,15 +14,17 @@ import GlobalProperties from "./properties/GlobalProperties";
import AsstePropertiies from "./properties/AssetProperties"; import AsstePropertiies from "./properties/AssetProperties";
import Analysis from "./analysis/Analysis"; import Analysis from "./analysis/Analysis";
import Simulations from "./simulation/Simulations"; import Simulations from "./simulation/Simulations";
import { useSelectedActionSphere } from "../../../store/store";
const SideBarRight: React.FC = () => { const SideBarRight: React.FC = () => {
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const [activeList, setActiveList] = useState("properties"); const { selectedActionSphere } = useSelectedActionSphere();
const { subModule, setSubModule } = useSubModuleStore();
const { toggleUI } = useToggleStore(); const { toggleUI } = useToggleStore();
// Reset activeList whenever activeModule changes // Reset subModule whenever activeModule changes
useEffect(() => { useEffect(() => {
setActiveList("properties"); setSubModule("properties");
}, [activeModule]); }, [activeModule]);
return ( return (
@ -31,38 +33,34 @@ const SideBarRight: React.FC = () => {
{toggleUI && ( {toggleUI && (
<div className="sidebar-actions-container"> <div className="sidebar-actions-container">
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "properties" ? "active" : ""
activeList === "properties" ? "active" : "" }`}
}`} onClick={() => setSubModule("properties")}
onClick={() => setActiveList("properties")}
> >
<PropertiesIcon isActive={activeList === "properties"} /> <PropertiesIcon isActive={subModule === "properties"} />
</div> </div>
{activeModule === "simulation" && ( {activeModule === "simulation" && (
<> <>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "mechanics" ? "active" : ""
activeList === "mechanics" ? "active" : "" }`}
}`} onClick={() => setSubModule("mechanics")}
onClick={() => setActiveList("mechanics")}
> >
<MechanicsIcon isActive={activeList === "mechanics"} /> <MechanicsIcon isActive={subModule === "mechanics"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "simulations" ? "active" : ""
activeList === "simulations" ? "active" : "" }`}
}`} onClick={() => setSubModule("simulations")}
onClick={() => setActiveList("simulations")}
> >
<SimulationIcon isActive={activeList === "simulations"} /> <SimulationIcon isActive={subModule === "simulations"} />
</div> </div>
<div <div
className={`sidebar-action-list ${ className={`sidebar-action-list ${subModule === "analysis" ? "active" : ""
activeList === "analysis" ? "active" : "" }`}
}`} onClick={() => setSubModule("analysis")}
onClick={() => setActiveList("analysis")}
> >
<AnalysisIcon isActive={activeList === "analysis"} /> <AnalysisIcon isActive={subModule === "analysis"} />
</div> </div>
</> </>
)} )}
@ -70,7 +68,7 @@ const SideBarRight: React.FC = () => {
)} )}
{/* process builder */} {/* process builder */}
{toggleUI && {toggleUI &&
activeList === "properties" && subModule === "properties" &&
activeModule !== "visualization" && ( activeModule !== "visualization" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
@ -84,21 +82,28 @@ const SideBarRight: React.FC = () => {
{toggleUI && activeModule === "simulation" && ( {toggleUI && activeModule === "simulation" && (
<> <>
{activeList === "mechanics" && ( {(subModule === "mechanics" && selectedActionSphere) && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<MachineMechanics /> <MachineMechanics />
</div> </div>
</div> </div>
)} )}
{activeList === "analysis" && ( {(subModule === "mechanics" && !selectedActionSphere) && (
<div className="sidebar-right-container">
<div className="sidebar-right-content-container">
{/* <MachineMechanics /> */}
</div>
</div>
)}
{subModule === "analysis" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<Analysis /> <Analysis />
</div> </div>
</div> </div>
)} )}
{activeList === "simulations" && ( {subModule === "simulations" && (
<div className="sidebar-right-container"> <div className="sidebar-right-container">
<div className="sidebar-right-content-container"> <div className="sidebar-right-content-container">
<Simulations /> <Simulations />

View File

@ -11,8 +11,11 @@ import LabledDropdown from "../../../ui/inputs/LabledDropdown";
import RegularDropDown from "../../../ui/inputs/RegularDropDown"; import RegularDropDown from "../../../ui/inputs/RegularDropDown";
import { handleResize } from "../../../../functions/handleResizePannel"; import { handleResize } from "../../../../functions/handleResizePannel";
import EyeDropInput from "../../../ui/inputs/EyeDropInput"; import EyeDropInput from "../../../ui/inputs/EyeDropInput";
import { useSelectedActionSphere } from "../../../../store/store";
const MachineMechanics: React.FC = () => { const MachineMechanics: React.FC = () => {
const { selectedActionSphere, setSelectedActionSphere } = useSelectedActionSphere();
console.log('selectedActionSphere: ', selectedActionSphere);
const [actionList, setActionList] = useState<string[]>([]); const [actionList, setActionList] = useState<string[]>([]);
const [triggerList, setTriggerList] = useState<string[]>([]); const [triggerList, setTriggerList] = useState<string[]>([]);
const [selectedItem, setSelectedItem] = useState<{ const [selectedItem, setSelectedItem] = useState<{
@ -68,8 +71,8 @@ const MachineMechanics: React.FC = () => {
return ( return (
<div className="machine-mechanics-container"> <div className="machine-mechanics-container">
<div className="machine-mechanics-header">Selected Object</div> <div className="machine-mechanics-header">{selectedActionSphere.path.modelName}</div>
<div className="process-list-container"> {/* <div className="process-list-container">
<div className="label">Process:</div> <div className="label">Process:</div>
<RegularDropDown <RegularDropDown
header={activeProcess || "add process ->"} header={activeProcess || "add process ->"}
@ -79,7 +82,7 @@ const MachineMechanics: React.FC = () => {
<div className="add-new-process" onClick={handleAddProcess}> <div className="add-new-process" onClick={handleAddProcess}>
<AddIcon /> <AddIcon />
</div> </div>
</div> </div> */}
<div className="machine-mechanics-content-container"> <div className="machine-mechanics-content-container">
<div className="actions"> <div className="actions">
<div className="header"> <div className="header">
@ -97,12 +100,11 @@ const MachineMechanics: React.FC = () => {
{actionList.map((action, index) => ( {actionList.map((action, index) => (
<div <div
key={index} key={index}
className={`list-item ${ className={`list-item ${selectedItem?.type === "action" &&
selectedItem?.type === "action" &&
selectedItem.name === action selectedItem.name === action
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -144,12 +146,11 @@ const MachineMechanics: React.FC = () => {
{triggerList.map((trigger, index) => ( {triggerList.map((trigger, index) => (
<div <div
key={index} key={index}
className={`list-item ${ className={`list-item ${selectedItem?.type === "trigger" &&
selectedItem?.type === "trigger" &&
selectedItem.name === trigger selectedItem.name === trigger
? "active" ? "active"
: "" : ""
}`} }`}
> >
<div <div
className="value" className="value"
@ -187,7 +188,7 @@ const MachineMechanics: React.FC = () => {
label="Speed" label="Speed"
value="" value=""
activeOption=".mm" activeOption=".mm"
onChange={() => {}} onChange={() => { }}
/> />
<EyeDropInput /> <EyeDropInput />
</> </>

View File

@ -55,9 +55,9 @@ const DisplayZone: React.FC<DisplayZoneProps> = ({
const [selectedOption, setSelectedOption] = React.useState<string | null>( const [selectedOption, setSelectedOption] = React.useState<string | null>(
null null
); );
console.log('setSelectedOption: ', setSelectedOption); // console.log('setSelectedOption: ', setSelectedOption);
const [options, setOptions] = React.useState<string[]>([]); const [options, setOptions] = React.useState<string[]>([]);
console.log('setOptions: ', setOptions); // console.log('setOptions: ', setOptions);
// Scroll to the selected option when it changes // Scroll to the selected option when it changes
useEffect(() => { useEffect(() => {

View File

@ -83,7 +83,7 @@ const ZoneGroup: React.FC = () => {
useEffect(() => { useEffect(() => {
localStorage.setItem('zones', zones); localStorage.setItem('zones', JSON.stringify(zones));
}, [zones]) }, [zones])

View File

@ -1,7 +1,7 @@
import * as THREE from 'three' import * as THREE from 'three'
import { EffectComposer, N8AO, Outline } from '@react-three/postprocessing' import { EffectComposer, N8AO, Outline } from '@react-three/postprocessing'
import { BlendFunction } from 'postprocessing' import { BlendFunction } from 'postprocessing'
import { useDeletableFloorItem, useSelectedEventSphere, useSelectedPath, useSelectedWallItem, useselectedFloorItem } from '../../../store/store'; import { useDeletableFloorItem, useSelectedActionSphere, useSelectedPath, useSelectedWallItem, useselectedFloorItem } from '../../../store/store';
import * as Types from '../../../types/world/worldTypes' import * as Types from '../../../types/world/worldTypes'
import * as CONSTANTS from '../../../types/world/worldConstants'; import * as CONSTANTS from '../../../types/world/worldConstants';
@ -9,7 +9,7 @@ export default function PostProcessing() {
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem(); const { selectedWallItem, setSelectedWallItem } = useSelectedWallItem();
const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem();
const { selectedEventSphere } = useSelectedEventSphere(); const { selectedActionSphere } = useSelectedActionSphere();
const { selectedPath } = useSelectedPath(); const { selectedPath } = useSelectedPath();
function flattenChildren(children: any[]) { function flattenChildren(children: any[]) {
@ -75,9 +75,9 @@ export default function PostProcessing() {
xRay={true} xRay={true}
/> />
} }
{selectedEventSphere && {selectedActionSphere &&
<Outline <Outline
selection={[selectedEventSphere.point]} selection={[selectedActionSphere.point]}
selectionLayer={10} selectionLayer={10}
width={750} width={750}
blendFunction={BlendFunction.ALPHA} blendFunction={BlendFunction.ALPHA}

View File

@ -6,11 +6,12 @@ import { useEffect } from 'react';
interface Path { interface Path {
modeluuid: string; modeluuid: string;
modelName: string;
points: { points: {
uuid: string; uuid: string;
position: [number, number, number]; position: [number, number, number];
rotation: [number, number, number]; rotation: [number, number, number];
events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
triggers: { uuid: string; type: string; isUsed: boolean }[] | []; triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
}[]; }[];
pathPosition: [number, number, number]; pathPosition: [number, number, number];
@ -36,26 +37,27 @@ function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) {
const newPath: Path = { const newPath: Path = {
modeluuid: item.modeluuid, modeluuid: item.modeluuid,
modelName: item.modelname,
points: [ points: [
{ {
uuid: point1UUID, uuid: point1UUID,
position: [point1Position.x, point1Position.y, point1Position.z], position: [point1Position.x, point1Position.y, point1Position.z],
rotation: [0, 0, 0], rotation: [0, 0, 0],
events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
triggers: [], triggers: [],
}, },
{ {
uuid: middlePointUUID, uuid: middlePointUUID,
position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z], position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z],
rotation: [0, 0, 0], rotation: [0, 0, 0],
events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
triggers: [], triggers: [],
}, },
{ {
uuid: point2UUID, uuid: point2UUID,
position: [point2Position.x, point2Position.y, point2Position.z], position: [point2Position.x, point2Position.y, point2Position.z],
rotation: [0, 0, 0], rotation: [0, 0, 0],
events: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }],
triggers: [], triggers: [],
}, },
], ],

View File

@ -1,55 +0,0 @@
import { useControls } from 'leva';
import { useSelectedEventSphere } from '../../../store/store';
interface Path {
modeluuid: string;
points: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
events: string;
triggers: string;
}[];
position: [number, number, number];
rotation: [number, number, number];
}
const EventsControl = ({ simulationPaths, setSimulationPaths }: { simulationPaths: Path[], setSimulationPaths: any }) => {
const { selectedEventSphere, setSelectedEventSphere } = useSelectedEventSphere();
const { events, triggers }: any = useControls({
events: {
value: selectedEventSphere?.point?.userData?.events || '',
options: ['Event1', 'Event2', 'Event3'],
onChange: (newEvent: string) => updatePathData(newEvent, 'events')
},
triggers: {
value: selectedEventSphere?.point?.userData?.triggers || '',
options: ['None', 'Trigger1', 'Trigger2', 'Trigger3'],
onChange: (newTrigger: string) => updatePathData(newTrigger, 'triggers')
},
});
function updatePathData(value: string, key: 'events' | 'triggers') {
if (!selectedEventSphere) return;
const updatedPaths = simulationPaths.map((path) =>
path.modeluuid === selectedEventSphere.path.modeluuid
? {
...path,
points: path.points.map((point) =>
point.uuid === selectedEventSphere.point.uuid
? { ...point, [key]: value }
: point
),
}
: path
);
console.log('updatedPaths: ', updatedPaths);
setSimulationPaths(updatedPaths);
}
return null;
};
export default EventsControl;

View File

@ -1,16 +1,18 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useRef, useState, useEffect } from 'react'; import { useRef, useState, useEffect } from 'react';
import { Sphere, TransformControls } from '@react-three/drei'; import { Sphere, TransformControls } from '@react-three/drei';
import { useIsConnecting, useRenderDistance, useSelectedEventSphere, useSelectedPath, useSimulationPaths } from '../../../store/store'; import { useIsConnecting, useRenderDistance, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../../store/store';
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from '@react-three/fiber';
import { useSubModuleStore } from '../../../store/useModuleStore';
interface Path { interface Path {
modeluuid: string; modeluuid: string;
modelName: string;
points: { points: {
uuid: string; uuid: string;
position: [number, number, number]; position: [number, number, number];
rotation: [number, number, number]; rotation: [number, number, number];
events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
triggers: { uuid: string; type: string; isUsed: boolean }[] | []; triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
}[]; }[];
pathPosition: [number, number, number]; pathPosition: [number, number, number];
@ -20,7 +22,8 @@ interface Path {
function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) { function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject<THREE.Group> }) {
const { renderDistance } = useRenderDistance(); const { renderDistance } = useRenderDistance();
const { setSelectedEventSphere, selectedEventSphere } = useSelectedEventSphere(); const { setSubModule } = useSubModuleStore();
const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere();
const { setSelectedPath } = useSelectedPath(); const { setSelectedPath } = useSelectedPath();
const { simulationPaths, setSimulationPaths } = useSimulationPaths(); const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const { isConnecting, setIsConnecting } = useIsConnecting(); const { isConnecting, setIsConnecting } = useIsConnecting();
@ -34,7 +37,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
useEffect(() => { useEffect(() => {
setTransformMode(null); setTransformMode(null);
const handleKeyDown = (e: KeyboardEvent) => { const handleKeyDown = (e: KeyboardEvent) => {
if (!selectedEventSphere) return; if (!selectedActionSphere) return;
if (e.key === 'g') { if (e.key === 'g') {
setTransformMode(prev => prev === 'translate' ? null : 'translate'); setTransformMode(prev => prev === 'translate' ? null : 'translate');
} }
@ -45,7 +48,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
window.addEventListener('keydown', handleKeyDown); window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown);
}, [selectedEventSphere]); }, [selectedActionSphere]);
useFrame(() => { useFrame(() => {
Object.values(groupRefs.current).forEach(group => { Object.values(groupRefs.current).forEach(group => {
@ -57,23 +60,23 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
}); });
const updateSimulationPaths = () => { const updateSimulationPaths = () => {
if (!selectedEventSphere) return; if (!selectedActionSphere) return;
const updatedPaths: Path[] = simulationPaths.map((path) => ({ const updatedPaths: Path[] = simulationPaths.map((path) => ({
...path, ...path,
points: path.points.map((point) => points: path.points.map((point) =>
point.uuid === selectedEventSphere.point.uuid point.uuid === selectedActionSphere.point.uuid
? { ? {
...point, ...point,
position: [ position: [
selectedEventSphere.point.position.x, selectedActionSphere.point.position.x,
selectedEventSphere.point.position.y, selectedActionSphere.point.position.y,
selectedEventSphere.point.position.z, selectedActionSphere.point.position.z,
], ],
rotation: [ rotation: [
selectedEventSphere.point.rotation.x, selectedActionSphere.point.rotation.x,
selectedEventSphere.point.rotation.y, selectedActionSphere.point.rotation.y,
selectedEventSphere.point.rotation.z, selectedActionSphere.point.rotation.z,
] ]
} }
: point : point
@ -100,11 +103,12 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
if (isConnecting) return; if (isConnecting) return;
e.stopPropagation(); e.stopPropagation();
setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); setSelectedPath({ path, group: groupRefs.current[path.modeluuid] });
setSelectedEventSphere(null); setSelectedActionSphere(null);
setTransformMode(null); setTransformMode(null);
}} }}
onPointerMissed={() => { onPointerMissed={() => {
setSelectedPath(null); setSelectedPath(null);
setSubModule('properties');
}} }}
> >
{path.points.map((point, index) => ( {path.points.map((point, index) => (
@ -118,14 +122,18 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
onClick={(e) => { onClick={(e) => {
if (isConnecting) return; if (isConnecting) return;
e.stopPropagation(); e.stopPropagation();
setSelectedEventSphere({ setSelectedActionSphere({
path, path,
point: sphereRefs.current[point.uuid] point: sphereRefs.current[point.uuid]
}); });
setSubModule('mechanics');
setSelectedPath(null); setSelectedPath(null);
}} }}
userData={{ point, path }} userData={{ point, path }}
onPointerMissed={() => setSelectedEventSphere(null)} onPointerMissed={() => {
setSubModule('properties');
setSelectedActionSphere(null)
}}
> >
<meshStandardMaterial <meshStandardMaterial
color={index === 0 ? 'orange' : index === path.points.length - 1 ? 'blue' : 'green'} color={index === 0 ? 'orange' : index === path.points.length - 1 ? 'blue' : 'green'}
@ -148,10 +156,10 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject
); );
})} })}
{selectedEventSphere && transformMode && ( {selectedActionSphere && transformMode && (
<TransformControls <TransformControls
ref={transformRef} ref={transformRef}
object={selectedEventSphere.point} object={selectedActionSphere.point}
mode={transformMode} mode={transformMode}
onObjectChange={updateSimulationPaths} onObjectChange={updateSimulationPaths}
/> />

View File

@ -1,5 +1,5 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { useConnections, useFloorItems, useSelectedEventSphere, useSelectedPath, useSimulationPaths } from '../../store/store'; import { useConnections, useFloorItems, useSelectedActionSphere, useSelectedPath, useSimulationPaths } from '../../store/store';
import { useThree } from '@react-three/fiber'; import { useThree } from '@react-three/fiber';
import * as THREE from 'three'; import * as THREE from 'three';
import Behaviour from './behaviour/behaviour'; import Behaviour from './behaviour/behaviour';
@ -19,10 +19,10 @@ function Simulation() {
}, [simulationPaths]); }, [simulationPaths]);
// useEffect(() => { // useEffect(() => {
// if (selectedEventSphere) { // if (selectedActionSphere) {
// console.log('selectedEventSphere: ', selectedEventSphere); // console.log('selectedActionSphere: ', selectedActionSphere);
// } // }
// }, [selectedEventSphere]); // }, [selectedActionSphere]);
// useEffect(() => { // useEffect(() => {
// if (selectedPath) { // if (selectedPath) {

View File

@ -0,0 +1,381 @@
import { useMemo, useState } from 'react';
import { useSelectedActionSphere, useToggleView, useSimulationPaths, useSelectedPath, useStartSimulation } from '../../store/store';
import * as THREE from 'three';
import useModuleStore from '../../store/useModuleStore';
function SimulationUI() {
const { ToggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { startSimulation, setStartSimulation } = useStartSimulation();
const { selectedActionSphere } = useSelectedActionSphere();
const { selectedPath, setSelectedPath } = useSelectedPath();
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
const handleAddAction = () => {
if (!selectedActionSphere) return;
const newAction = { uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false };
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, actions: [...point.actions, newAction] }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleDeleteAction = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, actions: point.actions.filter(action => action.uuid !== uuid) }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleActionSelect = (uuid: string, actionType: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, type: actionType } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleMaterialSelect = (uuid: string, material: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, material } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleDelayChange = (uuid: string, delay: number | string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, delay } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleSpawnIntervalChange = (uuid: string, spawnInterval: number | string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) =>
action.uuid === uuid ? { ...action, spawnInterval } : action
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleSpeedChange = (speed: number) => {
if (!selectedPath) return;
const updatedPaths = simulationPaths.map((path) =>
path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
);
setSimulationPaths(updatedPaths);
setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
};
const handleAddTrigger = () => {
if (!selectedActionSphere) return;
const newTrigger = { uuid: THREE.MathUtils.generateUUID(), type: '', isUsed: false };
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, triggers: [...point.triggers, newTrigger] }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleDeleteTrigger = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? { ...point, triggers: point.triggers.filter(trigger => trigger.uuid !== uuid) }
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleTriggerSelect = (uuid: string, triggerType: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) =>
trigger.uuid === uuid ? { ...trigger, type: triggerType } : trigger
),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleResetPath = () => {
if (!selectedPath) return;
};
const handleActionToggle = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
actions: point.actions.map((action) => ({
...action,
isUsed: action.uuid === uuid ? !action.isUsed : false,
})),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const handleTriggerToggle = (uuid: string) => {
if (!selectedActionSphere) return;
const updatedPaths = simulationPaths.map((path) => ({
...path,
points: path.points.map((point) =>
point.uuid === selectedActionSphere.point.uuid
? {
...point,
triggers: point.triggers.map((trigger) => ({
...trigger,
isUsed: trigger.uuid === uuid ? !trigger.isUsed : false,
})),
}
: point
),
}));
setSimulationPaths(updatedPaths);
};
const selectedPoint = useMemo(() => {
if (!selectedActionSphere) return null;
return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid);
}, [selectedActionSphere, simulationPaths]);
return (
<>
{activeModule === "simulation" && (
<div style={{ zIndex: 10, position: "relative", width: '260px' }}>
{!ToggleView && (
<>
<button
onClick={() => setStartSimulation(!startSimulation)}
style={{
marginTop: "10px",
background: startSimulation ? '#ff320e' : '',
padding: "10px",
borderRadius: "5px"
}}
>
{startSimulation ? 'Stop Simulation' : 'Start Simulation'}
</button>
{selectedPath && (
<div style={{ marginTop: "10px" }}>
<label>Path Speed:</label>
<input
style={{ width: '50px' }}
type="number"
value={selectedPath.path.speed}
min="0.1"
step="0.1"
onChange={(e) => handleSpeedChange(parseFloat(e.target.value))}
/>
</div>
)}
{selectedActionSphere && (
<div style={{ marginTop: "10px" }}>
<button onClick={handleAddAction}>Add Action</button>
<button onClick={handleAddTrigger}>Add Trigger</button>
{selectedPoint?.actions.map((action) => (
<div key={action.uuid} style={{ marginTop: "10px" }}>
<select value={action.type} onChange={(e) => handleActionSelect(action.uuid, e.target.value)}>
<option value="Inherit">Inherit</option>
<option value="Spawn">Spawn Point</option>
<option value="Swap">Swap Material</option>
<option value="Despawn">Despawn Point</option>
<option value="Delay">Delay</option>
</select>
<button onClick={() => handleDeleteAction(action.uuid)}>Delete Action</button>
<label>
<input
type="checkbox"
checked={action.isUsed}
onChange={() => handleActionToggle(action.uuid)}
/>
</label>
{(action.type === 'Spawn' || action.type === 'Swap') && (
<div style={{ marginTop: "10px" }}>
<select value={action.material} onChange={(e) => handleMaterialSelect(action.uuid, e.target.value)}>
<option value="Inherit">Inherit</option>
<option value="Crate">Crate</option>
<option value="Box">Box</option>
</select>
</div>
)}
{action.type === 'Delay' && (
<div style={{ marginTop: "10px" }}>
<label>Delay Time:</label>
<input
style={{ width: '50px' }}
type="text"
value={isNaN(Number(action.delay)) || action.delay === "Inherit" ? "Inherit" : action.delay}
min="1"
onChange={(e) => handleDelayChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
/>
</div>
)}
{action.type === 'Spawn' && (
<div style={{ marginTop: "10px" }}>
<label>Spawn Interval:</label>
<input
style={{ width: '50px' }}
type="text"
value={isNaN(Number(action.spawnInterval)) || action.spawnInterval === "Inherit" ? "Inherit" : action.spawnInterval}
min="1"
onChange={(e) => handleSpawnIntervalChange(action.uuid, parseInt(e.target.value) || 'Inherit')}
/>
</div>
)}
<hr style={{ margin: "10px 0", borderColor: "#ccc" }} />
</div>
))}
<hr style={{ margin: "10px 0", border: "1px solid black" }} />
{selectedPoint?.triggers.map((trigger) => (
<div key={trigger.uuid} style={{ marginTop: "10px" }}>
<select value={trigger.type} onChange={(e) => handleTriggerSelect(trigger.uuid, e.target.value)}>
<option value="">Select Trigger Type</option>
<option value="On-Hit">On Hit</option>
<option value="Buffer">Buffer</option>
</select>
<button onClick={() => handleDeleteTrigger(trigger.uuid)}>Delete Trigger</button>
<label>
<input
type="checkbox"
checked={trigger.isUsed}
onChange={() => handleTriggerToggle(trigger.uuid)}
/>
</label>
<hr style={{ margin: "10px 0", borderColor: "#ccc" }} />
</div>
))}
</div>
)}
{selectedPath && (
<div style={{ marginTop: "10px" }}>
<button
onClick={handleResetPath}
style={{ padding: "10px", borderRadius: "5px", background: "#ff0000", color: "#fff" }}
>
Reset Path
</button>
</div>
)}
</>
)}
</div>
)}
</>
);
}
export default SimulationUI;

View File

@ -8,6 +8,7 @@ import Tools from "../components/ui/Tools";
import Scene from "../modules/scene/scene"; import Scene from "../modules/scene/scene";
import { useSocketStore, useFloorItems, useOrganization, useUserName, useWallItems, useZones } from "../store/store"; import { useSocketStore, useFloorItems, useOrganization, useUserName, useWallItems, useZones } from "../store/store";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import SimulationUI from "../modules/simulation/simulationUI";
const Project: React.FC = () => { const Project: React.FC = () => {
let navigate = useNavigate(); let navigate = useNavigate();
@ -45,6 +46,7 @@ const Project: React.FC = () => {
{activeModule === "visualization" && <RealTimeVisulization />} {activeModule === "visualization" && <RealTimeVisulization />}
<Tools /> <Tools />
<Scene /> <Scene />
<SimulationUI />
</div> </div>
); );
}; };

View File

@ -2,6 +2,9 @@ import React, { useState, FormEvent } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { LogoIconLarge } from "../components/icons/Logo"; import { LogoIconLarge } from "../components/icons/Logo";
import { EyeIcon } from "../components/icons/ExportCommonIcons"; import { EyeIcon } from "../components/icons/ExportCommonIcons";
import { useOrganization, useUserName } from "../store/store";
import { signInApi } from "../services/factoryBuilder/signInSignUp/signInApi";
import { signUpApi } from "../services/factoryBuilder/signInSignUp/signUpApi";
// import LoadingPage from "../components/templates/LoadingPage"; // import LoadingPage from "../components/templates/LoadingPage";
const UserAuth: React.FC = () => { const UserAuth: React.FC = () => {
@ -9,34 +12,50 @@ const UserAuth: React.FC = () => {
const [password, setPassword] = useState(""); const [password, setPassword] = useState("");
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
const [isSignIn, setIsSignIn] = useState(true); // Toggle between login and register const [isSignIn, setIsSignIn] = useState(true);
const [userName, setUserName] = useState(""); // Username for registration const { userName, setUserName } = useUserName();
const { organization, setOrganization } = useOrganization();
const navigate = useNavigate(); const navigate = useNavigate();
const handleLogin = (e: FormEvent) => { const handleLogin = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
// Dummy validation for "account not found"
if (email !== "user@example.com") { const organization = (email.split("@")[1]).split(".")[0];
setError("Account not found"); try {
} else { const res = await signInApi(email, password, organization);
setError("");
console.log("Login Successful!"); if (res.message === "login successfull") {
console.log("Email:", email); setError("");
console.log("Password:", password); setOrganization(organization);
} setUserName(res.name);
localStorage.setItem("userId", res.userId);
localStorage.setItem("email", res.email);
localStorage.setItem("userName", res.name);
if (res.isShare) {
navigate("/Project");
}
} else if (res.message === "User Not Found!!! Kindly signup...") {
setError("Account not found");
}
} catch (error) { }
}; };
const handleRegister = (e: FormEvent) => { const handleRegister = async (e: FormEvent) => {
e.preventDefault(); e.preventDefault();
// Dummy validation for registration
if (email && password && userName) { if (email && password && userName) {
setError(""); setError("");
console.log("Registration Successful!"); try {
console.log("Username:", userName); const organization = (email.split("@")[1]).split(".")[0];
console.log("Email:", email); const res = await signUpApi(userName, email, password, organization);
console.log("Password:", password);
setIsSignIn(true); if (res.message === "New User created") {
setIsSignIn(true);
}
if (res.message === "User already exists") {
setError("User already exists");
}
} catch (error) { }
} else { } else {
setError("Please fill all the fields!"); setError("Please fill all the fields!");
} }
@ -97,6 +116,7 @@ const UserAuth: React.FC = () => {
)} )}
<input <input
type="email" type="email"
name="email"
value={email} value={email}
placeholder="Email" placeholder="Email"
onChange={(e) => setEmail(e.target.value)} onChange={(e) => setEmail(e.target.value)}
@ -104,6 +124,7 @@ const UserAuth: React.FC = () => {
/> />
<div className="password-container"> <div className="password-container">
<input <input
name="password"
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
value={password} value={password}
placeholder="Password" placeholder="Password"

View File

@ -1,6 +1,6 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const signIn = async (email: string, password: Object, organization: Object) => { export const signInApi = async (email: string, password: Object, organization: Object) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, { const response = await fetch(`${url_Backend_dwinzo}/api/v1/login`, {
method: "POST", method: "POST",

View File

@ -1,6 +1,6 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const signUp = async (userName: string, email: string, password: Object, organization: Object) => { export const signUpApi = async (userName: string, email: string, password: Object, organization: Object) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, { const response = await fetch(`${url_Backend_dwinzo}/api/v1/signup`, {
method: "POST", method: "POST",
@ -11,7 +11,7 @@ export const signUp = async (userName: string, email: string, password: Object,
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to signUp"); throw new Error("Failed to signUpApi");
} }
const result = await response.json(); const result = await response.json();

View File

@ -283,9 +283,9 @@ export const useDrawMaterialPath = create<any>((set: any) => ({
setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }), setDrawMaterialPath: (x: any) => set({ drawMaterialPath: x }),
})); }));
export const useSelectedEventSphere = create<any>((set: any) => ({ export const useSelectedActionSphere = create<any>((set: any) => ({
selectedEventSphere: undefined, selectedActionSphere: undefined,
setSelectedEventSphere: (x: any) => set({ selectedEventSphere: x }), setSelectedActionSphere: (x: any) => set({ selectedActionSphere: x }),
})); }));
export const useSelectedPath = create<any>((set: any) => ({ export const useSelectedPath = create<any>((set: any) => ({
@ -293,11 +293,77 @@ export const useSelectedPath = create<any>((set: any) => ({
setSelectedPath: (x: any) => set({ selectedPath: x }), setSelectedPath: (x: any) => set({ selectedPath: x }),
})); }));
export const useSimulationPaths = create<Types.SimulationPathsStore>((set) => ({ interface Path {
modeluuid: string;
modelName: string;
points: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
actions: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
}[];
pathPosition: [number, number, number];
pathRotation: [number, number, number];
speed: number;
}
interface SimulationPathsStore {
simulationPaths: Path[];
setSimulationPaths: (paths: Path[]) => void;
}
export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
simulationPaths: [], simulationPaths: [],
setSimulationPaths: (paths) => set({ simulationPaths: paths }), setSimulationPaths: (paths) => set({ simulationPaths: paths }),
})); }));
// interface Point {
// uuid: string;
// position: [number, number, number];
// rotation: [number, number, number];
// event: {
// uuid: string;
// type: string;
// material: string;
// delay: number | string;
// spawnInterval: number | string;
// isUsed: boolean;
// };
// trigger: {
// uuid: string;
// type: string;
// isUsed: boolean;
// };
// }
// interface Process {
// processId: string;
// processName: string;
// points: Point[];
// pathPosition: [number, number, number];
// pathRotation: [number, number, number];
// speed: number;
// isUsed: boolean;
// }
// interface Path {
// modeluuid: string;
// processes: Process[];
// }
// interface SimulationPathsStore {
// simulationPaths: Path[];
// setSimulationPaths: (paths: Path[]) => void;
// }
// export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
// simulationPaths: [],
// setSimulationPaths: (paths) => set({ simulationPaths: paths }),
// }));
export const useConnections = create<Types.ConnectionStore>((set) => ({ export const useConnections = create<Types.ConnectionStore>((set) => ({
connections: [], connections: [],

View File

@ -1,4 +1,3 @@
// store/useModuleStore.ts
import { create } from "zustand"; import { create } from "zustand";
interface ModuleStore { interface ModuleStore {
@ -12,3 +11,16 @@ const useModuleStore = create<ModuleStore>((set) => ({
})); }));
export default useModuleStore; export default useModuleStore;
// New store for subModule
interface SubModuleStore {
subModule: string;
setSubModule: (subModule: string) => void;
}
const useSubModuleStore = create<SubModuleStore>((set) => ({
subModule: "properties", // Initial subModule state
setSubModule: (subModule) => set({ subModule }), // Update subModule state
}));
export { useSubModuleStore };

View File

@ -270,7 +270,7 @@ export const planeConfig: PlaneConfig = {
width: 300, // Width of the plane width: 300, // Width of the plane
height: 300, // Height of the plane height: 300, // Height of the plane
color: "white" // Color of the plane color: "#f3f3f3" // Color of the plane
} }
export const shadowConfig: ShadowConfig = { export const shadowConfig: ShadowConfig = {

View File

@ -270,26 +270,6 @@ export type setSelectedItemsIndexSetState = (index: number | null) => void;
export type RefCSM = React.MutableRefObject<CSM>; export type RefCSM = React.MutableRefObject<CSM>;
export type RefCSMHelper = React.MutableRefObject<CSMHelper>; export type RefCSMHelper = React.MutableRefObject<CSMHelper>;
interface Path {
modeluuid: string;
points: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
events: { uuid: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | [];
triggers: { uuid: string; type: string; isUsed: boolean }[] | [];
}[];
pathPosition: [number, number, number];
pathRotation: [number, number, number];
speed: number;
}
interface SimulationPathsStore {
simulationPaths: Path[];
setSimulationPaths: (paths: Path[]) => void;
}
interface PathConnection { interface PathConnection {
fromPathUUID: string; fromPathUUID: string;
fromUUID: string; fromUUID: string;