feat: Enhance InputWithDropDown to support disabled state
fix: Update Model component to manage animation states and transitions more effectively feat: Implement worker action handling in useWorkerHandler for material management feat: Add MaterialAnimator to HumanInstance for dynamic material loading feat: Extend useTriggerHandler to support interactions between humans and various entities feat: Create WorkerAction component for managing load capacity and actions feat: Introduce MaterialAnimator for human instances to visualize material loads refactor: Update asset store to manage animation completion state fix: Ensure proper handling of human materials in useHumanStore
This commit is contained in:
@@ -35,7 +35,7 @@ const AssetProperties: React.FC = () => {
|
|||||||
|
|
||||||
const handleAnimationClick = (animation: string) => {
|
const handleAnimationClick = (animation: string) => {
|
||||||
if (selectedFloorItem) {
|
if (selectedFloorItem) {
|
||||||
setCurrentAnimation(selectedFloorItem.uuid, animation, true, loopAnimation);
|
setCurrentAnimation(selectedFloorItem.uuid, animation, true, loopAnimation, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
import EyeDropInput from "../../../../../ui/inputs/EyeDropInput";
|
|
||||||
|
|
||||||
interface TravelActionProps {
|
interface TravelActionProps {
|
||||||
loadCapacity: {
|
loadCapacity: {
|
||||||
@@ -17,22 +16,12 @@ interface TravelActionProps {
|
|||||||
defaultValue: string;
|
defaultValue: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
};
|
};
|
||||||
pickPoint?: {
|
|
||||||
value: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
};
|
|
||||||
unloadPoint?: {
|
|
||||||
value: string;
|
|
||||||
onChange: (value: string) => void;
|
|
||||||
};
|
|
||||||
clearPoints: () => void;
|
clearPoints: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const TravelAction: React.FC<TravelActionProps> = ({
|
const TravelAction: React.FC<TravelActionProps> = ({
|
||||||
loadCapacity,
|
loadCapacity,
|
||||||
unloadDuration,
|
unloadDuration,
|
||||||
pickPoint,
|
|
||||||
unloadPoint,
|
|
||||||
clearPoints,
|
clearPoints,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
@@ -44,7 +33,7 @@ const TravelAction: React.FC<TravelActionProps> = ({
|
|||||||
max={loadCapacity.max}
|
max={loadCapacity.max}
|
||||||
defaultValue={loadCapacity.defaultValue}
|
defaultValue={loadCapacity.defaultValue}
|
||||||
step={1}
|
step={1}
|
||||||
activeOption="s"
|
activeOption="unit"
|
||||||
onClick={() => { }}
|
onClick={() => { }}
|
||||||
onChange={loadCapacity.onChange}
|
onChange={loadCapacity.onChange}
|
||||||
/>
|
/>
|
||||||
@@ -74,20 +63,6 @@ const TravelAction: React.FC<TravelActionProps> = ({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{pickPoint && (
|
|
||||||
<EyeDropInput
|
|
||||||
label="Pick Point"
|
|
||||||
value={pickPoint.value}
|
|
||||||
onChange={pickPoint.onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{unloadPoint && (
|
|
||||||
<EyeDropInput
|
|
||||||
label="Unload Point"
|
|
||||||
value={unloadPoint.value}
|
|
||||||
onChange={unloadPoint.onChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import React from "react";
|
||||||
|
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||||
|
|
||||||
|
interface WorkerActionProps {
|
||||||
|
loadCapacity: {
|
||||||
|
value: string;
|
||||||
|
min: number;
|
||||||
|
max: number;
|
||||||
|
step: number;
|
||||||
|
defaultValue: string;
|
||||||
|
disabled?: boolean,
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
};
|
||||||
|
clearPoints: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorkerAction: React.FC<WorkerActionProps> = ({
|
||||||
|
loadCapacity,
|
||||||
|
clearPoints,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<InputWithDropDown
|
||||||
|
label="Load Capacity"
|
||||||
|
value={loadCapacity.value}
|
||||||
|
min={loadCapacity.min}
|
||||||
|
max={loadCapacity.max}
|
||||||
|
disabled={loadCapacity.disabled}
|
||||||
|
defaultValue={loadCapacity.defaultValue}
|
||||||
|
step={loadCapacity.step}
|
||||||
|
activeOption="unit"
|
||||||
|
onClick={() => { }}
|
||||||
|
onChange={loadCapacity.onChange}
|
||||||
|
/>
|
||||||
|
<div className="selected-actions-list">
|
||||||
|
<div className="value-field-container">
|
||||||
|
<div className="label">Reset</div>
|
||||||
|
<button
|
||||||
|
id="rest-button"
|
||||||
|
type="button"
|
||||||
|
className="regularDropdown-container"
|
||||||
|
onClick={() => {
|
||||||
|
clearPoints();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WorkerAction;
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
import React, { useRef } from "react";
|
|
||||||
import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons";
|
|
||||||
import { handleResize } from "../../../../../../functions/handleResizePannel";
|
|
||||||
import { useSelectedAction, useSelectedAnimation } from "../../../../../../store/simulation/useSimulationStore";
|
|
||||||
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
|
||||||
|
|
||||||
interface AnimationListProps {
|
|
||||||
animationOptions: string[];
|
|
||||||
animationSequences: {
|
|
||||||
animationUuid: string;
|
|
||||||
animationName: string;
|
|
||||||
animationType: "behaviour" | "animatedTravel";
|
|
||||||
animation: string | null;
|
|
||||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null };
|
|
||||||
}[];
|
|
||||||
onAddAnimation: () => void;
|
|
||||||
onRemoveAnimation: (animationUuid: string) => void;
|
|
||||||
handleAnimationSelect: (animationUuid: string) => void;
|
|
||||||
handleRenameAnimation: (animationUuid: string, newName: string) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const AnimationList: React.FC<AnimationListProps> = ({
|
|
||||||
animationSequences,
|
|
||||||
onAddAnimation,
|
|
||||||
onRemoveAnimation,
|
|
||||||
handleAnimationSelect,
|
|
||||||
handleRenameAnimation,
|
|
||||||
}) => {
|
|
||||||
const animationContainerRef = useRef<HTMLDivElement>(null);
|
|
||||||
const { selectedAction } = useSelectedAction();
|
|
||||||
const { selectedAnimation } = useSelectedAnimation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="actions-list-container">
|
|
||||||
<div className="actions">
|
|
||||||
<div className="header">
|
|
||||||
<div className="header-value">Animation Sequences</div>
|
|
||||||
<button
|
|
||||||
id="add-action-button"
|
|
||||||
className="add-button"
|
|
||||||
onClick={onAddAnimation}
|
|
||||||
disabled={!selectedAction.actionId}
|
|
||||||
>
|
|
||||||
<AddIcon /> Add
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="lists-main-container"
|
|
||||||
ref={animationContainerRef}
|
|
||||||
style={{ height: "120px" }}
|
|
||||||
>
|
|
||||||
<div className="list-container">
|
|
||||||
{animationSequences.map((sequence) => (
|
|
||||||
<div
|
|
||||||
key={sequence.animationUuid}
|
|
||||||
className={`list-item ${selectedAnimation?.animationUuid === sequence.animationUuid ? "active" : ""}`}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
id="action-button"
|
|
||||||
className="value"
|
|
||||||
onClick={() =>
|
|
||||||
handleAnimationSelect(sequence.animationUuid)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<RenameInput
|
|
||||||
value={sequence.animationName}
|
|
||||||
onRename={(value) => handleRenameAnimation(sequence.animationUuid, value)}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
{animationSequences.length > 1 && (
|
|
||||||
<button
|
|
||||||
id="remove-action-button"
|
|
||||||
className="remove-button"
|
|
||||||
onClick={() => onRemoveAnimation(sequence.animationUuid)}
|
|
||||||
>
|
|
||||||
<RemoveIcon />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
{animationSequences.length > 0 && (
|
|
||||||
<button
|
|
||||||
className="resize-icon"
|
|
||||||
id="action-resize"
|
|
||||||
onMouseDown={(e: any) => handleResize(e, animationContainerRef)}
|
|
||||||
>
|
|
||||||
<ResizeHeightIcon />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AnimationList;
|
|
||||||
@@ -4,30 +4,27 @@ import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
|||||||
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
||||||
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
import LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
||||||
import Trigger from "../trigger/Trigger";
|
import Trigger from "../trigger/Trigger";
|
||||||
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
|
|
||||||
import ActionsList from "../components/ActionsList";
|
import ActionsList from "../components/ActionsList";
|
||||||
import AnimationList from "../components/AnimationList";
|
|
||||||
import { useSelectedEventData, useSelectedAction, useSelectedAnimation } from "../../../../../../store/simulation/useSimulationStore";
|
import { useSelectedEventData, useSelectedAction, useSelectedAnimation } from "../../../../../../store/simulation/useSimulationStore";
|
||||||
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||||
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
|
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
|
||||||
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
|
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
|
||||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import WorkerAction from "../actions/workerAction";
|
||||||
|
|
||||||
function HumanMechanics() {
|
function HumanMechanics() {
|
||||||
const [activeOption, setActiveOption] = useState<"worker">("worker");
|
const [activeOption, setActiveOption] = useState<"worker">("worker");
|
||||||
const [animationOptions, setAnimationOptions] = useState<string[]>([]);
|
|
||||||
const [speed, setSpeed] = useState("0.5");
|
const [speed, setSpeed] = useState("0.5");
|
||||||
|
const [loadCapacity, setLoadCapacity] = useState("1");
|
||||||
const [currentAction, setCurrentAction] = useState<HumanAction | undefined>();
|
const [currentAction, setCurrentAction] = useState<HumanAction | undefined>();
|
||||||
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
|
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
|
||||||
const { selectedEventData } = useSelectedEventData();
|
const { selectedEventData } = useSelectedEventData();
|
||||||
const { productStore, assetStore } = useSceneContext();
|
const { productStore } = useSceneContext();
|
||||||
const { getAssetById } = assetStore();
|
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid } = productStore();
|
||||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||||
const { selectedAnimation, setSelectedAnimation } = useSelectedAnimation();
|
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
const { selectedVersion } = selectedVersionStore();
|
const { selectedVersion } = selectedVersionStore();
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
@@ -44,6 +41,13 @@ function HumanMechanics() {
|
|||||||
setSelectedPointData(point);
|
setSelectedPointData(point);
|
||||||
setCurrentAction(point.action);
|
setCurrentAction(point.action);
|
||||||
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
setSelectedAction(point.action.actionUuid, point.action.actionName);
|
||||||
|
setSpeed((
|
||||||
|
getEventByModelUuid(
|
||||||
|
selectedProduct.productUuid,
|
||||||
|
selectedEventData?.data.modelUuid || ""
|
||||||
|
) as HumanEventSchema | undefined
|
||||||
|
)?.speed?.toString() || "1");
|
||||||
|
setLoadCapacity(point.action.loadCapacity.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
clearSelectedAction();
|
clearSelectedAction();
|
||||||
@@ -68,6 +72,7 @@ function HumanMechanics() {
|
|||||||
clearSelectedAction();
|
clearSelectedAction();
|
||||||
setCurrentAction(undefined);
|
setCurrentAction(undefined);
|
||||||
setSpeed("0.5");
|
setSpeed("0.5");
|
||||||
|
setLoadCapacity("1");
|
||||||
}
|
}
|
||||||
}, [selectedEventData, selectedProduct, selectedAction]);
|
}, [selectedEventData, selectedProduct, selectedAction]);
|
||||||
|
|
||||||
@@ -130,6 +135,29 @@ function HumanMechanics() {
|
|||||||
setSpeed(value);
|
setSpeed(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleLoadCapacityChange = (value: string) => {
|
||||||
|
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||||
|
|
||||||
|
const updatedAction = { ...currentAction };
|
||||||
|
updatedAction.loadCapacity = parseInt(value)
|
||||||
|
|
||||||
|
const updatedPoint = { ...selectedPointData, action: updatedAction };
|
||||||
|
|
||||||
|
const event = updateAction(
|
||||||
|
selectedProduct.productUuid,
|
||||||
|
selectedAction.actionId,
|
||||||
|
updatedAction
|
||||||
|
);
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || '', event);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentAction(updatedAction);
|
||||||
|
setSelectedPointData(updatedPoint);
|
||||||
|
setLoadCapacity(value);
|
||||||
|
};
|
||||||
|
|
||||||
const handleClearPoints = () => {
|
const handleClearPoints = () => {
|
||||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||||
|
|
||||||
@@ -239,7 +267,18 @@ function HumanMechanics() {
|
|||||||
disabled={true}
|
disabled={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<PickAndPlaceAction clearPoints={handleClearPoints} />
|
<WorkerAction
|
||||||
|
loadCapacity={{
|
||||||
|
value: loadCapacity,
|
||||||
|
min: 1,
|
||||||
|
max: 5,
|
||||||
|
step: 1,
|
||||||
|
defaultValue: "1",
|
||||||
|
disabled: true,
|
||||||
|
onChange: handleLoadCapacityChange,
|
||||||
|
}}
|
||||||
|
clearPoints={handleClearPoints}
|
||||||
|
/>
|
||||||
<div className="tirgger">
|
<div className="tirgger">
|
||||||
<Trigger selectedPointData={selectedPointData as any} type="Human" />
|
<Trigger selectedPointData={selectedPointData as any} type="Human" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -272,14 +272,6 @@ function VehicleMechanics() {
|
|||||||
onChange: handleUnloadDurationChange,
|
onChange: handleUnloadDurationChange,
|
||||||
}}
|
}}
|
||||||
clearPoints={handleClearPoints}
|
clearPoints={handleClearPoints}
|
||||||
// pickPoint={{
|
|
||||||
// value: currentPickPoint,
|
|
||||||
// onChange: handlePickPointChange,
|
|
||||||
// }}
|
|
||||||
// unloadPoint={{
|
|
||||||
// value: currentUnloadPoint,
|
|
||||||
// onChange: handleUnloadPointChange,
|
|
||||||
// }}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ type InputWithDropDownProps = {
|
|||||||
max?: number;
|
max?: number;
|
||||||
step?: number;
|
step?: number;
|
||||||
defaultValue?: string;
|
defaultValue?: string;
|
||||||
|
disabled?: boolean;
|
||||||
options?: string[]; // Array of dropdown options
|
options?: string[]; // Array of dropdown options
|
||||||
activeOption?: string; // The currently active dropdown option
|
activeOption?: string; // The currently active dropdown option
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
@@ -23,6 +24,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
|||||||
max,
|
max,
|
||||||
step,
|
step,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
disabled = false,
|
||||||
options,
|
options,
|
||||||
activeOption,
|
activeOption,
|
||||||
onClick,
|
onClick,
|
||||||
@@ -54,6 +56,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
|||||||
type="number"
|
type="number"
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
// value={value}
|
// value={value}
|
||||||
|
disabled={disabled}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
onChange(e.target.value);
|
onChange(e.target.value);
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
const { subModule } = useSubModuleStore();
|
const { subModule } = useSubModuleStore();
|
||||||
const { activeModule } = useModuleStore();
|
const { activeModule } = useModuleStore();
|
||||||
const { assetStore, eventStore, productStore } = useSceneContext();
|
const { assetStore, eventStore, productStore } = useSceneContext();
|
||||||
const { removeAsset, setAnimations, resetAnimation } = assetStore();
|
const { removeAsset, setAnimations, resetAnimation, setAnimationComplete, setCurrentAnimation: setAnmationAnimation } = assetStore();
|
||||||
const { setTop } = useTopData();
|
const { setTop } = useTopData();
|
||||||
const { setLeft } = useLeftData();
|
const { setLeft } = useLeftData();
|
||||||
const { getIsEventInProduct } = productStore();
|
const { getIsEventInProduct } = productStore();
|
||||||
@@ -49,10 +49,9 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
const mixerRef = useRef<THREE.AnimationMixer>();
|
const mixerRef = useRef<THREE.AnimationMixer>();
|
||||||
const actions = useRef<{ [name: string]: THREE.AnimationAction }>({});
|
const actions = useRef<{ [name: string]: THREE.AnimationAction }>({});
|
||||||
const [currentAnimation, setCurrentAnimation] = useState<string | null>(null);
|
|
||||||
const [previousAnimation, setPreviousAnimation] = useState<string | null>(null);
|
const [previousAnimation, setPreviousAnimation] = useState<string | null>(null);
|
||||||
const [blendFactor, setBlendFactor] = useState(0);
|
const blendFactor = useRef(0);
|
||||||
const blendDuration = 0.3;
|
const blendDuration = 0.5;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDeletableFloorItem(null);
|
setDeletableFloorItem(null);
|
||||||
@@ -283,63 +282,48 @@ function Model({ asset }: { readonly asset: Asset }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleAnimationComplete = useCallback(() => {
|
const handleAnimationComplete = useCallback(() => {
|
||||||
console.log(`Animation "${currentAnimation}" completed`);
|
if (asset.animationState) {
|
||||||
}, [currentAnimation]);
|
setAnimationComplete(asset.modelUuid, true);
|
||||||
|
}
|
||||||
|
}, [asset.animationState]);
|
||||||
|
|
||||||
useFrame((_, delta) => {
|
useFrame((_, delta) => {
|
||||||
if (mixerRef.current) {
|
if (mixerRef.current) {
|
||||||
if (blendFactor < 1) {
|
|
||||||
setBlendFactor(prev => Math.min(prev + delta / blendDuration, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
mixerRef.current.update(delta);
|
mixerRef.current.update(delta);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (asset.animationState && asset.animationState.isPlaying) {
|
if (!asset.animationState || !mixerRef.current) return;
|
||||||
if (!mixerRef.current) return;
|
|
||||||
|
|
||||||
if (asset.animationState.current !== currentAnimation) {
|
const { current, loopAnimation, isPlaying } = asset.animationState;
|
||||||
setPreviousAnimation(currentAnimation);
|
const currentAction = actions.current[current];
|
||||||
setCurrentAnimation(asset.animationState.current);
|
|
||||||
setBlendFactor(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentAction = actions.current[asset.animationState.current];
|
|
||||||
const previousAction = previousAnimation ? actions.current[previousAnimation] : null;
|
const previousAction = previousAnimation ? actions.current[previousAnimation] : null;
|
||||||
|
|
||||||
if (currentAction) {
|
if (isPlaying && currentAction) {
|
||||||
const loopMode = asset.animationState.loopAnimation ? THREE.LoopRepeat : THREE.LoopOnce;
|
blendFactor.current = 0;
|
||||||
|
|
||||||
currentAction.reset();
|
currentAction.reset();
|
||||||
currentAction.setLoop(loopMode, loopMode === THREE.LoopRepeat ? Infinity : 1);
|
currentAction.setLoop(loopAnimation ? THREE.LoopRepeat : THREE.LoopOnce, loopAnimation ? Infinity : 1);
|
||||||
|
currentAction.clampWhenFinished = true;
|
||||||
|
|
||||||
|
if (previousAction && previousAction !== currentAction) {
|
||||||
|
previousAction.crossFadeTo(currentAction, blendDuration, false);
|
||||||
|
}
|
||||||
|
|
||||||
currentAction.play();
|
currentAction.play();
|
||||||
|
|
||||||
mixerRef.current.addEventListener('finished', handleAnimationComplete);
|
mixerRef.current.addEventListener('finished', handleAnimationComplete);
|
||||||
|
setPreviousAnimation(current);
|
||||||
if (previousAction && blendFactor < 1) {
|
|
||||||
previousAction.crossFadeTo(currentAction, blendDuration, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.entries(actions.current).forEach(([name, action]) => {
|
|
||||||
if ((asset.animationState && name !== asset.animationState.current) && name !== previousAnimation) {
|
|
||||||
action.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
Object.values(actions.current).forEach((action) => action.stop());
|
Object.values(actions.current).forEach((action) => action.stop());
|
||||||
setCurrentAnimation(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
if (mixerRef.current) {
|
if (mixerRef.current) {
|
||||||
mixerRef.current.removeEventListener('finished', handleAnimationComplete);
|
mixerRef.current.removeEventListener('finished', handleAnimationComplete);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}, [asset.animationState, currentAnimation, previousAnimation, handleAnimationComplete]);
|
}, [asset.animationState?.current, asset.animationState?.isPlaying]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<group
|
<group
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { useProductContext } from "../../../products/productContext";
|
|||||||
export function useWorkerHandler() {
|
export function useWorkerHandler() {
|
||||||
const { materialStore, humanStore, productStore } = useSceneContext();
|
const { materialStore, humanStore, productStore } = useSceneContext();
|
||||||
const { getMaterialById } = materialStore();
|
const { getMaterialById } = materialStore();
|
||||||
const { } = humanStore();
|
|
||||||
const { getModelUuidByActionUuid } = productStore();
|
const { getModelUuidByActionUuid } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
|
const { incrementHumanLoad, addCurrentMaterial } = humanStore();
|
||||||
|
|
||||||
const workerLogStatus = (materialUuid: string, status: string) => {
|
const workerLogStatus = (materialUuid: string, status: string) => {
|
||||||
echo.info(`${materialUuid}, ${status}`);
|
echo.info(`${materialUuid}, ${status}`);
|
||||||
@@ -23,6 +23,8 @@ export function useWorkerHandler() {
|
|||||||
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
|
const modelUuid = getModelUuidByActionUuid(selectedProduct.productUuid, action.actionUuid);
|
||||||
if (!modelUuid) return;
|
if (!modelUuid) return;
|
||||||
|
|
||||||
|
incrementHumanLoad(modelUuid, 1);
|
||||||
|
addCurrentMaterial(modelUuid, material.materialType, material.materialId);
|
||||||
|
|
||||||
workerLogStatus(material.materialName, `performing worker action`);
|
workerLogStatus(material.materialName, `performing worker action`);
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ interface HumanAnimatorProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, startUnloadingProcess }: Readonly<HumanAnimatorProps>) {
|
function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, startUnloadingProcess }: Readonly<HumanAnimatorProps>) {
|
||||||
const { humanStore } = useSceneContext();
|
const { humanStore, assetStore } = useSceneContext();
|
||||||
const { getHumanById } = humanStore();
|
const { getHumanById } = humanStore();
|
||||||
|
const { setCurrentAnimation } = assetStore();
|
||||||
const { isPaused } = usePauseButtonStore();
|
const { isPaused } = usePauseButtonStore();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { speed } = useAnimationPlaySpeed();
|
const { speed } = useAnimationPlaySpeed();
|
||||||
@@ -116,6 +117,17 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
|||||||
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
const t = (progressRef.current - accumulatedDistance) / segmentDistance;
|
||||||
const position = start.clone().lerp(end, t);
|
const position = start.clone().lerp(end, t);
|
||||||
object.position.copy(position);
|
object.position.copy(position);
|
||||||
|
if (human.currentMaterials.length > 0) {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
|
||||||
|
} else {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (human.currentMaterials.length > 0) {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true);
|
||||||
|
} else {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +145,11 @@ function HumanAnimator({ path, handleCallBack, currentPhase, human, reset, start
|
|||||||
object.rotation.copy(targetEuler);
|
object.rotation.copy(targetEuler);
|
||||||
setRestingRotation(false);
|
setRestingRotation(false);
|
||||||
}
|
}
|
||||||
|
if (human.currentMaterials.length > 0) {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle_with_box', true, true, true);
|
||||||
|
} else {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { useThree } from '@react-three/fiber';
|
||||||
|
import * as THREE from 'three';
|
||||||
|
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
||||||
|
|
||||||
|
const MaterialAnimator = ({ human }: { human: HumanStatus }) => {
|
||||||
|
const meshRef = useRef<any>(null!);
|
||||||
|
const [hasLoad, setHasLoad] = useState(false);
|
||||||
|
const { scene } = useThree();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setHasLoad(human.currentLoad > 0);
|
||||||
|
}, [human.currentLoad]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!hasLoad || !meshRef.current) return;
|
||||||
|
|
||||||
|
const humanModel = scene.getObjectByProperty("uuid", human.modelUuid) as THREE.Object3D;
|
||||||
|
if (!humanModel) return;
|
||||||
|
|
||||||
|
const bone = humanModel.getObjectByName('PlaceObjectRefBone') as THREE.Bone;
|
||||||
|
if (bone) {
|
||||||
|
bone.add(meshRef.current);
|
||||||
|
|
||||||
|
meshRef.current.position.set(0, 0, 0);
|
||||||
|
meshRef.current.rotation.set(0, 0, 0);
|
||||||
|
meshRef.current.scale.set(1, 1, 1);
|
||||||
|
}
|
||||||
|
}, [hasLoad, human.modelUuid]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{hasLoad && human.currentMaterials.length > 0 && (
|
||||||
|
<MaterialModel
|
||||||
|
matRef={meshRef}
|
||||||
|
materialId={human.currentMaterials[0].materialId || ''}
|
||||||
|
materialType={human.currentMaterials[0].materialType || 'Default material'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default MaterialAnimator;
|
||||||
@@ -8,21 +8,24 @@ import { useSceneContext } from '../../../../scene/sceneContext';
|
|||||||
import { useProductContext } from '../../../products/productContext';
|
import { useProductContext } from '../../../products/productContext';
|
||||||
|
|
||||||
import HumanAnimator from '../animator/humanAnimator';
|
import HumanAnimator from '../animator/humanAnimator';
|
||||||
|
import MaterialAnimator from '../animator/materialAnimator';
|
||||||
|
|
||||||
function HumanInstance({ human }: { human: HumanStatus }) {
|
function HumanInstance({ human }: { human: HumanStatus }) {
|
||||||
const { navMesh } = useNavMesh();
|
const { navMesh } = useNavMesh();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const { materialStore, armBotStore, conveyorStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext();
|
const { assetStore, materialStore, armBotStore, conveyorStore, machineStore, vehicleStore, humanStore, storageUnitStore, productStore } = useSceneContext();
|
||||||
const { removeMaterial, setEndTime } = materialStore();
|
const { removeMaterial, setEndTime } = materialStore();
|
||||||
const { getStorageUnitById } = storageUnitStore();
|
const { getStorageUnitById } = storageUnitStore();
|
||||||
const { getArmBotById } = armBotStore();
|
const { getArmBotById } = armBotStore();
|
||||||
const { getConveyorById } = conveyorStore();
|
const { getConveyorById } = conveyorStore();
|
||||||
const { getVehicleById } = vehicleStore();
|
const { getVehicleById } = vehicleStore();
|
||||||
|
const { getMachineById } = machineStore();
|
||||||
const { triggerPointActions } = useTriggerHandler();
|
const { triggerPointActions } = useTriggerHandler();
|
||||||
|
const { setCurrentAnimation, resetAnimation, getAssetById } = assetStore();
|
||||||
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
|
const { getActionByUuid, getEventByModelUuid, getTriggerByUuid } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
const { humans, setHumanActive, setHumanState, setHumanPicking, clearCurrentMaterials, setHumanLoad, decrementHumanLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore();
|
const { setHumanActive, setHumanState, setHumanPicking, clearCurrentMaterials, setHumanLoad, decrementHumanLoad, removeLastMaterial, getLastMaterial, incrementIdleTime, incrementActiveTime, resetTime } = humanStore();
|
||||||
|
|
||||||
const [currentPhase, setCurrentPhase] = useState<string>('init');
|
const [currentPhase, setCurrentPhase] = useState<string>('init');
|
||||||
const [path, setPath] = useState<[number, number, number][]>([]);
|
const [path, setPath] = useState<[number, number, number][]>([]);
|
||||||
@@ -32,11 +35,11 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
const isPausedRef = useRef<boolean>(false);
|
const isPausedRef = useRef<boolean>(false);
|
||||||
const isSpeedRef = useRef<number>(0);
|
const isSpeedRef = useRef<number>(0);
|
||||||
let startTime: number;
|
let startTime: number;
|
||||||
let fixedInterval: number;
|
|
||||||
const { speed } = useAnimationPlaySpeed();
|
const { speed } = useAnimationPlaySpeed();
|
||||||
const { isPaused } = usePauseButtonStore();
|
const { isPaused } = usePauseButtonStore();
|
||||||
const previousTimeRef = useRef<number | null>(null);
|
const previousTimeRef = useRef<number | null>(null);
|
||||||
const animationFrameIdRef = useRef<number | null>(null);
|
const animationFrameIdRef = useRef<number | null>(null);
|
||||||
|
const humanAsset = getAssetById(human.modelUuid);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
isPausedRef.current = isPaused;
|
isPausedRef.current = isPaused;
|
||||||
@@ -69,7 +72,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
}, [navMesh]);
|
}, [navMesh]);
|
||||||
|
|
||||||
function humanStatus(modelId: string, status: string) {
|
function humanStatus(modelId: string, status: string) {
|
||||||
console.log(`${modelId} , ${status}`);
|
// console.log(`${modelId} , ${status}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset() {
|
function reset() {
|
||||||
@@ -78,6 +81,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
setHumanPicking(human.modelUuid, false);
|
setHumanPicking(human.modelUuid, false);
|
||||||
setHumanState(human.modelUuid, 'idle');
|
setHumanState(human.modelUuid, 'idle');
|
||||||
setHumanLoad(human.modelUuid, 0);
|
setHumanLoad(human.modelUuid, 0);
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
setPath([]);
|
setPath([]);
|
||||||
startTime = 0;
|
startTime = 0;
|
||||||
isPausedRef.current = false;
|
isPausedRef.current = false;
|
||||||
@@ -110,8 +114,57 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
setHumanState(human.modelUuid, 'running');
|
setHumanState(human.modelUuid, 'running');
|
||||||
setHumanPicking(human.modelUuid, false);
|
setHumanPicking(human.modelUuid, false);
|
||||||
setHumanActive(human.modelUuid, true);
|
setHumanActive(human.modelUuid, true);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
|
||||||
humanStatus(human.modelUuid, 'Started from init, heading to pickup');
|
humanStatus(human.modelUuid, 'Started from init, heading to pickup');
|
||||||
return;
|
return;
|
||||||
|
} else if (!human.isActive && human.state === 'idle' && currentPhase === 'picking') {
|
||||||
|
if (humanAsset && human.currentLoad === human.point.action.loadCapacity && human.currentMaterials.length > 0 && humanAsset.animationState?.current === 'pickup' && humanAsset.animationState?.isCompleted) {
|
||||||
|
if (human.point.action.pickUpPoint && human.point.action.dropPoint) {
|
||||||
|
const toDrop = computePath(
|
||||||
|
new THREE.Vector3(
|
||||||
|
human.point.action.pickUpPoint.position?.[0] ?? 0,
|
||||||
|
human.point.action.pickUpPoint.position?.[1] ?? 0,
|
||||||
|
human.point.action.pickUpPoint.position?.[2] ?? 0
|
||||||
|
),
|
||||||
|
new THREE.Vector3(
|
||||||
|
human.point.action.dropPoint.position?.[0] ?? 0,
|
||||||
|
human.point.action.dropPoint.position?.[1] ?? 0,
|
||||||
|
human.point.action.dropPoint.position?.[2] ?? 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setPath(toDrop);
|
||||||
|
setCurrentPhase('pickup-drop');
|
||||||
|
setHumanState(human.modelUuid, 'running');
|
||||||
|
setHumanPicking(human.modelUuid, false);
|
||||||
|
setHumanPicking(human.modelUuid, true);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'walk_with_box', true, true, true);
|
||||||
|
humanStatus(human.modelUuid, 'Started from pickup point, heading to drop point');
|
||||||
|
}
|
||||||
|
} else if (human.currentLoad === human.point.action.loadCapacity && human.currentMaterials.length > 0) {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'pickup', true, false, false);
|
||||||
|
}
|
||||||
|
} else if (!human.isActive && human.state === 'idle' && currentPhase === 'dropping' && human.currentLoad === 0) {
|
||||||
|
if (human.point.action.pickUpPoint && human.point.action.dropPoint) {
|
||||||
|
const dropToPickup = computePath(
|
||||||
|
new THREE.Vector3(
|
||||||
|
human.point.action.dropPoint.position?.[0] ?? 0,
|
||||||
|
human.point.action.dropPoint.position?.[1] ?? 0,
|
||||||
|
human.point.action.dropPoint.position?.[2] ?? 0
|
||||||
|
),
|
||||||
|
new THREE.Vector3(
|
||||||
|
human.point.action.pickUpPoint.position?.[0] ?? 0,
|
||||||
|
human.point.action.pickUpPoint.position?.[1] ?? 0,
|
||||||
|
human.point.action.pickUpPoint.position?.[2] ?? 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
setPath(dropToPickup);
|
||||||
|
setCurrentPhase('drop-pickup');
|
||||||
|
setHumanState(human.modelUuid, 'running');
|
||||||
|
setHumanPicking(human.modelUuid, false);
|
||||||
|
setHumanActive(human.modelUuid, true);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'walking', true, true, true);
|
||||||
|
humanStatus(human.modelUuid, 'Started from dropping point, heading to pickup point');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -119,17 +172,488 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
reset()
|
reset()
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [human, currentPhase, path, isPlaying]);
|
}, [human, currentPhase, path, isPlaying, humanAsset?.animationState?.isCompleted]);
|
||||||
|
|
||||||
function handleCallBack() {
|
function handleCallBack() {
|
||||||
if (currentPhase === 'init-pickup') {
|
if (currentPhase === 'init-pickup') {
|
||||||
setCurrentPhase('picking');
|
setCurrentPhase('picking');
|
||||||
|
setHumanState(human.modelUuid, 'idle');
|
||||||
|
setHumanPicking(human.modelUuid, true);
|
||||||
|
setHumanActive(human.modelUuid, false);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||||
|
humanStatus(human.modelUuid, 'Reached pickup point, waiting for material');
|
||||||
|
setPath([]);
|
||||||
} else if (currentPhase === 'pickup-drop') {
|
} else if (currentPhase === 'pickup-drop') {
|
||||||
|
setCurrentPhase('dropping');
|
||||||
|
setHumanState(human.modelUuid, 'idle');
|
||||||
|
setHumanPicking(human.modelUuid, false);
|
||||||
|
setHumanActive(human.modelUuid, false);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
humanStatus(human.modelUuid, 'Reached drop point');
|
||||||
|
setPath([]);
|
||||||
} else if (currentPhase === 'drop-pickup') {
|
} else if (currentPhase === 'drop-pickup') {
|
||||||
|
setCurrentPhase('picking');
|
||||||
|
setHumanState(human.modelUuid, 'idle');
|
||||||
|
setHumanPicking(human.modelUuid, true);
|
||||||
|
setHumanActive(human.modelUuid, false);
|
||||||
|
setPath([]);
|
||||||
|
clearCurrentMaterials(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'idle', true, true, true);
|
||||||
|
humanStatus(human.modelUuid, 'Reached pickup point again, cycle complete');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function animate(currentTime: number) {
|
||||||
|
if (previousTimeRef.current === null) {
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaTime = (currentTime - previousTimeRef.current) / 1000;
|
||||||
|
previousTimeRef.current = currentTime;
|
||||||
|
|
||||||
|
if (human.isActive) {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
activeTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!isPausedRef.current) {
|
||||||
|
idleTimeRef.current += deltaTime * isSpeedRef.current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isPlaying) return
|
||||||
|
if (!human.isActive) {
|
||||||
|
const roundedActiveTime = Math.round(activeTimeRef.current);
|
||||||
|
incrementActiveTime(human.modelUuid, roundedActiveTime);
|
||||||
|
activeTimeRef.current = 0;
|
||||||
|
} else {
|
||||||
|
const roundedIdleTime = Math.round(idleTimeRef.current);
|
||||||
|
incrementIdleTime(human.modelUuid, roundedIdleTime);
|
||||||
|
idleTimeRef.current = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (animationFrameIdRef.current === null) {
|
||||||
|
animationFrameIdRef.current = requestAnimationFrame(animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (animationFrameIdRef.current !== null) {
|
||||||
|
cancelAnimationFrame(animationFrameIdRef.current);
|
||||||
|
animationFrameIdRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [human, isPlaying]);
|
||||||
|
|
||||||
|
|
||||||
function startUnloadingProcess() {
|
function startUnloadingProcess() {
|
||||||
|
const humanAsset = getAssetById(human.modelUuid);
|
||||||
|
if (humanAsset?.animationState?.current === 'drop' && humanAsset?.animationState?.isCompleted) {
|
||||||
|
if (human.point.action.triggers.length > 0) {
|
||||||
|
const trigger = getTriggerByUuid(selectedProduct.productUuid, human.point.action.triggers[0]?.triggerUuid);
|
||||||
|
const model = getEventByModelUuid(selectedProduct.productUuid, trigger?.triggeredAsset?.triggeredModel?.modelUuid || '');
|
||||||
|
|
||||||
|
if (trigger && model) {
|
||||||
|
if (model.type === 'transfer') {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||||
|
if (action) {
|
||||||
|
handleMaterialDropToConveyor(model);
|
||||||
|
}
|
||||||
|
} else if (model.type === 'machine') {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||||
|
if (action) {
|
||||||
|
handleMaterialDropToMachine(model);
|
||||||
|
}
|
||||||
|
} else if (model.type === 'roboticArm') {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||||
|
if (action) {
|
||||||
|
handleMaterialDropToArmBot(model);
|
||||||
|
}
|
||||||
|
} else if (model.type === 'storageUnit') {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||||
|
if (action) {
|
||||||
|
handleMaterialDropToStorageUnit(model);
|
||||||
|
}
|
||||||
|
} else if (model.type === 'vehicle') {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, human.point.action.actionUuid);
|
||||||
|
if (action) {
|
||||||
|
handleMaterialDropToVehicle(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const droppedMaterial = human.currentLoad;
|
||||||
|
startTime = performance.now();
|
||||||
|
handleMaterialDropByDefault(droppedMaterial);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const droppedMaterial = human.currentLoad;
|
||||||
|
startTime = performance.now();
|
||||||
|
handleMaterialDropByDefault(droppedMaterial);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(startUnloadingProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropToStorageUnit(model: StorageEventSchema) {
|
||||||
|
if (model && humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAnimation = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
if (model.point.action.actionType === 'store') {
|
||||||
|
loopMaterialDropToStorage(
|
||||||
|
human.modelUuid,
|
||||||
|
human.currentLoad,
|
||||||
|
model.modelUuid,
|
||||||
|
model.point.action.storageCapacity,
|
||||||
|
human.point.action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(checkAnimation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loopMaterialDropToStorage(
|
||||||
|
humanId: string,
|
||||||
|
humanCurrentLoad: number,
|
||||||
|
storageUnitId: string,
|
||||||
|
storageMaxCapacity: number,
|
||||||
|
action: HumanAction
|
||||||
|
) {
|
||||||
|
const storageUnit = getStorageUnitById(storageUnitId);
|
||||||
|
|
||||||
|
if (!storageUnit || humanCurrentLoad <= 0 || storageUnit.currentLoad >= storageMaxCapacity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementHumanLoad(humanId, 1);
|
||||||
|
humanCurrentLoad -= 1;
|
||||||
|
|
||||||
|
const material = removeLastMaterial(humanId);
|
||||||
|
if (material) {
|
||||||
|
triggerPointActions(action, material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanCurrentLoad > 0 && storageUnit.currentLoad < storageMaxCapacity) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
const waitForNextDrop = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
loopMaterialDropToStorage(
|
||||||
|
humanId,
|
||||||
|
humanCurrentLoad,
|
||||||
|
storageUnitId,
|
||||||
|
storageMaxCapacity,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextDrop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
waitForNextDrop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropToConveyor(model: ConveyorEventSchema) {
|
||||||
|
if (humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAnimation = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
const conveyor = getConveyorById(model.modelUuid);
|
||||||
|
if (conveyor) {
|
||||||
|
loopMaterialDropToConveyor(
|
||||||
|
human.modelUuid,
|
||||||
|
human.currentLoad,
|
||||||
|
conveyor.modelUuid,
|
||||||
|
human.point.action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(checkAnimation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loopMaterialDropToConveyor(
|
||||||
|
humanId: string,
|
||||||
|
humanCurrentLoad: number,
|
||||||
|
conveyorId: string,
|
||||||
|
action: HumanAction
|
||||||
|
) {
|
||||||
|
const conveyor = getConveyorById(conveyorId);
|
||||||
|
|
||||||
|
if (!conveyor || humanCurrentLoad <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementHumanLoad(humanId, 1);
|
||||||
|
humanCurrentLoad -= 1;
|
||||||
|
|
||||||
|
const material = removeLastMaterial(humanId);
|
||||||
|
if (material) {
|
||||||
|
triggerPointActions(action, material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanCurrentLoad > 0) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
const waitForNextDrop = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
loopMaterialDropToConveyor(
|
||||||
|
humanId,
|
||||||
|
humanCurrentLoad,
|
||||||
|
conveyorId,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextDrop);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
waitForNextDrop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropToArmBot(model: RoboticArmEventSchema) {
|
||||||
|
if (humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAnimation = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
const armBot = getArmBotById(model.modelUuid);
|
||||||
|
if (armBot && armBot.state === 'idle' && !armBot.isActive) {
|
||||||
|
loopMaterialDropToArmBot(
|
||||||
|
human.modelUuid,
|
||||||
|
human.currentLoad,
|
||||||
|
model.modelUuid,
|
||||||
|
human.point.action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(checkAnimation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loopMaterialDropToArmBot(
|
||||||
|
humanId: string,
|
||||||
|
humanCurrentLoad: number,
|
||||||
|
armBotId: string,
|
||||||
|
action: HumanAction
|
||||||
|
) {
|
||||||
|
const armBot = getArmBotById(armBotId);
|
||||||
|
|
||||||
|
if (!armBot || armBot.state !== 'idle' || armBot.isActive || humanCurrentLoad <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementHumanLoad(humanId, 1);
|
||||||
|
humanCurrentLoad -= 1;
|
||||||
|
|
||||||
|
const material = removeLastMaterial(humanId);
|
||||||
|
if (material) {
|
||||||
|
triggerPointActions(action, material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanCurrentLoad > 0) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
const waitForNextTransfer = () => {
|
||||||
|
const currentArmBot = getArmBotById(armBotId);
|
||||||
|
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
loopMaterialDropToArmBot(
|
||||||
|
humanId,
|
||||||
|
humanCurrentLoad,
|
||||||
|
armBotId,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
waitForNextTransfer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropToVehicle(model: VehicleEventSchema) {
|
||||||
|
if (humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAnimation = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
const vehicle = getVehicleById(model.modelUuid);
|
||||||
|
if (vehicle && vehicle.state === 'idle' && !vehicle.isActive) {
|
||||||
|
loopMaterialDropToVehicle(
|
||||||
|
human.modelUuid,
|
||||||
|
human.currentLoad,
|
||||||
|
model.modelUuid,
|
||||||
|
human.point.action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(checkAnimation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loopMaterialDropToVehicle(
|
||||||
|
humanId: string,
|
||||||
|
humanCurrentLoad: number,
|
||||||
|
vehicleId: string,
|
||||||
|
action: HumanAction
|
||||||
|
) {
|
||||||
|
const vehicle = getVehicleById(vehicleId);
|
||||||
|
|
||||||
|
if (!vehicle || vehicle.state !== 'idle' || vehicle.isActive || humanCurrentLoad <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementHumanLoad(humanId, 1);
|
||||||
|
humanCurrentLoad -= 1;
|
||||||
|
|
||||||
|
const material = removeLastMaterial(humanId);
|
||||||
|
if (material) {
|
||||||
|
triggerPointActions(action, material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanCurrentLoad > 0) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
const waitForNextTransfer = () => {
|
||||||
|
const currentArmBot = getVehicleById(vehicleId);
|
||||||
|
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
loopMaterialDropToArmBot(
|
||||||
|
humanId,
|
||||||
|
humanCurrentLoad,
|
||||||
|
vehicleId,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
waitForNextTransfer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropToMachine(model: MachineEventSchema) {
|
||||||
|
if (humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkAnimation = () => {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
const machine = getMachineById(model.modelUuid);
|
||||||
|
if (machine && machine.state === 'idle' && !machine.isActive) {
|
||||||
|
loopMaterialDropToMachine(
|
||||||
|
human.modelUuid,
|
||||||
|
human.currentLoad,
|
||||||
|
model.modelUuid,
|
||||||
|
human.point.action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(checkAnimation);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
checkAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loopMaterialDropToMachine(
|
||||||
|
humanId: string,
|
||||||
|
humanCurrentLoad: number,
|
||||||
|
machineId: string,
|
||||||
|
action: HumanAction
|
||||||
|
) {
|
||||||
|
const machine = getMachineById(machineId);
|
||||||
|
|
||||||
|
if (!machine || machine.state !== 'idle' || machine.isActive || humanCurrentLoad <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
decrementHumanLoad(humanId, 1);
|
||||||
|
humanCurrentLoad -= 1;
|
||||||
|
|
||||||
|
const material = removeLastMaterial(humanId);
|
||||||
|
if (material) {
|
||||||
|
triggerPointActions(action, material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanCurrentLoad > 0) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
const waitForNextTransfer = () => {
|
||||||
|
const currentArmBot = getMachineById(machineId);
|
||||||
|
if (currentArmBot && currentArmBot.state === 'idle' && !currentArmBot.isActive) {
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
loopMaterialDropToArmBot(
|
||||||
|
humanId,
|
||||||
|
humanCurrentLoad,
|
||||||
|
machineId,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
requestAnimationFrame(waitForNextTransfer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
waitForNextTransfer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMaterialDropByDefault(droppedMaterial: number) {
|
||||||
|
if (humanAsset?.animationState?.current !== 'drop') {
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (humanAsset?.animationState?.isCompleted) {
|
||||||
|
const remainingMaterials = droppedMaterial - 1;
|
||||||
|
decrementHumanLoad(human.modelUuid, 1);
|
||||||
|
const material = removeLastMaterial(human.modelUuid);
|
||||||
|
|
||||||
|
if (material) {
|
||||||
|
setEndTime(material.materialId, performance.now());
|
||||||
|
removeMaterial(material.materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remainingMaterials > 0) {
|
||||||
|
resetAnimation(human.modelUuid);
|
||||||
|
setCurrentAnimation(human.modelUuid, 'drop', true, false, false);
|
||||||
|
|
||||||
|
requestAnimationFrame(() => handleMaterialDropByDefault(remainingMaterials));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestAnimationFrame(() => handleMaterialDropByDefault(droppedMaterial));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -144,6 +668,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
startUnloadingProcess={startUnloadingProcess}
|
startUnloadingProcess={startUnloadingProcess}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<MaterialAnimator human={human} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,6 @@ export function useTriggerHandler() {
|
|||||||
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||||
const material = getMaterialById(materialId);
|
const material = getMaterialById(materialId);
|
||||||
if (material) {
|
if (material) {
|
||||||
const triggeredAction = action;
|
|
||||||
|
|
||||||
// Handle current action of the material
|
// Handle current action of the material
|
||||||
handleAction(action, materialId);
|
handleAction(action, materialId);
|
||||||
@@ -291,7 +290,7 @@ export function useTriggerHandler() {
|
|||||||
|
|
||||||
if (human) {
|
if (human) {
|
||||||
|
|
||||||
if (human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < (triggeredAction as HumanAction).loadCapacity) {
|
if (human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) {
|
||||||
|
|
||||||
setIsVisible(materialId, false);
|
setIsVisible(materialId, false);
|
||||||
|
|
||||||
@@ -302,6 +301,9 @@ export function useTriggerHandler() {
|
|||||||
|
|
||||||
// Handle current action using Event Manager
|
// Handle current action using Event Manager
|
||||||
addHumanToMonitor(human.modelUuid, () => {
|
addHumanToMonitor(human.modelUuid, () => {
|
||||||
|
|
||||||
|
setIsVisible(materialId, false);
|
||||||
|
|
||||||
handleAction(action, materialId);
|
handleAction(action, materialId);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -433,6 +435,9 @@ export function useTriggerHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (toEvent?.type === 'human') {
|
||||||
|
// Vehicle to Human
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (fromEvent?.type === 'machine') {
|
} else if (fromEvent?.type === 'machine') {
|
||||||
if (toEvent?.type === 'transfer') {
|
if (toEvent?.type === 'transfer') {
|
||||||
@@ -539,6 +544,9 @@ export function useTriggerHandler() {
|
|||||||
} else if (toEvent?.type === 'storageUnit') {
|
} else if (toEvent?.type === 'storageUnit') {
|
||||||
// Machine to Storage Unit
|
// Machine to Storage Unit
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'human') {
|
||||||
|
// Machine to Human
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (fromEvent?.type === 'roboticArm') {
|
} else if (fromEvent?.type === 'roboticArm') {
|
||||||
if (toEvent?.type === 'transfer') {
|
if (toEvent?.type === 'transfer') {
|
||||||
@@ -812,6 +820,53 @@ export function useTriggerHandler() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (toEvent?.type === 'human') {
|
||||||
|
// Robotic Arm to Vehicle
|
||||||
|
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||||
|
const material = getMaterialById(materialId);
|
||||||
|
if (material) {
|
||||||
|
|
||||||
|
setIsPaused(material.materialId, false);
|
||||||
|
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
|
||||||
|
const human = getHumanById(trigger.triggeredAsset?.triggeredModel.modelUuid);
|
||||||
|
|
||||||
|
setNextLocation(material.materialId, null);
|
||||||
|
|
||||||
|
if (action) {
|
||||||
|
|
||||||
|
if (human) {
|
||||||
|
|
||||||
|
if (human.isActive === false && human.state === 'idle' && human.isPicking && human.currentLoad < human.point.action.loadCapacity) {
|
||||||
|
|
||||||
|
setIsVisible(materialId, false);
|
||||||
|
|
||||||
|
setPreviousLocation(material.materialId, {
|
||||||
|
modelUuid: material.current.modelUuid,
|
||||||
|
pointUuid: material.current.pointUuid,
|
||||||
|
actionUuid: material.current.actionUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
setCurrentLocation(material.materialId, {
|
||||||
|
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
|
||||||
|
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle current action from human
|
||||||
|
handleAction(action, materialId);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Event Manager Needed
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else if (fromEvent?.type === 'storageUnit') {
|
} else if (fromEvent?.type === 'storageUnit') {
|
||||||
if (toEvent?.type === 'transfer') {
|
if (toEvent?.type === 'transfer') {
|
||||||
@@ -829,6 +884,135 @@ export function useTriggerHandler() {
|
|||||||
} else if (toEvent?.type === 'storageUnit') {
|
} else if (toEvent?.type === 'storageUnit') {
|
||||||
// Storage Unit to Storage Unit
|
// Storage Unit to Storage Unit
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'human') {
|
||||||
|
// Storage Unit to Human
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if (fromEvent?.type === 'human') {
|
||||||
|
if (toEvent?.type === 'transfer') {
|
||||||
|
// Human to Transfer
|
||||||
|
|
||||||
|
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||||
|
const material = getMaterialById(materialId);
|
||||||
|
if (material) {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
|
||||||
|
|
||||||
|
setPreviousLocation(material.materialId, {
|
||||||
|
modelUuid: material.current.modelUuid,
|
||||||
|
pointUuid: material.current.pointUuid,
|
||||||
|
actionUuid: material.current.actionUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
setCurrentLocation(material.materialId, {
|
||||||
|
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
|
||||||
|
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
setIsVisible(materialId, true);
|
||||||
|
|
||||||
|
if (action &&
|
||||||
|
action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid &&
|
||||||
|
action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid
|
||||||
|
) {
|
||||||
|
setNextLocation(material.materialId, {
|
||||||
|
modelUuid: action.triggers[0]?.triggeredAsset?.triggeredModel.modelUuid,
|
||||||
|
pointUuid: action.triggers[0]?.triggeredAsset?.triggeredPoint?.pointUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
handleAction(action, materialId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'vehicle') {
|
||||||
|
// Human to Vehicle
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'machine') {
|
||||||
|
// Human to Machine
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'roboticArm') {
|
||||||
|
// Human to Robotic Arm
|
||||||
|
|
||||||
|
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||||
|
const material = getMaterialById(materialId);
|
||||||
|
if (material) {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
|
||||||
|
const armBot = getArmBotById(trigger.triggeredAsset?.triggeredModel.modelUuid);
|
||||||
|
|
||||||
|
setPreviousLocation(material.materialId, {
|
||||||
|
modelUuid: material.current.modelUuid,
|
||||||
|
pointUuid: material.current.pointUuid,
|
||||||
|
actionUuid: material.current.actionUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
setCurrentLocation(material.materialId, {
|
||||||
|
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
|
||||||
|
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
setNextLocation(material.materialId, null);
|
||||||
|
|
||||||
|
setIsVisible(materialId, false);
|
||||||
|
|
||||||
|
if (action && armBot) {
|
||||||
|
|
||||||
|
if (armBot.isActive === false && armBot.state === 'idle') {
|
||||||
|
|
||||||
|
// Handle current action from arm bot
|
||||||
|
handleAction(action, materialId);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Event Manager Needed
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (toEvent?.type === 'storageUnit') {
|
||||||
|
// Human to Storage Unit
|
||||||
|
|
||||||
|
if (materialId && trigger.triggeredAsset && trigger.triggeredAsset.triggeredPoint && trigger.triggeredAsset.triggeredAction) {
|
||||||
|
const material = getMaterialById(materialId);
|
||||||
|
if (material) {
|
||||||
|
const action = getActionByUuid(selectedProduct.productUuid, trigger.triggeredAsset.triggeredAction.actionUuid);
|
||||||
|
const storageUnit = getStorageUnitById(trigger.triggeredAsset?.triggeredModel.modelUuid);
|
||||||
|
|
||||||
|
setPreviousLocation(material.materialId, {
|
||||||
|
modelUuid: material.current.modelUuid,
|
||||||
|
pointUuid: material.current.pointUuid,
|
||||||
|
actionUuid: material.current.actionUuid,
|
||||||
|
})
|
||||||
|
|
||||||
|
setCurrentLocation(material.materialId, {
|
||||||
|
modelUuid: trigger.triggeredAsset.triggeredModel.modelUuid,
|
||||||
|
pointUuid: trigger.triggeredAsset.triggeredPoint.pointUuid,
|
||||||
|
actionUuid: trigger.triggeredAsset?.triggeredAction?.actionUuid,
|
||||||
|
});
|
||||||
|
|
||||||
|
setNextLocation(material.materialId, null);
|
||||||
|
|
||||||
|
setIsVisible(materialId, false);
|
||||||
|
|
||||||
|
if (action && storageUnit) {
|
||||||
|
|
||||||
|
if (storageUnit.currentLoad < storageUnit.point.action.storageCapacity) {
|
||||||
|
|
||||||
|
// Handle current action from vehicle
|
||||||
|
handleAction(action, materialId);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Event Manager Needed
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,7 @@ import { useThree, useFrame } from '@react-three/fiber';
|
|||||||
import * as THREE from 'three';
|
import * as THREE from 'three';
|
||||||
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
import { MaterialModel } from '../../../materials/instances/material/materialModel';
|
||||||
|
|
||||||
type MaterialAnimatorProps = {
|
const MaterialAnimator = ({ agvDetail }: { agvDetail: VehicleStatus }) => {
|
||||||
agvDetail: VehicleStatus;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const MaterialAnimator = ({ agvDetail }: MaterialAnimatorProps) => {
|
|
||||||
const meshRef = useRef<any>(null!);
|
const meshRef = useRef<any>(null!);
|
||||||
const [hasLoad, setHasLoad] = useState(false);
|
const [hasLoad, setHasLoad] = useState(false);
|
||||||
const { scene } = useThree();
|
const { scene } = useThree();
|
||||||
|
|||||||
@@ -22,7 +22,8 @@ interface AssetsStore {
|
|||||||
|
|
||||||
// Animation controls
|
// Animation controls
|
||||||
setAnimations: (modelUuid: string, animations: string[]) => void;
|
setAnimations: (modelUuid: string, animations: string[]) => void;
|
||||||
setCurrentAnimation: (modelUuid: string, current: string, isisPlaying: boolean, loopAnimation: boolean) => void;
|
setCurrentAnimation: (modelUuid: string, current: string, isPlaying: boolean, loopAnimation: boolean, isCompleted: boolean) => void;
|
||||||
|
setAnimationComplete: (modelUuid: string, isCompleted: boolean) => void;
|
||||||
resetAnimation: (modelUuid: string) => void;
|
resetAnimation: (modelUuid: string) => void;
|
||||||
addAnimation: (modelUuid: string, animation: string) => void;
|
addAnimation: (modelUuid: string, animation: string) => void;
|
||||||
removeAnimation: (modelUuid: string, animation: string) => void;
|
removeAnimation: (modelUuid: string, animation: string) => void;
|
||||||
@@ -150,19 +151,29 @@ export const createAssetStore = () => {
|
|||||||
if (asset) {
|
if (asset) {
|
||||||
asset.animations = animations;
|
asset.animations = animations;
|
||||||
if (!asset.animationState) {
|
if (!asset.animationState) {
|
||||||
asset.animationState = { current: '', isPlaying: false, loopAnimation: true };
|
asset.animationState = { current: '', isPlaying: false, loopAnimation: true, isCompleted: true };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setCurrentAnimation: (modelUuid, current, isisPlaying, loopAnimation) => {
|
setCurrentAnimation: (modelUuid, current, isPlaying, loopAnimation, isCompleted) => {
|
||||||
set((state) => {
|
set((state) => {
|
||||||
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
||||||
if (asset?.animationState) {
|
if (asset?.animationState) {
|
||||||
asset.animationState.current = current;
|
asset.animationState.current = current;
|
||||||
asset.animationState.isPlaying = isisPlaying;
|
asset.animationState.isPlaying = isPlaying;
|
||||||
asset.animationState.loopAnimation = loopAnimation;
|
asset.animationState.loopAnimation = loopAnimation;
|
||||||
|
asset.animationState.isCompleted = isCompleted;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
setAnimationComplete: (modelUuid, isCompleted) => {
|
||||||
|
set((state) => {
|
||||||
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
||||||
|
if (asset?.animationState) {
|
||||||
|
asset.animationState.isCompleted = isCompleted;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -171,7 +182,7 @@ export const createAssetStore = () => {
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
||||||
if (asset?.animationState) {
|
if (asset?.animationState) {
|
||||||
asset.animationState = { current: '', isPlaying: false, loopAnimation: true };
|
asset.animationState = { current: '', isPlaying: false, loopAnimation: true, isCompleted: true };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ export const createHumanStore = () => {
|
|||||||
set((state) => {
|
set((state) => {
|
||||||
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
const human = state.humans.find(h => h.modelUuid === modelUuid);
|
||||||
if (human && human.currentMaterials.length > 0) {
|
if (human && human.currentMaterials.length > 0) {
|
||||||
removed = human.currentMaterials.pop();
|
removed = JSON.parse(JSON.stringify(human.currentMaterials.pop()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return removed;
|
return removed;
|
||||||
|
|||||||
1
app/src/types/builderTypes.d.ts
vendored
1
app/src/types/builderTypes.d.ts
vendored
@@ -28,6 +28,7 @@ interface Asset {
|
|||||||
current: string;
|
current: string;
|
||||||
isPlaying: boolean;
|
isPlaying: boolean;
|
||||||
loopAnimation: boolean;
|
loopAnimation: boolean;
|
||||||
|
isCompleted: boolean;
|
||||||
};
|
};
|
||||||
eventData?: {
|
eventData?: {
|
||||||
type: string;
|
type: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user