From 4639aa8209eaad8c0149a3a94a39fc98a3a87e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BC=C3=9Femeyer?= <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:26:30 +0200 Subject: [PATCH 1/5] Only use d/f switching / dynamic space direction for d/f --- .../controller/combinations/move_handlers.ts | 11 ++++++++-- .../controller/viewmodes/plane_controller.tsx | 21 ++++++++++++------- .../viewer/model/actions/flycam_actions.ts | 9 +++++++- .../viewer/model/reducers/flycam_reducer.ts | 14 ++++++++++--- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/frontend/javascripts/viewer/controller/combinations/move_handlers.ts b/frontend/javascripts/viewer/controller/combinations/move_handlers.ts index 4bce751bfa..1d78461009 100644 --- a/frontend/javascripts/viewer/controller/combinations/move_handlers.ts +++ b/frontend/javascripts/viewer/controller/combinations/move_handlers.ts @@ -36,7 +36,11 @@ export const moveU = (deltaU: number): void => { export const moveV = (deltaV: number): void => { movePlane([0, deltaV, 0]); }; -export const moveW = (deltaW: number, oneSlide: boolean): void => { +export const moveW = ( + deltaW: number, + oneSlide: boolean, + useDynamicSpaceDirection: boolean, +): void => { const state = Store.getState(); if (is2dDataset(state.dataset)) { return; @@ -58,10 +62,13 @@ export const moveW = (deltaW: number, oneSlide: boolean): void => { moveFlycamOrthoAction( Dimensions.transDim([0, 0, Math.sign(deltaW) * Math.max(1, wStep)], activeViewport), activeViewport, + useDynamicSpaceDirection, ), ); } else { - Store.dispatch(movePlaneFlycamOrthoAction([0, 0, deltaW], activeViewport, false)); + Store.dispatch( + movePlaneFlycamOrthoAction([0, 0, deltaW], activeViewport, false, useDynamicSpaceDirection), + ); } }; export function moveWhenAltIsPressed(delta: Point2, position: Point2, _id: any, event: MouseEvent) { diff --git a/frontend/javascripts/viewer/controller/viewmodes/plane_controller.tsx b/frontend/javascripts/viewer/controller/viewmodes/plane_controller.tsx index 6e922405fb..47c873aab6 100644 --- a/frontend/javascripts/viewer/controller/viewmodes/plane_controller.tsx +++ b/frontend/javascripts/viewer/controller/viewmodes/plane_controller.tsx @@ -220,11 +220,18 @@ class BoundingBoxKeybindings { } } -function createDelayAwareMoveHandler(multiplier: number) { +function createDelayAwareMoveHandler( + multiplier: number, + useDynamicSpaceDirection: boolean = false, +) { // The multiplier can be used for inverting the direction as well as for // speeding up the movement as it's done for shift+f, for example. const fn = (timeFactor: number, first: boolean) => - MoveHandlers.moveW(getMoveOffset(Store.getState(), timeFactor) * multiplier, first); + MoveHandlers.moveW( + getMoveOffset(Store.getState(), timeFactor) * multiplier, + first, + useDynamicSpaceDirection, + ); fn.customAdditionalDelayFn = () => { // Depending on the float fraction of the current position, we want to @@ -251,7 +258,7 @@ function createDelayAwareMoveHandler(multiplier: number) { const voxelPerSecond = state.userConfiguration.moveValue / state.dataset.dataSource.scale.factor[thirdDim]; - if (state.userConfiguration.dynamicSpaceDirection) { + if (state.userConfiguration.dynamicSpaceDirection && useDynamicSpaceDirection) { // Change direction of the value connected to space, based on the last direction direction *= state.flycam.spaceDirectionOrtho[thirdDim]; } @@ -441,15 +448,15 @@ class PlaneController extends React.PureComponent { // KeyboardJS is sensitive to ordering (complex combos first) "shift + i": () => VolumeHandlers.changeBrushSizeIfBrushIsActiveBy(-1), "shift + o": () => VolumeHandlers.changeBrushSizeIfBrushIsActiveBy(1), - "shift + f": createDelayAwareMoveHandler(5), - "shift + d": createDelayAwareMoveHandler(-5), + "shift + f": createDelayAwareMoveHandler(5, true), + "shift + d": createDelayAwareMoveHandler(-5, true), "shift + space": createDelayAwareMoveHandler(-1), "ctrl + space": createDelayAwareMoveHandler(-1), enter: () => Store.dispatch(enterAction()), esc: () => Store.dispatch(escapeAction()), space: createDelayAwareMoveHandler(1), - f: createDelayAwareMoveHandler(1), - d: createDelayAwareMoveHandler(-1), + f: createDelayAwareMoveHandler(1, true), + d: createDelayAwareMoveHandler(-1, true), // Zoom in/out i: () => MoveHandlers.zoom(1, false), o: () => MoveHandlers.zoom(-1, false), diff --git a/frontend/javascripts/viewer/model/actions/flycam_actions.ts b/frontend/javascripts/viewer/model/actions/flycam_actions.ts index a48e0a0e9f..15030bc773 100644 --- a/frontend/javascripts/viewer/model/actions/flycam_actions.ts +++ b/frontend/javascripts/viewer/model/actions/flycam_actions.ts @@ -101,23 +101,30 @@ export const setDirectionAction = (direction: Vector3) => direction, }) as const; -export const moveFlycamOrthoAction = (vector: Vector3, planeId: OrthoView | null | undefined) => +export const moveFlycamOrthoAction = ( + vector: Vector3, + planeId: OrthoView | null | undefined, + useDynamicSpaceDirection: boolean = false, +) => ({ type: "MOVE_FLYCAM_ORTHO", vector, planeId, + useDynamicSpaceDirection, }) as const; export const movePlaneFlycamOrthoAction = ( vector: Vector3, planeId: OrthoView, increaseSpeedWithZoom: boolean = true, + useDynamicSpaceDirection: boolean = false, ) => ({ type: "MOVE_PLANE_FLYCAM_ORTHO", vector, planeId, increaseSpeedWithZoom, + useDynamicSpaceDirection, }) as const; export const moveFlycamAction = (vector: Vector3) => diff --git a/frontend/javascripts/viewer/model/reducers/flycam_reducer.ts b/frontend/javascripts/viewer/model/reducers/flycam_reducer.ts index 627ab7aa19..6583319749 100644 --- a/frontend/javascripts/viewer/model/reducers/flycam_reducer.ts +++ b/frontend/javascripts/viewer/model/reducers/flycam_reducer.ts @@ -336,7 +336,11 @@ function FlycamReducer(state: WebknossosState, action: Action): WebknossosState .toArray(); // if planeID is given, use it to manipulate z - if (planeId != null && state.userConfiguration.dynamicSpaceDirection) { + if ( + planeId != null && + state.userConfiguration.dynamicSpaceDirection && + action.useDynamicSpaceDirection + ) { // change direction of the value connected to space, based on the last direction deltaInWorldV3 = V3.multiply(deltaInWorldV3, state.flycam.spaceDirectionOrtho); } @@ -363,8 +367,12 @@ function FlycamReducer(state: WebknossosState, action: Action): WebknossosState scaleFactor, ); - if (planeId != null && state.userConfiguration.dynamicSpaceDirection) { - // change direction of the value connected to space, based on the last direction + if ( + planeId != null && + state.userConfiguration.dynamicSpaceDirection && + action.useDynamicSpaceDirection + ) { + // Change direction of the value connected to space, based on the last direction deltaInWorldZoomed = V3.multiply(deltaInWorldZoomed, state.flycam.spaceDirectionOrtho); } From 2390b4169e4ce5c8d79d889483578026808e6f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BC=C3=9Femeyer?= <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Thu, 17 Jul 2025 17:36:36 +0200 Subject: [PATCH 2/5] add changelog entry --- unreleased_changes/8786.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 unreleased_changes/8786.md diff --git a/unreleased_changes/8786.md b/unreleased_changes/8786.md new file mode 100644 index 0000000000..5db4b855d1 --- /dev/null +++ b/unreleased_changes/8786.md @@ -0,0 +1,2 @@ +### Changed +- Change that the d/f switching setting no longer affects movements other than moving via the d/f keyboard shortcuts. \ No newline at end of file From c2f75c6e24cec600748180ab7ce4570ec698e1ad Mon Sep 17 00:00:00 2001 From: MichaelBuessemeyer <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:28:39 +0200 Subject: [PATCH 3/5] Update unreleased_changes/8786.md Co-authored-by: Philipp Otto --- unreleased_changes/8786.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unreleased_changes/8786.md b/unreleased_changes/8786.md index 5db4b855d1..a26e39242f 100644 --- a/unreleased_changes/8786.md +++ b/unreleased_changes/8786.md @@ -1,2 +1,2 @@ ### Changed -- Change that the d/f switching setting no longer affects movements other than moving via the d/f keyboard shortcuts. \ No newline at end of file +- Changed that the d/f switching setting no longer affects movements other than moving via the d/f keyboard shortcuts. \ No newline at end of file From 4bee8400df871a11c40c8132a283984583873200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BC=C3=9Femeyer?= <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:40:58 +0200 Subject: [PATCH 4/5] add missing default for moveW in move_handlers --- .../javascripts/viewer/controller/combinations/move_handlers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/javascripts/viewer/controller/combinations/move_handlers.ts b/frontend/javascripts/viewer/controller/combinations/move_handlers.ts index 1d78461009..2d3af6f1af 100644 --- a/frontend/javascripts/viewer/controller/combinations/move_handlers.ts +++ b/frontend/javascripts/viewer/controller/combinations/move_handlers.ts @@ -39,7 +39,7 @@ export const moveV = (deltaV: number): void => { export const moveW = ( deltaW: number, oneSlide: boolean, - useDynamicSpaceDirection: boolean, + useDynamicSpaceDirection: boolean = false, ): void => { const state = Store.getState(); if (is2dDataset(state.dataset)) { From f04a366a56409b88dd3826932d279494477dd379 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20B=C3=BC=C3=9Femeyer?= <39529669+MichaelBuessemeyer@users.noreply.github.com> Date: Fri, 18 Jul 2025 10:57:38 +0200 Subject: [PATCH 5/5] fix frontend tests && add new test checking dynamicSpaceDirection to not be applied if not said so by the action --- .../test/reducers/flycam_reducer.spec.ts | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/frontend/javascripts/test/reducers/flycam_reducer.spec.ts b/frontend/javascripts/test/reducers/flycam_reducer.spec.ts index 00ccc9890e..61e9718816 100644 --- a/frontend/javascripts/test/reducers/flycam_reducer.spec.ts +++ b/frontend/javascripts/test/reducers/flycam_reducer.spec.ts @@ -163,11 +163,20 @@ describe("Flycam", () => { let newState = FlycamReducer(initialState, FlycamActions.setDirectionAction([0, 0, -2])); newState = FlycamReducer( newState, - FlycamActions.moveFlycamOrthoAction([2, 0, 2], OrthoViews.PLANE_XY), + FlycamActions.moveFlycamOrthoAction([2, 0, 2], OrthoViews.PLANE_XY, true), ); equalWithEpsilon(getPosition(newState.flycam), [2, 0, -2]); }); + it("should move not in ortho mode with dynamicSpaceDirection if action does not explicity say so", () => { + let newState = FlycamReducer(initialState, FlycamActions.setDirectionAction([0, 0, -2])); + newState = FlycamReducer( + newState, + FlycamActions.moveFlycamOrthoAction([2, 0, 2], OrthoViews.PLANE_XY), + ); + equalWithEpsilon(getPosition(newState.flycam), [2, 0, 2]); + }); + it("should move by plane in ortho mode (1/3)", () => { const moveAction = FlycamActions.movePlaneFlycamOrthoAction( [2, 0, 0], @@ -202,11 +211,20 @@ describe("Flycam", () => { let newState = FlycamReducer(initialState, FlycamActions.setDirectionAction([0, 0, -2])); newState = FlycamReducer( newState, - FlycamActions.movePlaneFlycamOrthoAction([0, 0, 2], OrthoViews.PLANE_XY, true), + FlycamActions.movePlaneFlycamOrthoAction([0, 0, 2], OrthoViews.PLANE_XY, true, true), ); equalWithEpsilon(getPosition(newState.flycam), [0, 0, -2]); }); + it("should not move by plane in ortho mode with dynamicSpaceDirection if action does not explicity say so", () => { + let newState = FlycamReducer(initialState, FlycamActions.setDirectionAction([0, 0, -2])); + newState = FlycamReducer( + newState, + FlycamActions.movePlaneFlycamOrthoAction([0, 0, 2], OrthoViews.PLANE_XY, true), + ); + equalWithEpsilon(getPosition(newState.flycam), [0, 0, 2]); + }); + it("should not change additional coordinates value when layers don't have any", () => { const newState = FlycamReducer( initialState,