diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index b361395..0ed4f23 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -37,37 +37,33 @@ const SideBarRight: React.FC = () => { {toggleUI && (
{/* {activeModule === "builder" && ( */} -
setSubModule("properties")} - > - -
+ onClick={() => setSubModule("properties")} + > + +
{/* )} */} {activeModule === "simulation" && ( <>
setSubModule("mechanics")} >
setSubModule("simulations")} >
setSubModule("analysis")} > @@ -103,7 +99,7 @@ const SideBarRight: React.FC = () => { {subModule === "mechanics" && !selectedActionSphere && (
- + {/* */}
)} diff --git a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx index 05b7041..90d3ecf 100644 --- a/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx +++ b/app/src/components/layout/sidebarRight/customInput/Vector3Input.tsx @@ -17,10 +17,10 @@ const Vector3Input: React.FC = ({ return (
- {header}{" "} -
+ {header} + {/*
-
+
*/}
diff --git a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx index 9a7e81b..6093e2c 100644 --- a/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx +++ b/app/src/components/layout/sidebarRight/mechanics/MachineMechanics.tsx @@ -1,4 +1,4 @@ -import React, { useRef, useState } from "react"; +import React, { useRef, useState, useMemo } from "react"; import { AddIcon, InfoIcon, @@ -11,80 +11,331 @@ import LabledDropdown from "../../../ui/inputs/LabledDropdown"; import RegularDropDown from "../../../ui/inputs/RegularDropDown"; import { handleResize } from "../../../../functions/handleResizePannel"; import EyeDropInput from "../../../ui/inputs/EyeDropInput"; -import { useSelectedActionSphere } from "../../../../store/store"; +import { useSelectedActionSphere, useSelectedPath, useSimulationPaths } from "../../../../store/store"; +import * as THREE from 'three'; +import InputToggle from "../../../ui/inputs/InputToggle"; const MachineMechanics: React.FC = () => { const { selectedActionSphere } = useSelectedActionSphere(); - console.log("selectedActionSphere: ", selectedActionSphere); - const [actionList, setActionList] = useState([]); - const [triggerList, setTriggerList] = useState([]); - const [selectedItem, setSelectedItem] = useState<{ - type: "action" | "trigger"; - name: string; - } | null>(null); + const { selectedPath, setSelectedPath } = useSelectedPath(); + const { simulationPaths, setSimulationPaths } = useSimulationPaths(); const actionsContainerRef = useRef(null); const triggersContainerRef = useRef(null); + const selectedPoint = useMemo(() => { + if (!selectedActionSphere) return null; + return simulationPaths.flatMap((path) => path.points).find((point) => point.uuid === selectedActionSphere.point.uuid); + }, [selectedActionSphere, simulationPaths]); + const handleAddAction = () => { - setActionList([...actionList, `Action ${actionList.length + 1}`]); + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return 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, + // Reset dependent fields when type changes + material: actionType === 'Spawn' || actionType === 'Swap' ? 'Inherit' : action.material, + delay: actionType === 'Delay' ? 'Inherit' : action.delay, + spawnInterval: actionType === 'Spawn' ? 'Inherit' : action.spawnInterval + } + : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + + // Update the selected item to reflect changes + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + const updatedAction = updatedPaths + .flatMap(path => path.points) + .find(p => p.uuid === selectedActionSphere.point.uuid) + ?.actions.find(a => a.uuid === uuid); + + if (updatedAction) { + setSelectedItem({ + type: "action", + item: updatedAction + }); + } + } + }; + + // Modified handleMaterialSelect to ensure it only applies to relevant action types + 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.type === 'Spawn' || action.type === 'Swap') + ? { ...action, material } + : action + ), + } + : point + ), + })); + + setSimulationPaths(updatedPaths); + + // Update selected item if it's the current action + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + material + } + }); + } + }; + + 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 = () => { - setTriggerList([...triggerList, `Trigger ${triggerList.length + 1}`]); + if (!selectedActionSphere) return; + + const updatedPaths = simulationPaths.map((path) => ({ + ...path, + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), + })); + + setSimulationPaths(updatedPaths); }; - const handleRemoveAction = (index: number) => { - setActionList(actionList.filter((_, i) => i !== index)); - if ( - selectedItem?.type === "action" && - selectedItem.name === actionList[index] - ) { - setSelectedItem(null); + 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); + }; + + // Update the toggle handlers to immediately update the selected item + 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); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "action" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); } }; - const handleRemoveTrigger = (index: number) => { - setTriggerList(triggerList.filter((_, i) => i !== index)); - if ( - selectedItem?.type === "trigger" && - selectedItem.name === triggerList[index] - ) { - setSelectedItem(null); + // Do the same for trigger toggle + 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); + + // Immediately update the selected item if it's the one being toggled + if (selectedItem?.type === "trigger" && selectedItem.item.uuid === uuid) { + setSelectedItem({ + ...selectedItem, + item: { + ...selectedItem.item, + isUsed: !selectedItem.item.isUsed + } + }); } }; - const handleSelectItem = (type: "action" | "trigger", name: string) => { - setSelectedItem({ type, name }); - }; - - const [processes, setProcesses] = useState([]); - const [activeProcess, setActiveProcesses] = useState(); - - const handleSelect = (option: string) => { - setActiveProcesses(option); // Update the active option state - }; - const handleAddProcess = () => { - const newProcess = `Process ${processes.length + 1}`; // Generate new process name dynamically - setProcesses((prevProcesses) => [...prevProcesses, newProcess]); // Update the state with the new process - }; + const [selectedItem, setSelectedItem] = useState<{ + type: "action" | "trigger"; + item: any; + } | null>(null); return (
- {selectedActionSphere?.path?.modelName || "path name not found"} + {selectedActionSphere?.path?.modelName || "point name not found"}
- {/*
-
Process:
- "} - options={processes} - onSelect={handleSelect} - /> -
- -
-
*/} +
@@ -99,25 +350,24 @@ const MachineMechanics: React.FC = () => { style={{ height: "120px" }} >
- {actionList.map((action, index) => ( + {selectedPoint?.actions.map((action) => (
handleSelectItem("action", action)} + onClick={() => setSelectedItem({ type: "action", item: action })} > - +
handleRemoveAction(index)} + onClick={() => handleDeleteAction(action.uuid)} >
@@ -146,25 +396,24 @@ const MachineMechanics: React.FC = () => { style={{ height: "120px" }} >
- {triggerList.map((trigger, index) => ( + {selectedPoint?.triggers.map((trigger) => (
handleSelectItem("trigger", trigger)} + onClick={() => setSelectedItem({ type: "trigger", item: trigger })} > - +
handleRemoveTrigger(index)} + onClick={() => handleDeleteTrigger(trigger.uuid)} >
@@ -183,28 +432,105 @@ const MachineMechanics: React.FC = () => {
{selectedItem && ( <> -
{selectedItem.name}
- - {}} - /> - +
{selectedItem.item.name}
+ + {selectedItem.type === "action" && ( + <> + handleActionToggle(selectedItem.item.uuid)} + /> + handleActionSelect(selectedItem.item.uuid, option)} + /> + + {/* Only show material dropdown for Spawn/Swap actions */} + {(selectedItem.item.type === 'Spawn' || selectedItem.item.type === 'Swap') && ( + handleMaterialSelect(selectedItem.item.uuid, option)} + /> + )} + + {/* Only show delay input for Delay actions */} + {selectedItem.item.type === 'Delay' && ( + { + const numValue = parseInt(value); + handleDelayChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + {/* Only show spawn interval for Spawn actions */} + {selectedItem.item.type === 'Spawn' && ( + { + const numValue = parseInt(value); + handleSpawnIntervalChange( + selectedItem.item.uuid, + !value ? 'Inherit' : numValue + ); + }} + /> + )} + + )} + + {selectedItem.type === "trigger" && ( + <> + handleTriggerToggle(selectedItem.item.uuid)} + /> + + handleTriggerSelect(selectedItem.item.uuid, option)} + /> + + )} )} + + {selectedPath && !selectedItem && ( +
+ handleSpeedChange(parseFloat(value))} + /> +
+ )}
- By Selecting Path, you can create Object Triggers. + By selecting points, you can create events and triggers.
); }; -export default MachineMechanics; +export default MachineMechanics; \ No newline at end of file diff --git a/app/src/components/templates/LoadingPage.tsx b/app/src/components/templates/LoadingPage.tsx index 523caf5..a5fef18 100644 --- a/app/src/components/templates/LoadingPage.tsx +++ b/app/src/components/templates/LoadingPage.tsx @@ -7,7 +7,6 @@ interface LoadingPageProps { } const LoadingPage: React.FC = ({ progress }) => { - // Ensure progress stays within 0-100 range const validatedProgress = Math.min(100, Math.max(0, progress)); return ( diff --git a/app/src/components/ui/inputs/InputToggle.tsx b/app/src/components/ui/inputs/InputToggle.tsx index 0774100..941d486 100644 --- a/app/src/components/ui/inputs/InputToggle.tsx +++ b/app/src/components/ui/inputs/InputToggle.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React from "react"; interface InputToggleProps { label: string; // Represents the toggle state (on/off) @@ -7,23 +7,18 @@ interface InputToggleProps { inputKey: string; } +// Update InputToggle.tsx to be fully controlled const InputToggle: React.FC = ({ label, onClick, value = false, inputKey, }) => { - const [activeValue, setActiveValue] = useState(value); - + // Remove internal state and use the value prop directly function handleOnClick() { - setActiveValue(!activeValue); if (onClick) onClick(); } - useEffect(() => { - setActiveValue(value); - }, [value]); - return (
diff --git a/app/src/components/ui/inputs/InputWithDropDown.tsx b/app/src/components/ui/inputs/InputWithDropDown.tsx index fa19af3..86b3e91 100644 --- a/app/src/components/ui/inputs/InputWithDropDown.tsx +++ b/app/src/components/ui/inputs/InputWithDropDown.tsx @@ -9,6 +9,7 @@ type InputWithDropDownProps = { onClick?: () => void; onChange: (newValue: string) => void; editableLabel?: boolean; + placeholder?: string; // New placeholder prop }; const InputWithDropDown: React.FC = ({ @@ -19,6 +20,7 @@ const InputWithDropDown: React.FC = ({ onClick, onChange, editableLabel = false, + placeholder = "Inherit", // Default empty placeholder }) => { const separatedWords = label .split(/(?=[A-Z])/) @@ -38,11 +40,12 @@ const InputWithDropDown: React.FC = ({ )}
{ onChange(e.target.value); }} + placeholder={placeholder} // Added placeholder prop /> {activeOption && ( @@ -73,4 +76,4 @@ const InputWithDropDown: React.FC = ({ ); }; -export default InputWithDropDown; +export default InputWithDropDown; \ No newline at end of file diff --git a/app/src/components/ui/inputs/LabledDropdown.tsx b/app/src/components/ui/inputs/LabledDropdown.tsx index 29dbac5..7b86cd3 100644 --- a/app/src/components/ui/inputs/LabledDropdown.tsx +++ b/app/src/components/ui/inputs/LabledDropdown.tsx @@ -1,29 +1,49 @@ -import React, { useState } from "react"; +import React, { useState, useEffect } from "react"; import RegularDropDown from "./RegularDropDown"; type LabledDropdownProps = { defaultOption: string; // Initial active option options: string[]; // Array of dropdown options + label?: string; // Customizable label text + onSelect?: (option: string) => void; // Callback when option is selected + className?: string; // Additional className for styling + disabled?: boolean; // Disable dropdown + search?: boolean; // Enable/disable search functionality }; -const LabledDropdown: React.FC = ({ defaultOption, options }) => { - const [activeOption, setActiveOption] = useState(defaultOption); // State for active option +const LabledDropdown: React.FC = ({ + defaultOption, + options, + label = "Type", + onSelect, + className = "", + search = false +}) => { + const [activeOption, setActiveOption] = useState(defaultOption); + + // Update active option if defaultOption changes + useEffect(() => { + setActiveOption(defaultOption); + }, [defaultOption]); const handleSelect = (option: string) => { - setActiveOption(option); // Update the active option state + setActiveOption(option); + if (onSelect) { + onSelect(option); + } }; return ( -
-
Type
+
+
{label}
); }; -export default LabledDropdown; +export default LabledDropdown; \ No newline at end of file diff --git a/app/src/modules/builder/groups/floorItemsGroup.tsx b/app/src/modules/builder/groups/floorItemsGroup.tsx index 033146d..8435724 100644 --- a/app/src/modules/builder/groups/floorItemsGroup.tsx +++ b/app/src/modules/builder/groups/floorItemsGroup.tsx @@ -1,5 +1,5 @@ import { useFrame, useThree } from "@react-three/fiber"; -import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store"; +import { useActiveTool, useCamMode, useDeletableFloorItem, useDeleteModels, useFloorItems, useLoadingProgress, useRenderDistance, useselectedFloorItem, useSelectedItem, useSocketStore, useToggleView, useTransformMode } from "../../../store/store"; import assetVisibility from "../geomentries/assets/assetVisibility"; import { useEffect } from "react"; import * as THREE from "three"; @@ -11,24 +11,25 @@ import DeletableHoveredFloorItems from "../geomentries/assets/deletableHoveredFl import DeleteFloorItems from "../geomentries/assets/deleteFloorItems"; import loadInitialFloorItems from "../../scene/IntialLoad/loadInitialFloorItems"; import addAssetModel from "../geomentries/assets/addAssetModel"; -// import { getFloorItems } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi"; +import { getFloorItems } from "../../../services/factoryBuilder/assest/floorAsset/getFloorItemsApi"; // import { retrieveGLTF } from "../../../utils/indexDB/idbUtils"; const assetManagerWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/assetManagerWorker.js', import.meta.url)); -// const gltfLoaderWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js', import.meta.url)); +const gltfLoaderWorker = new Worker(new URL('../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js', import.meta.url)); const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject, floorGroup, tempLoader, isTempLoader, plane }: any) => { const state: Types.ThreeState = useThree(); - const { raycaster, camera, controls, pointer }: any = state; - const { renderDistance, setRenderDistance } = useRenderDistance(); - const { toggleView, setToggleView } = useToggleView(); + const { raycaster, controls }: any = state; + const { renderDistance } = useRenderDistance(); + const { toggleView } = useToggleView(); const { floorItems, setFloorItems } = useFloorItems(); - const { camMode, setCamMode } = useCamMode(); - const { deleteModels, setDeleteModels } = useDeleteModels(); - const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem(); - const { transformMode, setTransformMode } = useTransformMode(); - const { selectedFloorItem, setselectedFloorItem } = useselectedFloorItem(); - const { activeTool, setActiveTool } = useActiveTool(); + const { camMode } = useCamMode(); + const { deleteModels } = useDeleteModels(); + const { setDeletableFloorItem } = useDeletableFloorItem(); + const { transformMode } = useTransformMode(); + const { setselectedFloorItem } = useselectedFloorItem(); + const { activeTool } = useActiveTool(); const { selectedItem, setSelectedItem } = useSelectedItem(); + const { setLoadingProgress } = useLoadingProgress(); const { socket } = useSocketStore(); const loader = new GLTFLoader(); @@ -38,32 +39,57 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject loader.setDRACOLoader(dracoLoader); useEffect(() => { - // Load initial floor items + const email = localStorage.getItem('email'); + const organization = (email!.split("@")[1]).split(".")[0]; - // const email = localStorage.getItem('email'); - // const organization = (email!.split("@")[1]).split(".")[0]; + let totalAssets = 0; + let loadedAssets = 0; - // getFloorItems(organization).then((data) => { - // gltfLoaderWorker.postMessage({ FloorItems: data }) - // }) + const updateLoadingProgress = (progress: number) => { + if (progress < 100) { + setLoadingProgress(progress); + } else if (progress === 100) { + setTimeout(() => { + setLoadingProgress(100); + setTimeout(() => { + setLoadingProgress(0); + }, 1500); + }, 1000); + } + }; - // gltfLoaderWorker.onmessage = async (event) => { - // if (event.data.message === "gltfLoaded" && event.data.modelBlob) { - // const blobUrl = URL.createObjectURL(event.data.modelBlob); + getFloorItems(organization).then((data) => { + const uniqueItems = (data as Types.FloorItems).filter((item, index, self) => + index === self.findIndex((t) => t.modelfileID === item.modelfileID) + ); + totalAssets = uniqueItems.length; + if (totalAssets === 0) { + updateLoadingProgress(100); + return; + } + gltfLoaderWorker.postMessage({ floorItems: data }); + }); - // loader.load(blobUrl, (gltf) => { - // URL.revokeObjectURL(blobUrl); - // THREE.Cache.remove(blobUrl); - // THREE.Cache.add(event.data.modelID, gltf); - // }); + gltfLoaderWorker.onmessage = async (event) => { + if (event.data.message === "gltfLoaded" && event.data.modelBlob) { + const blobUrl = URL.createObjectURL(event.data.modelBlob); - // } else if (event.data.message === "done") { - // loadInitialFloorItems(itemsGroup, setFloorItems); - // } - // } + loader.load(blobUrl, (gltf) => { + URL.revokeObjectURL(blobUrl); + THREE.Cache.remove(blobUrl); + THREE.Cache.add(event.data.modelID, gltf); + loadedAssets++; + const progress = Math.round((loadedAssets / totalAssets) * 100); + updateLoadingProgress(progress); - loadInitialFloorItems(itemsGroup, setFloorItems); + if (loadedAssets === totalAssets) { + loadInitialFloorItems(itemsGroup, setFloorItems); + updateLoadingProgress(100); + } + }); + } + }; }, []); useEffect(() => { diff --git a/app/src/modules/builder/groups/zoneGroup.tsx b/app/src/modules/builder/groups/zoneGroup.tsx index 9e0bc15..128a72a 100644 --- a/app/src/modules/builder/groups/zoneGroup.tsx +++ b/app/src/modules/builder/groups/zoneGroup.tsx @@ -145,7 +145,7 @@ const ZoneGroup: React.FC = () => { const target: [number, number, number] | null = calculateCenter(zone.points); if (!target) return; - const position = [target[0], 75, target[2]]; + const position = [target[0], 50, target[2]]; const input = { userId: userId, diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 3aaff94..df1246a 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -24,7 +24,6 @@ export default function Scene() { { name: "backward", keys: ["ArrowDown", "s", "S"] }, { name: "left", keys: ["ArrowLeft", "a", "A"] }, { name: "right", keys: ["ArrowRight", "d", "D"] }, - // { name: "jump", keys: ["Space"] }, ], []) return ( diff --git a/app/src/modules/simulation/behaviour/behaviour.tsx b/app/src/modules/simulation/behaviour/behaviour.tsx index f7484f3..346e703 100644 --- a/app/src/modules/simulation/behaviour/behaviour.tsx +++ b/app/src/modules/simulation/behaviour/behaviour.tsx @@ -11,8 +11,9 @@ interface Path { 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 }[] | []; + actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; + }[]; pathPosition: [number, number, number]; pathRotation: [number, number, number]; @@ -43,21 +44,21 @@ function Behaviour({ setSimulationPaths }: { setSimulationPaths: any }) { uuid: point1UUID, position: [point1Position.x, point1Position.y, point1Position.z], rotation: [0, 0, 0], - actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], triggers: [], }, { uuid: middlePointUUID, position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z], rotation: [0, 0, 0], - actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], triggers: [], }, { uuid: point2UUID, position: [point2Position.x, point2Position.y, point2Position.z], rotation: [0, 0, 0], - actions: [{ uuid: THREE.MathUtils.generateUUID(), type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], + actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: false }], triggers: [], }, ], diff --git a/app/src/modules/simulation/path/pathConnector.tsx b/app/src/modules/simulation/path/pathConnector.tsx index 03724d5..9b27c48 100644 --- a/app/src/modules/simulation/path/pathConnector.tsx +++ b/app/src/modules/simulation/path/pathConnector.tsx @@ -47,7 +47,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec if (intersects.length > 0) { const intersected = intersects[0].object; - if (intersected.name.includes("event-sphere")) { + if (intersected.name.includes("action-sphere")) { const pathUUID = intersected.userData.path.modeluuid; const sphereUUID = intersected.uuid; const worldPosition = new THREE.Vector3(); @@ -153,7 +153,7 @@ function PathConnector({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObjec } const sphereIntersects = raycaster.intersectObjects(pathsGroupRef.current.children, true).filter((obj) => - obj.object.name.includes("event-sphere") + obj.object.name.includes("action-sphere") ); if (sphereIntersects.length > 0) { diff --git a/app/src/modules/simulation/path/pathCreation.tsx b/app/src/modules/simulation/path/pathCreation.tsx index 7ff7489..00dfe57 100644 --- a/app/src/modules/simulation/path/pathCreation.tsx +++ b/app/src/modules/simulation/path/pathCreation.tsx @@ -12,8 +12,8 @@ interface Path { 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 }[] | []; + actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; }[]; pathPosition: [number, number, number]; pathRotation: [number, number, number]; @@ -26,7 +26,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject const { setSelectedActionSphere, selectedActionSphere } = useSelectedActionSphere(); const { setSelectedPath } = useSelectedPath(); const { simulationPaths, setSimulationPaths } = useSimulationPaths(); - const { isConnecting, setIsConnecting } = useIsConnecting(); + const { isConnecting } = useIsConnecting(); const { camera } = useThree(); const groupRefs = useRef<{ [key: string]: THREE.Group }>({}); @@ -105,6 +105,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject setSelectedPath({ path, group: groupRefs.current[path.modeluuid] }); setSelectedActionSphere(null); setTransformMode(null); + setSubModule('mechanics'); }} onPointerMissed={() => { setSelectedPath(null); @@ -117,7 +118,7 @@ function PathCreation({ pathsGroupRef }: { pathsGroupRef: React.MutableRefObject uuid={point.uuid} position={point.position} args={[0.15, 32, 32]} - name='event-sphere' + name='action-sphere' ref={el => (sphereRefs.current[point.uuid] = el!)} onClick={(e) => { if (isConnecting) return; diff --git a/app/src/modules/simulation/simulationUI.tsx b/app/src/modules/simulation/simulationUI.tsx index 1ce60e7..e7d1834 100644 --- a/app/src/modules/simulation/simulationUI.tsx +++ b/app/src/modules/simulation/simulationUI.tsx @@ -14,15 +14,25 @@ function SimulationUI() { 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 - ), + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const actionIndex = point.actions.length; + const newAction = { + uuid: THREE.MathUtils.generateUUID(), + name: `Action ${actionIndex + 1}`, // Assign action name based on index + type: 'Inherit', + material: 'Inherit', + delay: 'Inherit', + spawnInterval: 'Inherit', + isUsed: false + }; + + return { ...point, actions: [...point.actions, newAction] }; + } + return point; + }), })); setSimulationPaths(updatedPaths); @@ -137,15 +147,22 @@ function SimulationUI() { 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 - ), + points: path.points.map((point) => { + if (point.uuid === selectedActionSphere.point.uuid) { + const triggerIndex = point.triggers.length; + const newTrigger = { + uuid: THREE.MathUtils.generateUUID(), + name: `Trigger ${triggerIndex + 1}`, // Assign name based on index + type: '', + isUsed: false + }; + + return { ...point, triggers: [...point.triggers, newTrigger] }; + } + return point; + }), })); setSimulationPaths(updatedPaths); diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 02a02b9..8a48516 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -5,7 +5,7 @@ import SideBarRight from "../components/layout/sidebarRight/SideBarRight"; import useModuleStore from "../store/useModuleStore"; import RealTimeVisulization from "../components/ui/componets/RealTimeVisulization"; import Tools from "../components/ui/Tools"; -import Scene from "../modules/scene/scene"; +// import Scene from "../modules/scene/scene"; import { useSocketStore, useFloorItems, @@ -13,14 +13,16 @@ import { useUserName, useWallItems, useZones, + useLoadingProgress, } from "../store/store"; import { useNavigate } from "react-router-dom"; -import SimulationUI from "../modules/simulation/simulationUI"; +// import SimulationUI from "../modules/simulation/simulationUI"; +import LoadingPage from "../components/templates/LoadingPage"; const Project: React.FC = () => { let navigate = useNavigate(); const { activeModule } = useModuleStore(); - + const { loadingProgress, setLoadingProgress } = useLoadingProgress(); const { setUserName } = useUserName(); const { setOrganization } = useOrganization(); const { setFloorItems } = useFloorItems(); @@ -47,16 +49,13 @@ const Project: React.FC = () => { return (
+ {loadingProgress && } {activeModule !== "market" && } {/* */} -
); }; diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 851ab7e..a5a7c57 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -2,10 +2,9 @@ import React, { useState, FormEvent } from "react"; import { useNavigate } from "react-router-dom"; import { LogoIconLarge } from "../components/icons/Logo"; import { EyeIcon } from "../components/icons/ExportCommonIcons"; -import { useOrganization, useUserName } from "../store/store"; +import { useLoadingProgress, 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"; const UserAuth: React.FC = () => { const [email, setEmail] = useState(""); @@ -14,7 +13,8 @@ const UserAuth: React.FC = () => { const [error, setError] = useState(""); const [isSignIn, setIsSignIn] = useState(true); const { userName, setUserName } = useUserName(); - const { organization, setOrganization } = useOrganization(); + const { setOrganization } = useOrganization(); + const { setLoadingProgress } = useLoadingProgress(); const navigate = useNavigate(); @@ -33,6 +33,7 @@ const UserAuth: React.FC = () => { localStorage.setItem("email", res.email); localStorage.setItem("userName", res.name); if (res.isShare) { + setLoadingProgress(1); navigate("/Project"); } } else if (res.message === "User Not Found!!! Kindly signup...") { @@ -63,7 +64,6 @@ const UserAuth: React.FC = () => { return ( <> - {/* */}
@@ -141,7 +141,7 @@ const UserAuth: React.FC = () => {
{!isSignIn && (
- +
I have read and agree to the terms of service
diff --git a/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js b/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js index effa8b3..2fbdc13 100644 --- a/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js +++ b/app/src/services/factoryBuilder/webWorkers/gltfLoaderWorker.js @@ -1,7 +1,7 @@ import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader'; -import { retrieveGLTF, storeGLTF } from '../../../components/scene/indexDB/idbUtils'; +import { retrieveGLTF, storeGLTF } from '../../../utils/indexDB/idbUtils'; const loader = new GLTFLoader(); const dracoLoader = new DRACOLoader(); diff --git a/app/src/store/store.ts b/app/src/store/store.ts index 0cca1fe..0aa980b 100644 --- a/app/src/store/store.ts +++ b/app/src/store/store.ts @@ -26,6 +26,11 @@ export const useSocketStore = create((set: any, get: any) => ({ } })); +export const useLoadingProgress = create<{ loadingProgress: number; setLoadingProgress: (x: number) => void }>((set) => ({ + loadingProgress: 1, + setLoadingProgress: (x: number) => set({ loadingProgress: x }), +})); + export const useOrganization = create((set: any) => ({ organization: "", setOrganization: (x: any) => set(() => ({ organization: x })), @@ -300,8 +305,8 @@ interface Path { 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 }[] | []; + actions: { uuid: string; name: string; type: string; material: string; delay: number | string; spawnInterval: number | string; isUsed: boolean }[] | []; + triggers: { uuid: string; name: string; type: string; isUsed: boolean }[] | []; }[]; pathPosition: [number, number, number]; pathRotation: [number, number, number];