diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts index ebd6c5ae84..acce1e267c 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts @@ -19,6 +19,9 @@ import type { CollectInvocation, Edge, NonNullableGraph, S } from 'services/api/ import { assert } from 'tsafe'; export const addRegionalPromptsToGraph = async (state: RootState, graph: NonNullableGraph, denoiseNodeId: string) => { + if (!state.regionalPrompts.present.isEnabled) { + return; + } const { dispatch } = getStore(); // TODO: Handle non-SDXL // const isSDXL = state.generation.model?.base === 'sdxl'; diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/RPEnabledSwitch.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/RPEnabledSwitch.tsx new file mode 100644 index 0000000000..86b10afb9a --- /dev/null +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/RPEnabledSwitch.tsx @@ -0,0 +1,27 @@ +import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { isEnabledChanged } from 'features/regionalPrompts/store/regionalPromptsSlice'; +import type { ChangeEvent } from 'react'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +export const RPEnabledSwitch = memo(() => { + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + const isEnabled = useAppSelector((s) => s.regionalPrompts.present.isEnabled); + const onChange = useCallback( + (e: ChangeEvent) => { + dispatch(isEnabledChanged(e.target.checked)); + }, + [dispatch] + ); + + return ( + + Enable RP + + + ); +}); + +RPEnabledSwitch.displayName = 'RPEnabledSwitch'; diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx index 5cc123c7a5..f3803d7ff7 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx @@ -6,6 +6,7 @@ import { AddLayerButton } from 'features/regionalPrompts/components/AddLayerButt import { BrushSize } from 'features/regionalPrompts/components/BrushSize'; import { DeleteAllLayersButton } from 'features/regionalPrompts/components/DeleteAllLayersButton'; import { PromptLayerOpacity } from 'features/regionalPrompts/components/PromptLayerOpacity'; +import { RPEnabledSwitch } from 'features/regionalPrompts/components/RPEnabledSwitch'; import { RPLayerListItem } from 'features/regionalPrompts/components/RPLayerListItem'; import { StageComponent } from 'features/regionalPrompts/components/StageComponent'; import { ToolChooser } from 'features/regionalPrompts/components/ToolChooser'; @@ -39,6 +40,7 @@ export const RegionalPromptsEditor = memo(() => { + {rpLayerIdsReversed.map((id) => ( diff --git a/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts b/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts index c05130f427..6161957f9d 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts +++ b/invokeai/frontend/web/src/features/regionalPrompts/store/regionalPromptsSlice.ts @@ -68,6 +68,7 @@ type RegionalPromptsState = { layers: Layer[]; brushSize: number; promptLayerOpacity: number; + isEnabled: boolean; }; export const initialRegionalPromptsState: RegionalPromptsState = { @@ -77,11 +78,11 @@ export const initialRegionalPromptsState: RegionalPromptsState = { brushSize: 40, layers: [], promptLayerOpacity: 0.5, // This currently doesn't work + isEnabled: false, }; const isLine = (obj: LayerObject): obj is LineObject => obj.kind === 'line'; -export const isRPLayer = (layer?: Layer): layer is RegionalPromptLayer => - layer?.kind === 'regionalPromptLayer'; +export const isRPLayer = (layer?: Layer): layer is RegionalPromptLayer => layer?.kind === 'regionalPromptLayer'; export const regionalPromptsSlice = createSlice({ name: 'regionalPrompts', @@ -247,6 +248,9 @@ export const regionalPromptsSlice = createSlice({ promptLayerOpacityChanged: (state, action: PayloadAction) => { state.promptLayerOpacity = action.payload; }, + isEnabledChanged: (state, action: PayloadAction) => { + state.isEnabled = action.payload; + }, //#endregion }, }); @@ -276,16 +280,14 @@ class LayerColors { } export const { - allLayersDeleted, - brushSizeChanged, + // Meta layer actions layerAdded, layerDeleted, layerMovedBackward, layerMovedForward, layerMovedToBack, layerMovedToFront, - promptLayerOpacityChanged, - toolChanged, + allLayersDeleted, // Regional Prompt layer actions rpLayerAutoNegativeChanged, rpLayerBboxChanged, @@ -298,6 +300,11 @@ export const { rpLayerReset, rpLayerSelected, rpLayerTranslated, + // General actions + isEnabledChanged, + brushSizeChanged, + promptLayerOpacityChanged, + toolChanged, } = regionalPromptsSlice.actions; export const selectRegionalPromptsSlice = (state: RootState) => state.regionalPrompts; @@ -346,6 +353,7 @@ export const clearHistoryRegionalPrompts = createAction(`${regionalPromptsSlice. const undoableGroupByMatcher = isAnyOf( brushSizeChanged, promptLayerOpacityChanged, + isEnabledChanged, rpLayerPositivePromptChanged, rpLayerNegativePromptChanged, rpLayerTranslated