diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasImageToControlNet.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasImageToControlNet.ts index b1b19b35dc..55392ebff4 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasImageToControlNet.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasImageToControlNet.ts @@ -48,10 +48,12 @@ export const addCanvasImageToControlNetListener = (startAppListening: AppStartLi }) ).unwrap(); + const { image_name } = imageDTO; + dispatch( controlAdapterImageChanged({ id, - controlImage: imageDTO, + controlImage: image_name, }) ); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMaskToControlNet.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMaskToControlNet.ts index b3014277f1..569b4badc7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMaskToControlNet.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasMaskToControlNet.ts @@ -58,10 +58,12 @@ export const addCanvasMaskToControlNetListener = (startAppListening: AppStartLis }) ).unwrap(); + const { image_name } = imageDTO; + dispatch( controlAdapterImageChanged({ id, - controlImage: imageDTO, + controlImage: image_name, }) ); }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts index 14af0246a2..e52df30681 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts @@ -12,7 +12,6 @@ import { selectControlAdapterById, } from 'features/controlAdapters/store/controlAdaptersSlice'; import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { isEqual } from 'lodash-es'; type AnyControlAdapterParamChangeAction = | ReturnType @@ -53,11 +52,6 @@ const predicate: AnyListenerPredicate = (action, state, prevState) => return false; } - if (prevCA.controlImage === ca.controlImage && isEqual(prevCA.processorNode, ca.processorNode)) { - // Don't re-process if the processor hasn't changed - return false; - } - const isProcessorSelected = processorType !== 'none'; const hasControlImage = Boolean(controlImage); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts index 08afc98836..0055866aa7 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts @@ -91,7 +91,7 @@ export const addControlNetImageProcessedListener = (startAppListening: AppStartL dispatch( controlAdapterProcessedImageChanged({ id, - processedControlImage, + processedControlImage: processedControlImage.image_name, }) ); } diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts index de2ac3a39a..5db78ed75e 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts @@ -76,7 +76,7 @@ export const addImageDroppedListener = (startAppListening: AppStartListening) => dispatch( controlAdapterImageChanged({ id, - controlImage: activeData.payload.imageDTO, + controlImage: activeData.payload.imageDTO.image_name, }) ); dispatch( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts index fd568ef1bd..d0edfafd57 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts @@ -101,7 +101,7 @@ export const addImageUploadedFulfilledListener = (startAppListening: AppStartLis dispatch( controlAdapterImageChanged({ id, - controlImage: imageDTO, + controlImage: imageDTO.image_name, }) ); dispatch( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts index b69e56e84a..bc049cf498 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelSelected.ts @@ -1,7 +1,7 @@ import { logger } from 'app/logging/logger'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; import { - controlAdapterModelChanged, + controlAdapterIsEnabledChanged, selectControlAdapterAll, } from 'features/controlAdapters/store/controlAdaptersSlice'; import { loraRemoved } from 'features/lora/store/loraSlice'; @@ -54,7 +54,7 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) = // handle incompatible controlnets selectControlAdapterAll(state.controlAdapters).forEach((ca) => { if (ca.model?.base !== newBaseModel) { - dispatch(controlAdapterModelChanged({ id: ca.id, modelConfig: null })); + dispatch(controlAdapterIsEnabledChanged({ id: ca.id, isEnabled: false })); modelsCleared += 1; } }); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx index 032e46f477..fcc816d75f 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx @@ -113,7 +113,7 @@ const ControlAdapterConfig = (props: { id: string; number: number }) => { - {controlAdapterType === 'ip_adapter' && } + diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx index d7d91ab780..c7aaa9f26c 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx @@ -46,9 +46,13 @@ const ParamControlAdapterIPMethod = ({ id }: Props) => { const value = useMemo(() => options.find((o) => o.value === method), [options, method]); + if (!method) { + return null; + } + return ( - + {t('controlnet.ipAdapterMethod')} diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx index 73a7d695b3..00c7d5859d 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx +++ b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx @@ -102,9 +102,13 @@ const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => { ); return ( - + - + { { const selector = useMemo( () => createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - assert(ca?.type === 'ip_adapter'); - return ca.method; + const cn = selectControlAdapterById(controlAdapters, id); + if (cn && cn?.type === 'ip_adapter') { + return cn.method; + } }), [id] ); diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts b/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts index f8afde677c..8ec397f99c 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts +++ b/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts @@ -7,7 +7,7 @@ import { buildControlAdapter } from 'features/controlAdapters/util/buildControlA import { buildControlAdapterProcessor } from 'features/controlAdapters/util/buildControlAdapterProcessor'; import { zModelIdentifierField } from 'features/nodes/types/common'; import { merge, uniq } from 'lodash-es'; -import type { ControlNetModelConfig, ImageDTO, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types'; +import type { ControlNetModelConfig, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types'; import { socketInvocationError } from 'services/events/actions'; import { v4 as uuidv4 } from 'uuid'; @@ -134,46 +134,23 @@ export const controlAdaptersSlice = createSlice({ const { id, isEnabled } = action.payload; caAdapter.updateOne(state, { id, changes: { isEnabled } }); }, - controlAdapterImageChanged: (state, action: PayloadAction<{ id: string; controlImage: ImageDTO | null }>) => { + controlAdapterImageChanged: ( + state, + action: PayloadAction<{ + id: string; + controlImage: string | null; + }> + ) => { const { id, controlImage } = action.payload; const ca = selectControlAdapterById(state, id); if (!ca) { return; } - if (isControlNetOrT2IAdapter(ca)) { - if (controlImage) { - const { image_name, width, height } = controlImage; - const processorNode = deepClone(ca.processorNode); - const minDim = Math.min(controlImage.width, controlImage.height); - if ('detect_resolution' in processorNode) { - processorNode.detect_resolution = minDim; - } - if ('image_resolution' in processorNode) { - processorNode.image_resolution = minDim; - } - if ('resolution' in processorNode) { - processorNode.resolution = minDim; - } - caAdapter.updateOne(state, { - id, - changes: { - processorNode, - controlImage: image_name, - controlImageDimensions: { width, height }, - processedControlImage: null, - }, - }); - } else { - caAdapter.updateOne(state, { - id, - changes: { controlImage: null, controlImageDimensions: null, processedControlImage: null }, - }); - } - } else { - // ip adapter - caAdapter.updateOne(state, { id, changes: { controlImage: controlImage?.image_name ?? null } }); - } + caAdapter.updateOne(state, { + id, + changes: { controlImage, processedControlImage: null }, + }); if (controlImage !== null && isControlNetOrT2IAdapter(ca) && ca.processorType !== 'none') { state.pendingControlImages.push(id); @@ -183,7 +160,7 @@ export const controlAdaptersSlice = createSlice({ state, action: PayloadAction<{ id: string; - processedControlImage: ImageDTO | null; + processedControlImage: string | null; }> ) => { const { id, processedControlImage } = action.payload; @@ -196,24 +173,12 @@ export const controlAdaptersSlice = createSlice({ return; } - if (processedControlImage) { - const { image_name, width, height } = processedControlImage; - caAdapter.updateOne(state, { - id, - changes: { - processedControlImage: image_name, - processedControlImageDimensions: { width, height }, - }, - }); - } else { - caAdapter.updateOne(state, { - id, - changes: { - processedControlImage: null, - processedControlImageDimensions: null, - }, - }); - } + caAdapter.updateOne(state, { + id, + changes: { + processedControlImage, + }, + }); state.pendingControlImages = state.pendingControlImages.filter((pendingId) => pendingId !== id); }, @@ -227,7 +192,7 @@ export const controlAdaptersSlice = createSlice({ state, action: PayloadAction<{ id: string; - modelConfig: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig | null; + modelConfig: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig; }> ) => { const { id, modelConfig } = action.payload; @@ -236,11 +201,6 @@ export const controlAdaptersSlice = createSlice({ return; } - if (modelConfig === null) { - caAdapter.updateOne(state, { id, changes: { model: null } }); - return; - } - const model = zModelIdentifierField.parse(modelConfig); if (!isControlNetOrT2IAdapter(cn)) { @@ -248,36 +208,22 @@ export const controlAdaptersSlice = createSlice({ return; } + const update: Update = { + id, + changes: { model, shouldAutoConfig: true }, + }; + + update.changes.processedControlImage = null; + if (modelConfig.type === 'ip_adapter') { // should never happen... return; } - // We always update the model - const update: Update = { id, changes: { model } }; - - // Build the default processor for this model const processor = buildControlAdapterProcessor(modelConfig); - if (processor.processorType !== cn.processorNode.type) { - // If the processor type has changed, update the processor node - update.changes.shouldAutoConfig = true; - update.changes.processedControlImage = null; - update.changes.processorType = processor.processorType; - update.changes.processorNode = processor.processorNode; + update.changes.processorType = processor.processorType; + update.changes.processorNode = processor.processorNode; - if (cn.controlImageDimensions) { - const minDim = Math.min(cn.controlImageDimensions.width, cn.controlImageDimensions.height); - if ('detect_resolution' in update.changes.processorNode) { - update.changes.processorNode.detect_resolution = minDim; - } - if ('image_resolution' in update.changes.processorNode) { - update.changes.processorNode.image_resolution = minDim; - } - if ('resolution' in update.changes.processorNode) { - update.changes.processorNode.resolution = minDim; - } - } - } caAdapter.updateOne(state, update); }, controlAdapterWeightChanged: (state, action: PayloadAction<{ id: string; weight: number }>) => { @@ -394,23 +340,8 @@ export const controlAdaptersSlice = createSlice({ if (update.changes.shouldAutoConfig && modelConfig) { const processor = buildControlAdapterProcessor(modelConfig); - if (processor.processorType !== cn.processorNode.type) { - update.changes.processorType = processor.processorType; - update.changes.processorNode = processor.processorNode; - // Copy image resolution settings, urgh - if (cn.controlImageDimensions) { - const minDim = Math.min(cn.controlImageDimensions.width, cn.controlImageDimensions.height); - if ('detect_resolution' in update.changes.processorNode) { - update.changes.processorNode.detect_resolution = minDim; - } - if ('image_resolution' in update.changes.processorNode) { - update.changes.processorNode.image_resolution = minDim; - } - if ('resolution' in update.changes.processorNode) { - update.changes.processorNode.resolution = minDim; - } - } - } + update.changes.processorType = processor.processorType; + update.changes.processorNode = processor.processorNode; } caAdapter.updateOne(state, update); diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/types.ts b/invokeai/frontend/web/src/features/controlAdapters/store/types.ts index 80af59cd01..7e2f18af5c 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/store/types.ts +++ b/invokeai/frontend/web/src/features/controlAdapters/store/types.ts @@ -225,9 +225,7 @@ export type ControlNetConfig = { controlMode: ControlMode; resizeMode: ResizeMode; controlImage: string | null; - controlImageDimensions: { width: number; height: number } | null; processedControlImage: string | null; - processedControlImageDimensions: { width: number; height: number } | null; processorType: ControlAdapterProcessorType; processorNode: RequiredControlAdapterProcessorNode; shouldAutoConfig: boolean; @@ -243,9 +241,7 @@ export type T2IAdapterConfig = { endStepPct: number; resizeMode: ResizeMode; controlImage: string | null; - controlImageDimensions: { width: number; height: number } | null; processedControlImage: string | null; - processedControlImageDimensions: { width: number; height: number } | null; processorType: ControlAdapterProcessorType; processorNode: RequiredControlAdapterProcessorNode; shouldAutoConfig: boolean; diff --git a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts b/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts index 7c9c28e2b3..ad7bdba363 100644 --- a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts +++ b/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts @@ -20,9 +20,7 @@ export const initialControlNet: Omit = { controlMode: 'balanced', resizeMode: 'just_resize', controlImage: null, - controlImageDimensions: null, processedControlImage: null, - processedControlImageDimensions: null, processorType: 'canny_image_processor', processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, shouldAutoConfig: true, @@ -37,9 +35,7 @@ export const initialT2IAdapter: Omit = { endStepPct: 1, resizeMode: 'just_resize', controlImage: null, - controlImageDimensions: null, processedControlImage: null, - processedControlImageDimensions: null, processorType: 'canny_image_processor', processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, shouldAutoConfig: true, diff --git a/invokeai/frontend/web/src/features/metadata/util/parsers.ts b/invokeai/frontend/web/src/features/metadata/util/parsers.ts index 5d2bd78784..3decea6737 100644 --- a/invokeai/frontend/web/src/features/metadata/util/parsers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/parsers.ts @@ -286,9 +286,7 @@ const parseControlNet: MetadataParseFunc = async (meta controlMode: control_mode ?? initialControlNet.controlMode, resizeMode: resize_mode ?? initialControlNet.resizeMode, controlImage: image?.image_name ?? null, - controlImageDimensions: null, processedControlImage: processedImage?.image_name ?? null, - processedControlImageDimensions: null, processorType, processorNode, shouldAutoConfig: true, @@ -352,11 +350,9 @@ const parseT2IAdapter: MetadataParseFunc = async (meta endStepPct: end_step_percent ?? initialT2IAdapter.endStepPct, resizeMode: resize_mode ?? initialT2IAdapter.resizeMode, controlImage: image?.image_name ?? null, - controlImageDimensions: null, processedControlImage: processedImage?.image_name ?? null, - processedControlImageDimensions: null, - processorNode, processorType, + processorNode, shouldAutoConfig: true, id: uuidv4(), };