tidy(ui): revert changes to old CA implementation

These changes were left over from the previous attempt to handle control adapters in control layers with the same logic. Control Layers are now handled totally separately, so these changes may be reverted.
This commit is contained in:
psychedelicious 2024-05-02 15:50:29 +10:00 committed by Kent Keirsey
parent 33a9f9a4dc
commit b1d8f3a3f9
15 changed files with 60 additions and 136 deletions

View File

@ -48,10 +48,12 @@ export const addCanvasImageToControlNetListener = (startAppListening: AppStartLi
}) })
).unwrap(); ).unwrap();
const { image_name } = imageDTO;
dispatch( dispatch(
controlAdapterImageChanged({ controlAdapterImageChanged({
id, id,
controlImage: imageDTO, controlImage: image_name,
}) })
); );
}, },

View File

@ -58,10 +58,12 @@ export const addCanvasMaskToControlNetListener = (startAppListening: AppStartLis
}) })
).unwrap(); ).unwrap();
const { image_name } = imageDTO;
dispatch( dispatch(
controlAdapterImageChanged({ controlAdapterImageChanged({
id, id,
controlImage: imageDTO, controlImage: image_name,
}) })
); );
}, },

View File

@ -12,7 +12,6 @@ import {
selectControlAdapterById, selectControlAdapterById,
} from 'features/controlAdapters/store/controlAdaptersSlice'; } from 'features/controlAdapters/store/controlAdaptersSlice';
import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types';
import { isEqual } from 'lodash-es';
type AnyControlAdapterParamChangeAction = type AnyControlAdapterParamChangeAction =
| ReturnType<typeof controlAdapterProcessorParamsChanged> | ReturnType<typeof controlAdapterProcessorParamsChanged>
@ -53,11 +52,6 @@ const predicate: AnyListenerPredicate<RootState> = (action, state, prevState) =>
return false; return false;
} }
if (prevCA.controlImage === ca.controlImage && isEqual(prevCA.processorNode, ca.processorNode)) {
// Don't re-process if the processor hasn't changed
return false;
}
const isProcessorSelected = processorType !== 'none'; const isProcessorSelected = processorType !== 'none';
const hasControlImage = Boolean(controlImage); const hasControlImage = Boolean(controlImage);

View File

@ -91,7 +91,7 @@ export const addControlNetImageProcessedListener = (startAppListening: AppStartL
dispatch( dispatch(
controlAdapterProcessedImageChanged({ controlAdapterProcessedImageChanged({
id, id,
processedControlImage, processedControlImage: processedControlImage.image_name,
}) })
); );
} }

View File

