feat: Implement selected animation handling and integrate with human mechanics
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import React, { useRef } from "react";
|
import React, { useRef } from "react";
|
||||||
import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons";
|
import { AddIcon, RemoveIcon, ResizeHeightIcon } from "../../../../../icons/ExportCommonIcons";
|
||||||
import { handleResize } from "../../../../../../functions/handleResizePannel";
|
import { handleResize } from "../../../../../../functions/handleResizePannel";
|
||||||
import { useSelectedAction } from "../../../../../../store/simulation/useSimulationStore";
|
import { useSelectedAction, useSelectedAnimation } from "../../../../../../store/simulation/useSimulationStore";
|
||||||
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../../../ui/inputs/RenameInput";
|
||||||
|
|
||||||
interface AnimationListProps {
|
interface AnimationListProps {
|
||||||
@@ -17,13 +17,6 @@ interface AnimationListProps {
|
|||||||
onRemoveAnimation: (animationUuid: string) => void;
|
onRemoveAnimation: (animationUuid: string) => void;
|
||||||
handleAnimationSelect: (animationUuid: string) => void;
|
handleAnimationSelect: (animationUuid: string) => void;
|
||||||
handleRenameAnimation: (animationUuid: string, newName: string) => void;
|
handleRenameAnimation: (animationUuid: string, newName: string) => void;
|
||||||
selectedAnimation: {
|
|
||||||
animationUuid: string;
|
|
||||||
animationName: string;
|
|
||||||
animationType: "behaviour" | "animatedTravel";
|
|
||||||
animation: string | null;
|
|
||||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null };
|
|
||||||
} | undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnimationList: React.FC<AnimationListProps> = ({
|
const AnimationList: React.FC<AnimationListProps> = ({
|
||||||
@@ -32,10 +25,10 @@ const AnimationList: React.FC<AnimationListProps> = ({
|
|||||||
onRemoveAnimation,
|
onRemoveAnimation,
|
||||||
handleAnimationSelect,
|
handleAnimationSelect,
|
||||||
handleRenameAnimation,
|
handleRenameAnimation,
|
||||||
selectedAnimation
|
|
||||||
}) => {
|
}) => {
|
||||||
const animationContainerRef = useRef<HTMLDivElement>(null);
|
const animationContainerRef = useRef<HTMLDivElement>(null);
|
||||||
const { selectedAction } = useSelectedAction();
|
const { selectedAction } = useSelectedAction();
|
||||||
|
const { selectedAnimation } = useSelectedAnimation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="actions-list-container">
|
<div className="actions-list-container">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Trigger from "../trigger/Trigger";
|
|||||||
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
|
import PickAndPlaceAction from "../actions/PickAndPlaceAction";
|
||||||
import ActionsList from "../components/ActionsList";
|
import ActionsList from "../components/ActionsList";
|
||||||
import AnimationList from "../components/AnimationList";
|
import AnimationList from "../components/AnimationList";
|
||||||
import { useSelectedEventData, useSelectedAction } 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";
|
||||||
@@ -26,14 +26,8 @@ function HumanMechanics() {
|
|||||||
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
const { getPointByUuid, getEventByModelUuid, updateEvent, updateAction, addAction, removeAction } = productStore();
|
||||||
const { selectedProductStore } = useProductContext();
|
const { selectedProductStore } = useProductContext();
|
||||||
const { selectedProduct } = selectedProductStore();
|
const { selectedProduct } = selectedProductStore();
|
||||||
const [selectedAnimation, setSelectedAnimation] = useState<{
|
|
||||||
animationUuid: string;
|
|
||||||
animationName: string;
|
|
||||||
animationType: "behaviour" | "animatedTravel";
|
|
||||||
animation: string | null;
|
|
||||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
|
||||||
}>();
|
|
||||||
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();
|
||||||
@@ -210,10 +204,8 @@ function HumanMechanics() {
|
|||||||
|
|
||||||
if (!updatedAnimation) return;
|
if (!updatedAnimation) return;
|
||||||
|
|
||||||
updatedAnimation.travelPoints = {
|
delete updatedAnimation.startPoint;
|
||||||
startPoint: null,
|
delete updatedAnimation.endPoint;
|
||||||
endPoint: null
|
|
||||||
};
|
|
||||||
|
|
||||||
const updatedAction = {
|
const updatedAction = {
|
||||||
...currentAction,
|
...currentAction,
|
||||||
@@ -387,14 +379,8 @@ function HumanMechanics() {
|
|||||||
animationType: newType
|
animationType: newType
|
||||||
};
|
};
|
||||||
|
|
||||||
if (newType === 'animatedTravel') {
|
delete updatedAnim.startPoint;
|
||||||
updatedAnim.travelPoints = {
|
delete updatedAnim.endPoint;
|
||||||
startPoint: null,
|
|
||||||
endPoint: null
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
delete updatedAnim.travelPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
return updatedAnim;
|
return updatedAnim;
|
||||||
}
|
}
|
||||||
@@ -546,7 +532,6 @@ function HumanMechanics() {
|
|||||||
onRemoveAnimation={handleRemoveAnimation}
|
onRemoveAnimation={handleRemoveAnimation}
|
||||||
handleAnimationSelect={handleAnimationSelect}
|
handleAnimationSelect={handleAnimationSelect}
|
||||||
handleRenameAnimation={handleRenameAnimation}
|
handleRenameAnimation={handleRenameAnimation}
|
||||||
selectedAnimation={selectedAnimation}
|
|
||||||
/>
|
/>
|
||||||
{selectedAnimation && (
|
{selectedAnimation && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -422,7 +422,6 @@ async function handleModelLoad(
|
|||||||
userId: userId,
|
userId: userId,
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log('completeData: ', completeData);
|
|
||||||
socket.emit("v1:model-asset:add", completeData);
|
socket.emit("v1:model-asset:add", completeData);
|
||||||
|
|
||||||
const asset: Asset = {
|
const asset: Asset = {
|
||||||
|
|||||||
@@ -1,32 +1,43 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { useSelectedAnimation, useSelectedEventSphere } from '../../../store/simulation/useSimulationStore';
|
||||||
|
import { usePlayButtonStore } from '../../../store/usePlayButtonStore';
|
||||||
|
import { useSceneContext } from '../../scene/sceneContext';
|
||||||
import HumanInstances from './instances/humanInstances'
|
import HumanInstances from './instances/humanInstances'
|
||||||
import { useEffect, useState } from "react";
|
import HumanUi from './instances/instance/humanUi';
|
||||||
import { useSelectedEventSphere } from "../../../store/simulation/useSimulationStore";
|
|
||||||
import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
|
|
||||||
import { useSceneContext } from "../../scene/sceneContext";
|
|
||||||
|
|
||||||
function Human() {
|
function Human() {
|
||||||
const { humanStore } = useSceneContext();
|
const { humanStore } = useSceneContext();
|
||||||
const { getHumanById } = humanStore();
|
const { getHumanById } = humanStore();
|
||||||
|
const { selectedAnimation } = useSelectedAnimation();
|
||||||
const { selectedEventSphere } = useSelectedEventSphere();
|
const { selectedEventSphere } = useSelectedEventSphere();
|
||||||
const { isPlaying } = usePlayButtonStore();
|
const { isPlaying } = usePlayButtonStore();
|
||||||
const [isHumanSelected, setIsHumanSelected] = useState(false);
|
const [isVehicleSelected, setIsHumanSelected] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedEventSphere) {
|
if (selectedEventSphere) {
|
||||||
const selectedVehicle = getHumanById(selectedEventSphere.userData.modelUuid);
|
const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid);
|
||||||
if (selectedVehicle) {
|
if (selectedHuman &&
|
||||||
|
selectedHuman.point.actions.some((action) =>
|
||||||
|
action.animationSequences.some((animation) =>
|
||||||
|
animation.animationUuid === selectedAnimation?.animationUuid && animation.animationType === 'animatedTravel'
|
||||||
|
)
|
||||||
|
)) {
|
||||||
setIsHumanSelected(true);
|
setIsHumanSelected(true);
|
||||||
} else {
|
} else {
|
||||||
setIsHumanSelected(false);
|
setIsHumanSelected(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [getHumanById, selectedEventSphere])
|
}, [getHumanById, selectedEventSphere, selectedAnimation])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<HumanInstances />
|
<HumanInstances />
|
||||||
|
|
||||||
|
{isVehicleSelected && selectedEventSphere && !isPlaying &&
|
||||||
|
<HumanUi />
|
||||||
|
}
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
function HumanAnimator() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default HumanAnimator
|
||||||
@@ -10,7 +10,7 @@ function HumanInstance({ human }: { human: HumanStatus }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<HumanUi human={human} />
|
<HumanUi />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,8 +1,281 @@
|
|||||||
import React from 'react'
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import { useGLTF } from '@react-three/drei';
|
||||||
|
import { useFrame, useThree } from '@react-three/fiber';
|
||||||
|
import { useIsDragging, useIsRotating, useSelectedAction, useSelectedEventSphere } from '../../../../../store/simulation/useSimulationStore';
|
||||||
|
import { useProductContext } from '../../../products/productContext';
|
||||||
|
import { useSceneContext } from '../../../../scene/sceneContext';
|
||||||
|
import { Group, Plane, Vector3 } from 'three';
|
||||||
|
import { useVersionContext } from '../../../../builder/version/versionContext';
|
||||||
|
import { useParams } from 'react-router-dom';
|
||||||
|
import startPoint from "../../../../../assets/gltf-glb/ui/arrow_green.glb";
|
||||||
|
import startEnd from "../../../../../assets/gltf-glb/ui/arrow_red.glb";
|
||||||
|
import { upsertProductOrEventApi } from '../../../../../services/simulation/products/UpsertProductOrEventApi';
|
||||||
|
|
||||||
|
function HumanUi() {
|
||||||
|
const { scene: startScene } = useGLTF(startPoint) as any;
|
||||||
|
const { scene: endScene } = useGLTF(startEnd) as any;
|
||||||
|
const startMarker = useRef<Group>(null);
|
||||||
|
const endMarker = useRef<Group>(null);
|
||||||
|
const outerGroup = useRef<Group>(null);
|
||||||
|
const prevMousePos = useRef({ x: 0, y: 0 });
|
||||||
|
const { controls, raycaster } = useThree();
|
||||||
|
const { selectedEventSphere } = useSelectedEventSphere();
|
||||||
|
const { selectedProductStore } = useProductContext();
|
||||||
|
const { humanStore, productStore } = useSceneContext();
|
||||||
|
const { selectedProduct } = selectedProductStore();
|
||||||
|
const { humans, getHumanById } = humanStore();
|
||||||
|
const { updateEvent } = productStore();
|
||||||
|
const [startPosition, setStartPosition] = useState<[number, number, number]>([0, 1, 0]);
|
||||||
|
const [endPosition, setEndPosition] = useState<[number, number, number]>([0, 1, 0]);
|
||||||
|
const [startRotation, setStartRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
|
const [endRotation, setEndRotation] = useState<[number, number, number]>([0, 0, 0]);
|
||||||
|
const { isDragging, setIsDragging } = useIsDragging();
|
||||||
|
const { isRotating, setIsRotating } = useIsRotating();
|
||||||
|
const plane = useRef(new Plane(new Vector3(0, 1, 0), 0));
|
||||||
|
|
||||||
|
const [selectedHumanData, setSelectedHumanData] = useState<{
|
||||||
|
position: [number, number, number];
|
||||||
|
rotation: [number, number, number];
|
||||||
|
}>({ position: [0, 0, 0], rotation: [0, 0, 0] });
|
||||||
|
|
||||||
|
const { selectedAction } = useSelectedAction();
|
||||||
|
const { selectedVersionStore } = useVersionContext();
|
||||||
|
const { selectedVersion } = selectedVersionStore();
|
||||||
|
const { projectId } = useParams();
|
||||||
|
|
||||||
|
const updateBackend = (
|
||||||
|
productName: string,
|
||||||
|
productUuid: string,
|
||||||
|
projectId: string,
|
||||||
|
eventData: EventsSchema
|
||||||
|
) => {
|
||||||
|
upsertProductOrEventApi({
|
||||||
|
productName: productName,
|
||||||
|
productUuid: productUuid,
|
||||||
|
projectId: projectId,
|
||||||
|
eventDatas: eventData,
|
||||||
|
versionId: selectedVersion?.versionId || '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!selectedEventSphere) return;
|
||||||
|
const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid);
|
||||||
|
|
||||||
|
if (selectedHuman) {
|
||||||
|
setSelectedHumanData({
|
||||||
|
position: selectedHuman.position,
|
||||||
|
rotation: selectedHuman.rotation,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (selectedHuman.point?.actions && selectedAction.actionId) {
|
||||||
|
const action = selectedHuman.point.actions.find(a => a.actionUuid === selectedAction.actionId);
|
||||||
|
|
||||||
|
if (action?.animationSequences[0]) {
|
||||||
|
const sequence = action.animationSequences[0];
|
||||||
|
|
||||||
|
if (sequence.startPoint?.position && outerGroup.current) {
|
||||||
|
const worldPos = new Vector3(...sequence.startPoint.position);
|
||||||
|
const localPosition = outerGroup.current.worldToLocal(worldPos.clone());
|
||||||
|
setStartPosition([localPosition.x, 0.5, localPosition.z]);
|
||||||
|
setStartRotation(sequence.startPoint.rotation || [0, 0, 0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sequence.endPoint?.position && outerGroup.current) {
|
||||||
|
const worldPos = new Vector3(...sequence.endPoint.position);
|
||||||
|
const localPosition = outerGroup.current.worldToLocal(worldPos.clone());
|
||||||
|
setEndPosition([localPosition.x, 0.5, localPosition.z]);
|
||||||
|
setEndRotation(sequence.endPoint.rotation || [0, 0, 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedEventSphere, outerGroup.current, selectedAction, humans]);
|
||||||
|
|
||||||
|
const handlePointerDown = (
|
||||||
|
e: any,
|
||||||
|
state: "start" | "end",
|
||||||
|
rotation: "start" | "end"
|
||||||
|
) => {
|
||||||
|
if (e.object.name === "handle") {
|
||||||
|
const normalizedX = (e.clientX / window.innerWidth) * 2 - 1;
|
||||||
|
const normalizedY = -(e.clientY / window.innerHeight) * 2 + 1;
|
||||||
|
prevMousePos.current = { x: normalizedX, y: normalizedY };
|
||||||
|
setIsRotating(rotation);
|
||||||
|
if (controls) (controls as any).enabled = false;
|
||||||
|
setIsDragging(null);
|
||||||
|
} else {
|
||||||
|
setIsDragging(state);
|
||||||
|
setIsRotating(null);
|
||||||
|
if (controls) (controls as any).enabled = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePointerUp = () => {
|
||||||
|
(controls as any).enabled = true;
|
||||||
|
setIsDragging(null);
|
||||||
|
setIsRotating(null);
|
||||||
|
|
||||||
|
if (selectedEventSphere?.userData.modelUuid && selectedAction.actionId) {
|
||||||
|
const selectedHuman = getHumanById(selectedEventSphere.userData.modelUuid);
|
||||||
|
|
||||||
|
if (selectedHuman && outerGroup.current && startMarker.current && endMarker.current) {
|
||||||
|
const worldPosStart = new Vector3(...startPosition);
|
||||||
|
const globalStartPosition = outerGroup.current.localToWorld(worldPosStart.clone());
|
||||||
|
|
||||||
|
const worldPosEnd = new Vector3(...endPosition);
|
||||||
|
const globalEndPosition = outerGroup.current.localToWorld(worldPosEnd.clone());
|
||||||
|
|
||||||
|
const updatedActions = selectedHuman.point.actions.map(action => {
|
||||||
|
if (action.actionUuid === selectedAction.actionId) {
|
||||||
|
const updatedSequences = action.animationSequences.map(sequence => {
|
||||||
|
return {
|
||||||
|
...sequence,
|
||||||
|
startPoint: {
|
||||||
|
position: [globalStartPosition.x, globalStartPosition.y, globalStartPosition.z] as [number, number, number],
|
||||||
|
rotation: startRotation
|
||||||
|
},
|
||||||
|
endPoint: {
|
||||||
|
position: [globalEndPosition.x, globalEndPosition.y, globalEndPosition.z] as [number, number, number],
|
||||||
|
rotation: endRotation
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...action,
|
||||||
|
animationSequences: updatedSequences
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return action;
|
||||||
|
});
|
||||||
|
|
||||||
|
const event = updateEvent(
|
||||||
|
selectedProduct.productUuid,
|
||||||
|
selectedEventSphere.userData.modelUuid,
|
||||||
|
{
|
||||||
|
...selectedHuman,
|
||||||
|
point: {
|
||||||
|
...selectedHuman.point,
|
||||||
|
actions: updatedActions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (event) {
|
||||||
|
updateBackend(
|
||||||
|
selectedProduct.productName,
|
||||||
|
selectedProduct.productUuid,
|
||||||
|
projectId || '',
|
||||||
|
event
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useFrame(() => {
|
||||||
|
if (!isDragging || !plane.current || !raycaster || !outerGroup.current) return;
|
||||||
|
const intersectPoint = new Vector3();
|
||||||
|
const intersects = raycaster.ray.intersectPlane(
|
||||||
|
plane.current,
|
||||||
|
intersectPoint
|
||||||
|
);
|
||||||
|
if (!intersects) return;
|
||||||
|
const localPoint = outerGroup?.current.worldToLocal(intersectPoint.clone());
|
||||||
|
if (isDragging === "start") {
|
||||||
|
setStartPosition([localPoint.x, 0.5, localPoint.z]);
|
||||||
|
} else if (isDragging === "end") {
|
||||||
|
setEndPosition([localPoint.x, 0.5, localPoint.z]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useFrame((state) => {
|
||||||
|
if (!isRotating) return;
|
||||||
|
const currentPointerX = state.pointer.x;
|
||||||
|
const deltaX = currentPointerX - prevMousePos.current.x;
|
||||||
|
prevMousePos.current.x = currentPointerX;
|
||||||
|
const marker =
|
||||||
|
isRotating === "start" ? startMarker.current : endMarker.current;
|
||||||
|
if (marker) {
|
||||||
|
const rotationSpeed = 10;
|
||||||
|
marker.rotation.y += deltaX * rotationSpeed;
|
||||||
|
if (isRotating === "start") {
|
||||||
|
setStartRotation([
|
||||||
|
marker.rotation.x,
|
||||||
|
marker.rotation.y,
|
||||||
|
marker.rotation.z,
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
setEndRotation([
|
||||||
|
marker.rotation.x,
|
||||||
|
marker.rotation.y,
|
||||||
|
marker.rotation.z,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const handleGlobalPointerUp = () => {
|
||||||
|
setIsDragging(null);
|
||||||
|
setIsRotating(null);
|
||||||
|
if (controls) (controls as any).enabled = true;
|
||||||
|
handlePointerUp();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isDragging || isRotating) {
|
||||||
|
window.addEventListener("pointerup", handleGlobalPointerUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("pointerup", handleGlobalPointerUp);
|
||||||
|
};
|
||||||
|
}, [isDragging, isRotating, startPosition, startRotation, endPosition, endRotation]);
|
||||||
|
|
||||||
function HumanUi({ human }: { human: HumanStatus }) {
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{selectedHumanData && (
|
||||||
|
<group
|
||||||
|
position={selectedHumanData.position}
|
||||||
|
rotation={selectedHumanData.rotation}
|
||||||
|
ref={outerGroup}
|
||||||
|
>
|
||||||
|
<primitive
|
||||||
|
name="startMarker"
|
||||||
|
object={startScene}
|
||||||
|
ref={startMarker}
|
||||||
|
position={startPosition}
|
||||||
|
rotation={startRotation}
|
||||||
|
onPointerDown={(e: any) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePointerDown(e, "start", "start");
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
(controls as any).enabled = true;
|
||||||
|
setIsDragging(null);
|
||||||
|
setIsRotating(null);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<primitive
|
||||||
|
name="endMarker"
|
||||||
|
object={endScene}
|
||||||
|
ref={endMarker}
|
||||||
|
position={endPosition}
|
||||||
|
rotation={endRotation}
|
||||||
|
onPointerDown={(e: any) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handlePointerDown(e, "end", "end");
|
||||||
|
}}
|
||||||
|
onPointerMissed={() => {
|
||||||
|
(controls as any).enabled = true;
|
||||||
|
setIsDragging(null);
|
||||||
|
setIsRotating(null);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</group>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ const VehicleUI = () => {
|
|||||||
const outerGroup = useRef<Group>(null);
|
const outerGroup = useRef<Group>(null);
|
||||||
const state: Types.ThreeState = useThree();
|
const state: Types.ThreeState = useThree();
|
||||||
const controls: any = state.controls;
|
const controls: any = state.controls;
|
||||||
const [selectedVehicleData, setSelectedVechicleData] = useState<{ position: [number, number, number]; rotation: [number, number, number]; }>({ position: [0, 0, 0], rotation: [0, 0, 0] });
|
const [selectedVehicleData, setSelectedVehicleData] = useState<{ position: [number, number, number]; rotation: [number, number, number]; }>({ position: [0, 0, 0], rotation: [0, 0, 0] });
|
||||||
const CIRCLE_RADIUS = 0.8;
|
const CIRCLE_RADIUS = 0.8;
|
||||||
const { selectedVersionStore } = useVersionContext();
|
const { selectedVersionStore } = useVersionContext();
|
||||||
const { selectedVersion } = selectedVersionStore();
|
const { selectedVersion } = selectedVersionStore();
|
||||||
@@ -71,7 +71,7 @@ const VehicleUI = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (selectedVehicle) {
|
if (selectedVehicle) {
|
||||||
setSelectedVechicleData({
|
setSelectedVehicleData({
|
||||||
position: selectedVehicle.position,
|
position: selectedVehicle.position,
|
||||||
rotation: selectedVehicle.rotation,
|
rotation: selectedVehicle.rotation,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -146,6 +146,40 @@ export const useSelectedAction = create<SelectedActionState>()(
|
|||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
interface SelectedAnimationState {
|
||||||
|
selectedAnimation: {
|
||||||
|
animationUuid: string;
|
||||||
|
animationName: string;
|
||||||
|
animationType: "behaviour" | "animatedTravel";
|
||||||
|
animation: string | null;
|
||||||
|
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
||||||
|
} | null;
|
||||||
|
setSelectedAnimation: (animation: {
|
||||||
|
animationUuid: string;
|
||||||
|
animationName: string;
|
||||||
|
animationType: "behaviour" | "animatedTravel";
|
||||||
|
animation: string | null;
|
||||||
|
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
||||||
|
}) => void;
|
||||||
|
clearSelectedAnimation: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useSelectedAnimation = create<SelectedAnimationState>()(
|
||||||
|
immer((set) => ({
|
||||||
|
selectedAnimation: null,
|
||||||
|
setSelectedAnimation: (animation) => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedAnimation = animation;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clearSelectedAnimation: () => {
|
||||||
|
set((state) => {
|
||||||
|
state.selectedAnimation = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
interface IsDraggingState {
|
interface IsDraggingState {
|
||||||
isDragging: "start" | "end" | null;
|
isDragging: "start" | "end" | null;
|
||||||
setIsDragging: (state: "start" | "end" | null) => void;
|
setIsDragging: (state: "start" | "end" | null) => void;
|
||||||
|
|||||||
3
app/src/types/simulationTypes.d.ts
vendored
3
app/src/types/simulationTypes.d.ts
vendored
@@ -78,7 +78,8 @@ interface HumanAction {
|
|||||||
animationName: string;
|
animationName: string;
|
||||||
animationType: "behaviour" | "animatedTravel";
|
animationType: "behaviour" | "animatedTravel";
|
||||||
animation: string | null;
|
animation: string | null;
|
||||||
travelPoints?: { startPoint: [number, number, number] | null; endPoint: [number, number, number] | null; }
|
startPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; }
|
||||||
|
endPoint?: { position: [number, number, number] | null; rotation: [number, number, number] | null; }
|
||||||
}[]
|
}[]
|
||||||
loadCapacity: number;
|
loadCapacity: number;
|
||||||
triggers: TriggerSchema[];
|
triggers: TriggerSchema[];
|
||||||
|
|||||||
Reference in New Issue
Block a user