diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 9d93ebed8d..36e915c4fc 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -1513,7 +1513,7 @@ "app": { "storeNotInitialized": "Store is not initialized" }, - "regionalPrompts": { + "controlLayers": { "deleteAll": "Delete All", "addLayer": "Add Layer", "moveToFront": "Move to Front", @@ -1521,8 +1521,7 @@ "moveForward": "Move Forward", "moveBackward": "Move Backward", "brushSize": "Brush Size", - "regionalControl": "Regional Control (ALPHA)", - "enableRegionalPrompts": "Enable $t(regionalPrompts.regionalPrompts)", + "controlLayers": "Control Layers (BETA)", "globalMaskOpacity": "Global Mask Opacity", "autoNegative": "Auto Negative", "toggleVisibility": "Toggle Layer Visibility", @@ -1535,7 +1534,7 @@ "addNegativePrompt": "Add $t(common.negativePrompt)", "addIPAdapter": "Add $t(common.ipAdapter)", "maskedGuidance": "Masked Guidance", - "maskedGuidanceLayer": "$t(regionalPrompts.maskedGuidance) $t(unifiedCanvas.layer)", + "maskedGuidanceLayer": "$t(controlLayers.maskedGuidance) $t(unifiedCanvas.layer)", "controlNetLayer": "$t(common.controlNet) $t(unifiedCanvas.layer)", "ipAdapterLayer": "$t(common.ipAdapter) $t(unifiedCanvas.layer)", "opacity": "Opacity" diff --git a/invokeai/frontend/web/src/app/logging/logger.ts b/invokeai/frontend/web/src/app/logging/logger.ts index 00389d8c4f..ca7a24201a 100644 --- a/invokeai/frontend/web/src/app/logging/logger.ts +++ b/invokeai/frontend/web/src/app/logging/logger.ts @@ -28,7 +28,7 @@ export type LoggerNamespace = | 'session' | 'queue' | 'dnd' - | 'regionalPrompts'; + | 'controlLayers'; export const logger = (namespace: LoggerNamespace) => $logger.get().child({ namespace }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts index 42b1cd36b4..eb86f54c84 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts @@ -6,7 +6,7 @@ import { controlAdapterModelCleared, selectControlAdapterAll, } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { heightChanged, widthChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { heightChanged, widthChanged } from 'features/controlLayers/store/controlLayersSlice'; import { loraRemoved } from 'features/lora/store/loraSlice'; import { calculateNewSize } from 'features/parameters/components/ImageSize/calculateNewSize'; import { modelChanged, vaeSelected } from 'features/parameters/store/generationSlice'; @@ -72,15 +72,15 @@ const handleMainModels: ModelHandler = (models, state, dispatch, log) => { const optimalDimension = getOptimalDimension(defaultModelInList); if ( getIsSizeOptimal( - state.regionalPrompts.present.size.width, - state.regionalPrompts.present.size.height, + state.controlLayers.present.size.width, + state.controlLayers.present.size.height, optimalDimension ) ) { return; } const { width, height } = calculateNewSize( - state.regionalPrompts.present.size.aspectRatio.value, + state.controlLayers.present.size.aspectRatio.value, optimalDimension * optimalDimension ); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/promptChanged.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/promptChanged.ts index 06df2e2b92..4633eb45a5 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/promptChanged.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/promptChanged.ts @@ -1,6 +1,6 @@ import { isAnyOf } from '@reduxjs/toolkit'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; -import { positivePromptChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice'; import { combinatorialToggled, isErrorChanged, @@ -28,7 +28,7 @@ export const addDynamicPromptsListener = (startAppListening: AppStartListening) effect: async (action, { dispatch, getState, cancelActiveListeners, delay }) => { cancelActiveListeners(); const state = getState(); - const { positivePrompt } = state.regionalPrompts.present; + const { positivePrompt } = state.controlLayers.present; const { maxPrompts } = state.dynamicPrompts; if (state.config.disabledFeatures.includes('dynamicPrompting')) { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/regionalControlToControlAdapterBridge.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/regionalControlToControlAdapterBridge.ts index ae7913594a..d90dfb97bf 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/regionalControlToControlAdapterBridge.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/regionalControlToControlAdapterBridge.ts @@ -11,19 +11,19 @@ import { maskedGuidanceLayerAdded, maskLayerIPAdapterAdded, maskLayerIPAdapterDeleted, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import type { Layer } from 'features/controlLayers/store/types'; import { modelConfigsAdapterSelectors, modelsApi } from 'services/api/endpoints/models'; import { isControlNetModelConfig, isIPAdapterModelConfig } from 'services/api/types'; import { assert } from 'tsafe'; import { v4 as uuidv4 } from 'uuid'; -export const guidanceLayerAdded = createAction('regionalPrompts/guidanceLayerAdded'); -export const guidanceLayerDeleted = createAction('regionalPrompts/guidanceLayerDeleted'); -export const allLayersDeleted = createAction('regionalPrompts/allLayersDeleted'); -export const guidanceLayerIPAdapterAdded = createAction('regionalPrompts/guidanceLayerIPAdapterAdded'); +export const guidanceLayerAdded = createAction('controlLayers/guidanceLayerAdded'); +export const guidanceLayerDeleted = createAction('controlLayers/guidanceLayerDeleted'); +export const allLayersDeleted = createAction('controlLayers/allLayersDeleted'); +export const guidanceLayerIPAdapterAdded = createAction('controlLayers/guidanceLayerIPAdapterAdded'); export const guidanceLayerIPAdapterDeleted = createAction<{ layerId: string; ipAdapterId: string }>( - 'regionalPrompts/guidanceLayerIPAdapterDeleted' + 'controlLayers/guidanceLayerIPAdapterDeleted' ); export const addRegionalControlToControlAdapterBridge = (startAppListening: AppStartListening) => { @@ -32,7 +32,7 @@ export const addRegionalControlToControlAdapterBridge = (startAppListening: AppS effect: (action, { dispatch, getState }) => { const type = action.payload; const layerId = uuidv4(); - if (type === 'masked_guidance_layer') { + if (type === 'regional_guidance_layer') { dispatch(maskedGuidanceLayerAdded({ layerId })); return; } @@ -84,14 +84,14 @@ export const addRegionalControlToControlAdapterBridge = (startAppListening: AppS effect: (action, { getState, dispatch }) => { const layerId = action.payload; const state = getState(); - const layer = state.regionalPrompts.present.layers.find((l) => l.id === layerId); + const layer = state.controlLayers.present.layers.find((l) => l.id === layerId); assert(layer, `Layer ${layerId} not found`); if (layer.type === 'ip_adapter_layer') { dispatch(controlAdapterRemoved({ id: layer.ipAdapterId })); } else if (layer.type === 'control_adapter_layer') { dispatch(controlAdapterRemoved({ id: layer.controlNetId })); - } else if (layer.type === 'masked_guidance_layer') { + } else if (layer.type === 'regional_guidance_layer') { for (const ipAdapterId of layer.ipAdapterIds) { dispatch(controlAdapterRemoved({ id: ipAdapterId })); } @@ -104,7 +104,7 @@ export const addRegionalControlToControlAdapterBridge = (startAppListening: AppS actionCreator: allLayersDeleted, effect: (action, { dispatch, getOriginalState }) => { const state = getOriginalState(); - for (const layer of state.regionalPrompts.present.layers) { + for (const layer of state.controlLayers.present.layers) { dispatch(guidanceLayerDeleted(layer.id)); } }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts index 0644e40856..6f3aa9756a 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/setDefaultSettings.ts @@ -1,5 +1,5 @@ import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; -import { heightChanged, widthChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { heightChanged, widthChanged } from 'features/controlLayers/store/controlLayersSlice'; import { setDefaultSettings } from 'features/parameters/store/actions'; import { setCfgRescaleMultiplier, diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index 054617f77c..9661f57f99 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -11,10 +11,10 @@ import { controlAdaptersSlice, } from 'features/controlAdapters/store/controlAdaptersSlice'; import { - regionalPromptsPersistConfig, - regionalPromptsSlice, - regionalPromptsUndoableConfig, -} from 'features/controlLayers/store/regionalPromptsSlice'; + controlLayersPersistConfig, + controlLayersSlice, + controlLayersUndoableConfig, +} from 'features/controlLayers/store/controlLayersSlice'; import { deleteImageModalSlice } from 'features/deleteImageModal/store/slice'; import { dynamicPromptsPersistConfig, dynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import { galleryPersistConfig, gallerySlice } from 'features/gallery/store/gallerySlice'; @@ -65,7 +65,7 @@ const allReducers = { [queueSlice.name]: queueSlice.reducer, [workflowSlice.name]: workflowSlice.reducer, [hrfSlice.name]: hrfSlice.reducer, - [regionalPromptsSlice.name]: undoable(regionalPromptsSlice.reducer, regionalPromptsUndoableConfig), + [controlLayersSlice.name]: undoable(controlLayersSlice.reducer, controlLayersUndoableConfig), [api.reducerPath]: api.reducer, }; @@ -110,7 +110,7 @@ const persistConfigs: { [key in keyof typeof allReducers]?: PersistConfig } = { [loraPersistConfig.name]: loraPersistConfig, [modelManagerV2PersistConfig.name]: modelManagerV2PersistConfig, [hrfPersistConfig.name]: hrfPersistConfig, - [regionalPromptsPersistConfig.name]: regionalPromptsPersistConfig, + [controlLayersPersistConfig.name]: controlLayersPersistConfig, }; const unserialize: UnserializeFunction = (data, key) => { diff --git a/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts b/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts index 461c3b3032..d765e987eb 100644 --- a/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts +++ b/invokeai/frontend/web/src/common/hooks/useIsReadyToEnqueue.ts @@ -5,7 +5,7 @@ import { selectControlAdaptersSlice, } from 'features/controlAdapters/store/controlAdaptersSlice'; import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import { getShouldProcessPrompt } from 'features/dynamicPrompts/util/getShouldProcessPrompt'; import { selectNodesSlice } from 'features/nodes/store/nodesSlice'; @@ -24,12 +24,12 @@ const selector = createMemoizedSelector( selectSystemSlice, selectNodesSlice, selectDynamicPromptsSlice, - selectRegionalPromptsSlice, + selectControlLayersSlice, activeTabNameSelector, ], - (controlAdapters, generation, system, nodes, dynamicPrompts, regionalPrompts, activeTabName) => { + (controlAdapters, generation, system, nodes, dynamicPrompts, controlLayers, activeTabName) => { const { initialImage, model } = generation; - const { positivePrompt } = regionalPrompts.present; + const { positivePrompt } = controlLayers.present; const { isConnected } = system; @@ -101,10 +101,10 @@ const selector = createMemoizedSelector( if (activeTabName === 'txt2img') { // Special handling for control layers on txt2img - const enabledControlLayersAdapterIds = regionalPrompts.present.layers + const enabledControlLayersAdapterIds = controlLayers.present.layers .filter((l) => l.isEnabled) .flatMap((layer) => { - if (layer.type === 'masked_guidance_layer') { + if (layer.type === 'regional_guidance_layer') { return layer.ipAdapterIds; } if (layer.type === 'control_adapter_layer') { @@ -117,8 +117,8 @@ const selector = createMemoizedSelector( enabledControlAdapters = enabledControlAdapters.filter((ca) => enabledControlLayersAdapterIds.includes(ca.id)); } else { - const allControlLayerAdapterIds = regionalPrompts.present.layers.flatMap((layer) => { - if (layer.type === 'masked_guidance_layer') { + const allControlLayerAdapterIds = controlLayers.present.layers.flatMap((layer) => { + if (layer.type === 'regional_guidance_layer') { return layer.ipAdapterIds; } if (layer.type === 'control_adapter_layer') { diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx index 017cbe4bf6..56589fe613 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx @@ -13,7 +13,7 @@ import { controlAdapterImageChanged, selectControlAdaptersSlice, } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { heightChanged, widthChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { heightChanged, widthChanged } from 'features/controlLayers/store/controlLayersSlice'; import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types'; import { calculateNewSize } from 'features/parameters/components/ImageSize/calculateNewSize'; import { selectOptimalDimension } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/AddLayerButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/AddLayerButton.tsx index b112cebe1b..9c324b1f9e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/AddLayerButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/AddLayerButton.tsx @@ -9,7 +9,7 @@ export const AddLayerButton = memo(() => { const { t } = useTranslation(); const dispatch = useAppDispatch(); const addMaskedGuidanceLayer = useCallback(() => { - dispatch(guidanceLayerAdded('masked_guidance_layer')); + dispatch(guidanceLayerAdded('regional_guidance_layer')); }, [dispatch]); const addControlNetLayer = useCallback(() => { dispatch(guidanceLayerAdded('control_adapter_layer')); @@ -21,12 +21,12 @@ export const AddLayerButton = memo(() => { return ( } variant="ghost"> - {t('regionalPrompts.addLayer')} + {t('controlLayers.addLayer')} - {t('regionalPrompts.maskedGuidanceLayer')} - {t('regionalPrompts.controlNetLayer')} - {t('regionalPrompts.ipAdapterLayer')} + {t('controlLayers.maskedGuidanceLayer')} + {t('controlLayers.controlNetLayer')} + {t('controlLayers.ipAdapterLayer')} ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/AddPromptButtons.tsx b/invokeai/frontend/web/src/features/controlLayers/components/AddPromptButtons.tsx index 0ed7a479c4..81b119c7c3 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/AddPromptButtons.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/AddPromptButtons.tsx @@ -6,8 +6,8 @@ import { isMaskedGuidanceLayer, maskLayerNegativePromptChanged, maskLayerPositivePromptChanged, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiPlusBold } from 'react-icons/pi'; @@ -21,8 +21,8 @@ export const AddPromptButtons = ({ layerId }: AddPromptButtonProps) => { const dispatch = useAppDispatch(); const selectValidActions = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); return { canAddPositivePrompt: layer.positivePrompt === null, diff --git a/invokeai/frontend/web/src/features/controlLayers/components/BrushSize.tsx b/invokeai/frontend/web/src/features/controlLayers/components/BrushSize.tsx index f145a47e75..a34250c29f 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/BrushSize.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/BrushSize.tsx @@ -10,7 +10,7 @@ import { PopoverTrigger, } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { brushSizeChanged, initialRegionalPromptsState } from 'features/controlLayers/store/regionalPromptsSlice'; +import { brushSizeChanged, initialControlLayersState } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -20,7 +20,7 @@ const formatPx = (v: number | string) => `${v} px`; export const BrushSize = memo(() => { const dispatch = useAppDispatch(); const { t } = useTranslation(); - const brushSize = useAppSelector((s) => s.regionalPrompts.present.brushSize); + const brushSize = useAppSelector((s) => s.controlLayers.present.brushSize); const onChange = useCallback( (v: number) => { dispatch(brushSizeChanged(Math.round(v))); @@ -29,13 +29,13 @@ export const BrushSize = memo(() => { ); return ( - {t('regionalPrompts.brushSize')} + {t('controlLayers.brushSize')} { { } variant="ghost" @@ -50,7 +50,7 @@ const CALayerOpacity = ({ layerId }: Props) => { - {t('regionalPrompts.opacity')} + {t('controlLayers.opacity')} { const dispatch = useAppDispatch(); const selector = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isControlAdapterLayer(layer), `Layer ${layerId} not found or not a ControlNet layer`); return { controlNetId: layer.controlNetId, - isSelected: layerId === regionalPrompts.present.selectedLayerId, + isSelected: layerId === controlLayers.present.selectedLayerId, }; }), [layerId] diff --git a/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.stories.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.stories.tsx new file mode 100644 index 0000000000..c0fa306c6b --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.stories.tsx @@ -0,0 +1,24 @@ +import { Flex } from '@invoke-ai/ui-library'; +import type { Meta, StoryObj } from '@storybook/react'; +import { ControlLayersEditor } from 'features/controlLayers/components/ControlLayersEditor'; + +const meta: Meta = { + title: 'Feature/ControlLayers', + tags: ['autodocs'], + component: ControlLayersEditor, +}; + +export default meta; +type Story = StoryObj; + +const Component = () => { + return ( + + + + ); +}; + +export const Default: Story = { + render: Component, +}; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsEditor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx similarity index 64% rename from invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsEditor.tsx rename to invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx index cf190a444c..e9275426fe 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsEditor.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersEditor.tsx @@ -1,10 +1,10 @@ /* eslint-disable i18next/no-literal-string */ import { Flex } from '@invoke-ai/ui-library'; -import { RegionalPromptsToolbar } from 'features/controlLayers/components/RegionalPromptsToolbar'; +import { ControlLayersToolbar } from 'features/controlLayers/components/ControlLayersToolbar'; import { StageComponent } from 'features/controlLayers/components/StageComponent'; import { memo } from 'react'; -export const RegionalPromptsEditor = memo(() => { +export const ControlLayersEditor = memo(() => { return ( { alignItems="center" justifyContent="center" > - + ); }); -RegionalPromptsEditor.displayName = 'RegionalPromptsEditor'; +ControlLayersEditor.displayName = 'ControlLayersEditor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsPanelContent.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersPanelContent.tsx similarity index 80% rename from invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsPanelContent.tsx rename to invokeai/frontend/web/src/features/controlLayers/components/ControlLayersPanelContent.tsx index 59853ddda3..4d1545badb 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsPanelContent.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersPanelContent.tsx @@ -8,17 +8,17 @@ import { ControlAdapterLayerListItem } from 'features/controlLayers/components/C import { DeleteAllLayersButton } from 'features/controlLayers/components/DeleteAllLayersButton'; import { IPAdapterLayerListItem } from 'features/controlLayers/components/IPAdapterLayerListItem'; import { MaskedGuidanceLayerListItem } from 'features/controlLayers/components/MaskedGuidanceLayerListItem'; -import { isRenderableLayer, selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isRenderableLayer, selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import type { Layer } from 'features/controlLayers/store/types'; import { partition } from 'lodash-es'; import { memo } from 'react'; -const selectLayerIdTypePairs = createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const [renderableLayers, ipAdapterLayers] = partition(regionalPrompts.present.layers, isRenderableLayer); +const selectLayerIdTypePairs = createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const [renderableLayers, ipAdapterLayers] = partition(controlLayers.present.layers, isRenderableLayer); return [...ipAdapterLayers, ...renderableLayers].map((l) => ({ id: l.id, type: l.type })).reverse(); }); -export const RegionalPromptsPanelContent = memo(() => { +export const ControlLayersPanelContent = memo(() => { const layerIdTypePairs = useAppSelector(selectLayerIdTypePairs); return ( @@ -37,7 +37,7 @@ export const RegionalPromptsPanelContent = memo(() => { ); }); -RegionalPromptsPanelContent.displayName = 'RegionalPromptsPanelContent'; +ControlLayersPanelContent.displayName = 'ControlLayersPanelContent'; type LayerWrapperProps = { id: string; @@ -45,7 +45,7 @@ type LayerWrapperProps = { }; const LayerWrapper = memo(({ id, type }: LayerWrapperProps) => { - if (type === 'masked_guidance_layer') { + if (type === 'regional_guidance_layer') { return ; } if (type === 'control_adapter_layer') { diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsToolbar.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx similarity index 84% rename from invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsToolbar.tsx rename to invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx index 978dddf717..15a74a332a 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptsToolbar.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ControlLayersToolbar.tsx @@ -6,7 +6,7 @@ import { ToolChooser } from 'features/controlLayers/components/ToolChooser'; import { UndoRedoButtonGroup } from 'features/controlLayers/components/UndoRedoButtonGroup'; import { memo } from 'react'; -export const RegionalPromptsToolbar = memo(() => { +export const ControlLayersToolbar = memo(() => { return ( @@ -17,4 +17,4 @@ export const RegionalPromptsToolbar = memo(() => { ); }); -RegionalPromptsToolbar.displayName = 'RegionalPromptsToolbar'; +ControlLayersToolbar.displayName = 'ControlLayersToolbar'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/DeleteAllLayersButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/DeleteAllLayersButton.tsx index 83e464b844..110a018a8e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/DeleteAllLayersButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/DeleteAllLayersButton.tsx @@ -14,7 +14,7 @@ export const DeleteAllLayersButton = memo(() => { return ( ); }); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/GlobalMaskLayerOpacity.tsx b/invokeai/frontend/web/src/features/controlLayers/components/GlobalMaskLayerOpacity.tsx index 3769b40bc7..40985499db 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/GlobalMaskLayerOpacity.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/GlobalMaskLayerOpacity.tsx @@ -2,8 +2,8 @@ import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } f import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { globalMaskLayerOpacityChanged, - initialRegionalPromptsState, -} from 'features/controlLayers/store/regionalPromptsSlice'; + initialControlLayersState, +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -14,7 +14,7 @@ export const GlobalMaskLayerOpacity = memo(() => { const dispatch = useAppDispatch(); const { t } = useTranslation(); const globalMaskLayerOpacity = useAppSelector((s) => - Math.round(s.regionalPrompts.present.globalMaskLayerOpacity * 100) + Math.round(s.controlLayers.present.globalMaskLayerOpacity * 100) ); const onChange = useCallback( (v: number) => { @@ -24,14 +24,14 @@ export const GlobalMaskLayerOpacity = memo(() => { ); return ( - {t('regionalPrompts.globalMaskOpacity')} + {t('controlLayers.globalMaskOpacity')} { max={100} step={1} value={globalMaskLayerOpacity} - defaultValue={initialRegionalPromptsState.globalMaskLayerOpacity * 100} + defaultValue={initialControlLayersState.globalMaskLayerOpacity * 100} onChange={onChange} w={28} format={formatPct} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/IPAdapterLayerListItem.tsx b/invokeai/frontend/web/src/features/controlLayers/components/IPAdapterLayerListItem.tsx index 0a07f29e82..188a7c1f4f 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/IPAdapterLayerListItem.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/IPAdapterLayerListItem.tsx @@ -5,7 +5,7 @@ import ControlAdapterLayerConfig from 'features/controlLayers/components/control import { LayerTitle } from 'features/controlLayers/components/LayerTitle'; import { RPLayerDeleteButton } from 'features/controlLayers/components/RPLayerDeleteButton'; import { RPLayerVisibilityToggle } from 'features/controlLayers/components/RPLayerVisibilityToggle'; -import { isIPAdapterLayer, selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isIPAdapterLayer, selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useMemo } from 'react'; import { assert } from 'tsafe'; @@ -16,8 +16,8 @@ type Props = { export const IPAdapterLayerListItem = memo(({ layerId }: Props) => { const selector = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isIPAdapterLayer(layer), `Layer ${layerId} not found or not an IP Adapter layer`); return layer.ipAdapterId; }), diff --git a/invokeai/frontend/web/src/features/controlLayers/components/LayerTitle.tsx b/invokeai/frontend/web/src/features/controlLayers/components/LayerTitle.tsx index a14ce1fd96..a192b9e865 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/LayerTitle.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/LayerTitle.tsx @@ -10,8 +10,8 @@ type Props = { export const LayerTitle = memo(({ type }: Props) => { const { t } = useTranslation(); const title = useMemo(() => { - if (type === 'masked_guidance_layer') { - return t('regionalPrompts.maskedGuidance'); + if (type === 'regional_guidance_layer') { + return t('controlLayers.maskedGuidance'); } else if (type === 'control_adapter_layer') { return t('common.controlNet'); } else if (type === 'ip_adapter_layer') { diff --git a/invokeai/frontend/web/src/features/controlLayers/components/MaskedGuidanceLayerListItem.tsx b/invokeai/frontend/web/src/features/controlLayers/components/MaskedGuidanceLayerListItem.tsx index 11b285dae0..2a48417f8c 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/MaskedGuidanceLayerListItem.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/MaskedGuidanceLayerListItem.tsx @@ -14,8 +14,8 @@ import { RPLayerVisibilityToggle } from 'features/controlLayers/components/RPLay import { isMaskedGuidanceLayer, layerSelected, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { assert } from 'tsafe'; @@ -31,15 +31,15 @@ export const MaskedGuidanceLayerListItem = memo(({ layerId }: Props) => { const dispatch = useAppDispatch(); const selector = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); return { color: rgbColorToString(layer.previewColor), hasPositivePrompt: layer.positivePrompt !== null, hasNegativePrompt: layer.negativePrompt !== null, hasIPAdapters: layer.ipAdapterIds.length > 0, - isSelected: layerId === regionalPrompts.present.selectedLayerId, + isSelected: layerId === controlLayers.present.selectedLayerId, autoNegative: layer.autoNegative, }; }), @@ -63,11 +63,11 @@ export const MaskedGuidanceLayerListItem = memo(({ layerId }: Props) => { - + {autoNegative === 'invert' && ( - {t('regionalPrompts.autoNegative')} + {t('controlLayers.autoNegative')} )} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerAutoNegativeCheckbox.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerAutoNegativeCheckbox.tsx index ec9ac5b24e..32a60039f6 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerAutoNegativeCheckbox.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerAutoNegativeCheckbox.tsx @@ -4,8 +4,8 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { isMaskedGuidanceLayer, maskLayerAutoNegativeChanged, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import type { ChangeEvent } from 'react'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; @@ -18,8 +18,8 @@ type Props = { const useAutoNegative = (layerId: string) => { const selectAutoNegative = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); return layer.autoNegative; }), @@ -42,7 +42,7 @@ export const MaskedGuidanceLayerAutoNegativeCheckbox = memo(({ layerId }: Props) return ( - {t('regionalPrompts.autoNegative')} + {t('controlLayers.autoNegative')} ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerColorPicker.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerColorPicker.tsx index 550ff1a2bc..e1a20d0210 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerColorPicker.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerColorPicker.tsx @@ -6,8 +6,8 @@ import { rgbColorToString } from 'features/canvas/util/colorToString'; import { isMaskedGuidanceLayer, maskLayerPreviewColorChanged, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback, useMemo } from 'react'; import type { RgbColor } from 'react-colorful'; import { useTranslation } from 'react-i18next'; @@ -21,8 +21,8 @@ export const RPLayerColorPicker = memo(({ layerId }: Props) => { const { t } = useTranslation(); const selectColor = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an vector mask layer`); return layer.previewColor; }), @@ -40,10 +40,10 @@ export const RPLayerColorPicker = memo(({ layerId }: Props) => { - + { const selectIPAdapterIds = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.filter(isMaskedGuidanceLayer).find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.filter(isMaskedGuidanceLayer).find((l) => l.id === layerId); assert(layer, `Layer ${layerId} not found`); return layer.ipAdapterIds; }), diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenu.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenu.tsx index 41e1fb3aa8..95879701c8 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenu.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenu.tsx @@ -3,7 +3,7 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { RPLayerMenuArrangeActions } from 'features/controlLayers/components/RPLayerMenuArrangeActions'; import { RPLayerMenuMaskedGuidanceActions } from 'features/controlLayers/components/RPLayerMenuMaskedGuidanceActions'; import { useLayerType } from 'features/controlLayers/hooks/layerStateHooks'; -import { layerDeleted, layerReset } from 'features/controlLayers/store/regionalPromptsSlice'; +import { layerDeleted, layerReset } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiArrowCounterClockwiseBold, PiDotsThreeVerticalBold, PiTrashSimpleBold } from 'react-icons/pi'; @@ -24,19 +24,19 @@ export const RPLayerMenu = memo(({ layerId }: Props) => { } /> - {layerType === 'masked_guidance_layer' && ( + {layerType === 'regional_guidance_layer' && ( <> )} - {(layerType === 'masked_guidance_layer' || layerType === 'control_adapter_layer') && ( + {(layerType === 'regional_guidance_layer' || layerType === 'control_adapter_layer') && ( <> )} - {layerType === 'masked_guidance_layer' && ( + {layerType === 'regional_guidance_layer' && ( }> {t('accessibility.reset')} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuArrangeActions.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuArrangeActions.tsx index deb74d4cc5..fab3a47adb 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuArrangeActions.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuArrangeActions.tsx @@ -7,8 +7,8 @@ import { layerMovedForward, layerMovedToBack, layerMovedToFront, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiArrowDownBold, PiArrowLineDownBold, PiArrowLineUpBold, PiArrowUpBold } from 'react-icons/pi'; @@ -21,11 +21,11 @@ export const RPLayerMenuArrangeActions = memo(({ layerId }: Props) => { const { t } = useTranslation(); const selectValidActions = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isRenderableLayer(layer), `Layer ${layerId} not found or not an RP layer`); - const layerIndex = regionalPrompts.present.layers.findIndex((l) => l.id === layerId); - const layerCount = regionalPrompts.present.layers.length; + const layerIndex = controlLayers.present.layers.findIndex((l) => l.id === layerId); + const layerCount = controlLayers.present.layers.length; return { canMoveForward: layerIndex < layerCount - 1, canMoveBackward: layerIndex > 0, @@ -51,16 +51,16 @@ export const RPLayerMenuArrangeActions = memo(({ layerId }: Props) => { return ( <> }> - {t('regionalPrompts.moveToFront')} + {t('controlLayers.moveToFront')} }> - {t('regionalPrompts.moveForward')} + {t('controlLayers.moveForward')} }> - {t('regionalPrompts.moveBackward')} + {t('controlLayers.moveBackward')} }> - {t('regionalPrompts.moveToBack')} + {t('controlLayers.moveToBack')} ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuMaskedGuidanceActions.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuMaskedGuidanceActions.tsx index 674c9d3a26..a3da006d0b 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuMaskedGuidanceActions.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerMenuMaskedGuidanceActions.tsx @@ -6,8 +6,8 @@ import { isMaskedGuidanceLayer, maskLayerNegativePromptChanged, maskLayerPositivePromptChanged, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiPlusBold } from 'react-icons/pi'; @@ -20,8 +20,8 @@ export const RPLayerMenuMaskedGuidanceActions = memo(({ layerId }: Props) => { const { t } = useTranslation(); const selectValidActions = useMemo( () => - createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); return { canAddPositivePrompt: layer.positivePrompt === null, @@ -43,13 +43,13 @@ export const RPLayerMenuMaskedGuidanceActions = memo(({ layerId }: Props) => { return ( <> }> - {t('regionalPrompts.addPositivePrompt')} + {t('controlLayers.addPositivePrompt')} }> - {t('regionalPrompts.addNegativePrompt')} + {t('controlLayers.addNegativePrompt')} }> - {t('regionalPrompts.addIPAdapter')} + {t('controlLayers.addIPAdapter')} ); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerNegativePrompt.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerNegativePrompt.tsx index c81c7009fe..d396de4634 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerNegativePrompt.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerNegativePrompt.tsx @@ -2,7 +2,7 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch } from 'app/store/storeHooks'; import { RPLayerPromptDeleteButton } from 'features/controlLayers/components/RPLayerPromptDeleteButton'; import { useLayerNegativePrompt } from 'features/controlLayers/hooks/layerStateHooks'; -import { maskLayerNegativePromptChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { maskLayerNegativePromptChanged } from 'features/controlLayers/store/controlLayersSlice'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPositivePrompt.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPositivePrompt.tsx index b99c529e34..054c75958c 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPositivePrompt.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPositivePrompt.tsx @@ -2,7 +2,7 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch } from 'app/store/storeHooks'; import { RPLayerPromptDeleteButton } from 'features/controlLayers/components/RPLayerPromptDeleteButton'; import { useLayerPositivePrompt } from 'features/controlLayers/hooks/layerStateHooks'; -import { maskLayerPositivePromptChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { maskLayerPositivePromptChanged } from 'features/controlLayers/store/controlLayersSlice'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPromptDeleteButton.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPromptDeleteButton.tsx index ae3c9317fd..b2778d0997 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPromptDeleteButton.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerPromptDeleteButton.tsx @@ -3,7 +3,7 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { maskLayerNegativePromptChanged, maskLayerPositivePromptChanged, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiTrashSimpleBold } from 'react-icons/pi'; @@ -24,10 +24,10 @@ export const RPLayerPromptDeleteButton = memo(({ layerId, polarity }: Props) => } }, [dispatch, layerId, polarity]); return ( - + } onClick={onClick} /> diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerVisibilityToggle.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerVisibilityToggle.tsx index 67d249191c..7a39f5d95e 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/RPLayerVisibilityToggle.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/RPLayerVisibilityToggle.tsx @@ -1,7 +1,7 @@ import { IconButton } from '@invoke-ai/ui-library'; import { useAppDispatch } from 'app/store/storeHooks'; import { useLayerIsVisible } from 'features/controlLayers/hooks/layerStateHooks'; -import { layerVisibilityToggled } from 'features/controlLayers/store/regionalPromptsSlice'; +import { layerVisibilityToggled } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; import { PiCheckBold } from 'react-icons/pi'; @@ -21,8 +21,8 @@ export const RPLayerVisibilityToggle = memo(({ layerId }: Props) => { return ( : undefined} onClick={onClick} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptingEditor.stories.tsx b/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptingEditor.stories.tsx deleted file mode 100644 index 8d822fb954..0000000000 --- a/invokeai/frontend/web/src/features/controlLayers/components/RegionalPromptingEditor.stories.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Flex } from '@invoke-ai/ui-library'; -import type { Meta, StoryObj } from '@storybook/react'; -import { RegionalPromptsEditor } from 'features/controlLayers/components/RegionalPromptsEditor'; - -const meta: Meta = { - title: 'Feature/RegionalPrompts', - tags: ['autodocs'], - component: RegionalPromptsEditor, -}; - -export default meta; -type Story = StoryObj; - -const Component = () => { - return ( - - - - ); -}; - -export const Default: Story = { - render: Component, -}; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/StageComponent.tsx b/invokeai/frontend/web/src/features/controlLayers/components/StageComponent.tsx index 2cff657aad..be7f584627 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/StageComponent.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/StageComponent.tsx @@ -13,8 +13,8 @@ import { isMaskedGuidanceLayer, layerBboxChanged, layerTranslated, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { debouncedRenderers, renderers as normalRenderers } from 'features/controlLayers/util/renderers'; import Konva from 'konva'; import type { IRect } from 'konva/lib/types'; @@ -25,17 +25,17 @@ import { v4 as uuidv4 } from 'uuid'; // This will log warnings when layers > 5 - maybe use `import.meta.env.MODE === 'development'` instead? Konva.showWarnings = false; -const log = logger('regionalPrompts'); +const log = logger('controlLayers'); -const selectSelectedLayerColor = createMemoizedSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers +const selectSelectedLayerColor = createMemoizedSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers .filter(isMaskedGuidanceLayer) - .find((l) => l.id === regionalPrompts.present.selectedLayerId); + .find((l) => l.id === controlLayers.present.selectedLayerId); return layer?.previewColor ?? null; }); -const selectSelectedLayerType = createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const selectedLayer = regionalPrompts.present.layers.find((l) => l.id === regionalPrompts.present.selectedLayerId); +const selectSelectedLayerType = createSelector(selectControlLayersSlice, (controlLayers) => { + const selectedLayer = controlLayers.present.layers.find((l) => l.id === controlLayers.present.selectedLayerId); return selectedLayer?.type ?? null; }); @@ -46,7 +46,7 @@ const useStageRenderer = ( asPreview: boolean ) => { const dispatch = useAppDispatch(); - const state = useAppSelector((s) => s.regionalPrompts.present); + const state = useAppSelector((s) => s.controlLayers.present); const tool = useStore($tool); const { onMouseDown, onMouseUp, onMouseMove, onMouseEnter, onMouseLeave, onMouseWheel } = useMouseEvents(); const cursorPosition = useStore($cursorPosition); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/ToolChooser.tsx b/invokeai/frontend/web/src/features/controlLayers/components/ToolChooser.tsx index bc93556f77..53535b4248 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/ToolChooser.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/ToolChooser.tsx @@ -4,18 +4,18 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { $tool, + selectControlLayersSlice, selectedLayerDeleted, selectedLayerReset, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import { useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { PiArrowsOutCardinalBold, PiEraserBold, PiPaintBrushBold, PiRectangleBold } from 'react-icons/pi'; -const selectIsDisabled = createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const selectedLayer = regionalPrompts.present.layers.find((l) => l.id === regionalPrompts.present.selectedLayerId); - return selectedLayer?.type !== 'masked_guidance_layer'; +const selectIsDisabled = createSelector(selectControlLayersSlice, (controlLayers) => { + const selectedLayer = controlLayers.present.layers.find((l) => l.id === controlLayers.present.selectedLayerId); + return selectedLayer?.type !== 'regional_guidance_layer'; }); export const ToolChooser: React.FC = () => { @@ -70,8 +70,8 @@ export const ToolChooser: React.FC = () => { isDisabled={isDisabled} /> } variant={tool === 'rect' ? 'solid' : 'outline'} onClick={setToolToRect} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/UndoRedoButtonGroup.tsx b/invokeai/frontend/web/src/features/controlLayers/components/UndoRedoButtonGroup.tsx index bfc5e0bd24..8babae7fcc 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/UndoRedoButtonGroup.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/UndoRedoButtonGroup.tsx @@ -1,7 +1,7 @@ /* eslint-disable i18next/no-literal-string */ import { ButtonGroup, IconButton } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { redo, undo } from 'features/controlLayers/store/regionalPromptsSlice'; +import { redo, undo } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; @@ -11,13 +11,13 @@ export const UndoRedoButtonGroup = memo(() => { const { t } = useTranslation(); const dispatch = useAppDispatch(); - const mayUndo = useAppSelector((s) => s.regionalPrompts.past.length > 0); + const mayUndo = useAppSelector((s) => s.controlLayers.past.length > 0); const handleUndo = useCallback(() => { dispatch(undo()); }, [dispatch]); useHotkeys(['meta+z', 'ctrl+z'], handleUndo, { enabled: mayUndo, preventDefault: true }, [mayUndo, handleUndo]); - const mayRedo = useAppSelector((s) => s.regionalPrompts.future.length > 0); + const mayRedo = useAppSelector((s) => s.controlLayers.future.length > 0); const handleRedo = useCallback(() => { dispatch(redo()); }, [dispatch]); diff --git a/invokeai/frontend/web/src/features/controlLayers/components/controlAdapterOverrides/ControlAdapterImagePreview.tsx b/invokeai/frontend/web/src/features/controlLayers/components/controlAdapterOverrides/ControlAdapterImagePreview.tsx index 41339b0efa..b3094e5599 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/controlAdapterOverrides/ControlAdapterImagePreview.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/controlAdapterOverrides/ControlAdapterImagePreview.tsx @@ -13,7 +13,7 @@ import { controlAdapterImageChanged, selectControlAdaptersSlice, } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { heightChanged, widthChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { heightChanged, widthChanged } from 'features/controlLayers/store/controlLayersSlice'; import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types'; import { calculateNewSize } from 'features/parameters/components/ImageSize/calculateNewSize'; import { selectOptimalDimension } from 'features/parameters/store/generationSlice'; diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/layerStateHooks.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/layerStateHooks.ts index 5925322fc9..346f553e32 100644 --- a/invokeai/frontend/web/src/features/controlLayers/hooks/layerStateHooks.ts +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/layerStateHooks.ts @@ -3,16 +3,16 @@ import { useAppSelector } from 'app/store/storeHooks'; import { isControlAdapterLayer, isMaskedGuidanceLayer, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; + selectControlLayersSlice, +} from 'features/controlLayers/store/controlLayersSlice'; import { useMemo } from 'react'; import { assert } from 'tsafe'; export const useLayerPositivePrompt = (layerId: string) => { const selectLayer = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); assert(layer.positivePrompt !== null, `Layer ${layerId} does not have a positive prompt`); return layer.positivePrompt; @@ -26,8 +26,8 @@ export const useLayerPositivePrompt = (layerId: string) => { export const useLayerNegativePrompt = (layerId: string) => { const selectLayer = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(isMaskedGuidanceLayer(layer), `Layer ${layerId} not found or not an RP layer`); assert(layer.negativePrompt !== null, `Layer ${layerId} does not have a negative prompt`); return layer.negativePrompt; @@ -41,8 +41,8 @@ export const useLayerNegativePrompt = (layerId: string) => { export const useLayerIsVisible = (layerId: string) => { const selectLayer = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(layer, `Layer ${layerId} not found`); return layer.isEnabled; }), @@ -55,8 +55,8 @@ export const useLayerIsVisible = (layerId: string) => { export const useLayerType = (layerId: string) => { const selectLayer = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.find((l) => l.id === layerId); assert(layer, `Layer ${layerId} not found`); return layer.type; }), @@ -69,8 +69,8 @@ export const useLayerType = (layerId: string) => { export const useLayerOpacity = (layerId: string) => { const selectLayer = useMemo( () => - createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - const layer = regionalPrompts.present.layers.filter(isControlAdapterLayer).find((l) => l.id === layerId); + createSelector(selectControlLayersSlice, (controlLayers) => { + const layer = controlLayers.present.layers.filter(isControlAdapterLayer).find((l) => l.id === layerId); assert(layer, `Layer ${layerId} not found`); return Math.round(layer.opacity * 100); }), diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/mouseEventHooks.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/mouseEventHooks.ts index ca44480a2b..bab7ef263f 100644 --- a/invokeai/frontend/web/src/features/controlLayers/hooks/mouseEventHooks.ts +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/mouseEventHooks.ts @@ -12,7 +12,7 @@ import { maskLayerLineAdded, maskLayerPointsAdded, maskLayerRectAdded, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import type Konva from 'konva'; import type { KonvaEventObject } from 'konva/lib/Node'; import type { Vector2d } from 'konva/lib/types'; @@ -48,11 +48,11 @@ const BRUSH_SPACING = 20; export const useMouseEvents = () => { const dispatch = useAppDispatch(); - const selectedLayerId = useAppSelector((s) => s.regionalPrompts.present.selectedLayerId); + const selectedLayerId = useAppSelector((s) => s.controlLayers.present.selectedLayerId); const tool = useStore($tool); const lastCursorPosRef = useRef<[number, number] | null>(null); const shouldInvertBrushSizeScrollDirection = useAppSelector((s) => s.canvas.shouldInvertBrushSizeScrollDirection); - const brushSize = useAppSelector((s) => s.regionalPrompts.present.brushSize); + const brushSize = useAppSelector((s) => s.controlLayers.present.brushSize); const onMouseDown = useCallback( (e: KonvaEventObject) => { diff --git a/invokeai/frontend/web/src/features/controlLayers/hooks/useRegionalControlTitle.ts b/invokeai/frontend/web/src/features/controlLayers/hooks/useRegionalControlTitle.ts index c5e74868d7..f755b3e6f2 100644 --- a/invokeai/frontend/web/src/features/controlLayers/hooks/useRegionalControlTitle.ts +++ b/invokeai/frontend/web/src/features/controlLayers/hooks/useRegionalControlTitle.ts @@ -1,14 +1,14 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; -import { isMaskedGuidanceLayer, selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isMaskedGuidanceLayer, selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -const selectValidLayerCount = createSelector(selectRegionalPromptsSlice, (regionalPrompts) => { - if (!regionalPrompts.present.isEnabled) { +const selectValidLayerCount = createSelector(selectControlLayersSlice, (controlLayers) => { + if (!controlLayers.present.isEnabled) { return 0; } - const validLayers = regionalPrompts.present.layers + const validLayers = controlLayers.present.layers .filter(isMaskedGuidanceLayer) .filter((l) => l.isEnabled) .filter((l) => { @@ -25,7 +25,7 @@ export const useRegionalControlTitle = () => { const validLayerCount = useAppSelector(selectValidLayerCount); const title = useMemo(() => { const suffix = validLayerCount > 0 ? ` (${validLayerCount})` : ''; - return `${t('regionalPrompts.regionalControl')}${suffix}`; + return `${t('controlLayers.regionalControl')}${suffix}`; }, [t, validLayerCount]); return title; }; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/regionalPromptsSlice.ts b/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts similarity index 90% rename from invokeai/frontend/web/src/features/controlLayers/store/regionalPromptsSlice.ts rename to invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts index 0d94b8624c..f5e0fe616a 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/regionalPromptsSlice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts @@ -25,17 +25,17 @@ import { v4 as uuidv4 } from 'uuid'; import type { ControlAdapterLayer, + ControlLayersState, DrawingTool, IPAdapterLayer, Layer, - MaskedGuidanceLayer, - RegionalPromptsState, + RegionalGuidanceLayer, Tool, VectorMaskLine, VectorMaskRect, } from './types'; -export const initialRegionalPromptsState: RegionalPromptsState = { +export const initialControlLayersState: ControlLayersState = { _version: 1, selectedLayerId: null, brushSize: 100, @@ -56,15 +56,15 @@ export const initialRegionalPromptsState: RegionalPromptsState = { }; const isLine = (obj: VectorMaskLine | VectorMaskRect): obj is VectorMaskLine => obj.type === 'vector_mask_line'; -export const isMaskedGuidanceLayer = (layer?: Layer): layer is MaskedGuidanceLayer => - layer?.type === 'masked_guidance_layer'; +export const isMaskedGuidanceLayer = (layer?: Layer): layer is RegionalGuidanceLayer => + layer?.type === 'regional_guidance_layer'; export const isControlAdapterLayer = (layer?: Layer): layer is ControlAdapterLayer => layer?.type === 'control_adapter_layer'; export const isIPAdapterLayer = (layer?: Layer): layer is IPAdapterLayer => layer?.type === 'ip_adapter_layer'; -export const isRenderableLayer = (layer?: Layer): layer is MaskedGuidanceLayer | ControlAdapterLayer => - layer?.type === 'masked_guidance_layer' || layer?.type === 'control_adapter_layer'; +export const isRenderableLayer = (layer?: Layer): layer is RegionalGuidanceLayer | ControlAdapterLayer => + layer?.type === 'regional_guidance_layer' || layer?.type === 'control_adapter_layer'; const resetLayer = (layer: Layer) => { - if (layer.type === 'masked_guidance_layer') { + if (layer.type === 'regional_guidance_layer') { layer.maskObjects = []; layer.bbox = null; layer.isEnabled = true; @@ -77,22 +77,22 @@ const resetLayer = (layer: Layer) => { // TODO } }; -const getVectorMaskPreviewColor = (state: RegionalPromptsState): RgbColor => { +const getVectorMaskPreviewColor = (state: ControlLayersState): RgbColor => { const vmLayers = state.layers.filter(isMaskedGuidanceLayer); const lastColor = vmLayers[vmLayers.length - 1]?.previewColor; return LayerColors.next(lastColor); }; -export const regionalPromptsSlice = createSlice({ - name: 'regionalPrompts', - initialState: initialRegionalPromptsState, +export const controlLayersSlice = createSlice({ + name: 'controlLayers', + initialState: initialControlLayersState, reducers: { //#region All Layers maskedGuidanceLayerAdded: (state, action: PayloadAction<{ layerId: string }>) => { const { layerId } = action.payload; - const layer: MaskedGuidanceLayer = { + const layer: RegionalGuidanceLayer = { id: getMaskedGuidanceLayerId(layerId), - type: 'masked_guidance_layer', + type: 'regional_guidance_layer', isEnabled: true, bbox: null, bboxNeedsUpdate: false, @@ -181,7 +181,7 @@ export const regionalPromptsSlice = createSlice({ if (isRenderableLayer(layer)) { layer.bbox = bbox; layer.bboxNeedsUpdate = false; - if (bbox === null && layer.type === 'masked_guidance_layer') { + if (bbox === null && layer.type === 'regional_guidance_layer') { // The layer was fully erased, empty its objects to prevent accumulation of invisible objects layer.maskObjects = []; layer.needsPixelBbox = false; @@ -247,35 +247,35 @@ export const regionalPromptsSlice = createSlice({ maskLayerPositivePromptChanged: (state, action: PayloadAction<{ layerId: string; prompt: string | null }>) => { const { layerId, prompt } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.positivePrompt = prompt; } }, maskLayerNegativePromptChanged: (state, action: PayloadAction<{ layerId: string; prompt: string | null }>) => { const { layerId, prompt } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.negativePrompt = prompt; } }, maskLayerIPAdapterAdded: (state, action: PayloadAction<{ layerId: string; ipAdapterId: string }>) => { const { layerId, ipAdapterId } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.ipAdapterIds.push(ipAdapterId); } }, maskLayerIPAdapterDeleted: (state, action: PayloadAction<{ layerId: string; ipAdapterId: string }>) => { const { layerId, ipAdapterId } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.ipAdapterIds = layer.ipAdapterIds.filter((id) => id !== ipAdapterId); } }, maskLayerPreviewColorChanged: (state, action: PayloadAction<{ layerId: string; color: RgbColor }>) => { const { layerId, color } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.previewColor = color; } }, @@ -290,7 +290,7 @@ export const regionalPromptsSlice = createSlice({ ) => { const { layerId, points, tool } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { const lineId = getMaskedGuidanceLayerLineId(layer.id, action.meta.uuid); layer.maskObjects.push({ type: 'vector_mask_line', @@ -315,7 +315,7 @@ export const regionalPromptsSlice = createSlice({ maskLayerPointsAdded: (state, action: PayloadAction<{ layerId: string; point: [number, number] }>) => { const { layerId, point } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { const lastLine = layer.maskObjects.findLast(isLine); if (!lastLine) { return; @@ -334,7 +334,7 @@ export const regionalPromptsSlice = createSlice({ return; } const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { const id = getMaskedGuidnaceLayerRectId(layer.id, action.meta.uuid); layer.maskObjects.push({ type: 'vector_mask_rect', @@ -355,7 +355,7 @@ export const regionalPromptsSlice = createSlice({ ) => { const { layerId, autoNegative } = action.payload; const layer = state.layers.find((l) => l.id === layerId); - if (layer?.type === 'masked_guidance_layer') { + if (layer?.type === 'regional_guidance_layer') { layer.autoNegative = autoNegative; } }, @@ -546,26 +546,26 @@ export const { globalMaskLayerOpacityChanged, undo, redo, -} = regionalPromptsSlice.actions; +} = controlLayersSlice.actions; -export const selectAllControlAdapterIds = (regionalPrompts: RegionalPromptsState) => - regionalPrompts.layers.flatMap((l) => { +export const selectAllControlAdapterIds = (controlLayers: ControlLayersState) => + controlLayers.layers.flatMap((l) => { if (l.type === 'control_adapter_layer') { return [l.controlNetId]; } if (l.type === 'ip_adapter_layer') { return [l.ipAdapterId]; } - if (l.type === 'masked_guidance_layer') { + if (l.type === 'regional_guidance_layer') { return l.ipAdapterIds; } return []; }); -export const selectRegionalPromptsSlice = (state: RootState) => state.regionalPrompts; +export const selectControlLayersSlice = (state: RootState) => state.controlLayers; /* eslint-disable-next-line @typescript-eslint/no-explicit-any */ -const migrateRegionalPromptsState = (state: any): any => { +const migrateControlLayersState = (state: any): any => { return state; }; @@ -588,14 +588,14 @@ export const BACKGROUND_RECT_ID = 'background_layer.rect'; // Names (aka classes) for Konva layers and objects export const CONTROLNET_LAYER_NAME = 'control_adapter_layer'; export const CONTROLNET_LAYER_IMAGE_NAME = 'control_adapter_layer.image'; -export const MASKED_GUIDANCE_LAYER_NAME = 'masked_guidance_layer'; -export const MASKED_GUIDANCE_LAYER_LINE_NAME = 'masked_guidance_layer.line'; -export const MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME = 'masked_guidance_layer.object_group'; -export const MASKED_GUIDANCE_LAYER_RECT_NAME = 'masked_guidance_layer.rect'; +export const regional_guidance_layer_NAME = 'regional_guidance_layer'; +export const regional_guidance_layer_LINE_NAME = 'regional_guidance_layer.line'; +export const regional_guidance_layer_OBJECT_GROUP_NAME = 'regional_guidance_layer.object_group'; +export const regional_guidance_layer_RECT_NAME = 'regional_guidance_layer.rect'; export const LAYER_BBOX_NAME = 'layer.bbox'; // Getters for non-singleton layer and object IDs -const getMaskedGuidanceLayerId = (layerId: string) => `${MASKED_GUIDANCE_LAYER_NAME}_${layerId}`; +const getMaskedGuidanceLayerId = (layerId: string) => `${regional_guidance_layer_NAME}_${layerId}`; const getMaskedGuidanceLayerLineId = (layerId: string, lineId: string) => `${layerId}.line_${lineId}`; const getMaskedGuidnaceLayerRectId = (layerId: string, lineId: string) => `${layerId}.rect_${lineId}`; export const getMaskedGuidanceLayerObjectGroupId = (layerId: string, groupId: string) => @@ -605,10 +605,10 @@ const getControlNetLayerId = (layerId: string) => `control_adapter_layer_${layer export const getControlNetLayerImageId = (layerId: string, imageName: string) => `${layerId}.image_${imageName}`; const getIPAdapterLayerId = (layerId: string) => `ip_adapter_layer_${layerId}`; -export const regionalPromptsPersistConfig: PersistConfig = { - name: regionalPromptsSlice.name, - initialState: initialRegionalPromptsState, - migrate: migrateRegionalPromptsState, +export const controlLayersPersistConfig: PersistConfig = { + name: controlLayersSlice.name, + initialState: initialControlLayersState, + migrate: migrateControlLayersState, persistDenylist: [], }; @@ -626,10 +626,10 @@ const undoableGroupByMatcher = isAnyOf( const LINE_1 = 'LINE_1'; const LINE_2 = 'LINE_2'; -export const regionalPromptsUndoableConfig: UndoableOptions = { +export const controlLayersUndoableConfig: UndoableOptions = { limit: 64, - undoType: regionalPromptsSlice.actions.undo.type, - redoType: regionalPromptsSlice.actions.redo.type, + undoType: controlLayersSlice.actions.undo.type, + redoType: controlLayersSlice.actions.redo.type, groupBy: (action, state, history) => { // Lines are started with `maskLayerLineAdded` and may have any number of subsequent `maskLayerPointsAdded` events. // We can use a double-buffer-esque trick to group each "logical" line as a single undoable action, without grouping @@ -649,7 +649,7 @@ export const regionalPromptsUndoableConfig: UndoableOptions { // Ignore all actions from other slices - if (!action.type.startsWith(regionalPromptsSlice.name)) { + if (!action.type.startsWith(controlLayersSlice.name)) { return false; } // This action is triggered on state changes, including when we undo. If we do not ignore this action, when we diff --git a/invokeai/frontend/web/src/features/controlLayers/store/types.ts b/invokeai/frontend/web/src/features/controlLayers/store/types.ts index ac66c013d6..5f3d11c765 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/types.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/types.ts @@ -57,8 +57,8 @@ export type IPAdapterLayer = LayerBase & { ipAdapterId: string; }; -export type MaskedGuidanceLayer = RenderableLayerBase & { - type: 'masked_guidance_layer'; +export type RegionalGuidanceLayer = RenderableLayerBase & { + type: 'regional_guidance_layer'; maskObjects: (VectorMaskLine | VectorMaskRect)[]; positivePrompt: ParameterPositivePrompt | null; negativePrompt: ParameterNegativePrompt | null; // Up to one text prompt per mask @@ -68,9 +68,9 @@ export type MaskedGuidanceLayer = RenderableLayerBase & { needsPixelBbox: boolean; // Needs the slower pixel-based bbox calculation - set to true when an there is an eraser object }; -export type Layer = MaskedGuidanceLayer | ControlAdapterLayer | IPAdapterLayer; +export type Layer = RegionalGuidanceLayer | ControlAdapterLayer | IPAdapterLayer; -export type RegionalPromptsState = { +export type ControlLayersState = { _version: 1; selectedLayerId: string | null; layers: Layer[]; diff --git a/invokeai/frontend/web/src/features/controlLayers/util/bbox.ts b/invokeai/frontend/web/src/features/controlLayers/util/bbox.ts index a75650fd0a..3c2915e0ab 100644 --- a/invokeai/frontend/web/src/features/controlLayers/util/bbox.ts +++ b/invokeai/frontend/web/src/features/controlLayers/util/bbox.ts @@ -1,6 +1,6 @@ import openBase64ImageInTab from 'common/util/openBase64ImageInTab'; import { imageDataToDataURL } from 'features/canvas/util/blobToDataURL'; -import { MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME } from 'features/controlLayers/store/regionalPromptsSlice'; +import { regional_guidance_layer_OBJECT_GROUP_NAME } from 'features/controlLayers/store/controlLayersSlice'; import Konva from 'konva'; import type { Layer as KonvaLayerType } from 'konva/lib/Layer'; import type { IRect } from 'konva/lib/types'; @@ -81,7 +81,7 @@ export const getLayerBboxPixels = (layer: KonvaLayerType, preview: boolean = fal offscreenStage.add(layerClone); for (const child of layerClone.getChildren()) { - if (child.name() === MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME) { + if (child.name() === regional_guidance_layer_OBJECT_GROUP_NAME) { // We need to cache the group to ensure it composites out eraser strokes correctly child.opacity(1); child.cache(); diff --git a/invokeai/frontend/web/src/features/controlLayers/util/getLayerBlobs.ts b/invokeai/frontend/web/src/features/controlLayers/util/getLayerBlobs.ts index 783fdee513..c7616e4300 100644 --- a/invokeai/frontend/web/src/features/controlLayers/util/getLayerBlobs.ts +++ b/invokeai/frontend/web/src/features/controlLayers/util/getLayerBlobs.ts @@ -1,7 +1,7 @@ import { getStore } from 'app/store/nanostores/store'; import openBase64ImageInTab from 'common/util/openBase64ImageInTab'; import { blobToDataURL } from 'features/canvas/util/blobToDataURL'; -import { isMaskedGuidanceLayer, MASKED_GUIDANCE_LAYER_NAME } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isMaskedGuidanceLayer, regional_guidance_layer_NAME } from 'features/controlLayers/store/controlLayersSlice'; import { renderers } from 'features/controlLayers/util/renderers'; import Konva from 'konva'; import { assert } from 'tsafe'; @@ -17,14 +17,14 @@ export const getRegionalPromptLayerBlobs = async ( preview: boolean = false ): Promise> => { const state = getStore().getState(); - const { layers } = state.regionalPrompts.present; - const { width, height } = state.regionalPrompts.present.size; + const { layers } = state.controlLayers.present; + const { width, height } = state.controlLayers.present.size; const reduxLayers = layers.filter(isMaskedGuidanceLayer); const container = document.createElement('div'); const stage = new Konva.Stage({ container, width, height }); renderers.renderLayers(stage, reduxLayers, 1, 'brush'); - const konvaLayers = stage.find(`.${MASKED_GUIDANCE_LAYER_NAME}`); + const konvaLayers = stage.find(`.${regional_guidance_layer_NAME}`); const blobs: Record = {}; // First remove all layers diff --git a/invokeai/frontend/web/src/features/controlLayers/util/renderers.ts b/invokeai/frontend/web/src/features/controlLayers/util/renderers.ts index c64baa211c..d61e6d1b96 100644 --- a/invokeai/frontend/web/src/features/controlLayers/util/renderers.ts +++ b/invokeai/frontend/web/src/features/controlLayers/util/renderers.ts @@ -14,21 +14,21 @@ import { isMaskedGuidanceLayer, isRenderableLayer, LAYER_BBOX_NAME, - MASKED_GUIDANCE_LAYER_LINE_NAME, - MASKED_GUIDANCE_LAYER_NAME, - MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME, - MASKED_GUIDANCE_LAYER_RECT_NAME, + regional_guidance_layer_LINE_NAME, + regional_guidance_layer_NAME, + regional_guidance_layer_OBJECT_GROUP_NAME, + regional_guidance_layer_RECT_NAME, TOOL_PREVIEW_BRUSH_BORDER_INNER_ID, TOOL_PREVIEW_BRUSH_BORDER_OUTER_ID, TOOL_PREVIEW_BRUSH_FILL_ID, TOOL_PREVIEW_BRUSH_GROUP_ID, TOOL_PREVIEW_LAYER_ID, TOOL_PREVIEW_RECT_ID, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import type { ControlAdapterLayer, Layer, - MaskedGuidanceLayer, + RegionalGuidanceLayer, Tool, VectorMaskLine, VectorMaskRect, @@ -52,10 +52,10 @@ const STAGE_BG_DATAURL = const mapId = (object: { id: string }) => object.id; const selectRenderableLayers = (n: Konva.Node) => - n.name() === MASKED_GUIDANCE_LAYER_NAME || n.name() === CONTROLNET_LAYER_NAME; + n.name() === regional_guidance_layer_NAME || n.name() === CONTROLNET_LAYER_NAME; const selectVectorMaskObjects = (node: Konva.Node) => { - return node.name() === MASKED_GUIDANCE_LAYER_LINE_NAME || node.name() === MASKED_GUIDANCE_LAYER_RECT_NAME; + return node.name() === regional_guidance_layer_LINE_NAME || node.name() === regional_guidance_layer_RECT_NAME; }; /** @@ -140,12 +140,12 @@ const renderToolPreview = ( isMouseOver: boolean, brushSize: number ) => { - const layerCount = stage.find(`.${MASKED_GUIDANCE_LAYER_NAME}`).length; + const layerCount = stage.find(`.${regional_guidance_layer_NAME}`).length; // Update the stage's pointer style if (layerCount === 0) { // We have no layers, so we should not render any tool stage.container().style.cursor = 'default'; - } else if (selectedLayerType !== 'masked_guidance_layer') { + } else if (selectedLayerType !== 'regional_guidance_layer') { // Non-mask-guidance layers don't have tools stage.container().style.cursor = 'not-allowed'; } else if (tool === 'move') { @@ -226,13 +226,13 @@ const renderToolPreview = ( */ const createMaskedGuidanceLayer = ( stage: Konva.Stage, - reduxLayer: MaskedGuidanceLayer, + reduxLayer: RegionalGuidanceLayer, onLayerPosChanged?: (layerId: string, x: number, y: number) => void ) => { // This layer hasn't been added to the konva state yet const konvaLayer = new Konva.Layer({ id: reduxLayer.id, - name: MASKED_GUIDANCE_LAYER_NAME, + name: regional_guidance_layer_NAME, draggable: true, dragDistance: 0, }); @@ -265,7 +265,7 @@ const createMaskedGuidanceLayer = ( // The object group holds all of the layer's objects (e.g. lines and rects) const konvaObjectGroup = new Konva.Group({ id: getMaskedGuidanceLayerObjectGroupId(reduxLayer.id, uuidv4()), - name: MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME, + name: regional_guidance_layer_OBJECT_GROUP_NAME, listening: false, }); konvaLayer.add(konvaObjectGroup); @@ -284,7 +284,7 @@ const createVectorMaskLine = (reduxObject: VectorMaskLine, konvaGroup: Konva.Gro const vectorMaskLine = new Konva.Line({ id: reduxObject.id, key: reduxObject.id, - name: MASKED_GUIDANCE_LAYER_LINE_NAME, + name: regional_guidance_layer_LINE_NAME, strokeWidth: reduxObject.strokeWidth, tension: 0, lineCap: 'round', @@ -306,7 +306,7 @@ const createVectorMaskRect = (reduxObject: VectorMaskRect, konvaGroup: Konva.Gro const vectorMaskRect = new Konva.Rect({ id: reduxObject.id, key: reduxObject.id, - name: MASKED_GUIDANCE_LAYER_RECT_NAME, + name: regional_guidance_layer_RECT_NAME, x: reduxObject.x, y: reduxObject.y, width: reduxObject.width, @@ -327,7 +327,7 @@ const createVectorMaskRect = (reduxObject: VectorMaskRect, konvaGroup: Konva.Gro */ const renderMaskedGuidanceLayer = ( stage: Konva.Stage, - reduxLayer: MaskedGuidanceLayer, + reduxLayer: RegionalGuidanceLayer, globalMaskLayerOpacity: number, tool: Tool, onLayerPosChanged?: (layerId: string, x: number, y: number) => void @@ -345,7 +345,7 @@ const renderMaskedGuidanceLayer = ( // Convert the color to a string, stripping the alpha - the object group will handle opacity. const rgbColor = rgbColorToString(reduxLayer.previewColor); - const konvaObjectGroup = konvaLayer.findOne(`.${MASKED_GUIDANCE_LAYER_OBJECT_GROUP_NAME}`); + const konvaObjectGroup = konvaLayer.findOne(`.${regional_guidance_layer_OBJECT_GROUP_NAME}`); assert(konvaObjectGroup, `Object group not found for layer ${reduxLayer.id}`); // We use caching to handle "global" layer opacity, but caching is expensive and we should only do it when required. @@ -592,7 +592,7 @@ const renderBbox = ( } for (const reduxLayer of reduxLayers) { - if (reduxLayer.type === 'masked_guidance_layer') { + if (reduxLayer.type === 'regional_guidance_layer') { const konvaLayer = stage.findOne(`#${reduxLayer.id}`); assert(konvaLayer, `Layer ${reduxLayer.id} not found in stage`); diff --git a/invokeai/frontend/web/src/features/metadata/util/recallers.ts b/invokeai/frontend/web/src/features/metadata/util/recallers.ts index fbf72ef98f..f07b2ab8b6 100644 --- a/invokeai/frontend/web/src/features/metadata/util/recallers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/recallers.ts @@ -12,7 +12,7 @@ import { positivePrompt2Changed, positivePromptChanged, widthChanged, -} from 'features/controlLayers/store/regionalPromptsSlice'; +} from 'features/controlLayers/store/controlLayersSlice'; import { setHrfEnabled, setHrfMethod, setHrfStrength } from 'features/hrf/store/hrfSlice'; import type { LoRA } from 'features/lora/store/loraSlice'; import { loraRecalled, lorasReset } from 'features/lora/store/loraSlice'; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addControlLayersToGraph.ts similarity index 98% rename from invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts rename to invokeai/frontend/web/src/features/nodes/util/graph/addControlLayersToGraph.ts index 5c581ad24e..b16fe806b6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addControlLayersToGraph.ts @@ -1,7 +1,7 @@ import { getStore } from 'app/store/nanostores/store'; import type { RootState } from 'app/store/store'; import { selectAllIPAdapters } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isMaskedGuidanceLayer } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isMaskedGuidanceLayer } from 'features/controlLayers/store/controlLayersSlice'; import { getRegionalPromptLayerBlobs } from 'features/controlLayers/util/getLayerBlobs'; import { IP_ADAPTER_COLLECT, @@ -20,13 +20,13 @@ import { imagesApi } from 'services/api/endpoints/images'; import type { CollectInvocation, Edge, IPAdapterInvocation, NonNullableGraph, S } from 'services/api/types'; import { assert } from 'tsafe'; -export const addRegionalPromptsToGraph = async (state: RootState, graph: NonNullableGraph, denoiseNodeId: string) => { - if (!state.regionalPrompts.present.isEnabled) { +export const addControlLayersToGraph = async (state: RootState, graph: NonNullableGraph, denoiseNodeId: string) => { + if (!state.controlLayers.present.isEnabled) { return; } const { dispatch } = getStore(); const isSDXL = state.generation.model?.base === 'sdxl'; - const layers = state.regionalPrompts.present.layers + const layers = state.controlLayers.present.layers // Only support vector mask layers now // TODO: Image masks .filter(isMaskedGuidanceLayer) diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts index 90898a0852..fb912d0be2 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addControlNetToLinearGraph.ts @@ -1,7 +1,7 @@ import type { RootState } from 'app/store/store'; import { selectValidControlNets } from 'features/controlAdapters/store/controlAdaptersSlice'; import type { ControlAdapterProcessorType, ControlNetConfig } from 'features/controlAdapters/store/types'; -import { isControlAdapterLayer } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isControlAdapterLayer } from 'features/controlLayers/store/controlLayersSlice'; import type { ImageField } from 'features/nodes/types/common'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { differenceWith, intersectionWith } from 'lodash-es'; @@ -36,7 +36,7 @@ const getControlNets = (state: RootState) => { if (activeTabName === 'txt2img') { // Add only the cnets that are used in control layers // Collect all ControlNet ids for enabled ControlNet layers - const layerControlNetIds = state.regionalPrompts.present.layers + const layerControlNetIds = state.controlLayers.present.layers .filter(isControlAdapterLayer) .filter((l) => l.isEnabled) .map((l) => l.controlNetId); @@ -44,7 +44,7 @@ const getControlNets = (state: RootState) => { } else { // Else, we want to exclude the cnets that are used in control layers // Collect all ControlNet ids for all ControlNet layers - const layerControlNetIds = state.regionalPrompts.present.layers + const layerControlNetIds = state.controlLayers.present.layers .filter(isControlAdapterLayer) .map((l) => l.controlNetId); return differenceWith(validControlNets, layerControlNetIds, (a, b) => a.id === b); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addHrfToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addHrfToGraph.ts index d7c512728e..5abf07740a 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addHrfToGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addHrfToGraph.ts @@ -110,7 +110,7 @@ export const addHrfToGraph = (state: RootState, graph: NonNullableGraph): void = const { vae, seamlessXAxis, seamlessYAxis } = state.generation; const { hrfStrength, hrfEnabled, hrfMethod } = state.hrf; - const { width, height } = state.regionalPrompts.present.size; + const { width, height } = state.controlLayers.present.size; const isAutoVae = !vae; const isSeamlessEnabled = seamlessXAxis || seamlessYAxis; const optimalDimension = selectOptimalDimension(state); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts index 6373c87eb5..1fd0ea76d7 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addIPAdapterToLinearGraph.ts @@ -1,7 +1,7 @@ import type { RootState } from 'app/store/store'; import { selectValidIPAdapters } from 'features/controlAdapters/store/controlAdaptersSlice'; import type { IPAdapterConfig } from 'features/controlAdapters/store/types'; -import { isIPAdapterLayer, isMaskedGuidanceLayer } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isIPAdapterLayer, isMaskedGuidanceLayer } from 'features/controlLayers/store/controlLayersSlice'; import type { ImageField } from 'features/nodes/types/common'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { differenceWith, intersectionWith } from 'lodash-es'; @@ -27,7 +27,7 @@ const getIPAdapters = (state: RootState) => { }); // Masked IP adapters are handled in the graph helper for regional control - skip them here - const maskedIPAdapterIds = state.regionalPrompts.present.layers + const maskedIPAdapterIds = state.controlLayers.present.layers .filter(isMaskedGuidanceLayer) .map((l) => l.ipAdapterIds) .flat(); @@ -40,7 +40,7 @@ const getIPAdapters = (state: RootState) => { if (activeTabName === 'txt2img') { // If we are on the t2i tab, we only want to add the IP adapters that are used in unmasked IP Adapter layers // Collect all IP Adapter ids for enabled IP adapter layers - const layerIPAdapterIds = state.regionalPrompts.present.layers + const layerIPAdapterIds = state.controlLayers.present.layers .filter(isIPAdapterLayer) .filter((l) => l.isEnabled) .map((l) => l.ipAdapterId); @@ -48,7 +48,7 @@ const getIPAdapters = (state: RootState) => { } else { // Else, we want to exclude the IP adapters that are used in IP Adapter layers // Collect all IP Adapter ids for enabled IP adapter layers - const layerIPAdapterIds = state.regionalPrompts.present.layers.filter(isIPAdapterLayer).map((l) => l.ipAdapterId); + const layerIPAdapterIds = state.controlLayers.present.layers.filter(isIPAdapterLayer).map((l) => l.ipAdapterId); return differenceWith(nonMaskedIPAdapters, layerIPAdapterIds, (a, b) => a.id === b); } }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts index 9006ed8b83..1632449724 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addT2IAdapterToLinearGraph.ts @@ -1,7 +1,7 @@ import type { RootState } from 'app/store/store'; import { selectValidT2IAdapters } from 'features/controlAdapters/store/controlAdaptersSlice'; import type { ControlAdapterProcessorType, T2IAdapterConfig } from 'features/controlAdapters/store/types'; -import { isControlAdapterLayer } from 'features/controlLayers/store/regionalPromptsSlice'; +import { isControlAdapterLayer } from 'features/controlLayers/store/controlLayersSlice'; import type { ImageField } from 'features/nodes/types/common'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; import { differenceWith, intersectionWith } from 'lodash-es'; @@ -36,14 +36,14 @@ const getT2IAdapters = (state: RootState) => { if (activeTabName === 'txt2img') { // Add only the T2Is that are used in control layers // Collect all ids for enabled control adapter layers - const layerControlAdapterIds = state.regionalPrompts.present.layers + const layerControlAdapterIds = state.controlLayers.present.layers .filter(isControlAdapterLayer) .filter((l) => l.isEnabled) .map((l) => l.controlNetId); return intersectionWith(validT2IAdapters, layerControlAdapterIds, (a, b) => a.id === b); } else { // Else, we want to exclude the T2Is that are used in control layers - const layerControlAdapterIds = state.regionalPrompts.present.layers + const layerControlAdapterIds = state.controlLayers.present.layers .filter(isControlAdapterLayer) .map((l) => l.controlNetId); return differenceWith(validT2IAdapters, layerControlAdapterIds, (a, b) => a.id === b); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasImageToImageGraph.ts index 144db94f3c..f2c9957edc 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasImageToImageGraph.ts @@ -55,7 +55,7 @@ export const buildCanvasImageToImageGraph = async ( seamlessXAxis, seamlessYAxis, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; // The bounding box determines width and height, not the width and height params const { width, height } = state.canvas.boundingBoxDimensions; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasInpaintGraph.ts index 49cd590780..ab73953008 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasInpaintGraph.ts @@ -64,7 +64,7 @@ export const buildCanvasInpaintGraph = async ( canvasCoherenceEdgeSize, maskBlur, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; if (!model) { log.error('No model found in state'); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasOutpaintGraph.ts index c94b07d395..6b564f464e 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasOutpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasOutpaintGraph.ts @@ -76,7 +76,7 @@ export const buildCanvasOutpaintGraph = async ( canvasCoherenceEdgeSize, maskBlur, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; if (!model) { log.error('No model found in state'); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLImageToImageGraph.ts index 7b29d0a8fb..ee918d1470 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLImageToImageGraph.ts @@ -55,7 +55,7 @@ export const buildCanvasSDXLImageToImageGraph = async ( seamlessYAxis, img2imgStrength: strength, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; const { refinerModel, refinerStart } = state.sdxl; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLInpaintGraph.ts index 4b1fd4575a..68b948a44a 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLInpaintGraph.ts @@ -64,7 +64,7 @@ export const buildCanvasSDXLInpaintGraph = async ( canvasCoherenceEdgeSize, maskBlur, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; const { refinerModel, refinerStart } = state.sdxl; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLOutpaintGraph.ts index 0561976edb..c5c40b695a 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLOutpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLOutpaintGraph.ts @@ -76,7 +76,7 @@ export const buildCanvasSDXLOutpaintGraph = async ( canvasCoherenceEdgeSize, maskBlur, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; const { refinerModel, refinerStart } = state.sdxl; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLTextToImageGraph.ts index 3f890e02ef..f6ac645580 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasSDXLTextToImageGraph.ts @@ -44,7 +44,7 @@ export const buildCanvasSDXLTextToImageGraph = async (state: RootState): Promise seamlessXAxis, seamlessYAxis, } = state.generation; - const { positivePrompt, negativePrompt } = state.regionalPrompts.present; + const { positivePrompt, negativePrompt } = state.controlLayers.present; // The bounding box determines width and height, not the width and height params const { width, height } = state.canvas.boundingBoxDimensions; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasTextToImageGraph.ts index 4458720be7..0749308fb8 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildCanvasTextToImageGraph.ts @@ -44,7 +44,7 @@ export const buildCanvasTextToImageGraph = async (state: RootState): Promise { const { iterations, model, shouldRandomizeSeed, seed } = state.generation; - const { shouldConcatPrompts } = state.regionalPrompts.present; + const { shouldConcatPrompts } = state.controlLayers.present; const { prompts, seedBehaviour } = state.dynamicPrompts; const data: Batch['data'] = []; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearImageToImageGraph.ts index 1a890ed57a..0ca121b667 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearImageToImageGraph.ts @@ -53,8 +53,8 @@ export const buildLinearImageToImageGraph = async (state: RootState): Promise { */ export const getSDXLStylePrompts = (state: RootState): { positiveStylePrompt: string; negativeStylePrompt: string } => { const { positivePrompt, negativePrompt, positivePrompt2, negativePrompt2, shouldConcatPrompts } = - state.regionalPrompts.present; + state.controlLayers.present; return { positiveStylePrompt: shouldConcatPrompts ? positivePrompt : positivePrompt2, diff --git a/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx b/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx index ccfb6f7c72..5702cf8bd7 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Core/ParamNegativePrompt.tsx @@ -1,6 +1,6 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { negativePromptChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { negativePromptChanged } from 'features/controlLayers/store/controlLayersSlice'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; @@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'; export const ParamNegativePrompt = memo(() => { const dispatch = useAppDispatch(); - const prompt = useAppSelector((s) => s.regionalPrompts.present.negativePrompt); + const prompt = useAppSelector((s) => s.controlLayers.present.negativePrompt); const textareaRef = useRef(null); const { t } = useTranslation(); const _onChange = useCallback( diff --git a/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx b/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx index 4f6e66e50a..0b2890875e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Core/ParamPositivePrompt.tsx @@ -1,6 +1,6 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { positivePromptChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { positivePromptChanged } from 'features/controlLayers/store/controlLayersSlice'; import { ShowDynamicPromptsPreviewButton } from 'features/dynamicPrompts/components/ShowDynamicPromptsPreviewButton'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; @@ -14,7 +14,7 @@ import { useTranslation } from 'react-i18next'; export const ParamPositivePrompt = memo(() => { const dispatch = useAppDispatch(); - const prompt = useAppSelector((s) => s.regionalPrompts.present.positivePrompt); + const prompt = useAppSelector((s) => s.controlLayers.present.positivePrompt); const baseModel = useAppSelector((s) => s.generation.model)?.base; const textareaRef = useRef(null); diff --git a/invokeai/frontend/web/src/features/queue/components/QueueButtonTooltip.tsx b/invokeai/frontend/web/src/features/queue/components/QueueButtonTooltip.tsx index 351589a949..f63e96c45f 100644 --- a/invokeai/frontend/web/src/features/queue/components/QueueButtonTooltip.tsx +++ b/invokeai/frontend/web/src/features/queue/components/QueueButtonTooltip.tsx @@ -2,7 +2,7 @@ import { Divider, Flex, ListItem, Text, UnorderedList } from '@invoke-ai/ui-libr import { createSelector } from '@reduxjs/toolkit'; import { useAppSelector } from 'app/store/storeHooks'; import { useIsReadyToEnqueue } from 'common/hooks/useIsReadyToEnqueue'; -import { selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { selectDynamicPromptsSlice } from 'features/dynamicPrompts/store/dynamicPromptsSlice'; import { getShouldProcessPrompt } from 'features/dynamicPrompts/util/getShouldProcessPrompt'; import { memo, useMemo } from 'react'; @@ -11,10 +11,10 @@ import { useEnqueueBatchMutation } from 'services/api/endpoints/queue'; import { useBoardName } from 'services/api/hooks/useBoardName'; const selectPromptsCount = createSelector( - selectRegionalPromptsSlice, + selectControlLayersSlice, selectDynamicPromptsSlice, - (regionalPrompts, dynamicPrompts) => - getShouldProcessPrompt(regionalPrompts.present.positivePrompt) ? dynamicPrompts.prompts.length : 1 + (controlLayers, dynamicPrompts) => + getShouldProcessPrompt(controlLayers.present.positivePrompt) ? dynamicPrompts.prompts.length : 1 ); type Props = { diff --git a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLNegativeStylePrompt.tsx b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLNegativeStylePrompt.tsx index 6104642b62..bba9e0b32d 100644 --- a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLNegativeStylePrompt.tsx +++ b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLNegativeStylePrompt.tsx @@ -1,6 +1,6 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { negativePrompt2Changed } from 'features/controlLayers/store/regionalPromptsSlice'; +import { negativePrompt2Changed } from 'features/controlLayers/store/controlLayersSlice'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; @@ -11,7 +11,7 @@ import { useTranslation } from 'react-i18next'; export const ParamSDXLNegativeStylePrompt = memo(() => { const dispatch = useAppDispatch(); - const prompt = useAppSelector((s) => s.regionalPrompts.present.negativePrompt2); + const prompt = useAppSelector((s) => s.controlLayers.present.negativePrompt2); const textareaRef = useRef(null); const { t } = useTranslation(); const handleChange = useCallback( diff --git a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLPositiveStylePrompt.tsx b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLPositiveStylePrompt.tsx index d14d42a3ce..3828136c74 100644 --- a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLPositiveStylePrompt.tsx +++ b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/ParamSDXLPositiveStylePrompt.tsx @@ -1,6 +1,6 @@ import { Box, Textarea } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { positivePrompt2Changed } from 'features/controlLayers/store/regionalPromptsSlice'; +import { positivePrompt2Changed } from 'features/controlLayers/store/controlLayersSlice'; import { PromptOverlayButtonWrapper } from 'features/parameters/components/Prompts/PromptOverlayButtonWrapper'; import { AddPromptTriggerButton } from 'features/prompt/AddPromptTriggerButton'; import { PromptPopover } from 'features/prompt/PromptPopover'; @@ -10,7 +10,7 @@ import { useTranslation } from 'react-i18next'; export const ParamSDXLPositiveStylePrompt = memo(() => { const dispatch = useAppDispatch(); - const prompt = useAppSelector((s) => s.regionalPrompts.present.positivePrompt2); + const prompt = useAppSelector((s) => s.controlLayers.present.positivePrompt2); const textareaRef = useRef(null); const { t } = useTranslation(); const handleChange = useCallback( diff --git a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLConcatButton.tsx b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLConcatButton.tsx index 436749428b..0af3dfcee4 100644 --- a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLConcatButton.tsx +++ b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLConcatButton.tsx @@ -1,12 +1,12 @@ import { IconButton, Tooltip } from '@invoke-ai/ui-library'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { shouldConcatPromptsChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { shouldConcatPromptsChanged } from 'features/controlLayers/store/controlLayersSlice'; import { memo, useCallback, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { PiLinkSimpleBold, PiLinkSimpleBreakBold } from 'react-icons/pi'; export const SDXLConcatButton = memo(() => { - const shouldConcatPrompts = useAppSelector((s) => s.regionalPrompts.present.shouldConcatPrompts); + const shouldConcatPrompts = useAppSelector((s) => s.controlLayers.present.shouldConcatPrompts); const dispatch = useAppDispatch(); const { t } = useTranslation(); diff --git a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLPrompts.tsx b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLPrompts.tsx index edfd6302a4..b585e92a5f 100644 --- a/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLPrompts.tsx +++ b/invokeai/frontend/web/src/features/sdxl/components/SDXLPrompts/SDXLPrompts.tsx @@ -8,7 +8,7 @@ import { ParamSDXLNegativeStylePrompt } from './ParamSDXLNegativeStylePrompt'; import { ParamSDXLPositiveStylePrompt } from './ParamSDXLPositiveStylePrompt'; export const SDXLPrompts = memo(() => { - const shouldConcatPrompts = useAppSelector((s) => s.regionalPrompts.present.shouldConcatPrompts); + const shouldConcatPrompts = useAppSelector((s) => s.controlLayers.present.shouldConcatPrompts); return ( diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/ControlSettingsAccordion/ControlSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/ControlSettingsAccordion/ControlSettingsAccordion.tsx index 2de6d9de00..eb3f932bbf 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/ControlSettingsAccordion/ControlSettingsAccordion.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/ControlSettingsAccordion/ControlSettingsAccordion.tsx @@ -13,10 +13,7 @@ import { selectValidIPAdapters, selectValidT2IAdapters, } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { - selectAllControlAdapterIds, - selectRegionalPromptsSlice, -} from 'features/controlLayers/store/regionalPromptsSlice'; +import { selectAllControlAdapterIds, selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/useStandaloneAccordionToggle'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; import { Fragment, memo } from 'react'; @@ -24,12 +21,12 @@ import { useTranslation } from 'react-i18next'; import { PiPlusBold } from 'react-icons/pi'; const selector = createMemoizedSelector( - [selectControlAdaptersSlice, selectRegionalPromptsSlice], - (controlAdapters, regionalPrompts) => { + [selectControlAdaptersSlice, selectControlLayersSlice], + (controlAdapters, controlLayers) => { const badges: string[] = []; let isError = false; - const regionalControlAdapterIds = selectAllControlAdapterIds(regionalPrompts.present); + const regionalControlAdapterIds = selectAllControlAdapterIds(controlLayers.present); const enabledNonRegionalIPAdapterCount = selectAllIPAdapters(controlAdapters) .filter((ca) => !regionalControlAdapterIds.includes(ca.id)) diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion.tsx index 6f30d5110a..bb9cfd36ce 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSettingsAccordion.tsx @@ -3,7 +3,7 @@ import { Expander, Flex, FormControlGroup, StandaloneAccordion } from '@invoke-a import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; import { useAppSelector } from 'app/store/storeHooks'; import { selectCanvasSlice } from 'features/canvas/store/canvasSlice'; -import { selectRegionalPromptsSlice } from 'features/controlLayers/store/regionalPromptsSlice'; +import { selectControlLayersSlice } from 'features/controlLayers/store/controlLayersSlice'; import { HrfSettings } from 'features/hrf/components/HrfSettings'; import { selectHrfSlice } from 'features/hrf/store/hrfSlice'; import ParamScaleBeforeProcessing from 'features/parameters/components/Canvas/InfillAndScaling/ParamScaleBeforeProcessing'; @@ -25,8 +25,8 @@ import { ImageSizeCanvas } from './ImageSizeCanvas'; import { ImageSizeLinear } from './ImageSizeLinear'; const selector = createMemoizedSelector( - [selectGenerationSlice, selectCanvasSlice, selectHrfSlice, selectRegionalPromptsSlice, activeTabNameSelector], - (generation, canvas, hrf, regionalPrompts, activeTabName) => { + [selectGenerationSlice, selectCanvasSlice, selectHrfSlice, selectControlLayersSlice, activeTabNameSelector], + (generation, canvas, hrf, controlLayers, activeTabName) => { const { shouldRandomizeSeed, model } = generation; const { hrfEnabled } = hrf; const badges: string[] = []; @@ -43,7 +43,7 @@ const selector = createMemoizedSelector( badges.push('locked'); } } else { - const { aspectRatio, width, height } = regionalPrompts.present.size; + const { aspectRatio, width, height } = controlLayers.present.size; badges.push(`${width}×${height}`); badges.push(aspectRatio.id); if (aspectRatio.isLocked) { diff --git a/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear.tsx b/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear.tsx index 6ca9988f67..7e436556da 100644 --- a/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear.tsx +++ b/invokeai/frontend/web/src/features/settingsAccordions/components/ImageSettingsAccordion/ImageSizeLinear.tsx @@ -1,5 +1,5 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { aspectRatioChanged, heightChanged, widthChanged } from 'features/controlLayers/store/regionalPromptsSlice'; +import { aspectRatioChanged, heightChanged, widthChanged } from 'features/controlLayers/store/controlLayersSlice'; import { ParamHeight } from 'features/parameters/components/Core/ParamHeight'; import { ParamWidth } from 'features/parameters/components/Core/ParamWidth'; import { AspectRatioCanvasPreview } from 'features/parameters/components/ImageSize/AspectRatioCanvasPreview'; @@ -12,9 +12,9 @@ import { memo, useCallback } from 'react'; export const ImageSizeLinear = memo(() => { const dispatch = useAppDispatch(); const tab = useAppSelector(activeTabNameSelector); - const width = useAppSelector((s) => s.regionalPrompts.present.size.width); - const height = useAppSelector((s) => s.regionalPrompts.present.size.height); - const aspectRatioState = useAppSelector((s) => s.regionalPrompts.present.size.aspectRatio); + const width = useAppSelector((s) => s.controlLayers.present.size.width); + const height = useAppSelector((s) => s.controlLayers.present.size.height); + const aspectRatioState = useAppSelector((s) => s.controlLayers.present.size.aspectRatio); const onChangeWidth = useCallback( (width: number) => { diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPanelTextToImage.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPanelTextToImage.tsx index 0adf65d0bb..82243867d7 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPanelTextToImage.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPanelTextToImage.tsx @@ -1,7 +1,7 @@ import { Box, Flex, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants'; -import { RegionalPromptsPanelContent } from 'features/controlLayers/components/RegionalPromptsPanelContent'; +import { ControlLayersPanelContent } from 'features/controlLayers/components/ControlLayersPanelContent'; import { useRegionalControlTitle } from 'features/controlLayers/hooks/useRegionalControlTitle'; import { Prompts } from 'features/parameters/components/Prompts/Prompts'; import QueueControls from 'features/queue/components/QueueControls'; @@ -55,7 +55,7 @@ const ParametersPanelTextToImage = () => { - + diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx index fc8694e06d..1ff5dd6462 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx @@ -1,5 +1,5 @@ import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library'; -import { RegionalPromptsEditor } from 'features/controlLayers/components/RegionalPromptsEditor'; +import { ControlLayersEditor } from 'features/controlLayers/components/ControlLayersEditor'; import { useRegionalControlTitle } from 'features/controlLayers/hooks/useRegionalControlTitle'; import CurrentImageDisplay from 'features/gallery/components/CurrentImage/CurrentImageDisplay'; import { memo } from 'react'; @@ -22,7 +22,7 @@ const TextToImageTab = () => { - +