Skip to content

Commit 4817dc7

Browse files
Add tile ControlNet model selection to upscale settings
Co-authored-by: kent <kent@invoke.ai>
1 parent 9066dc1 commit 4817dc7

File tree

3 files changed

+83
-1
lines changed

3 files changed

+83
-1
lines changed

invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/modelsLoaded.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { refImageModelChanged, selectRefImagesSlice } from 'features/controlLaye
1515
import { selectCanvasSlice } from 'features/controlLayers/store/selectors';
1616
import { getEntityIdentifier, isFLUXReduxConfig, isIPAdapterConfig } from 'features/controlLayers/store/types';
1717
import { modelSelected } from 'features/parameters/store/actions';
18-
import { postProcessingModelChanged, upscaleModelChanged } from 'features/parameters/store/upscaleSlice';
18+
import { postProcessingModelChanged, tileControlnetModelChanged, upscaleModelChanged } from 'features/parameters/store/upscaleSlice';
1919
import {
2020
zParameterCLIPEmbedModel,
2121
zParameterSpandrelImageToImageModel,
@@ -28,6 +28,7 @@ import type { AnyModelConfig } from 'services/api/types';
2828
import {
2929
isCLIPEmbedModelConfig,
3030
isControlLayerModelConfig,
31+
isControlNetModelConfig,
3132
isFluxReduxModelConfig,
3233
isFluxVAEModelConfig,
3334
isIPAdapterModelConfig,
@@ -71,6 +72,7 @@ export const addModelsLoadedListener = (startAppListening: AppStartListening) =>
7172
handleControlAdapterModels(models, state, dispatch, log);
7273
handlePostProcessingModel(models, state, dispatch, log);
7374
handleUpscaleModel(models, state, dispatch, log);
75+
handleTileControlNetModel(models, state, dispatch, log);
7476
handleIPAdapterModels(models, state, dispatch, log);
7577
handleT5EncoderModels(models, state, dispatch, log);
7678
handleCLIPEmbedModels(models, state, dispatch, log);
@@ -345,6 +347,46 @@ const handleUpscaleModel: ModelHandler = (models, state, dispatch, log) => {
345347
}
346348
};
347349

350+
const handleTileControlNetModel: ModelHandler = (models, state, dispatch, log) => {
351+
const selectedTileControlNetModel = state.upscale.tileControlnetModel;
352+
const controlNetModels = models.filter(isControlNetModelConfig);
353+
354+
// If the currently selected model is available, we don't need to do anything
355+
if (selectedTileControlNetModel && controlNetModels.some((m) => m.key === selectedTileControlNetModel.key)) {
356+
return;
357+
}
358+
359+
// Find a model with "Tile" in the name, case-insensitive
360+
const tileModel = controlNetModels.find((m) => m.name.toLowerCase().includes('tile'));
361+
362+
// If we have a tile model, select it
363+
if (tileModel) {
364+
log.debug(
365+
{ selectedTileControlNetModel, tileModel },
366+
'No selected tile ControlNet model or selected model is not available, selecting tile model'
367+
);
368+
dispatch(tileControlnetModelChanged(tileModel));
369+
return;
370+
}
371+
372+
// Otherwise, select the first available ControlNet model
373+
const firstModel = controlNetModels[0] || null;
374+
if (firstModel) {
375+
log.debug(
376+
{ selectedTileControlNetModel, firstModel },
377+
'No tile ControlNet model found, selecting first available ControlNet model'
378+
);
379+
dispatch(tileControlnetModelChanged(firstModel));
380+
return;
381+
}
382+
383+
// No available models, we should clear the selected model - but only if we have one selected
384+
if (selectedTileControlNetModel) {
385+
log.debug({ selectedTileControlNetModel }, 'Selected tile ControlNet model is not available, clearing');
386+
dispatch(tileControlnetModelChanged(null));
387+
}
388+
};
389+
348390
const handleT5EncoderModels: ModelHandler = (models, state, dispatch, log) => {
349391
const selectedT5EncoderModel = state.params.t5EncoderModel;
350392
const t5EncoderModels = models.filter((m) => isT5EncoderModelConfig(m));
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Combobox, FormControl, FormLabel } from '@invoke-ai/ui-library';
2+
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
3+
import { useModelCombobox } from 'common/hooks/useModelCombobox';
4+
import { selectTileControlNetModel, tileControlnetModelChanged } from 'features/parameters/store/upscaleSlice';
5+
import { memo, useCallback } from 'react';
6+
import { useTranslation } from 'react-i18next';
7+
import { useControlNetModels } from 'services/api/hooks/modelsByType';
8+
import type { ControlNetModelConfig } from 'services/api/types';
9+
10+
const ParamTileControlNetModel = () => {
11+
const dispatch = useAppDispatch();
12+
const { t } = useTranslation();
13+
const tileControlNetModel = useAppSelector(selectTileControlNetModel);
14+
const [modelConfigs, { isLoading }] = useControlNetModels();
15+
16+
const _onChange = useCallback(
17+
(controlNetModel: ControlNetModelConfig | null) => {
18+
dispatch(tileControlnetModelChanged(controlNetModel));
19+
},
20+
[dispatch]
21+
);
22+
23+
const { options, value, onChange, noOptionsMessage } = useModelCombobox({
24+
modelConfigs,
25+
onChange: _onChange,
26+
selectedModel: tileControlNetModel,
27+
isLoading,
28+
});
29+
30+
return (
31+
<FormControl isDisabled={!options.length} isInvalid={!options.length} minW={0} flexGrow={1} gap={2}>
32+
<FormLabel m={0}>{t('controlLayers.controlNet')}</FormLabel>
33+
<Combobox value={value} options={options} onChange={onChange} noOptionsMessage={noOptionsMessage} />
34+
</FormControl>
35+
);
36+
};
37+
38+
export default memo(ParamTileControlNetModel);

invokeai/frontend/web/src/features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleSettingsAccordion.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { roundDownToMultiple } from 'common/util/roundDownToMultiple';
55
import ParamCreativity from 'features/parameters/components/Upscale/ParamCreativity';
66
import ParamSpandrelModel from 'features/parameters/components/Upscale/ParamSpandrelModel';
77
import ParamStructure from 'features/parameters/components/Upscale/ParamStructure';
8+
import ParamTileControlNetModel from 'features/parameters/components/Upscale/ParamTileControlNetModel';
89
import { selectUpscaleSlice } from 'features/parameters/store/upscaleSlice';
910
import { getGridSize } from 'features/parameters/util/optimalDimension';
1011
import { UpscaleScaleSlider } from 'features/settingsAccordions/components/UpscaleSettingsAccordion/UpscaleScaleSlider';
@@ -70,6 +71,7 @@ export const UpscaleSettingsAccordion = memo(() => {
7071
</Flex>
7172
<Expander label={t('accordions.advanced.options')} isOpen={isOpenExpander} onToggle={onToggleExpander}>
7273
<Flex gap={4} pb={4} flexDir="column">
74+
<ParamTileControlNetModel />
7375
<ParamCreativity />
7476
<ParamStructure />
7577
</Flex>

0 commit comments

Comments
 (0)