Skip to content

Commit 7a7a2e1

Browse files
cursoragentpsychedelicious
authored andcommitted
Add toggle for non-raster layers with hotkey and UI button
1 parent adf4cc7 commit 7a7a2e1

File tree

8 files changed

+104
-0
lines changed

8 files changed

+104
-0
lines changed

invokeai/frontend/web/public/locales/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@
579579
"cancelTransform": {
580580
"title": "Cancel Transform",
581581
"desc": "Cancel the pending transform."
582+
},
583+
"toggleNonRasterLayers": {
584+
"title": "Toggle Non-Raster Layers",
585+
"desc": "Show or hide all non-raster layer categories (Control Layers, Inpaint Masks, Regional Guidance)."
582586
}
583587
},
584588
"workflows": {
@@ -1994,6 +1998,8 @@
19941998
"disableTransparencyEffect": "Disable Transparency Effect",
19951999
"hidingType": "Hiding {{type}}",
19962000
"showingType": "Showing {{type}}",
2001+
"showNonRasterLayers": "Show Non-Raster Layers",
2002+
"hideNonRasterLayers": "Hide Non-Raster Layers",
19972003
"dynamicGrid": "Dynamic Grid",
19982004
"logDebugInfo": "Log Debug Info",
19992005
"locked": "Locked",

invokeai/frontend/web/src/features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Flex, Spacer } from '@invoke-ai/ui-library';
2+
import { CanvasNonRasterLayersIsHiddenToggle } from 'features/controlLayers/components/common/CanvasNonRasterLayersIsHiddenToggle';
23
import { EntityListGlobalActionBarAddLayerMenu } from 'features/controlLayers/components/CanvasEntityList/EntityListGlobalActionBarAddLayerMenu';
34
import { EntityListSelectedEntityActionBarDuplicateButton } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarDuplicateButton';
45
import { EntityListSelectedEntityActionBarFill } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBarFill';
@@ -22,6 +23,7 @@ export const EntityListSelectedEntityActionBar = memo(() => {
2223
<EntityListSelectedEntityActionBarTransformButton />
2324
<EntityListSelectedEntityActionBarSaveToAssetsButton />
2425
<EntityListSelectedEntityActionBarDuplicateButton />
26+
<CanvasNonRasterLayersIsHiddenToggle />
2527
<EntityListGlobalActionBarAddLayerMenu />
2628
</Flex>
2729
</Flex>

invokeai/frontend/web/src/features/controlLayers/components/CanvasLayersPanelContent.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ import { CanvasAddEntityButtons } from 'features/controlLayers/components/Canvas
44
import { CanvasEntityList } from 'features/controlLayers/components/CanvasEntityList/CanvasEntityList';
55
import { EntityListSelectedEntityActionBar } from 'features/controlLayers/components/CanvasEntityList/EntityListSelectedEntityActionBar';
66
import { CanvasManagerProviderGate } from 'features/controlLayers/contexts/CanvasManagerProviderGate';
7+
import { useCanvasToggleNonRasterLayersHotkey } from 'features/controlLayers/hooks/useCanvasToggleNonRasterLayersHotkey';
78
import { selectHasEntities } from 'features/controlLayers/store/selectors';
89
import { memo } from 'react';
910

1011
import { ParamDenoisingStrength } from './ParamDenoisingStrength';
1112

1213
export const CanvasLayersPanel = memo(() => {
1314
const hasEntities = useAppSelector(selectHasEntities);
15+
useCanvasToggleNonRasterLayersHotkey();
1416

1517
return (
1618
<CanvasManagerProviderGate>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { IconButton } from '@invoke-ai/ui-library';
2+
import { useAppDispatch } from 'app/store/storeHooks';
3+
import { useNonRasterLayersIsHidden } from 'features/controlLayers/hooks/useNonRasterLayersIsHidden';
4+
import { allNonRasterLayersIsHiddenToggled } from 'features/controlLayers/store/canvasSlice';
5+
import type { MouseEventHandler } from 'react';
6+
import { memo, useCallback } from 'react';
7+
import { useTranslation } from 'react-i18next';
8+
import { PiEyeBold, PiEyeClosedBold } from 'react-icons/pi';
9+
10+
export const CanvasNonRasterLayersIsHiddenToggle = memo(() => {
11+
const { t } = useTranslation();
12+
const dispatch = useAppDispatch();
13+
const isHidden = useNonRasterLayersIsHidden();
14+
15+
const onClick = useCallback<MouseEventHandler>(
16+
(e) => {
17+
e.stopPropagation();
18+
dispatch(allNonRasterLayersIsHiddenToggled());
19+
},
20+
[dispatch]
21+
);
22+
23+
return (
24+
<IconButton
25+
size="sm"
26+
aria-label={t(isHidden ? 'controlLayers.showNonRasterLayers' : 'controlLayers.hideNonRasterLayers')}
27+
tooltip={t(isHidden ? 'controlLayers.showNonRasterLayers' : 'controlLayers.hideNonRasterLayers')}
28+
variant="link"
29+
icon={isHidden ? <PiEyeClosedBold /> : <PiEyeBold />}
30+
onClick={onClick}
31+
alignSelf="stretch"
32+
/>
33+
);
34+
});
35+
36+
CanvasNonRasterLayersIsHiddenToggle.displayName = 'CanvasNonRasterLayersIsHiddenToggle';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { useAppDispatch } from 'app/store/storeHooks';
2+
import { allNonRasterLayersIsHiddenToggled } from 'features/controlLayers/store/canvasSlice';
3+
import { useRegisteredHotkeys } from 'features/system/components/HotkeysModal/useHotkeyData';
4+
import { useCallback } from 'react';
5+
6+
export const useCanvasToggleNonRasterLayersHotkey = () => {
7+
const dispatch = useAppDispatch();
8+
9+
const handleToggleNonRasterLayers = useCallback(() => {
10+
dispatch(allNonRasterLayersIsHiddenToggled());
11+
}, [dispatch]);
12+
13+
useRegisteredHotkeys({
14+
id: 'toggleNonRasterLayers',
15+
category: 'canvas',
16+
callback: handleToggleNonRasterLayers,
17+
dependencies: [handleToggleNonRasterLayers],
18+
});
19+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { createSelector } from '@reduxjs/toolkit';
2+
import { useAppSelector } from 'app/store/storeHooks';
3+
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
4+
import { useMemo } from 'react';
5+
6+
export const useNonRasterLayersIsHidden = (): boolean => {
7+
const selectNonRasterLayersIsHidden = useMemo(
8+
() =>
9+
createSelector(selectCanvasSlice, (canvas) => {
10+
// Check if all non-raster layer categories are hidden
11+
return (
12+
canvas.controlLayers.isHidden &&
13+
canvas.inpaintMasks.isHidden &&
14+
canvas.regionalGuidance.isHidden
15+
);
16+
}),
17+
[]
18+
);
19+
const isHidden = useAppSelector(selectNonRasterLayersIsHidden);
20+
return isHidden;
21+
};

invokeai/frontend/web/src/features/controlLayers/store/canvasSlice.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1539,6 +1539,22 @@ export const canvasSlice = createSlice({
15391539
break;
15401540
}
15411541
},
1542+
allNonRasterLayersIsHiddenToggled: (state) => {
1543+
// Toggle visibility for all non-raster layer categories
1544+
// Check if any non-raster layers are currently visible
1545+
const hasVisibleNonRasterLayers =
1546+
!state.controlLayers.isHidden ||
1547+
!state.inpaintMasks.isHidden ||
1548+
!state.regionalGuidance.isHidden;
1549+
1550+
// If any are visible, hide all; if all are hidden, show all
1551+
const shouldHide = hasVisibleNonRasterLayers;
1552+
1553+
state.controlLayers.isHidden = shouldHide;
1554+
state.inpaintMasks.isHidden = shouldHide;
1555+
state.regionalGuidance.isHidden = shouldHide;
1556+
// Note: reference_image doesn't have isHidden property, so it's not included
1557+
},
15421558
allEntitiesDeleted: (state) => {
15431559
// Deleting all entities is equivalent to resetting the state for each entity type
15441560
const initialState = getInitialCanvasState();
@@ -1648,6 +1664,7 @@ export const {
16481664
entitiesReordered,
16491665
allEntitiesDeleted,
16501666
allEntitiesOfTypeIsHiddenToggled,
1667+
allNonRasterLayersIsHiddenToggled,
16511668
// bbox
16521669
bboxChangedFromCanvas,
16531670
bboxScaledWidthChanged,

invokeai/frontend/web/src/features/system/components/HotkeysModal/useHotkeyData.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export const useHotkeyData = (): HotkeysData => {
122122
addHotkey('canvas', 'cancelTransform', ['esc']);
123123
addHotkey('canvas', 'applySegmentAnything', ['enter']);
124124
addHotkey('canvas', 'cancelSegmentAnything', ['esc']);
125+
addHotkey('canvas', 'toggleNonRasterLayers', ['shift+h']);
125126

126127
// Workflows
127128
addHotkey('workflows', 'addNode', ['shift+a', 'space']);

0 commit comments

Comments
 (0)