From 28f2bbc9ffa14438a919b23dc8b13866167e296a Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 27 Sep 2023 14:19:34 -0400 Subject: [PATCH 1/3] fix(paint): show paint stencil when mouse starts in view Stencil outline would not show if mouse started on view when point is was activated. --- src/components/tools/paint/PaintWidget2D.vue | 14 ++++++++++++++ src/vtk/PaintWidget/behavior.ts | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/components/tools/paint/PaintWidget2D.vue b/src/components/tools/paint/PaintWidget2D.vue index 4f7529b55..93229900e 100644 --- a/src/components/tools/paint/PaintWidget2D.vue +++ b/src/components/tools/paint/PaintWidget2D.vue @@ -23,6 +23,7 @@ import { PaintWidgetState } from '@/src/vtk/PaintWidget/state'; import { vec3 } from 'gl-matrix'; import { manageVTKSubscription } from '@/src/composables/manageVTKSubscription'; import { LPSAxisDir } from '@/src/types/lps'; +import { onVTKEvent } from '@/src/composables/onVTKEvent'; export default defineComponent({ name: 'PaintWidget2D', @@ -150,8 +151,21 @@ export default defineComponent({ // --- visibility --- // + let checkIfPointerInView = false; + onMounted(() => { widgetRef.value!.setVisibility(false); + checkIfPointerInView = true; + }); + + // Turn on widget visibility if mouse starts within view + onVTKEvent(viewProxyRef.value!.getInteractor(), 'onMouseMove', () => { + if (!checkIfPointerInView) { + return; + } + checkIfPointerInView = false; + + widgetRef.value!.setVisibility(true); }); manageVTKSubscription( diff --git a/src/vtk/PaintWidget/behavior.ts b/src/vtk/PaintWidget/behavior.ts index b4254c26f..cfb2f44b9 100644 --- a/src/vtk/PaintWidget/behavior.ts +++ b/src/vtk/PaintWidget/behavior.ts @@ -59,8 +59,11 @@ export default function widgetBehavior(publicAPI: any, model: any) { if (isPainting) { publicAPI.invokeInteractionEvent(); + return macro.EVENT_ABORT; } - return macro.EVENT_ABORT; + + // Let interactor get event + return macro.VOID; }; /** From 32045923ea19afc67f3eac8d13f56a1ad0b8c6c4 Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 27 Sep 2023 15:43:46 -0400 Subject: [PATCH 2/3] fix(paint): fix switching layouts with paint active --- src/components/tools/paint/PaintWidget2D.vue | 126 ++++++++----------- 1 file changed, 53 insertions(+), 73 deletions(-) diff --git a/src/components/tools/paint/PaintWidget2D.vue b/src/components/tools/paint/PaintWidget2D.vue index 93229900e..ffa5269c5 100644 --- a/src/components/tools/paint/PaintWidget2D.vue +++ b/src/components/tools/paint/PaintWidget2D.vue @@ -3,9 +3,6 @@ import vtkWidgetManager from '@kitware/vtk.js/Widgets/Core/WidgetManager'; import { computed, defineComponent, - onBeforeUnmount, - onMounted, - onUnmounted, PropType, ref, toRefs, @@ -15,15 +12,17 @@ import vtkPlaneManipulator from '@kitware/vtk.js/Widgets/Manipulators/PlaneManip import { getLPSAxisFromDir } from '@/src/utils/lps'; import { useCurrentImage } from '@/src/composables/useCurrentImage'; import { updatePlaneManipulatorFor2DView } from '@/src/utils/manipulators'; -import type { vtkSubscription } from '@kitware/vtk.js/interfaces'; import { usePaintToolStore } from '@/src/store/tools/paint'; import { vtkPaintViewWidget } from '@/src/vtk/PaintWidget'; import { useViewStore } from '@/src/store/views'; import { PaintWidgetState } from '@/src/vtk/PaintWidget/state'; import { vec3 } from 'gl-matrix'; -import { manageVTKSubscription } from '@/src/composables/manageVTKSubscription'; import { LPSAxisDir } from '@/src/types/lps'; import { onVTKEvent } from '@/src/composables/onVTKEvent'; +import { + onViewProxyMounted, + onViewProxyUnmounted, +} from '@/src/composables/useViewProxy'; export default defineComponent({ name: 'PaintWidget2D', @@ -47,17 +46,14 @@ export default defineComponent({ }, setup(props) { const { - widgetManager: widgetManagerRef, + widgetManager, viewDirection, slice, viewId: viewID, } = toRefs(props); const paintStore = usePaintToolStore(); - const factory = paintStore.getWidgetFactory(); - - const viewStore = useViewStore(); - const viewProxyRef = computed(() => viewStore.getViewProxy(viewID.value)); + const widgetFactory = paintStore.getWidgetFactory(); const widgetRef = ref(); @@ -74,13 +70,26 @@ export default defineComponent({ return indexPoint; }; - onMounted(() => { - const widgetManager = widgetManagerRef.value; - widgetRef.value = widgetManager.addWidget(factory) as vtkPaintViewWidget; + const viewProxy = computed(() => useViewStore().getViewProxy(viewID.value)); + + onViewProxyMounted(viewProxy, () => { + widgetRef.value = widgetManager.value.addWidget( + widgetFactory + ) as vtkPaintViewWidget; if (!widgetRef.value) { throw new Error('[PaintWidget2D] failed to create view widget'); } + + widgetManager.value.renderWidgets(); + widgetManager.value.grabFocus(widgetRef.value); + }); + + onViewProxyUnmounted(viewProxy, () => { + if (!widgetRef.value) { + return; + } + widgetManager.value.removeWidget(widgetRef.value); }); // --- widget representation config --- // @@ -98,45 +107,31 @@ export default defineComponent({ // --- interaction --- // - const subs: vtkSubscription[] = []; - - onMounted(() => { - const widget = widgetRef.value!; + onVTKEvent(widgetRef, 'onStartInteractionEvent', () => { + const state = widgetRef.value!.getWidgetState() as PaintWidgetState; + // StartInteraction cannot occur if origin is null. + const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); + paintStore.startStroke(indexPoint, viewAxisIndex.value); + }); - subs.push( - widget.onStartInteractionEvent(() => { - // start stroke - const state = widget.getWidgetState() as PaintWidgetState; - // StartInteraction cannot occur if origin is null. - const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); - paintStore.startStroke(indexPoint, viewAxisIndex.value); - }), - widget.onInteractionEvent(() => { - // register stroke - const state = widget.getWidgetState() as PaintWidgetState; - const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); - paintStore.placeStrokePoint(indexPoint, viewAxisIndex.value); - }), - widget.onEndInteractionEvent(() => { - // end stroke - const state = widget.getWidgetState() as PaintWidgetState; - const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); - paintStore.endStroke(indexPoint, viewAxisIndex.value); - }) - ); + onVTKEvent(widgetRef, 'onInteractionEvent', () => { + const state = widgetRef.value!.getWidgetState() as PaintWidgetState; + const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); + paintStore.placeStrokePoint(indexPoint, viewAxisIndex.value); }); - onUnmounted(() => { - while (subs.length) { - subs.pop()!.unsubscribe(); - } + onVTKEvent(widgetRef, 'onEndInteractionEvent', () => { + // end stroke + const state = widgetRef.value!.getWidgetState() as PaintWidgetState; + const indexPoint = worldPointToIndex(state.getBrush().getOrigin()!); + paintStore.endStroke(indexPoint, viewAxisIndex.value); }); // --- manipulator --- // const manipulator = vtkPlaneManipulator.newInstance(); - onMounted(() => { + onViewProxyMounted(viewProxy, () => { widgetRef.value!.setManipulator(manipulator); }); @@ -153,13 +148,15 @@ export default defineComponent({ let checkIfPointerInView = false; - onMounted(() => { + onViewProxyMounted(viewProxy, () => { widgetRef.value!.setVisibility(false); checkIfPointerInView = true; }); + const viewInteractor = computed(() => viewProxy.value!.getInteractor()); + // Turn on widget visibility if mouse starts within view - onVTKEvent(viewProxyRef.value!.getInteractor(), 'onMouseMove', () => { + onVTKEvent(viewInteractor, 'onMouseMove', () => { if (!checkIfPointerInView) { return; } @@ -168,36 +165,19 @@ export default defineComponent({ widgetRef.value!.setVisibility(true); }); - manageVTKSubscription( - viewProxyRef.value!.getInteractor().onMouseEnter(() => { - const widget = widgetRef.value; - if (widget) { - paintStore.setSliceAxis(viewAxisIndex.value); - widget.setVisibility(true); - } - }) - ); - - manageVTKSubscription( - viewProxyRef.value!.getInteractor().onMouseLeave(() => { - const widget = widgetRef.value; - if (widget) { - widget.setVisibility(false); - } - }) - ); - - // --- focus and rendering --- // - - onMounted(() => { - const widgetManager = widgetManagerRef.value; - widgetManager.renderWidgets(); - widgetManager.grabFocus(widgetRef.value!); + onVTKEvent(viewInteractor, 'onMouseEnter', () => { + const widget = widgetRef.value; + if (widget) { + paintStore.setSliceAxis(viewAxisIndex.value); + widget.setVisibility(true); + } }); - onBeforeUnmount(() => { - widgetManagerRef.value.removeWidget(widgetRef.value!); - widgetManagerRef.value.releaseFocus(); + onVTKEvent(viewInteractor, 'onMouseLeave', () => { + const widget = widgetRef.value; + if (widget) { + widget.setVisibility(false); + } }); return () => null; From 74050d931a16347bc7e3d3f187f208ef5ded643a Mon Sep 17 00:00:00 2001 From: Paul Elliott Date: Wed, 27 Sep 2023 15:48:57 -0400 Subject: [PATCH 3/3] fix(polygon): fix switching from polygon to paint tool --- src/vtk/PolygonWidget/behavior.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/vtk/PolygonWidget/behavior.ts b/src/vtk/PolygonWidget/behavior.ts index e68887968..8ed8ffe80 100644 --- a/src/vtk/PolygonWidget/behavior.ts +++ b/src/vtk/PolygonWidget/behavior.ts @@ -37,7 +37,7 @@ export default function widgetBehavior(publicAPI: any, model: any) { // overSegment guards against clicking anywhere in view const selections = model._widgetManager.getSelections(); const overSegment = - selections[0]?.getProperties().prop === + selections?.[0]?.getProperties().prop === model.representations[1].getActors()[0]; // line representation is second representation return overSegment && !overUnselectedHandle; }; @@ -428,6 +428,5 @@ export default function widgetBehavior(publicAPI: any, model: any) { model.activeState = null; model.hasFocus = false; model._widgetManager.enablePicking(); - model._interactor.render(); }; }