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) => {
|
||||
if (selectedFloorItem) {
|
||||
setCurrentAnimation(selectedFloorItem.uuid, animation, true, loopAnimation);
|
||||
setCurrentAnimation(selectedFloorItem.uuid, animation, true, loopAnimation, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,95 +1,70 @@
|
||||
import React from "react";
|
||||
import InputWithDropDown from "../../../../../ui/inputs/InputWithDropDown";
|
||||
import EyeDropInput from "../../../../../ui/inputs/EyeDropInput";
|
||||
|
||||
interface TravelActionProps {
|
||||
loadCapacity: {
|
||||
value: string;
|
||||
min: number;
|
||||
max: number;
|
||||
defaultValue: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
unloadDuration: {
|
||||
value: string;
|
||||
min: number;
|
||||
max: number;
|
||||
defaultValue: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
pickPoint?: {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
unloadPoint?: {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
clearPoints: () => void;
|
||||
loadCapacity: {
|
||||
value: string;
|
||||
min: number;
|
||||
max: number;
|
||||
defaultValue: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
unloadDuration: {
|
||||
value: string;
|
||||
min: number;
|
||||
max: number;
|
||||
defaultValue: string;
|
||||
onChange: (value: string) => void;
|
||||
};
|
||||
clearPoints: () => void;
|
||||
}
|
||||
|
||||
const TravelAction: React.FC<TravelActionProps> = ({
|
||||
loadCapacity,
|
||||
unloadDuration,
|
||||
pickPoint,
|
||||
unloadPoint,
|
||||
clearPoints,
|
||||
loadCapacity,
|
||||
unloadDuration,
|
||||
clearPoints,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<InputWithDropDown
|
||||
label="Load Capacity"
|
||||
value={loadCapacity.value}
|
||||
min={loadCapacity.min}
|
||||
max={loadCapacity.max}
|
||||
defaultValue={loadCapacity.defaultValue}
|
||||
step={1}
|
||||
activeOption="s"
|
||||
onClick={() => {}}
|
||||
onChange={loadCapacity.onChange}
|
||||
/>
|
||||
<InputWithDropDown
|
||||
label="Unload Duration"
|
||||
value={unloadDuration.value}
|
||||
min={unloadDuration.min}
|
||||
max={unloadDuration.max}
|
||||
defaultValue={unloadDuration.defaultValue}
|
||||
step={0.1}
|
||||
activeOption="s"
|
||||
onClick={() => {}}
|
||||
onChange={unloadDuration.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>
|
||||
{pickPoint && (
|
||||
<EyeDropInput
|
||||
label="Pick Point"
|
||||
value={pickPoint.value}
|
||||
onChange={pickPoint.onChange}
|
||||
/>
|
||||
)}
|
||||
{unloadPoint && (
|
||||
<EyeDropInput
|
||||
label="Unload Point"
|
||||
value={unloadPoint.value}
|
||||
onChange={unloadPoint.onChange}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<InputWithDropDown
|
||||
label="Load Capacity"
|
||||
value={loadCapacity.value}
|
||||
min={loadCapacity.min}
|
||||
max={loadCapacity.max}
|
||||
defaultValue={loadCapacity.defaultValue}
|
||||
step={1}
|
||||
activeOption="unit"
|
||||
onClick={() => { }}
|
||||
onChange={loadCapacity.onChange}
|
||||
/>
|
||||
<InputWithDropDown
|
||||
label="Unload Duration"
|
||||
value={unloadDuration.value}
|
||||
min={unloadDuration.min}
|
||||
max={unloadDuration.max}
|
||||
defaultValue={unloadDuration.defaultValue}
|
||||
step={0.1}
|
||||
activeOption="s"
|
||||
onClick={() => { }}
|
||||
onChange={unloadDuration.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 TravelAction;
|
||||
|
||||
@@ -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 LabledDropdown from "../../../../../ui/inputs/LabledDropdown";
|
||||
import Trigger from "../trigger/Trigger";
|
||||
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
|
||||
import ActionsList from "../components/ActionsList";
|
||||
import AnimationList from "../components/AnimationList";
|
||||
import { useSelectedEventData, useSelectedAction, useSelectedAnimation } from "../../../../../../store/simulation/useSimulationStore";
|
||||
import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
|
||||
import { useProductContext } from "../../../../../../modules/simulation/products/productContext";
|
||||
import { useVersionContext } from "../../../../../../modules/builder/version/versionContext";
|
||||
import { useSceneContext } from "../../../../../../modules/scene/sceneContext";
|
||||
import { useParams } from "react-router-dom";
|
||||
import WorkerAction from "../actions/workerAction";
|
||||
|
||||
function HumanMechanics() {
|
||||
const [activeOption, setActiveOption] = useState<"worker">("worker");
|
||||
const [animationOptions, setAnimationOptions] = useState<string[]>([]);
|
||||
const [speed, setSpeed] = useState("0.5");
|
||||
const [loadCapacity, setLoadCapacity] = useState("1");
|
||||
const [currentAction, setCurrentAction] = useState<HumanAction | undefined>();
|
||||
const [selectedPointData, setSelectedPointData] = useState<HumanPointSchema | undefined>();
|
||||
const { selectedEventData } = useSelectedEventData();
|
||||
const { productStore, assetStore } = useSceneContext();
|
||||
const { getAssetById } = assetStore();
|
||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
||||
const { productStore } = useSceneContext();
|
||||
const { getPointByUuid, updateEvent, updateAction, addAction, removeAction, getEventByModelUuid } = productStore();
|
||||
const { selectedProductStore } = useProductContext();
|
||||
const { selectedProduct } = selectedProductStore();
|
||||
const { selectedAction, setSelectedAction, clearSelectedAction } = useSelectedAction();
|
||||
const { selectedAnimation, setSelectedAnimation } = useSelectedAnimation();
|
||||
const { selectedVersionStore } = useVersionContext();
|
||||
const { selectedVersion } = selectedVersionStore();
|
||||
const { projectId } = useParams();
|
||||
@@ -44,6 +41,13 @@ function HumanMechanics() {
|
||||
setSelectedPointData(point);
|
||||
setCurrentAction(point.action);
|
||||
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 {
|
||||
clearSelectedAction();
|
||||
@@ -68,6 +72,7 @@ function HumanMechanics() {
|
||||
clearSelectedAction();
|
||||
setCurrentAction(undefined);
|
||||
setSpeed("0.5");
|
||||
setLoadCapacity("1");
|
||||
}
|
||||
}, [selectedEventData, selectedProduct, selectedAction]);
|
||||
|
||||
@@ -130,6 +135,29 @@ function HumanMechanics() {
|
||||
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 = () => {
|
||||
if (!currentAction || !selectedPointData || !selectedAction.actionId) return;
|
||||
|
||||
@@ -239,7 +267,18 @@ function HumanMechanics() {
|
||||
disabled={true}
|
||||
/>
|
||||
</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">
|
||||
<Trigger selectedPointData={selectedPointData as any} type="Human" />
|
||||
</div>
|
||||
|
||||
@@ -272,14 +272,6 @@ function VehicleMechanics() {
|
||||
onChange: handleUnloadDurationChange,
|
||||
}}
|
||||
clearPoints={handleClearPoints}
|
||||
// pickPoint={{
|
||||
// value: currentPickPoint,
|
||||
// onChange: handlePickPointChange,
|
||||
// }}
|
||||
// unloadPoint={{
|
||||
// value: currentUnloadPoint,
|
||||
// onChange: handleUnloadPointChange,
|
||||
// }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@ type InputWithDropDownProps = {
|
||||
max?: number;
|
||||
step?: number;
|
||||
defaultValue?: string;
|
||||
disabled?: boolean;
|
||||
options?: string[]; // Array of dropdown options
|
||||
activeOption?: string; // The currently active dropdown option
|
||||
onClick?: () => void;
|
||||
@@ -23,6 +24,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
max,
|
||||
step,
|
||||
defaultValue,
|
||||
disabled = false,
|
||||
options,
|
||||
activeOption,
|
||||
onClick,
|
||||
@@ -54,6 +56,7 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
type="number"
|
||||
defaultValue={value}
|
||||
// value={value}
|
||||
disabled={disabled}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user