From 424a27eedab95a0464657a73c38941e0d15d634a Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Wed, 1 May 2024 16:04:05 +1000 Subject: [PATCH] refactor(ui): add CA processor config components (wip) --- .../components/CALayer/CALayerConfig.tsx | 4 +- .../components/CALayer/CALayerProcessor.tsx | 95 +++++++++++++++++++ .../CALayer/processors/CannyProcessor.tsx | 67 +++++++++++++ .../CALayer/processors/ColorMapProcessor.tsx | 47 +++++++++ .../processors/ContentShuffleProcessor.tsx | 79 +++++++++++++++ .../processors/DWOpenposeProcessor.tsx | 62 ++++++++++++ .../processors/DepthAnythingProcessor.tsx | 52 ++++++++++ .../CALayer/processors/HedProcessor.tsx | 32 +++++++ .../CALayer/processors/LineartProcessor.tsx | 32 +++++++ .../processors/MediapipeFaceProcessor.tsx | 73 ++++++++++++++ .../processors/MidasDepthProcessor.tsx | 76 +++++++++++++++ .../CALayer/processors/MlsdImageProcessor.tsx | 76 +++++++++++++++ .../CALayer/processors/PidiProcessor.tsx | 43 +++++++++ .../CALayer/processors/ProcessorWrapper.tsx | 15 +++ .../components/CALayer/processors/types.ts | 6 ++ .../controlLayers/store/controlLayersSlice.ts | 2 +- .../util/controlAdapters.test.ts | 11 ++- 17 files changed, 768 insertions(+), 4 deletions(-) create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/CannyProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ColorMapProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ContentShuffleProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DWOpenposeProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DepthAnythingProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/HedProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/LineartProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MediapipeFaceProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MidasDepthProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MlsdImageProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/PidiProcessor.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ProcessorWrapper.tsx create mode 100644 invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/types.ts diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerConfig.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerConfig.tsx index 024ffe791b..7627fe4364 100644 --- a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerConfig.tsx +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerConfig.tsx @@ -1,6 +1,5 @@ import { Box, Flex, Icon, IconButton } from '@invoke-ai/ui-library'; import { useAppSelector } from 'app/store/storeHooks'; -import ControlAdapterProcessorComponent from 'features/controlAdapters/components/ControlAdapterProcessorComponent'; import { CALayerModelCombobox } from 'features/controlLayers/components/CALayer/CALayerModelCombobox'; import { selectCALayer } from 'features/controlLayers/store/controlLayersSlice'; import { memo } from 'react'; @@ -11,6 +10,7 @@ import { useToggle } from 'react-use'; import { CALayerBeginEndStepPct } from './CALayerBeginEndStepPct'; import { CALayerControlMode } from './CALayerControlMode'; import { CALayerImagePreview } from './CALayerImagePreview'; +import { CALayerProcessor } from './CALayerProcessor'; import { CALayerProcessorCombobox } from './CALayerProcessorCombobox'; import { CALayerWeight } from './CALayerWeight'; @@ -60,7 +60,7 @@ export const CALayerConfig = memo(({ layerId }: Props) => { {isExpanded && ( <> - + )} diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerProcessor.tsx new file mode 100644 index 0000000000..05271010ba --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/CALayerProcessor.tsx @@ -0,0 +1,95 @@ +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import { caLayerProcessorConfigChanged, selectCALayer } from 'features/controlLayers/store/controlLayersSlice'; +import type { ProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } 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 { LineartProcessor } from './processors/LineartProcessor'; +import { MediapipeFaceProcessor } from './processors/MediapipeFaceProcessor'; +import { MidasDepthProcessor } from './processors/MidasDepthProcessor'; +import { MlsdImageProcessor } from './processors/MlsdImageProcessor'; +import { PidiProcessor } from './processors/PidiProcessor'; + +type Props = { + layerId: string; +}; + +export const CALayerProcessor = memo(({ layerId }: Props) => { + const dispatch = useAppDispatch(); + const config = useAppSelector((s) => selectCALayer(s.controlLayers.present, layerId).controlAdapter.processorConfig); + const onChange = useCallback( + (processorConfig: ProcessorConfig) => { + dispatch(caLayerProcessorConfigChanged({ layerId, processorConfig })); + }, + [dispatch, layerId] + ); + + if (!config) { + return null; + } + + if (config.type === 'canny_image_processor') { + return ; + } + + if (config.type === 'color_map_image_processor') { + return ; + } + + if (config.type === 'depth_anything_image_processor') { + return ; + } + + if (config.type === 'hed_image_processor') { + return ; + } + + if (config.type === 'lineart_image_processor') { + return ; + } + + if (config.type === 'content_shuffle_image_processor') { + return ; + } + + if (config.type === 'lineart_anime_image_processor') { + // No configurable options for this processor + return null; + } + + if (config.type === 'mediapipe_face_processor') { + return ; + } + + if (config.type === 'midas_depth_image_processor') { + return ; + } + + if (config.type === 'mlsd_image_processor') { + return ; + } + + if (config.type === 'normalbae_image_processor') { + // No configurable options for this processor + return null; + } + + if (config.type === 'dw_openpose_image_processor') { + return ; + } + + if (config.type === 'pidi_image_processor') { + return ; + } + + if (config.type === 'zoe_depth_image_processor') { + return null; + } +}); + +CALayerProcessor.displayName = 'CALayerProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/CannyProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/CannyProcessor.tsx new file mode 100644 index 0000000000..5ae1e2cc0e --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/CannyProcessor.tsx @@ -0,0 +1,67 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import { type CannyProcessorConfig, CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['canny_image_processor'].buildDefaults(); + +export const CannyProcessor = ({ onChange, config }: Props) => { + const { t } = useTranslation(); + const handleLowThresholdChanged = useCallback( + (v: number) => { + onChange({ ...config, low_threshold: v }); + }, + [onChange, config] + ); + const handleHighThresholdChanged = useCallback( + (v: number) => { + onChange({ ...config, high_threshold: v }); + }, + [onChange, config] + ); + + return ( + + + {t('controlnet.lowThreshold')} + + + + + {t('controlnet.highThreshold')} + + + + + ); +}; + +CannyProcessor.displayName = 'CannyProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ColorMapProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ColorMapProcessor.tsx new file mode 100644 index 0000000000..e867ecfe12 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ColorMapProcessor.tsx @@ -0,0 +1,47 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import { type ColorMapProcessorConfig, CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['color_map_image_processor'].buildDefaults(); + +export const ColorMapProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + const handleColorMapTileSizeChanged = useCallback( + (v: number) => { + onChange({ ...config, color_map_tile_size: v }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.colorMapTileSize')} + + + + + ); +}); + +ColorMapProcessor.displayName = 'ColorMapProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ContentShuffleProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ContentShuffleProcessor.tsx new file mode 100644 index 0000000000..19c75045b4 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ContentShuffleProcessor.tsx @@ -0,0 +1,79 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { ContentShuffleProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['content_shuffle_image_processor'].buildDefaults(); + +export const ContentShuffleProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleWChanged = useCallback( + (v: number) => { + onChange({ ...config, w: v }); + }, + [config, onChange] + ); + + const handleHChanged = useCallback( + (v: number) => { + onChange({ ...config, h: v }); + }, + [config, onChange] + ); + + const handleFChanged = useCallback( + (v: number) => { + onChange({ ...config, f: v }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.w')} + + + + + {t('controlnet.h')} + + + + + {t('controlnet.f')} + + + + + ); +}); + +ContentShuffleProcessor.displayName = 'ContentShuffleProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DWOpenposeProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DWOpenposeProcessor.tsx new file mode 100644 index 0000000000..4d6776a913 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DWOpenposeProcessor.tsx @@ -0,0 +1,62 @@ +import { Flex, FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { DWOpenposeProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import type { ChangeEvent } from 'react'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['dw_openpose_image_processor'].buildDefaults(); + +export const DWOpenposeProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleDrawBodyChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, draw_body: e.target.checked }); + }, + [config, onChange] + ); + + const handleDrawFaceChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, draw_face: e.target.checked }); + }, + [config, onChange] + ); + + const handleDrawHandsChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, draw_hands: e.target.checked }); + }, + [config, onChange] + ); + + return ( + + + + {t('controlnet.body')} + + + + {t('controlnet.face')} + + + + {t('controlnet.hands')} + + + + + ); +}); + +DWOpenposeProcessor.displayName = 'DWOpenposeProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DepthAnythingProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DepthAnythingProcessor.tsx new file mode 100644 index 0000000000..90c8b32e69 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/DepthAnythingProcessor.tsx @@ -0,0 +1,52 @@ +import type { ComboboxOnChange } from '@invoke-ai/ui-library'; +import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { DepthAnythingModelSize, DepthAnythingProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { CONTROLNET_PROCESSORS, isDepthAnythingModelSize } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback, useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['depth_anything_image_processor'].buildDefaults(); + +export const DepthAnythingProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + const handleModelSizeChange = useCallback( + (v) => { + if (!isDepthAnythingModelSize(v?.value)) { + return; + } + onChange({ ...config, model_size: v.value }); + }, + [config, onChange] + ); + + const options: { label: string; value: DepthAnythingModelSize }[] = useMemo( + () => [ + { 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 === config.model_size)[0], [options, config.model_size]); + + return ( + + + {t('controlnet.modelSize')} + + + + ); +}); + +DepthAnythingProcessor.displayName = 'DepthAnythingProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/HedProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/HedProcessor.tsx new file mode 100644 index 0000000000..3708287450 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/HedProcessor.tsx @@ -0,0 +1,32 @@ +import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { HedProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import type { ChangeEvent } from 'react'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; + +export const HedProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleScribbleChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, scribble: e.target.checked }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.scribble')} + + + + ); +}); + +HedProcessor.displayName = 'HedProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/LineartProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/LineartProcessor.tsx new file mode 100644 index 0000000000..ef18e9d61f --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/LineartProcessor.tsx @@ -0,0 +1,32 @@ +import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { LineartProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import type { ChangeEvent } from 'react'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; + +export const LineartProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleCoarseChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, coarse: e.target.checked }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.coarse')} + + + + ); +}); + +LineartProcessor.displayName = 'LineartProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MediapipeFaceProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MediapipeFaceProcessor.tsx new file mode 100644 index 0000000000..e3d67f91bb --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MediapipeFaceProcessor.tsx @@ -0,0 +1,73 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import { CONTROLNET_PROCESSORS, type MediapipeFaceProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['mediapipe_face_processor'].buildDefaults(); + +export const MediapipeFaceProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleMaxFacesChanged = useCallback( + (v: number) => { + onChange({ ...config, max_faces: v }); + }, + [config, onChange] + ); + + const handleMinConfidenceChanged = useCallback( + (v: number) => { + onChange({ ...config, min_confidence: v }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.maxFaces')} + + + + + {t('controlnet.minConfidence')} + + + + + ); +}); + +MediapipeFaceProcessor.displayName = 'MediapipeFaceProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MidasDepthProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MidasDepthProcessor.tsx new file mode 100644 index 0000000000..36f008d6be --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MidasDepthProcessor.tsx @@ -0,0 +1,76 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { MidasDepthProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['midas_depth_image_processor'].buildDefaults(); + +export const MidasDepthProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleAMultChanged = useCallback( + (v: number) => { + onChange({ ...config, a_mult: v }); + }, + [config, onChange] + ); + + const handleBgThChanged = useCallback( + (v: number) => { + onChange({ ...config, bg_th: v }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.amult')} + + + + + {t('controlnet.bgth')} + + + + + ); +}); + +MidasDepthProcessor.displayName = 'MidasDepthProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MlsdImageProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MlsdImageProcessor.tsx new file mode 100644 index 0000000000..69dc1ce4d9 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/MlsdImageProcessor.tsx @@ -0,0 +1,76 @@ +import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { MlsdProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import { CONTROLNET_PROCESSORS } from 'features/controlLayers/util/controlAdapters'; +import { memo, useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; +const DEFAULTS = CONTROLNET_PROCESSORS['mlsd_image_processor'].buildDefaults(); + +export const MlsdImageProcessor = memo(({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleThrDChanged = useCallback( + (v: number) => { + onChange({ ...config, thr_d: v }); + }, + [config, onChange] + ); + + const handleThrVChanged = useCallback( + (v: number) => { + onChange({ ...config, thr_v: v }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.w')} + + + + + {t('controlnet.h')} + + + + + ); +}); + +MlsdImageProcessor.displayName = 'MlsdImageProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/PidiProcessor.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/PidiProcessor.tsx new file mode 100644 index 0000000000..e4c894ef45 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/PidiProcessor.tsx @@ -0,0 +1,43 @@ +import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library'; +import type { ProcessorComponentProps } from 'features/controlLayers/components/CALayer/processors/types'; +import type { PidiProcessorConfig } from 'features/controlLayers/util/controlAdapters'; +import type { ChangeEvent } from 'react'; +import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; + +import ProcessorWrapper from './ProcessorWrapper'; + +type Props = ProcessorComponentProps; + +export const PidiProcessor = ({ onChange, config }: Props) => { + const { t } = useTranslation(); + + const handleScribbleChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, scribble: e.target.checked }); + }, + [config, onChange] + ); + + const handleSafeChanged = useCallback( + (e: ChangeEvent) => { + onChange({ ...config, safe: e.target.checked }); + }, + [config, onChange] + ); + + return ( + + + {t('controlnet.scribble')} + + + + {t('controlnet.safe')} + + + + ); +}; + +PidiProcessor.displayName = 'PidiProcessor'; diff --git a/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ProcessorWrapper.tsx b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ProcessorWrapper.tsx new file mode 100644 index 0000000000..0b99887b53 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/ProcessorWrapper.tsx @@ -0,0 +1,15 @@ +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/controlLayers/components/CALayer/processors/types.ts b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/types.ts new file mode 100644 index 0000000000..48a0942678 --- /dev/null +++ b/invokeai/frontend/web/src/features/controlLayers/components/CALayer/processors/types.ts @@ -0,0 +1,6 @@ +import type { ProcessorConfig } from 'features/controlLayers/util/controlAdapters'; + +export type ProcessorComponentProps = { + onChange: (config: T) => void; + config: T; +}; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts b/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts index f8c55b7223..8ea3bb5bee 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/controlLayersSlice.ts @@ -240,7 +240,7 @@ export const controlLayersSlice = createSlice({ layer.bboxNeedsUpdate = true; layer.isEnabled = true; layer.controlAdapter.image = imageDTO ? imageDTOToImageWithDims(imageDTO) : null; - layer.controlAdapter.processedImage = null; + layer.controlAdapter.processedImage = null; }, caLayerProcessedImageChanged: (state, action: PayloadAction<{ layerId: string; imageDTO: ImageDTO | null }>) => { const { layerId, imageDTO } = action.payload; diff --git a/invokeai/frontend/web/src/features/controlLayers/util/controlAdapters.test.ts b/invokeai/frontend/web/src/features/controlLayers/util/controlAdapters.test.ts index b8ef50f4c7..656b759faa 100644 --- a/invokeai/frontend/web/src/features/controlLayers/util/controlAdapters.test.ts +++ b/invokeai/frontend/web/src/features/controlLayers/util/controlAdapters.test.ts @@ -3,7 +3,14 @@ import type { Equals } from 'tsafe'; import { assert } from 'tsafe'; import { describe, test } from 'vitest'; -import type { CLIPVisionModel, ControlMode, IPMethod, ProcessorConfig, ProcessorType } from './controlAdapters'; +import type { + CLIPVisionModel, + ControlMode, + DepthAnythingModelSize, + IPMethod, + ProcessorConfig, + ProcessorType, +} from './controlAdapters'; describe('Control Adapter Types', () => { test('ProcessorType', () => assert>()); @@ -11,4 +18,6 @@ describe('Control Adapter Types', () => { test('CLIP Vision Model', () => assert, CLIPVisionModel>>()); test('Control Mode', () => assert, ControlMode>>()); + test('DepthAnything Model Size', () => + assert, DepthAnythingModelSize>>()); });