diff --git a/components/label/components/PaperContainer.tsx b/components/label/components/PaperContainer.tsx index 85e75fc..fd5c1fc 100644 --- a/components/label/components/PaperContainer.tsx +++ b/components/label/components/PaperContainer.tsx @@ -38,6 +38,7 @@ import { getTrackingAuxiliaryAnnotation, } from "../api/label" import { Project } from "../api/project/typing" +import { labelimagePerformanceConfig } from "../config/performance" import { LabelState } from "../LabelNossr" import { initialDetail, @@ -57,7 +58,6 @@ import useRenderTag from "../useRenderTag" import { useRightToolsStore } from "../useRightToolsStore" import { useTopToolsStore } from "../useTopToolsStore" import { checkCommentsIsSame } from "../util" -import { labelimagePerformanceConfig } from "../config/performance" import { safeClone } from "../utils/clone" import { labelTypeMap } from "../utils/constants" import { adjustPoints } from "../utils/paperjs" @@ -126,6 +126,11 @@ type FrameSwitchGhostState = { animating: boolean } +const clonePaperPoint = (point: paper.Point | null | undefined) => { + if (!point) return null + return new paper.Point(point.x, point.y) +} + const normalizePoint = (value: any): NormalizedPoint | null => { if (value instanceof paper.Point) return [value.x, value.y] if (value instanceof paper.Segment) { @@ -445,6 +450,7 @@ const PaperContainer = ( assistToolEnabled, assistToolSize, renderMode, + saveCurrentScale, showTags, showTagsConfigs, } = useTopToolsStore() @@ -2583,6 +2589,24 @@ const PaperContainer = ( } }, [renderMode, stopRenderModePan]) + const getTargetGroupPosition = useCallback( + ({ + defaultPosition, + preservedPosition, + canPreserve, + }: { + defaultPosition: paper.Point + preservedPosition?: paper.Point | null + canPreserve?: boolean + }) => { + if (saveCurrentScale && canPreserve && preservedPosition) { + return clonePaperPoint(preservedPosition) ?? defaultPosition.clone() + } + return defaultPosition.clone() + }, + [saveCurrentScale] + ) + const preparePendingFrameSwitch = useCallback( async (imageName: string, token: number) => { if ( @@ -2600,6 +2624,12 @@ const PaperContainer = ( clearPendingFrameSwitch(token) return } + const preserveGroupPosition = + saveCurrentScale && + currentVisibleGroup.getItems({ data: { name: "pic" } }).length > 0 + const preservedGroupPosition = preserveGroupPosition + ? clonePaperPoint(currentVisibleGroup.position) + : null const stagingGroup = new paper.Group({ applyMatrix: false, @@ -2684,10 +2714,15 @@ const PaperContainer = ( raster.bounds.width / 2, raster.bounds.height / 2 ) - stagingGroup.position = new paper.Point( + const centeredGroupPosition = new paper.Point( raster.bounds.width / 2, raster.bounds.height / 2 ) + stagingGroup.position = getTargetGroupPosition({ + defaultPosition: centeredGroupPosition, + preservedPosition: preservedGroupPosition, + canPreserve: preserveGroupPosition, + }) raster.sendToBack() const imageData = useLabelStore.getState().label.get(imageName) @@ -2732,6 +2767,7 @@ const PaperContainer = ( [ clearPendingFrameSwitch, commitFrameSwitch, + getTargetGroupPosition, imgSize?.clientHeight, imgSize?.clientWidth, isPendingFrameSwitchStale, @@ -2739,6 +2775,7 @@ const PaperContainer = ( reconcileRasterScaleForImage, renderImagePolygonsBatchedToGroup, renderTag, + saveCurrentScale, setGroup, setRasterPath, setRasterSize, @@ -2823,6 +2860,11 @@ const PaperContainer = ( if (activeImage && projectDetail?.id) { const requestId = ++rasterLoadRequestIdRef.current const requestImage = activeImage + const preserveGroupPosition = + saveCurrentScale && getPicRasters(paperGroup).length > 0 + const preservedGroupPosition = preserveGroupPosition + ? clonePaperPoint(paperGroup.position) + : null rasterLoadingImageRef.current = requestImage cancelRasterFadeTransition() getPicRasters(paperGroup).forEach((item) => { @@ -2981,6 +3023,10 @@ const PaperContainer = ( raster.bounds.width / 2, raster.bounds.height / 2 ) + const centeredGroupPosition = new paper.Point( + raster.bounds.width / 2, + raster.bounds.height / 2 + ) raster.visible = true const previousRasters = getPicRasters(paperGroup).filter( (item) => item !== raster @@ -3034,10 +3080,11 @@ const PaperContainer = ( }) } - usePaperStore.getState().group!.position = new paper.Point( - raster.bounds.width / 2, - raster.bounds.height / 2 - ) + paperGroup.position = getTargetGroupPosition({ + defaultPosition: centeredGroupPosition, + preservedPosition: preservedGroupPosition, + canPreserve: preserveGroupPosition, + }) setRasterPath(new paper.Path.Rectangle(raster.bounds)) raster.sendToBack() renderedImageRef.current = requestImage @@ -3059,9 +3106,11 @@ const PaperContainer = ( cancelRasterFadeTransition, decodeFrameImage, getPicRasters, + getTargetGroupPosition, imgSize?.clientHeight, imgSize?.clientWidth, projectDetail?.id, + saveCurrentScale, setRasterPath, setRasterScale, setRasterSize, @@ -3171,6 +3220,9 @@ const PaperContainer = ( : undefined) || (rasterItems.length ? rasterItems[rasterItems.length - 1] : undefined) if (!currentRaster) return false + const preservedGroupPosition = saveCurrentScale + ? clonePaperPoint(group.position) + : null const rasterSizeStore = usePaperStore.getState().rasterSize const rawRasterSize = rasterSizeStore[activeImage] ?? [ @@ -3224,10 +3276,15 @@ const PaperContainer = ( currentRaster.bounds.width / 2, currentRaster.bounds.height / 2 ) - group.position = new paper.Point( + const centeredGroupPosition = new paper.Point( currentRaster.bounds.width / 2, currentRaster.bounds.height / 2 ) + group.position = getTargetGroupPosition({ + defaultPosition: centeredGroupPosition, + preservedPosition: preservedGroupPosition, + canPreserve: saveCurrentScale, + }) setRasterPath(new paper.Path.Rectangle(currentRaster.bounds)) setRasterScale(activeImage, nextScale) @@ -3241,9 +3298,11 @@ const PaperContainer = ( }, [ activeImage, getPicRasters, + getTargetGroupPosition, imgSize?.clientHeight, imgSize?.clientWidth, renderTag, + saveCurrentScale, scaleRenderedAnnotationItemsInPlace, setRasterPath, setRasterScale,