diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlAdapterPreprocessor.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlAdapterPreprocessor.ts index 4e5fb3cb00..6d77a53342 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlAdapterPreprocessor.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlAdapterPreprocessor.ts @@ -4,15 +4,15 @@ import type { AppStartListening } from 'app/store/middleware/listenerMiddleware' import type { AppDispatch } from 'app/store/store'; import { parseify } from 'common/util/serialize'; import { - controlAdapterImageChanged, - controlAdapterModelChanged, - controlAdapterProcessedImageChanged, - controlAdapterProcessorConfigChanged, - controlAdapterProcessorPendingBatchIdChanged, - controlAdapterRecalled, + caImageChanged, + caModelChanged, + caProcessedImageChanged, + caProcessorConfigChanged, + caProcessorPendingBatchIdChanged, + caRecalled, } from 'features/controlLayers/store/canvasV2Slice'; -import { isControlAdapterLayer } from 'features/controlLayers/store/types'; -import { CA_PROCESSOR_DATA } from 'features/controlLayers/util/controlAdapters'; +import { selectCA } from 'features/controlLayers/store/controlAdaptersReducers'; +import { CA_PROCESSOR_DATA } from 'features/controlLayers/store/types'; import { toast } from 'features/toast/toast'; import { t } from 'i18next'; import { isEqual } from 'lodash-es'; @@ -22,13 +22,7 @@ import type { BatchConfig } from 'services/api/types'; import { socketInvocationComplete } from 'services/events/actions'; import { assert } from 'tsafe'; -const matcher = isAnyOf( - controlAdapterImageChanged, - controlAdapterProcessedImageChanged, - controlAdapterProcessorConfigChanged, - controlAdapterModelChanged, - controlAdapterRecalled -); +const matcher = isAnyOf(caImageChanged, caProcessedImageChanged, caProcessorConfigChanged, caModelChanged, caRecalled); const DEBOUNCE_MS = 300; const log = logger('session'); @@ -36,7 +30,7 @@ const log = logger('session'); /** * Simple helper to cancel a batch and reset the pending batch ID */ -const cancelProcessorBatch = async (dispatch: AppDispatch, layerId: string, batchId: string) => { +const cancelProcessorBatch = async (dispatch: AppDispatch, id: string, batchId: string) => { const req = dispatch(queueApi.endpoints.cancelByBatchIds.initiate({ batch_ids: [batchId] })); log.trace({ batchId }, 'Cancelling existing preprocessor batch'); try { @@ -46,7 +40,7 @@ const cancelProcessorBatch = async (dispatch: AppDispatch, layerId: string, batc } finally { req.reset(); // Always reset the pending batch ID - the cancel req could fail if the batch doesn't exist - dispatch(controlAdapterProcessorPendingBatchIdChanged({ layerId, batchId: null })); + dispatch(caProcessorPendingBatchIdChanged({ id, batchId: null })); } }; @@ -54,7 +48,7 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni startAppListening({ matcher, effect: async (action, { dispatch, getState, getOriginalState, cancelActiveListeners, delay, take, signal }) => { - const layerId = controlAdapterRecalled.match(action) ? action.payload.id : action.payload.layerId; + const id = caRecalled.match(action) ? action.payload.data.id : action.payload.id; const state = getState(); const originalState = getOriginalState(); @@ -65,22 +59,20 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni // Delay before starting actual work await delay(DEBOUNCE_MS); - const layer = state.canvasV2.layers.filter(isControlAdapterLayer).find((l) => l.id === layerId); + const ca = selectCA(state.canvasV2, id); - if (!layer) { + if (!ca) { return; } // We should only process if the processor settings or image have changed - const originalLayer = originalState.canvasV2.layers - .filter(isControlAdapterLayer) - .find((l) => l.id === layerId); - const originalImage = originalLayer?.controlAdapter.image; - const originalConfig = originalLayer?.controlAdapter.processorConfig; + const originalCA = selectCA(originalState.canvasV2, id); + const originalImage = originalCA?.image; + const originalConfig = originalCA?.processorConfig; - const image = layer.controlAdapter.image; - const processedImage = layer.controlAdapter.processedImage; - const config = layer.controlAdapter.processorConfig; + const image = ca.image; + const processedImage = ca.processedImage; + const config = ca.processorConfig; if (isEqual(config, originalConfig) && isEqual(image, originalImage) && processedImage) { // Neither config nor image have changed, we can bail @@ -91,15 +83,15 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni // - If we have no image, we have nothing to process // - If we have no processor config, we have nothing to process // Clear the processed image and bail - dispatch(controlAdapterProcessedImageChanged({ layerId, imageDTO: null })); + dispatch(caProcessedImageChanged({ id, imageDTO: null })); return; } // At this point, the user has stopped fiddling with the processor settings and there is a processor selected. // If there is a pending processor batch, cancel it. - if (layer.controlAdapter.processorPendingBatchId) { - cancelProcessorBatch(dispatch, layerId, layer.controlAdapter.processorPendingBatchId); + if (ca.processorPendingBatchId) { + cancelProcessorBatch(dispatch, id, ca.processorPendingBatchId); } // TODO(psyche): I can't get TS to be happy, it thinkgs `config` is `never` but it should be inferred from the generic... I'll just cast it for now @@ -132,7 +124,7 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni const enqueueResult = await req.unwrap(); // TODO(psyche): Update the pydantic models, pretty sure we will _always_ have a batch_id here, but the model says it's optional assert(enqueueResult.batch.batch_id, 'Batch ID not returned from queue'); - dispatch(controlAdapterProcessorPendingBatchIdChanged({ layerId, batchId: enqueueResult.batch.batch_id })); + dispatch(caProcessorPendingBatchIdChanged({ id, batchId: enqueueResult.batch.batch_id })); log.debug({ enqueueResult: parseify(enqueueResult) }, t('queue.graphQueued')); // Wait for the processor node to complete @@ -154,17 +146,15 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni assert(imageDTO, "Failed to fetch processor output's image DTO"); // Whew! We made it. Update the layer with the processed image - log.debug({ layerId, imageDTO }, 'ControlNet image processed'); - dispatch(controlAdapterProcessedImageChanged({ layerId, imageDTO })); - dispatch(controlAdapterProcessorPendingBatchIdChanged({ layerId, batchId: null })); + log.debug({ id, imageDTO }, 'ControlNet image processed'); + dispatch(caProcessedImageChanged({ id, imageDTO })); + dispatch(caProcessorPendingBatchIdChanged({ id, batchId: null })); } catch (error) { if (signal.aborted) { // The listener was canceled - we need to cancel the pending processor batch, if there is one (could have changed by now). - const pendingBatchId = getState() - .canvasV2.layers.filter(isControlAdapterLayer) - .find((l) => l.id === layerId)?.controlAdapter.processorPendingBatchId; + const pendingBatchId = selectCA(getState().canvasV2, id)?.processorPendingBatchId; if (pendingBatchId) { - cancelProcessorBatch(dispatch, layerId, pendingBatchId); + cancelProcessorBatch(dispatch, id, pendingBatchId); } log.trace('Control Adapter preprocessor cancelled'); } else { @@ -174,7 +164,7 @@ export const addControlAdapterPreprocessor = (startAppListening: AppStartListeni if (error instanceof Object) { if ('data' in error && 'status' in error) { if (error.status === 403) { - dispatch(controlAdapterImageChanged({ layerId, imageDTO: null })); + dispatch(caImageChanged({ id, imageDTO: null })); return; } } 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 deleted file mode 100644 index e52df30681..0000000000 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetAutoProcess.ts +++ /dev/null @@ -1,85 +0,0 @@ -import type { AnyListenerPredicate } from '@reduxjs/toolkit'; -import { logger } from 'app/logging/logger'; -import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; -import type { RootState } from 'app/store/store'; -import { controlAdapterImageProcessed } from 'features/controlAdapters/store/actions'; -import { - controlAdapterAutoConfigToggled, - controlAdapterImageChanged, - controlAdapterModelChanged, - controlAdapterProcessorParamsChanged, - controlAdapterProcessortTypeChanged, - selectControlAdapterById, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; - -type AnyControlAdapterParamChangeAction = - | ReturnType - | ReturnType - | ReturnType - | ReturnType - | ReturnType; - -const predicate: AnyListenerPredicate = (action, state, prevState) => { - const isActionMatched = - controlAdapterProcessorParamsChanged.match(action) || - controlAdapterModelChanged.match(action) || - controlAdapterImageChanged.match(action) || - controlAdapterProcessortTypeChanged.match(action) || - controlAdapterAutoConfigToggled.match(action); - - if (!isActionMatched) { - return false; - } - - const { id } = action.payload; - const prevCA = selectControlAdapterById(prevState.controlAdapters, id); - const ca = selectControlAdapterById(state.controlAdapters, id); - if (!prevCA || !isControlNetOrT2IAdapter(prevCA) || !ca || !isControlNetOrT2IAdapter(ca)) { - return false; - } - - if (controlAdapterAutoConfigToggled.match(action)) { - // do not process if the user just disabled auto-config - if (prevCA.shouldAutoConfig === true) { - return false; - } - } - - const { controlImage, processorType, shouldAutoConfig } = ca; - if (controlAdapterModelChanged.match(action) && !shouldAutoConfig) { - // do not process if the action is a model change but the processor settings are dirty - return false; - } - - const isProcessorSelected = processorType !== 'none'; - - const hasControlImage = Boolean(controlImage); - - return isProcessorSelected && hasControlImage; -}; - -const DEBOUNCE_MS = 300; - -/** - * Listener that automatically processes a ControlNet image when its processor parameters are changed. - * - * The network request is debounced. - */ -export const addControlNetAutoProcessListener = (startAppListening: AppStartListening) => { - startAppListening({ - predicate, - effect: async (action, { dispatch, cancelActiveListeners, delay }) => { - const log = logger('session'); - const { id } = (action as AnyControlAdapterParamChangeAction).payload; - - // Cancel any in-progress instances of this listener - cancelActiveListeners(); - log.trace('ControlNet auto-process triggered'); - // Delay before starting actual work - await delay(DEBOUNCE_MS); - - dispatch(controlAdapterImageProcessed({ id })); - }, - }); -}; 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 deleted file mode 100644 index 574dad00eb..0000000000 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { logger } from 'app/logging/logger'; -import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; -import { parseify } from 'common/util/serialize'; -import { controlAdapterImageProcessed } from 'features/controlAdapters/store/actions'; -import { - controlAdapterImageChanged, - controlAdapterProcessedImageChanged, - pendingControlImagesCleared, - selectControlAdapterById, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { toast } from 'features/toast/toast'; -import { t } from 'i18next'; -import { imagesApi } from 'services/api/endpoints/images'; -import { queueApi } from 'services/api/endpoints/queue'; -import type { BatchConfig, ImageDTO } from 'services/api/types'; -import { socketInvocationComplete } from 'services/events/actions'; - -export const addControlNetImageProcessedListener = (startAppListening: AppStartListening) => { - startAppListening({ - actionCreator: controlAdapterImageProcessed, - effect: async (action, { dispatch, getState, take }) => { - const log = logger('session'); - const { id } = action.payload; - const ca = selectControlAdapterById(getState().controlAdapters, id); - - if (!ca?.controlImage || !isControlNetOrT2IAdapter(ca)) { - log.error('Unable to process ControlNet image'); - return; - } - - if (ca.processorType === 'none' || ca.processorNode.type === 'none') { - return; - } - - // ControlNet one-off procressing graph is just the processor node, no edges. - // Also we need to grab the image. - - const nodeId = ca.processorNode.id; - const enqueueBatchArg: BatchConfig = { - prepend: true, - batch: { - graph: { - nodes: { - [ca.processorNode.id]: { - ...ca.processorNode, - is_intermediate: true, - use_cache: false, - image: { image_name: ca.controlImage }, - }, - }, - edges: [], - }, - runs: 1, - }, - }; - - try { - const req = dispatch( - queueApi.endpoints.enqueueBatch.initiate(enqueueBatchArg, { - fixedCacheKey: 'enqueueBatch', - }) - ); - const enqueueResult = await req.unwrap(); - req.reset(); - log.debug({ enqueueResult: parseify(enqueueResult) }, t('queue.graphQueued')); - - const [invocationCompleteAction] = await take( - (action): action is ReturnType => - socketInvocationComplete.match(action) && - action.payload.data.batch_id === enqueueResult.batch.batch_id && - action.payload.data.invocation_source_id === nodeId - ); - - // We still have to check the output type - if (invocationCompleteAction.payload.data.result.type === 'image_output') { - const { image_name } = invocationCompleteAction.payload.data.result.image; - - // Wait for the ImageDTO to be received - const [{ payload }] = await take( - (action) => - imagesApi.endpoints.getImageDTO.matchFulfilled(action) && action.payload.image_name === image_name - ); - - const processedControlImage = payload as ImageDTO; - - log.debug({ controlNetId: action.payload, processedControlImage }, 'ControlNet image processed'); - - // Update the processed image in the store - dispatch( - controlAdapterProcessedImageChanged({ - id, - processedControlImage: processedControlImage.image_name, - }) - ); - } - } catch (error) { - log.error({ enqueueBatchArg: parseify(enqueueBatchArg) }, t('queue.graphFailedToQueue')); - - if (error instanceof Object) { - if ('data' in error && 'status' in error) { - if (error.status === 403) { - dispatch(pendingControlImagesCleared()); - dispatch(controlAdapterImageChanged({ id, controlImage: null })); - return; - } - } - } - - toast({ - id: 'GRAPH_QUEUE_FAILED', - title: t('queue.graphFailedToQueue'), - status: 'error', - }); - } - }, - }); -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx deleted file mode 100644 index c13783cddd..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterConfig.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { Box, Flex, FormControl, FormLabel, Icon, IconButton, Switch } from '@invoke-ai/ui-library'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import ParamControlAdapterModel from 'features/controlAdapters/components/parameters/ParamControlAdapterModel'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterType } from 'features/controlAdapters/hooks/useControlAdapterType'; -import { - controlAdapterDuplicated, - controlAdapterIsEnabledChanged, - controlAdapterRemoved, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; -import { PiCaretUpBold, PiCopyBold, PiTrashSimpleBold } from 'react-icons/pi'; -import { useToggle } from 'react-use'; - -import ControlAdapterImagePreview from './ControlAdapterImagePreview'; -import ControlAdapterProcessorComponent from './ControlAdapterProcessorComponent'; -import ControlAdapterShouldAutoConfig from './ControlAdapterShouldAutoConfig'; -import ControlNetCanvasImageImports from './imports/ControlNetCanvasImageImports'; -import { ParamControlAdapterBeginEnd } from './parameters/ParamControlAdapterBeginEnd'; -import ParamControlAdapterControlMode from './parameters/ParamControlAdapterControlMode'; -import ParamControlAdapterIPMethod from './parameters/ParamControlAdapterIPMethod'; -import ParamControlAdapterProcessorSelect from './parameters/ParamControlAdapterProcessorSelect'; -import ParamControlAdapterResizeMode from './parameters/ParamControlAdapterResizeMode'; -import ParamControlAdapterWeight from './parameters/ParamControlAdapterWeight'; - -const ControlAdapterConfig = (props: { id: string; number: number }) => { - const { id, number } = props; - const controlAdapterType = useControlAdapterType(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const activeTabName = useAppSelector(activeTabNameSelector); - const isEnabled = useControlAdapterIsEnabled(id); - const [isExpanded, toggleIsExpanded] = useToggle(false); - - const handleDelete = useCallback(() => { - dispatch(controlAdapterRemoved({ id })); - }, [id, dispatch]); - - const handleDuplicate = useCallback(() => { - dispatch(controlAdapterDuplicated(id)); - }, [id, dispatch]); - - const handleToggleIsEnabled = useCallback( - (e: ChangeEvent) => { - dispatch( - controlAdapterIsEnabledChanged({ - id, - isEnabled: e.target.checked, - }) - ); - }, - [id, dispatch] - ); - - if (!controlAdapterType) { - return null; - } - - return ( - - - - {t(`controlnet.${controlAdapterType}`, { number })} - - - - - - - - {activeTabName === 'canvas' && } - } - /> - } - /> - - } - /> - - - - - - - - - - {!isExpanded && ( - - - - )} - - - - {isExpanded && ( - <> - - - - - - - - - - )} - - ); -}; - -export default memo(ControlAdapterConfig); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx deleted file mode 100644 index c8670470b2..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterImagePreview.tsx +++ /dev/null @@ -1,227 +0,0 @@ -import { Box, Flex, Spinner } from '@invoke-ai/ui-library'; -import { skipToken } from '@reduxjs/toolkit/query'; -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAIDndImage from 'common/components/IAIDndImage'; -import IAIDndImageIcon from 'common/components/IAIDndImageIcon'; -import { setBoundingBoxDimensions } from 'features/canvas/store/canvasSlice'; -import { useControlAdapterControlImage } from 'features/controlAdapters/hooks/useControlAdapterControlImage'; -import { useControlAdapterProcessedControlImage } from 'features/controlAdapters/hooks/useControlAdapterProcessedControlImage'; -import { useControlAdapterProcessorType } from 'features/controlAdapters/hooks/useControlAdapterProcessorType'; -import { - controlAdapterImageChanged, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { heightChanged, widthChanged } from 'features/controlLayers/store/canvasV2Slice'; -import type { TypesafeDraggableData, TypesafeDroppableData } from 'features/dnd/types'; -import { calculateNewSize } from 'features/parameters/components/ImageSize/calculateNewSize'; -import { selectOptimalDimension } from 'features/parameters/store/generationSlice'; -import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { memo, useCallback, useEffect, useMemo, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { PiArrowCounterClockwiseBold, PiFloppyDiskBold, PiRulerBold } from 'react-icons/pi'; -import { - useAddImageToBoardMutation, - useChangeImageIsIntermediateMutation, - useGetImageDTOQuery, - useRemoveImageFromBoardMutation, -} from 'services/api/endpoints/images'; -import type { PostUploadAction } from 'services/api/types'; - -type Props = { - id: string; - isSmall?: boolean; -}; - -const selectPendingControlImages = createMemoizedSelector( - selectControlAdaptersSlice, - (controlAdapters) => controlAdapters.pendingControlImages -); - -const ControlAdapterImagePreview = ({ isSmall, id }: Props) => { - const { t } = useTranslation(); - const dispatch = useAppDispatch(); - const controlImageName = useControlAdapterControlImage(id); - const processedControlImageName = useControlAdapterProcessedControlImage(id); - const processorType = useControlAdapterProcessorType(id); - const autoAddBoardId = useAppSelector((s) => s.gallery.autoAddBoardId); - const isConnected = useAppSelector((s) => s.system.isConnected); - const activeTabName = useAppSelector(activeTabNameSelector); - const optimalDimension = useAppSelector(selectOptimalDimension); - const pendingControlImages = useAppSelector(selectPendingControlImages); - - const [isMouseOverImage, setIsMouseOverImage] = useState(false); - - const { currentData: controlImage, isError: isErrorControlImage } = useGetImageDTOQuery( - controlImageName ?? skipToken - ); - - const { currentData: processedControlImage, isError: isErrorProcessedControlImage } = useGetImageDTOQuery( - processedControlImageName ?? skipToken - ); - - const [changeIsIntermediate] = useChangeImageIsIntermediateMutation(); - const [addToBoard] = useAddImageToBoardMutation(); - const [removeFromBoard] = useRemoveImageFromBoardMutation(); - const handleResetControlImage = useCallback(() => { - dispatch(controlAdapterImageChanged({ id, controlImage: null })); - }, [id, dispatch]); - - const handleSaveControlImage = useCallback(async () => { - if (!processedControlImage) { - return; - } - - await changeIsIntermediate({ - imageDTO: processedControlImage, - is_intermediate: false, - }).unwrap(); - - if (autoAddBoardId !== 'none') { - addToBoard({ - imageDTO: processedControlImage, - board_id: autoAddBoardId, - }); - } else { - removeFromBoard({ imageDTO: processedControlImage }); - } - }, [processedControlImage, changeIsIntermediate, autoAddBoardId, addToBoard, removeFromBoard]); - - const handleSetControlImageToDimensions = useCallback(() => { - if (!controlImage) { - return; - } - - if (activeTabName === 'canvas') { - dispatch(setBoundingBoxDimensions({ width: controlImage.width, height: controlImage.height }, optimalDimension)); - } else { - const options = { updateAspectRatio: true, clamp: true }; - const { width, height } = calculateNewSize( - controlImage.width / controlImage.height, - optimalDimension * optimalDimension - ); - dispatch(widthChanged({ width, ...options })); - dispatch(heightChanged({ height, ...options })); - } - }, [controlImage, activeTabName, dispatch, optimalDimension]); - - const handleMouseEnter = useCallback(() => { - setIsMouseOverImage(true); - }, []); - - const handleMouseLeave = useCallback(() => { - setIsMouseOverImage(false); - }, []); - - const draggableData = useMemo(() => { - if (controlImage) { - return { - id, - payloadType: 'IMAGE_DTO', - payload: { imageDTO: controlImage }, - }; - } - }, [controlImage, id]); - - const droppableData = useMemo( - () => ({ - id, - actionType: 'SET_CONTROL_ADAPTER_IMAGE', - context: { id }, - }), - [id] - ); - - const postUploadAction = useMemo(() => ({ type: 'SET_CONTROL_ADAPTER_IMAGE', id }), [id]); - - const shouldShowProcessedImage = - controlImage && - processedControlImage && - !isMouseOverImage && - !pendingControlImages.includes(id) && - processorType !== 'none'; - - useEffect(() => { - if (isConnected && (isErrorControlImage || isErrorProcessedControlImage)) { - handleResetControlImage(); - } - }, [handleResetControlImage, isConnected, isErrorControlImage, isErrorProcessedControlImage]); - - return ( - - - - - - - - {controlImage && ( - - } - tooltip={t('controlnet.resetControlImage')} - /> - } - tooltip={t('controlnet.saveControlImage')} - /> - } - tooltip={t('controlnet.setControlImageDimensions')} - /> - - )} - - {pendingControlImages.includes(id) && ( - - - - )} - - ); -}; - -export default memo(ControlAdapterImagePreview); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterProcessorComponent.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterProcessorComponent.tsx deleted file mode 100644 index 2e37d88e27..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterProcessorComponent.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterProcessorNode } from 'features/controlAdapters/hooks/useControlAdapterProcessorNode'; -import { memo } from 'react'; - -import CannyProcessor from './processors/CannyProcessor'; -import ColorMapProcessor from './processors/ColorMapProcessor'; -import ContentShuffleProcessor from './processors/ContentShuffleProcessor'; -import DepthAnyThingProcessor from './processors/DepthAnyThingProcessor'; -import DWOpenposeProcessor from './processors/DWOpenposeProcessor'; -import HedProcessor from './processors/HedProcessor'; -import LineartAnimeProcessor from './processors/LineartAnimeProcessor'; -import LineartProcessor from './processors/LineartProcessor'; -import MediapipeFaceProcessor from './processors/MediapipeFaceProcessor'; -import MidasDepthProcessor from './processors/MidasDepthProcessor'; -import MlsdImageProcessor from './processors/MlsdImageProcessor'; -import NormalBaeProcessor from './processors/NormalBaeProcessor'; -import PidiProcessor from './processors/PidiProcessor'; -import ZoeDepthProcessor from './processors/ZoeDepthProcessor'; - -type Props = { - id: string; -}; - -const ControlAdapterProcessorComponent = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const processorNode = useControlAdapterProcessorNode(id); - - if (!processorNode) { - return null; - } - - if (processorNode.type === 'canny_image_processor') { - return ; - } - - if (processorNode.type === 'color_map_image_processor') { - return ; - } - - if (processorNode.type === 'depth_anything_image_processor') { - return ; - } - - if (processorNode.type === 'hed_image_processor') { - return ; - } - - if (processorNode.type === 'lineart_image_processor') { - return ; - } - - if (processorNode.type === 'content_shuffle_image_processor') { - return ; - } - - if (processorNode.type === 'lineart_anime_image_processor') { - return ; - } - - if (processorNode.type === 'mediapipe_face_processor') { - return ; - } - - if (processorNode.type === 'midas_depth_image_processor') { - return ; - } - - if (processorNode.type === 'mlsd_image_processor') { - return ; - } - - if (processorNode.type === 'normalbae_image_processor') { - return ; - } - - if (processorNode.type === 'dw_openpose_image_processor') { - return ; - } - - if (processorNode.type === 'pidi_image_processor') { - return ; - } - - if (processorNode.type === 'zoe_depth_image_processor') { - return ; - } - - return null; -}; - -export default memo(ControlAdapterProcessorComponent); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterShouldAutoConfig.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterShouldAutoConfig.tsx deleted file mode 100644 index cb3d36c58d..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/ControlAdapterShouldAutoConfig.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterModel } from 'features/controlAdapters/hooks/useControlAdapterModel'; -import { useControlAdapterShouldAutoConfig } from 'features/controlAdapters/hooks/useControlAdapterShouldAutoConfig'; -import { controlAdapterAutoConfigToggled } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isNil } from 'lodash-es'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const ControlAdapterShouldAutoConfig = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const shouldAutoConfig = useControlAdapterShouldAutoConfig(id); - const { modelConfig } = useControlAdapterModel(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const handleShouldAutoConfigChanged = useCallback(() => { - dispatch(controlAdapterAutoConfigToggled({ id, modelConfig })); - }, [id, dispatch, modelConfig]); - - if (isNil(shouldAutoConfig)) { - return null; - } - - return ( - - {t('controlnet.autoConfigure')} - - - ); -}; - -export default memo(ControlAdapterShouldAutoConfig); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/hooks/useProcessorNodeChanged.ts b/invokeai/frontend/web/src/features/controlAdapters/components/hooks/useProcessorNodeChanged.ts deleted file mode 100644 index d76717cbf3..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/hooks/useProcessorNodeChanged.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { useAppDispatch } from 'app/store/storeHooks'; -import { controlAdapterProcessorParamsChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { ControlAdapterProcessorNode } from 'features/controlAdapters/store/types'; -import { useCallback } from 'react'; - -export const useProcessorNodeChanged = () => { - const dispatch = useAppDispatch(); - const handleProcessorNodeChanged = useCallback( - (id: string, params: Partial) => { - dispatch( - controlAdapterProcessorParamsChanged({ - id, - params, - }) - ); - }, - [dispatch] - ); - return handleProcessorNodeChanged; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/imports/ControlNetCanvasImageImports.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/imports/ControlNetCanvasImageImports.tsx deleted file mode 100644 index fada3e3abf..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/imports/ControlNetCanvasImageImports.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Flex, IconButton } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { canvasImageToControlAdapter, canvasMaskToControlAdapter } from 'features/canvas/store/actions'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; -import { PiExcludeBold, PiImageSquareBold } from 'react-icons/pi'; - -type ControlNetCanvasImageImportsProps = { - id: string; -}; - -const ControlNetCanvasImageImports = (props: ControlNetCanvasImageImportsProps) => { - const { id } = props; - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const handleImportImageFromCanvas = useCallback(() => { - dispatch(canvasImageToControlAdapter({ id })); - }, [id, dispatch]); - - const handleImportMaskFromCanvas = useCallback(() => { - dispatch(canvasMaskToControlAdapter({ id })); - }, [id, dispatch]); - - return ( - - } - tooltip={t('controlnet.importImageFromCanvas')} - aria-label={t('controlnet.importImageFromCanvas')} - onClick={handleImportImageFromCanvas} - /> - } - tooltip={t('controlnet.importMaskFromCanvas')} - aria-label={t('controlnet.importMaskFromCanvas')} - onClick={handleImportMaskFromCanvas} - /> - - ); -}; - -export default memo(ControlNetCanvasImageImports); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterBeginEnd.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterBeginEnd.tsx deleted file mode 100644 index 245c182b9f..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterBeginEnd.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { CompositeRangeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterBeginEndStepPct } from 'features/controlAdapters/hooks/useControlAdapterBeginEndStepPct'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { - controlAdapterBeginStepPctChanged, - controlAdapterEndStepPctChanged, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const formatPct = (v: number) => `${Math.round(v * 100)}%`; - -export const ParamControlAdapterBeginEnd = memo(({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const stepPcts = useControlAdapterBeginEndStepPct(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const onChange = useCallback( - (v: [number, number]) => { - dispatch( - controlAdapterBeginStepPctChanged({ - id, - beginStepPct: v[0], - }) - ); - dispatch( - controlAdapterEndStepPctChanged({ - id, - endStepPct: v[1], - }) - ); - }, - [dispatch, id] - ); - - const onReset = useCallback(() => { - dispatch( - controlAdapterBeginStepPctChanged({ - id, - beginStepPct: 0, - }) - ); - dispatch( - controlAdapterEndStepPctChanged({ - id, - endStepPct: 1, - }) - ); - }, [dispatch, id]); - - const value = useMemo<[number, number]>(() => [stepPcts?.beginStepPct ?? 0, stepPcts?.endStepPct ?? 1], [stepPcts]); - - if (!stepPcts) { - return null; - } - - return ( - - - {t('controlnet.beginEndStepPercent')} - - - - ); -}); - -ParamControlAdapterBeginEnd.displayName = 'ParamControlAdapterBeginEnd'; - -const ariaLabel = ['Begin Step %', 'End Step %']; diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterControlMode.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterControlMode.tsx deleted file mode 100644 index ea16d6bc1f..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterControlMode.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import type { ComboboxOnChange } from '@invoke-ai/ui-library'; -import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterControlMode } from 'features/controlAdapters/hooks/useControlAdapterControlMode'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { controlAdapterControlModeChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { ControlMode } from 'features/controlAdapters/store/types'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const ParamControlAdapterControlMode = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const controlMode = useControlAdapterControlMode(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const CONTROL_MODE_DATA = useMemo( - () => [ - { label: t('controlnet.balanced'), value: 'balanced' }, - { label: t('controlnet.prompt'), value: 'more_prompt' }, - { label: t('controlnet.control'), value: 'more_control' }, - { label: t('controlnet.megaControl'), value: 'unbalanced' }, - ], - [t] - ); - - const handleControlModeChange = useCallback( - (v) => { - if (!v) { - return; - } - dispatch( - controlAdapterControlModeChanged({ - id, - controlMode: v.value as ControlMode, - }) - ); - }, - [id, dispatch] - ); - - const value = useMemo( - () => CONTROL_MODE_DATA.filter((o) => o.value === controlMode)[0], - [CONTROL_MODE_DATA, controlMode] - ); - - if (!controlMode) { - return null; - } - - return ( - - - {t('controlnet.controlMode')} - - - - ); -}; - -export default memo(ParamControlAdapterControlMode); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx deleted file mode 100644 index c7aaa9f26c..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterIPMethod.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import type { ComboboxOnChange } from '@invoke-ai/ui-library'; -import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterIPMethod } from 'features/controlAdapters/hooks/useControlAdapterIPMethod'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { controlAdapterIPMethodChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { IPMethod } from 'features/controlAdapters/store/types'; -import { isIPMethod } from 'features/controlAdapters/store/types'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const ParamControlAdapterIPMethod = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const method = useControlAdapterIPMethod(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const options: { label: string; value: IPMethod }[] = useMemo( - () => [ - { label: t('controlnet.full'), value: 'full' }, - { label: `${t('controlnet.style')} (${t('common.beta')})`, value: 'style' }, - { label: `${t('controlnet.composition')} (${t('common.beta')})`, value: 'composition' }, - ], - [t] - ); - - const handleIPMethodChanged = useCallback( - (v) => { - if (!isIPMethod(v?.value)) { - return; - } - dispatch( - controlAdapterIPMethodChanged({ - id, - method: v.value, - }) - ); - }, - [id, dispatch] - ); - - const value = useMemo(() => options.find((o) => o.value === method), [options, method]); - - if (!method) { - return null; - } - - return ( - - - {t('controlnet.ipAdapterMethod')} - - - - ); -}; - -export default memo(ParamControlAdapterIPMethod); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx deleted file mode 100644 index 00c7d5859d..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterModel.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library'; -import { Combobox, Flex, FormControl, Tooltip } from '@invoke-ai/ui-library'; -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { useGroupedModelCombobox } from 'common/hooks/useGroupedModelCombobox'; -import { useControlAdapterCLIPVisionModel } from 'features/controlAdapters/hooks/useControlAdapterCLIPVisionModel'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterModel } from 'features/controlAdapters/hooks/useControlAdapterModel'; -import { useControlAdapterModels } from 'features/controlAdapters/hooks/useControlAdapterModels'; -import { useControlAdapterType } from 'features/controlAdapters/hooks/useControlAdapterType'; -import { - controlAdapterCLIPVisionModelChanged, - controlAdapterModelChanged, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { CLIPVisionModel } from 'features/controlAdapters/store/types'; -import { selectGenerationSlice } from 'features/parameters/store/generationSlice'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import type { - AnyModelConfig, - ControlNetModelConfig, - IPAdapterModelConfig, - T2IAdapterModelConfig, -} from 'services/api/types'; - -type ParamControlAdapterModelProps = { - id: string; -}; - -const selectMainModel = createMemoizedSelector(selectGenerationSlice, (generation) => generation.model); - -const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => { - const isEnabled = useControlAdapterIsEnabled(id); - const controlAdapterType = useControlAdapterType(id); - const { modelConfig } = useControlAdapterModel(id); - const dispatch = useAppDispatch(); - const currentBaseModel = useAppSelector((s) => s.generation.model?.base); - const currentCLIPVisionModel = useControlAdapterCLIPVisionModel(id); - const mainModel = useAppSelector(selectMainModel); - const { t } = useTranslation(); - - const [modelConfigs, { isLoading }] = useControlAdapterModels(controlAdapterType); - - const _onChange = useCallback( - (modelConfig: ControlNetModelConfig | IPAdapterModelConfig | T2IAdapterModelConfig | null) => { - if (!modelConfig) { - return; - } - dispatch( - controlAdapterModelChanged({ - id, - modelConfig, - }) - ); - }, - [dispatch, id] - ); - - const onCLIPVisionModelChange = useCallback( - (v) => { - if (!v?.value) { - return; - } - dispatch(controlAdapterCLIPVisionModelChanged({ id, clipVisionModel: v.value as CLIPVisionModel })); - }, - [dispatch, id] - ); - - const selectedModel = useMemo( - () => (modelConfig && controlAdapterType ? { ...modelConfig, model_type: controlAdapterType } : null), - [controlAdapterType, modelConfig] - ); - - const getIsDisabled = useCallback( - (model: AnyModelConfig): boolean => { - const isCompatible = currentBaseModel === model.base; - const hasMainModel = Boolean(currentBaseModel); - return !hasMainModel || !isCompatible; - }, - [currentBaseModel] - ); - - const { options, value, onChange, noOptionsMessage } = useGroupedModelCombobox({ - modelConfigs, - onChange: _onChange, - selectedModel, - getIsDisabled, - isLoading, - }); - - const clipVisionOptions = useMemo( - () => [ - { label: 'ViT-H', value: 'ViT-H' }, - { label: 'ViT-G', value: 'ViT-G' }, - ], - [] - ); - - const clipVisionModel = useMemo( - () => clipVisionOptions.find((o) => o.value === currentCLIPVisionModel), - [clipVisionOptions, currentCLIPVisionModel] - ); - - return ( - - - - - - - {modelConfig?.type === 'ip_adapter' && modelConfig.format === 'checkpoint' && ( - - - - )} - - ); -}; - -export default memo(ParamControlAdapterModel); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterProcessorSelect.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterProcessorSelect.tsx deleted file mode 100644 index 5257a47128..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterProcessorSelect.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui-library'; -import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterProcessorNode } from 'features/controlAdapters/hooks/useControlAdapterProcessorNode'; -import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants'; -import { controlAdapterProcessortTypeChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { ControlAdapterProcessorType } from 'features/controlAdapters/store/types'; -import { configSelector } from 'features/system/store/configSelectors'; -import { map } from 'lodash-es'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const selectOptions = createMemoizedSelector(configSelector, (config) => { - const options: ComboboxOption[] = map(CONTROLNET_PROCESSORS, (p) => ({ - value: p.type, - label: p.label, - })) - .sort((a, b) => - // sort 'none' to the top - a.value === 'none' ? -1 : b.value === 'none' ? 1 : a.label.localeCompare(b.label) - ) - .filter((d) => !config.sd.disabledControlNetProcessors.includes(d.value as ControlAdapterProcessorType)); - - return options; -}); - -const ParamControlAdapterProcessorSelect = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const processorNode = useControlAdapterProcessorNode(id); - const dispatch = useAppDispatch(); - const options = useAppSelector(selectOptions); - const { t } = useTranslation(); - - const onChange = useCallback( - (v) => { - if (!v) { - return; - } - dispatch( - controlAdapterProcessortTypeChanged({ - id, - processorType: v.value as ControlAdapterProcessorType, // TODO: need runtime check... - }) - ); - }, - [id, dispatch] - ); - const value = useMemo(() => options.find((o) => o.value === processorNode?.type), [options, processorNode]); - - if (!processorNode) { - return null; - } - return ( - - - {t('controlnet.processor')} - - - - ); -}; - -export default memo(ParamControlAdapterProcessorSelect); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterResizeMode.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterResizeMode.tsx deleted file mode 100644 index 58b8905f5a..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterResizeMode.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import type { ComboboxOnChange } from '@invoke-ai/ui-library'; -import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterResizeMode } from 'features/controlAdapters/hooks/useControlAdapterResizeMode'; -import { controlAdapterResizeModeChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import type { ResizeMode } from 'features/controlAdapters/store/types'; -import { isResizeMode } from 'features/controlAdapters/store/types'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -type Props = { - id: string; -}; - -const ParamControlAdapterResizeMode = ({ id }: Props) => { - const isEnabled = useControlAdapterIsEnabled(id); - const resizeMode = useControlAdapterResizeMode(id); - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const options: { label: string; value: ResizeMode }[] = useMemo( - () => [ - { label: t('controlnet.resize'), value: 'just_resize' }, - { label: t('controlnet.crop'), value: 'crop_resize' }, - { label: t('controlnet.fill'), value: 'fill_resize' }, - { label: t('controlnet.resizeSimple'), value: 'just_resize_simple' }, - ], - [t] - ); - - const handleResizeModeChange = useCallback( - (v) => { - if (!isResizeMode(v?.value)) { - return; - } - dispatch( - controlAdapterResizeModeChanged({ - id, - resizeMode: v.value, - }) - ); - }, - [id, dispatch] - ); - - const value = useMemo(() => options.find((o) => o.value === resizeMode), [options, resizeMode]); - - if (!resizeMode) { - return null; - } - - return ( - - - {t('controlnet.resizeMode')} - - - - ); -}; - -export default memo(ParamControlAdapterResizeMode); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterWeight.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterWeight.tsx deleted file mode 100644 index 7f45901f53..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/parameters/ParamControlAdapterWeight.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover'; -import { useControlAdapterIsEnabled } from 'features/controlAdapters/hooks/useControlAdapterIsEnabled'; -import { useControlAdapterWeight } from 'features/controlAdapters/hooks/useControlAdapterWeight'; -import { controlAdapterWeightChanged } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isNil } from 'lodash-es'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -type ParamControlAdapterWeightProps = { - id: string; -}; - -const formatValue = (v: number) => v.toFixed(2); - -const ParamControlAdapterWeight = ({ id }: ParamControlAdapterWeightProps) => { - const { t } = useTranslation(); - const dispatch = useAppDispatch(); - const isEnabled = useControlAdapterIsEnabled(id); - const weight = useControlAdapterWeight(id); - const initial = useAppSelector((s) => s.config.sd.ca.weight.initial); - const sliderMin = useAppSelector((s) => s.config.sd.ca.weight.sliderMin); - const sliderMax = useAppSelector((s) => s.config.sd.ca.weight.sliderMax); - const numberInputMin = useAppSelector((s) => s.config.sd.ca.weight.numberInputMin); - const numberInputMax = useAppSelector((s) => s.config.sd.ca.weight.numberInputMax); - const coarseStep = useAppSelector((s) => s.config.sd.ca.weight.coarseStep); - const fineStep = useAppSelector((s) => s.config.sd.ca.weight.fineStep); - - const onChange = useCallback( - (weight: number) => { - dispatch(controlAdapterWeightChanged({ id, weight })); - }, - [dispatch, id] - ); - - if (isNil(weight)) { - // should never happen - return null; - } - - return ( - - - {t('controlnet.weight')} - - - - - ); -}; - -export default memo(ParamControlAdapterWeight); - -const marks = [0, 1, 2]; diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/CannyProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/CannyProcessor.tsx deleted file mode 100644 index 0d547b9490..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/CannyProcessor.tsx +++ /dev/null @@ -1,129 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredCannyImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type CannyProcessorProps = { - controlNetId: string; - processorNode: RequiredCannyImageProcessorInvocation; - isEnabled: boolean; -}; - -const CannyProcessor = (props: CannyProcessorProps) => { - const { controlNetId, processorNode, isEnabled } = props; - const { low_threshold, high_threshold, image_resolution, detect_resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - const defaults = useGetDefaultForControlnetProcessor( - 'canny_image_processor' - ) as RequiredCannyImageProcessorInvocation; - - const handleLowThresholdChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { low_threshold: v }); - }, - [controlNetId, processorChanged] - ); - - const handleHighThresholdChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { high_threshold: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.lowThreshold')} - - - - - {t('controlnet.highThreshold')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.detectResolution')} - - - - - ); -}; - -export default memo(CannyProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ColorMapProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/ColorMapProcessor.tsx deleted file mode 100644 index 3dd6bf0aa9..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ColorMapProcessor.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredColorMapImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type ColorMapProcessorProps = { - controlNetId: string; - processorNode: RequiredColorMapImageProcessorInvocation; - isEnabled: boolean; -}; - -const ColorMapProcessor = (props: ColorMapProcessorProps) => { - const { controlNetId, processorNode, isEnabled } = props; - const { color_map_tile_size } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - const defaults = useGetDefaultForControlnetProcessor( - 'color_map_image_processor' - ) as RequiredColorMapImageProcessorInvocation; - - const handleColorMapTileSizeChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { color_map_tile_size: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.colorMapTileSize')} - - - - - ); -}; - -export default memo(ColorMapProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ContentShuffleProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/ContentShuffleProcessor.tsx deleted file mode 100644 index 9677a3a223..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ContentShuffleProcessor.tsx +++ /dev/null @@ -1,118 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredContentShuffleImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredContentShuffleImageProcessorInvocation; - isEnabled: boolean; -}; - -const ContentShuffleProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution, w, h, f } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'content_shuffle_image_processor' - ) as RequiredContentShuffleImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleWChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { w: v }); - }, - [controlNetId, processorChanged] - ); - - const handleHChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { h: v }); - }, - [controlNetId, processorChanged] - ); - - const handleFChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { f: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.w')} - - - - - {t('controlnet.h')} - - - - - {t('controlnet.f')} - - - - - ); -}; - -export default memo(ContentShuffleProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/DWOpenposeProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/DWOpenposeProcessor.tsx deleted file mode 100644 index 6761bfd4e1..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/DWOpenposeProcessor.tsx +++ /dev/null @@ -1,93 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredDWOpenposeImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredDWOpenposeImageProcessorInvocation; - isEnabled: boolean; -}; - -const DWOpenposeProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, draw_body, draw_face, draw_hands } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'dw_openpose_image_processor' - ) as RequiredDWOpenposeImageProcessorInvocation; - - const handleDrawBodyChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { draw_body: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - const handleDrawFaceChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { draw_face: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - const handleDrawHandsChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { draw_hands: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - - {t('controlnet.body')} - - - - {t('controlnet.face')} - - - - {t('controlnet.hands')} - - - - - {t('controlnet.imageResolution')} - - - - - ); -}; - -export default memo(DWOpenposeProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/DepthAnyThingProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/DepthAnyThingProcessor.tsx deleted file mode 100644 index 3f248a82be..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/DepthAnyThingProcessor.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import type { ComboboxOnChange } from '@invoke-ai/ui-library'; -import { Combobox, CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { - DepthAnythingModelSize, - RequiredDepthAnythingImageProcessorInvocation, -} from 'features/controlAdapters/store/types'; -import { isDepthAnythingModelSize } from 'features/controlAdapters/store/types'; -import { memo, useCallback, useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredDepthAnythingImageProcessorInvocation; - isEnabled: boolean; -}; - -const DepthAnythingProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { model_size, resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'midas_depth_image_processor' - ) as RequiredDepthAnythingImageProcessorInvocation; - - const handleModelSizeChange = useCallback( - (v) => { - if (!isDepthAnythingModelSize(v?.value)) { - return; - } - processorChanged(controlNetId, { - model_size: v.value, - }); - }, - [controlNetId, processorChanged] - ); - - const options: { label: string; value: DepthAnythingModelSize }[] = useMemo( - () => [ - { label: t('controlnet.depthAnythingSmallV2'), value: 'small_v2' }, - { label: t('controlnet.small'), value: 'small' }, - { label: t('controlnet.base'), value: 'base' }, - { label: t('controlnet.large'), value: 'large' }, - ], - [t] - ); - - const value = useMemo(() => options.filter((o) => o.value === model_size)[0], [options, model_size]); - - const handleResolutionChange = useCallback( - (v: number) => { - processorChanged(controlNetId, { resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleResolutionDefaultChange = useCallback(() => { - processorChanged(controlNetId, { resolution: 512 }); - }, [controlNetId, processorChanged]); - - return ( - - - {t('controlnet.modelSize')} - - - - {t('controlnet.imageResolution')} - - - - - ); -}; - -export default memo(DepthAnythingProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/HedProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/HedProcessor.tsx deleted file mode 100644 index e75d50de36..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/HedProcessor.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredHedImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type HedProcessorProps = { - controlNetId: string; - processorNode: RequiredHedImageProcessorInvocation; - isEnabled: boolean; -}; - -const HedPreprocessor = (props: HedProcessorProps) => { - const { - controlNetId, - processorNode: { detect_resolution, image_resolution, scribble }, - isEnabled, - } = props; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor('hed_image_processor') as RequiredHedImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleScribbleChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { scribble: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.scribble')} - - - - ); -}; - -export default memo(HedPreprocessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartAnimeProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartAnimeProcessor.tsx deleted file mode 100644 index 9849bda7c8..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartAnimeProcessor.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredLineartAnimeImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredLineartAnimeImageProcessorInvocation; - isEnabled: boolean; -}; - -const LineartAnimeProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'lineart_anime_image_processor' - ) as RequiredLineartAnimeImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - ); -}; - -export default memo(LineartAnimeProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartProcessor.tsx deleted file mode 100644 index 51d082eb57..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/LineartProcessor.tsx +++ /dev/null @@ -1,94 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredLineartImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type LineartProcessorProps = { - controlNetId: string; - processorNode: RequiredLineartImageProcessorInvocation; - isEnabled: boolean; -}; - -const LineartProcessor = (props: LineartProcessorProps) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution, coarse } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'lineart_image_processor' - ) as RequiredLineartImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleCoarseChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { coarse: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.coarse')} - - - - ); -}; - -export default memo(LineartProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MediapipeFaceProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/MediapipeFaceProcessor.tsx deleted file mode 100644 index de35d628d7..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MediapipeFaceProcessor.tsx +++ /dev/null @@ -1,134 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredMediapipeFaceProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredMediapipeFaceProcessorInvocation; - isEnabled: boolean; -}; - -const MediapipeFaceProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { max_faces, min_confidence, image_resolution, detect_resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'mediapipe_face_processor' - ) as RequiredMediapipeFaceProcessorInvocation; - - const handleMaxFacesChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { max_faces: v }); - }, - [controlNetId, processorChanged] - ); - - const handleMinConfidenceChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { min_confidence: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.maxFaces')} - - - - - {t('controlnet.minConfidence')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.detectResolution')} - - - - - ); -}; - -export default memo(MediapipeFaceProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MidasDepthProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/MidasDepthProcessor.tsx deleted file mode 100644 index f4089ed48f..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MidasDepthProcessor.tsx +++ /dev/null @@ -1,136 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredMidasDepthImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredMidasDepthImageProcessorInvocation; - isEnabled: boolean; -}; - -const MidasDepthProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { a_mult, bg_th, image_resolution, detect_resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'midas_depth_image_processor' - ) as RequiredMidasDepthImageProcessorInvocation; - - const handleAMultChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { a_mult: v }); - }, - [controlNetId, processorChanged] - ); - - const handleBgThChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { bg_th: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.amult')} - - - - - {t('controlnet.bgth')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.detectResolution')} - - - - - ); -}; - -export default memo(MidasDepthProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MlsdImageProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/MlsdImageProcessor.tsx deleted file mode 100644 index 69fd4f6807..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/MlsdImageProcessor.tsx +++ /dev/null @@ -1,137 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredMlsdImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredMlsdImageProcessorInvocation; - isEnabled: boolean; -}; - -const MlsdImageProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution, thr_d, thr_v } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor('mlsd_image_processor') as RequiredMlsdImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleThrDChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { thr_d: v }); - }, - [controlNetId, processorChanged] - ); - - const handleThrVChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { thr_v: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.w')} - - - - - {t('controlnet.h')} - - - - - ); -}; - -export default memo(MlsdImageProcessor); - -const marks0to4096 = [0, 4096]; -const marks0to1 = [0, 1]; diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/NormalBaeProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/NormalBaeProcessor.tsx deleted file mode 100644 index 43f7115df5..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/NormalBaeProcessor.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredNormalbaeImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredNormalbaeImageProcessorInvocation; - isEnabled: boolean; -}; - -const NormalBaeProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor( - 'normalbae_image_processor' - ) as RequiredNormalbaeImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - ); -}; - -export default memo(NormalBaeProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/PidiProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/PidiProcessor.tsx deleted file mode 100644 index 763069f769..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/PidiProcessor.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; -import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged'; -import { useGetDefaultForControlnetProcessor } from 'features/controlAdapters/hooks/useGetDefaultForControlnetProcessor'; -import type { RequiredPidiImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import type { ChangeEvent } from 'react'; -import { memo, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; - -import ProcessorWrapper from './common/ProcessorWrapper'; - -type Props = { - controlNetId: string; - processorNode: RequiredPidiImageProcessorInvocation; - isEnabled: boolean; -}; - -const PidiProcessor = (props: Props) => { - const { controlNetId, processorNode, isEnabled } = props; - const { image_resolution, detect_resolution, scribble, safe } = processorNode; - const processorChanged = useProcessorNodeChanged(); - const { t } = useTranslation(); - - const defaults = useGetDefaultForControlnetProcessor('pidi_image_processor') as RequiredPidiImageProcessorInvocation; - - const handleDetectResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { detect_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleImageResolutionChanged = useCallback( - (v: number) => { - processorChanged(controlNetId, { image_resolution: v }); - }, - [controlNetId, processorChanged] - ); - - const handleScribbleChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { scribble: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - const handleSafeChanged = useCallback( - (e: ChangeEvent) => { - processorChanged(controlNetId, { safe: e.target.checked }); - }, - [controlNetId, processorChanged] - ); - - return ( - - - {t('controlnet.detectResolution')} - - - - - {t('controlnet.imageResolution')} - - - - - {t('controlnet.scribble')} - - - - {t('controlnet.safe')} - - - - ); -}; - -export default memo(PidiProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ZoeDepthProcessor.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/ZoeDepthProcessor.tsx deleted file mode 100644 index 61897a5d27..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/ZoeDepthProcessor.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { RequiredZoeDepthImageProcessorInvocation } from 'features/controlAdapters/store/types'; -import { memo } from 'react'; - -type Props = { - controlNetId: string; - processorNode: RequiredZoeDepthImageProcessorInvocation; - isEnabled: boolean; -}; - -const ZoeDepthProcessor = (_props: Props) => { - // Has no parameters? - return null; -}; - -export default memo(ZoeDepthProcessor); diff --git a/invokeai/frontend/web/src/features/controlAdapters/components/processors/common/ProcessorWrapper.tsx b/invokeai/frontend/web/src/features/controlAdapters/components/processors/common/ProcessorWrapper.tsx deleted file mode 100644 index 0b99887b53..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/components/processors/common/ProcessorWrapper.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { Flex } from '@invoke-ai/ui-library'; -import type { PropsWithChildren } from 'react'; -import { memo } from 'react'; - -type Props = PropsWithChildren; - -const ProcessorWrapper = (props: Props) => { - return ( - - {props.children} - - ); -}; - -export default memo(ProcessorWrapper); diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useAddControlAdapter.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useAddControlAdapter.ts deleted file mode 100644 index 1af2fc81b9..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useAddControlAdapter.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { useControlAdapterModels } from 'features/controlAdapters/hooks/useControlAdapterModels'; -import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants'; -import { controlAdapterAdded } from 'features/controlAdapters/store/controlAdaptersSlice'; -import { type ControlAdapterType, isControlAdapterProcessorType } from 'features/controlAdapters/store/types'; -import { useCallback, useMemo } from 'react'; -import type { ControlNetModelConfig, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types'; - -export const useAddControlAdapter = (type: ControlAdapterType) => { - const baseModel = useAppSelector((s) => s.generation.model?.base); - const dispatch = useAppDispatch(); - - const [models] = useControlAdapterModels(type); - - const firstModel: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig | undefined = useMemo(() => { - // prefer to use a model that matches the base model - const firstCompatibleModel = models.filter((m) => (baseModel ? m.base === baseModel : true))[0]; - - if (firstCompatibleModel) { - return firstCompatibleModel; - } - - return models[0]; - }, [baseModel, models]); - - const isDisabled = useMemo(() => !firstModel, [firstModel]); - - const addControlAdapter = useCallback(() => { - if (isDisabled) { - return; - } - - if ( - (type === 'controlnet' || type === 't2i_adapter') && - (firstModel?.type === 'controlnet' || firstModel?.type === 't2i_adapter') - ) { - const defaultPreprocessor = firstModel.default_settings?.preprocessor; - const processorType = isControlAdapterProcessorType(defaultPreprocessor) ? defaultPreprocessor : 'none'; - const processorNode = CONTROLNET_PROCESSORS[processorType].buildDefaults(baseModel); - dispatch( - controlAdapterAdded({ - type, - overrides: { - model: firstModel, - processorType, - processorNode, - }, - }) - ); - return; - } - dispatch( - controlAdapterAdded({ - type, - overrides: { model: firstModel }, - }) - ); - }, [dispatch, firstModel, isDisabled, type, baseModel]); - - return [addControlAdapter, isDisabled] as const; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterBeginEndStepPct.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterBeginEndStepPct.ts deleted file mode 100644 index c9c99fcb2e..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterBeginEndStepPct.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterBeginEndStepPct = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const cn = selectControlAdapterById(controlAdapters, id); - return cn - ? { - beginStepPct: cn.beginStepPct, - endStepPct: cn.endStepPct, - } - : undefined; - }), - [id] - ); - - const stepPcts = useAppSelector(selector); - - return stepPcts; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterCLIPVisionModel.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterCLIPVisionModel.ts deleted file mode 100644 index 249d2022fe..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterCLIPVisionModel.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterCLIPVisionModel = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const cn = selectControlAdapterById(controlAdapters, id); - if (cn && cn?.type === 'ip_adapter') { - return cn.clipVisionModel; - } - }), - [id] - ); - - const clipVisionModel = useAppSelector(selector); - - return clipVisionModel; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlImage.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlImage.ts deleted file mode 100644 index c8efdf9125..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlImage.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterControlImage = (id: string) => { - const selector = useMemo( - () => - createSelector( - selectControlAdaptersSlice, - (controlAdapters) => selectControlAdapterById(controlAdapters, id)?.controlImage - ), - [id] - ); - - const controlImageName = useAppSelector(selector); - - return controlImageName; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlMode.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlMode.ts deleted file mode 100644 index 50ddd80156..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterControlMode.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNet } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterControlMode = (id: string) => { - const selector = useMemo( - () => - createSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - if (ca && isControlNet(ca)) { - return ca.controlMode; - } - return undefined; - }), - [id] - ); - - const controlMode = useAppSelector(selector); - - return controlMode; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIPMethod.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIPMethod.ts deleted file mode 100644 index a179899396..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIPMethod.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterIPMethod = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const cn = selectControlAdapterById(controlAdapters, id); - if (cn && cn?.type === 'ip_adapter') { - return cn.method; - } - }), - [id] - ); - - const method = useAppSelector(selector); - - return method; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIsEnabled.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIsEnabled.ts deleted file mode 100644 index 58bb956ce3..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterIsEnabled.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterIsEnabled = (id: string) => { - const selector = useMemo( - () => - createSelector( - selectControlAdaptersSlice, - (controlAdapters) => selectControlAdapterById(controlAdapters, id)?.isEnabled ?? false - ), - [id] - ); - - const isEnabled = useAppSelector(selector); - - return isEnabled; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModel.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModel.ts deleted file mode 100644 index 4de2aeac7f..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModel.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { skipToken } from '@reduxjs/toolkit/query'; -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; -import { useGetModelConfigWithTypeGuard } from 'services/api/hooks/useGetModelConfigWithTypeGuard'; -import { isControlAdapterModelConfig } from 'services/api/types'; - -export const useControlAdapterModel = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector( - selectControlAdaptersSlice, - (controlAdapters) => selectControlAdapterById(controlAdapters, id)?.model?.key - ), - [id] - ); - - const key = useAppSelector(selector); - - const result = useGetModelConfigWithTypeGuard(key ?? skipToken, isControlAdapterModelConfig); - - return result; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModels.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModels.ts deleted file mode 100644 index 4fe5ae7811..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterModels.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { ControlAdapterType } from 'features/controlAdapters/store/types'; -import { useControlNetModels, useIPAdapterModels, useT2IAdapterModels } from 'services/api/hooks/modelsByType'; - -export const useControlAdapterModels = (type: ControlAdapterType) => { - const controlNetModels = useControlNetModels(); - const t2iAdapterModels = useT2IAdapterModels(); - const ipAdapterModels = useIPAdapterModels(); - - if (type === 'controlnet') { - return controlNetModels; - } - if (type === 't2i_adapter') { - return t2iAdapterModels; - } - if (type === 'ip_adapter') { - return ipAdapterModels; - } - - // Assert that the end of the function is not reachable. - const exhaustiveCheck: never = type; - return exhaustiveCheck; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessedControlImage.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessedControlImage.ts deleted file mode 100644 index a02e1f9ed9..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessedControlImage.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterProcessedControlImage = (id: string) => { - const selector = useMemo( - () => - createSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - - return ca && isControlNetOrT2IAdapter(ca) ? ca.processedControlImage : undefined; - }), - [id] - ); - - const weight = useAppSelector(selector); - - return weight; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorNode.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorNode.ts deleted file mode 100644 index 272af132a6..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorNode.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterProcessorNode = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - - return ca && isControlNetOrT2IAdapter(ca) ? ca.processorNode : undefined; - }), - [id] - ); - - const processorNode = useAppSelector(selector); - - return processorNode; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorType.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorType.ts deleted file mode 100644 index 777bfc05b4..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterProcessorType.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterProcessorType = (id: string) => { - const selector = useMemo( - () => - createSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - - return ca && isControlNetOrT2IAdapter(ca) ? ca.processorType : undefined; - }), - [id] - ); - - const processorType = useAppSelector(selector); - - return processorType; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterResizeMode.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterResizeMode.ts deleted file mode 100644 index c6140bced7..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterResizeMode.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterResizeMode = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - if (ca && isControlNetOrT2IAdapter(ca)) { - return ca.resizeMode; - } - return undefined; - }), - [id] - ); - - const controlMode = useAppSelector(selector); - - return controlMode; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterShouldAutoConfig.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterShouldAutoConfig.ts deleted file mode 100644 index 07fbd2982c..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterShouldAutoConfig.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useControlAdapterShouldAutoConfig = (id: string) => { - const selector = useMemo( - () => - createSelector(selectControlAdaptersSlice, (controlAdapters) => { - const ca = selectControlAdapterById(controlAdapters, id); - if (ca && isControlNetOrT2IAdapter(ca)) { - return ca.shouldAutoConfig; - } - return undefined; - }), - [id] - ); - - const controlMode = useAppSelector(selector); - - return controlMode; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterType.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterType.ts deleted file mode 100644 index fe818f3287..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterType.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { createMemoizedSelector } from 'app/store/createMemoizedSelector'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; -import { assert } from 'tsafe'; - -export const useControlAdapterType = (id: string) => { - const selector = useMemo( - () => - createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { - const type = selectControlAdapterById(controlAdapters, id)?.type; - assert(type !== undefined, `Control adapter with id ${id} not found`); - return type; - }), - [id] - ); - - const type = useAppSelector(selector); - - return type; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterWeight.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterWeight.ts deleted file mode 100644 index 9e65993fde..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useControlAdapterWeight.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { createSelector } from '@reduxjs/toolkit'; -import { useAppSelector } from 'app/store/storeHooks'; -import { - selectControlAdapterById, - selectControlAdaptersSlice, -} from 'features/controlAdapters/store/controlAdaptersSlice'; -import { useMemo } from 'react'; - -export const useControlAdapterWeight = (id: string) => { - const selector = useMemo( - () => - createSelector( - selectControlAdaptersSlice, - (controlAdapters) => selectControlAdapterById(controlAdapters, id)?.weight - ), - [id] - ); - - const weight = useAppSelector(selector); - - return weight; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/hooks/useGetDefaultForControlnetProcessor.ts b/invokeai/frontend/web/src/features/controlAdapters/hooks/useGetDefaultForControlnetProcessor.ts deleted file mode 100644 index 99d2e0da8c..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/hooks/useGetDefaultForControlnetProcessor.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useAppSelector } from 'app/store/storeHooks'; -import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants'; -import type { ControlAdapterProcessorType } from 'features/controlAdapters/store/types'; -import { useMemo } from 'react'; - -export const useGetDefaultForControlnetProcessor = (processorType: ControlAdapterProcessorType) => { - const baseModel = useAppSelector((s) => s.generation.model?.base); - - const defaults = useMemo(() => { - return CONTROLNET_PROCESSORS[processorType].buildDefaults(baseModel); - }, [baseModel, processorType]); - - return defaults; -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/actions.ts b/invokeai/frontend/web/src/features/controlAdapters/store/actions.ts deleted file mode 100644 index 99ea84ed13..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/store/actions.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createAction } from '@reduxjs/toolkit'; - -export const controlAdapterImageProcessed = createAction<{ - id: string; -}>('controlAdapters/imageProcessed'); diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts b/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts deleted file mode 100644 index 1e01e5627e..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/store/constants.ts +++ /dev/null @@ -1,261 +0,0 @@ -import i18n from 'i18next'; -import type { BaseModelType } from 'services/api/types'; - -import type { ControlAdapterProcessorType, RequiredControlAdapterProcessorNode } from './types'; - -type ControlNetProcessorsDict = Record< - ControlAdapterProcessorType, - { - type: ControlAdapterProcessorType | 'none'; - label: string; - description: string; - buildDefaults(baseModel?: BaseModelType): RequiredControlAdapterProcessorNode | { type: 'none' }; - } ->; -/** - * A dict of ControlNet processors, including: - * - type - * - label - * - description - * - default values - * - * TODO: Generate from the OpenAPI schema - */ -export const CONTROLNET_PROCESSORS: ControlNetProcessorsDict = { - none: { - type: 'none', - get label() { - return i18n.t('controlnet.none'); - }, - get description() { - return i18n.t('controlnet.noneDescription'); - }, - buildDefaults: () => ({ - type: 'none', - }), - }, - canny_image_processor: { - type: 'canny_image_processor', - get label() { - return i18n.t('controlnet.canny'); - }, - get description() { - return i18n.t('controlnet.cannyDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'canny_image_processor', - type: 'canny_image_processor', - low_threshold: 100, - high_threshold: 200, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - color_map_image_processor: { - type: 'color_map_image_processor', - get label() { - return i18n.t('controlnet.colorMap'); - }, - get description() { - return i18n.t('controlnet.colorMapDescription'); - }, - buildDefaults: () => ({ - id: 'color_map_image_processor', - type: 'color_map_image_processor', - color_map_tile_size: 64, - }), - }, - content_shuffle_image_processor: { - type: 'content_shuffle_image_processor', - get label() { - return i18n.t('controlnet.contentShuffle'); - }, - get description() { - return i18n.t('controlnet.contentShuffleDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'content_shuffle_image_processor', - type: 'content_shuffle_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - h: baseModel === 'sdxl' ? 1024 : 512, - w: baseModel === 'sdxl' ? 1024 : 512, - f: baseModel === 'sdxl' ? 512 : 256, - }), - }, - depth_anything_image_processor: { - type: 'depth_anything_image_processor', - get label() { - return i18n.t('controlnet.depthAnything'); - }, - get description() { - return i18n.t('controlnet.depthAnythingDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'depth_anything_image_processor', - type: 'depth_anything_image_processor', - model_size: 'small_v2', - resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - hed_image_processor: { - type: 'hed_image_processor', - get label() { - return i18n.t('controlnet.hed'); - }, - get description() { - return i18n.t('controlnet.hedDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'hed_image_processor', - type: 'hed_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - scribble: false, - }), - }, - lineart_anime_image_processor: { - type: 'lineart_anime_image_processor', - get label() { - return i18n.t('controlnet.lineartAnime'); - }, - get description() { - return i18n.t('controlnet.lineartAnimeDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'lineart_anime_image_processor', - type: 'lineart_anime_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - lineart_image_processor: { - type: 'lineart_image_processor', - get label() { - return i18n.t('controlnet.lineart'); - }, - get description() { - return i18n.t('controlnet.lineartDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'lineart_image_processor', - type: 'lineart_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - coarse: false, - }), - }, - mediapipe_face_processor: { - type: 'mediapipe_face_processor', - get label() { - return i18n.t('controlnet.mediapipeFace'); - }, - get description() { - return i18n.t('controlnet.mediapipeFaceDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'mediapipe_face_processor', - type: 'mediapipe_face_processor', - max_faces: 1, - min_confidence: 0.5, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - midas_depth_image_processor: { - type: 'midas_depth_image_processor', - get label() { - return i18n.t('controlnet.depthMidas'); - }, - get description() { - return i18n.t('controlnet.depthMidasDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'midas_depth_image_processor', - type: 'midas_depth_image_processor', - a_mult: 2, - bg_th: 0.1, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - mlsd_image_processor: { - type: 'mlsd_image_processor', - get label() { - return i18n.t('controlnet.mlsd'); - }, - get description() { - return i18n.t('controlnet.mlsdDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'mlsd_image_processor', - type: 'mlsd_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - thr_d: 0.1, - thr_v: 0.1, - }), - }, - normalbae_image_processor: { - type: 'normalbae_image_processor', - get label() { - return i18n.t('controlnet.normalBae'); - }, - get description() { - return i18n.t('controlnet.normalBaeDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'normalbae_image_processor', - type: 'normalbae_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - }), - }, - dw_openpose_image_processor: { - type: 'dw_openpose_image_processor', - get label() { - return i18n.t('controlnet.dwOpenpose'); - }, - get description() { - return i18n.t('controlnet.dwOpenposeDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'dw_openpose_image_processor', - type: 'dw_openpose_image_processor', - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - draw_body: true, - draw_face: false, - draw_hands: false, - }), - }, - pidi_image_processor: { - type: 'pidi_image_processor', - get label() { - return i18n.t('controlnet.pidi'); - }, - get description() { - return i18n.t('controlnet.pidiDescription'); - }, - buildDefaults: (baseModel?: BaseModelType) => ({ - id: 'pidi_image_processor', - type: 'pidi_image_processor', - detect_resolution: baseModel === 'sdxl' ? 1024 : 512, - image_resolution: baseModel === 'sdxl' ? 1024 : 512, - scribble: false, - safe: false, - }), - }, - zoe_depth_image_processor: { - type: 'zoe_depth_image_processor', - get label() { - return i18n.t('controlnet.depthZoe'); - }, - get description() { - return i18n.t('controlnet.depthZoeDescription'); - }, - buildDefaults: () => ({ - id: 'zoe_depth_image_processor', - type: 'zoe_depth_image_processor', - }), - }, -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts b/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts deleted file mode 100644 index 8ec397f99c..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/store/controlAdaptersSlice.ts +++ /dev/null @@ -1,433 +0,0 @@ -import type { PayloadAction, Update } from '@reduxjs/toolkit'; -import { createEntityAdapter, createSlice } from '@reduxjs/toolkit'; -import { getSelectorsOptions } from 'app/store/createMemoizedSelector'; -import type { PersistConfig, RootState } from 'app/store/store'; -import { deepClone } from 'common/util/deepClone'; -import { buildControlAdapter } from 'features/controlAdapters/util/buildControlAdapter'; -import { buildControlAdapterProcessor } from 'features/controlAdapters/util/buildControlAdapterProcessor'; -import { zModelIdentifierField } from 'features/nodes/types/common'; -import { merge, uniq } from 'lodash-es'; -import type { ControlNetModelConfig, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types'; -import { socketInvocationError } from 'services/events/actions'; -import { v4 as uuidv4 } from 'uuid'; - -import { controlAdapterImageProcessed } from './actions'; -import { CONTROLNET_PROCESSORS } from './constants'; -import type { - CLIPVisionModel, - ControlAdapterConfig, - ControlAdapterProcessorType, - ControlAdaptersState, - ControlAdapterType, - ControlMode, - ControlNetConfig, - IPMethod, - RequiredControlAdapterProcessorNode, - ResizeMode, - T2IAdapterConfig, -} from './types'; -import { isControlNet, isControlNetOrT2IAdapter, isIPAdapter, isT2IAdapter } from './types'; - -const caAdapter = createEntityAdapter({ - selectId: (ca) => ca.id, -}); -const caAdapterSelectors = caAdapter.getSelectors(undefined, getSelectorsOptions); - -export const { - selectById: selectControlAdapterById, - selectAll: selectControlAdapterAll, - selectIds: selectControlAdapterIds, -} = caAdapterSelectors; - -const initialControlAdaptersState: ControlAdaptersState = caAdapter.getInitialState<{ - _version: 2; - pendingControlImages: string[]; -}>({ - _version: 2, - pendingControlImages: [], -}); - -export const selectAllControlNets = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters).filter(isControlNet); - -export const selectValidControlNets = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters) - .filter(isControlNet) - .filter( - (ca) => - ca.isEnabled && - ca.model && - (Boolean(ca.processedControlImage) || (ca.processorType === 'none' && Boolean(ca.controlImage))) - ); - -export const selectAllIPAdapters = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters).filter(isIPAdapter); - -export const selectValidIPAdapters = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters) - .filter(isIPAdapter) - .filter((ca) => ca.isEnabled && ca.model && Boolean(ca.controlImage)); - -export const selectAllT2IAdapters = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters).filter(isT2IAdapter); - -export const selectValidT2IAdapters = (controlAdapters: ControlAdaptersState) => - selectControlAdapterAll(controlAdapters) - .filter(isT2IAdapter) - .filter( - (ca) => - ca.isEnabled && - ca.model && - (Boolean(ca.processedControlImage) || (ca.processorType === 'none' && Boolean(ca.controlImage))) - ); - -export const controlAdaptersSlice = createSlice({ - name: 'controlAdapters', - initialState: initialControlAdaptersState, - reducers: { - controlAdapterAdded: { - reducer: ( - state, - action: PayloadAction<{ - id: string; - type: ControlAdapterType; - overrides?: Partial; - }> - ) => { - const { id, type, overrides } = action.payload; - caAdapter.addOne(state, buildControlAdapter(id, type, overrides)); - }, - prepare: ({ type, overrides }: { type: ControlAdapterType; overrides?: Partial }) => { - return { payload: { id: uuidv4(), type, overrides } }; - }, - }, - controlAdapterRecalled: (state, action: PayloadAction) => { - caAdapter.addOne(state, action.payload); - }, - controlAdapterDuplicated: { - reducer: ( - state, - action: PayloadAction<{ - id: string; - newId: string; - }> - ) => { - const { id, newId } = action.payload; - const controlAdapter = selectControlAdapterById(state, id); - if (!controlAdapter) { - return; - } - const newControlAdapter = merge(deepClone(controlAdapter), { - id: newId, - isEnabled: true, - }); - caAdapter.addOne(state, newControlAdapter); - }, - prepare: (id: string) => { - return { payload: { id, newId: uuidv4() } }; - }, - }, - controlAdapterRemoved: (state, action: PayloadAction<{ id: string }>) => { - caAdapter.removeOne(state, action.payload.id); - }, - controlAdapterIsEnabledChanged: (state, action: PayloadAction<{ id: string; isEnabled: boolean }>) => { - const { id, isEnabled } = action.payload; - caAdapter.updateOne(state, { id, changes: { isEnabled } }); - }, - controlAdapterImageChanged: ( - state, - action: PayloadAction<{ - id: string; - controlImage: string | null; - }> - ) => { - const { id, controlImage } = action.payload; - const ca = selectControlAdapterById(state, id); - if (!ca) { - return; - } - - caAdapter.updateOne(state, { - id, - changes: { controlImage, processedControlImage: null }, - }); - - if (controlImage !== null && isControlNetOrT2IAdapter(ca) && ca.processorType !== 'none') { - state.pendingControlImages.push(id); - } - }, - controlAdapterProcessedImageChanged: ( - state, - action: PayloadAction<{ - id: string; - processedControlImage: string | null; - }> - ) => { - const { id, processedControlImage } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn) { - return; - } - - if (!isControlNetOrT2IAdapter(cn)) { - return; - } - - caAdapter.updateOne(state, { - id, - changes: { - processedControlImage, - }, - }); - - state.pendingControlImages = state.pendingControlImages.filter((pendingId) => pendingId !== id); - }, - controlAdapterModelCleared: (state, action: PayloadAction<{ id: string }>) => { - caAdapter.updateOne(state, { - id: action.payload.id, - changes: { model: null }, - }); - }, - controlAdapterModelChanged: ( - state, - action: PayloadAction<{ - id: string; - modelConfig: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig; - }> - ) => { - const { id, modelConfig } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn) { - return; - } - - const model = zModelIdentifierField.parse(modelConfig); - - if (!isControlNetOrT2IAdapter(cn)) { - caAdapter.updateOne(state, { id, changes: { model } }); - return; - } - - const update: Update = { - id, - changes: { model, shouldAutoConfig: true }, - }; - - update.changes.processedControlImage = null; - - if (modelConfig.type === 'ip_adapter') { - // should never happen... - return; - } - - const processor = buildControlAdapterProcessor(modelConfig); - update.changes.processorType = processor.processorType; - update.changes.processorNode = processor.processorNode; - - caAdapter.updateOne(state, update); - }, - controlAdapterWeightChanged: (state, action: PayloadAction<{ id: string; weight: number }>) => { - const { id, weight } = action.payload; - caAdapter.updateOne(state, { id, changes: { weight } }); - }, - controlAdapterBeginStepPctChanged: (state, action: PayloadAction<{ id: string; beginStepPct: number }>) => { - const { id, beginStepPct } = action.payload; - caAdapter.updateOne(state, { id, changes: { beginStepPct } }); - }, - controlAdapterEndStepPctChanged: (state, action: PayloadAction<{ id: string; endStepPct: number }>) => { - const { id, endStepPct } = action.payload; - caAdapter.updateOne(state, { id, changes: { endStepPct } }); - }, - controlAdapterControlModeChanged: (state, action: PayloadAction<{ id: string; controlMode: ControlMode }>) => { - const { id, controlMode } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn || !isControlNet(cn)) { - return; - } - caAdapter.updateOne(state, { id, changes: { controlMode } }); - }, - controlAdapterIPMethodChanged: (state, action: PayloadAction<{ id: string; method: IPMethod }>) => { - const { id, method } = action.payload; - caAdapter.updateOne(state, { id, changes: { method } }); - }, - controlAdapterCLIPVisionModelChanged: ( - state, - action: PayloadAction<{ id: string; clipVisionModel: CLIPVisionModel }> - ) => { - const { id, clipVisionModel } = action.payload; - caAdapter.updateOne(state, { id, changes: { clipVisionModel } }); - }, - controlAdapterResizeModeChanged: ( - state, - action: PayloadAction<{ - id: string; - resizeMode: ResizeMode; - }> - ) => { - const { id, resizeMode } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn || !isControlNetOrT2IAdapter(cn)) { - return; - } - caAdapter.updateOne(state, { id, changes: { resizeMode } }); - }, - controlAdapterProcessorParamsChanged: ( - state, - action: PayloadAction<{ - id: string; - params: Partial; - }> - ) => { - const { id, params } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn || !isControlNetOrT2IAdapter(cn) || !cn.processorNode) { - return; - } - - const processorNode = merge(deepClone(cn.processorNode), params); - - caAdapter.updateOne(state, { - id, - changes: { - shouldAutoConfig: false, - processorNode, - }, - }); - }, - controlAdapterProcessortTypeChanged: ( - state, - action: PayloadAction<{ - id: string; - processorType: ControlAdapterProcessorType; - }> - ) => { - const { id, processorType } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn || !isControlNetOrT2IAdapter(cn)) { - return; - } - - const processorNode = deepClone( - CONTROLNET_PROCESSORS[processorType].buildDefaults(cn.model?.base) - ) as RequiredControlAdapterProcessorNode; - - caAdapter.updateOne(state, { - id, - changes: { - processorType, - processedControlImage: null, - processorNode, - shouldAutoConfig: false, - }, - }); - }, - controlAdapterAutoConfigToggled: ( - state, - action: PayloadAction<{ - id: string; - modelConfig?: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig; - }> - ) => { - const { id, modelConfig } = action.payload; - const cn = selectControlAdapterById(state, id); - if (!cn || !isControlNetOrT2IAdapter(cn) || modelConfig?.type === 'ip_adapter') { - return; - } - const update: Update = { - id, - changes: { shouldAutoConfig: !cn.shouldAutoConfig }, - }; - - if (update.changes.shouldAutoConfig && modelConfig) { - const processor = buildControlAdapterProcessor(modelConfig); - update.changes.processorType = processor.processorType; - update.changes.processorNode = processor.processorNode; - } - - caAdapter.updateOne(state, update); - }, - controlAdaptersReset: () => { - return deepClone(initialControlAdaptersState); - }, - pendingControlImagesCleared: (state) => { - state.pendingControlImages = []; - }, - ipAdaptersReset: (state) => { - selectAllIPAdapters(state).forEach((ca) => { - caAdapter.removeOne(state, ca.id); - }); - }, - controlNetsReset: (state) => { - selectAllControlNets(state).forEach((ca) => { - caAdapter.removeOne(state, ca.id); - }); - }, - t2iAdaptersReset: (state) => { - selectAllT2IAdapters(state).forEach((ca) => { - caAdapter.removeOne(state, ca.id); - }); - }, - }, - extraReducers: (builder) => { - builder.addCase(controlAdapterImageProcessed, (state, action) => { - const cn = selectControlAdapterById(state, action.payload.id); - if (!cn) { - return; - } - if (cn.controlImage !== null) { - state.pendingControlImages = uniq(state.pendingControlImages.concat(action.payload.id)); - } - }); - - builder.addCase(socketInvocationError, (state) => { - state.pendingControlImages = []; - }); - }, -}); - -export const { - controlAdapterAdded, - controlAdapterRecalled, - controlAdapterDuplicated, - controlAdapterRemoved, - controlAdapterImageChanged, - controlAdapterProcessedImageChanged, - controlAdapterIsEnabledChanged, - controlAdapterModelChanged, - controlAdapterCLIPVisionModelChanged, - controlAdapterIPMethodChanged, - controlAdapterWeightChanged, - controlAdapterBeginStepPctChanged, - controlAdapterEndStepPctChanged, - controlAdapterControlModeChanged, - controlAdapterResizeModeChanged, - controlAdapterProcessorParamsChanged, - controlAdapterProcessortTypeChanged, - controlAdaptersReset, - controlAdapterAutoConfigToggled, - pendingControlImagesCleared, - controlAdapterModelCleared, - ipAdaptersReset, - controlNetsReset, - t2iAdaptersReset, -} = controlAdaptersSlice.actions; - -export const selectControlAdaptersSlice = (state: RootState) => state.controlAdapters; - -/* eslint-disable-next-line @typescript-eslint/no-explicit-any */ -const migrateControlAdaptersState = (state: any): any => { - if (!('_version' in state)) { - state._version = 1; - } - if (state._version === 1) { - state = deepClone(initialControlAdaptersState); - } - return state; -}; - -export const controlAdaptersPersistConfig: PersistConfig = { - name: controlAdaptersSlice.name, - initialState: initialControlAdaptersState, - migrate: migrateControlAdaptersState, - persistDenylist: ['pendingControlImages'], -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts b/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts deleted file mode 100644 index 3bde8bc6c6..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/store/types.test.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { ControlAdapterProcessorType, zControlAdapterProcessorType } from 'features/controlAdapters/store/types'; -import type { Equals } from 'tsafe'; -import { assert } from 'tsafe'; -import { describe, test } from 'vitest'; -import type { z } from 'zod'; - -describe('Control Adapter Types', () => { - test('ControlAdapterProcessorType', () => - assert>>()); -}); diff --git a/invokeai/frontend/web/src/features/controlAdapters/store/types.ts b/invokeai/frontend/web/src/features/controlAdapters/store/types.ts deleted file mode 100644 index cceb3d594e..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/store/types.ts +++ /dev/null @@ -1,274 +0,0 @@ -import type { EntityState } from '@reduxjs/toolkit'; -import type { - ParameterControlNetModel, - ParameterIPAdapterModel, - ParameterT2IAdapterModel, -} from 'features/parameters/types/parameterSchemas'; -import type { components } from 'services/api/schema'; -import type { Invocation } from 'services/api/types'; -import type { O } from 'ts-toolbelt'; -import { z } from 'zod'; - -/** - * Any ControlNet processor node - */ -export type ControlAdapterProcessorNode = - | Invocation<'canny_image_processor'> - | Invocation<'color_map_image_processor'> - | Invocation<'content_shuffle_image_processor'> - | Invocation<'depth_anything_image_processor'> - | Invocation<'hed_image_processor'> - | Invocation<'lineart_anime_image_processor'> - | Invocation<'lineart_image_processor'> - | Invocation<'mediapipe_face_processor'> - | Invocation<'midas_depth_image_processor'> - | Invocation<'mlsd_image_processor'> - | Invocation<'normalbae_image_processor'> - | Invocation<'dw_openpose_image_processor'> - | Invocation<'pidi_image_processor'> - | Invocation<'zoe_depth_image_processor'>; - -/** - * Any ControlNet processor type - */ -export type ControlAdapterProcessorType = NonNullable; -export const zControlAdapterProcessorType = z.enum([ - 'canny_image_processor', - 'color_map_image_processor', - 'content_shuffle_image_processor', - 'depth_anything_image_processor', - 'hed_image_processor', - 'lineart_anime_image_processor', - 'lineart_image_processor', - 'mediapipe_face_processor', - 'midas_depth_image_processor', - 'mlsd_image_processor', - 'normalbae_image_processor', - 'dw_openpose_image_processor', - 'pidi_image_processor', - 'zoe_depth_image_processor', - 'none', -]); -export const isControlAdapterProcessorType = (v: unknown): v is ControlAdapterProcessorType => - zControlAdapterProcessorType.safeParse(v).success; - -/** - * The Canny processor node, with parameters flagged as required - */ -export type RequiredCannyImageProcessorInvocation = O.Required< - Invocation<'canny_image_processor'>, - 'type' | 'low_threshold' | 'high_threshold' | 'image_resolution' | 'detect_resolution' ->; - -/** - * The Color Map processor node, with parameters flagged as required - */ -export type RequiredColorMapImageProcessorInvocation = O.Required< - Invocation<'color_map_image_processor'>, - 'type' | 'color_map_tile_size' ->; - -/** - * The ContentShuffle processor node, with parameters flagged as required - */ -export type RequiredContentShuffleImageProcessorInvocation = O.Required< - Invocation<'content_shuffle_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' | 'w' | 'h' | 'f' ->; - -/** - * The DepthAnything processor node, with parameters flagged as required - */ -export type RequiredDepthAnythingImageProcessorInvocation = O.Required< - Invocation<'depth_anything_image_processor'>, - 'type' | 'model_size' | 'resolution' | 'offload' ->; - -const zDepthAnythingModelSize = z.enum(['large', 'base', 'small', 'small_v2']); -export type DepthAnythingModelSize = z.infer; -export const isDepthAnythingModelSize = (v: unknown): v is DepthAnythingModelSize => - zDepthAnythingModelSize.safeParse(v).success; - -/** - * The HED processor node, with parameters flagged as required - */ -export type RequiredHedImageProcessorInvocation = O.Required< - Invocation<'hed_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' | 'scribble' ->; - -/** - * The Lineart Anime processor node, with parameters flagged as required - */ -export type RequiredLineartAnimeImageProcessorInvocation = O.Required< - Invocation<'lineart_anime_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' ->; - -/** - * The Lineart processor node, with parameters flagged as required - */ -export type RequiredLineartImageProcessorInvocation = O.Required< - Invocation<'lineart_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' | 'coarse' ->; - -/** - * The MediapipeFace processor node, with parameters flagged as required - */ -export type RequiredMediapipeFaceProcessorInvocation = O.Required< - Invocation<'mediapipe_face_processor'>, - 'type' | 'max_faces' | 'min_confidence' | 'image_resolution' | 'detect_resolution' ->; - -/** - * The MidasDepth processor node, with parameters flagged as required - */ -export type RequiredMidasDepthImageProcessorInvocation = O.Required< - Invocation<'midas_depth_image_processor'>, - 'type' | 'a_mult' | 'bg_th' | 'image_resolution' | 'detect_resolution' ->; - -/** - * The MLSD processor node, with parameters flagged as required - */ -export type RequiredMlsdImageProcessorInvocation = O.Required< - Invocation<'mlsd_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' | 'thr_v' | 'thr_d' ->; - -/** - * The NormalBae processor node, with parameters flagged as required - */ -export type RequiredNormalbaeImageProcessorInvocation = O.Required< - Invocation<'normalbae_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' ->; - -/** - * The DW Openpose processor node, with parameters flagged as required - */ -export type RequiredDWOpenposeImageProcessorInvocation = O.Required< - Invocation<'dw_openpose_image_processor'>, - 'type' | 'image_resolution' | 'draw_body' | 'draw_face' | 'draw_hands' ->; - -/** - * The Pidi processor node, with parameters flagged as required - */ -export type RequiredPidiImageProcessorInvocation = O.Required< - Invocation<'pidi_image_processor'>, - 'type' | 'detect_resolution' | 'image_resolution' | 'safe' | 'scribble' ->; - -/** - * The ZoeDepth processor node, with parameters flagged as required - */ -export type RequiredZoeDepthImageProcessorInvocation = O.Required, 'type'>; - -/** - * Any ControlNet Processor node, with its parameters flagged as required - */ -export type RequiredControlAdapterProcessorNode = - | O.Required< - | RequiredCannyImageProcessorInvocation - | RequiredColorMapImageProcessorInvocation - | RequiredContentShuffleImageProcessorInvocation - | RequiredDepthAnythingImageProcessorInvocation - | RequiredHedImageProcessorInvocation - | RequiredLineartAnimeImageProcessorInvocation - | RequiredLineartImageProcessorInvocation - | RequiredMediapipeFaceProcessorInvocation - | RequiredMidasDepthImageProcessorInvocation - | RequiredMlsdImageProcessorInvocation - | RequiredNormalbaeImageProcessorInvocation - | RequiredDWOpenposeImageProcessorInvocation - | RequiredPidiImageProcessorInvocation - | RequiredZoeDepthImageProcessorInvocation, - 'id' - > - | { type: 'none' }; - -export type ControlMode = NonNullable; - -const zResizeMode = z.enum(['just_resize', 'crop_resize', 'fill_resize', 'just_resize_simple']); -export type ResizeMode = z.infer; -export const isResizeMode = (v: unknown): v is ResizeMode => zResizeMode.safeParse(v).success; - -const zIPMethod = z.enum(['full', 'style', 'composition']); -export type IPMethod = z.infer; -export const isIPMethod = (v: unknown): v is IPMethod => zIPMethod.safeParse(v).success; - -export type ControlNetConfig = { - type: 'controlnet'; - id: string; - isEnabled: boolean; - model: ParameterControlNetModel | null; - weight: number; - beginStepPct: number; - endStepPct: number; - controlMode: ControlMode; - resizeMode: ResizeMode; - controlImage: string | null; - processedControlImage: string | null; - processorType: ControlAdapterProcessorType; - processorNode: RequiredControlAdapterProcessorNode; - shouldAutoConfig: boolean; -}; - -export type T2IAdapterConfig = { - type: 't2i_adapter'; - id: string; - isEnabled: boolean; - model: ParameterT2IAdapterModel | null; - weight: number; - beginStepPct: number; - endStepPct: number; - resizeMode: ResizeMode; - controlImage: string | null; - processedControlImage: string | null; - processorType: ControlAdapterProcessorType; - processorNode: RequiredControlAdapterProcessorNode; - shouldAutoConfig: boolean; -}; - -export type CLIPVisionModel = 'ViT-H' | 'ViT-G'; - -export type IPAdapterConfig = { - type: 'ip_adapter'; - id: string; - isEnabled: boolean; - controlImage: string | null; - model: ParameterIPAdapterModel | null; - clipVisionModel: CLIPVisionModel; - weight: number; - method: IPMethod; - beginStepPct: number; - endStepPct: number; -}; - -export type ControlAdapterConfig = ControlNetConfig | IPAdapterConfig | T2IAdapterConfig; - -export type ControlAdapterType = ControlAdapterConfig['type']; - -export type ControlAdaptersState = EntityState & { - pendingControlImages: string[]; -}; - -export const isControlNet = (controlAdapter: ControlAdapterConfig): controlAdapter is ControlNetConfig => { - return controlAdapter.type === 'controlnet'; -}; - -export const isIPAdapter = (controlAdapter: ControlAdapterConfig): controlAdapter is IPAdapterConfig => { - return controlAdapter.type === 'ip_adapter'; -}; - -export const isT2IAdapter = (controlAdapter: ControlAdapterConfig): controlAdapter is T2IAdapterConfig => { - return controlAdapter.type === 't2i_adapter'; -}; - -export const isControlNetOrT2IAdapter = ( - controlAdapter: ControlAdapterConfig -): controlAdapter is ControlNetConfig | T2IAdapterConfig => { - return isControlNet(controlAdapter) || isT2IAdapter(controlAdapter); -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts b/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts deleted file mode 100644 index ad7bdba363..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapter.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { deepClone } from 'common/util/deepClone'; -import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants'; -import type { - ControlAdapterConfig, - ControlAdapterType, - ControlNetConfig, - IPAdapterConfig, - RequiredCannyImageProcessorInvocation, - T2IAdapterConfig, -} from 'features/controlAdapters/store/types'; -import { merge } from 'lodash-es'; - -export const initialControlNet: Omit = { - type: 'controlnet', - isEnabled: true, - model: null, - weight: 1, - beginStepPct: 0, - endStepPct: 1, - controlMode: 'balanced', - resizeMode: 'just_resize', - controlImage: null, - processedControlImage: null, - processorType: 'canny_image_processor', - processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, - shouldAutoConfig: true, -}; - -export const initialT2IAdapter: Omit = { - type: 't2i_adapter', - isEnabled: true, - model: null, - weight: 1, - beginStepPct: 0, - endStepPct: 1, - resizeMode: 'just_resize', - controlImage: null, - processedControlImage: null, - processorType: 'canny_image_processor', - processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, - shouldAutoConfig: true, -}; - -export const initialIPAdapter: Omit = { - type: 'ip_adapter', - isEnabled: true, - controlImage: null, - model: null, - method: 'full', - clipVisionModel: 'ViT-H', - weight: 1, - beginStepPct: 0, - endStepPct: 1, -}; - -export const buildControlAdapter = ( - id: string, - type: ControlAdapterType, - overrides: Partial = {} -): ControlAdapterConfig => { - switch (type) { - case 'controlnet': - return merge(deepClone(initialControlNet), { id, ...overrides }); - case 't2i_adapter': - return merge(deepClone(initialT2IAdapter), { id, ...overrides }); - case 'ip_adapter': - return merge(deepClone(initialIPAdapter), { id, ...overrides }); - default: - throw new Error(`Unknown control adapter type: ${type}`); - } -}; diff --git a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapterProcessor.ts b/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapterProcessor.ts deleted file mode 100644 index 63766b8e6e..0000000000 --- a/invokeai/frontend/web/src/features/controlAdapters/util/buildControlAdapterProcessor.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants'; -import { isControlAdapterProcessorType } from 'features/controlAdapters/store/types'; -import type { ControlNetModelConfig, T2IAdapterModelConfig } from 'services/api/types'; - -export const buildControlAdapterProcessor = (modelConfig: ControlNetModelConfig | T2IAdapterModelConfig) => { - const defaultPreprocessor = modelConfig.default_settings?.preprocessor; - const processorType = isControlAdapterProcessorType(defaultPreprocessor) ? defaultPreprocessor : 'none'; - const processorNode = CONTROLNET_PROCESSORS[processorType].buildDefaults(modelConfig.base); - - return { processorType, processorNode }; -};