pillar Jig half way completed
This commit is contained in:
@@ -17,255 +17,242 @@ import SkeletonUI from "../../templates/SkeletonUI";
|
|||||||
// -------------------------------------
|
// -------------------------------------
|
||||||
|
|
||||||
interface AssetProp {
|
interface AssetProp {
|
||||||
filename: string;
|
filename: string;
|
||||||
thumbnail?: string;
|
thumbnail?: string;
|
||||||
category: string;
|
category: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
tags: string;
|
tags: string;
|
||||||
url?: string;
|
url?: string;
|
||||||
uploadDate?: number;
|
uploadDate?: number;
|
||||||
isArchieve?: boolean;
|
isArchieve?: boolean;
|
||||||
animated?: boolean;
|
animated?: boolean;
|
||||||
price?: number;
|
price?: number;
|
||||||
CreatedBy?: string;
|
CreatedBy?: string;
|
||||||
}
|
}
|
||||||
interface CategoryListProp {
|
interface CategoryListProp {
|
||||||
assetImage?: string;
|
assetImage?: string;
|
||||||
assetName?: string;
|
assetName?: string;
|
||||||
categoryImage: string;
|
categoryImage: string;
|
||||||
category: string;
|
category: string;
|
||||||
}
|
}
|
||||||
const Assets: React.FC = () => {
|
const Assets: React.FC = () => {
|
||||||
const { setSelectedItem } = useSelectedItem();
|
const { setSelectedItem } = useSelectedItem();
|
||||||
const [searchValue, setSearchValue] = useState<string>("");
|
const [searchValue, setSearchValue] = useState<string>("");
|
||||||
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
|
||||||
const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
|
const [categoryAssets, setCategoryAssets] = useState<AssetProp[]>([]);
|
||||||
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[]>([]);
|
const [filtereredAssets, setFiltereredAssets] = useState<AssetProp[]>([]);
|
||||||
const [categoryList, setCategoryList] = useState<CategoryListProp[]>([]);
|
const [categoryList, setCategoryList] = useState<CategoryListProp[]>([]);
|
||||||
const [isLoading, setisLoading] = useState<boolean>(false); // Loading state for assets
|
const [isLoading, setisLoading] = useState<boolean>(false); // Loading state for assets
|
||||||
|
|
||||||
const handleSearchChange = (value: string) => {
|
const handleSearchChange = (value: string) => {
|
||||||
const searchTerm = value.toLowerCase();
|
const searchTerm = value.toLowerCase();
|
||||||
setSearchValue(value);
|
setSearchValue(value);
|
||||||
if (searchTerm.trim() === "" && !selectedCategory) {
|
if (searchTerm.trim() === "" && !selectedCategory) {
|
||||||
setCategoryAssets([]);
|
setCategoryAssets([]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const filteredModels = filtereredAssets?.filter((model) => {
|
const filteredModels = filtereredAssets?.filter((model) => {
|
||||||
if (!model?.tags || !model?.filename || !model?.category) return false;
|
if (!model?.tags || !model?.filename || !model?.category) return false;
|
||||||
if (searchTerm.startsWith(":") && searchTerm.length > 1) {
|
if (searchTerm.startsWith(":") && searchTerm.length > 1) {
|
||||||
const tagSearchTerm = searchTerm.slice(1);
|
const tagSearchTerm = searchTerm.slice(1);
|
||||||
return model.tags.toLowerCase().includes(tagSearchTerm);
|
return model.tags.toLowerCase().includes(tagSearchTerm);
|
||||||
} else if (selectedCategory) {
|
} else if (selectedCategory) {
|
||||||
return (
|
return (
|
||||||
model.category
|
model.category
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(selectedCategory.toLowerCase()) &&
|
.includes(selectedCategory.toLowerCase()) &&
|
||||||
model.filename.toLowerCase().includes(searchTerm)
|
model.filename.toLowerCase().includes(searchTerm)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return model.filename.toLowerCase().includes(searchTerm);
|
return model.filename.toLowerCase().includes(searchTerm);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setCategoryAssets(filteredModels);
|
setCategoryAssets(filteredModels);
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const filteredAssets = async () => {
|
|
||||||
try {
|
|
||||||
const filt = await fetchAssets();
|
|
||||||
setFiltereredAssets(filt);
|
|
||||||
} catch {
|
|
||||||
echo.error("Filter asset not found");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
filteredAssets();
|
|
||||||
}, [categoryAssets]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCategoryList([
|
const filteredAssets = async () => {
|
||||||
{ category: "Fenestration", categoryImage: feneration },
|
try {
|
||||||
{ category: "Vehicles", categoryImage: vehicle },
|
const filt = await fetchAssets();
|
||||||
{ category: "Workstation", categoryImage: workStation },
|
setFiltereredAssets(filt);
|
||||||
{ category: "Machines", categoryImage: machines },
|
} catch {
|
||||||
{ category: "Workers", categoryImage: worker },
|
echo.error("Filter asset not found");
|
||||||
{ category: "Storage", categoryImage: storage },
|
|
||||||
{ category: "Safety", categoryImage: safety },
|
|
||||||
{ category: "Office", categoryImage: office },
|
|
||||||
]);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const fetchCategoryAssets = async (asset: any) => {
|
|
||||||
setisLoading(true);
|
|
||||||
setSelectedCategory(asset);
|
|
||||||
try {
|
|
||||||
const res = await getCategoryAsset(asset);
|
|
||||||
setCategoryAssets(res);
|
|
||||||
setFiltereredAssets(res);
|
|
||||||
setisLoading(false); // End loading
|
|
||||||
// eslint-disable-next-line
|
|
||||||
} catch (error) {
|
|
||||||
echo.error("failed to fetch assets");
|
|
||||||
setisLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="assets-container-main">
|
|
||||||
<Search onChange={handleSearchChange} />
|
|
||||||
<div className="assets-list-section">
|
|
||||||
<section>
|
|
||||||
{(() => {
|
|
||||||
if (isLoading) {
|
|
||||||
return <SkeletonUI type="asset" />; // Show skeleton when loading
|
|
||||||
}
|
}
|
||||||
if (searchValue) {
|
};
|
||||||
return (
|
filteredAssets();
|
||||||
<div className="assets-result">
|
}, [categoryAssets]);
|
||||||
<div className="assets-wrapper">
|
|
||||||
<div className="searched-content">
|
|
||||||
<p>Results for {searchValue}</p>
|
|
||||||
</div>
|
|
||||||
<div className="assets-container">
|
|
||||||
{categoryAssets?.map((asset: any, index: number) => (
|
|
||||||
<div
|
|
||||||
key={`${index}-${asset.filename}`}
|
|
||||||
className="assets"
|
|
||||||
id={asset.filename}
|
|
||||||
title={asset.filename}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={asset?.thumbnail}
|
|
||||||
alt={asset.filename}
|
|
||||||
className="asset-image"
|
|
||||||
onPointerDown={() => {
|
|
||||||
setSelectedItem({
|
|
||||||
name: asset.filename,
|
|
||||||
id: asset.AssetID,
|
|
||||||
type:
|
|
||||||
asset.type === "undefined"
|
|
||||||
? undefined
|
|
||||||
: asset.type
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="asset-name">
|
useEffect(() => {
|
||||||
{asset.filename
|
setCategoryList([
|
||||||
.split("_")
|
{ category: "Fenestration", categoryImage: feneration },
|
||||||
.map(
|
{ category: "Vehicles", categoryImage: vehicle },
|
||||||
(word: any) =>
|
{ category: "Workstation", categoryImage: workStation },
|
||||||
word.charAt(0).toUpperCase() + word.slice(1)
|
{ category: "Machines", categoryImage: machines },
|
||||||
)
|
{ category: "Workers", categoryImage: worker },
|
||||||
.join(" ")}
|
{ category: "Storage", categoryImage: storage },
|
||||||
</div>
|
{ category: "Safety", categoryImage: safety },
|
||||||
</div>
|
{ category: "Office", categoryImage: office },
|
||||||
))}
|
]);
|
||||||
</div>
|
}, []);
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedCategory) {
|
const fetchCategoryAssets = async (asset: any) => {
|
||||||
return (
|
setisLoading(true);
|
||||||
<div className="assets-wrapper">
|
setSelectedCategory(asset);
|
||||||
<h2>
|
try {
|
||||||
{selectedCategory}
|
const res = await getCategoryAsset(asset);
|
||||||
<button
|
setCategoryAssets(res);
|
||||||
className="back-button"
|
setFiltereredAssets(res);
|
||||||
id="asset-backButtom"
|
setisLoading(false); // End loading
|
||||||
onClick={() => {
|
// eslint-disable-next-line
|
||||||
setSelectedCategory(null);
|
} catch (error) {
|
||||||
setCategoryAssets([]);
|
echo.error("failed to fetch assets");
|
||||||
}}
|
setisLoading(false);
|
||||||
>
|
}
|
||||||
← Back
|
};
|
||||||
</button>
|
|
||||||
</h2>
|
|
||||||
<div className="assets-container">
|
|
||||||
{categoryAssets?.map((asset: any, index: number) => (
|
|
||||||
<div
|
|
||||||
key={`${index}-${asset}`}
|
|
||||||
className="assets"
|
|
||||||
id={asset.filename}
|
|
||||||
title={asset.filename}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
src={asset?.thumbnail}
|
|
||||||
alt={asset.filename}
|
|
||||||
className="asset-image"
|
|
||||||
onPointerDown={() => {
|
|
||||||
setSelectedItem({
|
|
||||||
name: asset.filename,
|
|
||||||
id: asset.AssetID,
|
|
||||||
type:
|
|
||||||
asset.type === "undefined"
|
|
||||||
? undefined
|
|
||||||
: asset.type,
|
|
||||||
category: asset.category,
|
|
||||||
subCategory: asset.subCategory
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="asset-name">
|
|
||||||
{asset.filename
|
|
||||||
.split("_")
|
|
||||||
.map(
|
|
||||||
(word: any) =>
|
|
||||||
word.charAt(0).toUpperCase() + word.slice(1)
|
|
||||||
)
|
|
||||||
.join(" ")}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{categoryAssets.length === 0 && (
|
|
||||||
<div className="no-asset">
|
|
||||||
🚧 The asset shelf is empty. We're working on filling it
|
|
||||||
up!
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="assets-wrapper">
|
<div className="assets-container-main">
|
||||||
<h2>Categories</h2>
|
<Search onChange={handleSearchChange} />
|
||||||
<div className="categories-container">
|
<div className="assets-list-section">
|
||||||
{Array.from(
|
<section>
|
||||||
new Set(categoryList.map((asset) => asset.category))
|
{(() => {
|
||||||
).map((category, index) => {
|
if (isLoading) {
|
||||||
const categoryInfo = categoryList.find(
|
return <SkeletonUI type="asset" />; // Show skeleton when loading
|
||||||
(asset) => asset.category === category
|
}
|
||||||
);
|
if (searchValue) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="assets-result">
|
||||||
key={`${index}-${category}`}
|
<div className="assets-wrapper">
|
||||||
className="category"
|
<div className="searched-content">
|
||||||
id={category}
|
<p>Results for {searchValue}</p>
|
||||||
onClick={() => fetchCategoryAssets(category)}
|
</div>
|
||||||
>
|
<div className="assets-container">
|
||||||
<img
|
{categoryAssets?.map((asset: any, index: number) => (
|
||||||
src={categoryInfo?.categoryImage ?? ""}
|
<div
|
||||||
alt={category}
|
key={`${index}-${asset.filename}`}
|
||||||
className="category-image"
|
className="assets"
|
||||||
draggable={false}
|
id={asset.filename}
|
||||||
/>
|
title={asset.filename}
|
||||||
<div className="category-name">{category}</div>
|
>
|
||||||
</div>
|
<img
|
||||||
);
|
src={asset?.thumbnail}
|
||||||
})}
|
alt={asset.filename}
|
||||||
</div>
|
className="asset-image"
|
||||||
</div>
|
onPointerDown={() => {
|
||||||
);
|
setSelectedItem({
|
||||||
})()}
|
name: asset.filename,
|
||||||
</section>
|
id: asset.AssetID,
|
||||||
</div>
|
type: asset.type === "undefined" ? undefined : asset.type
|
||||||
</div>
|
});
|
||||||
);
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="asset-name">
|
||||||
|
{asset.filename
|
||||||
|
.split("_")
|
||||||
|
.map(
|
||||||
|
(word: any) =>
|
||||||
|
word.charAt(0).toUpperCase() + word.slice(1)
|
||||||
|
)
|
||||||
|
.join(" ")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCategory) {
|
||||||
|
return (
|
||||||
|
<div className="assets-wrapper">
|
||||||
|
<h2>
|
||||||
|
{selectedCategory}
|
||||||
|
<button
|
||||||
|
className="back-button"
|
||||||
|
id="asset-backButtom"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedCategory(null);
|
||||||
|
setCategoryAssets([]);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
← Back
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div className="assets-container">
|
||||||
|
{categoryAssets?.map((asset: any, index: number) => (
|
||||||
|
<div
|
||||||
|
key={`${index}-${asset}`}
|
||||||
|
className="assets"
|
||||||
|
id={asset.filename}
|
||||||
|
title={asset.filename}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={asset?.thumbnail}
|
||||||
|
alt={asset.filename}
|
||||||
|
className="asset-image"
|
||||||
|
onPointerDown={() => {
|
||||||
|
setSelectedItem({
|
||||||
|
name: asset.filename,
|
||||||
|
id: asset.AssetID,
|
||||||
|
type: asset.type === "undefined" ? undefined : asset.type,
|
||||||
|
category: asset.category,
|
||||||
|
subType: asset.subType
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="asset-name">
|
||||||
|
{asset.filename.split("_").map((word: any) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{categoryAssets.length === 0 && (
|
||||||
|
<div className="no-asset">
|
||||||
|
🚧 The asset shelf is empty. We're working on filling it up!
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="assets-wrapper">
|
||||||
|
<h2>Categories</h2>
|
||||||
|
<div className="categories-container">
|
||||||
|
{Array.from(
|
||||||
|
new Set(categoryList.map((asset) => asset.category))
|
||||||
|
).map((category, index) => {
|
||||||
|
const categoryInfo = categoryList.find(
|
||||||
|
(asset) => asset.category === category
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={`${index}-${category}`}
|
||||||
|
className="category"
|
||||||
|
id={category}
|
||||||
|
onClick={() => fetchCategoryAssets(category)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={categoryInfo?.categoryImage ?? ""}
|
||||||
|
alt={category}
|
||||||
|
className="category-image"
|
||||||
|
draggable={false}
|
||||||
|
/>
|
||||||
|
<div className="category-name">{category}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Assets;
|
export default Assets;
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "vehicle",
|
type: "vehicle",
|
||||||
|
subType: item.eventData.subType as VehicleEventSchema['subType'] || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
||||||
@@ -151,6 +152,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "transfer",
|
type: "transfer",
|
||||||
|
subType: item.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
points: item.eventData.points?.map((point: any, index: number) => ({
|
points: item.eventData.points?.map((point: any, index: number) => ({
|
||||||
uuid: point.uuid || THREE.MathUtils.generateUUID(),
|
uuid: point.uuid || THREE.MathUtils.generateUUID(),
|
||||||
@@ -177,6 +179,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "machine",
|
type: "machine",
|
||||||
|
subType: item.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
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],
|
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
|
||||||
@@ -200,6 +203,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "roboticArm",
|
type: "roboticArm",
|
||||||
|
subType: item.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
||||||
@@ -228,6 +232,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "storageUnit",
|
type: "storageUnit",
|
||||||
|
subType: item.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
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],
|
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
|
||||||
@@ -250,6 +255,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "human",
|
type: "human",
|
||||||
|
subType: item.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
|
||||||
@@ -270,6 +276,31 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addEvent(humanEvent);
|
addEvent(humanEvent);
|
||||||
|
} else if (item.eventData.type === 'Crane') {
|
||||||
|
const craneEvent: CraneEventSchema = {
|
||||||
|
modelUuid: item.modelUuid,
|
||||||
|
modelName: item.modelName,
|
||||||
|
position: item.position,
|
||||||
|
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "crane",
|
||||||
|
subType: item.eventData.subType as CraneEventSchema['subType'] || 'pillarJib',
|
||||||
|
point: {
|
||||||
|
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(),
|
||||||
|
actionName: "Action 1",
|
||||||
|
actionType: "pickAndDrop",
|
||||||
|
maxPickUpCount: 1,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(craneEvent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assets.push({
|
assets.push({
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import * as THREE from "three";
|
import * as THREE from "three";
|
||||||
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
|
||||||
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
|
|
||||||
import * as Types from "../../../../types/world/worldTypes";
|
import * as Types from "../../../../types/world/worldTypes";
|
||||||
import { retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils";
|
import { retrieveGLTF, storeGLTF } from "../../../../utils/indexDB/idbUtils";
|
||||||
// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
|
|
||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
import * as CONSTANTS from "../../../../types/world/worldConstants";
|
import * as CONSTANTS from "../../../../types/world/worldConstants";
|
||||||
import PointsCalculator from "../../../simulation/events/points/functions/pointsCalculator";
|
import PointsCalculator from "../../../simulation/events/points/functions/pointsCalculator";
|
||||||
|
|
||||||
import { getUserData } from "../../../../functions/getUserData";
|
import { getUserData } from "../../../../functions/getUserData";
|
||||||
|
// import { setAssetsApi } from '../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi';
|
||||||
|
|
||||||
async function addAssetModel(
|
async function addAssetModel(
|
||||||
scene: THREE.Scene,
|
scene: THREE.Scene,
|
||||||
@@ -165,7 +165,7 @@ async function handleModelLoad(
|
|||||||
|
|
||||||
if (!data || !data.points) return;
|
if (!data || !data.points) return;
|
||||||
|
|
||||||
const eventData: any = { type: selectedItem.type };
|
const eventData: any = { type: selectedItem.type, subType: selectedItem.subType };
|
||||||
|
|
||||||
if (selectedItem.type === "Conveyor") {
|
if (selectedItem.type === "Conveyor") {
|
||||||
const ConveyorEvent: ConveyorEventSchema = {
|
const ConveyorEvent: ConveyorEventSchema = {
|
||||||
@@ -175,6 +175,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "transfer",
|
type: "transfer",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
points: data.points.map((point: THREE.Vector3, index: number) => {
|
points: data.points.map((point: THREE.Vector3, index: number) => {
|
||||||
const triggers: TriggerSchema[] = [];
|
const triggers: TriggerSchema[] = [];
|
||||||
@@ -243,6 +244,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "vehicle",
|
type: "vehicle",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -280,6 +282,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "roboticArm",
|
type: "roboticArm",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -313,6 +316,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "machine",
|
type: "machine",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
@@ -341,6 +345,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "storageUnit",
|
type: "storageUnit",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
@@ -368,6 +373,7 @@ async function handleModelLoad(
|
|||||||
rotation: newFloorItem.rotation,
|
rotation: newFloorItem.rotation,
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "human",
|
type: "human",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -393,6 +399,36 @@ async function handleModelLoad(
|
|||||||
position: humanEvent.point.position,
|
position: humanEvent.point.position,
|
||||||
rotation: humanEvent.point.rotation,
|
rotation: humanEvent.point.rotation,
|
||||||
}
|
}
|
||||||
|
} else if (selectedItem.type === "Crane") {
|
||||||
|
const craneEvent: CraneEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modelUuid,
|
||||||
|
modelName: newFloorItem.modelName,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: newFloorItem.rotation,
|
||||||
|
state: "idle",
|
||||||
|
type: "crane",
|
||||||
|
subType: selectedItem.subType || '',
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [data.points[0].x, data.points[0].y, data.points[0].z],
|
||||||
|
rotation: [0, 0, 0],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Action 1",
|
||||||
|
actionType: "pickAndDrop",
|
||||||
|
maxPickUpCount: 1,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(craneEvent);
|
||||||
|
eventData.point = {
|
||||||
|
uuid: craneEvent.point.uuid,
|
||||||
|
position: craneEvent.point.position,
|
||||||
|
rotation: craneEvent.point.rotation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const completeData = {
|
const completeData = {
|
||||||
@@ -401,11 +437,7 @@ async function handleModelLoad(
|
|||||||
modelName: newFloorItem.modelName,
|
modelName: newFloorItem.modelName,
|
||||||
assetId: newFloorItem.assetId,
|
assetId: newFloorItem.assetId,
|
||||||
position: newFloorItem.position,
|
position: newFloorItem.position,
|
||||||
rotation: {
|
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
|
||||||
x: model.rotation.x,
|
|
||||||
y: model.rotation.y,
|
|
||||||
z: model.rotation.z,
|
|
||||||
},
|
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
@@ -422,11 +454,7 @@ async function handleModelLoad(
|
|||||||
modelName: completeData.modelName,
|
modelName: completeData.modelName,
|
||||||
assetId: completeData.assetId,
|
assetId: completeData.assetId,
|
||||||
position: completeData.position,
|
position: completeData.position,
|
||||||
rotation: [
|
rotation: [completeData.rotation.x, completeData.rotation.y, completeData.rotation.z,] as [number, number, number],
|
||||||
completeData.rotation.x,
|
|
||||||
completeData.rotation.y,
|
|
||||||
completeData.rotation.z,
|
|
||||||
] as [number, number, number],
|
|
||||||
isLocked: completeData.isLocked,
|
isLocked: completeData.isLocked,
|
||||||
isCollidable: false,
|
isCollidable: false,
|
||||||
isVisible: completeData.isVisible,
|
isVisible: completeData.isVisible,
|
||||||
@@ -442,11 +470,7 @@ async function handleModelLoad(
|
|||||||
modelName: newFloorItem.modelName,
|
modelName: newFloorItem.modelName,
|
||||||
assetId: newFloorItem.assetId,
|
assetId: newFloorItem.assetId,
|
||||||
position: newFloorItem.position,
|
position: newFloorItem.position,
|
||||||
rotation: {
|
rotation: { x: model.rotation.x, y: model.rotation.y, z: model.rotation.z, },
|
||||||
x: model.rotation.x,
|
|
||||||
y: model.rotation.y,
|
|
||||||
z: model.rotation.z,
|
|
||||||
},
|
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
socketId: socket.id,
|
socketId: socket.id,
|
||||||
@@ -462,11 +486,7 @@ async function handleModelLoad(
|
|||||||
modelName: data.modelName,
|
modelName: data.modelName,
|
||||||
assetId: data.assetId,
|
assetId: data.assetId,
|
||||||
position: data.position,
|
position: data.position,
|
||||||
rotation: [data.rotation.x, data.rotation.y, data.rotation.z] as [
|
rotation: [data.rotation.x, data.rotation.y, data.rotation.z] as [number, number, number],
|
||||||
number,
|
|
||||||
number,
|
|
||||||
number
|
|
||||||
],
|
|
||||||
isLocked: data.isLocked,
|
isLocked: data.isLocked,
|
||||||
isCollidable: false,
|
isCollidable: false,
|
||||||
isVisible: data.isVisible,
|
isVisible: data.isVisible,
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { CameraControls } from '@react-three/drei';
|
import { CameraControls } from '@react-three/drei';
|
||||||
import { ThreeEvent } from '@react-three/fiber';
|
import { ThreeEvent, useThree } from '@react-three/fiber';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
import { ProductStoreType } from '../../../../../../store/simulation/useProductStore';
|
|
||||||
import { EventStoreType } from '../../../../../../store/simulation/useEventsStore';
|
|
||||||
import { Socket } from 'socket.io-client';
|
|
||||||
|
|
||||||
import { useActiveTool, useToolMode } from '../../../../../../store/builder/store';
|
import { useActiveTool, useDeletableFloorItem, useSelectedFloorItem, useToggleView } from '../../../../../../store/builder/store';
|
||||||
import useModuleStore, { useSubModuleStore } from '../../../../../../store/useModuleStore';
|
import useModuleStore, { useSubModuleStore } from '../../../../../../store/useModuleStore';
|
||||||
import { useSocketStore } from '../../../../../../store/builder/store';
|
import { useSocketStore } from '../../../../../../store/builder/store';
|
||||||
import { useSceneContext } from '../../../../../scene/sceneContext';
|
import { useSceneContext } from '../../../../../scene/sceneContext';
|
||||||
@@ -14,60 +11,60 @@ import { useProductContext } from '../../../../../simulation/products/productCon
|
|||||||
import { useVersionContext } from '../../../../version/versionContext';
|
import { useVersionContext } from '../../../../version/versionContext';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { getUserData } from '../../../../../../functions/getUserData';
|
import { getUserData } from '../../../../../../functions/getUserData';
|
||||||
|
import { useLeftData, useTopData } from '../../../../../../store/visualization/useZone3DWidgetStore';
|
||||||
|
import { useSelectedAsset } from '../../../../../../store/simulation/useSimulationStore';
|
||||||
|
import { upsertProductOrEventApi } from '../../../../../../services/simulation/products/UpsertProductOrEventApi';
|
||||||
|
|
||||||
// import { deleteFloorItem } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
|
// import { deleteFloorItem } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorItemApi';
|
||||||
|
|
||||||
export function useModelEventHandlers({
|
export function useModelEventHandlers({
|
||||||
controls,
|
|
||||||
boundingBox,
|
boundingBox,
|
||||||
groupRef,
|
groupRef,
|
||||||
toggleView,
|
|
||||||
deletableFloorItem,
|
|
||||||
setDeletableFloorItem,
|
|
||||||
setSelectedFloorItem,
|
|
||||||
gl,
|
|
||||||
setTop,
|
|
||||||
setLeft,
|
|
||||||
getIsEventInProduct,
|
|
||||||
getEventByModelUuid,
|
|
||||||
setSelectedAsset,
|
|
||||||
clearSelectedAsset,
|
|
||||||
removeAsset,
|
|
||||||
updateBackend,
|
|
||||||
leftDrag,
|
|
||||||
rightDrag
|
|
||||||
}: {
|
}: {
|
||||||
controls: CameraControls | any,
|
|
||||||
boundingBox: THREE.Box3 | null,
|
boundingBox: THREE.Box3 | null,
|
||||||
groupRef: React.RefObject<THREE.Group>,
|
groupRef: React.RefObject<THREE.Group>,
|
||||||
toggleView: boolean,
|
|
||||||
deletableFloorItem: THREE.Object3D | null,
|
|
||||||
setDeletableFloorItem: (item: THREE.Object3D | null) => void,
|
|
||||||
setSelectedFloorItem: (item: THREE.Object3D | null) => void,
|
|
||||||
gl: THREE.WebGLRenderer,
|
|
||||||
setTop: (top: number) => void,
|
|
||||||
setLeft: (left: number) => void,
|
|
||||||
getIsEventInProduct: (productUuid: string, modelUuid: string) => boolean,
|
|
||||||
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined,
|
|
||||||
setSelectedAsset: (EventData: EventsSchema) => void,
|
|
||||||
clearSelectedAsset: () => void,
|
|
||||||
removeAsset: (modelUuid: string) => void,
|
|
||||||
updateBackend: (productName: string, productUuid: string, projectId: string, event: EventsSchema) => void,
|
|
||||||
leftDrag: React.MutableRefObject<boolean>,
|
|
||||||
rightDrag: React.MutableRefObject<boolean>
|
|
||||||
}) {
|
}) {
|
||||||
|
const { controls, gl } = useThree();
|
||||||
const { activeTool } = useActiveTool();
|
const { activeTool } = useActiveTool();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
|
const { toggleView } = useToggleView();
|
||||||
const { subModule } = useSubModuleStore();
|
const { subModule } = useSubModuleStore();
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { eventStore, productStore } = useSceneContext();
|
const { eventStore, productStore, assetStore } = useSceneContext();
|
||||||
|
const { removeAsset } = assetStore();
|
||||||
|
const { removeEvent } = eventStore();
|
||||||
|
const { getIsEventInProduct, addPoint, deleteEvent } = productStore();
|
||||||
|
const { getEventByModelUuid } = eventStore();
|
||||||
|
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
|
||||||
|
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
||||||
|
const { setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
const { selectedVersion } = selectedVersionStore();
|
const { selectedVersion } = selectedVersionStore();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
|
const leftDrag = useRef(false);
|
||||||
|
const isLeftMouseDown = useRef(false);
|
||||||
|
const rightDrag = useRef(false);
|
||||||
|
const isRightMouseDown = useRef(false);
|
||||||
|
const { setTop } = useTopData();
|
||||||
|
const { setLeft } = useLeftData();
|
||||||
|
|
||||||
|
const updateBackend = (
|
||||||
|
productName: string,
|
||||||
|
productUuid: string,
|
||||||
|
projectId: string,
|
||||||
|
eventData: EventsSchema
|
||||||
|
) => {
|
||||||
|
upsertProductOrEventApi({
|
||||||
|
productName: productName,
|
||||||
|
productUuid: productUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
eventDatas: eventData,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleDblClick = (asset: Asset) => {
|
const handleDblClick = (asset: Asset) => {
|
||||||
if (asset && activeTool === "cursor" && boundingBox && groupRef.current && activeModule === 'builder') {
|
if (asset && activeTool === "cursor" && boundingBox && groupRef.current && activeModule === 'builder') {
|
||||||
@@ -117,8 +114,8 @@ export function useModelEventHandlers({
|
|||||||
|
|
||||||
const response = socket.emit('v1:model-asset:delete', data)
|
const response = socket.emit('v1:model-asset:delete', data)
|
||||||
|
|
||||||
eventStore.getState().removeEvent(asset.modelUuid);
|
removeEvent(asset.modelUuid);
|
||||||
const updatedEvents = productStore.getState().deleteEvent(asset.modelUuid);
|
const updatedEvents = deleteEvent(asset.modelUuid);
|
||||||
|
|
||||||
updatedEvents.forEach((event) => {
|
updatedEvents.forEach((event) => {
|
||||||
updateBackend(
|
updateBackend(
|
||||||
@@ -157,7 +154,7 @@ export function useModelEventHandlers({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const event = productStore.getState().addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint);
|
const event = addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint);
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
updateBackend(
|
updateBackend(
|
||||||
@@ -169,7 +166,6 @@ export function useModelEventHandlers({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -228,6 +224,50 @@ export function useModelEventHandlers({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const canvasElement = gl.domElement;
|
||||||
|
|
||||||
|
const onPointerDown = (evt: any) => {
|
||||||
|
if (evt.button === 0) {
|
||||||
|
isLeftMouseDown.current = true;
|
||||||
|
leftDrag.current = false;
|
||||||
|
}
|
||||||
|
if (evt.button === 2) {
|
||||||
|
isRightMouseDown.current = true;
|
||||||
|
rightDrag.current = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPointerMove = () => {
|
||||||
|
if (isLeftMouseDown.current) {
|
||||||
|
leftDrag.current = true;
|
||||||
|
}
|
||||||
|
if (isRightMouseDown.current) {
|
||||||
|
rightDrag.current = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPointerUp = (evt: any) => {
|
||||||
|
if (evt.button === 0) {
|
||||||
|
isLeftMouseDown.current = false;
|
||||||
|
}
|
||||||
|
if (evt.button === 2) {
|
||||||
|
isRightMouseDown.current = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
canvasElement.addEventListener('pointerdown', onPointerDown);
|
||||||
|
canvasElement.addEventListener('pointermove', onPointerMove);
|
||||||
|
canvasElement.addEventListener('pointerup', onPointerUp);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
canvasElement.removeEventListener('pointerdown', onPointerDown);
|
||||||
|
canvasElement.removeEventListener('pointermove', onPointerMove);
|
||||||
|
canvasElement.removeEventListener('pointerup', onPointerUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [gl])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleDblClick,
|
handleDblClick,
|
||||||
handleClick,
|
handleClick,
|
||||||
|
|||||||
@@ -1,76 +1,34 @@
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
|
import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
|
||||||
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
||||||
import { ThreeEvent, useThree } from '@react-three/fiber';
|
import { useDeletableFloorItem, useSelectedAssets, useSelectedFloorItem, useToggleView, useToolMode } from '../../../../../store/builder/store';
|
||||||
import { useActiveTool, useDeletableFloorItem, useSelectedAssets, useSelectedFloorItem, useSocketStore, useToggleView, useToolMode } from '../../../../../store/builder/store';
|
|
||||||
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
|
import { AssetBoundingBox } from '../../functions/assetBoundingBox';
|
||||||
import { CameraControls } from '@react-three/drei';
|
import useModuleStore from '../../../../../store/useModuleStore';
|
||||||
import useModuleStore, { useSubModuleStore } from '../../../../../store/useModuleStore';
|
|
||||||
import { useLeftData, useTopData } from '../../../../../store/visualization/useZone3DWidgetStore';
|
|
||||||
import { useSelectedAsset } from '../../../../../store/simulation/useSimulationStore';
|
|
||||||
import { useProductContext } from '../../../../simulation/products/productContext';
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
import { getUserData } from '../../../../../functions/getUserData';
|
|
||||||
import { useSceneContext } from '../../../../scene/sceneContext';
|
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||||
import { useVersionContext } from '../../../version/versionContext';
|
|
||||||
import { SkeletonUtils } from 'three-stdlib';
|
import { SkeletonUtils } from 'three-stdlib';
|
||||||
|
|
||||||
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
|
|
||||||
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
|
import { getAssetIksApi } from '../../../../../services/simulation/ik/getAssetIKs';
|
||||||
import { ModelAnimator } from './animator/modelAnimator';
|
import { ModelAnimator } from './animator/modelAnimator';
|
||||||
|
import { useModelEventHandlers } from './eventHandlers/useEventHandlers';
|
||||||
|
|
||||||
function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendered: boolean, loader: GLTFLoader }) {
|
function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendered: boolean, loader: GLTFLoader }) {
|
||||||
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
|
||||||
const savedTheme: string = localStorage.getItem("theme") || "light";
|
const savedTheme: string = localStorage.getItem("theme") || "light";
|
||||||
const { controls, gl } = useThree();
|
|
||||||
const { activeTool } = useActiveTool();
|
|
||||||
const { toolMode } = useToolMode();
|
const { toolMode } = useToolMode();
|
||||||
const { toggleView } = useToggleView();
|
const { toggleView } = useToggleView();
|
||||||
const { subModule } = useSubModuleStore();
|
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
const { assetStore } = useSceneContext();
|
||||||
const { removeAsset, resetAnimation } = assetStore();
|
const { resetAnimation } = assetStore();
|
||||||
const { setTop } = useTopData();
|
const { setDeletableFloorItem } = useDeletableFloorItem();
|
||||||
const { setLeft } = useLeftData();
|
|
||||||
const { getIsEventInProduct, addPoint } = productStore();
|
|
||||||
const { getEventByModelUuid } = eventStore();
|
|
||||||
const { selectedProductStore } = useProductContext();
|
|
||||||
const { selectedProduct } = selectedProductStore();
|
|
||||||
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
|
|
||||||
const { socket } = useSocketStore();
|
|
||||||
const { deletableFloorItem, setDeletableFloorItem } = useDeletableFloorItem();
|
|
||||||
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
const { selectedFloorItem, setSelectedFloorItem } = useSelectedFloorItem();
|
||||||
const leftDrag = useRef(false);
|
|
||||||
const isLeftMouseDown = useRef(false);
|
|
||||||
const rightDrag = useRef(false);
|
|
||||||
const isRightMouseDown = useRef(false);
|
|
||||||
const [gltfScene, setGltfScene] = useState<GLTF["scene"] | null>(null);
|
const [gltfScene, setGltfScene] = useState<GLTF["scene"] | null>(null);
|
||||||
const [boundingBox, setBoundingBox] = useState<THREE.Box3 | null>(null);
|
const [boundingBox, setBoundingBox] = useState<THREE.Box3 | null>(null);
|
||||||
const [isSelected, setIsSelected] = useState(false);
|
const [isSelected, setIsSelected] = useState(false);
|
||||||
const groupRef = useRef<THREE.Group>(null);
|
const groupRef = useRef<THREE.Group>(null);
|
||||||
const [ikData, setIkData] = useState<any>();
|
const [ikData, setIkData] = useState<any>();
|
||||||
const { selectedVersionStore } = useVersionContext();
|
|
||||||
const { selectedVersion } = selectedVersionStore();
|
|
||||||
const { userId, organization } = getUserData();
|
|
||||||
const { projectId } = useParams();
|
|
||||||
const { selectedAssets } = useSelectedAssets();
|
const { selectedAssets } = useSelectedAssets();
|
||||||
|
|
||||||
const updateBackend = (
|
|
||||||
productName: string,
|
|
||||||
productUuid: string,
|
|
||||||
projectId: string,
|
|
||||||
eventData: EventsSchema
|
|
||||||
) => {
|
|
||||||
upsertProductOrEventApi({
|
|
||||||
productName: productName,
|
|
||||||
productUuid: productUuid,
|
|
||||||
projectId: projectId,
|
|
||||||
eventDatas: eventData,
|
|
||||||
versionId: selectedVersion?.versionId || '',
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!ikData && asset.eventData && asset.eventData.type === 'ArmBot') {
|
if (!ikData && asset.eventData && asset.eventData.type === 'ArmBot') {
|
||||||
getAssetIksApi(asset.assetId).then((data) => {
|
getAssetIksApi(asset.assetId).then((data) => {
|
||||||
@@ -82,17 +40,6 @@ function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendere
|
|||||||
}
|
}
|
||||||
}, [asset.modelUuid, ikData])
|
}, [asset.modelUuid, ikData])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (gltfScene) {
|
|
||||||
gltfScene.traverse((child: any) => {
|
|
||||||
if (child.isMesh) {
|
|
||||||
child.castShadow = true;
|
|
||||||
child.receiveShadow = true;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [gltfScene]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDeletableFloorItem(null);
|
setDeletableFloorItem(null);
|
||||||
if (selectedFloorItem === null || selectedFloorItem.userData.modelUuid !== asset.modelUuid) {
|
if (selectedFloorItem === null || selectedFloorItem.userData.modelUuid !== asset.modelUuid) {
|
||||||
@@ -106,285 +53,6 @@ function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendere
|
|||||||
}
|
}
|
||||||
}, [isRendered, selectedFloorItem])
|
}, [isRendered, selectedFloorItem])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadModel = async () => {
|
|
||||||
try {
|
|
||||||
|
|
||||||
// Check Cache
|
|
||||||
const assetId = asset.assetId;
|
|
||||||
const cachedModel = THREE.Cache.get(assetId);
|
|
||||||
if (cachedModel) {
|
|
||||||
const clone: any = SkeletonUtils.clone(cachedModel.scene);
|
|
||||||
clone.animations = cachedModel.animations || [];
|
|
||||||
setGltfScene(clone);
|
|
||||||
calculateBoundingBox(clone);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check IndexedDB
|
|
||||||
const indexedDBModel = await retrieveGLTF(assetId);
|
|
||||||
if (indexedDBModel) {
|
|
||||||
const blobUrl = URL.createObjectURL(indexedDBModel);
|
|
||||||
loader.load(blobUrl, (gltf) => {
|
|
||||||
URL.revokeObjectURL(blobUrl);
|
|
||||||
THREE.Cache.remove(blobUrl);
|
|
||||||
THREE.Cache.add(assetId, gltf);
|
|
||||||
setGltfScene(gltf.scene.clone());
|
|
||||||
calculateBoundingBox(gltf.scene);
|
|
||||||
},
|
|
||||||
undefined,
|
|
||||||
(error) => {
|
|
||||||
echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
|
|
||||||
URL.revokeObjectURL(blobUrl);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch from Backend
|
|
||||||
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
|
|
||||||
const handleBackendLoad = async (gltf: GLTF) => {
|
|
||||||
try {
|
|
||||||
const response = await fetch(modelUrl);
|
|
||||||
const modelBlob = await response.blob();
|
|
||||||
await storeGLTF(assetId, modelBlob);
|
|
||||||
THREE.Cache.add(assetId, gltf);
|
|
||||||
setGltfScene(gltf.scene.clone());
|
|
||||||
calculateBoundingBox(gltf.scene);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`[Backend] Error storing/loading ${asset.modelName}:`, error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loader.load(modelUrl,
|
|
||||||
handleBackendLoad,
|
|
||||||
undefined,
|
|
||||||
(error) => {
|
|
||||||
echo.error(`[Backend] Error loading ${asset.modelName}:`);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Failed to load model:", asset.assetId, err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const calculateBoundingBox = (scene: THREE.Object3D) => {
|
|
||||||
const box = new THREE.Box3().setFromObject(scene);
|
|
||||||
setBoundingBox(box);
|
|
||||||
};
|
|
||||||
|
|
||||||
loadModel();
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDblClick = (asset: Asset) => {
|
|
||||||
if (asset) {
|
|
||||||
if (activeTool === "cursor" && boundingBox && groupRef.current && activeModule === 'builder') {
|
|
||||||
const size = boundingBox.getSize(new THREE.Vector3());
|
|
||||||
const center = boundingBox.getCenter(new THREE.Vector3());
|
|
||||||
|
|
||||||
const front = new THREE.Vector3(0, 0, 1);
|
|
||||||
groupRef.current.localToWorld(front);
|
|
||||||
front.sub(groupRef.current.position).normalize();
|
|
||||||
|
|
||||||
const distance = Math.max(size.x, size.y, size.z) * 2;
|
|
||||||
const newPosition = center.clone().addScaledVector(front, distance);
|
|
||||||
|
|
||||||
(controls as CameraControls).setPosition(
|
|
||||||
newPosition.x,
|
|
||||||
newPosition.y,
|
|
||||||
newPosition.z,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
(controls as CameraControls).setTarget(center.x, center.y, center.z, true);
|
|
||||||
(controls as CameraControls).fitToBox(groupRef.current, true, {
|
|
||||||
cover: true,
|
|
||||||
paddingTop: 5,
|
|
||||||
paddingLeft: 5,
|
|
||||||
paddingBottom: 5,
|
|
||||||
paddingRight: 5,
|
|
||||||
});
|
|
||||||
setSelectedFloorItem(groupRef.current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClick = (evt: ThreeEvent<MouseEvent>, asset: Asset) => {
|
|
||||||
if (leftDrag.current || toggleView) return;
|
|
||||||
if (activeTool === 'delete' && deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
|
|
||||||
|
|
||||||
//REST
|
|
||||||
|
|
||||||
// const response = await deleteFloorItem(organization, asset.modelUuid, asset.modelName);
|
|
||||||
|
|
||||||
//SOCKET
|
|
||||||
|
|
||||||
const data = {
|
|
||||||
organization,
|
|
||||||
modelUuid: asset.modelUuid,
|
|
||||||
modelName: asset.modelName,
|
|
||||||
socketId: socket.id,
|
|
||||||
userId,
|
|
||||||
versionId: selectedVersion?.versionId || '',
|
|
||||||
projectId
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = socket.emit('v1:model-asset:delete', data)
|
|
||||||
|
|
||||||
eventStore.getState().removeEvent(asset.modelUuid);
|
|
||||||
const updatedEvents = productStore.getState().deleteEvent(asset.modelUuid);
|
|
||||||
|
|
||||||
updatedEvents.forEach((event) => {
|
|
||||||
updateBackend(
|
|
||||||
selectedProduct.productName,
|
|
||||||
selectedProduct.productUuid,
|
|
||||||
projectId || '',
|
|
||||||
event
|
|
||||||
);
|
|
||||||
})
|
|
||||||
|
|
||||||
if (response) {
|
|
||||||
|
|
||||||
removeAsset(asset.modelUuid);
|
|
||||||
|
|
||||||
echo.success("Model Removed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (activeModule === 'simulation' && subModule === "simulations" && activeTool === 'pen') {
|
|
||||||
if (asset.eventData && asset.eventData.type === 'Conveyor') {
|
|
||||||
const intersectedPoint = evt.point;
|
|
||||||
const localPosition = groupRef.current?.worldToLocal(intersectedPoint.clone());
|
|
||||||
if (localPosition) {
|
|
||||||
const conveyorPoint: ConveyorPointSchema = {
|
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
|
||||||
position: [localPosition?.x, localPosition?.y, localPosition?.z],
|
|
||||||
rotation: [0, 0, 0],
|
|
||||||
action: {
|
|
||||||
actionUuid: THREE.MathUtils.generateUUID(),
|
|
||||||
actionName: `Action 1`,
|
|
||||||
actionType: 'default',
|
|
||||||
material: 'Default Material',
|
|
||||||
delay: 0,
|
|
||||||
spawnInterval: 5,
|
|
||||||
spawnCount: 1,
|
|
||||||
triggers: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const event = addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint);
|
|
||||||
|
|
||||||
if (event) {
|
|
||||||
updateBackend(
|
|
||||||
selectedProduct.productName,
|
|
||||||
selectedProduct.productUuid,
|
|
||||||
projectId || '',
|
|
||||||
event
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePointerOver = useCallback((asset: Asset) => {
|
|
||||||
if (activeTool === "delete" && activeModule === 'builder') {
|
|
||||||
if (deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
setDeletableFloorItem(groupRef.current);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [activeTool, activeModule, deletableFloorItem]);
|
|
||||||
|
|
||||||
const handlePointerOut = useCallback((evt: ThreeEvent<MouseEvent>, asset: Asset) => {
|
|
||||||
if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorItem && deletableFloorItem.uuid === asset.modelUuid) {
|
|
||||||
setDeletableFloorItem(null);
|
|
||||||
}
|
|
||||||
}, [activeTool, deletableFloorItem]);
|
|
||||||
|
|
||||||
const handleContextMenu = (asset: Asset, evt: ThreeEvent<MouseEvent>) => {
|
|
||||||
if (rightDrag.current || toggleView) return;
|
|
||||||
if (activeTool === "cursor" && subModule === 'simulations') {
|
|
||||||
if (asset.modelUuid) {
|
|
||||||
const canvasElement = gl.domElement;
|
|
||||||
const isInProduct = getIsEventInProduct(selectedProduct.productUuid, asset.modelUuid);
|
|
||||||
if (isInProduct) {
|
|
||||||
const event = getEventByModelUuid(asset.modelUuid);
|
|
||||||
if (event) {
|
|
||||||
setSelectedAsset(event);
|
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
|
||||||
const relativeX = evt.clientX - canvasRect.left;
|
|
||||||
const relativeY = evt.clientY - canvasRect.top;
|
|
||||||
setTop(relativeY);
|
|
||||||
setLeft(relativeX);
|
|
||||||
} else {
|
|
||||||
clearSelectedAsset();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const event = getEventByModelUuid(asset.modelUuid);
|
|
||||||
if (event) {
|
|
||||||
setSelectedAsset(event)
|
|
||||||
const canvasRect = canvasElement.getBoundingClientRect();
|
|
||||||
const relativeX = evt.clientX - canvasRect.left;
|
|
||||||
const relativeY = evt.clientY - canvasRect.top;
|
|
||||||
setTop(relativeY);
|
|
||||||
setLeft(relativeX);
|
|
||||||
} else {
|
|
||||||
clearSelectedAsset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clearSelectedAsset()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
clearSelectedAsset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const canvasElement = gl.domElement;
|
|
||||||
|
|
||||||
const onPointerDown = (evt: any) => {
|
|
||||||
if (evt.button === 0) {
|
|
||||||
isLeftMouseDown.current = true;
|
|
||||||
leftDrag.current = false;
|
|
||||||
}
|
|
||||||
if (evt.button === 2) {
|
|
||||||
isRightMouseDown.current = true;
|
|
||||||
rightDrag.current = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPointerMove = () => {
|
|
||||||
if (isLeftMouseDown.current) {
|
|
||||||
leftDrag.current = true;
|
|
||||||
}
|
|
||||||
if (isRightMouseDown.current) {
|
|
||||||
rightDrag.current = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onPointerUp = (evt: any) => {
|
|
||||||
if (evt.button === 0) {
|
|
||||||
isLeftMouseDown.current = false;
|
|
||||||
}
|
|
||||||
if (evt.button === 2) {
|
|
||||||
isRightMouseDown.current = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
canvasElement.addEventListener('pointerdown', onPointerDown);
|
|
||||||
canvasElement.addEventListener('pointermove', onPointerMove);
|
|
||||||
canvasElement.addEventListener('pointerup', onPointerUp);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
canvasElement.removeEventListener('pointerdown', onPointerDown);
|
|
||||||
canvasElement.removeEventListener('pointermove', onPointerMove);
|
|
||||||
canvasElement.removeEventListener('pointerup', onPointerUp);
|
|
||||||
}
|
|
||||||
|
|
||||||
}, [gl])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedAssets.length > 0) {
|
if (selectedAssets.length > 0) {
|
||||||
if (selectedAssets.some((selectedAsset: THREE.Object3D) => selectedAsset.userData.modelUuid === asset.modelUuid)) {
|
if (selectedAssets.some((selectedAsset: THREE.Object3D) => selectedAsset.userData.modelUuid === asset.modelUuid)) {
|
||||||
@@ -397,6 +65,89 @@ function Model({ asset, isRendered, loader }: { readonly asset: Asset, isRendere
|
|||||||
}
|
}
|
||||||
}, [selectedAssets])
|
}, [selectedAssets])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (gltfScene) {
|
||||||
|
gltfScene.traverse((child: any) => {
|
||||||
|
if (child.isMesh) {
|
||||||
|
child.castShadow = true;
|
||||||
|
child.receiveShadow = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [gltfScene]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Calculate Bounding Box
|
||||||
|
const calculateBoundingBox = (scene: THREE.Object3D) => {
|
||||||
|
const box = new THREE.Box3().setFromObject(scene);
|
||||||
|
setBoundingBox(box);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check Cache
|
||||||
|
const assetId = asset.assetId;
|
||||||
|
const cachedModel = THREE.Cache.get(assetId);
|
||||||
|
if (cachedModel) {
|
||||||
|
const clone: any = SkeletonUtils.clone(cachedModel.scene);
|
||||||
|
clone.animations = cachedModel.animations || [];
|
||||||
|
setGltfScene(clone);
|
||||||
|
calculateBoundingBox(clone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check IndexedDB
|
||||||
|
retrieveGLTF(assetId).then((indexedDBModel) => {
|
||||||
|
if (indexedDBModel) {
|
||||||
|
const blobUrl = URL.createObjectURL(indexedDBModel);
|
||||||
|
loader.load(
|
||||||
|
blobUrl,
|
||||||
|
(gltf) => {
|
||||||
|
URL.revokeObjectURL(blobUrl);
|
||||||
|
THREE.Cache.remove(blobUrl);
|
||||||
|
THREE.Cache.add(assetId, gltf);
|
||||||
|
setGltfScene(gltf.scene.clone());
|
||||||
|
calculateBoundingBox(gltf.scene);
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
(error) => {
|
||||||
|
echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
|
||||||
|
URL.revokeObjectURL(blobUrl);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch from Backend
|
||||||
|
const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
|
||||||
|
loader.load(
|
||||||
|
modelUrl,
|
||||||
|
(gltf: GLTF) => {
|
||||||
|
fetch(modelUrl)
|
||||||
|
.then((response) => response.blob())
|
||||||
|
.then((modelBlob) => storeGLTF(assetId, modelBlob))
|
||||||
|
.then(() => {
|
||||||
|
THREE.Cache.add(assetId, gltf);
|
||||||
|
setGltfScene(gltf.scene.clone());
|
||||||
|
calculateBoundingBox(gltf.scene);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(
|
||||||
|
`[Backend] Error storing/loading ${asset.modelName}:`,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
(error) => {
|
||||||
|
echo.error(`[Backend] Error loading ${asset.modelName}:`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error("Failed to load model:", asset.assetId, err);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const { handleDblClick, handleClick, handlePointerOver, handlePointerOut, handleContextMenu } = useModelEventHandlers({ boundingBox, groupRef });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group
|
<group
|
||||||
key={asset.modelUuid}
|
key={asset.modelUuid}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react";
|
|||||||
import { useThree, useFrame } from "@react-three/fiber";
|
import { useThree, useFrame } from "@react-three/fiber";
|
||||||
import { Group, Vector3 } from "three";
|
import { Group, Vector3 } from "three";
|
||||||
import { CameraControls } from '@react-three/drei';
|
import { CameraControls } from '@react-three/drei';
|
||||||
import { useLimitDistance, useRenderDistance, useSelectedFloorItem } from '../../../../store/builder/store';
|
import { useLimitDistance, useRenderDistance, useSelectedFloorItem, useToggleView } from '../../../../store/builder/store';
|
||||||
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
|
import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
|
||||||
import { useSceneContext } from '../../../scene/sceneContext';
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ import { GLTFLoader } from "three/examples/jsm/Addons";
|
|||||||
const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url));
|
const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url));
|
||||||
|
|
||||||
function Models({ loader }: { loader: GLTFLoader }) {
|
function Models({ loader }: { loader: GLTFLoader }) {
|
||||||
const { controls, camera, raycaster, pointer, gl } = useThree();
|
const { controls, camera } = useThree();
|
||||||
const assetGroupRef = useRef<Group>(null);
|
const assetGroupRef = useRef<Group>(null);
|
||||||
const { assetStore } = useSceneContext();
|
const { assetStore } = useSceneContext();
|
||||||
const { assets } = assetStore();
|
const { assets } = assetStore();
|
||||||
@@ -43,28 +43,6 @@ function Models({ loader }: { loader: GLTFLoader }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// const canvasElement = gl.domElement;
|
|
||||||
|
|
||||||
// const onClick = () => {
|
|
||||||
// if (!assetGroupRef.current || assetGroupRef.current.children.length === 0) return;
|
|
||||||
// raycaster.setFromCamera(pointer, camera);
|
|
||||||
|
|
||||||
// const intersects = raycaster.intersectObjects(assetGroupRef.current.children, true);
|
|
||||||
|
|
||||||
// if (intersects.length > 0) {
|
|
||||||
// console.log('intersects: ', intersects);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// canvasElement.addEventListener('click', onClick);
|
|
||||||
|
|
||||||
// return () => {
|
|
||||||
// canvasElement.removeEventListener('click', onClick);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}, [camera])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group
|
<group
|
||||||
name='Asset Group'
|
name='Asset Group'
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
|
|||||||
|
|
||||||
const updatedWallAsset = updateWallAsset(wallAsset.modelUuid, {
|
const updatedWallAsset = updateWallAsset(wallAsset.modelUuid, {
|
||||||
wallUuid: intersect.object.userData.wallUuid,
|
wallUuid: intersect.object.userData.wallUuid,
|
||||||
position: [newPoint.x, wallAsset.wallAssetType === 'fixed-move' ? 0 : intersect.point.y, newPoint.z],
|
position: [newPoint.x, wallAsset.wallAssetType === 'fixedMove' ? 0 : intersect.point.y, newPoint.z],
|
||||||
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ function WallAssetInstance({ wallAsset }: { wallAsset: WallAsset }) {
|
|||||||
|
|
||||||
updateWallAsset(wallAsset.modelUuid, {
|
updateWallAsset(wallAsset.modelUuid, {
|
||||||
wallUuid: intersect.object.userData.wallUuid,
|
wallUuid: intersect.object.userData.wallUuid,
|
||||||
position: [newPoint.x, wallAsset.wallAssetType === 'fixed-move' ? 0 : intersect.point.y, newPoint.z],
|
position: [newPoint.x, wallAsset.wallAssetType === 'fixedMove' ? 0 : intersect.point.y, newPoint.z],
|
||||||
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ function WallAssetCreator() {
|
|||||||
modelName: selectedItem.name,
|
modelName: selectedItem.name,
|
||||||
modelUuid: MathUtils.generateUUID(),
|
modelUuid: MathUtils.generateUUID(),
|
||||||
wallUuid: wall.wallUuid,
|
wallUuid: wall.wallUuid,
|
||||||
wallAssetType: selectedItem.subCategory,
|
wallAssetType: selectedItem.subType,
|
||||||
assetId: selectedItem.id,
|
assetId: selectedItem.id,
|
||||||
position: [closestPoint.x, selectedItem.subCategory === "fixed-move" ? 0 : intersect.point.y, closestPoint.z],
|
position: [closestPoint.x, selectedItem.subType === "fixedMove" ? 0 : intersect.point.y, closestPoint.z],
|
||||||
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
|
||||||
isLocked: false,
|
isLocked: false,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
|||||||
@@ -39,10 +39,7 @@ const CopyPasteControls3D = ({
|
|||||||
const [isPasting, setIsPasting] = useState(false);
|
const [isPasting, setIsPasting] = useState(false);
|
||||||
const [relativePositions, setRelativePositions] = useState<THREE.Vector3[]>([]);
|
const [relativePositions, setRelativePositions] = useState<THREE.Vector3[]>([]);
|
||||||
const [centerOffset, setCenterOffset] = useState<THREE.Vector3 | null>(null);
|
const [centerOffset, setCenterOffset] = useState<THREE.Vector3 | null>(null);
|
||||||
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({
|
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
|
||||||
left: false,
|
|
||||||
right: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const calculateRelativePositions = useCallback((objects: THREE.Object3D[]) => {
|
const calculateRelativePositions = useCallback((objects: THREE.Object3D[]) => {
|
||||||
if (objects.length === 0) return { center: new THREE.Vector3(), relatives: [] };
|
if (objects.length === 0) return { center: new THREE.Vector3(), relatives: [] };
|
||||||
@@ -227,6 +224,7 @@ const CopyPasteControls3D = ({
|
|||||||
|
|
||||||
const eventData: any = {
|
const eventData: any = {
|
||||||
type: pastedAsset.userData.eventData.type,
|
type: pastedAsset.userData.eventData.type,
|
||||||
|
subType: pastedAsset.userData.eventData.subType,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (pastedAsset.userData.eventData.type === "Conveyor") {
|
if (pastedAsset.userData.eventData.type === "Conveyor") {
|
||||||
@@ -237,6 +235,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: 'transfer',
|
type: 'transfer',
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
points: updatedEventData.points.map((point: any, index: number) => ({
|
points: updatedEventData.points.map((point: any, index: number) => ({
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -269,6 +268,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "vehicle",
|
type: "vehicle",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -307,6 +307,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "roboticArm",
|
type: "roboticArm",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -341,6 +342,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "machine",
|
type: "machine",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
@@ -369,6 +371,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "storageUnit",
|
type: "storageUnit",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
@@ -396,6 +399,7 @@ const CopyPasteControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "human",
|
type: "human",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -421,6 +425,36 @@ const CopyPasteControls3D = ({
|
|||||||
position: humanEvent.point.position,
|
position: humanEvent.point.position,
|
||||||
rotation: humanEvent.point.rotation
|
rotation: humanEvent.point.rotation
|
||||||
};
|
};
|
||||||
|
} else if (pastedAsset.userData.eventData.type === "Crane") {
|
||||||
|
const craneEvent: CraneEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modelUuid,
|
||||||
|
modelName: newFloorItem.modelName,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "crane",
|
||||||
|
subType: pastedAsset.userData.eventData.subType || '',
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
|
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Action 1",
|
||||||
|
actionType: "pickAndDrop",
|
||||||
|
maxPickUpCount: 1,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(craneEvent);
|
||||||
|
eventData.point = {
|
||||||
|
uuid: craneEvent.point.uuid,
|
||||||
|
position: craneEvent.point.position,
|
||||||
|
rotation: craneEvent.point.rotation
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
newFloorItem.eventData = eventData;
|
newFloorItem.eventData = eventData;
|
||||||
|
|||||||
@@ -37,10 +37,7 @@ const DuplicationControls3D = ({
|
|||||||
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
|
||||||
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
|
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
|
||||||
const [isDuplicating, setIsDuplicating] = useState(false);
|
const [isDuplicating, setIsDuplicating] = useState(false);
|
||||||
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({
|
const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
|
||||||
left: false,
|
|
||||||
right: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
|
const calculateDragOffset = useCallback((point: THREE.Object3D, hitPoint: THREE.Vector3) => {
|
||||||
const pointPosition = new THREE.Vector3().copy(point.position);
|
const pointPosition = new THREE.Vector3().copy(point.position);
|
||||||
@@ -228,6 +225,7 @@ const DuplicationControls3D = ({
|
|||||||
|
|
||||||
const eventData: any = {
|
const eventData: any = {
|
||||||
type: duplicatedAsset.userData.eventData.type,
|
type: duplicatedAsset.userData.eventData.type,
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (duplicatedAsset.userData.eventData.type === "Conveyor") {
|
if (duplicatedAsset.userData.eventData.type === "Conveyor") {
|
||||||
@@ -238,6 +236,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: 'transfer',
|
type: 'transfer',
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
points: updatedEventData.points.map((point: any, index: number) => ({
|
points: updatedEventData.points.map((point: any, index: number) => ({
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -270,6 +269,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "vehicle",
|
type: "vehicle",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -308,6 +308,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "roboticArm",
|
type: "roboticArm",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -342,6 +343,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "machine",
|
type: "machine",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
@@ -370,6 +372,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "storageUnit",
|
type: "storageUnit",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
@@ -397,6 +400,7 @@ const DuplicationControls3D = ({
|
|||||||
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
state: "idle",
|
state: "idle",
|
||||||
type: "human",
|
type: "human",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
speed: 1,
|
speed: 1,
|
||||||
point: {
|
point: {
|
||||||
uuid: THREE.MathUtils.generateUUID(),
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
@@ -422,6 +426,36 @@ const DuplicationControls3D = ({
|
|||||||
position: humanEvent.point.position,
|
position: humanEvent.point.position,
|
||||||
rotation: humanEvent.point.rotation
|
rotation: humanEvent.point.rotation
|
||||||
};
|
};
|
||||||
|
} else if (duplicatedAsset.userData.eventData.type === "Crane") {
|
||||||
|
const craneEvent: CraneEventSchema = {
|
||||||
|
modelUuid: newFloorItem.modelUuid,
|
||||||
|
modelName: newFloorItem.modelName,
|
||||||
|
position: newFloorItem.position,
|
||||||
|
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
|
||||||
|
state: "idle",
|
||||||
|
type: "crane",
|
||||||
|
subType: duplicatedAsset.userData.eventData.subType || '',
|
||||||
|
point: {
|
||||||
|
uuid: THREE.MathUtils.generateUUID(),
|
||||||
|
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
|
||||||
|
rotation: [updatedEventData.point.rotation[0], updatedEventData.point.rotation[1], updatedEventData.point.rotation[2]],
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
actionUuid: THREE.MathUtils.generateUUID(),
|
||||||
|
actionName: "Action 1",
|
||||||
|
actionType: "pickAndDrop",
|
||||||
|
maxPickUpCount: 1,
|
||||||
|
triggers: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(craneEvent);
|
||||||
|
eventData.point = {
|
||||||
|
uuid: craneEvent.point.uuid,
|
||||||
|
position: craneEvent.point.position,
|
||||||
|
rotation: craneEvent.point.rotation
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
newFloorItem.eventData = eventData;
|
newFloorItem.eventData = eventData;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { createConveyorStore, ConveyorStoreType } from '../../store/simulation/u
|
|||||||
import { createVehicleStore, VehicleStoreType } from '../../store/simulation/useVehicleStore';
|
import { createVehicleStore, VehicleStoreType } from '../../store/simulation/useVehicleStore';
|
||||||
import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simulation/useStorageUnitStore';
|
import { createStorageUnitStore, StorageUnitStoreType } from '../../store/simulation/useStorageUnitStore';
|
||||||
import { createHumanStore, HumanStoreType } from '../../store/simulation/useHumanStore';
|
import { createHumanStore, HumanStoreType } from '../../store/simulation/useHumanStore';
|
||||||
|
import { createCraneStore, CraneStoreType } from '../../store/simulation/useCraneStore';
|
||||||
|
|
||||||
type SceneContextValue = {
|
type SceneContextValue = {
|
||||||
|
|
||||||
@@ -41,6 +42,7 @@ type SceneContextValue = {
|
|||||||
vehicleStore: VehicleStoreType;
|
vehicleStore: VehicleStoreType;
|
||||||
storageUnitStore: StorageUnitStoreType;
|
storageUnitStore: StorageUnitStoreType;
|
||||||
humanStore: HumanStoreType;
|
humanStore: HumanStoreType;
|
||||||
|
craneStore: CraneStoreType;
|
||||||
|
|
||||||
humanEventManagerRef: React.RefObject<HumanEventManagerState>;
|
humanEventManagerRef: React.RefObject<HumanEventManagerState>;
|
||||||
|
|
||||||
@@ -78,6 +80,7 @@ export function SceneProvider({
|
|||||||
const vehicleStore = useMemo(() => createVehicleStore(), []);
|
const vehicleStore = useMemo(() => createVehicleStore(), []);
|
||||||
const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
|
const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
|
||||||
const humanStore = useMemo(() => createHumanStore(), []);
|
const humanStore = useMemo(() => createHumanStore(), []);
|
||||||
|
const craneStore = useMemo(() => createCraneStore(), []);
|
||||||
|
|
||||||
const humanEventManagerRef = useRef<HumanEventManagerState>({ humanStates: [] });
|
const humanEventManagerRef = useRef<HumanEventManagerState>({ humanStates: [] });
|
||||||
|
|
||||||
@@ -98,8 +101,9 @@ export function SceneProvider({
|
|||||||
vehicleStore.getState().clearVehicles();
|
vehicleStore.getState().clearVehicles();
|
||||||
storageUnitStore.getState().clearStorageUnits();
|
storageUnitStore.getState().clearStorageUnits();
|
||||||
humanStore.getState().clearHumans();
|
humanStore.getState().clearHumans();
|
||||||
|
craneStore.getState().clearCranes();
|
||||||
humanEventManagerRef.current.humanStates = [];
|
humanEventManagerRef.current.humanStates = [];
|
||||||
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, undoRedo2DStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore]);
|
}, [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, undoRedo2DStore, floorStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore]);
|
||||||
|
|
||||||
const contextValue = useMemo(() => (
|
const contextValue = useMemo(() => (
|
||||||
{
|
{
|
||||||
@@ -119,11 +123,12 @@ export function SceneProvider({
|
|||||||
vehicleStore,
|
vehicleStore,
|
||||||
storageUnitStore,
|
storageUnitStore,
|
||||||
humanStore,
|
humanStore,
|
||||||
|
craneStore,
|
||||||
humanEventManagerRef,
|
humanEventManagerRef,
|
||||||
clearStores,
|
clearStores,
|
||||||
layout
|
layout
|
||||||
}
|
}
|
||||||
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, undoRedo2DStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, clearStores, layout]);
|
), [assetStore, wallAssetStore, wallStore, aisleStore, zoneStore, floorStore, undoRedo2DStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, clearStores, layout]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SceneContext.Provider value={contextValue}>
|
<SceneContext.Provider value={contextValue}>
|
||||||
|
|||||||
15
app/src/modules/simulation/crane/crane.tsx
Normal file
15
app/src/modules/simulation/crane/crane.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import CraneInstances from './instances/craneInstances'
|
||||||
|
|
||||||
|
function Crane() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<CraneInstances />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Crane
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { useEffect, useMemo } from 'react';
|
||||||
|
import { useThree } from '@react-three/fiber';
|
||||||
|
|
||||||
|
function PillarJibAnimator({ crane }: { crane: CraneStatus }) {
|
||||||
|
const { scene } = useThree();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
|
||||||
|
|
||||||
|
if (model) {
|
||||||
|
const base = model.getObjectByName('base');
|
||||||
|
const trolley = model.getObjectByName('trolley');
|
||||||
|
const hook = model.getObjectByName('hook');
|
||||||
|
|
||||||
|
if (base && trolley && hook) {
|
||||||
|
let trolleyDir = 1;
|
||||||
|
let hookDir = 1;
|
||||||
|
|
||||||
|
const trolleySpeed = 0.01;
|
||||||
|
const hookSpeed = 0.01;
|
||||||
|
const rotationSpeed = 0.005;
|
||||||
|
|
||||||
|
const trolleyMinOffset = -1;
|
||||||
|
const trolleyMaxOffset = 1.75;
|
||||||
|
const hookMinOffset = 0.25;
|
||||||
|
const hookMaxOffset = -1.5;
|
||||||
|
|
||||||
|
const originalTrolleyX = trolley.position.x;
|
||||||
|
const originalHookY = hook.position.y;
|
||||||
|
|
||||||
|
const animate = () => {
|
||||||
|
if (base) {
|
||||||
|
base.rotation.y += rotationSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trolley) {
|
||||||
|
trolley.position.x += trolleyDir * trolleySpeed;
|
||||||
|
if (trolley.position.x >= originalTrolleyX + trolleyMaxOffset ||
|
||||||
|
trolley.position.x <= originalTrolleyX + trolleyMinOffset) {
|
||||||
|
trolleyDir *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hook) {
|
||||||
|
hook.position.y += hookDir * hookSpeed;
|
||||||
|
if (hook.position.y >= originalHookY + hookMinOffset ||
|
||||||
|
hook.position.y <= originalHookY + hookMaxOffset) {
|
||||||
|
hookDir *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
};
|
||||||
|
|
||||||
|
animate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [crane, scene]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PillarJibHelper crane={crane} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PillarJibAnimator;
|
||||||
|
|
||||||
|
function PillarJibHelper({ crane }: { crane: CraneStatus }) {
|
||||||
|
const { scene } = useThree();
|
||||||
|
|
||||||
|
const { geometry, position } = useMemo(() => {
|
||||||
|
const model = scene.getObjectByProperty('uuid', crane.modelUuid);
|
||||||
|
if (!model) return { geometry: null, position: null };
|
||||||
|
|
||||||
|
const base = model.getObjectByName('base');
|
||||||
|
const trolley = model.getObjectByName('trolley');
|
||||||
|
const hook = model.getObjectByName('hook');
|
||||||
|
|
||||||
|
if (!base || !trolley || !hook) return { geometry: null, position: null };
|
||||||
|
|
||||||
|
const baseWorld = new THREE.Vector3();
|
||||||
|
base.getWorldPosition(baseWorld);
|
||||||
|
|
||||||
|
const trolleyWorld = new THREE.Vector3();
|
||||||
|
trolley.getWorldPosition(trolleyWorld);
|
||||||
|
|
||||||
|
const hookWorld = new THREE.Vector3();
|
||||||
|
hook.getWorldPosition(hookWorld);
|
||||||
|
|
||||||
|
const distFromBase = new THREE.Vector2(trolleyWorld.x - baseWorld.x, trolleyWorld.z - baseWorld.z).length();
|
||||||
|
const outerRadius = distFromBase + 1.75;
|
||||||
|
const innerRadius = Math.max(distFromBase - 1, 0.05);
|
||||||
|
const height = (0.25 - (-1.5));
|
||||||
|
const cylinderYPosition = hookWorld.y + (height / 2) + (-1.5 + 0.25) / 2;
|
||||||
|
|
||||||
|
const shape = new THREE.Shape();
|
||||||
|
shape.absarc(0, 0, outerRadius, 0, Math.PI * 2, false);
|
||||||
|
|
||||||
|
const hole = new THREE.Path();
|
||||||
|
hole.absarc(0, 0, innerRadius, 0, Math.PI * 2, true);
|
||||||
|
shape.holes.push(hole);
|
||||||
|
|
||||||
|
const extrudeSettings = {
|
||||||
|
depth: height,
|
||||||
|
bevelEnabled: false,
|
||||||
|
steps: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
|
||||||
|
const position: [number, number, number] = [baseWorld.x, cylinderYPosition, baseWorld.z];
|
||||||
|
|
||||||
|
return { geometry, position };
|
||||||
|
}, [scene, crane.modelUuid]);
|
||||||
|
|
||||||
|
if (!geometry || !position) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<mesh
|
||||||
|
geometry={geometry}
|
||||||
|
position={position}
|
||||||
|
rotation={[Math.PI / 2, 0, 0]}
|
||||||
|
>
|
||||||
|
<meshStandardMaterial
|
||||||
|
color={0x888888}
|
||||||
|
metalness={0.5}
|
||||||
|
roughness={0.4}
|
||||||
|
side={THREE.DoubleSide}
|
||||||
|
transparent={true}
|
||||||
|
opacity={0.3}
|
||||||
|
/>
|
||||||
|
</mesh>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PillarJibInstance from './instance/pillarJibInstance';
|
||||||
|
import { useSceneContext } from '../../../scene/sceneContext';
|
||||||
|
|
||||||
|
function CraneInstances() {
|
||||||
|
const { craneStore } = useSceneContext();
|
||||||
|
const { cranes } = craneStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{cranes.map((crane: CraneStatus) => (
|
||||||
|
<React.Fragment key={crane.modelUuid}>
|
||||||
|
|
||||||
|
{crane.subType === "pillarJib" &&
|
||||||
|
<PillarJibInstance crane={crane} />
|
||||||
|
}
|
||||||
|
|
||||||
|
</React.Fragment>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CraneInstances
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import PillarJibAnimator from '../animator/pillarJibAnimator'
|
||||||
|
|
||||||
|
function PillarJibInstance({ crane }: { crane: CraneStatus }) {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
|
||||||
|
<PillarJibAnimator crane={crane} />
|
||||||
|
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PillarJibInstance
|
||||||
@@ -40,7 +40,7 @@ function PointsCalculator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
points: [worldTopMiddle]
|
points: [new THREE.Vector3(worldTopMiddle.x, worldTopMiddle.y + 0.1, worldTopMiddle.z)]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ function PointInstances() {
|
|||||||
machine: "purple",
|
machine: "purple",
|
||||||
storageUnit: "red",
|
storageUnit: "red",
|
||||||
human: "white",
|
human: "white",
|
||||||
|
crane: "yellow",
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -173,6 +173,22 @@ function TriggerConnector() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
// Handle Human point
|
||||||
|
else if (event.type === "crane" && 'point' in event) {
|
||||||
|
const point = event.point;
|
||||||
|
point.actions?.forEach(action => {
|
||||||
|
action.triggers?.forEach(trigger => {
|
||||||
|
if (trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint) {
|
||||||
|
newConnections.push({
|
||||||
|
id: `${point.uuid}-${trigger.triggeredAsset.triggeredPoint.pointUuid}-${trigger.triggerUuid}`,
|
||||||
|
startPointUuid: point.uuid,
|
||||||
|
endPointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
trigger
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setConnections(newConnections);
|
setConnections(newConnections);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { useParams } from 'react-router-dom';
|
|||||||
import { useVersionContext } from '../../builder/version/versionContext';
|
import { useVersionContext } from '../../builder/version/versionContext';
|
||||||
|
|
||||||
function Products() {
|
function Products() {
|
||||||
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, layout, productStore } = useSceneContext();
|
const { armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore, humanStore, craneStore, layout, productStore } = useSceneContext();
|
||||||
const { products, getProductById, addProduct, setProducts } = productStore();
|
const { products, getProductById, addProduct, setProducts } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { setMainProduct } = useMainProduct();
|
const { setMainProduct } = useMainProduct();
|
||||||
@@ -20,7 +20,8 @@ function Products() {
|
|||||||
const { addMachine, clearMachines } = machineStore();
|
const { addMachine, clearMachines } = machineStore();
|
||||||
const { addConveyor, clearConveyors } = conveyorStore();
|
const { addConveyor, clearConveyors } = conveyorStore();
|
||||||
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
const { setCurrentMaterials, clearStorageUnits, updateCurrentLoad, addStorageUnit } = storageUnitStore();
|
||||||
const { addHuman, addCurrentAction, clearHumans } = humanStore();
|
const { addHuman, addCurrentAction: addCurrentActionHuman, clearHumans } = humanStore();
|
||||||
|
const { addCrane, addCurrentAction: addCurrentActionCrane, clearCranes } = craneStore();
|
||||||
const { isReset } = useResetButtonStore();
|
const { isReset } = useResetButtonStore();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { mainProduct } = useMainProduct();
|
const { mainProduct } = useMainProduct();
|
||||||
@@ -164,7 +165,25 @@ function Products() {
|
|||||||
addHuman(selectedProduct.productUuid, events);
|
addHuman(selectedProduct.productUuid, events);
|
||||||
|
|
||||||
if (events.point.actions.length > 0) {
|
if (events.point.actions.length > 0) {
|
||||||
addCurrentAction(events.modelUuid, events.point.actions[0].actionUuid);
|
addCurrentActionHuman(events.modelUuid, events.point.actions[0].actionUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedProduct, products, isReset, isPlaying]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedProduct.productUuid) {
|
||||||
|
const product = getProductById(selectedProduct.productUuid);
|
||||||
|
if (product) {
|
||||||
|
clearCranes();
|
||||||
|
product.eventDatas.forEach(events => {
|
||||||
|
if (events.type === 'crane') {
|
||||||
|
addCrane(selectedProduct.productUuid, events);
|
||||||
|
|
||||||
|
if (events.point.actions.length > 0) {
|
||||||
|
addCurrentActionCrane(events.modelUuid, events.point.actions[0].actionUuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import Materials from './materials/materials';
|
|||||||
import Machine from './machine/machine';
|
import Machine from './machine/machine';
|
||||||
import StorageUnit from './storageUnit/storageUnit';
|
import StorageUnit from './storageUnit/storageUnit';
|
||||||
import Human from './human/human';
|
import Human from './human/human';
|
||||||
|
import Crane from './crane/crane';
|
||||||
import Simulator from './simulator/simulator';
|
import Simulator from './simulator/simulator';
|
||||||
import Products from './products/products';
|
import Products from './products/products';
|
||||||
import Trigger from './triggers/trigger';
|
import Trigger from './triggers/trigger';
|
||||||
@@ -55,6 +56,8 @@ function Simulation() {
|
|||||||
|
|
||||||
<Human />
|
<Human />
|
||||||
|
|
||||||
|
<Crane />
|
||||||
|
|
||||||
<Simulator />
|
<Simulator />
|
||||||
|
|
||||||
<SimulationAnalysis />
|
<SimulationAnalysis />
|
||||||
|
|||||||
@@ -3,74 +3,74 @@ import { io } from "socket.io-client";
|
|||||||
import * as CONSTANTS from "../../types/world/worldConstants";
|
import * as CONSTANTS from "../../types/world/worldConstants";
|
||||||
|
|
||||||
export const useSocketStore = create<any>((set: any, get: any) => ({
|
export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||||
socket: null,
|
socket: null,
|
||||||
initializeSocket: (
|
initializeSocket: (
|
||||||
email?: string,
|
email?: string,
|
||||||
organization?: string,
|
organization?: string,
|
||||||
token?: string,
|
token?: string,
|
||||||
refreshToken?: string
|
refreshToken?: string
|
||||||
) => {
|
) => {
|
||||||
const existingSocket = get().socket;
|
const existingSocket = get().socket;
|
||||||
if (existingSocket) {
|
if (existingSocket) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const socket = io(
|
const socket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder_v1`,
|
||||||
{
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const visualizationSocket = io(
|
const visualizationSocket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization_v1`,
|
||||||
{
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const dashBoardSocket = io(
|
const dashBoardSocket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/dashboard`,
|
||||||
{
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const projectSocket = io(
|
const projectSocket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`,
|
||||||
{
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const threadSocket = io(
|
const threadSocket = io(
|
||||||
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
|
`http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/thread`,
|
||||||
{
|
{
|
||||||
reconnection: true,
|
reconnection: true,
|
||||||
auth: { token, refreshToken },
|
auth: { token, refreshToken },
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
set({
|
set({
|
||||||
socket,
|
socket,
|
||||||
visualizationSocket,
|
visualizationSocket,
|
||||||
dashBoardSocket,
|
dashBoardSocket,
|
||||||
projectSocket,
|
projectSocket,
|
||||||
threadSocket,
|
threadSocket,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
disconnectSocket: () => {
|
disconnectSocket: () => {
|
||||||
set((state: any) => {
|
set((state: any) => {
|
||||||
state.socket?.disconnect();
|
state.socket?.disconnect();
|
||||||
state.visualizationSocket?.disconnect();
|
state.visualizationSocket?.disconnect();
|
||||||
state.dashBoardSocket?.disconnect();
|
state.dashBoardSocket?.disconnect();
|
||||||
state.projectSocket?.disconnect();
|
state.projectSocket?.disconnect();
|
||||||
state.threadSocket?.disconnect();
|
state.threadSocket?.disconnect();
|
||||||
return { socket: null };
|
return { socket: null };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
// export const useSocketStore = create<any>((set: any, get: any) => ({
|
// export const useSocketStore = create<any>((set: any, get: any) => ({
|
||||||
// socket: null,
|
// socket: null,
|
||||||
@@ -128,507 +128,507 @@ export const useSocketStore = create<any>((set: any, get: any) => ({
|
|||||||
// },
|
// },
|
||||||
// }));
|
// }));
|
||||||
export const useLoadingProgress = create<{
|
export const useLoadingProgress = create<{
|
||||||
loadingProgress: number;
|
loadingProgress: number;
|
||||||
setLoadingProgress: (x: number) => void;
|
setLoadingProgress: (x: number) => void;
|
||||||
}>((set) => ({
|
}>((set) => ({
|
||||||
loadingProgress: 1,
|
loadingProgress: 1,
|
||||||
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
|
setLoadingProgress: (x: number) => set({ loadingProgress: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useOrganization = create<any>((set: any) => ({
|
export const useOrganization = create<any>((set: any) => ({
|
||||||
organization: "",
|
organization: "",
|
||||||
setOrganization: (x: any) => set(() => ({ organization: x })),
|
setOrganization: (x: any) => set(() => ({ organization: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useToggleView = create<any>((set: any) => ({
|
export const useToggleView = create<any>((set: any) => ({
|
||||||
toggleView: false,
|
toggleView: false,
|
||||||
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
setToggleView: (x: any) => set(() => ({ toggleView: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRoomsState = create<any>((set: any) => ({
|
export const useRoomsState = create<any>((set: any) => ({
|
||||||
roomsState: [],
|
roomsState: [],
|
||||||
setRoomsState: (x: any) => set(() => ({ roomsState: x })),
|
setRoomsState: (x: any) => set(() => ({ roomsState: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedItem = create<any>((set: any) => ({
|
export const useSelectedItem = create<any>((set: any) => ({
|
||||||
selectedItem: {
|
selectedItem: {
|
||||||
name: "",
|
name: "",
|
||||||
id: "",
|
id: "",
|
||||||
type: undefined,
|
type: undefined,
|
||||||
category: "",
|
category: "",
|
||||||
subCatergory: "",
|
subType: "",
|
||||||
},
|
},
|
||||||
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
setSelectedItem: (x: any) => set(() => ({ selectedItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useNavMesh = create<any>((set: any) => ({
|
export const useNavMesh = create<any>((set: any) => ({
|
||||||
navMesh: null,
|
navMesh: null,
|
||||||
setNavMesh: (x: any) => set({ navMesh: x }),
|
setNavMesh: (x: any) => set({ navMesh: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedAssets = create<any>((set: any) => ({
|
export const useSelectedAssets = create<any>((set: any) => ({
|
||||||
selectedAssets: [],
|
selectedAssets: [],
|
||||||
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useLayers = create<any>((set: any) => ({
|
export const useLayers = create<any>((set: any) => ({
|
||||||
Layers: 1,
|
Layers: 1,
|
||||||
setLayers: (x: any) => set(() => ({ Layers: x })),
|
setLayers: (x: any) => set(() => ({ Layers: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useCamPosition = create<any>((set: any) => ({
|
export const useCamPosition = create<any>((set: any) => ({
|
||||||
camPosition: { x: undefined, y: undefined, z: undefined },
|
camPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
|
setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useMenuVisible = create<any>((set: any) => ({
|
export const useMenuVisible = create<any>((set: any) => ({
|
||||||
menuVisible: false,
|
menuVisible: false,
|
||||||
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
setMenuVisible: (x: any) => set(() => ({ menuVisible: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useToolMode = create<any>((set: any) => ({
|
export const useToolMode = create<any>((set: any) => ({
|
||||||
toolMode: null,
|
toolMode: null,
|
||||||
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
setToolMode: (x: any) => set(() => ({ toolMode: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedWallItem = create<any>((set: any) => ({
|
export const useSelectedWallItem = create<any>((set: any) => ({
|
||||||
selectedWallItem: null,
|
selectedWallItem: null,
|
||||||
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedFloorItem = create<any>((set: any) => ({
|
export const useSelectedFloorItem = create<any>((set: any) => ({
|
||||||
selectedFloorItem: null,
|
selectedFloorItem: null,
|
||||||
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDeletableFloorItem = create<any>((set: any) => ({
|
export const useDeletableFloorItem = create<any>((set: any) => ({
|
||||||
deletableFloorItem: null,
|
deletableFloorItem: null,
|
||||||
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
|
setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSetScale = create<any>((set: any) => ({
|
export const useSetScale = create<any>((set: any) => ({
|
||||||
scale: null,
|
scale: null,
|
||||||
setScale: (x: any) => set(() => ({ scale: x })),
|
setScale: (x: any) => set(() => ({ scale: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRoofVisibility = create<any>((set: any) => ({
|
export const useRoofVisibility = create<any>((set: any) => ({
|
||||||
roofVisibility: false,
|
roofVisibility: false,
|
||||||
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useWallVisibility = create<any>((set: any) => ({
|
export const useWallVisibility = create<any>((set: any) => ({
|
||||||
wallVisibility: false,
|
wallVisibility: false,
|
||||||
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
|
setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useShadows = create<any>((set: any) => ({
|
export const useShadows = create<any>((set: any) => ({
|
||||||
shadows: false,
|
shadows: false,
|
||||||
setShadows: (x: any) => set(() => ({ shadows: x })),
|
setShadows: (x: any) => set(() => ({ shadows: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSunPosition = create<any>((set: any) => ({
|
export const useSunPosition = create<any>((set: any) => ({
|
||||||
sunPosition: { x: undefined, y: undefined, z: undefined },
|
sunPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setSunPosition: (newSuntPosition: any) =>
|
setSunPosition: (newSuntPosition: any) =>
|
||||||
set({ sunPosition: newSuntPosition }),
|
set({ sunPosition: newSuntPosition }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRemoveLayer = create<any>((set: any) => ({
|
export const useRemoveLayer = create<any>((set: any) => ({
|
||||||
removeLayer: false,
|
removeLayer: false,
|
||||||
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
|
setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRemovedLayer = create<any>((set: any) => ({
|
export const useRemovedLayer = create<any>((set: any) => ({
|
||||||
removedLayer: null,
|
removedLayer: null,
|
||||||
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
|
setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useProjectName = create<any>((set: any) => ({
|
export const useProjectName = create<any>((set: any) => ({
|
||||||
projectName: "Creating Your Project",
|
projectName: "Creating Your Project",
|
||||||
setProjectName: (x: any) => set({ projectName: x }),
|
setProjectName: (x: any) => set({ projectName: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useActiveLayer = create<any>((set: any) => ({
|
export const useActiveLayer = create<any>((set: any) => ({
|
||||||
activeLayer: 1,
|
activeLayer: 1,
|
||||||
setActiveLayer: (x: any) => set({ activeLayer: x }),
|
setActiveLayer: (x: any) => set({ activeLayer: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useResetCamera = create<any>((set: any) => ({
|
export const useResetCamera = create<any>((set: any) => ({
|
||||||
resetCamera: false,
|
resetCamera: false,
|
||||||
setResetCamera: (x: any) => set({ resetCamera: x }),
|
setResetCamera: (x: any) => set({ resetCamera: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useAddAction = create<any>((set: any) => ({
|
export const useAddAction = create<any>((set: any) => ({
|
||||||
addAction: null,
|
addAction: null,
|
||||||
setAddAction: (x: any) => set({ addAction: x }),
|
setAddAction: (x: any) => set({ addAction: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useActiveTool = create<any>((set: any) => ({
|
export const useActiveTool = create<any>((set: any) => ({
|
||||||
activeTool: "cursor",
|
activeTool: "cursor",
|
||||||
setActiveTool: (x: any) => set({ activeTool: x }),
|
setActiveTool: (x: any) => set({ activeTool: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useActiveSubTool = create<any>((set: any) => ({
|
export const useActiveSubTool = create<any>((set: any) => ({
|
||||||
activeSubTool: "cursor",
|
activeSubTool: "cursor",
|
||||||
setActiveSubTool: (x: any) => set({ activeSubTool: x }),
|
setActiveSubTool: (x: any) => set({ activeSubTool: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useElevation = create<any>((set: any) => ({
|
export const useElevation = create<any>((set: any) => ({
|
||||||
elevation: 45,
|
elevation: 45,
|
||||||
setElevation: (x: any) => set({ elevation: x }),
|
setElevation: (x: any) => set({ elevation: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useAzimuth = create<any>((set: any) => ({
|
export const useAzimuth = create<any>((set: any) => ({
|
||||||
azimuth: -160,
|
azimuth: -160,
|
||||||
setAzimuth: (x: any) => set({ azimuth: x }),
|
setAzimuth: (x: any) => set({ azimuth: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRenderDistance = create<any>((set: any) => ({
|
export const useRenderDistance = create<any>((set: any) => ({
|
||||||
renderDistance: 40,
|
renderDistance: 40,
|
||||||
setRenderDistance: (x: any) => set({ renderDistance: x }),
|
setRenderDistance: (x: any) => set({ renderDistance: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useCamMode = create<any>((set: any) => ({
|
export const useCamMode = create<any>((set: any) => ({
|
||||||
camMode: "ThirdPerson",
|
camMode: "ThirdPerson",
|
||||||
setCamMode: (x: any) => set({ camMode: x }),
|
setCamMode: (x: any) => set({ camMode: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useUserName = create<any>((set: any) => ({
|
export const useUserName = create<any>((set: any) => ({
|
||||||
userName: "",
|
userName: "",
|
||||||
setUserName: (x: any) => set({ userName: x }),
|
setUserName: (x: any) => set({ userName: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useRenameModeStore = create<any>((set: any) => ({
|
export const useRenameModeStore = create<any>((set: any) => ({
|
||||||
isRenameMode: false,
|
isRenameMode: false,
|
||||||
setIsRenameMode: (state: boolean) => set({ isRenameMode: state }),
|
setIsRenameMode: (state: boolean) => set({ isRenameMode: state }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useObjectPosition = create<any>((set: any) => ({
|
export const useObjectPosition = create<any>((set: any) => ({
|
||||||
objectPosition: { x: undefined, y: undefined, z: undefined },
|
objectPosition: { x: undefined, y: undefined, z: undefined },
|
||||||
setObjectPosition: (newObjectPosition: any) =>
|
setObjectPosition: (newObjectPosition: any) =>
|
||||||
set({ objectPosition: newObjectPosition }),
|
set({ objectPosition: newObjectPosition }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useObjectRotation = create<any>((set: any) => ({
|
export const useObjectRotation = create<any>((set: any) => ({
|
||||||
objectRotation: { x: undefined, y: undefined, z: undefined },
|
objectRotation: { x: undefined, y: undefined, z: undefined },
|
||||||
setObjectRotation: (newObjectRotation: any) =>
|
setObjectRotation: (newObjectRotation: any) =>
|
||||||
set({ objectRotation: newObjectRotation }),
|
set({ objectRotation: newObjectRotation }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDrieTemp = create<any>((set: any) => ({
|
export const useDrieTemp = create<any>((set: any) => ({
|
||||||
drieTemp: undefined,
|
drieTemp: undefined,
|
||||||
setDrieTemp: (x: any) => set({ drieTemp: x }),
|
setDrieTemp: (x: any) => set({ drieTemp: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useActiveUsers = create<any>((set: any) => ({
|
export const useActiveUsers = create<any>((set: any) => ({
|
||||||
activeUsers: [],
|
activeUsers: [],
|
||||||
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
|
setActiveUsers: (callback: (prev: any[]) => any[] | any[]) =>
|
||||||
set((state: { activeUsers: any[] }) => ({
|
set((state: { activeUsers: any[] }) => ({
|
||||||
activeUsers:
|
activeUsers:
|
||||||
typeof callback === "function" ? callback(state.activeUsers) : callback,
|
typeof callback === "function" ? callback(state.activeUsers) : callback,
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useDrieUIValue = create<any>((set: any) => ({
|
export const useDrieUIValue = create<any>((set: any) => ({
|
||||||
drieUIValue: { touch: null, temperature: null, humidity: null },
|
drieUIValue: { touch: null, temperature: null, humidity: null },
|
||||||
|
|
||||||
setDrieUIValue: (x: any) =>
|
setDrieUIValue: (x: any) =>
|
||||||
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
|
set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })),
|
||||||
|
|
||||||
setTouch: (value: any) =>
|
setTouch: (value: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
drieUIValue: { ...state.drieUIValue, touch: value },
|
drieUIValue: { ...state.drieUIValue, touch: value },
|
||||||
})),
|
})),
|
||||||
setTemperature: (value: any) =>
|
setTemperature: (value: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
drieUIValue: { ...state.drieUIValue, temperature: value },
|
drieUIValue: { ...state.drieUIValue, temperature: value },
|
||||||
})),
|
})),
|
||||||
setHumidity: (value: any) =>
|
setHumidity: (value: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
drieUIValue: { ...state.drieUIValue, humidity: value },
|
drieUIValue: { ...state.drieUIValue, humidity: value },
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const usezoneTarget = create<any>((set: any) => ({
|
export const usezoneTarget = create<any>((set: any) => ({
|
||||||
zoneTarget: [],
|
zoneTarget: [],
|
||||||
setZoneTarget: (x: any) => set({ zoneTarget: x }),
|
setZoneTarget: (x: any) => set({ zoneTarget: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const usezonePosition = create<any>((set: any) => ({
|
export const usezonePosition = create<any>((set: any) => ({
|
||||||
zonePosition: [],
|
zonePosition: [],
|
||||||
setZonePosition: (x: any) => set({ zonePosition: x }),
|
setZonePosition: (x: any) => set({ zonePosition: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface EditPositionState {
|
interface EditPositionState {
|
||||||
Edit: boolean;
|
Edit: boolean;
|
||||||
setEdit: (value: boolean) => void;
|
setEdit: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useEditPosition = create<EditPositionState>((set) => ({
|
export const useEditPosition = create<EditPositionState>((set) => ({
|
||||||
Edit: false,
|
Edit: false,
|
||||||
setEdit: (value) => set({ Edit: value }),
|
setEdit: (value) => set({ Edit: value }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useAsset3dWidget = create<any>((set: any) => ({
|
export const useAsset3dWidget = create<any>((set: any) => ({
|
||||||
widgetSelect: "",
|
widgetSelect: "",
|
||||||
setWidgetSelect: (x: any) => set({ widgetSelect: x }),
|
setWidgetSelect: (x: any) => set({ widgetSelect: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useWidgetSubOption = create<any>((set: any) => ({
|
export const useWidgetSubOption = create<any>((set: any) => ({
|
||||||
widgetSubOption: "2D",
|
widgetSubOption: "2D",
|
||||||
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
|
setWidgetSubOption: (x: any) => set({ widgetSubOption: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useLimitDistance = create<any>((set: any) => ({
|
export const useLimitDistance = create<any>((set: any) => ({
|
||||||
limitDistance: true,
|
limitDistance: true,
|
||||||
setLimitDistance: (x: any) => set({ limitDistance: x }),
|
setLimitDistance: (x: any) => set({ limitDistance: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useTileDistance = create<any>((set: any) => ({
|
export const useTileDistance = create<any>((set: any) => ({
|
||||||
gridValue: {
|
gridValue: {
|
||||||
size: CONSTANTS.gridConfig.size,
|
size: CONSTANTS.gridConfig.size,
|
||||||
divisions: CONSTANTS.gridConfig.divisions,
|
divisions: CONSTANTS.gridConfig.divisions,
|
||||||
},
|
},
|
||||||
planeValue: {
|
planeValue: {
|
||||||
height: CONSTANTS.planeConfig.height,
|
height: CONSTANTS.planeConfig.height,
|
||||||
width: CONSTANTS.planeConfig.width,
|
width: CONSTANTS.planeConfig.width,
|
||||||
},
|
},
|
||||||
|
|
||||||
setGridValue: (value: any) =>
|
setGridValue: (value: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
gridValue: { ...state.gridValue, ...value },
|
gridValue: { ...state.gridValue, ...value },
|
||||||
})),
|
})),
|
||||||
|
|
||||||
setPlaneValue: (value: any) =>
|
setPlaneValue: (value: any) =>
|
||||||
set((state: any) => ({
|
set((state: any) => ({
|
||||||
planeValue: { ...state.planeValue, ...value },
|
planeValue: { ...state.planeValue, ...value },
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const usePlayAgv = create<any>((set, get) => ({
|
export const usePlayAgv = create<any>((set, get) => ({
|
||||||
PlayAgv: [],
|
PlayAgv: [],
|
||||||
setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
|
setPlayAgv: (updateFn: (prev: any[]) => any[]) =>
|
||||||
set({ PlayAgv: updateFn(get().PlayAgv) }),
|
set({ PlayAgv: updateFn(get().PlayAgv) }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Define the Asset type
|
// Define the Asset type
|
||||||
type Asset = {
|
type Asset = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
position?: [number, number, number]; // Optional: 3D position
|
position?: [number, number, number]; // Optional: 3D position
|
||||||
rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
|
rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation
|
||||||
};
|
};
|
||||||
|
|
||||||
// Zustand store type
|
// Zustand store type
|
||||||
type ZoneAssetState = {
|
type ZoneAssetState = {
|
||||||
zoneAssetId: Asset | null;
|
zoneAssetId: Asset | null;
|
||||||
setZoneAssetId: (asset: Asset | null) => void;
|
setZoneAssetId: (asset: Asset | null) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Zustand store
|
// Zustand store
|
||||||
export const useZoneAssetId = create<ZoneAssetState>((set) => ({
|
export const useZoneAssetId = create<ZoneAssetState>((set) => ({
|
||||||
zoneAssetId: null,
|
zoneAssetId: null,
|
||||||
setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
|
setZoneAssetId: (asset) => set({ zoneAssetId: asset }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// version visible hidden
|
// version visible hidden
|
||||||
interface VersionHistoryState {
|
interface VersionHistoryState {
|
||||||
viewVersionHistory: boolean;
|
viewVersionHistory: boolean;
|
||||||
setVersionHistoryVisible: (value: boolean) => void;
|
setVersionHistoryVisible: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useVersionHistoryVisibleStore = create<VersionHistoryState>((set) => ({
|
const useVersionHistoryVisibleStore = create<VersionHistoryState>((set) => ({
|
||||||
viewVersionHistory: false,
|
viewVersionHistory: false,
|
||||||
setVersionHistoryVisible: (value) => set({ viewVersionHistory: value }),
|
setVersionHistoryVisible: (value) => set({ viewVersionHistory: value }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default useVersionHistoryVisibleStore;
|
export default useVersionHistoryVisibleStore;
|
||||||
|
|
||||||
interface ShortcutStore {
|
interface ShortcutStore {
|
||||||
showShortcuts: boolean;
|
showShortcuts: boolean;
|
||||||
setShowShortcuts: (value: boolean) => void;
|
setShowShortcuts: (value: boolean) => void;
|
||||||
toggleShortcuts: () => void;
|
toggleShortcuts: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useShortcutStore = create<ShortcutStore>((set) => ({
|
export const useShortcutStore = create<ShortcutStore>((set) => ({
|
||||||
showShortcuts: false,
|
showShortcuts: false,
|
||||||
setShowShortcuts: (value) => set({ showShortcuts: value }),
|
setShowShortcuts: (value) => set({ showShortcuts: value }),
|
||||||
toggleShortcuts: () =>
|
toggleShortcuts: () =>
|
||||||
set((state) => ({ showShortcuts: !state.showShortcuts })),
|
set((state) => ({ showShortcuts: !state.showShortcuts })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useMachineCount = create<any>((set: any) => ({
|
export const useMachineCount = create<any>((set: any) => ({
|
||||||
machineCount: 0,
|
machineCount: 0,
|
||||||
setMachineCount: (x: any) => set({ machineCount: x }),
|
setMachineCount: (x: any) => set({ machineCount: x }),
|
||||||
}));
|
}));
|
||||||
export const useMachineUptime = create<any>((set: any) => ({
|
export const useMachineUptime = create<any>((set: any) => ({
|
||||||
machineActiveTime: 0,
|
machineActiveTime: 0,
|
||||||
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
|
setMachineActiveTime: (x: any) => set({ machineActiveTime: x }),
|
||||||
}));
|
}));
|
||||||
export const useMachineDowntime = create<any>((set: any) => ({
|
export const useMachineDowntime = create<any>((set: any) => ({
|
||||||
machineIdleTime: 0,
|
machineIdleTime: 0,
|
||||||
setMachineIdleTime: (x: any) => set({ machineIdleTime: x }),
|
setMachineIdleTime: (x: any) => set({ machineIdleTime: x }),
|
||||||
}));
|
}));
|
||||||
export const useMaterialCycle = create<any>((set: any) => ({
|
export const useMaterialCycle = create<any>((set: any) => ({
|
||||||
materialCycleTime: 0,
|
materialCycleTime: 0,
|
||||||
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
|
setMaterialCycleTime: (x: any) => set({ materialCycleTime: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useThroughPutData = create<any>((set: any) => ({
|
export const useThroughPutData = create<any>((set: any) => ({
|
||||||
throughputData: 0,
|
throughputData: 0,
|
||||||
setThroughputData: (x: any) => set({ throughputData: x }),
|
setThroughputData: (x: any) => set({ throughputData: x }),
|
||||||
}));
|
}));
|
||||||
export const useProductionCapacityData = create<any>((set: any) => ({
|
export const useProductionCapacityData = create<any>((set: any) => ({
|
||||||
productionCapacityData: 0,
|
productionCapacityData: 0,
|
||||||
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
|
setProductionCapacityData: (x: any) => set({ productionCapacityData: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useProcessBar = create<any>((set: any) => ({
|
export const useProcessBar = create<any>((set: any) => ({
|
||||||
processBar: [],
|
processBar: [],
|
||||||
setProcessBar: (x: any) => set({ processBar: x }),
|
setProcessBar: (x: any) => set({ processBar: x }),
|
||||||
}));
|
}));
|
||||||
export const useDfxUpload = create<any>((set: any) => ({
|
export const useDfxUpload = create<any>((set: any) => ({
|
||||||
dfxuploaded: [],
|
dfxuploaded: [],
|
||||||
dfxWallGenerate: [],
|
dfxWallGenerate: [],
|
||||||
objValue: { x: 0, y: 0, z: 0 },
|
objValue: { x: 0, y: 0, z: 0 },
|
||||||
setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
|
setDfxUploaded: (x: any) => set({ dfxuploaded: x }),
|
||||||
setDxfWallGenerate: (x: any) => set({ dfxWallGenerate: x }),
|
setDxfWallGenerate: (x: any) => set({ dfxWallGenerate: x }),
|
||||||
setObjValue: (x: any) => set({ objValue: x }),
|
setObjValue: (x: any) => set({ objValue: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
type InputValuesStore = {
|
type InputValuesStore = {
|
||||||
inputValues: Record<string, string>;
|
inputValues: Record<string, string>;
|
||||||
setInputValues: (values: Record<string, string>) => void;
|
setInputValues: (values: Record<string, string>) => void;
|
||||||
updateInputValue: (label: string, value: string) => void; // <- New
|
updateInputValue: (label: string, value: string) => void; // <- New
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useInputValues = create<InputValuesStore>((set) => ({
|
export const useInputValues = create<InputValuesStore>((set) => ({
|
||||||
inputValues: {},
|
inputValues: {},
|
||||||
setInputValues: (values) => set({ inputValues: values }),
|
setInputValues: (values) => set({ inputValues: values }),
|
||||||
updateInputValue: (label, value) =>
|
updateInputValue: (label, value) =>
|
||||||
set((state) => ({
|
set((state) => ({
|
||||||
inputValues: {
|
inputValues: {
|
||||||
...state.inputValues,
|
...state.inputValues,
|
||||||
[label]: value,
|
[label]: value,
|
||||||
},
|
},
|
||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface ROISummaryData {
|
export interface ROISummaryData {
|
||||||
productName: string;
|
productName: string;
|
||||||
roiPercentage: number;
|
roiPercentage: number;
|
||||||
paybackPeriod: number;
|
paybackPeriod: number;
|
||||||
totalCost: number;
|
totalCost: number;
|
||||||
revenueGenerated: number;
|
revenueGenerated: number;
|
||||||
netProfit: number;
|
netProfit: number;
|
||||||
netLoss: number;
|
netLoss: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ROISummaryStore {
|
interface ROISummaryStore {
|
||||||
roiSummary: ROISummaryData;
|
roiSummary: ROISummaryData;
|
||||||
setRoiSummaryData: (values: ROISummaryData) => void;
|
setRoiSummaryData: (values: ROISummaryData) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useROISummaryData = create<ROISummaryStore>((set) => ({
|
export const useROISummaryData = create<ROISummaryStore>((set) => ({
|
||||||
roiSummary: {
|
roiSummary: {
|
||||||
productName: "",
|
productName: "",
|
||||||
roiPercentage: 0,
|
roiPercentage: 0,
|
||||||
paybackPeriod: 0,
|
paybackPeriod: 0,
|
||||||
totalCost: 0,
|
totalCost: 0,
|
||||||
revenueGenerated: 0,
|
revenueGenerated: 0,
|
||||||
netProfit: 0,
|
netProfit: 0,
|
||||||
netLoss: 0,
|
netLoss: 0,
|
||||||
},
|
},
|
||||||
setRoiSummaryData: (values) => set({ roiSummary: values }),
|
setRoiSummaryData: (values) => set({ roiSummary: values }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface CompareStore {
|
interface CompareStore {
|
||||||
comparePopUp: boolean;
|
comparePopUp: boolean;
|
||||||
setComparePopUp: (value: boolean) => void;
|
setComparePopUp: (value: boolean) => void;
|
||||||
toggleComparePopUp: () => void;
|
toggleComparePopUp: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCompareStore = create<CompareStore>((set) => ({
|
export const useCompareStore = create<CompareStore>((set) => ({
|
||||||
comparePopUp: false,
|
comparePopUp: false,
|
||||||
setComparePopUp: (value) => set({ comparePopUp: value }),
|
setComparePopUp: (value) => set({ comparePopUp: value }),
|
||||||
toggleComparePopUp: () =>
|
toggleComparePopUp: () =>
|
||||||
set((state) => ({ comparePopUp: !state.comparePopUp })),
|
set((state) => ({ comparePopUp: !state.comparePopUp })),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Save state store
|
// Save state store
|
||||||
interface SaveVersionStore {
|
interface SaveVersionStore {
|
||||||
isVersionSaved: boolean;
|
isVersionSaved: boolean;
|
||||||
setIsVersionSaved: (value: boolean) => void;
|
setIsVersionSaved: (value: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSaveVersion = create<SaveVersionStore>((set) => ({
|
export const useSaveVersion = create<SaveVersionStore>((set) => ({
|
||||||
isVersionSaved: false,
|
isVersionSaved: false,
|
||||||
setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }),
|
setIsVersionSaved: (value: boolean) => set({ isVersionSaved: value }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
interface ViewSceneState {
|
interface ViewSceneState {
|
||||||
viewSceneLabels: boolean;
|
viewSceneLabels: boolean;
|
||||||
setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void;
|
setViewSceneLabels: (value: boolean | ((prev: boolean) => boolean)) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useViewSceneStore = create<ViewSceneState>((set) => ({
|
export const useViewSceneStore = create<ViewSceneState>((set) => ({
|
||||||
viewSceneLabels: getInitialViewSceneLabels(),
|
viewSceneLabels: getInitialViewSceneLabels(),
|
||||||
setViewSceneLabels: (value) => {
|
setViewSceneLabels: (value) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const newValue =
|
const newValue =
|
||||||
typeof value === "function" ? value(state.viewSceneLabels) : value;
|
typeof value === "function" ? value(state.viewSceneLabels) : value;
|
||||||
|
|
||||||
// Store in localStorage manually
|
// Store in localStorage manually
|
||||||
localStorage.setItem("viewSceneLabels", JSON.stringify(newValue));
|
localStorage.setItem("viewSceneLabels", JSON.stringify(newValue));
|
||||||
|
|
||||||
return { viewSceneLabels: newValue };
|
return { viewSceneLabels: newValue };
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function getInitialViewSceneLabels(): boolean {
|
function getInitialViewSceneLabels(): boolean {
|
||||||
if (typeof window === "undefined") return false; // SSR safety
|
if (typeof window === "undefined") return false; // SSR safety
|
||||||
const saved = localStorage.getItem("viewSceneLabels");
|
const saved = localStorage.getItem("viewSceneLabels");
|
||||||
return saved ? JSON.parse(saved) : false;
|
return saved ? JSON.parse(saved) : false;
|
||||||
}
|
}
|
||||||
export interface CompareProduct {
|
export interface CompareProduct {
|
||||||
productUuid: string;
|
productUuid: string;
|
||||||
productName: string;
|
productName: string;
|
||||||
simulationData: {
|
simulationData: {
|
||||||
// costPerUnit: number;
|
// costPerUnit: number;
|
||||||
// workingDaysPerYear: number;
|
// workingDaysPerYear: number;
|
||||||
// shiftLength: number;
|
// shiftLength: number;
|
||||||
// shiftsPerDay: number;
|
// shiftsPerDay: number;
|
||||||
roiPercentage: number;
|
roiPercentage: number;
|
||||||
// paybackPeriod: number;
|
// paybackPeriod: number;
|
||||||
// totalCost: number;
|
// totalCost: number;
|
||||||
// revenueGenerated: number;
|
// revenueGenerated: number;
|
||||||
netProfit: number;
|
netProfit: number;
|
||||||
productionCapacity: number;
|
productionCapacity: number;
|
||||||
paybackPeriod: number;
|
paybackPeriod: number;
|
||||||
// netLoss: number;
|
// netLoss: number;
|
||||||
machineIdleTime: number;
|
machineIdleTime: number;
|
||||||
machineActiveTime: number;
|
machineActiveTime: number;
|
||||||
throughputData: number;
|
throughputData: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCompareProductDataStore = create<{
|
export const useCompareProductDataStore = create<{
|
||||||
compareProductsData: CompareProduct[];
|
compareProductsData: CompareProduct[];
|
||||||
setCompareProductsData: (x: CompareProduct[]) => void;
|
setCompareProductsData: (x: CompareProduct[]) => void;
|
||||||
}>((set) => ({
|
}>((set) => ({
|
||||||
compareProductsData: [],
|
compareProductsData: [],
|
||||||
setCompareProductsData: (x) => set({ compareProductsData: x }),
|
setCompareProductsData: (x) => set({ compareProductsData: x }),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const useSelectedComment = create<any>((set: any) => ({
|
export const useSelectedComment = create<any>((set: any) => ({
|
||||||
selectedComment: null,
|
selectedComment: null,
|
||||||
setSelectedComment: (x: any) => set({ selectedComment: x }),
|
setSelectedComment: (x: any) => set({ selectedComment: x }),
|
||||||
position2Dstate: {},
|
position2Dstate: {},
|
||||||
setPosition2Dstate: (x: any) => set({ position2Dstate: x }),
|
setPosition2Dstate: (x: any) => set({ position2Dstate: x }),
|
||||||
commentPositionState: null,
|
commentPositionState: null,
|
||||||
setCommentPositionState: (x: any) => set({ commentPositionState: x }),
|
setCommentPositionState: (x: any) => set({ commentPositionState: x }),
|
||||||
}));
|
}));
|
||||||
export const useSelectedPath = create<any>((set: any) => ({
|
export const useSelectedPath = create<any>((set: any) => ({
|
||||||
selectedPath: "auto",
|
selectedPath: "auto",
|
||||||
setSelectedPath: (x: any) => set({ selectedPath: x }),
|
setSelectedPath: (x: any) => set({ selectedPath: x }),
|
||||||
}));
|
}));
|
||||||
|
|||||||
263
app/src/store/simulation/useCraneStore.ts
Normal file
263
app/src/store/simulation/useCraneStore.ts
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
import { create } from "zustand";
|
||||||
|
import { immer } from "zustand/middleware/immer";
|
||||||
|
|
||||||
|
interface CraneStore {
|
||||||
|
cranes: CraneStatus[];
|
||||||
|
|
||||||
|
addCrane: (productUuid: string, event: CraneEventSchema) => void;
|
||||||
|
removeCrane: (modelUuid: string) => void;
|
||||||
|
updateCrane: (
|
||||||
|
modelUuid: string,
|
||||||
|
updates: Partial<Omit<CraneStatus, "modelUuid" | "productUuid">>
|
||||||
|
) => void;
|
||||||
|
clearCranes: () => void;
|
||||||
|
|
||||||
|
setCurrentPhase: (modelUuid: string, phase: string) => void;
|
||||||
|
|
||||||
|
addCurrentAction: (modelUuid: string, actionUuid: string) => void;
|
||||||
|
removeCurrentAction: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
setCraneActive: (modelUuid: string, isActive: boolean) => void;
|
||||||
|
setCraneScheduled: (modelUuid: string, isScheduled: boolean) => void;
|
||||||
|
setCraneLoad: (modelUuid: string, load: number) => void;
|
||||||
|
setCraneState: (modelUuid: string, newState: CraneStatus["state"]) => void;
|
||||||
|
incrementCraneLoad: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
decrementCraneLoad: (modelUuid: string, decrementBy: number) => void;
|
||||||
|
|
||||||
|
addCurrentMaterial: (modelUuid: string, materialType: string, materialId: string) => void;
|
||||||
|
setCurrentMaterials: (modelUuid: string, materials: { materialType: string; materialId: string }[]) => void;
|
||||||
|
removeLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||||
|
getLastMaterial: (modelUuid: string) => { materialType: string; materialId: string } | undefined;
|
||||||
|
clearCurrentMaterials: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
incrementActiveTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
incrementIdleTime: (modelUuid: string, incrementBy: number) => void;
|
||||||
|
resetTime: (modelUuid: string) => void;
|
||||||
|
|
||||||
|
getCraneById: (modelUuid: string) => CraneStatus | undefined;
|
||||||
|
getCranesByProduct: (productUuid: string) => CraneStatus[];
|
||||||
|
getActiveCranes: () => CraneStatus[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createCraneStore = () => {
|
||||||
|
return create<CraneStore>()(
|
||||||
|
immer((set, get) => ({
|
||||||
|
cranes: [],
|
||||||
|
|
||||||
|
addCrane: (productUuid, event) => {
|
||||||
|
set((state) => {
|
||||||
|
const exists = state.cranes.some(c => c.modelUuid === event.modelUuid);
|
||||||
|
if (!exists) {
|
||||||
|
state.cranes.push({
|
||||||
|
...event,
|
||||||
|
productUuid,
|
||||||
|
currentPhase: 'init',
|
||||||
|
isActive: false,
|
||||||
|
isScheduled: false,
|
||||||
|
idleTime: 0,
|
||||||
|
activeTime: 0,
|
||||||
|
currentLoad: 0,
|
||||||
|
currentMaterials: []
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeCrane: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
state.cranes = state.cranes.filter(c => c.modelUuid !== modelUuid);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
updateCrane: (modelUuid, updates) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
Object.assign(crane, updates);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
clearCranes: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.cranes = [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentPhase: (modelUuid, phase) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentPhase = phase;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addCurrentAction: (modelUuid, actionUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
const action = crane.point.actions.find(a => a.actionUuid === actionUuid);
|
||||||
|
if (action) {
|
||||||
|
crane.currentAction = {
|
||||||
|
actionUuid: action.actionUuid,
|
||||||
|
actionName: action.actionName
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeCurrentAction: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentAction = undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCraneActive: (modelUuid, isActive) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.isActive = isActive;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCraneScheduled: (modelUuid, isScheduled) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.isScheduled = isScheduled;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCraneLoad: (modelUuid, load) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentLoad = load;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCraneState: (modelUuid, newState) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.state = newState;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementCraneLoad: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentLoad += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
decrementCraneLoad: (modelUuid, decrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentLoad = Math.max(0, crane.currentLoad - decrementBy);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addCurrentMaterial: (modelUuid, materialType, materialId) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentMaterials.push({ materialType, materialId });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setCurrentMaterials: (modelUuid, materials) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentMaterials = materials;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeLastMaterial: (modelUuid) => {
|
||||||
|
let removed;
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane && crane.currentMaterials.length > 0) {
|
||||||
|
removed = JSON.parse(JSON.stringify(crane.currentMaterials.pop()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return removed;
|
||||||
|
},
|
||||||
|
|
||||||
|
getLastMaterial: (modelUuid) => {
|
||||||
|
const crane = get().cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane && crane.currentMaterials.length > 0) {
|
||||||
|
return crane.currentMaterials[crane.currentMaterials.length - 1];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
clearCurrentMaterials: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.currentMaterials = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementActiveTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.activeTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
incrementIdleTime: (modelUuid, incrementBy) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.idleTime += incrementBy;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
resetTime: (modelUuid) => {
|
||||||
|
set((state) => {
|
||||||
|
const crane = state.cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
if (crane) {
|
||||||
|
crane.activeTime = 0;
|
||||||
|
crane.idleTime = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
getCraneById: (modelUuid) => {
|
||||||
|
return get().cranes.find(c => c.modelUuid === modelUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getCranesByProduct: (productUuid) => {
|
||||||
|
return get().cranes.filter(c => c.productUuid === productUuid);
|
||||||
|
},
|
||||||
|
|
||||||
|
getActiveCranes: () => {
|
||||||
|
return get().cranes.filter(c => c.isActive);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CraneStoreType = ReturnType<typeof createCraneStore>;
|
||||||
@@ -11,24 +11,24 @@ type EventsStore = {
|
|||||||
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
updateEvent: (modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
||||||
|
|
||||||
// Point-level actions
|
// Point-level actions
|
||||||
addPoint: (modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema) => void;
|
addPoint: (modelUuid: string, point: PointsScheme) => void;
|
||||||
removePoint: (modelUuid: string, pointUuid: string) => void;
|
removePoint: (modelUuid: string, pointUuid: string) => void;
|
||||||
updatePoint: (
|
updatePoint: (
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema>
|
updates: Partial<PointsScheme>
|
||||||
) => EventsSchema | undefined;
|
) => EventsSchema | undefined;
|
||||||
|
|
||||||
// Action-level actions
|
// Action-level actions
|
||||||
addAction: (
|
addAction: (
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']
|
action: ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction
|
||||||
) => void;
|
) => void;
|
||||||
removeAction: (actionUuid: string) => void;
|
removeAction: (actionUuid: string) => void;
|
||||||
updateAction: (
|
updateAction: (
|
||||||
actionUuid: string,
|
actionUuid: string,
|
||||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']>
|
updates: Partial<ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction>
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
// Trigger-level actions
|
// Trigger-level actions
|
||||||
@@ -38,8 +38,8 @@ type EventsStore = {
|
|||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
|
getEventByModelUuid: (modelUuid: string) => EventsSchema | undefined;
|
||||||
getPointByUuid: (modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | undefined;
|
getPointByUuid: (modelUuid: string, pointUuid: string) => PointsScheme | undefined;
|
||||||
getActionByUuid: (actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action']) | undefined;
|
getActionByUuid: (actionUuid: string) => (ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) | undefined;
|
||||||
getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
|
getTriggerByUuid: (triggerUuid: string) => TriggerSchema | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ type ProductsStore = {
|
|||||||
updateEvent: (productUuid: string, modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
updateEvent: (productUuid: string, modelUuid: string, updates: Partial<EventsSchema>) => EventsSchema | undefined;
|
||||||
|
|
||||||
// Point-level actions
|
// Point-level actions
|
||||||
addPoint: (productUuid: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema) => EventsSchema | undefined;
|
addPoint: (productUuid: string, modelUuid: string, point: PointsScheme) => EventsSchema | undefined;
|
||||||
removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => EventsSchema | undefined;
|
removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => EventsSchema | undefined;
|
||||||
updatePoint: (
|
updatePoint: (
|
||||||
productUuid: string,
|
productUuid: string,
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
updates: Partial<ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema>
|
updates: Partial<PointsScheme>
|
||||||
) => EventsSchema | undefined;
|
) => EventsSchema | undefined;
|
||||||
|
|
||||||
// Action-level actions
|
// Action-level actions
|
||||||
@@ -32,13 +32,13 @@ type ProductsStore = {
|
|||||||
productUuid: string,
|
productUuid: string,
|
||||||
modelUuid: string,
|
modelUuid: string,
|
||||||
pointUuid: string,
|
pointUuid: string,
|
||||||
action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]
|
action: ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction
|
||||||
) => EventsSchema | undefined;
|
) => EventsSchema | undefined;
|
||||||
removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
||||||
updateAction: (
|
updateAction: (
|
||||||
productUuid: string,
|
productUuid: string,
|
||||||
actionUuid: string,
|
actionUuid: string,
|
||||||
updates: Partial<ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]>
|
updates: Partial<ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction>
|
||||||
) => EventsSchema | undefined;
|
) => EventsSchema | undefined;
|
||||||
|
|
||||||
// Trigger-level actionss
|
// Trigger-level actionss
|
||||||
@@ -65,9 +65,9 @@ type ProductsStore = {
|
|||||||
getEventByActionUuid: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
getEventByActionUuid: (productUuid: string, actionUuid: string) => EventsSchema | undefined;
|
||||||
getEventByTriggerUuid: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
|
getEventByTriggerUuid: (productUuid: string, triggerUuid: string) => EventsSchema | undefined;
|
||||||
getEventByPointUuid: (productUuid: string, pointUuid: string) => EventsSchema | undefined;
|
getEventByPointUuid: (productUuid: string, pointUuid: string) => EventsSchema | undefined;
|
||||||
getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema | undefined;
|
getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => PointsScheme | undefined;
|
||||||
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined;
|
getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) | undefined;
|
||||||
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined;
|
getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction) | undefined;
|
||||||
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||||
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||||
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined;
|
||||||
@@ -375,6 +375,15 @@ export const createProductStore = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event.type === "crane") {
|
||||||
|
if ('actions' in point) {
|
||||||
|
const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid);
|
||||||
|
if (index !== -1) {
|
||||||
|
point.actions.splice(index, 1);
|
||||||
|
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if ('action' in point && point.action?.actionUuid === actionUuid) {
|
} else if ('action' in point && point.action?.actionUuid === actionUuid) {
|
||||||
point.action = undefined;
|
point.action = undefined;
|
||||||
updatedEvent = JSON.parse(JSON.stringify(event));
|
updatedEvent = JSON.parse(JSON.stringify(event));
|
||||||
|
|||||||
1
app/src/types/builderTypes.d.ts
vendored
1
app/src/types/builderTypes.d.ts
vendored
@@ -32,6 +32,7 @@ interface Asset {
|
|||||||
};
|
};
|
||||||
eventData?: {
|
eventData?: {
|
||||||
type: string;
|
type: string;
|
||||||
|
subType: string;
|
||||||
point?: {
|
point?: {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
|
|||||||
104
app/src/types/simulationTypes.d.ts
vendored
104
app/src/types/simulationTypes.d.ts
vendored
@@ -1,4 +1,5 @@
|
|||||||
// Base Types
|
// Base Types
|
||||||
|
|
||||||
interface AssetEventSchema {
|
interface AssetEventSchema {
|
||||||
modelUuid: string;
|
modelUuid: string;
|
||||||
modelName: string;
|
modelName: string;
|
||||||
@@ -19,7 +20,9 @@ interface TriggerSchema {
|
|||||||
} | null;
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
interface ConveyorAction {
|
interface ConveyorAction {
|
||||||
actionUuid: string;
|
actionUuid: string;
|
||||||
actionName: string;
|
actionName: string;
|
||||||
@@ -107,9 +110,19 @@ interface HumanAction {
|
|||||||
triggers: TriggerSchema[];
|
triggers: TriggerSchema[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction;
|
interface CraneAction {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
actionType: "pickAndDrop";
|
||||||
|
maxPickUpCount: number;
|
||||||
|
triggers: TriggerSchema[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action = ConveyorAction | VehicleAction | RoboticArmAction | MachineAction | StorageAction | HumanAction | CraneAction;
|
||||||
|
|
||||||
|
|
||||||
// Points
|
// Points
|
||||||
|
|
||||||
interface ConveyorPointSchema {
|
interface ConveyorPointSchema {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
@@ -152,46 +165,69 @@ interface HumanPointSchema {
|
|||||||
actions: HumanAction[];
|
actions: HumanAction[];
|
||||||
}
|
}
|
||||||
|
|
||||||
type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema;
|
interface CranePointSchema {
|
||||||
|
uuid: string;
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
actions: CraneAction[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type PointsScheme = | ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema | CranePointSchema;
|
||||||
|
|
||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
||||||
interface ConveyorEventSchema extends AssetEventSchema {
|
interface ConveyorEventSchema extends AssetEventSchema {
|
||||||
type: "transfer";
|
type: "transfer";
|
||||||
|
subType: string;
|
||||||
speed: number;
|
speed: number;
|
||||||
points: ConveyorPointSchema[];
|
points: ConveyorPointSchema[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VehicleEventSchema extends AssetEventSchema {
|
interface VehicleEventSchema extends AssetEventSchema {
|
||||||
type: "vehicle";
|
type: "vehicle";
|
||||||
|
subType: "manual" | "automatic" | "semiAutomatic" | '';
|
||||||
speed: number;
|
speed: number;
|
||||||
point: VehiclePointSchema;
|
point: VehiclePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RoboticArmEventSchema extends AssetEventSchema {
|
interface RoboticArmEventSchema extends AssetEventSchema {
|
||||||
type: "roboticArm";
|
type: "roboticArm";
|
||||||
|
subType: string;
|
||||||
speed: number;
|
speed: number;
|
||||||
point: RoboticArmPointSchema;
|
point: RoboticArmPointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MachineEventSchema extends AssetEventSchema {
|
interface MachineEventSchema extends AssetEventSchema {
|
||||||
type: "machine";
|
type: "machine";
|
||||||
|
subType: string;
|
||||||
point: MachinePointSchema;
|
point: MachinePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StorageEventSchema extends AssetEventSchema {
|
interface StorageEventSchema extends AssetEventSchema {
|
||||||
type: "storageUnit";
|
type: "storageUnit";
|
||||||
|
subType: string;
|
||||||
point: StoragePointSchema;
|
point: StoragePointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface HumanEventSchema extends AssetEventSchema {
|
interface HumanEventSchema extends AssetEventSchema {
|
||||||
type: "human";
|
type: "human";
|
||||||
|
subType: string;
|
||||||
speed: number;
|
speed: number;
|
||||||
point: HumanPointSchema;
|
point: HumanPointSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
type EventsSchema = | ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema | HumanEventSchema;
|
interface CraneEventSchema extends AssetEventSchema {
|
||||||
|
type: "crane";
|
||||||
|
subType: "pillarJib" | '';
|
||||||
|
point: CranePointSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
type EventsSchema = | ConveyorEventSchema | VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema | HumanEventSchema | CraneEventSchema;
|
||||||
|
|
||||||
|
|
||||||
// Statuses
|
// Statuses
|
||||||
|
|
||||||
interface ConveyorStatus extends ConveyorEventSchema {
|
interface ConveyorStatus extends ConveyorEventSchema {
|
||||||
productUuid: string;
|
productUuid: string;
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
@@ -262,6 +298,24 @@ interface HumanStatus extends HumanEventSchema {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface CraneStatus extends CraneEventSchema {
|
||||||
|
productUuid: string;
|
||||||
|
currentPhase: string;
|
||||||
|
isActive: boolean;
|
||||||
|
isScheduled: boolean;
|
||||||
|
idleTime: number;
|
||||||
|
activeTime: number;
|
||||||
|
currentLoad: number;
|
||||||
|
currentMaterials: { materialType: string; materialId: string; }[];
|
||||||
|
currentAction?: {
|
||||||
|
actionUuid: string;
|
||||||
|
actionName: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Event Manager
|
||||||
|
|
||||||
type HumanEventState = {
|
type HumanEventState = {
|
||||||
humanId: string;
|
humanId: string;
|
||||||
actionQueue: {
|
actionQueue: {
|
||||||
@@ -282,7 +336,9 @@ type HumanEventManagerState = {
|
|||||||
humanStates: HumanEventState[];
|
humanStates: HumanEventState[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Materials
|
// Materials
|
||||||
|
|
||||||
interface MaterialSchema {
|
interface MaterialSchema {
|
||||||
materialId: string;
|
materialId: string;
|
||||||
materialName: string;
|
materialName: string;
|
||||||
@@ -316,14 +372,18 @@ interface MaterialSchema {
|
|||||||
|
|
||||||
type MaterialsSchema = MaterialSchema[];
|
type MaterialsSchema = MaterialSchema[];
|
||||||
|
|
||||||
|
|
||||||
// Products
|
// Products
|
||||||
|
|
||||||
type productsSchema = {
|
type productsSchema = {
|
||||||
productName: string;
|
productName: string;
|
||||||
productUuid: string;
|
productUuid: string;
|
||||||
eventDatas: EventsSchema[];
|
eventDatas: EventsSchema[];
|
||||||
}[];
|
}[];
|
||||||
|
|
||||||
|
|
||||||
// Material History
|
// Material History
|
||||||
|
|
||||||
interface MaterialHistoryEntry {
|
interface MaterialHistoryEntry {
|
||||||
material: MaterialSchema;
|
material: MaterialSchema;
|
||||||
removedAt: string;
|
removedAt: string;
|
||||||
@@ -331,7 +391,8 @@ interface MaterialHistoryEntry {
|
|||||||
|
|
||||||
type MaterialHistorySchema = MaterialHistoryEntry[];
|
type MaterialHistorySchema = MaterialHistoryEntry[];
|
||||||
|
|
||||||
//IK
|
|
||||||
|
// IK Constraints
|
||||||
|
|
||||||
type Link = {
|
type Link = {
|
||||||
index: number;
|
index: number;
|
||||||
@@ -350,3 +411,38 @@ type IK = {
|
|||||||
maxheight?: number;
|
maxheight?: number;
|
||||||
minheight?: number;
|
minheight?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Conveyor Spline Points
|
||||||
|
|
||||||
|
type NormalConveyor = {
|
||||||
|
type: 'normal';
|
||||||
|
points: [number, number, number][][];
|
||||||
|
}
|
||||||
|
|
||||||
|
type YJunctionConveyor = {
|
||||||
|
type: 'y-junction';
|
||||||
|
points: [number, number, number][][];
|
||||||
|
}
|
||||||
|
|
||||||
|
type CurvedConveyor = {
|
||||||
|
type: 'curved';
|
||||||
|
points: [number, number, number][][];
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConveyorPoints = NormalConveyor | YJunctionConveyor | CurvedConveyor;
|
||||||
|
|
||||||
|
|
||||||
|
// Crane Constraints
|
||||||
|
|
||||||
|
|
||||||
|
type PillarJibCrane = {
|
||||||
|
trolleySpeed: number;
|
||||||
|
hookSpeed: number;
|
||||||
|
rotationSpeed: number;
|
||||||
|
trolleyMinOffset: number
|
||||||
|
trolleyMaxOffset: number;
|
||||||
|
hookMinOffset: number;
|
||||||
|
hookMaxOffset: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type CraneConstraints = PillarJibCrane;
|
||||||
3
app/src/types/world/worldTypes.d.ts
vendored
3
app/src/types/world/worldTypes.d.ts
vendored
@@ -198,6 +198,7 @@ export type FloorItemType = {
|
|||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
eventData?: {
|
eventData?: {
|
||||||
type: string;
|
type: string;
|
||||||
|
subType: string;
|
||||||
point?: {
|
point?: {
|
||||||
uuid: string;
|
uuid: string;
|
||||||
position: [number, number, number];
|
position: [number, number, number];
|
||||||
@@ -221,7 +222,7 @@ export type setFloorItemSetState = React.Dispatch<React.SetStateAction<FloorItem
|
|||||||
|
|
||||||
// Configuration for wall items, including model, scale, position, and rotation
|
// Configuration for wall items, including model, scale, position, and rotation
|
||||||
interface WallItem {
|
interface WallItem {
|
||||||
type: "fixed-move" | "free-move" | undefined;
|
type: "fixedMove" | "freeMove" | undefined;
|
||||||
model?: THREE.Group;
|
model?: THREE.Group;
|
||||||
modelUuid?: string;
|
modelUuid?: string;
|
||||||
assetId: string;
|
assetId: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user