Refactor asset model handling and event data management

- Removed redundant data structure in handleModelLoad function.
- Introduced eventData object to encapsulate event-related information for different asset types (Conveyor, Vehicle, ArmBot, StaticMachine).
- Updated socket emission to include complete data with eventData.
- Enhanced copy-paste and duplication controls to maintain eventData integrity during object duplication.
- Integrated event data updates in move and rotate controls to reflect changes in the simulation state.
- Improved PointsCreator component to handle rotation for event groups.
- Updated handleAddEventToProduct function to support event data management.
- Enhanced product management to fetch existing products from the server and handle new product creation.
- Added new types for eventData in worldTypes and simulationTypes for better type safety.
- Refactored IndexedDB utility functions for cleaner code.
This commit is contained in:
Jerald-Golden-B 2025-04-29 19:15:17 +05:30
parent ea53af62c4
commit 882c81a385
22 changed files with 1379 additions and 1209 deletions

View File

@ -1,6 +1,5 @@
import React, { useEffect, useState } from "react";
import {
useSelectedAsset,
useSelectedEventData,
useSelectedEventSphere,
useSelectedProduct,
@ -13,19 +12,17 @@ import MachineMechanics from "./mechanics/machineMechanics";
import StorageMechanics from "./mechanics/storageMechanics";
import { AddIcon } from "../../../../icons/ExportCommonIcons";
import { handleAddEventToProduct } from "../../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useEventsStore } from "../../../../../store/simulation/useEventsStore";
const EventProperties: React.FC = () => {
const { selectedEventData } = useSelectedEventData();
const { getEventByModelUuid } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(
null
);
const [currentEventData, setCurrentEventData] = useState<EventsSchema | null>(null);
const [assetType, setAssetType] = useState<string | null>(null);
const { products, addEvent } = useProductStore();
const { selectedEventSphere } = useSelectedEventSphere();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
useEffect(() => {
const event = getCurrentEventData();
setCurrentEventData(event);
@ -96,17 +93,15 @@ const EventProperties: React.FC = () => {
{products.map((product) => (
<li key={product.productId}>
<button
onClick={() =>
onClick={() => {
if (selectedEventData) {
handleAddEventToProduct({
selectedAsset,
event: useEventsStore.getState().getEventByModelUuid(selectedEventData?.data.modelUuid),
addEvent,
selectedProduct: {
productId: product.productId,
productName: product.productName,
},
clearSelectedAsset,
selectedProduct,
})
}
}}
>
<AddIcon />
{product.productName}
@ -116,7 +111,8 @@ const EventProperties: React.FC = () => {
</ul>
</div>
</div>
)}
)
}
{!selectedEventSphere && (
<div className="no-event-selected">
<p>
@ -125,7 +121,7 @@ const EventProperties: React.FC = () => {
</p>
</div>
)}
</div>
</div >
);
};

View File

@ -8,20 +8,13 @@ import SwapAction from "../actions/SwapAction";
import SpawnAction from "../actions/SpawnAction";
import DefaultAction from "../actions/DefaultAction";
import Trigger from "../trigger/Trigger";
import {
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ActionsList from "../components/ActionsList";
function ConveyorMechanics() {
const [activeOption, setActiveOption] = useState<
"default" | "spawn" | "swap" | "delay" | "despawn"
>("default");
const [selectedPointData, setSelectedPointData] = useState<
ConveyorPointSchema | undefined
>();
const [activeOption, setActiveOption] = useState<"default" | "spawn" | "swap" | "delay" | "despawn">("default");
const [selectedPointData, setSelectedPointData] = useState<ConveyorPointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
@ -35,14 +28,7 @@ function ConveyorMechanics() {
) as ConveyorPointSchema | undefined;
if (point && "action" in point) {
setSelectedPointData(point);
setActiveOption(
point.action.actionType as
| "default"
| "spawn"
| "swap"
| "delay"
| "despawn"
);
setActiveOption(point.action.actionType as | "default" | "spawn" | "swap" | "delay" | "despawn");
}
}
}, [selectedProduct, selectedEventData, getPointByUuid]);
@ -56,12 +42,7 @@ function ConveyorMechanics() {
const handleActionTypeChange = (option: string) => {
if (!selectedEventData || !selectedPointData) return;
const validOption = option as
| "default"
| "spawn"
| "swap"
| "delay"
| "despawn";
const validOption = option as | "default" | "spawn" | "swap" | "delay" | "despawn";
setActiveOption(validOption);
updateAction(selectedPointData.action.actionUuid, {
@ -106,8 +87,7 @@ function ConveyorMechanics() {
};
// Get current values from store
const currentSpeed =
selectedEventData?.data.type === "transfer"
const currentSpeed = selectedEventData?.data.type === "transfer"
? selectedEventData.data.speed.toString()
: "0.5";
@ -146,7 +126,7 @@ function ConveyorMechanics() {
defaultValue={"0.5"}
max={10}
activeOption="m/s"
onClick={() => {}}
onClick={() => { }}
onChange={handleSpeedChange}
/>
</div>
@ -167,11 +147,7 @@ function ConveyorMechanics() {
</div>
<div className="selected-actions-list">
<LabledDropdown
defaultOption={
selectedPointData
? selectedPointData.action.actionType
: "default"
}
defaultOption={selectedPointData ? selectedPointData.action.actionType : "default"}
options={availableActions.options}
onSelect={handleActionTypeChange}
/>

View File

@ -2,21 +2,14 @@ import { useEffect, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import {
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import ProcessAction from "../actions/ProcessAction";
import ActionsList from "../components/ActionsList";
function MachineMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "process">(
"default"
);
const [selectedPointData, setSelectedPointData] = useState<
MachinePointSchema | undefined
>();
const [activeOption, setActiveOption] = useState<"default" | "process">("default");
const [selectedPointData, setSelectedPointData] = useState<MachinePointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();

View File

@ -3,27 +3,18 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import {
useSelectedEventData,
useSelectedProduct,
useSelectedAction,
} from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedEventData, useSelectedProduct, useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
import ActionsList from "../components/ActionsList";
function RoboticArmMechanics() {
const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">(
"default"
);
const [selectedPointData, setSelectedPointData] = useState<
RoboticArmPointSchema | undefined
>();
const [activeOption, setActiveOption] = useState<"default" | "pickAndPlace">("default");
const [selectedPointData, setSelectedPointData] = useState<RoboticArmPointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateEvent, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();
const { selectedAction, setSelectedAction, clearSelectedAction } =
useSelectedAction();
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
useEffect(() => {
if (selectedEventData) {
@ -34,9 +25,7 @@ function RoboticArmMechanics() {
) as RoboticArmPointSchema | undefined;
if (point?.actions) {
setSelectedPointData(point);
setActiveOption(
point.actions[0].actionType as "default" | "pickAndPlace"
);
setActiveOption(point.actions[0].actionType as "default" | "pickAndPlace");
if (point.actions.length > 0 && !selectedAction.actionId) {
setSelectedAction(
point.actions[0].actionUuid,
@ -47,14 +36,7 @@ function RoboticArmMechanics() {
} else {
clearSelectedAction();
}
}, [
clearSelectedAction,
getPointByUuid,
selectedAction.actionId,
selectedEventData,
selectedProduct,
setSelectedAction,
]);
}, [clearSelectedAction, getPointByUuid, selectedAction.actionId, selectedEventData, selectedProduct, setSelectedAction,]);
const handleRenameAction = (newName: string) => {
if (!selectedAction.actionId) return;
@ -62,9 +44,7 @@ function RoboticArmMechanics() {
if (selectedPointData) {
const updatedActions = selectedPointData.actions.map((action) =>
action.actionUuid === selectedAction.actionId
? { ...action, actionName: newName }
: action
action.actionUuid === selectedAction.actionId ? { ...action, actionName: newName } : action
);
setSelectedPointData({
...selectedPointData,
@ -87,10 +67,7 @@ function RoboticArmMechanics() {
updateAction(selectedAction.actionId, {
process: {
startPoint: [x, y, z] as [number, number, number],
endPoint:
selectedPointData.actions.find(
(a) => a.actionUuid === selectedAction.actionId
)?.process.endPoint || null,
endPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.endPoint || null,
},
});
};
@ -101,10 +78,7 @@ function RoboticArmMechanics() {
updateAction(selectedAction.actionId, {
process: {
startPoint:
selectedPointData.actions.find(
(a) => a.actionUuid === selectedAction.actionId
)?.process.startPoint || null,
startPoint: selectedPointData.actions.find((a) => a.actionUuid === selectedAction.actionId)?.process.startPoint || null,
endPoint: [x, y, z] as [number, number, number],
},
});
@ -115,14 +89,12 @@ function RoboticArmMechanics() {
options: ["pickAndPlace"],
};
const currentSpeed =
selectedEventData?.data.type === "roboticArm"
const currentSpeed = selectedEventData?.data.type === "roboticArm"
? selectedEventData.data.speed.toString()
: "0.5";
const currentAction = selectedPointData?.actions.find(
(a) => a.actionUuid === selectedAction.actionId
);
const currentAction = selectedPointData?.actions.find((a) => a.actionUuid === selectedAction.actionId);
const currentPickPoint = currentAction?.process.startPoint
? `${currentAction.process.startPoint[0]},${currentAction.process.startPoint[1]},${currentAction.process.startPoint[2]}`
: "";
@ -145,7 +117,7 @@ function RoboticArmMechanics() {
defaultValue={"0.5"}
max={10}
activeOption="m/s"
onClick={() => {}}
onClick={() => { }}
onChange={handleSpeedChange}
/>
</div>
@ -170,7 +142,7 @@ function RoboticArmMechanics() {
<LabledDropdown
defaultOption={activeOption}
options={availableActions.options}
onSelect={() => {}}
onSelect={() => { }}
disabled={true}
/>
<PickAndPlaceAction

View File

@ -2,21 +2,14 @@ import { useEffect, useState } from "react";
import RenameInput from "../../../../../ui/inputs/RenameInput";
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
import Trigger from "../trigger/Trigger";
import {
useSelectedEventData,
useSelectedProduct,
} from "../../../../../../store/simulation/useSimulationStore";
import { useSelectedEventData, useSelectedProduct } from "../../../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../../../store/simulation/useProductStore";
import StorageAction from "../actions/StorageAction";
import ActionsList from "../components/ActionsList";
function StorageMechanics() {
const [activeOption, setActiveOption] = useState<
"default" | "store" | "spawn"
>("default");
const [selectedPointData, setSelectedPointData] = useState<
StoragePointSchema | undefined
>();
const [activeOption, setActiveOption] = useState<"default" | "store" | "spawn">("default");
const [selectedPointData, setSelectedPointData] = useState<StoragePointSchema | undefined>();
const { selectedEventData } = useSelectedEventData();
const { getPointByUuid, updateAction } = useProductStore();
const { selectedProduct } = useSelectedProduct();

View File

@ -1,4 +1,4 @@
import React, { useEffect, useRef } from "react";
import React, { useRef } from "react";
import {
AddIcon,
ArrowIcon,
@ -15,8 +15,9 @@ import { useProductStore } from "../../../../store/simulation/useProductStore";
import { generateUUID } from "three/src/math/MathUtils";
import RenderOverlay from "../../../templates/Overlay";
import EditWidgetOption from "../../../ui/menu/EditWidgetOption";
import { upsertProductOrEventApi } from "../../../../services/simulation/UpsertProductOrEventApi";
import { handleAddEventToProduct } from "../../../../modules/simulation/events/points/functions/handleAddEventToProduct";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { deleteEventDataApi } from "../../../../services/simulation/deleteEventDataApi";
interface Event {
pathName: string;
@ -36,15 +37,9 @@ const List: React.FC<ListProps> = ({ val }) => {
const Simulations: React.FC = () => {
const productsContainerRef = useRef<HTMLDivElement>(null);
const {
products,
addProduct,
removeProduct,
renameProduct,
addEvent,
removeEvent,
} = useProductStore();
const { products, addProduct, removeProduct, renameProduct, addEvent, removeEvent, } = useProductStore();
const { selectedProduct, setSelectedProduct } = useSelectedProduct();
const { getEventByModelUuid } = useEventsStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const handleAddProduct = () => {
@ -84,6 +79,13 @@ const Simulations: React.FC = () => {
const handleRemoveEventFromProduct = () => {
if (selectedAsset) {
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
deleteEventDataApi({
productId: selectedProduct.productId,
modelUuid: selectedAsset.modelUuid,
organization: organization
});
removeEvent(selectedProduct.productId, selectedAsset.modelUuid);
clearSelectedAsset();
}
@ -93,8 +95,7 @@ const Simulations: React.FC = () => {
(product) => product.productId === selectedProduct.productId
);
const events: Event[] =
selectedProductData?.eventDatas.map((event) => ({
const events: Event[] = selectedProductData?.eventDatas.map((event) => ({
pathName: event.modelName,
})) || [];
@ -118,8 +119,7 @@ const Simulations: React.FC = () => {
{products.map((product, index) => (
<div
key={product.productId}
className={`list-item ${
selectedProduct.productId === product.productId
className={`list-item ${selectedProduct.productId === product.productId
? "active"
: ""
}`}
@ -197,10 +197,10 @@ const Simulations: React.FC = () => {
onClick={(option) => {
if (option === "Add to Product") {
handleAddEventToProduct({
selectedAsset,
event: getEventByModelUuid(selectedAsset.modelUuid),
addEvent,
selectedProduct,
clearSelectedAsset,
clearSelectedAsset
});
} else {
handleRemoveEventFromProduct();

View File

@ -156,7 +156,7 @@ function processLoadedModel(
const model = gltf.clone();
model.uuid = item.modeluuid;
model.scale.set(...CONSTANTS.assetConfig.defaultScaleBeforeGsap);
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid };
model.userData = { name: item.modelname, modelId: item.modelfileID, modeluuid: item.modeluuid, eventData: item.eventData };
model.position.set(...item.position);
model.rotation.set(item.rotation.x, item.rotation.y, item.rotation.z);
@ -170,9 +170,9 @@ function processLoadedModel(
}
});
itemsGroup?.current?.add(model);
if (item.eventData) {
setFloorItems((prevItems) => [
...(prevItems || []),
{
@ -183,18 +183,11 @@ function processLoadedModel(
modelfileID: item.modelfileID,
isLocked: item.isLocked,
isVisible: item.isVisible,
eventData: item.eventData,
},
]);
if (item.modelfileID === "a1ee92554935007b10b3eb05") {
const data = PointsCalculator(
'Vehicle',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
if (item.eventData.type === "vehicle") {
const vehicleEvent: VehicleEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
@ -204,9 +197,9 @@ function processLoadedModel(
type: "vehicle",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Vehicle Action",
@ -220,15 +213,7 @@ function processLoadedModel(
}
};
addEvent(vehicleEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
const data = PointsCalculator(
'Conveyor',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
} else if (item.eventData.type === "Conveyor") {
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
@ -237,10 +222,10 @@ function processLoadedModel(
state: "idle",
type: "transfer",
speed: 1,
points: data.points.map((point: THREE.Vector3, index: number) => ({
uuid: THREE.MathUtils.generateUUID(),
position: [point.x, point.y, point.z],
rotation: [0, 0, 0],
points: item.eventData.points?.map((point: any, index: number) => ({
uuid: point.uuid || THREE.MathUtils.generateUUID(),
position: [point.position[0], point.position[1], point.position[2]],
rotation: [point.rotation[0], point.rotation[1], point.rotation[2]],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index + 1}`,
@ -251,117 +236,10 @@ function processLoadedModel(
spawnCount: 1,
triggers: []
}
}))
})) || [],
};
addEvent(ConveyorEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
// const data = PointsCalculator(
// 'Conveyor',
// gltf.clone(),
// new THREE.Vector3(...model.rotation)
// );
// if (!data || !data.points) return;
// const points: ConveyorPointSchema[] = data.points.map((point: THREE.Vector3, index: number) => {
// const actionUuid = THREE.MathUtils.generateUUID();
// return {
// uuid: THREE.MathUtils.generateUUID(),
// position: [point.x, point.y, point.z],
// rotation: [0, 0, 0],
// action: {
// actionUuid,
// actionName: `Action ${index}`,
// actionType: 'default',
// material: 'inherit',
// delay: 0,
// spawnInterval: 5,
// spawnCount: 1,
// triggers: []
// }
// };
// });
// points.forEach((point, index) => {
// if (index < points.length - 1) {
// const nextPoint = points[index + 1];
// point.action.triggers.push({
// triggerUuid: THREE.MathUtils.generateUUID(),
// triggerName: `Trigger 1`,
// triggerType: "onComplete",
// delay: 0,
// triggeredAsset: {
// triggeredModel: {
// modelName: item.modelname,
// modelUuid: item.modeluuid
// },
// triggeredPoint: {
// pointName: `Point ${index + 1}`,
// pointUuid: nextPoint.uuid
// },
// triggeredAction: {
// actionName: nextPoint.action.actionName,
// actionUuid: nextPoint.action.actionUuid
// }
// }
// });
// }
// });
// const ConveyorEvent: ConveyorEventSchema = {
// modelUuid: item.modeluuid,
// modelName: item.modelname,
// position: item.position,
// rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
// state: "idle",
// type: "transfer",
// speed: 1,
// points
// };
// addEvent(ConveyorEvent);
} else if (item.modelfileID === "7dc04e36882e4debbc1a8e3d") {
const data = PointsCalculator(
'Conveyor',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
position: item.position,
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "transfer",
speed: 1,
points: data.points.map((point: THREE.Vector3, index: number) => ({
uuid: THREE.MathUtils.generateUUID(),
position: [point.x, point.y, point.z],
rotation: [0, 0, 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action ${index}`,
actionType: 'default',
material: 'inherit',
delay: 0,
spawnInterval: 5,
spawnCount: 1,
triggers: []
}
}))
};
addEvent(ConveyorEvent);
} else if (item.modelfileID === "29dee78715ad5b853f5c346d") {
const data = PointsCalculator(
'StaticMachine',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
} else if (item.eventData.type === "StaticMachine") {
const machineEvent: MachineEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
@ -370,9 +248,9 @@ function processLoadedModel(
state: "idle",
type: "machine",
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Process Action",
@ -384,15 +262,7 @@ function processLoadedModel(
}
};
addEvent(machineEvent);
} else if (item.modelfileID === "52e6681fbb743a890d96c914") {
const data = PointsCalculator(
'ArmBot',
gltf.clone(),
new THREE.Vector3(...model.rotation)
);
if (!data || !data.points) return;
} else if (item.eventData.type === "ArmBot") {
const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: item.modeluuid,
modelName: item.modelname,
@ -402,9 +272,9 @@ function processLoadedModel(
type: "roboticArm",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [data.points[0].x, data.points[0].y, data.points[0].z],
rotation: [0, 0, 0],
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
rotation: [item.eventData.point?.rotation[0] || 0, item.eventData.point?.rotation[1] || 0, item.eventData.point?.rotation[2] || 0],
actions: [
{
actionUuid: THREE.MathUtils.generateUUID(),
@ -420,6 +290,21 @@ function processLoadedModel(
}
};
addEvent(roboticArmEvent);
}
} 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,
},
]);
}
gsap.to(model.position, { y: item.position[1], duration: 1.5, ease: 'power2.out' });

View File

@ -164,18 +164,6 @@ async function handleModelLoad(
// 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
};
if (selectedItem.type) {
const data = PointsCalculator(
selectedItem.type,
@ -185,6 +173,10 @@ async function handleModelLoad(
if (!data || !data.points) return;
const eventData: any = {
type: selectedItem.type,
};
if (selectedItem.type === "Conveyor") {
const ConveyorEvent: ConveyorEventSchema = {
modelUuid: newFloorItem.modeluuid,
@ -209,8 +201,14 @@ async function handleModelLoad(
triggers: []
}
}))
}
};
addEvent(ConveyorEvent);
eventData.points = ConveyorEvent.points.map(point => ({
uuid: point.uuid,
position: point.position,
rotation: point.rotation
}));
} else if (selectedItem.type === "Vehicle") {
const vehicleEvent: VehicleEventSchema = {
modelUuid: newFloorItem.modeluuid,
@ -237,6 +235,12 @@ async function handleModelLoad(
}
};
addEvent(vehicleEvent);
eventData.point = {
uuid: vehicleEvent.point.uuid,
position: vehicleEvent.point.position,
rotation: vehicleEvent.point.rotation
};
} else if (selectedItem.type === "ArmBot") {
const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: newFloorItem.modeluuid,
@ -265,6 +269,13 @@ async function handleModelLoad(
}
};
addEvent(roboticArmEvent);
console.log('roboticArmEvent: ', roboticArmEvent);
eventData.point = {
uuid: roboticArmEvent.point.uuid,
position: roboticArmEvent.point.position,
rotation: roboticArmEvent.point.rotation
};
} else if (selectedItem.type === "StaticMachine") {
const machineEvent: MachineEventSchema = {
modelUuid: newFloorItem.modeluuid,
@ -288,8 +299,53 @@ async function handleModelLoad(
}
};
addEvent(machineEvent);
eventData.point = {
uuid: machineEvent.point.uuid,
position: machineEvent.point.position,
rotation: machineEvent.point.rotation
};
}
}
const completeData = {
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,
eventData: eventData
};
model.userData.eventData = eventData;
newFloorItem.eventData = eventData;
setFloorItems((prevItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
return updatedItems;
});
socket.emit("v2:model-asset:add", completeData);
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!"); } });
} else {
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];
@ -301,6 +357,7 @@ async function handleModelLoad(
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!"); } });
}
}
export default addAssetModel;

View File

@ -65,6 +65,7 @@ const FloorItemsGroup = ({ itemsGroup, hoveredDeletableFloorItem, AttachedObject
};
getFloorAssets(organization).then((data) => {
console.log('data: ', data);
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;

View File

@ -137,6 +137,38 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
if (itemsGroupRef.current) {
let updatedEventData = null;
if (obj.userData.eventData) {
updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData));
updatedEventData.modelUuid = THREE.MathUtils.generateUUID();
if (updatedEventData.type === "Conveyor" && updatedEventData.points) {
updatedEventData.points = updatedEventData.points.map((point: any) => ({
...point,
uuid: THREE.MathUtils.generateUUID()
}));
}
else if (updatedEventData.type === "Vehicle" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "ArmBot" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
}
const newFloorItem: Types.FloorItemType = {
modeluuid: obj.uuid,
modelname: obj.userData.name,
@ -144,7 +176,8 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
isLocked: false,
isVisible: true
isVisible: true,
eventData: updatedEventData
};
setFloorItems((prevItems: Types.FloorItems) => {
@ -181,11 +214,18 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
isLocked: false,
isVisible: true,
socketId: socket.id,
eventData: updatedEventData
};
socket.emit("v2:model-asset:add", data);
obj.userData.modeluuid = newFloorItem.modeluuid;
obj.userData = {
name: newFloorItem.modelname,
modelId: newFloorItem.modelfileID,
modeluuid: newFloorItem.modeluuid,
eventData: updatedEventData
};
itemsGroupRef.current.add(obj);
}
});
@ -205,7 +245,7 @@ const CopyPasteControls = ({ itemsGroupRef, copiedObjects, setCopiedObjects, pas
setSelectedAssets([]);
}
return null; // No visible output, but the component handles copy-paste functionality
return null;
};
export default CopyPasteControls;

View File

@ -115,6 +115,38 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
if (itemsGroupRef.current) {
let updatedEventData = null;
if (obj.userData.eventData) {
updatedEventData = JSON.parse(JSON.stringify(obj.userData.eventData));
updatedEventData.modelUuid = THREE.MathUtils.generateUUID();
if (updatedEventData.type === "Conveyor" && updatedEventData.points) {
updatedEventData.points = updatedEventData.points.map((point: any) => ({
...point,
uuid: THREE.MathUtils.generateUUID()
}));
}
else if (updatedEventData.type === "Vehicle" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "ArmBot" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
else if (updatedEventData.type === "StaticMachine" && updatedEventData.point) {
updatedEventData.point = {
...updatedEventData.point,
uuid: THREE.MathUtils.generateUUID()
};
}
}
const newFloorItem: Types.FloorItemType = {
modeluuid: obj.uuid,
modelname: obj.userData.name,
@ -122,7 +154,8 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: { x: obj.rotation.x, y: obj.rotation.y, z: obj.rotation.z, },
isLocked: false,
isVisible: true
isVisible: true,
eventData: updatedEventData
};
setFloorItems((prevItems: Types.FloorItems) => {
@ -159,11 +192,18 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
isLocked: false,
isVisible: true,
socketId: socket.id,
eventData: updatedEventData
};
socket.emit("v2:model-asset:add", data);
obj.userData.modeluuid = newFloorItem.modeluuid;
obj.userData = {
name: newFloorItem.modelname,
modelId: newFloorItem.modelfileID,
modeluuid: newFloorItem.modeluuid,
eventData: updatedEventData
};
itemsGroupRef.current.add(obj);
}
});
@ -183,7 +223,7 @@ const DuplicationControls = ({ itemsGroupRef, duplicatedObjects, setDuplicatedOb
setSelectedAssets([]);
}
return null; // This component does not render any UI
return null;
};
export default DuplicationControls;

View File

@ -1,11 +1,14 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useFloorItems, useSelectedAssets, 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";
import { detectModifierKeys } from "../../../../utils/shortcutkeys/detectModifierKeys";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, rotatedObjects, setRotatedObjects, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@ -176,6 +179,24 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
isVisible: true
};
if (obj.userData.eventData) {
const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid);
const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid);
if (eventData) {
useEventsStore.getState().updateEvent(obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
if (productData) {
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
}
setFloorItems((prevItems: Types.FloorItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
@ -234,7 +255,7 @@ function MoveControls({ movedObjects, setMovedObjects, itemsGroupRef, copiedObje
setSelectedAssets([]);
}
return null; // No need to return anything, as this component is used for its side effects
return null;
}
export default MoveControls

View File

@ -1,11 +1,13 @@
import * as THREE from "three";
import { useEffect, useMemo, useRef, useState } from "react";
import { useEffect, useMemo, useRef } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { useFloorItems, useSelectedAssets, 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";
import { setFloorItemApi } from "../../../../services/factoryBuilder/assest/floorAsset/setFloorItemApi";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMovedObjects, itemsGroupRef, copiedObjects, setCopiedObjects, pastedObjects, setpastedObjects, duplicatedObjects, setDuplicatedObjects, selectionGroup, boundingBoxRef }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
@ -177,6 +179,24 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
isVisible: true
};
if (obj.userData.eventData) {
const eventData = useEventsStore.getState().getEventByModelUuid(obj.userData.modeluuid);
const productData = useProductStore.getState().getEventByModelUuid(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid);
if (eventData) {
useEventsStore.getState().updateEvent(obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
if (productData) {
useProductStore.getState().updateEvent(useSelectedProduct.getState().selectedProduct.productId, obj.userData.modeluuid, {
position: [worldPosition.x, worldPosition.y, worldPosition.z],
rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
})
}
}
setFloorItems((prevItems: Types.FloorItems) => {
const updatedItems = [...(prevItems || []), newFloorItem];
localStorage.setItem("FloorItems", JSON.stringify(updatedItems));
@ -235,7 +255,7 @@ function RotateControls({ rotatedObjects, setRotatedObjects, movedObjects, setMo
setSelectedAssets([]);
}
return null; // No need to return anything, as this component is used for its side effects
return null;
}
export default RotateControls

View File

@ -62,7 +62,7 @@ function PointsCreator() {
{events.map((event, i) => {
if (event.type === 'transfer') {
return (
<group key={i} position={new THREE.Vector3(...event.position)}>
<group key={i} position={[...event.position]} rotation={[...event.rotation]} >
{event.points.map((point, j) => (
<mesh
name='Event-Sphere'
@ -78,6 +78,7 @@ function PointsCreator() {
}}
key={`${i}-${j}`}
position={new THREE.Vector3(...point.position)}
// rotation={new THREE.Euler(...point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: point.uuid }}
>
<sphereGeometry args={[0.1, 16, 16]} />
@ -88,7 +89,7 @@ function PointsCreator() {
);
} else if (event.type === 'vehicle') {
return (
<group key={i} position={new THREE.Vector3(...event.position)}>
<group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh
name='Event-Sphere'
uuid={event.point.uuid}
@ -102,6 +103,7 @@ function PointsCreator() {
setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
>
<sphereGeometry args={[0.1, 16, 16]} />
@ -111,7 +113,7 @@ function PointsCreator() {
);
} else if (event.type === 'roboticArm') {
return (
<group key={i} position={new THREE.Vector3(...event.position)}>
<group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh
name='Event-Sphere'
uuid={event.point.uuid}
@ -125,6 +127,7 @@ function PointsCreator() {
setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
>
<sphereGeometry args={[0.1, 16, 16]} />
@ -134,7 +137,7 @@ function PointsCreator() {
);
} else if (event.type === 'machine') {
return (
<group key={i} position={new THREE.Vector3(...event.position)}>
<group key={i} position={[...event.position]} rotation={[...event.rotation]} >
<mesh
name='Event-Sphere'
uuid={event.point.uuid}
@ -148,6 +151,7 @@ function PointsCreator() {
setTransformMode(null);
}}
position={new THREE.Vector3(...event.point.position)}
// rotation={new THREE.Euler(...event.point.rotation)}
userData={{ modelUuid: event.modelUuid, pointUuid: event.point.uuid }}
>
<sphereGeometry args={[0.1, 16, 16]} />

View File

@ -1,28 +1,38 @@
import { upsertProductOrEventApi } from "../../../../../services/simulation/UpsertProductOrEventApi";
interface HandleAddEventToProductParams {
selectedAsset: any; // Replace `any` with specific type if you have it
addEvent: (productId: string, asset: any) => void;
event: EventsSchema | undefined;
addEvent: (productId: string, event: EventsSchema) => void;
selectedProduct: {
productId: string;
productName: string;
// Add other fields if needed
};
clearSelectedAsset: () => void;
}
clearSelectedAsset?: () => void;
}
export const handleAddEventToProduct = ({
selectedAsset,
event,
addEvent,
selectedProduct,
clearSelectedAsset,
clearSelectedAsset
}: HandleAddEventToProductParams) => {
console.log('selectedProduct: ', selectedProduct);
if (selectedAsset) {
addEvent(selectedProduct.productId, selectedAsset);
// upsertProductOrEventApi({
// productName: selectedProduct.productName,
// productId: selectedProduct.productId,
// eventDatas: selectedAsset
// });
if (event && selectedProduct.productId) {
addEvent(selectedProduct.productId, event);
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
upsertProductOrEventApi({
productName: selectedProduct.productName,
productId: selectedProduct.productId,
organization: organization,
eventDatas: event
}).then((data) => {
// console.log(data);
})
if (clearSelectedAsset) {
clearSelectedAsset();
}
}
};

View File

@ -7,28 +7,27 @@ import { upsertProductOrEventApi } from '../../../services/simulation/UpsertProd
import { getAllProductsApi } from '../../../services/simulation/getallProductsApi';
function Products() {
const { products, addProduct } = useProductStore();
const { products, addProduct, setProducts } = useProductStore();
const { setSelectedProduct } = useSelectedProduct();
useEffect(() => {
if (products.length === 0) {
const email = localStorage.getItem('email')
const organization = (email!.split("@")[1]).split(".")[0];
getAllProductsApi(organization).then((data) => {
if (data.length === 0) {
const id = THREE.MathUtils.generateUUID();
const name = 'Product 1';
addProduct(name, id);
// upsertProductOrEventApi({ productName: name, productId: id }).then((data) => {
// console.log('data: ', data);
// });
upsertProductOrEventApi({ productName: name, productId: id, organization: organization })
setSelectedProduct(id, name);
} else {
setProducts(data);
setSelectedProduct(data[0].productId, data[0].productName);
}
}, [products])
})
}, [])
useEffect(() => {
// const email = localStorage.getItem('email')
// const organization = (email!.split("@")[1]).split(".")[0];
// console.log(organization);
// getAllProductsApi(organization).then((data) => {
// console.log('data: ', data);
// })
}, [])
return (

View File

@ -19,11 +19,11 @@ function Simulation() {
const { products } = useProductStore();
useEffect(() => {
// console.log('events: ', events);
console.log('events: ', events);
}, [events])
useEffect(() => {
// console.log('products: ', products);
console.log('products: ', products);
}, [products])
return (

View File

@ -1,19 +1,85 @@
import { useEffect } from "react";
import { useEffect, useRef, useState } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
import { useSubModuleStore } from "../../../../store/useModuleStore";
import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
import { useProductStore } from "../../../../store/simulation/useProductStore";
import { useEventsStore } from "../../../../store/simulation/useEventsStore";
import { useSelectedProduct } from "../../../../store/simulation/useSimulationStore";
import { handleAddEventToProduct } from "../../events/points/functions/handleAddEventToProduct";
interface ConnectionLine {
id: string;
start: THREE.Vector3;
end: THREE.Vector3;
mid: THREE.Vector3;
trigger: TriggerSchema;
}
function TriggerConnector() {
const { gl, raycaster, scene } = useThree();
const { subModule } = useSubModuleStore();
const { getPointByUuid, getIsEventInProduct } = useProductStore();
const { products, getPointByUuid, getIsEventInProduct, getActionByUuid, addTrigger, addEvent, getEventByModelUuid } = useProductStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
const { selectedProduct } = useSelectedProduct();
useEffect(() => {
const [firstSelectedPoint, setFirstSelectedPoint] = useState<{
productId: string;
modelUuid: string;
pointUuid: string;
actionUuid?: string;
} | null>(null);
const [connections, setConnections] = useState<ConnectionLine[]>([]);
useEffect(() => {
const newConnections: ConnectionLine[] = [];
products.forEach(product => {
product.eventDatas.forEach(event => {
if ('points' in event) {
event.points.forEach(point => {
if ('action' in point && point.action?.triggers) {
point.action.triggers.forEach(trigger => {
if (trigger.triggeredAsset) {
const targetPoint = getPointByUuid(
product.productId,
trigger.triggeredAsset.triggeredModel.modelUuid,
trigger.triggeredAsset.triggeredPoint.pointUuid
);
if (targetPoint) {
const startPos = new THREE.Vector3(...point.position);
const endPos = new THREE.Vector3(...targetPoint.position);
const midPos = new THREE.Vector3()
.addVectors(startPos, endPos)
.multiplyScalar(0.5)
.add(new THREE.Vector3(0, 2, 0));
newConnections.push({
id: `${point.uuid}-${targetPoint.uuid}-${trigger.triggerUuid}`,
start: startPos,
end: endPos,
mid: midPos,
trigger
});
}
}
});
}
});
}
});
});
setConnections(newConnections);
}, [products]);
useEffect(() => {
console.log('connections: ', connections);
}, connections)
useEffect(() => {
const canvasElement = gl.domElement;
let drag = false;
@ -44,37 +110,114 @@ function TriggerConnector() {
const handleRightClick = (evt: MouseEvent) => {
if (drag) return;
evt.preventDefault();
const canvasElement = gl.domElement;
if (!canvasElement) return;
let intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0 && intersects[0]?.object?.parent?.parent?.position && intersects[0]?.object?.parent?.parent?.scale && intersects[0]?.object?.parent?.parent?.rotation) {
let currentObject = intersects[0].object;
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length === 0) return;
if (currentObject && currentObject.name === 'Event-Sphere') {
const currentObject = intersects[0].object;
if (!currentObject || currentObject.name !== 'Event-Sphere') return;
const isInProduct = getIsEventInProduct(
const modelUuid = currentObject.userData.modelUuid;
const pointUuid = currentObject.userData.pointUuid;
if (selectedProduct && getIsEventInProduct(selectedProduct.productId, modelUuid)) {
const point = getPointByUuid(
selectedProduct.productId,
currentObject.userData.modelUuid
modelUuid,
pointUuid
);
// You left Here
if (!point) return;
if (isInProduct) {
let actionUuid: string | undefined;
if ('action' in point && point.action) {
actionUuid = point.action.actionUuid;
} else if ('actions' in point && point.actions.length === 1) {
actionUuid = point.actions[0].actionUuid;
}
const event = getPointByUuid(
if (!firstSelectedPoint) {
setFirstSelectedPoint({
productId: selectedProduct.productId,
modelUuid,
pointUuid,
actionUuid
});
} else {
const trigger: TriggerSchema = {
triggerUuid: THREE.MathUtils.generateUUID(),
triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)}${pointUuid.slice(0, 4)}`,
triggerType: "onComplete",
delay: 0,
triggeredAsset: {
triggeredModel: {
modelName: currentObject.parent?.parent?.name || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
pointName: currentObject.name,
pointUuid: pointUuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
actionUuid: actionUuid
} : null
}
};
if (firstSelectedPoint.actionUuid) {
addTrigger(firstSelectedPoint.actionUuid, trigger);
}
setFirstSelectedPoint(null);
}
} else if (!getIsEventInProduct(selectedProduct.productId, modelUuid) && firstSelectedPoint) {
handleAddEventToProduct({
event: useEventsStore.getState().getEventByModelUuid(modelUuid),
addEvent,
selectedProduct,
})
const point = getPointByUuid(
selectedProduct.productId,
currentObject.userData.modelUuid,
currentObject.userData.pointUuid
modelUuid,
pointUuid
);
console.log('event: ', event);
} else {
}
if (!point) return;
let actionUuid: string | undefined;
if ('action' in point && point.action) {
actionUuid = point.action.actionUuid;
} else if ('actions' in point && point.actions.length === 1) {
actionUuid = point.actions[0].actionUuid;
}
} else {
const trigger: TriggerSchema = {
triggerUuid: THREE.MathUtils.generateUUID(),
triggerName: `Trigger ${firstSelectedPoint.pointUuid.slice(0, 4)}${pointUuid.slice(0, 4)}`,
triggerType: "onComplete",
delay: 0,
triggeredAsset: {
triggeredModel: {
modelName: currentObject.parent?.parent?.name || 'Unknown',
modelUuid: modelUuid
},
triggeredPoint: {
pointName: currentObject.name,
pointUuid: pointUuid
},
triggeredAction: actionUuid ? {
actionName: getActionByUuid(selectedProduct.productId, actionUuid)?.actionName || 'Action',
actionUuid: actionUuid
} : null
}
};
if (firstSelectedPoint.actionUuid) {
addTrigger(firstSelectedPoint.actionUuid, trigger);
}
setFirstSelectedPoint(null);
}
};
@ -92,12 +235,12 @@ function TriggerConnector() {
canvasElement.removeEventListener('contextmenu', handleRightClick);
};
}, [gl, subModule]);
}, [gl, subModule, selectedProduct, firstSelectedPoint]);
return (
<>
</>
)
);
}
export default TriggerConnector
export default TriggerConnector;

View File

@ -6,6 +6,7 @@ type ProductsStore = {
// Product-level actions
addProduct: (productName: string, productId: string) => void;
setProducts: (products: productsSchema) => void;
removeProduct: (productId: string) => void;
updateProduct: (productId: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void;
@ -78,6 +79,12 @@ export const useProductStore = create<ProductsStore>()(
});
},
setProducts: (products) => {
set((state) => {
state.products = products;
});
},
removeProduct: (productId) => {
set((state) => {
state.products = state.products.filter(p => p.productId !== productId);

View File

@ -14,7 +14,7 @@ interface TriggerSchema {
triggeredAsset: {
triggeredModel: { modelName: string, modelUuid: string };
triggeredPoint: { pointName: string, pointUuid: string };
triggeredAction: { actionName: string, actionUuid: string };
triggeredAction: { actionName: string, actionUuid: string } | null;
} | null;
}

View File

@ -196,6 +196,19 @@ export type FloorItemType = {
modelfileID: string;
isLocked: boolean;
isVisible: boolean;
eventData?: {
type: string;
point?: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
}
points?: {
uuid: string;
position: [number, number, number];
rotation: [number, number, number];
}[];
}
};
// Array of floor items for managing multiple objects on the floor