mirror of
https://github.com/invoke-ai/InvokeAI.git
synced 2026-04-23 03:00:31 -04:00
feat(ui):Adjust-bbox-to-masks
This commit is contained in:
committed by
psychedelicious
parent
1f5f70f898
commit
7640ee307c
@@ -599,6 +599,10 @@
|
||||
"toggleNonRasterLayers": {
|
||||
"title": "Toggle Non-Raster Layers",
|
||||
"desc": "Show or hide all non-raster layer categories (Control Layers, Inpaint Masks, Regional Guidance)."
|
||||
},
|
||||
"fitBboxToMasks": {
|
||||
"title": "Fit Bbox To Masks",
|
||||
"desc": "Automatically adjust the generation bounding box to fit visible inpaint masks"
|
||||
}
|
||||
},
|
||||
"workflows": {
|
||||
@@ -1940,6 +1944,7 @@
|
||||
"canvas": "Canvas",
|
||||
"bookmark": "Bookmark for Quick Switch",
|
||||
"fitBboxToLayers": "Fit Bbox To Layers",
|
||||
"fitBboxToMasks": "Fit Bbox To Masks",
|
||||
"removeBookmark": "Remove Bookmark",
|
||||
"saveCanvasToGallery": "Save Canvas to Gallery",
|
||||
"saveBboxToGallery": "Save Bbox to Gallery",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { CanvasSettingsPopover } from 'features/controlLayers/components/Setting
|
||||
import { ToolColorPicker } from 'features/controlLayers/components/Tool/ToolFillColorPicker';
|
||||
import { ToolSettings } from 'features/controlLayers/components/Tool/ToolSettings';
|
||||
import { CanvasToolbarFitBboxToLayersButton } from 'features/controlLayers/components/Toolbar/CanvasToolbarFitBboxToLayersButton';
|
||||
import { CanvasToolbarFitBboxToMasksButton } from 'features/controlLayers/components/Toolbar/CanvasToolbarFitBboxToMasksButton';
|
||||
import { CanvasToolbarNewSessionMenuButton } from 'features/controlLayers/components/Toolbar/CanvasToolbarNewSessionMenuButton';
|
||||
import { CanvasToolbarRedoButton } from 'features/controlLayers/components/Toolbar/CanvasToolbarRedoButton';
|
||||
import { CanvasToolbarResetViewButton } from 'features/controlLayers/components/Toolbar/CanvasToolbarResetViewButton';
|
||||
@@ -37,6 +38,7 @@ export const CanvasToolbar = memo(() => {
|
||||
<CanvasToolbarScale />
|
||||
<CanvasToolbarResetViewButton />
|
||||
<CanvasToolbarFitBboxToLayersButton />
|
||||
<CanvasToolbarFitBboxToMasksButton />
|
||||
</Flex>
|
||||
<Divider orientation="vertical" />
|
||||
<Flex alignItems="center" h="full">
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import { IconButton } from '@invoke-ai/ui-library';
|
||||
import { useAutoFitBBoxToMasks } from 'features/controlLayers/hooks/useAutoFitBBoxToMasks';
|
||||
import { useCanvasIsBusy } from 'features/controlLayers/hooks/useCanvasIsBusy';
|
||||
import { useVisibleEntityCountByType } from 'features/controlLayers/hooks/useVisibleEntityCountByType';
|
||||
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiSelectionAllDuotone } from 'react-icons/pi';
|
||||
|
||||
export const CanvasToolbarFitBboxToMasksButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isBusy = useCanvasIsBusy();
|
||||
const fitBBoxToMasks = useAutoFitBBoxToMasks();
|
||||
|
||||
// Check if there are any visible inpaint masks
|
||||
const visibleMaskCount = useVisibleEntityCountByType('inpaint_mask');
|
||||
const hasVisibleMasks = visibleMaskCount > 0;
|
||||
|
||||
const onClick = useCallback(() => {
|
||||
fitBBoxToMasks();
|
||||
}, [fitBBoxToMasks]);
|
||||
|
||||
// Register hotkey for Shift+B
|
||||
useRegisteredHotkeys({
|
||||
id: 'fitBboxToMasks',
|
||||
category: 'canvas',
|
||||
callback: fitBBoxToMasks,
|
||||
options: { enabled: !isBusy && hasVisibleMasks },
|
||||
dependencies: [fitBBoxToMasks, isBusy, hasVisibleMasks],
|
||||
});
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
onClick={onClick}
|
||||
variant="link"
|
||||
alignSelf="stretch"
|
||||
aria-label={t('controlLayers.fitBboxToMasks')}
|
||||
tooltip={t('controlLayers.fitBboxToMasks')}
|
||||
icon={<PiSelectionAllDuotone />}
|
||||
isDisabled={isBusy || !hasVisibleMasks}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
CanvasToolbarFitBboxToMasksButton.displayName = 'CanvasToolbarFitBboxToMasksButton';
|
||||
@@ -0,0 +1,40 @@
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { useCanvasManager } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
|
||||
import { fitRectToGrid } from 'features/controlLayers/konva/util';
|
||||
import { selectMaskBlur } from 'features/controlLayers/store/paramsSlice';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const useAutoFitBBoxToMasks = () => {
|
||||
const canvasManager = useCanvasManager();
|
||||
const maskBlur = useAppSelector(selectMaskBlur);
|
||||
|
||||
const fitBBoxToMasks = useCallback(() => {
|
||||
// Get the rect of all visible inpaint masks
|
||||
const visibleRect = canvasManager.compositor.getVisibleRectOfType('inpaint_mask');
|
||||
|
||||
// Can't fit the bbox to nothing
|
||||
if (visibleRect.height === 0 || visibleRect.width === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Account for mask blur expansion and add 8px padding
|
||||
const padding = 8;
|
||||
const totalPadding = maskBlur + padding;
|
||||
|
||||
const expandedRect = {
|
||||
x: visibleRect.x - totalPadding,
|
||||
y: visibleRect.y - totalPadding,
|
||||
width: visibleRect.width + totalPadding * 2,
|
||||
height: visibleRect.height + totalPadding * 2,
|
||||
};
|
||||
|
||||
// Apply grid fitting using the bbox grid size
|
||||
const gridSize = canvasManager.stateApi.getBboxGridSize();
|
||||
const rect = fitRectToGrid(expandedRect, gridSize);
|
||||
|
||||
// Update the generation bbox
|
||||
canvasManager.stateApi.setGenerationBbox(rect);
|
||||
}, [canvasManager, maskBlur]);
|
||||
|
||||
return fitBBoxToMasks;
|
||||
};
|
||||
@@ -123,6 +123,7 @@ export const useHotkeyData = (): HotkeysData => {
|
||||
addHotkey('canvas', 'applySegmentAnything', ['enter']);
|
||||
addHotkey('canvas', 'cancelSegmentAnything', ['esc']);
|
||||
addHotkey('canvas', 'toggleNonRasterLayers', ['shift+h']);
|
||||
addHotkey('canvas', 'fitBboxToMasks', ['shift+b']);
|
||||
|
||||
// Workflows
|
||||
addHotkey('workflows', 'addNode', ['shift+a', 'space']);
|
||||
|
||||
Reference in New Issue
Block a user