@ -76,7 +76,7 @@ export const addImageDroppedListener = (startAppListening: AppStartListening) =>
dispatch( dispatch(
controlAdapterImageChanged({ controlAdapterImageChanged({
id, id,
controlImage: activeData.payload.imageDTO, controlImage: activeData.payload.imageDTO.image_name,
}) })
); );
dispatch( dispatch(

View File

@ -101,7 +101,7 @@ export const addImageUploadedFulfilledListener = (startAppListening: AppStartLis
dispatch( dispatch(
controlAdapterImageChanged({ controlAdapterImageChanged({
id, id,
controlImage: imageDTO, controlImage: imageDTO.image_name,
}) })
); );
dispatch( dispatch(

View File

@ -1,7 +1,7 @@
import { logger } from 'app/logging/logger'; import { logger } from 'app/logging/logger';
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware'; import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
import { import {
controlAdapterModelChanged, controlAdapterIsEnabledChanged,
selectControlAdapterAll, selectControlAdapterAll,
} from 'features/controlAdapters/store/controlAdaptersSlice'; } from 'features/controlAdapters/store/controlAdaptersSlice';
import { loraRemoved } from 'features/lora/store/loraSlice'; import { loraRemoved } from 'features/lora/store/loraSlice';
@ -54,7 +54,7 @@ export const addModelSelectedListener = (startAppListening: AppStartListening) =
// handle incompatible controlnets // handle incompatible controlnets
selectControlAdapterAll(state.controlAdapters).forEach((ca) => { selectControlAdapterAll(state.controlAdapters).forEach((ca) => {
if (ca.model?.base !== newBaseModel) { if (ca.model?.base !== newBaseModel) {
dispatch(controlAdapterModelChanged({ id: ca.id, modelConfig: null })); dispatch(controlAdapterIsEnabledChanged({ id: ca.id, isEnabled: false }));
modelsCleared += 1; modelsCleared += 1;
} }
}); });

View File

@ -113,7 +113,7 @@ const ControlAdapterConfig = (props: { id: string; number: number }) => {
<Flex w="full" flexDir="column" gap={4}> <Flex w="full" flexDir="column" gap={4}>
<Flex gap={8} w="full" alignItems="center"> <Flex gap={8} w="full" alignItems="center">
<Flex flexDir="column" gap={4} h={controlAdapterType === 'ip_adapter' ? 40 : 32} w="full"> <Flex flexDir="column" gap={4} h={controlAdapterType === 'ip_adapter' ? 40 : 32} w="full">
{controlAdapterType === 'ip_adapter' && <ParamControlAdapterIPMethod id={id} />} <ParamControlAdapterIPMethod id={id} />
<ParamControlAdapterWeight id={id} /> <ParamControlAdapterWeight id={id} />
<ParamControlAdapterBeginEnd id={id} /> <ParamControlAdapterBeginEnd id={id} />
</Flex> </Flex>

View File

@ -46,9 +46,13 @@ const ParamControlAdapterIPMethod = ({ id }: Props) => {
const value = useMemo(() => options.find((o) => o.value === method), [options, method]); const value = useMemo(() => options.find((o) => o.value === method), [options, method]);
if (!method) {
return null;
}
return ( return (
<FormControl> <FormControl>
<InformationalPopover feature="ipAdapterMethod"> <InformationalPopover feature="controlNetResizeMode">
<FormLabel>{t('controlnet.ipAdapterMethod')}</FormLabel> <FormLabel>{t('controlnet.ipAdapterMethod')}</FormLabel>
</InformationalPopover> </InformationalPopover>
<Combobox value={value} options={options} isDisabled={!isEnabled} onChange={handleIPMethodChanged} /> <Combobox value={value} options={options} isDisabled={!isEnabled} onChange={handleIPMethodChanged} />

View File

@ -102,9 +102,13 @@ const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => {
); );
return ( return (
<Flex gap={4}> <Flex sx={{ gap: 2 }}>
<Tooltip label={selectedModel?.description}> <Tooltip label={selectedModel?.description}>
<FormControl isDisabled={!isEnabled} isInvalid={!value || mainModel?.base !== modelConfig?.base} w="full"> <FormControl
isDisabled={!isEnabled}
isInvalid={!value || mainModel?.base !== modelConfig?.base}
sx={{ width: '100%' }}
>
<Combobox <Combobox
options={options} options={options}
placeholder={t('controlnet.selectModel')} placeholder={t('controlnet.selectModel')}
@ -118,8 +122,7 @@ const ParamControlAdapterModel = ({ id }: ParamControlAdapterModelProps) => {
<FormControl <FormControl
isDisabled={!isEnabled} isDisabled={!isEnabled}
isInvalid={!value || mainModel?.base !== modelConfig?.base} isInvalid={!value || mainModel?.base !== modelConfig?.base}
width="max-content" sx={{ width: 'max-content', minWidth: 28 }}
minWidth={28}
> >
<Combobox <Combobox
options={clipVisionOptions} options={clipVisionOptions}

View File

@ -5,15 +5,15 @@ import {
selectControlAdaptersSlice, selectControlAdaptersSlice,
} from 'features/controlAdapters/store/controlAdaptersSlice'; } from 'features/controlAdapters/store/controlAdaptersSlice';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { assert } from 'tsafe';
export const useControlAdapterIPMethod = (id: string) => { export const useControlAdapterIPMethod = (id: string) => {
const selector = useMemo( const selector = useMemo(
() => () =>
createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => { createMemoizedSelector(selectControlAdaptersSlice, (controlAdapters) => {
const ca = selectControlAdapterById(controlAdapters, id); const cn = selectControlAdapterById(controlAdapters, id);
assert(ca?.type === 'ip_adapter'); if (cn && cn?.type === 'ip_adapter') {
return ca.method; return cn.method;
}
}), }),
[id] [id]
); );

View File

@ -7,7 +7,7 @@ import { buildControlAdapter } from 'features/controlAdapters/util/buildControlA
import { buildControlAdapterProcessor } from 'features/controlAdapters/util/buildControlAdapterProcessor'; import { buildControlAdapterProcessor } from 'features/controlAdapters/util/buildControlAdapterProcessor';
import { zModelIdentifierField } from 'features/nodes/types/common'; import { zModelIdentifierField } from 'features/nodes/types/common';
import { merge, uniq } from 'lodash-es'; import { merge, uniq } from 'lodash-es';
import type { ControlNetModelConfig, ImageDTO, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types'; import type { ControlNetModelConfig, IPAdapterModelConfig, T2IAdapterModelConfig } from 'services/api/types';
import { socketInvocationError } from 'services/events/actions'; import { socketInvocationError } from 'services/events/actions';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@ -134,46 +134,23 @@ export const controlAdaptersSlice = createSlice({
const { id, isEnabled } = action.payload; const { id, isEnabled } = action.payload;
caAdapter.updateOne(state, { id, changes: { isEnabled } }); caAdapter.updateOne(state, { id, changes: { isEnabled } });
}, },
controlAdapterImageChanged: (state, action: PayloadAction<{ id: string; controlImage: ImageDTO | null }>) => { controlAdapterImageChanged: (
state,
action: PayloadAction<{
id: string;
controlImage: string | null;
}>
) => {
const { id, controlImage } = action.payload; const { id, controlImage } = action.payload;
const ca = selectControlAdapterById(state, id); const ca = selectControlAdapterById(state, id);
if (!ca) { if (!ca) {
return; return;
} }
if (isControlNetOrT2IAdapter(ca)) { caAdapter.updateOne(state, {
if (controlImage) { id,
const { image_name, width, height } = controlImage; changes: { controlImage, processedControlImage: null },
const processorNode = deepClone(ca.processorNode); });
const minDim = Math.min(controlImage.width, controlImage.height);
if ('detect_resolution' in processorNode) {
processorNode.detect_resolution = minDim;
}
if ('image_resolution' in processorNode) {
processorNode.image_resolution = minDim;
}
if ('resolution' in processorNode) {
processorNode.resolution = minDim;
}
caAdapter.updateOne(state, {
id,
changes: {
processorNode,
controlImage: image_name,
controlImageDimensions: { width, height },
processedControlImage: null,
},
});
} else {
caAdapter.updateOne(state, {
id,
changes: { controlImage: null, controlImageDimensions: null, processedControlImage: null },
});
}
} else {
// ip adapter
caAdapter.updateOne(state, { id, changes: { controlImage: controlImage?.image_name ?? null } });
}
if (controlImage !== null && isControlNetOrT2IAdapter(ca) && ca.processorType !== 'none') { if (controlImage !== null && isControlNetOrT2IAdapter(ca) && ca.processorType !== 'none') {
state.pendingControlImages.push(id); state.pendingControlImages.push(id);
@ -183,7 +160,7 @@ export const controlAdaptersSlice = createSlice({
state, state,
action: PayloadAction<{ action: PayloadAction<{
id: string; id: string;
processedControlImage: ImageDTO | null; processedControlImage: string | null;
}> }>
) => { ) => {
const { id, processedControlImage } = action.payload; const { id, processedControlImage } = action.payload;
@ -196,24 +173,12 @@ export const controlAdaptersSlice = createSlice({
return; return;
} }
if (processedControlImage) { caAdapter.updateOne(state, {
const { image_name, width, height } = processedControlImage; id,
caAdapter.updateOne(state, { changes: {
id, processedControlImage,
changes: { },
processedControlImage: image_name, });
processedControlImageDimensions: { width, height },
},
});
} else {
caAdapter.updateOne(state, {
id,
changes: {
processedControlImage: null,
processedControlImageDimensions: null,
},
});
}
state.pendingControlImages = state.pendingControlImages.filter((pendingId) => pendingId !== id); state.pendingControlImages = state.pendingControlImages.filter((pendingId) => pendingId !== id);
}, },
@ -227,7 +192,7 @@ export const controlAdaptersSlice = createSlice({
state, state,
action: PayloadAction<{ action: PayloadAction<{
id: string; id: string;
modelConfig: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig | null; modelConfig: ControlNetModelConfig | T2IAdapterModelConfig | IPAdapterModelConfig;
}> }>
) => { ) => {
const { id, modelConfig } = action.payload; const { id, modelConfig } = action.payload;
@ -236,11 +201,6 @@ export const controlAdaptersSlice = createSlice({
return; return;
} }
if (modelConfig === null) {
caAdapter.updateOne(state, { id, changes: { model: null } });
return;
}
const model = zModelIdentifierField.parse(modelConfig); const model = zModelIdentifierField.parse(modelConfig);
if (!isControlNetOrT2IAdapter(cn)) { if (!isControlNetOrT2IAdapter(cn)) {
@ -248,36 +208,22 @@ export const controlAdaptersSlice = createSlice({
return; return;
} }
const update: Update<ControlNetConfig | T2IAdapterConfig, string> = {
id,
changes: { model, shouldAutoConfig: true },
};
update.changes.processedControlImage = null;
if (modelConfig.type === 'ip_adapter') { if (modelConfig.type === 'ip_adapter') {
// should never happen... // should never happen...
return; return;
} }
// We always update the model
const update: Update<ControlNetConfig | T2IAdapterConfig, string> = { id, changes: { model } };
// Build the default processor for this model
const processor = buildControlAdapterProcessor(modelConfig); const processor = buildControlAdapterProcessor(modelConfig);
if (processor.processorType !== cn.processorNode.type) { update.changes.processorType = processor.processorType;
// If the processor type has changed, update the processor node update.changes.processorNode = processor.processorNode;
update.changes.shouldAutoConfig = true;
update.changes.processedControlImage = null;
update.changes.processorType = processor.processorType;
update.changes.processorNode = processor.processorNode;
if (cn.controlImageDimensions) {
const minDim = Math.min(cn.controlImageDimensions.width, cn.controlImageDimensions.height);
if ('detect_resolution' in update.changes.processorNode) {
update.changes.processorNode.detect_resolution = minDim;
}
if ('image_resolution' in update.changes.processorNode) {
update.changes.processorNode.image_resolution = minDim;
}
if ('resolution' in update.changes.processorNode) {
update.changes.processorNode.resolution = minDim;
}
}
}
caAdapter.updateOne(state, update); caAdapter.updateOne(state, update);
}, },
controlAdapterWeightChanged: (state, action: PayloadAction<{ id: string; weight: number }>) => { controlAdapterWeightChanged: (state, action: PayloadAction<{ id: string; weight: number }>) => {
@ -394,23 +340,8 @@ export const controlAdaptersSlice = createSlice({
if (update.changes.shouldAutoConfig && modelConfig) { if (update.changes.shouldAutoConfig && modelConfig) {
const processor = buildControlAdapterProcessor(modelConfig); const processor = buildControlAdapterProcessor(modelConfig);
if (processor.processorType !== cn.processorNode.type) { update.changes.processorType = processor.processorType;
update.changes.processorType = processor.processorType; update.changes.processorNode = processor.processorNode;
update.changes.processorNode = processor.processorNode;
// Copy image resolution settings, urgh
if (cn.controlImageDimensions) {
const minDim = Math.min(cn.controlImageDimensions.width, cn.controlImageDimensions.height);
if ('detect_resolution' in update.changes.processorNode) {
update.changes.processorNode.detect_resolution = minDim;
}
if ('image_resolution' in update.changes.processorNode) {
update.changes.processorNode.image_resolution = minDim;
}
if ('resolution' in update.changes.processorNode) {
update.changes.processorNode.resolution = minDim;
}
}
}
} }
caAdapter.updateOne(state, update); caAdapter.updateOne(state, update);

View File

@ -225,9 +225,7 @@ export type ControlNetConfig = {
controlMode: ControlMode; controlMode: ControlMode;
resizeMode: ResizeMode; resizeMode: ResizeMode;
controlImage: string | null; controlImage: string | null;
controlImageDimensions: { width: number; height: number } | null;
processedControlImage: string | null; processedControlImage: string | null;
processedControlImageDimensions: { width: number; height: number } | null;
processorType: ControlAdapterProcessorType; processorType: ControlAdapterProcessorType;
processorNode: RequiredControlAdapterProcessorNode; processorNode: RequiredControlAdapterProcessorNode;
shouldAutoConfig: boolean; shouldAutoConfig: boolean;
@ -243,9 +241,7 @@ export type T2IAdapterConfig = {
endStepPct: number; endStepPct: number;
resizeMode: ResizeMode; resizeMode: ResizeMode;
controlImage: string | null; controlImage: string | null;
controlImageDimensions: { width: number; height: number } | null;
processedControlImage: string | null; processedControlImage: string | null;
processedControlImageDimensions: { width: number; height: number } | null;
processorType: ControlAdapterProcessorType; processorType: ControlAdapterProcessorType;
processorNode: RequiredControlAdapterProcessorNode; processorNode: RequiredControlAdapterProcessorNode;
shouldAutoConfig: boolean; shouldAutoConfig: boolean;

View File

@ -20,9 +20,7 @@ export const initialControlNet: Omit<ControlNetConfig, 'id'> = {
controlMode: 'balanced', controlMode: 'balanced',
resizeMode: 'just_resize', resizeMode: 'just_resize',
controlImage: null, controlImage: null,
controlImageDimensions: null,
processedControlImage: null, processedControlImage: null,
processedControlImageDimensions: null,
processorType: 'canny_image_processor', processorType: 'canny_image_processor',
processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation,
shouldAutoConfig: true, shouldAutoConfig: true,
@ -37,9 +35,7 @@ export const initialT2IAdapter: Omit<T2IAdapterConfig, 'id'> = {
endStepPct: 1, endStepPct: 1,
resizeMode: 'just_resize', resizeMode: 'just_resize',
controlImage: null, controlImage: null,
controlImageDimensions: null,
processedControlImage: null, processedControlImage: null,
processedControlImageDimensions: null,
processorType: 'canny_image_processor', processorType: 'canny_image_processor',
processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation, processorNode: CONTROLNET_PROCESSORS.canny_image_processor.buildDefaults() as RequiredCannyImageProcessorInvocation,
shouldAutoConfig: true, shouldAutoConfig: true,

View File

@ -286,9 +286,7 @@ const parseControlNet: MetadataParseFunc<ControlNetConfigMetadata> = async (meta
controlMode: control_mode ?? initialControlNet.controlMode, controlMode: control_mode ?? initialControlNet.controlMode,
resizeMode: resize_mode ?? initialControlNet.resizeMode, resizeMode: resize_mode ?? initialControlNet.resizeMode,
controlImage: image?.image_name ?? null, controlImage: image?.image_name ?? null,
controlImageDimensions: null,
processedControlImage: processedImage?.image_name ?? null, processedControlImage: processedImage?.image_name ?? null,
processedControlImageDimensions: null,
processorType, processorType,
processorNode, processorNode,
shouldAutoConfig: true, shouldAutoConfig: true,
@ -352,11 +350,9 @@ const parseT2IAdapter: MetadataParseFunc<T2IAdapterConfigMetadata> = async (meta
endStepPct: end_step_percent ?? initialT2IAdapter.endStepPct, endStepPct: end_step_percent ?? initialT2IAdapter.endStepPct,
resizeMode: resize_mode ?? initialT2IAdapter.resizeMode, resizeMode: resize_mode ?? initialT2IAdapter.resizeMode,
controlImage: image?.image_name ?? null, controlImage: image?.image_name ?? null,
controlImageDimensions: null,
processedControlImage: processedImage?.image_name ?? null, processedControlImage: processedImage?.image_name ?? null,
processedControlImageDimensions: null,
processorNode,
processorType, processorType,
processorNode,
shouldAutoConfig: true, shouldAutoConfig: true,
id: uuidv4(), id: uuidv4(),
}; };