From 7a6e8de60fd25815472e9a0ae38c0dab641c963e Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:42:12 +1000 Subject: [PATCH] feat(ui): reset view fits all visible objects --- .../components/CanvasResetViewButton.tsx | 4 +- .../controlLayers/konva/CanvasManager.ts | 38 ++++++++++++++++++- .../src/features/controlLayers/konva/util.ts | 18 +++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CanvasResetViewButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CanvasResetViewButton.tsx index 585f208803..4b380d0c16 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CanvasResetViewButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CanvasResetViewButton.tsx @@ -28,9 +28,9 @@ export const CanvasResetViewButton = memo(() => { const onReset = useCallback(() => { if ($shift.get()) { - resetZoom(); - } else { resetView(); + } else { + resetZoom(); } }, [resetView, resetZoom]); diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts index 4adc5c80e3..c52624217c 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/CanvasManager.ts @@ -6,6 +6,7 @@ import { MAX_CANVAS_SCALE, MIN_CANVAS_SCALE } from 'features/controlLayers/konva import { getImageDataTransparency, getPrefixedId, + getRectUnion, konvaNodeToBlob, konvaNodeToImageData, nanoid, @@ -179,9 +180,44 @@ export class CanvasManager { }); } + getVisibleRect = (): Rect => { + const rects = []; + + if (this.inpaintMaskAdapter.state.isEnabled) { + rects.push(this.inpaintMaskAdapter.transformer.getRelativeRect()); + } + + for (const adapter of this.rasterLayerAdapters.values()) { + if (adapter.state.isEnabled) { + rects.push(adapter.transformer.getRelativeRect()); + } + } + + for (const adapter of this.controlLayerAdapters.values()) { + if (adapter.state.isEnabled) { + rects.push(adapter.transformer.getRelativeRect()); + } + } + + for (const adapter of this.regionalGuidanceAdapters.values()) { + if (adapter.state.isEnabled) { + rects.push(adapter.transformer.getRelativeRect()); + } + } + + const rectUnion = getRectUnion(...rects); + + if (rectUnion.width === 0 || rectUnion.height === 0) { + // fall back to the bbox if there is no content + return this.stateApi.getBbox().rect; + } else { + return rectUnion; + } + }; + resetView() { const { width, height } = this.getStageSize(); - const { rect } = this.stateApi.getBbox(); + const rect = this.getVisibleRect(); const padding = 20; // Padding in absolute pixels diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/util.ts b/invokeai/frontend/web/src/features/controlLayers/konva/util.ts index 764d9759a9..092ca853fb 100644 --- a/invokeai/frontend/web/src/features/controlLayers/konva/util.ts +++ b/invokeai/frontend/web/src/features/controlLayers/konva/util.ts @@ -374,6 +374,7 @@ export function getObjectId(type: CanvasObjectState['type'], isBuffer?: boolean) export const getEmptyRect = (): Rect => { return { x: 0, y: 0, width: 0, height: 0 }; }; + export function snapToNearest(value: number, candidateValues: number[], threshold: number): number { let closest = value; let minDiff = Number.MAX_VALUE; @@ -388,3 +389,20 @@ export function snapToNearest(value: number, candidateValues: number[], threshol return closest; } + +/** + * Gets the union of two rects + * @param rect1 The first rect + * @param rect2 The second rect + * @returns The union of the two rects + */ +export const getRectUnion = (...rects: Rect[]): Rect => { + const rect = rects.reduce((acc, r) => { + const x = Math.min(acc.x, r.x); + const y = Math.min(acc.y, r.y); + const width = Math.max(acc.x + acc.width, r.x + r.width) - x; + const height = Math.max(acc.y + acc.height, r.y + r.height) - y; + return { x, y, width, height }; + }, getEmptyRect()); + return rect; +};