added direction movement to asset during move and duplication

This commit is contained in:
2025-08-14 13:59:24 +05:30
parent d12ead7d35
commit 75f77c4204
3 changed files with 95 additions and 4 deletions

View File

@@ -35,6 +35,7 @@ const DuplicationControls3D = ({
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
const [axisConstraint, setAxisConstraint] = useState<"x" | "z" | null>(null);
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null); const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({}); const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
const [isDuplicating, setIsDuplicating] = useState(false); const [isDuplicating, setIsDuplicating] = useState(false);
@@ -82,6 +83,19 @@ const DuplicationControls3D = ({
const onKeyDown = (event: KeyboardEvent) => { const onKeyDown = (event: KeyboardEvent) => {
const keyCombination = detectModifierKeys(event); const keyCombination = detectModifierKeys(event);
if (isDuplicating && duplicatedObjects.length > 0) {
if (event.key.toLowerCase() === 'x') {
setAxisConstraint(prev => prev === 'x' ? null : 'x');
event.preventDefault();
return;
}
if (event.key.toLowerCase() === 'z') {
setAxisConstraint(prev => prev === 'z' ? null : 'z');
event.preventDefault();
return;
}
}
if (keyCombination === "Ctrl+D" && movedObjects.length === 0 && rotatedObjects.length === 0) { if (keyCombination === "Ctrl+D" && movedObjects.length === 0 && rotatedObjects.length === 0) {
duplicateSelection(); duplicateSelection();
} }
@@ -127,7 +141,28 @@ const DuplicationControls3D = ({
} }
if (dragOffset) { if (dragOffset) {
const adjustedHit = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); let adjustedHit = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
if (axisConstraint) {
const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
if (model) {
const currentBasePosition = model.position.clone();
if (axisConstraint === 'x') {
adjustedHit = new THREE.Vector3(
adjustedHit.x,
currentBasePosition.y,
currentBasePosition.z
);
} else if (axisConstraint === 'z') {
adjustedHit = new THREE.Vector3(
currentBasePosition.x,
currentBasePosition.y,
adjustedHit.z
);
}
}
}
duplicatedObjects.forEach((duplicatedObject: THREE.Object3D) => { duplicatedObjects.forEach((duplicatedObject: THREE.Object3D) => {
if (duplicatedObject.userData.modelUuid) { if (duplicatedObject.userData.modelUuid) {
@@ -154,6 +189,21 @@ const DuplicationControls3D = ({
} }
}); });
useEffect(() => {
if (duplicatedObjects.length > 0) {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const model = scene.getObjectByProperty("uuid", duplicatedObjects[0].userData.modelUuid);
if (model) {
const newOffset = calculateDragOffset(model, intersectionPoint);
setDragOffset(newOffset);
}
}
}
}, [axisConstraint, camera, duplicatedObjects])
const duplicateSelection = useCallback(() => { const duplicateSelection = useCallback(() => {
if (selectedAssets.length > 0 && duplicatedObjects.length === 0) { if (selectedAssets.length > 0 && duplicatedObjects.length === 0) {
const positions: Record<string, THREE.Vector3> = {}; const positions: Record<string, THREE.Vector3> = {};
@@ -585,6 +635,7 @@ const DuplicationControls3D = ({
setSelectedAssets([]); setSelectedAssets([]);
setIsDuplicating(false); setIsDuplicating(false);
setDragOffset(null); setDragOffset(null);
setAxisConstraint(null);
}; };
return null; return null;

View File

@@ -43,6 +43,7 @@ function MoveControls3D({
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const [axisConstraint, setAxisConstraint] = useState<"x" | "z" | null>(null);
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null); const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({}); const [initialPositions, setInitialPositions] = useState<Record<string, THREE.Vector3>>({});
const [initialStates, setInitialStates] = useState<Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }>>({}); const [initialStates, setInitialStates] = useState<Record<string, { position: THREE.Vector3; rotation?: THREE.Euler; }>>({});
@@ -114,6 +115,19 @@ function MoveControls3D({
if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0) if (pastedObjects.length > 0 || duplicatedObjects.length > 0 || rotatedObjects.length > 0)
return; return;
if (isMoving && movedObjects.length > 0) {
if (event.key.toLowerCase() === 'x') {
setAxisConstraint(prev => prev === 'x' ? null : 'x');
event.preventDefault();
return;
}
if (event.key.toLowerCase() === 'z') {
setAxisConstraint(prev => prev === 'z' ? null : 'z');
event.preventDefault();
return;
}
}
if (keyCombination !== keyEvent) { if (keyCombination !== keyEvent) {
if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") { if (keyCombination === "Ctrl" || keyCombination === "Ctrl+Shift" || keyCombination === "Shift") {
setKeyEvent(keyCombination); setKeyEvent(keyCombination);
@@ -184,9 +198,22 @@ function MoveControls3D({
} }
} }
}); });
}, 0) setAxisConstraint(null);
}, 100)
}, [movedObjects, initialStates, updateAsset]); }, [movedObjects, initialStates, updateAsset]);
useEffect(() => {
if (movedObjects.length > 0) {
const intersectionPoint = new THREE.Vector3();
raycaster.setFromCamera(pointer, camera);
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const newOffset = calculateDragOffset(movedObjects[0], intersectionPoint);
setDragOffset(newOffset);
}
}
}, [axisConstraint, camera, movedObjects])
useFrame(() => { useFrame(() => {
if (!isMoving || movedObjects.length === 0) return; if (!isMoving || movedObjects.length === 0) return;
@@ -204,7 +231,16 @@ function MoveControls3D({
} }
if (dragOffset) { if (dragOffset) {
const rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset); let rawBasePosition = new THREE.Vector3().addVectors(intersectionPoint, dragOffset);
if (axisConstraint) {
const currentBasePosition = movedObjects[0].position.clone();
if (axisConstraint === 'x') {
rawBasePosition = new THREE.Vector3(rawBasePosition.x, currentBasePosition.y, currentBasePosition.z);
} else if (axisConstraint === 'z') {
rawBasePosition = new THREE.Vector3(currentBasePosition.x, currentBasePosition.y, rawBasePosition.z);
}
}
let moveDistance = keyEvent.includes("Shift") ? 0.05 : 1; let moveDistance = keyEvent.includes("Shift") ? 0.05 : 1;
@@ -422,6 +458,7 @@ function MoveControls3D({
echo.success("Object moved!"); echo.success("Object moved!");
setIsMoving(false); setIsMoving(false);
clearSelection(); clearSelection();
setAxisConstraint(null);
}; };
const clearSelection = () => { const clearSelection = () => {

View File

@@ -11,6 +11,7 @@ import useVersionHistoryVisibleStore, {
useDfxUpload, useDfxUpload,
useRenameModeStore, useRenameModeStore,
useSaveVersion, useSaveVersion,
useSelectedAssets,
useSelectedComment, useSelectedComment,
useSelectedFloorItem, useSelectedFloorItem,
useSelectedWallItem, useSelectedWallItem,
@@ -40,6 +41,7 @@ const KeyPressListener: React.FC = () => {
const { toggleView, setToggleView } = useToggleView(); const { toggleView, setToggleView } = useToggleView();
const { setAddAction } = useAddAction(); const { setAddAction } = useAddAction();
const { setSelectedWallItem } = useSelectedWallItem(); const { setSelectedWallItem } = useSelectedWallItem();
const { selectedAssets } = useSelectedAssets();
const { setActiveTool } = useActiveTool(); const { setActiveTool } = useActiveTool();
const { clearSelectedZone } = useSelectedZoneStore(); const { clearSelectedZone } = useSelectedZoneStore();
const { showShortcuts, setShowShortcuts } = useShortcutStore(); const { showShortcuts, setShowShortcuts } = useShortcutStore();
@@ -82,7 +84,7 @@ const KeyPressListener: React.FC = () => {
H: "free-hand", H: "free-hand",
}; };
const tool = toolMap[key]; const tool = toolMap[key];
if (tool) { if (tool && selectedAssets.length === 0) {
setActiveTool(tool); setActiveTool(tool);
setActiveSubTool(tool); setActiveSubTool(tool);
} }
@@ -278,6 +280,7 @@ const KeyPressListener: React.FC = () => {
hidePlayer, hidePlayer,
selectedFloorItem, selectedFloorItem,
isRenameMode, isRenameMode,
selectedAssets
]); ]);
return null; return null;