simulation #41
|
@ -101,7 +101,6 @@ const ProgressBarWidget = ({
|
|||
</div>
|
||||
);
|
||||
};
|
||||
console.log(chartTypes, "chartTypes");
|
||||
|
||||
const Widgets2D = () => {
|
||||
return (
|
||||
|
|
|
@ -10,6 +10,7 @@ import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
|||
import LabledDropdown from "../../../ui/inputs/LabledDropdown";
|
||||
import { handleResize } from "../../../../functions/handleResizePannel";
|
||||
import {
|
||||
useFloorItems,
|
||||
useSelectedActionSphere,
|
||||
useSelectedPath,
|
||||
useSimulationPaths,
|
||||
|
@ -17,11 +18,14 @@ import {
|
|||
import * as THREE from "three";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
import InputToggle from "../../../ui/inputs/InputToggle";
|
||||
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
|
||||
import { setEventApi } from "../../../../services/factoryBuilder/assest/floorAsset/setEventsApt";
|
||||
|
||||
const ConveyorMechanics: React.FC = () => {
|
||||
const { selectedActionSphere } = useSelectedActionSphere();
|
||||
const { selectedPath, setSelectedPath } = useSelectedPath();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
|
||||
const actionsContainerRef = useRef<HTMLDivElement>(null);
|
||||
const triggersContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
@ -36,6 +40,19 @@ const ConveyorMechanics: React.FC = () => {
|
|||
.find((point) => point.uuid === selectedActionSphere.point.uuid);
|
||||
}, [selectedActionSphere, simulationPaths]);
|
||||
|
||||
const updateBackend = async (updatedPath: Types.ConveyorEventsSchema | undefined) => {
|
||||
if (!updatedPath) return;
|
||||
// const email = localStorage.getItem("email");
|
||||
// const organization = email ? email.split("@")[1].split(".")[0] : "";
|
||||
// console.log('updatedPath: ', updatedPath);
|
||||
// const a = await setEventApi(
|
||||
// organization,
|
||||
// updatedPath.modeluuid,
|
||||
// updatedPath.points
|
||||
// );
|
||||
// console.log('a: ', a);
|
||||
}
|
||||
|
||||
const handleAddAction = () => {
|
||||
if (!selectedActionSphere) return;
|
||||
|
||||
|
@ -65,6 +82,15 @@ const ConveyorMechanics: React.FC = () => {
|
|||
return path;
|
||||
});
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -74,21 +100,30 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.filter(
|
||||
(action) => action.uuid !== uuid
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.filter(
|
||||
(action) => action.uuid !== uuid
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -98,36 +133,45 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid
|
||||
? {
|
||||
...action,
|
||||
type: actionType,
|
||||
material:
|
||||
actionType === "Spawn" || actionType === "Swap"
|
||||
? "Inherit"
|
||||
: action.material,
|
||||
delay:
|
||||
actionType === "Delay" ? "Inherit" : action.delay,
|
||||
spawnInterval:
|
||||
actionType === "Spawn"
|
||||
? "Inherit"
|
||||
: action.spawnInterval,
|
||||
}
|
||||
: action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid
|
||||
? {
|
||||
...action,
|
||||
type: actionType,
|
||||
material:
|
||||
actionType === "Spawn" || actionType === "Swap"
|
||||
? "Inherit"
|
||||
: action.material,
|
||||
delay:
|
||||
actionType === "Delay" ? "Inherit" : action.delay,
|
||||
spawnInterval:
|
||||
actionType === "Spawn"
|
||||
? "Inherit"
|
||||
: action.spawnInterval,
|
||||
}
|
||||
: action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Update the selected item to reflect changes
|
||||
|
@ -156,24 +200,33 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...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
|
||||
),
|
||||
}
|
||||
...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
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Update selected item if it's the current action
|
||||
|
@ -194,21 +247,30 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid ? { ...action, delay } : action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid ? { ...action, delay } : action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -221,23 +283,32 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid
|
||||
? { ...action, spawnInterval }
|
||||
: action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
actions: point.actions.map((action) =>
|
||||
action.uuid === uuid
|
||||
? { ...action, spawnInterval }
|
||||
: action
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -248,6 +319,15 @@ const ConveyorMechanics: React.FC = () => {
|
|||
path.modeluuid === selectedPath.path.modeluuid ? { ...path, speed } : path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
setSelectedPath({ ...selectedPath, path: { ...selectedPath.path, speed } });
|
||||
};
|
||||
|
@ -258,26 +338,35 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...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: "",
|
||||
bufferTime: 0,
|
||||
isUsed: false,
|
||||
};
|
||||
...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: "",
|
||||
bufferTime: 0,
|
||||
isUsed: false,
|
||||
};
|
||||
|
||||
return { ...point, triggers: [...point.triggers, newTrigger] };
|
||||
}
|
||||
return point;
|
||||
}),
|
||||
}
|
||||
return { ...point, triggers: [...point.triggers, newTrigger] };
|
||||
}
|
||||
return point;
|
||||
}),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -287,21 +376,30 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
triggers: point.triggers.filter(
|
||||
(trigger) => trigger.uuid !== uuid
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
triggers: point.triggers.filter(
|
||||
(trigger) => trigger.uuid !== uuid
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
};
|
||||
|
||||
|
@ -311,23 +409,32 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...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
|
||||
),
|
||||
}
|
||||
...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
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Ensure the selectedItem is updated immediately
|
||||
|
@ -347,22 +454,31 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...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
|
||||
),
|
||||
}
|
||||
...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
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Immediately update the selected item if it's the one being toggled
|
||||
|
@ -384,22 +500,31 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...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
|
||||
),
|
||||
}
|
||||
...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
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Immediately update the selected item if it's the one being toggled
|
||||
|
@ -420,23 +545,32 @@ const ConveyorMechanics: React.FC = () => {
|
|||
const updatedPaths = simulationPaths.map((path) =>
|
||||
path.type === "Conveyor"
|
||||
? {
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
triggers: point.triggers.map((trigger) =>
|
||||
trigger.uuid === uuid
|
||||
? { ...trigger, bufferTime }
|
||||
: trigger
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
...path,
|
||||
points: path.points.map((point) =>
|
||||
point.uuid === selectedActionSphere.point.uuid
|
||||
? {
|
||||
...point,
|
||||
triggers: point.triggers.map((trigger) =>
|
||||
trigger.uuid === uuid
|
||||
? { ...trigger, bufferTime }
|
||||
: trigger
|
||||
),
|
||||
}
|
||||
: point
|
||||
),
|
||||
}
|
||||
: path
|
||||
);
|
||||
|
||||
const updatedPath = updatedPaths.find(
|
||||
(path): path is Types.ConveyorEventsSchema =>
|
||||
path.type === "Conveyor" &&
|
||||
path.points.some(
|
||||
(point) => point.uuid === selectedActionSphere.point.uuid
|
||||
)
|
||||
);
|
||||
updateBackend(updatedPath);
|
||||
|
||||
setSimulationPaths(updatedPaths);
|
||||
|
||||
// Immediately update selectedItem if it's the currently selected trigger
|
||||
|
@ -493,12 +627,11 @@ const ConveyorMechanics: React.FC = () => {
|
|||
{selectedPoint?.actions.map((action) => (
|
||||
<div
|
||||
key={action.uuid}
|
||||
className={`list-item ${
|
||||
selectedItem?.type === "action" &&
|
||||
className={`list-item ${selectedItem?.type === "action" &&
|
||||
selectedItem.item?.uuid === action.uuid
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="value"
|
||||
|
@ -506,7 +639,7 @@ const ConveyorMechanics: React.FC = () => {
|
|||
setSelectedItem({ type: "action", item: action })
|
||||
}
|
||||
>
|
||||
<input type="radio" name="action" id="action" defaultChecked={action.isUsed}/>
|
||||
<input type="radio" name="action" id="action" defaultChecked={action.isUsed} />
|
||||
<RenameInput value={action.name} />
|
||||
</div>
|
||||
<div
|
||||
|
@ -543,12 +676,11 @@ const ConveyorMechanics: React.FC = () => {
|
|||
{selectedPoint?.triggers.map((trigger) => (
|
||||
<div
|
||||
key={trigger.uuid}
|
||||
className={`list-item ${
|
||||
selectedItem?.type === "trigger" &&
|
||||
className={`list-item ${selectedItem?.type === "trigger" &&
|
||||
selectedItem.item?.uuid === trigger.uuid
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
? "active"
|
||||
: ""
|
||||
}`}
|
||||
>
|
||||
<div
|
||||
className="value"
|
||||
|
@ -588,8 +720,8 @@ const ConveyorMechanics: React.FC = () => {
|
|||
{selectedItem.type === "action" && (
|
||||
<>
|
||||
<InputToggle
|
||||
inputKey="enableTrigger"
|
||||
label="Enable Trigger"
|
||||
inputKey="enableAction"
|
||||
label="Enable Action"
|
||||
value={selectedItem.item.isUsed}
|
||||
onClick={() => handleActionToggle(selectedItem.item.uuid)}
|
||||
/>
|
||||
|
@ -604,19 +736,19 @@ const ConveyorMechanics: React.FC = () => {
|
|||
{/* Only show material dropdown for Spawn/Swap actions */}
|
||||
{(selectedItem.item.type === "Spawn" ||
|
||||
selectedItem.item.type === "Swap") && (
|
||||
<LabledDropdown
|
||||
label={
|
||||
selectedItem.item.type === "Spawn"
|
||||
? "Spawn Material"
|
||||
: "Swap Material"
|
||||
}
|
||||
defaultOption={selectedItem.item.material}
|
||||
options={["Inherit", "Crate", "Box"]}
|
||||
onSelect={(option) =>
|
||||
handleMaterialSelect(selectedItem.item.uuid, option)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<LabledDropdown
|
||||
label={
|
||||
selectedItem.item.type === "Spawn"
|
||||
? "Spawn Material"
|
||||
: "Swap Material"
|
||||
}
|
||||
defaultOption={selectedItem.item.material}
|
||||
options={["Inherit", "Crate", "Box"]}
|
||||
onSelect={(option) =>
|
||||
handleMaterialSelect(selectedItem.item.uuid, option)
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Only show delay input for Delay actions */}
|
||||
{selectedItem.item.type === "Delay" && (
|
||||
|
|
|
@ -33,7 +33,7 @@ const GlobalProperties: React.FC = () => {
|
|||
const { setPlaneValue, setGridValue, planeValue, gridValue } =
|
||||
useTileDistance();
|
||||
useEffect(() => {
|
||||
console.log(gridValue, planeValue, "values");
|
||||
// console.log(gridValue, planeValue, "values");
|
||||
}, [gridValue, planeValue]);
|
||||
const { socket } = useSocketStore();
|
||||
const { limitDistance, setLimitDistance } = useLimitDistance();
|
||||
|
|
|
@ -24,6 +24,7 @@ async function addAssetModel(
|
|||
socket: Socket<any>,
|
||||
selectedItem: any,
|
||||
setSelectedItem: any,
|
||||
setSimulationPaths: any,
|
||||
plane: Types.RefMesh,
|
||||
): Promise<void> {
|
||||
|
||||
|
@ -64,7 +65,7 @@ async function addAssetModel(
|
|||
const cachedModel = THREE.Cache.get(selectedItem.id);
|
||||
if (cachedModel) {
|
||||
// console.log(`[Cache] Fetching ${selectedItem.name}`);
|
||||
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
||||
handleModelLoad(cachedModel, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
return;
|
||||
} else {
|
||||
const cachedModelBlob = await retrieveGLTF(selectedItem.id);
|
||||
|
@ -77,7 +78,7 @@ async function addAssetModel(
|
|||
URL.revokeObjectURL(blobUrl);
|
||||
THREE.Cache.remove(blobUrl);
|
||||
THREE.Cache.add(selectedItem.id, gltf);
|
||||
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
||||
handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
},
|
||||
() => {
|
||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||
|
@ -89,7 +90,7 @@ async function addAssetModel(
|
|||
const modelBlob = await fetch(`${url_Backend_dwinzo}/api/v1/AssetFile/${selectedItem.id}`).then((res) => res.blob());
|
||||
await storeGLTF(selectedItem.id, modelBlob);
|
||||
THREE.Cache.add(selectedItem.id, gltf);
|
||||
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, socket);
|
||||
await handleModelLoad(gltf, intersectPoint!, selectedItem, itemsGroup, tempLoader, isTempLoader, setFloorItems, setSimulationPaths, socket);
|
||||
},
|
||||
() => {
|
||||
TempLoader(intersectPoint!, isTempLoader, tempLoader, itemsGroup);
|
||||
|
@ -112,10 +113,11 @@ async function handleModelLoad(
|
|||
tempLoader: Types.RefMesh,
|
||||
isTempLoader: Types.RefBoolean,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: any,
|
||||
socket: Socket<any>
|
||||
) {
|
||||
const model = gltf.scene.clone();
|
||||
model.userData = { name: selectedItem.name, modelId: selectedItem.id };
|
||||
model.userData = { name: selectedItem.name, modelId: selectedItem.id, modeluuid: model.uuid };
|
||||
model.position.set(intersectPoint!.x, 3 + intersectPoint!.y, intersectPoint!.z);
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
|
||||
|
@ -152,7 +154,7 @@ async function handleModelLoad(
|
|||
if (res.type === "Conveyor") {
|
||||
const pointUUIDs = res.points.map(() => THREE.MathUtils.generateUUID());
|
||||
|
||||
const eventData: Extract<Types.FloorItemType['eventData'], { type: 'Conveyor' }> = {
|
||||
const backendEventData: Extract<Types.FloorItemType['eventData'], { type: 'Conveyor' }> = {
|
||||
type: 'Conveyor',
|
||||
points: res.points.map((point: any, index: number) => ({
|
||||
uuid: pointUUIDs[index],
|
||||
|
@ -176,49 +178,94 @@ async function handleModelLoad(
|
|||
speed: 'Inherit'
|
||||
};
|
||||
|
||||
// console.log('eventData: ', eventData);
|
||||
newFloorItem.eventData = eventData;
|
||||
// API
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// newFloorItem.modeluuid,
|
||||
// newFloorItem.modelname,
|
||||
// newFloorItem.modelfileID,
|
||||
// newFloorItem.position,
|
||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// newFloorItem.eventData
|
||||
// );
|
||||
|
||||
// SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
socketId: socket.id
|
||||
};
|
||||
|
||||
console.log('data: ', data);
|
||||
setFloorItems((prevItems) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
const eventData: any = backendEventData;
|
||||
eventData.modeluuid = newFloorItem.modeluuid;
|
||||
eventData.modelName = newFloorItem.modelname;
|
||||
eventData.position = newFloorItem.position;
|
||||
eventData.rotation = [model.rotation.x, model.rotation.y, model.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
eventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
} else {
|
||||
|
||||
// API
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// newFloorItem.modeluuid,
|
||||
// newFloorItem.modelname,
|
||||
// newFloorItem.modelfileID,
|
||||
// newFloorItem.position,
|
||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
// false,
|
||||
// true
|
||||
// );
|
||||
|
||||
// SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id
|
||||
};
|
||||
|
||||
setFloorItems((prevItems) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
}
|
||||
|
||||
setFloorItems((prevItems) => {
|
||||
const updatedItems = [...(prevItems || []), newFloorItem];
|
||||
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
|
||||
return updatedItems;
|
||||
});
|
||||
|
||||
// API
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// newFloorItem.modeluuid,
|
||||
// newFloorItem.modelname,
|
||||
// newFloorItem.modelfileID,
|
||||
// newFloorItem.position,
|
||||
// { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
// false,
|
||||
// true,
|
||||
// newFloorItem.eventData
|
||||
// );
|
||||
|
||||
// SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: newFloorItem.eventData,
|
||||
socketId: socket.id
|
||||
};
|
||||
console.log('data: ', data);
|
||||
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
gsap.to(model.position, { y: newFloorItem.position[1], duration: 1.5, ease: "power2.out" });
|
||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: "power2.out", onComplete: () => { toast.success("Model Added!"); } });
|
||||
});
|
||||
|
|
|
@ -121,7 +121,7 @@ export default async function assetManager(
|
|||
|
||||
const model = gltf;
|
||||
model.uuid = item.modeluuid;
|
||||
model.userData = { name: item.modelname, modelId: item.modelfileID };
|
||||
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
model.position.set(...item.position);
|
||||
model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
|
||||
|
|
|
@ -10,6 +10,7 @@ async function DeleteFloorItems(
|
|||
itemsGroup: Types.RefGroup,
|
||||
hoveredDeletableFloorItem: Types.RefMesh,
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: any,
|
||||
socket: Socket<any>
|
||||
): Promise<void> {
|
||||
|
||||
|
@ -74,6 +75,12 @@ async function DeleteFloorItems(
|
|||
itemsGroup.current.remove(hoveredDeletableFloorItem.current);
|
||||
}
|
||||
setFloorItems(updatedItems);
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).filter(event => event.modeluuid !== removedItem.modeluuid);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
toast.success("Model Removed!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
useRenderDistance,
|
||||
useselectedFloorItem,
|
||||
useSelectedItem,
|
||||
useSimulationPaths,
|
||||
useSocketStore,
|
||||
useToggleView,
|
||||
useTransformMode,
|
||||
|
@ -64,6 +65,7 @@ const FloorItemsGroup = ({
|
|||
const { setselectedFloorItem } = useselectedFloorItem();
|
||||
const { activeTool } = useActiveTool();
|
||||
const { selectedItem, setSelectedItem } = useSelectedItem();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { setLoadingProgress } = useLoadingProgress();
|
||||
const { activeModule } = useModuleStore();
|
||||
const { socket } = useSocketStore();
|
||||
|
@ -96,16 +98,23 @@ const FloorItemsGroup = ({
|
|||
};
|
||||
|
||||
getFloorAssets(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) {
|
||||
if (data.length > 0) {
|
||||
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 });
|
||||
} else {
|
||||
console.log('data: ', data);
|
||||
gltfLoaderWorker.postMessage({ floorItems: [] });
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
||||
updateLoadingProgress(100);
|
||||
return;
|
||||
}
|
||||
gltfLoaderWorker.postMessage({ floorItems: data });
|
||||
});
|
||||
|
||||
gltfLoaderWorker.onmessage = async (event) => {
|
||||
|
@ -122,7 +131,7 @@ const FloorItemsGroup = ({
|
|||
updateLoadingProgress(progress);
|
||||
|
||||
if (loadedAssets === totalAssets) {
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems);
|
||||
loadInitialFloorItems(itemsGroup, setFloorItems, setSimulationPaths);
|
||||
updateLoadingProgress(100);
|
||||
}
|
||||
});
|
||||
|
@ -240,6 +249,7 @@ const FloorItemsGroup = ({
|
|||
itemsGroup,
|
||||
hoveredDeletableFloorItem,
|
||||
setFloorItems,
|
||||
setSimulationPaths,
|
||||
socket
|
||||
);
|
||||
}
|
||||
|
@ -365,6 +375,7 @@ const FloorItemsGroup = ({
|
|||
socket,
|
||||
selectedItem,
|
||||
setSelectedItem,
|
||||
setSimulationPaths,
|
||||
plane
|
||||
);
|
||||
}
|
||||
|
@ -408,7 +419,6 @@ const FloorItemsGroup = ({
|
|||
activeModule,
|
||||
]);
|
||||
|
||||
useEffect(() => {}, [floorItems]);
|
||||
|
||||
useFrame(() => {
|
||||
if (controls)
|
||||
|
|
|
@ -105,7 +105,7 @@ export default function SocketResponses({
|
|||
// console.log(`Getting ${data.data.modelname} from cache`);
|
||||
const model = cachedModel.scene.clone();
|
||||
model.uuid = data.data.modeluuid;
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelFileID };
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelFileID, modeluuid: data.data.modeluuid };
|
||||
model.position.set(...data.data.position as [number, number, number]);
|
||||
model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
|
@ -183,7 +183,7 @@ export default function SocketResponses({
|
|||
THREE.Cache.remove(url);
|
||||
const model = gltf.scene;
|
||||
model.uuid = data.data.modeluuid;
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelFileID };
|
||||
model.userData = { name: data.data.modelname, modelId: data.data.modelFileID, modeluuid: data.data.modeluuid };
|
||||
model.position.set(...data.data.position as [number, number, number]);
|
||||
model.rotation.set(data.data.rotation.x, data.data.rotation.y, data.data.rotation.z);
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
|
|
|
@ -11,7 +11,8 @@ import { getFloorAssets } from '../../../services/factoryBuilder/assest/floorAss
|
|||
|
||||
async function loadInitialFloorItems(
|
||||
itemsGroup: Types.RefGroup,
|
||||
setFloorItems: Types.setFloorItemSetState
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
||||
): Promise<void> {
|
||||
if (!itemsGroup.current) return;
|
||||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||
|
@ -22,6 +23,8 @@ async function loadInitialFloorItems(
|
|||
localStorage.setItem("FloorItems", JSON.stringify(items));
|
||||
await initializeDB();
|
||||
|
||||
if (items.message === "floorItems not found") return;
|
||||
|
||||
if (items) {
|
||||
const storedFloorItems: Types.FloorItems = items;
|
||||
const loader = new GLTFLoader();
|
||||
|
@ -50,6 +53,7 @@ async function loadInitialFloorItems(
|
|||
});
|
||||
|
||||
for (const item of storedFloorItems) {
|
||||
console.log('item: ', item);
|
||||
if (!item.modelfileID) return;
|
||||
const itemPosition = new THREE.Vector3(item.position[0], item.position[1], item.position[2]);
|
||||
let storedPosition;
|
||||
|
@ -68,7 +72,7 @@ async function loadInitialFloorItems(
|
|||
const cachedModel = THREE.Cache.get(item.modelfileID!);
|
||||
if (cachedModel) {
|
||||
// console.log(`[Cache] Fetching ${item.modelname}`);
|
||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems);
|
||||
processLoadedModel(cachedModel.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
return;
|
||||
|
@ -85,7 +89,7 @@ async function loadInitialFloorItems(
|
|||
URL.revokeObjectURL(blobUrl);
|
||||
THREE.Cache.remove(blobUrl);
|
||||
THREE.Cache.add(item.modelfileID!, gltf);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
},
|
||||
|
@ -108,7 +112,7 @@ async function loadInitialFloorItems(
|
|||
const modelBlob = await fetch(modelUrl).then((res) => res.blob());
|
||||
await storeGLTF(item.modelfileID!, modelBlob);
|
||||
THREE.Cache.add(item.modelfileID!, gltf);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems);
|
||||
processLoadedModel(gltf.scene.clone(), item, itemsGroup, setFloorItems, setSimulationPaths);
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, resolve);
|
||||
},
|
||||
|
@ -121,34 +125,23 @@ async function loadInitialFloorItems(
|
|||
});
|
||||
} else {
|
||||
// console.log(`Item ${item.modelname} is not near`);
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
},
|
||||
]);
|
||||
|
||||
if (item.eventData) {
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
// eventData: item.eventData,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
},
|
||||
]);
|
||||
processEventData(item, setSimulationPaths);
|
||||
}
|
||||
|
||||
modelsLoaded++;
|
||||
checkLoadingCompletion(modelsLoaded, modelsToLoad, dracoLoader, () => { });
|
||||
}
|
||||
|
@ -164,12 +157,13 @@ function processLoadedModel(
|
|||
gltf: any,
|
||||
item: Types.FloorItemType,
|
||||
itemsGroup: Types.RefGroup,
|
||||
setFloorItems: Types.setFloorItemSetState
|
||||
setFloorItems: Types.setFloorItemSetState,
|
||||
setSimulationPaths: (paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => void
|
||||
) {
|
||||
const model = gltf;
|
||||
model.uuid = item.modeluuid;
|
||||
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
|
||||
model.userData = { name: item.modelname, modelId: item.modelfileID };
|
||||
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
|
||||
model.position.set(...item.position);
|
||||
model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
|
||||
|
||||
|
@ -186,39 +180,67 @@ function processLoadedModel(
|
|||
|
||||
itemsGroup?.current?.add(model);
|
||||
|
||||
if (item.eventData) {
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
// eventData: item.eventData,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
},
|
||||
]);
|
||||
setFloorItems((prevItems) => [
|
||||
...(prevItems || []),
|
||||
{
|
||||
modeluuid: item.modeluuid,
|
||||
modelname: item.modelname,
|
||||
position: item.position,
|
||||
rotation: item.rotation,
|
||||
modelfileID: item.modelfileID,
|
||||
isLocked: item.isLocked,
|
||||
isVisible: item.isVisible,
|
||||
},
|
||||
]);
|
||||
|
||||
if (item.eventData || item.modelfileID === '67e3da19c2e8f37134526e6a') {
|
||||
processEventData(item, setSimulationPaths);
|
||||
}
|
||||
|
||||
gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' });
|
||||
gsap.to(model.scale, { x: 1, y: 1, z: 1, duration: 1.5, ease: 'power2.out' });
|
||||
}
|
||||
|
||||
function processEventData(item: Types.FloorItemType, setSimulationPaths: any) {
|
||||
|
||||
if (item.eventData?.type === 'Conveyor') {
|
||||
|
||||
const data: any = item.eventData;
|
||||
data.modeluuid = item.modeluuid;
|
||||
data.modelName = item.modelname;
|
||||
data.position = item.position;
|
||||
data.rotation = [item.rotation.x, item.rotation.y, item.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
data as Types.ConveyorEventsSchema
|
||||
]);
|
||||
} else {
|
||||
|
||||
const pointUUID = THREE.MathUtils.generateUUID();
|
||||
const pointPosition = new THREE.Vector3(0, 1.3, 0);
|
||||
|
||||
const newVehiclePath: Types.VehicleEventsSchema = {
|
||||
modeluuid: item.modeluuid,
|
||||
modelName: item.modelname,
|
||||
type: 'Vehicle',
|
||||
point: {
|
||||
uuid: pointUUID,
|
||||
position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
speed: 2,
|
||||
},
|
||||
position: [...item.position],
|
||||
};
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.VehicleEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newVehiclePath as Types.VehicleEventsSchema
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function checkLoadingCompletion(
|
||||
modelsLoaded: number,
|
||||
modelsToLoad: number,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as THREE from "three";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { toast } from "react-toastify";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
|
@ -10,6 +10,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
|||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore()
|
||||
|
@ -150,37 +151,128 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
|
|||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
if (eventData) {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
const createConveyorPoint = (index: number) => {
|
||||
const pointUUID = THREE.MathUtils.generateUUID();
|
||||
const hasActions = (eventData as Types.ConveyorEventsSchema)?.points[index].actions.length > 0;
|
||||
|
||||
//REST
|
||||
const defaultAction = {
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
name: 'Action 1',
|
||||
type: 'Inherit',
|
||||
material: 'Inherit',
|
||||
delay: 'Inherit',
|
||||
spawnInterval: 'Inherit',
|
||||
isUsed: true
|
||||
};
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
return {
|
||||
uuid: pointUUID,
|
||||
position: (eventData as Types.ConveyorEventsSchema)?.points[index].position,
|
||||
rotation: (eventData as Types.ConveyorEventsSchema)?.points[index].rotation,
|
||||
actions: hasActions
|
||||
? (eventData as Types.ConveyorEventsSchema)?.points[index].actions.map(action => ({
|
||||
...action,
|
||||
uuid: THREE.MathUtils.generateUUID()
|
||||
}))
|
||||
: [defaultAction],
|
||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
||||
connections: {
|
||||
source: { pathUUID: obj.uuid, pointUUID },
|
||||
targets: []
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
//SOCKET
|
||||
const backendEventData = {
|
||||
type: 'Conveyor',
|
||||
points: [
|
||||
createConveyorPoint(0), // point1
|
||||
createConveyorPoint(1), // middlePoint
|
||||
createConveyorPoint(2) // point2
|
||||
],
|
||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||
};
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
//REST
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
}
|
||||
} else {
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
}
|
||||
|
||||
itemsGroupRef.current.add(obj);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as THREE from "three";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { toast } from "react-toastify";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
|
@ -10,11 +10,11 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
|||
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!camera || !scene || toggleView) return;
|
||||
const canvasElement = gl.domElement;
|
||||
|
@ -131,37 +131,129 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
|
|||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
//REST
|
||||
if (eventData) {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
const createConveyorPoint = (index: number) => {
|
||||
const pointUUID = THREE.MathUtils.generateUUID();
|
||||
const hasActions = (eventData as Types.ConveyorEventsSchema)?.points[index].actions.length > 0;
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
const defaultAction = {
|
||||
uuid: THREE.MathUtils.generateUUID(),
|
||||
name: 'Action 1',
|
||||
type: 'Inherit',
|
||||
material: 'Inherit',
|
||||
delay: 'Inherit',
|
||||
spawnInterval: 'Inherit',
|
||||
isUsed: true
|
||||
};
|
||||
|
||||
//SOCKET
|
||||
return {
|
||||
uuid: pointUUID,
|
||||
position: (eventData as Types.ConveyorEventsSchema)?.points[index].position,
|
||||
rotation: (eventData as Types.ConveyorEventsSchema)?.points[index].rotation,
|
||||
actions: hasActions
|
||||
? (eventData as Types.ConveyorEventsSchema)?.points[index].actions.map(action => ({
|
||||
...action,
|
||||
uuid: THREE.MathUtils.generateUUID()
|
||||
}))
|
||||
: [defaultAction],
|
||||
triggers: (eventData as Types.ConveyorEventsSchema)?.points[index].triggers,
|
||||
connections: {
|
||||
source: { pathUUID: obj.uuid, pointUUID },
|
||||
targets: []
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
const backendEventData = {
|
||||
type: 'Conveyor',
|
||||
points: [
|
||||
createConveyorPoint(0), // point1
|
||||
createConveyorPoint(1), // middlePoint
|
||||
createConveyorPoint(2) // point2
|
||||
],
|
||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||
};
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => [
|
||||
...(prevEvents || []),
|
||||
newEventData as Types.ConveyorEventsSchema | Types.VehicleEventsSchema
|
||||
]);
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
}
|
||||
} else {
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
}
|
||||
|
||||
itemsGroupRef.current.add(obj);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as THREE from "three";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import { toast } from "react-toastify";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
|
@ -12,6 +12,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
|||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
|
@ -179,37 +180,99 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
|
|||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
//REST
|
||||
if (eventData) {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
const backendEventData = {
|
||||
type: 'Conveyor',
|
||||
points: eventData.points,
|
||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||
};
|
||||
|
||||
//SOCKET
|
||||
//REST
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// );
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
: event
|
||||
);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
// socket.emit("v2:model-asset:add", data);
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
}
|
||||
|
||||
itemsGroupRef.current.add(obj);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as THREE from "three";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
// import { setFloorItemApi } from '../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi';
|
||||
import { toast } from "react-toastify";
|
||||
import * as Types from "../../../../types/world/worldTypes";
|
||||
|
@ -12,6 +12,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
|||
|
||||
const { toggleView } = useToggleView();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const { simulationPaths, setSimulationPaths } = useSimulationPaths();
|
||||
const { floorItems, setFloorItems } = useFloorItems();
|
||||
const { socket } = useSocketStore();
|
||||
const itemsData = useRef<Types.FloorItems>([]);
|
||||
|
@ -182,37 +183,99 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
|
|||
return updatedItems;
|
||||
});
|
||||
|
||||
let eventData: Types.ConveyorEventsSchema | Types.VehicleEventsSchema | undefined = simulationPaths.find((events) => events.modeluuid === obj.userData.modeluuid);
|
||||
|
||||
const email = localStorage.getItem("email");
|
||||
const organization = email ? email.split("@")[1].split(".")[0] : "default";
|
||||
|
||||
//REST
|
||||
if (eventData) {
|
||||
if (eventData.type === 'Conveyor' && eventData) {
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
const backendEventData = {
|
||||
type: 'Conveyor',
|
||||
points: eventData.points,
|
||||
speed: (eventData as Types.ConveyorEventsSchema)?.speed
|
||||
};
|
||||
|
||||
//SOCKET
|
||||
//REST
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// backendEventData
|
||||
// );
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
eventData: backendEventData,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
const newEventData: any = backendEventData;
|
||||
newEventData.modeluuid = newFloorItem.modeluuid;
|
||||
newEventData.modelName = newFloorItem.modelname;
|
||||
newEventData.position = newFloorItem.position;
|
||||
newEventData.rotation = [obj.rotation.x, obj.rotation.y, obj.rotation.z];
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).map(event =>
|
||||
event.modeluuid === newFloorItem.modeluuid
|
||||
? { ...event, ...newEventData }
|
||||
: event
|
||||
);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
// socket.emit("v2:model-asset:add", data);
|
||||
}
|
||||
} else {
|
||||
|
||||
|
||||
//REST
|
||||
|
||||
// await setFloorItemApi(
|
||||
// organization,
|
||||
// obj.uuid,
|
||||
// obj.userData.name,
|
||||
// [worldPosition.x, worldPosition.y, worldPosition.z],
|
||||
// { "x": obj.rotation.x, "y": obj.rotation.y, "z": obj.rotation.z },
|
||||
// obj.userData.modelId,
|
||||
// false,
|
||||
// true,
|
||||
// );
|
||||
|
||||
//SOCKET
|
||||
|
||||
const data = {
|
||||
organization,
|
||||
modeluuid: newFloorItem.modeluuid,
|
||||
modelname: newFloorItem.modelname,
|
||||
modelfileID: newFloorItem.modelfileID,
|
||||
position: newFloorItem.position,
|
||||
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z },
|
||||
isLocked: false,
|
||||
isVisible: true,
|
||||
socketId: socket.id,
|
||||
};
|
||||
|
||||
socket.emit("v2:model-asset:add", data);
|
||||
|
||||
}
|
||||
|
||||
itemsGroupRef.current.add(obj);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { useEffect, useMemo, useRef, useState } from "react";
|
|||
import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
|
||||
import { SelectionHelper } from "./selectionHelper";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useFloorItems, useSelectedAssets, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import { useFloorItems, useSelectedAssets, useSimulationPaths, useSocketStore, useToggleView } from "../../../../store/store";
|
||||
import BoundingBox from "./boundingBoxHelper";
|
||||
import { toast } from "react-toastify";
|
||||
// import { deleteFloorItem } from '../../../../services/factoryBuilder/assest/floorAsset/deleteFloorItemApi';
|
||||
|
@ -20,6 +20,7 @@ const SelectionControls: React.FC = () => {
|
|||
const itemsGroupRef = useRef<THREE.Group | undefined>(undefined);
|
||||
const selectionGroup = useRef() as Types.RefGroup;
|
||||
const { toggleView } = useToggleView();
|
||||
const { setSimulationPaths } = useSimulationPaths();
|
||||
const { selectedAssets, setSelectedAssets } = useSelectedAssets();
|
||||
const [movedObjects, setMovedObjects] = useState<THREE.Object3D[]>([]);
|
||||
const [rotatedObjects, setRotatedObjects] = useState<THREE.Object3D[]>([]);
|
||||
|
@ -239,6 +240,11 @@ const SelectionControls: React.FC = () => {
|
|||
}
|
||||
});
|
||||
|
||||
setSimulationPaths((prevEvents: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]) => {
|
||||
const updatedEvents = (prevEvents || []).filter(event => event.modeluuid !== selectedMesh.uuid);
|
||||
return updatedEvents;
|
||||
});
|
||||
|
||||
itemsGroupRef.current?.remove(selectedMesh);
|
||||
});
|
||||
|
||||
|
|
|
@ -93,13 +93,13 @@ export default function PostProcessing() {
|
|||
<Outline
|
||||
selection={[selectedActionSphere.point]}
|
||||
selectionLayer={10}
|
||||
width={750}
|
||||
width={1000}
|
||||
blendFunction={BlendFunction.ALPHA}
|
||||
edgeStrength={15}
|
||||
edgeStrength={10}
|
||||
resolutionScale={2}
|
||||
pulseSpeed={0}
|
||||
visibleEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||
hiddenEdgeColor={CONSTANTS.outlineConfig.assetSelectColor}
|
||||
visibleEdgeColor={0x6f42c1}
|
||||
hiddenEdgeColor={0x6f42c1}
|
||||
blur={true}
|
||||
xRay={true}
|
||||
/>
|
||||
|
@ -108,9 +108,9 @@ export default function PostProcessing() {
|
|||
<Outline
|
||||
selection={flattenChildren(selectedPath.group.children)}
|
||||
selectionLayer={10}
|
||||
width={750}
|
||||
width={1000}
|
||||
blendFunction={BlendFunction.ALPHA}
|
||||
edgeStrength={15}
|
||||
edgeStrength={10}
|
||||
resolutionScale={2}
|
||||
pulseSpeed={0}
|
||||
visibleEdgeColor={0x6f42c1}
|
||||
|
|
|
@ -10,76 +10,76 @@ function Behaviour() {
|
|||
useEffect(() => {
|
||||
const newPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[] = [];
|
||||
|
||||
floorItems.forEach((item: Types.FloorItemType) => {
|
||||
if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
|
||||
console.log('item: ', item);
|
||||
const point1Position = new THREE.Vector3(0, 0.85, 2.2);
|
||||
const middlePointPosition = new THREE.Vector3(0, 0.85, 0);
|
||||
const point2Position = new THREE.Vector3(0, 0.85, -2.2);
|
||||
// floorItems.forEach((item: Types.FloorItemType) => {
|
||||
// if (item.modelfileID === "672a090f80d91ac979f4d0bd") {
|
||||
// const point1Position = new THREE.Vector3(0, 0.85, 2.2);
|
||||
// const middlePointPosition = new THREE.Vector3(0, 0.85, 0);
|
||||
// const point2Position = new THREE.Vector3(0, 0.85, -2.2);
|
||||
|
||||
const point1UUID = THREE.MathUtils.generateUUID();
|
||||
const middlePointUUID = THREE.MathUtils.generateUUID();
|
||||
const point2UUID = THREE.MathUtils.generateUUID();
|
||||
// const point1UUID = THREE.MathUtils.generateUUID();
|
||||
// const middlePointUUID = THREE.MathUtils.generateUUID();
|
||||
// const point2UUID = THREE.MathUtils.generateUUID();
|
||||
|
||||
const newPath: Types.ConveyorEventsSchema = {
|
||||
modeluuid: item.modeluuid,
|
||||
modelName: item.modelname,
|
||||
type: 'Conveyor',
|
||||
points: [
|
||||
{
|
||||
uuid: point1UUID,
|
||||
position: [point1Position.x, point1Position.y, point1Position.z],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
triggers: [],
|
||||
connections: { source: { pathUUID: item.modeluuid, pointUUID: point1UUID }, targets: [] },
|
||||
},
|
||||
{
|
||||
uuid: middlePointUUID,
|
||||
position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
triggers: [],
|
||||
connections: { source: { pathUUID: item.modeluuid, pointUUID: middlePointUUID }, targets: [] },
|
||||
},
|
||||
{
|
||||
uuid: point2UUID,
|
||||
position: [point2Position.x, point2Position.y, point2Position.z],
|
||||
rotation: [0, 0, 0],
|
||||
actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
triggers: [],
|
||||
connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
|
||||
},
|
||||
],
|
||||
position: [...item.position],
|
||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||
speed: 'Inherit',
|
||||
};
|
||||
// const newPath: Types.ConveyorEventsSchema = {
|
||||
// modeluuid: item.modeluuid,
|
||||
// modelName: item.modelname,
|
||||
// type: 'Conveyor',
|
||||
// points: [
|
||||
// {
|
||||
// uuid: point1UUID,
|
||||
// position: [point1Position.x, point1Position.y, point1Position.z],
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: point1UUID }, targets: [] },
|
||||
// },
|
||||
// {
|
||||
// uuid: middlePointUUID,
|
||||
// position: [middlePointPosition.x, middlePointPosition.y, middlePointPosition.z],
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: middlePointUUID }, targets: [] },
|
||||
// },
|
||||
// {
|
||||
// uuid: point2UUID,
|
||||
// position: [point2Position.x, point2Position.y, point2Position.z],
|
||||
// rotation: [0, 0, 0],
|
||||
// actions: [{ uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Inherit', material: 'Inherit', delay: 'Inherit', spawnInterval: 'Inherit', isUsed: true }],
|
||||
// triggers: [],
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: point2UUID }, targets: [] },
|
||||
// },
|
||||
// ],
|
||||
// position: [...item.position],
|
||||
// rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||
// speed: 'Inherit',
|
||||
// };
|
||||
|
||||
newPaths.push(newPath);
|
||||
} else if (item.modelfileID === "67e3da19c2e8f37134526e6a") {
|
||||
const pointUUID = THREE.MathUtils.generateUUID();
|
||||
const pointPosition = new THREE.Vector3(0, 1.3, 0);
|
||||
// newPaths.push(newPath);
|
||||
// } else if (item.modelfileID === "67e3da19c2e8f37134526e6a") {
|
||||
// const pointUUID = THREE.MathUtils.generateUUID();
|
||||
// const pointPosition = new THREE.Vector3(0, 1.3, 0);
|
||||
|
||||
const newVehiclePath: Types.VehicleEventsSchema = {
|
||||
modeluuid: item.modeluuid,
|
||||
modelName: item.modelname,
|
||||
type: 'Vehicle',
|
||||
point: {
|
||||
uuid: pointUUID,
|
||||
position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
||||
actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
speed: 2,
|
||||
},
|
||||
position: [...item.position],
|
||||
};
|
||||
// const newVehiclePath: Types.VehicleEventsSchema = {
|
||||
// modeluuid: item.modeluuid,
|
||||
// modelName: item.modelname,
|
||||
// type: 'Vehicle',
|
||||
// point: {
|
||||
// uuid: pointUUID,
|
||||
// position: [pointPosition.x, pointPosition.y, pointPosition.z],
|
||||
// actions: { uuid: THREE.MathUtils.generateUUID(), name: 'Action 1', type: 'Start', start: {}, hitCount: 1, end: {}, buffer: 0 },
|
||||
// connections: { source: { pathUUID: item.modeluuid, pointUUID: pointUUID }, targets: [] },
|
||||
// speed: 2,
|
||||
// },
|
||||
// position: [...item.position],
|
||||
// };
|
||||
|
||||
newPaths.push(newVehiclePath);
|
||||
}
|
||||
});
|
||||
// newPaths.push(newVehiclePath);
|
||||
// }
|
||||
// });
|
||||
|
||||
setSimulationPaths(newPaths);
|
||||
// setSimulationPaths(newPaths);
|
||||
// console.log('floorItems: ', floorItems);
|
||||
}, [floorItems]);
|
||||
|
||||
return null;
|
||||
|
|
|
@ -14,12 +14,14 @@ import {
|
|||
} from "../../../store/store";
|
||||
import { useFrame, useThree } from "@react-three/fiber";
|
||||
import { useSubModuleStore } from "../../../store/useModuleStore";
|
||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
||||
|
||||
function PathCreation({
|
||||
pathsGroupRef,
|
||||
}: {
|
||||
pathsGroupRef: React.MutableRefObject<THREE.Group>;
|
||||
}) {
|
||||
const { isPlaying } = usePlayButtonStore();
|
||||
const { renderDistance } = useRenderDistance();
|
||||
const { setSubModule } = useSubModuleStore();
|
||||
const { setSelectedActionSphere, selectedActionSphere } =
|
||||
|
@ -66,7 +68,7 @@ function PathCreation({
|
|||
const distance = new THREE.Vector3(
|
||||
...group.position.toArray()
|
||||
).distanceTo(camera.position);
|
||||
group.visible = distance <= renderDistance;
|
||||
group.visible = ((distance <= renderDistance) && !isPlaying);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -193,7 +195,7 @@ function PathCreation({
|
|||
};
|
||||
|
||||
return (
|
||||
<group name="simulation-simulationPaths-group" ref={pathsGroupRef}>
|
||||
<group visible={!isPlaying} name="simulation-simulationPaths-group" ref={pathsGroupRef}>
|
||||
{simulationPaths.map((path) => {
|
||||
if (path.type === "Conveyor") {
|
||||
const points = path.points.map(
|
||||
|
|
|
@ -0,0 +1,916 @@
|
|||
// // animation-worker.js
|
||||
// // This web worker handles animation calculations off the main thread
|
||||
|
||||
// /* eslint-disable no-restricted-globals */
|
||||
// // The above disables the ESLint rule for this file since 'self' is valid in web workers
|
||||
|
||||
// // Store process data, animation states, and objects
|
||||
// let processes = [];
|
||||
// let animationStates = {};
|
||||
// let lastTimestamp = 0;
|
||||
|
||||
// // Message handler for communication with main thread
|
||||
// self.onmessage = function (event) {
|
||||
// const { type, data } = event.data;
|
||||
|
||||
// switch (type) {
|
||||
// case "initialize":
|
||||
// processes = data.processes;
|
||||
// initializeAnimationStates();
|
||||
// break;
|
||||
|
||||
// case "update":
|
||||
// const { timestamp, isPlaying } = data;
|
||||
// if (isPlaying) {
|
||||
// const delta = (timestamp - lastTimestamp) / 1000; // Convert to seconds
|
||||
// updateAnimations(delta, timestamp);
|
||||
// }
|
||||
// lastTimestamp = timestamp;
|
||||
// break;
|
||||
|
||||
// case "reset":
|
||||
// resetAnimations();
|
||||
// break;
|
||||
|
||||
// case "togglePlay":
|
||||
// // If resuming from pause, recalculate the time delta
|
||||
// lastTimestamp = data.timestamp;
|
||||
// break;
|
||||
// }
|
||||
// };
|
||||
|
||||
// // Initialize animation states for all processes
|
||||
// function initializeAnimationStates() {
|
||||
// animationStates = {};
|
||||
|
||||
// processes.forEach((process) => {
|
||||
// animationStates[process.id] = {
|
||||
// spawnedObjects: {},
|
||||
// nextSpawnTime: 0,
|
||||
// objectIdCounter: 0,
|
||||
// };
|
||||
// });
|
||||
|
||||
// // Send initial states back to main thread
|
||||
// self.postMessage({
|
||||
// type: "statesInitialized",
|
||||
// data: { animationStates },
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Reset all animations
|
||||
// function resetAnimations() {
|
||||
// initializeAnimationStates();
|
||||
// }
|
||||
|
||||
// // Find spawn point in a process
|
||||
// function findSpawnPoint(process) {
|
||||
// for (const path of process.paths || []) {
|
||||
// for (const point of path.points || []) {
|
||||
// const spawnAction = point.actions?.find(
|
||||
// (a) => a.isUsed && a.type === "Spawn"
|
||||
// );
|
||||
// if (spawnAction) {
|
||||
// return { point, path };
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// // Create a new spawned object with proper initial position
|
||||
// function createSpawnedObject(process, spawnPoint, currentTime, materialType) {
|
||||
// // Extract spawn position from the actual spawn point
|
||||
// const position = spawnPoint.point.position
|
||||
// ? [...spawnPoint.point.position]
|
||||
// : [0, 0, 0];
|
||||
|
||||
// // Get the path position and add it to the spawn point position
|
||||
// const pathPosition = spawnPoint.path.pathPosition || [0, 0, 0];
|
||||
// const absolutePosition = [
|
||||
// position[0] + pathPosition[0],
|
||||
// position[1] + pathPosition[1],
|
||||
// position[2] + pathPosition[2],
|
||||
// ];
|
||||
|
||||
// return {
|
||||
// id: `obj-${process.id}-${animationStates[process.id].objectIdCounter}`,
|
||||
// position: absolutePosition,
|
||||
// state: {
|
||||
// currentIndex: 0,
|
||||
// progress: 0,
|
||||
// isAnimating: true,
|
||||
// speed: process.speed || 1,
|
||||
// isDelaying: false,
|
||||
// delayStartTime: 0,
|
||||
// currentDelayDuration: 0,
|
||||
// delayComplete: false,
|
||||
// currentPathIndex: 0,
|
||||
// // Store the spawn point index to start animation from correct path point
|
||||
// spawnPointIndex: getPointIndexInProcess(process, spawnPoint.point),
|
||||
// },
|
||||
// visible: true,
|
||||
// materialType: materialType || "Default",
|
||||
// spawnTime: currentTime,
|
||||
// };
|
||||
// }
|
||||
|
||||
// // Get the index of a point within the process animation path
|
||||
// function getPointIndexInProcess(process, point) {
|
||||
// if (!process.paths) return 0;
|
||||
|
||||
// let cumulativePoints = 0;
|
||||
// for (const path of process.paths) {
|
||||
// for (let i = 0; i < (path.points?.length || 0); i++) {
|
||||
// if (path.points[i].uuid === point.uuid) {
|
||||
// return cumulativePoints + i;
|
||||
// }
|
||||
// }
|
||||
// cumulativePoints += path.points?.length || 0;
|
||||
// }
|
||||
|
||||
// return 0;
|
||||
// }
|
||||
|
||||
// // Get point data for current animation index
|
||||
// function getPointDataForAnimationIndex(process, index) {
|
||||
// if (!process.paths) return null;
|
||||
|
||||
// let cumulativePoints = 0;
|
||||
// for (const path of process.paths) {
|
||||
// const pointCount = path.points?.length || 0;
|
||||
|
||||
// if (index < cumulativePoints + pointCount) {
|
||||
// const pointIndex = index - cumulativePoints;
|
||||
// return path.points?.[pointIndex] || null;
|
||||
// }
|
||||
|
||||
// cumulativePoints += pointCount;
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// // Convert process paths to Vector3 format
|
||||
// function getProcessPath(process) {
|
||||
// return process.animationPath?.map((p) => ({ x: p.x, y: p.y, z: p.z })) || [];
|
||||
// }
|
||||
|
||||
// // Handle material swap for an object
|
||||
// function handleMaterialSwap(processId, objectId, materialType) {
|
||||
// const processState = animationStates[processId];
|
||||
// if (!processState || !processState.spawnedObjects[objectId]) return;
|
||||
|
||||
// processState.spawnedObjects[objectId].materialType = materialType;
|
||||
|
||||
// // Notify main thread about material change
|
||||
// self.postMessage({
|
||||
// type: "materialChanged",
|
||||
// data: {
|
||||
// processId,
|
||||
// objectId,
|
||||
// materialType,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Handle point actions for an object
|
||||
// function handlePointActions(processId, objectId, actions = [], currentTime) {
|
||||
// let shouldStopAnimation = false;
|
||||
// const processState = animationStates[processId];
|
||||
|
||||
// if (!processState || !processState.spawnedObjects[objectId]) return false;
|
||||
|
||||
// const objectState = processState.spawnedObjects[objectId];
|
||||
|
||||
// actions.forEach((action) => {
|
||||
// if (!action.isUsed) return;
|
||||
|
||||
// switch (action.type) {
|
||||
// case "Delay":
|
||||
// if (objectState.state.isDelaying) return;
|
||||
|
||||
// const delayDuration =
|
||||
// typeof action.delay === "number"
|
||||
// ? action.delay
|
||||
// : parseFloat(action.delay || "0");
|
||||
|
||||
// if (delayDuration > 0) {
|
||||
// objectState.state.isDelaying = true;
|
||||
// objectState.state.delayStartTime = currentTime;
|
||||
// objectState.state.currentDelayDuration = delayDuration;
|
||||
// objectState.state.delayComplete = false;
|
||||
// shouldStopAnimation = true;
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case "Despawn":
|
||||
// delete processState.spawnedObjects[objectId];
|
||||
// shouldStopAnimation = true;
|
||||
|
||||
// // Notify main thread about despawn
|
||||
// self.postMessage({
|
||||
// type: "objectDespawned",
|
||||
// data: {
|
||||
// processId,
|
||||
// objectId,
|
||||
// },
|
||||
// });
|
||||
// break;
|
||||
|
||||
// case "Swap":
|
||||
// if (action.material) {
|
||||
// handleMaterialSwap(processId, objectId, action.material);
|
||||
// }
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
|
||||
// return shouldStopAnimation;
|
||||
// }
|
||||
|
||||
// // Check if point has non-inherit actions
|
||||
// function hasNonInheritActions(actions = []) {
|
||||
// return actions.some((action) => action.isUsed && action.type !== "Inherit");
|
||||
// }
|
||||
|
||||
// // Calculate vector lerp (linear interpolation)
|
||||
// function lerpVectors(v1, v2, alpha) {
|
||||
// return {
|
||||
// x: v1.x + (v2.x - v1.x) * alpha,
|
||||
// y: v1.y + (v2.y - v1.y) * alpha,
|
||||
// z: v1.z + (v2.z - v1.z) * alpha,
|
||||
// };
|
||||
// }
|
||||
|
||||
// // Calculate vector distance
|
||||
// function distanceBetweenVectors(v1, v2) {
|
||||
// const dx = v2.x - v1.x;
|
||||
// const dy = v2.y - v1.y;
|
||||
// const dz = v2.z - v1.z;
|
||||
// return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
// }
|
||||
|
||||
// // Process spawn logic
|
||||
// function processSpawns(currentTime) {
|
||||
// processes.forEach((process) => {
|
||||
// const processState = animationStates[process.id];
|
||||
// if (!processState) return;
|
||||
|
||||
// const spawnPointData = findSpawnPoint(process);
|
||||
// if (!spawnPointData || !spawnPointData.point.actions) return;
|
||||
|
||||
// const spawnAction = spawnPointData.point.actions.find(
|
||||
// (a) => a.isUsed && a.type === "Spawn"
|
||||
// );
|
||||
// if (!spawnAction) return;
|
||||
|
||||
// const spawnInterval =
|
||||
// typeof spawnAction.spawnInterval === "number"
|
||||
// ? spawnAction.spawnInterval
|
||||
// : parseFloat(spawnAction.spawnInterval || "0");
|
||||
|
||||
// if (currentTime >= processState.nextSpawnTime) {
|
||||
// const newObject = createSpawnedObject(
|
||||
// process,
|
||||
// spawnPointData,
|
||||
// currentTime,
|
||||
// spawnAction.material || "Default"
|
||||
// );
|
||||
|
||||
// processState.spawnedObjects[newObject.id] = newObject;
|
||||
// processState.objectIdCounter++;
|
||||
// processState.nextSpawnTime = currentTime + spawnInterval;
|
||||
|
||||
// // Notify main thread about new object
|
||||
// self.postMessage({
|
||||
// type: "objectSpawned",
|
||||
// data: {
|
||||
// processId: process.id,
|
||||
// object: newObject,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// // Update all animations
|
||||
// function updateAnimations(delta, currentTime) {
|
||||
// // First handle spawning of new objects
|
||||
// processSpawns(currentTime);
|
||||
|
||||
// // Then animate existing objects
|
||||
// processes.forEach((process) => {
|
||||
// const processState = animationStates[process.id];
|
||||
// if (!processState) return;
|
||||
|
||||
// const path = getProcessPath(process);
|
||||
// if (path.length < 2) return;
|
||||
|
||||
// const updatedObjects = {};
|
||||
// let hasChanges = false;
|
||||
|
||||
// Object.entries(processState.spawnedObjects).forEach(([objectId, obj]) => {
|
||||
// if (!obj.visible || !obj.state.isAnimating) return;
|
||||
|
||||
// const stateRef = obj.state;
|
||||
|
||||
// // Use the spawnPointIndex as starting point if it's the initial movement
|
||||
// if (stateRef.currentIndex === 0 && stateRef.progress === 0) {
|
||||
// stateRef.currentIndex = stateRef.spawnPointIndex || 0;
|
||||
// }
|
||||
|
||||
// // Get current point data
|
||||
// const currentPointData = getPointDataForAnimationIndex(
|
||||
// process,
|
||||
// stateRef.currentIndex
|
||||
// );
|
||||
|
||||
// // Execute actions when arriving at a new point
|
||||
// if (stateRef.progress === 0 && currentPointData?.actions) {
|
||||
// const shouldStop = handlePointActions(
|
||||
// process.id,
|
||||
// objectId,
|
||||
// currentPointData.actions,
|
||||
// currentTime
|
||||
// );
|
||||
// if (shouldStop) return;
|
||||
// }
|
||||
|
||||
// // Handle delays
|
||||
// if (stateRef.isDelaying) {
|
||||
// if (
|
||||
// currentTime - stateRef.delayStartTime >=
|
||||
// stateRef.currentDelayDuration
|
||||
// ) {
|
||||
// stateRef.isDelaying = false;
|
||||
// stateRef.delayComplete = true;
|
||||
// } else {
|
||||
// updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
||||
// return; // Keep waiting
|
||||
// }
|
||||
// }
|
||||
|
||||
// const nextPointIdx = stateRef.currentIndex + 1;
|
||||
// const isLastPoint = nextPointIdx >= path.length;
|
||||
|
||||
// if (isLastPoint) {
|
||||
// if (currentPointData?.actions) {
|
||||
// const shouldStop = !hasNonInheritActions(currentPointData.actions);
|
||||
// if (shouldStop) {
|
||||
// // Reached the end of path with no more actions
|
||||
// delete processState.spawnedObjects[objectId];
|
||||
|
||||
// // Notify main thread to remove the object
|
||||
// self.postMessage({
|
||||
// type: "objectCompleted",
|
||||
// data: {
|
||||
// processId: process.id,
|
||||
// objectId,
|
||||
// },
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (!isLastPoint) {
|
||||
// const currentPos = path[stateRef.currentIndex];
|
||||
// const nextPos = path[nextPointIdx];
|
||||
// const distance = distanceBetweenVectors(currentPos, nextPos);
|
||||
// const movement = stateRef.speed * delta;
|
||||
|
||||
// // Update progress based on distance and speed
|
||||
// const oldProgress = stateRef.progress;
|
||||
// stateRef.progress += movement / distance;
|
||||
|
||||
// if (stateRef.progress >= 1) {
|
||||
// // Reached next point
|
||||
// stateRef.currentIndex = nextPointIdx;
|
||||
// stateRef.progress = 0;
|
||||
// stateRef.delayComplete = false;
|
||||
// obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
||||
// } else {
|
||||
// // Interpolate position
|
||||
// const lerpedPos = lerpVectors(currentPos, nextPos, stateRef.progress);
|
||||
// obj.position = [lerpedPos.x, lerpedPos.y, lerpedPos.z];
|
||||
// }
|
||||
|
||||
// // Only send updates when there's meaningful movement
|
||||
// if (Math.abs(oldProgress - stateRef.progress) > 0.01) {
|
||||
// hasChanges = true;
|
||||
// }
|
||||
// }
|
||||
|
||||
// updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
||||
// });
|
||||
|
||||
// // Update animation state with modified objects
|
||||
// if (Object.keys(updatedObjects).length > 0) {
|
||||
// processState.spawnedObjects = {
|
||||
// ...processState.spawnedObjects,
|
||||
// ...updatedObjects,
|
||||
// };
|
||||
|
||||
// // Only send position updates when there are meaningful changes
|
||||
// if (hasChanges) {
|
||||
// self.postMessage({
|
||||
// type: "positionsUpdated",
|
||||
// data: {
|
||||
// processId: process.id,
|
||||
// objects: updatedObjects,
|
||||
// },
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// animation-worker.js
|
||||
// This web worker handles animation calculations off the main thread
|
||||
|
||||
/* eslint-disable no-restricted-globals */
|
||||
// The above disables the ESLint rule for this file since 'self' is valid in web workers
|
||||
|
||||
// Store process data, animation states, and objects
|
||||
let processes = [];
|
||||
let animationStates = {};
|
||||
let lastTimestamp = 0;
|
||||
let debugMode = true;
|
||||
|
||||
// Logger function for debugging
|
||||
function log(...args) {
|
||||
if (debugMode) {
|
||||
self.postMessage({
|
||||
type: "debug",
|
||||
data: { message: args.join(' ') }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Message handler for communication with main thread
|
||||
self.onmessage = function (event) {
|
||||
const { type, data } = event.data;
|
||||
log(`Worker received message: ${type}`);
|
||||
|
||||
switch (type) {
|
||||
case "initialize":
|
||||
processes = data.processes;
|
||||
log(`Initialized with ${processes.length} processes`);
|
||||
initializeAnimationStates();
|
||||
break;
|
||||
|
||||
case "update":
|
||||
const { timestamp, isPlaying } = data;
|
||||
if (isPlaying) {
|
||||
const delta = lastTimestamp === 0 ? 0.016 : (timestamp - lastTimestamp) / 1000; // Convert to seconds
|
||||
updateAnimations(delta, timestamp);
|
||||
}
|
||||
lastTimestamp = timestamp;
|
||||
break;
|
||||
|
||||
case "reset":
|
||||
log("Resetting animations");
|
||||
resetAnimations();
|
||||
break;
|
||||
|
||||
case "togglePlay":
|
||||
// If resuming from pause, recalculate the time delta
|
||||
log(`Toggle play: ${data.isPlaying}`);
|
||||
lastTimestamp = data.timestamp;
|
||||
break;
|
||||
|
||||
case "setDebug":
|
||||
debugMode = data.enabled;
|
||||
log(`Debug mode: ${debugMode}`);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize animation states for all processes
|
||||
function initializeAnimationStates() {
|
||||
animationStates = {};
|
||||
|
||||
processes.forEach((process) => {
|
||||
if (!process || !process.id) {
|
||||
log("Invalid process found:", process);
|
||||
return;
|
||||
}
|
||||
|
||||
animationStates[process.id] = {
|
||||
spawnedObjects: {},
|
||||
nextSpawnTime: 0,
|
||||
objectIdCounter: 0,
|
||||
};
|
||||
});
|
||||
|
||||
// Send initial states back to main thread
|
||||
self.postMessage({
|
||||
type: "statesInitialized",
|
||||
data: { animationStates },
|
||||
});
|
||||
}
|
||||
|
||||
// Reset all animations
|
||||
function resetAnimations() {
|
||||
initializeAnimationStates();
|
||||
}
|
||||
|
||||
// Find spawn point in a process
|
||||
function findSpawnPoint(process) {
|
||||
if (!process || !process.paths) {
|
||||
log(`No paths found for process ${process?.id}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (const path of process.paths) {
|
||||
if (!path || !path.points) continue;
|
||||
|
||||
for (const point of path.points) {
|
||||
if (!point || !point.actions) continue;
|
||||
|
||||
const spawnAction = point.actions.find(
|
||||
(a) => a && a.isUsed && a.type === "Spawn"
|
||||
);
|
||||
if (spawnAction) {
|
||||
return { point, path };
|
||||
}
|
||||
}
|
||||
}
|
||||
log(`No spawn points found for process ${process.id}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create a new spawned object with proper initial position
|
||||
function createSpawnedObject(process, spawnPoint, currentTime, materialType) {
|
||||
// Extract spawn position from the actual spawn point
|
||||
const position = spawnPoint.point.position
|
||||
? [...spawnPoint.point.position]
|
||||
: [0, 0, 0];
|
||||
|
||||
// Get the path position and add it to the spawn point position
|
||||
const pathPosition = spawnPoint.path.pathPosition || [0, 0, 0];
|
||||
const absolutePosition = [
|
||||
position[0] + pathPosition[0],
|
||||
position[1] + pathPosition[1],
|
||||
position[2] + pathPosition[2],
|
||||
];
|
||||
|
||||
return {
|
||||
id: `obj-${process.id}-${animationStates[process.id].objectIdCounter}`,
|
||||
position: absolutePosition,
|
||||
state: {
|
||||
currentIndex: 0,
|
||||
progress: 0,
|
||||
isAnimating: true,
|
||||
speed: process.speed || 1,
|
||||
isDelaying: false,
|
||||
delayStartTime: 0,
|
||||
currentDelayDuration: 0,
|
||||
delayComplete: false,
|
||||
currentPathIndex: 0,
|
||||
// Store the spawn point index to start animation from correct path point
|
||||
spawnPointIndex: getPointIndexInProcess(process, spawnPoint.point),
|
||||
},
|
||||
visible: true,
|
||||
materialType: materialType || "Default",
|
||||
spawnTime: currentTime,
|
||||
};
|
||||
}
|
||||
|
||||
// Get the index of a point within the process animation path
|
||||
function getPointIndexInProcess(process, point) {
|
||||
if (!process.paths) return 0;
|
||||
|
||||
let cumulativePoints = 0;
|
||||
for (const path of process.paths) {
|
||||
for (let i = 0; i < (path.points?.length || 0); i++) {
|
||||
if (path.points[i].uuid === point.uuid) {
|
||||
return cumulativePoints + i;
|
||||
}
|
||||
}
|
||||
cumulativePoints += path.points?.length || 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get point data for current animation index
|
||||
function getPointDataForAnimationIndex(process, index) {
|
||||
if (!process.paths) return null;
|
||||
|
||||
let cumulativePoints = 0;
|
||||
for (const path of process.paths) {
|
||||
const pointCount = path.points?.length || 0;
|
||||
|
||||
if (index < cumulativePoints + pointCount) {
|
||||
const pointIndex = index - cumulativePoints;
|
||||
return path.points?.[pointIndex] || null;
|
||||
}
|
||||
|
||||
cumulativePoints += pointCount;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Convert process paths to Vector3 format
|
||||
function getProcessPath(process) {
|
||||
if (!process.animationPath) {
|
||||
log(`No animation path for process ${process.id}`);
|
||||
return [];
|
||||
}
|
||||
return process.animationPath.map((p) => ({ x: p.x, y: p.y, z: p.z })) || [];
|
||||
}
|
||||
|
||||
// Handle material swap for an object
|
||||
function handleMaterialSwap(processId, objectId, materialType) {
|
||||
const processState = animationStates[processId];
|
||||
if (!processState || !processState.spawnedObjects[objectId]) return;
|
||||
|
||||
processState.spawnedObjects[objectId].materialType = materialType;
|
||||
|
||||
// Notify main thread about material change
|
||||
self.postMessage({
|
||||
type: "materialChanged",
|
||||
data: {
|
||||
processId,
|
||||
objectId,
|
||||
materialType,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Handle point actions for an object
|
||||
function handlePointActions(processId, objectId, actions = [], currentTime) {
|
||||
let shouldStopAnimation = false;
|
||||
const processState = animationStates[processId];
|
||||
|
||||
if (!processState || !processState.spawnedObjects[objectId]) return false;
|
||||
|
||||
const objectState = processState.spawnedObjects[objectId];
|
||||
|
||||
actions.forEach((action) => {
|
||||
if (!action || !action.isUsed) return;
|
||||
|
||||
switch (action.type) {
|
||||
case "Delay":
|
||||
if (objectState.state.isDelaying) return;
|
||||
|
||||
const delayDuration =
|
||||
typeof action.delay === "number"
|
||||
? action.delay
|
||||
: parseFloat(action.delay || "0");
|
||||
|
||||
if (delayDuration > 0) {
|
||||
objectState.state.isDelaying = true;
|
||||
objectState.state.delayStartTime = currentTime;
|
||||
objectState.state.currentDelayDuration = delayDuration;
|
||||
objectState.state.delayComplete = false;
|
||||
shouldStopAnimation = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case "Despawn":
|
||||
delete processState.spawnedObjects[objectId];
|
||||
shouldStopAnimation = true;
|
||||
|
||||
// Notify main thread about despawn
|
||||
self.postMessage({
|
||||
type: "objectDespawned",
|
||||
data: {
|
||||
processId,
|
||||
objectId,
|
||||
},
|
||||
});
|
||||
break;
|
||||
|
||||
case "Swap":
|
||||
if (action.material) {
|
||||
handleMaterialSwap(processId, objectId, action.material);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return shouldStopAnimation;
|
||||
}
|
||||
|
||||
// Check if point has non-inherit actions
|
||||
function hasNonInheritActions(actions = []) {
|
||||
return actions.some((action) => action && action.isUsed && action.type !== "Inherit");
|
||||
}
|
||||
|
||||
// Calculate vector lerp (linear interpolation)
|
||||
function lerpVectors(v1, v2, alpha) {
|
||||
return {
|
||||
x: v1.x + (v2.x - v1.x) * alpha,
|
||||
y: v1.y + (v2.y - v1.y) * alpha,
|
||||
z: v1.z + (v2.z - v1.z) * alpha,
|
||||
};
|
||||
}
|
||||
|
||||
// Calculate vector distance
|
||||
function distanceBetweenVectors(v1, v2) {
|
||||
const dx = v2.x - v1.x;
|
||||
const dy = v2.y - v1.y;
|
||||
const dz = v2.z - v1.z;
|
||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
// Process spawn logic
|
||||
function processSpawns(currentTime) {
|
||||
processes.forEach((process) => {
|
||||
const processState = animationStates[process.id];
|
||||
if (!processState) return;
|
||||
|
||||
const spawnPointData = findSpawnPoint(process);
|
||||
if (!spawnPointData || !spawnPointData.point.actions) return;
|
||||
|
||||
const spawnAction = spawnPointData.point.actions.find(
|
||||
(a) => a.isUsed && a.type === "Spawn"
|
||||
);
|
||||
if (!spawnAction) return;
|
||||
|
||||
const spawnInterval =
|
||||
typeof spawnAction.spawnInterval === "number"
|
||||
? spawnAction.spawnInterval
|
||||
: parseFloat(spawnAction.spawnInterval || "2"); // Default to 2 seconds if not specified
|
||||
|
||||
if (currentTime >= processState.nextSpawnTime) {
|
||||
const newObject = createSpawnedObject(
|
||||
process,
|
||||
spawnPointData,
|
||||
currentTime,
|
||||
spawnAction.material || "Default"
|
||||
);
|
||||
|
||||
processState.spawnedObjects[newObject.id] = newObject;
|
||||
processState.objectIdCounter++;
|
||||
processState.nextSpawnTime = currentTime + spawnInterval;
|
||||
|
||||
log(`Spawned object ${newObject.id} for process ${process.id}`);
|
||||
|
||||
// Notify main thread about new object
|
||||
self.postMessage({
|
||||
type: "objectSpawned",
|
||||
data: {
|
||||
processId: process.id,
|
||||
object: newObject,
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Update all animations
|
||||
function updateAnimations(delta, currentTime) {
|
||||
// First handle spawning of new objects
|
||||
processSpawns(currentTime);
|
||||
|
||||
// Then animate existing objects
|
||||
processes.forEach((process) => {
|
||||
const processState = animationStates[process.id];
|
||||
if (!processState) return;
|
||||
|
||||
const path = getProcessPath(process);
|
||||
if (path.length < 2) {
|
||||
log(`Path too short for process ${process.id}, length: ${path.length}`);
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedObjects = {};
|
||||
let hasChanges = false;
|
||||
|
||||
Object.entries(processState.spawnedObjects).forEach(([objectId, obj]) => {
|
||||
if (!obj.visible || !obj.state.isAnimating) return;
|
||||
|
||||
const stateRef = obj.state;
|
||||
|
||||
// Use the spawnPointIndex as starting point if it's the initial movement
|
||||
if (stateRef.currentIndex === 0 && stateRef.progress === 0) {
|
||||
stateRef.currentIndex = stateRef.spawnPointIndex || 0;
|
||||
}
|
||||
|
||||
// Get current point data
|
||||
const currentPointData = getPointDataForAnimationIndex(
|
||||
process,
|
||||
stateRef.currentIndex
|
||||
);
|
||||
|
||||
// Execute actions when arriving at a new point
|
||||
if (stateRef.progress === 0 && currentPointData?.actions) {
|
||||
const shouldStop = handlePointActions(
|
||||
process.id,
|
||||
objectId,
|
||||
currentPointData.actions,
|
||||
currentTime
|
||||
);
|
||||
if (shouldStop) return;
|
||||
}
|
||||
|
||||
// Handle delays
|
||||
if (stateRef.isDelaying) {
|
||||
if (
|
||||
currentTime - stateRef.delayStartTime >=
|
||||
stateRef.currentDelayDuration
|
||||
) {
|
||||
stateRef.isDelaying = false;
|
||||
stateRef.delayComplete = true;
|
||||
} else {
|
||||
updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
||||
return; // Keep waiting
|
||||
}
|
||||
}
|
||||
|
||||
const nextPointIdx = stateRef.currentIndex + 1;
|
||||
const isLastPoint = nextPointIdx >= path.length;
|
||||
|
||||
if (isLastPoint) {
|
||||
if (currentPointData?.actions) {
|
||||
const shouldStop = !hasNonInheritActions(currentPointData.actions);
|
||||
if (shouldStop) {
|
||||
// Reached the end of path with no more actions
|
||||
delete processState.spawnedObjects[objectId];
|
||||
log(`Object ${objectId} completed path`);
|
||||
|
||||
// Notify main thread to remove the object
|
||||
self.postMessage({
|
||||
type: "objectCompleted",
|
||||
data: {
|
||||
processId: process.id,
|
||||
objectId,
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isLastPoint) {
|
||||
const currentPos = path[stateRef.currentIndex];
|
||||
const nextPos = path[nextPointIdx];
|
||||
const distance = distanceBetweenVectors(currentPos, nextPos);
|
||||
|
||||
// Ensure we don't divide by zero
|
||||
if (distance > 0) {
|
||||
const movement = stateRef.speed * delta;
|
||||
|
||||
// Update progress based on distance and speed
|
||||
const oldProgress = stateRef.progress;
|
||||
stateRef.progress += movement / distance;
|
||||
|
||||
if (stateRef.progress >= 1) {
|
||||
// Reached next point
|
||||
stateRef.currentIndex = nextPointIdx;
|
||||
stateRef.progress = 0;
|
||||
stateRef.delayComplete = false;
|
||||
obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
||||
} else {
|
||||
// Interpolate position
|
||||
const lerpedPos = lerpVectors(currentPos, nextPos, stateRef.progress);
|
||||
obj.position = [lerpedPos.x, lerpedPos.y, lerpedPos.z];
|
||||
}
|
||||
|
||||
// Only send updates when there's meaningful movement
|
||||
if (Math.abs(oldProgress - stateRef.progress) > 0.01) {
|
||||
hasChanges = true;
|
||||
}
|
||||
} else {
|
||||
// Skip to next point if distance is zero
|
||||
stateRef.currentIndex = nextPointIdx;
|
||||
stateRef.progress = 0;
|
||||
obj.position = [nextPos.x, nextPos.y, nextPos.z];
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
updatedObjects[objectId] = { ...obj, state: { ...stateRef } };
|
||||
});
|
||||
|
||||
// Update animation state with modified objects
|
||||
if (Object.keys(updatedObjects).length > 0) {
|
||||
processState.spawnedObjects = {
|
||||
...processState.spawnedObjects,
|
||||
...updatedObjects,
|
||||
};
|
||||
|
||||
// Only send position updates when there are meaningful changes
|
||||
if (hasChanges) {
|
||||
self.postMessage({
|
||||
type: "positionsUpdated",
|
||||
data: {
|
||||
processId: process.id,
|
||||
objects: updatedObjects,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
const Mesh: React.FC = () => {
|
||||
return <mesh></mesh>;
|
||||
};
|
||||
|
||||
export default Mesh;
|
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,7 @@ const ProcessContainer: React.FC = () => {
|
|||
<>
|
||||
<ProcessCreator onProcessesCreated={setProcesses} />
|
||||
{processes.length > 0 && <ProcessAnimator processes={processes} />}
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,3 +1,402 @@
|
|||
// import React, {
|
||||
// useEffect,
|
||||
// useMemo,
|
||||
// useState,
|
||||
// useCallback,
|
||||
// useRef,
|
||||
// } from "react";
|
||||
// import { useSimulationPaths } from "../../../store/store";
|
||||
// import * as THREE from "three";
|
||||
// import { useThree } from "@react-three/fiber";
|
||||
// import {
|
||||
// ConveyorEventsSchema,
|
||||
// VehicleEventsSchema,
|
||||
// } from "../../../types/world/worldTypes";
|
||||
|
||||
// // Type definitions
|
||||
// export interface PointAction {
|
||||
// uuid: string;
|
||||
// name: string;
|
||||
// type: string;
|
||||
// material: string;
|
||||
// delay: number | string;
|
||||
// spawnInterval: string | number;
|
||||
// isUsed: boolean;
|
||||
// }
|
||||
|
||||
// export interface PathPoint {
|
||||
// uuid: string;
|
||||
// position: [number, number, number];
|
||||
// actions: PointAction[];
|
||||
// connections: {
|
||||
// targets: Array<{ pathUUID: string }>;
|
||||
// };
|
||||
// }
|
||||
|
||||
// export interface SimulationPath {
|
||||
// modeluuid: string;
|
||||
// points: PathPoint[];
|
||||
// pathPosition: [number, number, number];
|
||||
// speed?: number;
|
||||
// }
|
||||
|
||||
// export interface Process {
|
||||
// id: string;
|
||||
// paths: SimulationPath[];
|
||||
// animationPath: THREE.Vector3[];
|
||||
// pointActions: PointAction[][];
|
||||
// speed: number;
|
||||
// }
|
||||
|
||||
// interface ProcessCreatorProps {
|
||||
// onProcessesCreated: (processes: Process[]) => void;
|
||||
// }
|
||||
|
||||
// // Convert event schemas to SimulationPath
|
||||
// function convertToSimulationPath(
|
||||
// path: ConveyorEventsSchema | VehicleEventsSchema
|
||||
// ): SimulationPath {
|
||||
// const { modeluuid } = path;
|
||||
|
||||
// // Simplified normalizeAction function that preserves exact original properties
|
||||
// const normalizeAction = (action: any): PointAction => {
|
||||
// return { ...action }; // Return exact copy with no modifications
|
||||
// };
|
||||
|
||||
// if (path.type === "Conveyor") {
|
||||
// return {
|
||||
// modeluuid,
|
||||
// points: path.points.map((point) => ({
|
||||
// uuid: point.uuid,
|
||||
// position: point.position,
|
||||
// actions: point.actions.map(normalizeAction), // Preserve exact actions
|
||||
// connections: {
|
||||
// targets: point.connections.targets.map((target) => ({
|
||||
// pathUUID: target.pathUUID,
|
||||
// })),
|
||||
// },
|
||||
// })),
|
||||
// pathPosition: path.position,
|
||||
// speed:
|
||||
// typeof path.speed === "string"
|
||||
// ? parseFloat(path.speed) || 1
|
||||
// : path.speed || 1,
|
||||
// };
|
||||
// } else {
|
||||
// return {
|
||||
// modeluuid,
|
||||
// points: [
|
||||
// {
|
||||
// uuid: path.point.uuid,
|
||||
// position: path.point.position,
|
||||
// actions: Array.isArray(path.point.actions)
|
||||
// ? path.point.actions.map(normalizeAction)
|
||||
// : [normalizeAction(path.point.actions)],
|
||||
// connections: {
|
||||
// targets: path.point.connections.targets.map((target) => ({
|
||||
// pathUUID: target.pathUUID,
|
||||
// })),
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// pathPosition: path.position,
|
||||
// speed: path.point.speed || 1,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Custom shallow comparison for arrays
|
||||
// const areArraysEqual = (a: any[], b: any[]) => {
|
||||
// if (a.length !== b.length) return false;
|
||||
// for (let i = 0; i < a.length; i++) {
|
||||
// if (a[i] !== b[i]) return false;
|
||||
// }
|
||||
// return true;
|
||||
// };
|
||||
|
||||
// // Helper function to create an empty process
|
||||
// const createEmptyProcess = (): Process => ({
|
||||
// id: `process-${Math.random().toString(36).substring(2, 11)}`,
|
||||
// paths: [],
|
||||
// animationPath: [],
|
||||
// pointActions: [],
|
||||
// speed: 1,
|
||||
// });
|
||||
|
||||
// // Enhanced connection checking function
|
||||
// function shouldReverseNextPath(
|
||||
// currentPath: SimulationPath,
|
||||
// nextPath: SimulationPath
|
||||
// ): boolean {
|
||||
// if (nextPath.points.length !== 3) return false;
|
||||
|
||||
// const currentLastPoint = currentPath.points[currentPath.points.length - 1];
|
||||
// const nextFirstPoint = nextPath.points[0];
|
||||
// const nextLastPoint = nextPath.points[nextPath.points.length - 1];
|
||||
|
||||
// // Check if current last connects to next last (requires reversal)
|
||||
// const connectsToLast = currentLastPoint.connections.targets.some(
|
||||
// (target) =>
|
||||
// target.pathUUID === nextPath.modeluuid &&
|
||||
// nextLastPoint.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
|
||||
// // Check if current last connects to next first (no reversal needed)
|
||||
// const connectsToFirst = currentLastPoint.connections.targets.some(
|
||||
// (target) =>
|
||||
// target.pathUUID === nextPath.modeluuid &&
|
||||
// nextFirstPoint.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
|
||||
// // Only reverse if connected to last point and not to first point
|
||||
// return connectsToLast && !connectsToFirst;
|
||||
// }
|
||||
|
||||
// // Updated path adjustment function
|
||||
// function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
|
||||
// if (paths.length < 2) return paths;
|
||||
|
||||
// const adjustedPaths = [...paths];
|
||||
|
||||
// for (let i = 0; i < adjustedPaths.length - 1; i++) {
|
||||
// const currentPath = adjustedPaths[i];
|
||||
// const nextPath = adjustedPaths[i + 1];
|
||||
|
||||
// if (shouldReverseNextPath(currentPath, nextPath)) {
|
||||
// const reversedPoints = [
|
||||
// nextPath.points[2],
|
||||
// nextPath.points[1],
|
||||
// nextPath.points[0],
|
||||
// ];
|
||||
|
||||
// adjustedPaths[i + 1] = {
|
||||
// ...nextPath,
|
||||
// points: reversedPoints,
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
// return adjustedPaths;
|
||||
// }
|
||||
|
||||
// // Main hook for process creation
|
||||
// export function useProcessCreation() {
|
||||
// const { scene } = useThree();
|
||||
// const [processes, setProcesses] = useState<Process[]>([]);
|
||||
|
||||
// const hasSpawnAction = useCallback((path: SimulationPath): boolean => {
|
||||
// return path.points.some((point) =>
|
||||
// point.actions.some((action) => action.type.toLowerCase() === "spawn")
|
||||
// );
|
||||
// }, []);
|
||||
|
||||
// const createProcess = useCallback(
|
||||
// (paths: SimulationPath[]): Process => {
|
||||
// if (!paths || paths.length === 0) {
|
||||
// return createEmptyProcess();
|
||||
// }
|
||||
|
||||
// const animationPath: THREE.Vector3[] = [];
|
||||
// const pointActions: PointAction[][] = [];
|
||||
// const processSpeed = paths[0]?.speed || 1;
|
||||
|
||||
// for (const path of paths) {
|
||||
// for (const point of path.points) {
|
||||
// const obj = scene.getObjectByProperty("uuid", point.uuid);
|
||||
// if (!obj) {
|
||||
// console.warn(`Object with UUID ${point.uuid} not found in scene`);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// const position = obj.getWorldPosition(new THREE.Vector3());
|
||||
// animationPath.push(position.clone());
|
||||
// pointActions.push(point.actions);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return {
|
||||
// id: `process-${Math.random().toString(36).substring(2, 11)}`,
|
||||
// paths,
|
||||
// animationPath,
|
||||
// pointActions,
|
||||
// speed: processSpeed,
|
||||
// };
|
||||
// },
|
||||
// [scene]
|
||||
// );
|
||||
|
||||
// const getAllConnectedPaths = useCallback(
|
||||
// (
|
||||
// initialPath: SimulationPath,
|
||||
// allPaths: SimulationPath[],
|
||||
// visited: Set<string> = new Set()
|
||||
// ): SimulationPath[] => {
|
||||
// const connectedPaths: SimulationPath[] = [];
|
||||
// const queue: SimulationPath[] = [initialPath];
|
||||
// visited.add(initialPath.modeluuid);
|
||||
|
||||
// const pathMap = new Map<string, SimulationPath>();
|
||||
// allPaths.forEach((path) => pathMap.set(path.modeluuid, path));
|
||||
|
||||
// while (queue.length > 0) {
|
||||
// const currentPath = queue.shift()!;
|
||||
// connectedPaths.push(currentPath);
|
||||
|
||||
// // Process outgoing connections
|
||||
// for (const point of currentPath.points) {
|
||||
// for (const target of point.connections.targets) {
|
||||
// if (!visited.has(target.pathUUID)) {
|
||||
// const targetPath = pathMap.get(target.pathUUID);
|
||||
// if (targetPath) {
|
||||
// visited.add(target.pathUUID);
|
||||
// queue.push(targetPath);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Process incoming connections
|
||||
// for (const [uuid, path] of pathMap) {
|
||||
// if (!visited.has(uuid)) {
|
||||
// const hasConnectionToCurrent = path.points.some((point) =>
|
||||
// point.connections.targets.some(
|
||||
// (t) => t.pathUUID === currentPath.modeluuid
|
||||
// )
|
||||
// );
|
||||
// if (hasConnectionToCurrent) {
|
||||
// visited.add(uuid);
|
||||
// queue.push(path);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return connectedPaths;
|
||||
// },
|
||||
// []
|
||||
// );
|
||||
|
||||
// const createProcessesFromPaths = useCallback(
|
||||
// (paths: SimulationPath[]): Process[] => {
|
||||
// if (!paths || paths.length === 0) return [];
|
||||
|
||||
// const visited = new Set<string>();
|
||||
// const processes: Process[] = [];
|
||||
// const pathMap = new Map<string, SimulationPath>();
|
||||
// paths.forEach((path) => pathMap.set(path.modeluuid, path));
|
||||
|
||||
// for (const path of paths) {
|
||||
// if (!visited.has(path.modeluuid) && hasSpawnAction(path)) {
|
||||
// const connectedPaths = getAllConnectedPaths(path, paths, visited);
|
||||
// const adjustedPaths = adjustPathPointsOrder(connectedPaths);
|
||||
// const process = createProcess(adjustedPaths);
|
||||
// processes.push(process);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return processes;
|
||||
// },
|
||||
// [createProcess, getAllConnectedPaths, hasSpawnAction]
|
||||
// );
|
||||
|
||||
// return {
|
||||
// processes,
|
||||
// createProcessesFromPaths,
|
||||
// setProcesses,
|
||||
// };
|
||||
// }
|
||||
|
||||
// const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
||||
// ({ onProcessesCreated }) => {
|
||||
// const { simulationPaths } = useSimulationPaths();
|
||||
// const { createProcessesFromPaths } = useProcessCreation();
|
||||
// const prevPathsRef = useRef<SimulationPath[]>([]);
|
||||
// const prevProcessesRef = useRef<Process[]>([]);
|
||||
|
||||
// const convertedPaths = useMemo((): SimulationPath[] => {
|
||||
// if (!simulationPaths) return [];
|
||||
// return simulationPaths.map((path) =>
|
||||
// convertToSimulationPath(
|
||||
// path as ConveyorEventsSchema | VehicleEventsSchema
|
||||
// )
|
||||
// );
|
||||
// }, [simulationPaths]);
|
||||
|
||||
// const pathsDependency = useMemo(() => {
|
||||
// if (!convertedPaths) return null;
|
||||
// return convertedPaths.map((path) => ({
|
||||
// id: path.modeluuid,
|
||||
// hasSpawn: path.points.some((p: PathPoint) =>
|
||||
// p.actions.some((a: PointAction) => a.type.toLowerCase() === "spawn")
|
||||
// ),
|
||||
// connections: path.points
|
||||
// .flatMap((p: PathPoint) =>
|
||||
// p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID)
|
||||
// )
|
||||
// .join(","),
|
||||
// }));
|
||||
// }, [convertedPaths]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (!convertedPaths || convertedPaths.length === 0) {
|
||||
// if (prevProcessesRef.current.length > 0) {
|
||||
// onProcessesCreated([]);
|
||||
// prevProcessesRef.current = [];
|
||||
// }
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (areArraysEqual(prevPathsRef.current, convertedPaths)) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// prevPathsRef.current = convertedPaths;
|
||||
// const newProcesses = createProcessesFromPaths(convertedPaths);
|
||||
|
||||
// // console.log("--- Action Types in Paths ---");
|
||||
// // convertedPaths.forEach((path) => {
|
||||
// // path.points.forEach((point) => {
|
||||
// // point.actions.forEach((action) => {
|
||||
// // console.log(
|
||||
// // `Path ${path.modeluuid}, Point ${point.uuid}: ${action.type}`
|
||||
// // );
|
||||
// // });
|
||||
// // });
|
||||
// // });
|
||||
// // console.log("New processes:", newProcesses);
|
||||
|
||||
// if (
|
||||
// newProcesses.length !== prevProcessesRef.current.length ||
|
||||
// !newProcesses.every(
|
||||
// (proc, i) =>
|
||||
// proc.paths.length === prevProcessesRef.current[i]?.paths.length &&
|
||||
// proc.paths.every(
|
||||
// (path, j) =>
|
||||
// path.modeluuid ===
|
||||
// prevProcessesRef.current[i]?.paths[j]?.modeluuid
|
||||
// )
|
||||
// )
|
||||
// ) {
|
||||
// onProcessesCreated(newProcesses);
|
||||
// // prevProcessesRef.current = newProcesses;
|
||||
// }
|
||||
// }, [
|
||||
// pathsDependency,
|
||||
// onProcessesCreated,
|
||||
// convertedPaths,
|
||||
// createProcessesFromPaths,
|
||||
// ]);
|
||||
|
||||
// return null;
|
||||
// }
|
||||
// );
|
||||
|
||||
// export default ProcessCreator;
|
||||
|
||||
import React, {
|
||||
useEffect,
|
||||
useMemo,
|
||||
|
@ -156,12 +555,38 @@ function shouldReverseNextPath(
|
|||
return connectsToLast && !connectsToFirst;
|
||||
}
|
||||
|
||||
// Check if a point has a spawn action
|
||||
function hasSpawnAction(point: PathPoint): boolean {
|
||||
return point.actions.some((action) => action.type.toLowerCase() === "spawn");
|
||||
}
|
||||
|
||||
// Ensure spawn point is always at the beginning of the path
|
||||
function ensureSpawnPointIsFirst(path: SimulationPath): SimulationPath {
|
||||
if (path.points.length !== 3) return path;
|
||||
|
||||
// If the third point has spawn action and first doesn't, reverse the array
|
||||
if (hasSpawnAction(path.points[2]) && !hasSpawnAction(path.points[0])) {
|
||||
return {
|
||||
...path,
|
||||
points: [...path.points].reverse(),
|
||||
};
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
// Updated path adjustment function
|
||||
function adjustPathPointsOrder(paths: SimulationPath[]): SimulationPath[] {
|
||||
if (paths.length < 2) return paths;
|
||||
if (paths.length < 1) return paths;
|
||||
|
||||
const adjustedPaths = [...paths];
|
||||
|
||||
// First ensure all paths have spawn points at the beginning
|
||||
for (let i = 0; i < adjustedPaths.length; i++) {
|
||||
adjustedPaths[i] = ensureSpawnPointIsFirst(adjustedPaths[i]);
|
||||
}
|
||||
|
||||
// Then handle connections between paths
|
||||
for (let i = 0; i < adjustedPaths.length - 1; i++) {
|
||||
const currentPath = adjustedPaths[i];
|
||||
const nextPath = adjustedPaths[i + 1];
|
||||
|
@ -326,13 +751,17 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
|||
);
|
||||
}, [simulationPaths]);
|
||||
|
||||
// Enhanced dependency tracking that includes action types
|
||||
const pathsDependency = useMemo(() => {
|
||||
if (!convertedPaths) return null;
|
||||
return convertedPaths.map((path) => ({
|
||||
id: path.modeluuid,
|
||||
hasSpawn: path.points.some((p: PathPoint) =>
|
||||
p.actions.some((a: PointAction) => a.type.toLowerCase() === "spawn")
|
||||
),
|
||||
// Track all action types for each point
|
||||
actionSignature: path.points
|
||||
.map((point, index) =>
|
||||
point.actions.map((action) => `${index}-${action.type}`).join("|")
|
||||
)
|
||||
.join(","),
|
||||
connections: path.points
|
||||
.flatMap((p: PathPoint) =>
|
||||
p.connections.targets.map((t: { pathUUID: string }) => t.pathUUID)
|
||||
|
@ -341,6 +770,7 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
|||
}));
|
||||
}, [convertedPaths]);
|
||||
|
||||
// Force process recreation when paths change
|
||||
useEffect(() => {
|
||||
if (!convertedPaths || convertedPaths.length === 0) {
|
||||
if (prevProcessesRef.current.length > 0) {
|
||||
|
@ -350,42 +780,16 @@ const ProcessCreator: React.FC<ProcessCreatorProps> = React.memo(
|
|||
return;
|
||||
}
|
||||
|
||||
if (areArraysEqual(prevPathsRef.current, convertedPaths)) {
|
||||
return;
|
||||
}
|
||||
|
||||
prevPathsRef.current = convertedPaths;
|
||||
// Always regenerate processes if the pathsDependency has changed
|
||||
// This ensures action type changes will be detected
|
||||
const newProcesses = createProcessesFromPaths(convertedPaths);
|
||||
prevPathsRef.current = convertedPaths;
|
||||
|
||||
// console.log("--- Action Types in Paths ---");
|
||||
// convertedPaths.forEach((path) => {
|
||||
// path.points.forEach((point) => {
|
||||
// point.actions.forEach((action) => {
|
||||
// console.log(
|
||||
// `Path ${path.modeluuid}, Point ${point.uuid}: ${action.type}`
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// console.log("New processes:", newProcesses);
|
||||
|
||||
if (
|
||||
newProcesses.length !== prevProcessesRef.current.length ||
|
||||
!newProcesses.every(
|
||||
(proc, i) =>
|
||||
proc.paths.length === prevProcessesRef.current[i]?.paths.length &&
|
||||
proc.paths.every(
|
||||
(path, j) =>
|
||||
path.modeluuid ===
|
||||
prevProcessesRef.current[i]?.paths[j]?.modeluuid
|
||||
)
|
||||
)
|
||||
) {
|
||||
onProcessesCreated(newProcesses);
|
||||
// prevProcessesRef.current = newProcesses;
|
||||
}
|
||||
// Always update processes when action types change
|
||||
onProcessesCreated(newProcesses);
|
||||
prevProcessesRef.current = newProcesses;
|
||||
}, [
|
||||
pathsDependency,
|
||||
pathsDependency, // This now includes action types
|
||||
onProcessesCreated,
|
||||
convertedPaths,
|
||||
createProcessesFromPaths,
|
||||
|
|
|
@ -19,7 +19,7 @@ function Simulation() {
|
|||
const [processes, setProcesses] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('simulationPaths: ', simulationPaths);
|
||||
console.log('simulationPaths: ', simulationPaths);
|
||||
}, [simulationPaths]);
|
||||
|
||||
// useEffect(() => {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
|
||||
|
||||
export const setEventApi = async (
|
||||
organization: string,
|
||||
modeluuid: string,
|
||||
eventData: any
|
||||
) => {
|
||||
try {
|
||||
const body: any = { organization, modeluuid, eventData };
|
||||
|
||||
const response = await fetch(`${url_Backend_dwinzo}/api/v2/eventDataUpdate`, {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to set or update Floor Item");
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
throw new Error(error.message);
|
||||
} else {
|
||||
throw new Error("An unknown error occurred");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -30,7 +30,6 @@ export const setFloorItemApi = async (
|
|||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('result: ', result);
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
|
|
|
@ -343,14 +343,21 @@ export const useSelectedPath = create<any>((set: any) => ({
|
|||
interface SimulationPathsStore {
|
||||
simulationPaths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[];
|
||||
setSimulationPaths: (
|
||||
paths: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]
|
||||
paths:
|
||||
| (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]
|
||||
| ((prev: (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[]
|
||||
) => (Types.ConveyorEventsSchema | Types.VehicleEventsSchema)[])
|
||||
) => void;
|
||||
}
|
||||
|
||||
export const useSimulationPaths = create<SimulationPathsStore>((set) => ({
|
||||
simulationPaths: [],
|
||||
setSimulationPaths: (paths) => set({ simulationPaths: paths }),
|
||||
}));
|
||||
setSimulationPaths: (paths) =>
|
||||
set((state) => ({
|
||||
simulationPaths:
|
||||
typeof paths === "function" ? paths(state.simulationPaths) : paths,
|
||||
})),
|
||||
}))
|
||||
|
||||
export const useIsConnecting = create<any>((set: any) => ({
|
||||
isConnecting: false,
|
||||
|
|
Loading…
Reference in New Issue