diff --git a/invokeai/frontend/web/src/features/controlLayers/konva/naming.ts b/invokeai/frontend/web/src/features/controlLayers/konva/naming.ts deleted file mode 100644 index a60e8456dc..0000000000 --- a/invokeai/frontend/web/src/features/controlLayers/konva/naming.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * This file contains IDs, names, and ID getters for konva layers and objects. - */ - -// Getters for non-singleton layer and object IDs -export const getRGId = (entityId: string) => `region_${entityId}`; -export const getLayerId = (entityId: string) => `layer_${entityId}`; -export const getBrushLineId = (entityId: string, lineId: string, isBuffer?: boolean) => - `${isBuffer ? 'buffer_' : ''}brush_line_${lineId}`; -export const getEraserLineId = (entityId: string, lineId: string, isBuffer?: boolean) => - `${isBuffer ? 'buffer_' : ''}eraser_line_${lineId}`; -export const getRectShapeId = (entityId: string, rectId: string, isBuffer?: boolean) => - `${isBuffer ? 'buffer_' : ''}rect_${rectId}`; -export const getImageObjectId = (entityId: string, imageId: string) => `image_${imageId}`; -export const getCAId = (entityId: string) => `control_adapter_${entityId}`; -export const getIPAId = (entityId: string) => `ip_adapter_${entityId}`; diff --git a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts index 801ccbe4aa..b2529e9712 100644 --- a/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts +++ b/invokeai/frontend/web/src/features/controlLayers/store/canvasV2Slice.ts @@ -463,11 +463,11 @@ export const { bboxSizeOptimized, // Raster layers rasterLayerAdded, - rasterLayerRecalled, + // rasterLayerRecalled, rasterLayerConvertedToControlLayer, // Control layers controlLayerAdded, - controlLayerRecalled, + // controlLayerRecalled, controlLayerConvertedToRasterLayer, controlLayerModelChanged, controlLayerControlModeChanged, @@ -476,7 +476,7 @@ export const { controlLayerWithTransparencyEffectToggled, // IP Adapters ipaAdded, - ipaRecalled, + // ipaRecalled, ipaImageChanged, ipaMethodChanged, ipaModelChanged, @@ -485,7 +485,7 @@ export const { ipaBeginEndStepPctChanged, // Regions rgAdded, - rgRecalled, + // rgRecalled, rgPositivePromptChanged, rgNegativePromptChanged, rgFillColorChanged, @@ -545,7 +545,7 @@ export const { loraAllDeleted, // Inpaint mask inpaintMaskAdded, - inpaintMaskRecalled, + // inpaintMaskRecalled, inpaintMaskFillColorChanged, inpaintMaskFillStyleChanged, // Staging diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx index 9c6b77075d..10d2656746 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx @@ -1,10 +1,6 @@ import { useAppSelector } from 'app/store/storeHooks'; -import { MetadataControlNets } from 'features/metadata/components/MetadataControlNets'; -import { MetadataIPAdapters } from 'features/metadata/components/MetadataIPAdapters'; import { MetadataItem } from 'features/metadata/components/MetadataItem'; -import { MetadataLayers } from 'features/metadata/components/MetadataLayers'; import { MetadataLoRAs } from 'features/metadata/components/MetadataLoRAs'; -import { MetadataT2IAdapters } from 'features/metadata/components/MetadataT2IAdapters'; import { handlers } from 'features/metadata/util/handlers'; import { selectActiveTab } from 'features/ui/store/uiSelectors'; import { memo } from 'react'; @@ -49,10 +45,6 @@ const ImageMetadataActions = (props: Props) => { - {activeTabName === 'generation' && } - {activeTabName !== 'generation' && } - {activeTabName !== 'generation' && } - {activeTabName !== 'generation' && } ); }; diff --git a/invokeai/frontend/web/src/features/metadata/components/MetadataControlNets.tsx b/invokeai/frontend/web/src/features/metadata/components/MetadataControlNets.tsx deleted file mode 100644 index 4933fa7b53..0000000000 --- a/invokeai/frontend/web/src/features/metadata/components/MetadataControlNets.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { MetadataItemView } from 'features/metadata/components/MetadataItemView'; -import type { ControlNetConfigMetadata, MetadataHandlers } from 'features/metadata/types'; -import { handlers } from 'features/metadata/util/handlers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -type Props = { - metadata: unknown; -}; - -export const MetadataControlNets = ({ metadata }: Props) => { - const [controlNets, setControlNets] = useState([]); - - useEffect(() => { - const parse = async () => { - try { - const parsed = await handlers.controlNets.parse(metadata); - setControlNets(parsed); - } catch (e) { - setControlNets([]); - } - }; - parse(); - }, [metadata]); - - const label = useMemo(() => handlers.controlNets.getLabel(), []); - - return ( - <> - {controlNets.map((controlNet, i) => ( - - ))} - - ); -}; - -const MetadataViewControlNet = ({ - label, - controlNet, - handlers, -}: { - label: string; - controlNet: ControlNetConfigMetadata; - handlers: MetadataHandlers; -}) => { - const onRecall = useCallback(() => { - if (!handlers.recallItem) { - return; - } - handlers.recallItem(controlNet, true); - }, [handlers, controlNet]); - - const [renderedValue, setRenderedValue] = useState(null); - useEffect(() => { - const _renderValue = async () => { - if (!handlers.renderItemValue) { - setRenderedValue(null); - return; - } - const rendered = await handlers.renderItemValue(controlNet); - setRenderedValue(rendered); - }; - - _renderValue(); - }, [handlers, controlNet]); - - return ; -}; diff --git a/invokeai/frontend/web/src/features/metadata/components/MetadataIPAdapters.tsx b/invokeai/frontend/web/src/features/metadata/components/MetadataIPAdapters.tsx deleted file mode 100644 index e6e6f555aa..0000000000 --- a/invokeai/frontend/web/src/features/metadata/components/MetadataIPAdapters.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { MetadataItemView } from 'features/metadata/components/MetadataItemView'; -import type { IPAdapterConfigMetadata, MetadataHandlers } from 'features/metadata/types'; -import { handlers } from 'features/metadata/util/handlers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -type Props = { - metadata: unknown; -}; - -export const MetadataIPAdapters = ({ metadata }: Props) => { - const [ipAdapters, setIPAdapters] = useState([]); - - useEffect(() => { - const parse = async () => { - try { - const parsed = await handlers.ipAdapters.parse(metadata); - setIPAdapters(parsed); - } catch (e) { - setIPAdapters([]); - } - }; - parse(); - }, [metadata]); - - const label = useMemo(() => handlers.ipAdapters.getLabel(), []); - - return ( - <> - {ipAdapters.map((ipAdapter, i) => ( - - ))} - - ); -}; - -const MetadataViewIPAdapter = ({ - label, - ipAdapter, - handlers, -}: { - label: string; - ipAdapter: IPAdapterConfigMetadata; - handlers: MetadataHandlers; -}) => { - const onRecall = useCallback(() => { - if (!handlers.recallItem) { - return; - } - handlers.recallItem(ipAdapter, true); - }, [handlers, ipAdapter]); - - const [renderedValue, setRenderedValue] = useState(null); - useEffect(() => { - const _renderValue = async () => { - if (!handlers.renderItemValue) { - setRenderedValue(null); - return; - } - const rendered = await handlers.renderItemValue(ipAdapter); - setRenderedValue(rendered); - }; - - _renderValue(); - }, [handlers, ipAdapter]); - - return ; -}; diff --git a/invokeai/frontend/web/src/features/metadata/components/MetadataLayers.tsx b/invokeai/frontend/web/src/features/metadata/components/MetadataLayers.tsx deleted file mode 100644 index c1b2f85d8a..0000000000 --- a/invokeai/frontend/web/src/features/metadata/components/MetadataLayers.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import type { CanvasRasterLayerState } from 'features/controlLayers/store/types'; -import { MetadataItemView } from 'features/metadata/components/MetadataItemView'; -import type { MetadataHandlers } from 'features/metadata/types'; -import { handlers } from 'features/metadata/util/handlers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -type Props = { - metadata: unknown; -}; - -export const MetadataLayers = ({ metadata }: Props) => { - const [layers, setLayers] = useState([]); - - useEffect(() => { - const parse = async () => { - try { - const parsed = await handlers.layers.parse(metadata); - setLayers(parsed); - } catch (e) { - setLayers([]); - } - }; - parse(); - }, [metadata]); - - const label = useMemo(() => handlers.layers.getLabel(), []); - - return ( - <> - {layers.map((layer) => ( - - ))} - - ); -}; - -const MetadataViewLayer = ({ - label, - layer, - handlers, -}: { - label: string; - layer: CanvasRasterLayerState; - handlers: MetadataHandlers; -}) => { - const onRecall = useCallback(() => { - if (!handlers.recallItem) { - return; - } - handlers.recallItem(layer, true); - }, [handlers, layer]); - - const [renderedValue, setRenderedValue] = useState(null); - useEffect(() => { - const _renderValue = async () => { - if (!handlers.renderItemValue) { - setRenderedValue(null); - return; - } - const rendered = await handlers.renderItemValue(layer); - setRenderedValue(rendered); - }; - - _renderValue(); - }, [handlers, layer]); - - return ; -}; diff --git a/invokeai/frontend/web/src/features/metadata/components/MetadataT2IAdapters.tsx b/invokeai/frontend/web/src/features/metadata/components/MetadataT2IAdapters.tsx deleted file mode 100644 index 52dbc4a278..0000000000 --- a/invokeai/frontend/web/src/features/metadata/components/MetadataT2IAdapters.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { MetadataItemView } from 'features/metadata/components/MetadataItemView'; -import type { MetadataHandlers, T2IAdapterConfigMetadata } from 'features/metadata/types'; -import { handlers } from 'features/metadata/util/handlers'; -import { useCallback, useEffect, useMemo, useState } from 'react'; - -type Props = { - metadata: unknown; -}; - -export const MetadataT2IAdapters = ({ metadata }: Props) => { - const [t2iAdapters, setT2IAdapters] = useState([]); - - useEffect(() => { - const parse = async () => { - try { - const parsed = await handlers.t2iAdapters.parse(metadata); - setT2IAdapters(parsed); - } catch (e) { - setT2IAdapters([]); - } - }; - parse(); - }, [metadata]); - - const label = useMemo(() => handlers.t2iAdapters.getLabel(), []); - - return ( - <> - {t2iAdapters.map((t2iAdapter, i) => ( - - ))} - - ); -}; - -const MetadataViewT2IAdapter = ({ - label, - t2iAdapter, - handlers, -}: { - label: string; - t2iAdapter: T2IAdapterConfigMetadata; - handlers: MetadataHandlers; -}) => { - const onRecall = useCallback(() => { - if (!handlers.recallItem) { - return; - } - handlers.recallItem(t2iAdapter, true); - }, [handlers, t2iAdapter]); - - const [renderedValue, setRenderedValue] = useState(null); - useEffect(() => { - const _renderValue = async () => { - if (!handlers.renderItemValue) { - setRenderedValue(null); - return; - } - const rendered = await handlers.renderItemValue(t2iAdapter); - setRenderedValue(rendered); - }; - - _renderValue(); - }, [handlers, t2iAdapter]); - - return ; -}; diff --git a/invokeai/frontend/web/src/features/metadata/types.ts b/invokeai/frontend/web/src/features/metadata/types.ts index 5a4bba35c8..a1f9f5a226 100644 --- a/invokeai/frontend/web/src/features/metadata/types.ts +++ b/invokeai/frontend/web/src/features/metadata/types.ts @@ -148,7 +148,3 @@ export type BuildMetadataHandlers = ( export type ControlNetConfigMetadata = O.NonNullable; export type T2IAdapterConfigMetadata = O.NonNullable; export type IPAdapterConfigMetadata = O.NonNullable; -export type AnyControlAdapterConfigMetadata = - | ControlNetConfigMetadata - | T2IAdapterConfigMetadata - | IPAdapterConfigMetadata; diff --git a/invokeai/frontend/web/src/features/metadata/util/handlers.ts b/invokeai/frontend/web/src/features/metadata/util/handlers.ts index 12d8af35a9..760a738df4 100644 --- a/invokeai/frontend/web/src/features/metadata/util/handlers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/handlers.ts @@ -2,9 +2,8 @@ import { getStore } from 'app/store/nanostores/store'; import { deepClone } from 'common/util/deepClone'; import { objectKeys } from 'common/util/objectKeys'; import { shouldConcatPromptsChanged } from 'features/controlLayers/store/canvasV2Slice'; -import type { CanvasRasterLayerState, LoRA } from 'features/controlLayers/store/types'; +import type { LoRA } from 'features/controlLayers/store/types'; import type { - AnyControlAdapterConfigMetadata, BuildMetadataHandlers, MetadataGetLabelFunc, MetadataHandlers, @@ -19,7 +18,6 @@ import type { ModelIdentifierField } from 'features/nodes/types/common'; import { toast } from 'features/toast/toast'; import { t } from 'i18next'; import { size } from 'lodash-es'; -import { assert } from 'tsafe'; import { parsers } from './parsers'; import { recallers } from './recallers'; @@ -40,57 +38,6 @@ const renderLoRAValue: MetadataRenderValueFunc = async (value) => { return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`; } }; -const renderControlAdapterValue: MetadataRenderValueFunc = async (value) => { - try { - const modelConfig = await fetchModelConfig(value.model.key ?? 'none'); - return `${modelConfig.name} (${modelConfig.base.toUpperCase()}) - ${value.weight}`; - } catch { - return `${value.model.key} (${value.model.base.toUpperCase()}) - ${value.weight}`; - } -}; -const renderLayerValue: MetadataRenderValueFunc = (layer) => { - if (layer.type === 'initial_image_layer') { - let rendered = t('controlLayers.globalInitialImageLayer'); - if (layer.image) { - rendered += ` (${layer.image})`; - } - return rendered; - } - if (layer.type === 'control_adapter_layer') { - let rendered = t('controlLayers.globalControlAdapterLayer'); - const model = layer.controlAdapter.model; - if (model) { - rendered += ` (${model.name} - ${model.base.toUpperCase()})`; - } - return rendered; - } - if (layer.type === 'ip_adapter_layer') { - let rendered = t('controlLayers.globalIPAdapterLayer'); - const model = layer.ipAdapter.model; - if (model) { - rendered += ` (${model.name} - ${model.base.toUpperCase()})`; - } - return rendered; - } - if (layer.type === 'regional_guidance_layer') { - const rendered = t('controlLayers.regionalGuidanceLayer'); - const items: string[] = []; - if (layer.positivePrompt) { - items.push(`Positive: ${layer.positivePrompt}`); - } - if (layer.negativePrompt) { - items.push(`Negative: ${layer.negativePrompt}`); - } - if (layer.ipAdapters.length > 0) { - items.push(`${layer.ipAdapters.length} IP Adapters`); - } - return `${rendered} (${items.join(', ')})`; - } - assert(false, 'Unknown layer type'); -}; -const renderLayersValue: MetadataRenderValueFunc = (layers) => { - return `${layers.length} ${t('controlLayers.layers', { count: layers.length })}`; -}; const parameterSetToast = (parameter: string) => { toast({ @@ -328,26 +275,6 @@ export const handlers = { }), // Arrays of models - controlNets: buildHandlers({ - getLabel: () => t('common.controlNet'), - parser: parsers.controlNets, - itemParser: parsers.controlNet, - recaller: recallers.controlNets, - itemRecaller: recallers.controlNet, - validator: validators.controlNets, - itemValidator: validators.controlNet, - renderItemValue: renderControlAdapterValue, - }), - ipAdapters: buildHandlers({ - getLabel: () => t('common.ipAdapter'), - parser: parsers.ipAdapters, - itemParser: parsers.ipAdapter, - recaller: recallers.ipAdapters, - itemRecaller: recallers.ipAdapter, - validator: validators.ipAdapters, - itemValidator: validators.ipAdapter, - renderItemValue: renderControlAdapterValue, - }), loras: buildHandlers({ getLabel: () => t('models.lora'), parser: parsers.loras, @@ -358,28 +285,6 @@ export const handlers = { itemValidator: validators.lora, renderItemValue: renderLoRAValue, }), - t2iAdapters: buildHandlers({ - getLabel: () => t('common.t2iAdapter'), - parser: parsers.t2iAdapters, - itemParser: parsers.t2iAdapter, - recaller: recallers.t2iAdapters, - itemRecaller: recallers.t2iAdapter, - validator: validators.t2iAdapters, - itemValidator: validators.t2iAdapter, - renderItemValue: renderControlAdapterValue, - }), - layers: buildHandlers({ - getLabel: () => t('controlLayers.layers_one'), - parser: parsers.layers, - itemParser: parsers.layer, - recaller: recallers.layers, - itemRecaller: recallers.layer, - validator: validators.layers, - itemValidator: validators.layer, - renderItemValue: renderLayerValue, - renderValue: renderLayersValue, - getIsVisible: (value) => value.length > 0, - }), } as const; type ParsedValue = Awaited>; @@ -406,9 +311,9 @@ export const parseAndRecallImageDimensions = (metadata: unknown) => { }; // These handlers should be omitted when recalling to control layers -const TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = ['controlNets', 'ipAdapters', 't2iAdapters', 'strength']; +const TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = ['strength']; // These handlers should be omitted when recalling to the rest of the app -const NOT_TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = ['layers']; +const NOT_TO_CONTROL_LAYERS_SKIP_KEYS: (keyof typeof handlers)[] = []; export const parseAndRecallAllMetadata = async ( metadata: unknown, diff --git a/invokeai/frontend/web/src/features/metadata/util/modelFetchingHelpers.ts b/invokeai/frontend/web/src/features/metadata/util/modelFetchingHelpers.ts index 4bd2436c0b..bdf6a3bd21 100644 --- a/invokeai/frontend/web/src/features/metadata/util/modelFetchingHelpers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/modelFetchingHelpers.ts @@ -76,17 +76,17 @@ const fetchModelConfigByAttrs = async (name: string, base: BaseModelType, type: * @returns A promise that resolves to the model config. * @throws {ModelConfigNotFoundError} If the model config is unable to be fetched. */ -export const fetchModelConfigByIdentifier = async (identifier: ModelIdentifierField): Promise => { - try { - return await fetchModelConfig(identifier.key); - } catch { - try { - return await fetchModelConfigByAttrs(identifier.name, identifier.base, identifier.type); - } catch { - throw new ModelConfigNotFoundError(`Unable to retrieve model config for identifier ${identifier}`); - } - } -}; +// export const fetchModelConfigByIdentifier = async (identifier: ModelIdentifierField): Promise => { +// try { +// return await fetchModelConfig(identifier.key); +// } catch { +// try { +// return await fetchModelConfigByAttrs(identifier.name, identifier.base, identifier.type); +// } catch { +// throw new ModelConfigNotFoundError(`Unable to retrieve model config for identifier ${identifier}`); +// } +// } +// }; /** * Fetches the model config for a given model key and type, and ensures that the model config is of a specific type. diff --git a/invokeai/frontend/web/src/features/metadata/util/parsers.ts b/invokeai/frontend/web/src/features/metadata/util/parsers.ts index 5c6831d9f7..60f9eea833 100644 --- a/invokeai/frontend/web/src/features/metadata/util/parsers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/parsers.ts @@ -1,18 +1,18 @@ -import { getCAId, getImageObjectId, getIPAId, getLayerId } from 'features/controlLayers/konva/naming'; +import { getPrefixedId } from 'features/controlLayers/konva/util'; import { defaultLoRAConfig } from 'features/controlLayers/store/lorasReducers'; import type { - CanvasControlAdapterState, + CanvasControlLayerState, + CanvasInpaintMaskState, CanvasIPAdapterState, CanvasRasterLayerState, + CanvasRegionalGuidanceState, LoRA, } from 'features/controlLayers/store/types'; import { - IMAGE_FILTERS, imageDTOToImageWithDims, initialControlNet, initialIPAdapter, initialT2IAdapter, - isFilterType, zCanvasRasterLayerState, } from 'features/controlLayers/store/types'; import type { @@ -76,8 +76,6 @@ import { isT2IAdapterModelConfig, isVAEModelConfig, } from 'services/api/types'; -import { assert } from 'tsafe'; -import { v4 as uuidv4 } from 'uuid'; export const MetadataParsePendingToken = Symbol('pending'); export const MetadataParseFailedToken = Symbol('failed'); @@ -222,6 +220,7 @@ const parseLoRA: MetadataParseFunc = async (metadataItem) => { const loraModelConfig = await fetchModelConfigWithTypeGuard(key, isLoRAModelConfig); return { + id: getPrefixedId('lora'), model: zModelIdentifierField.parse(loraModelConfig), weight: isParameterLoRAWeight(weight) ? weight : defaultLoRAConfig.weight, isEnabled: true, @@ -245,14 +244,6 @@ const parseControlNet: MetadataParseFunc = async (meta const control_model = await getProperty(metadataItem, 'control_model'); const key = await getModelKey(control_model, 'controlnet'); const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig); - const image = zControlField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'image')); - const processedImage = zControlField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'processed_image')); const control_weight = zControlField.shape.control_weight .nullish() .catch(null) @@ -269,28 +260,16 @@ const parseControlNet: MetadataParseFunc = async (meta .nullish() .catch(null) .parse(await getProperty(metadataItem, 'control_mode')); - const resize_mode = zControlField.shape.resize_mode - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'resize_mode')); - - const { processorType, processorNode } = buildControlAdapterProcessor(controlNetModel); const controlNet: ControlNetConfigMetadata = { type: 'controlnet', - isEnabled: true, model: zModelIdentifierField.parse(controlNetModel), weight: typeof control_weight === 'number' ? control_weight : initialControlNet.weight, - beginStepPct: begin_step_percent ?? initialControlNet.beginStepPct, - endStepPct: end_step_percent ?? initialControlNet.endStepPct, + beginEndStepPct: [ + begin_step_percent ?? initialControlNet.beginEndStepPct[0], + end_step_percent ?? initialControlNet.beginEndStepPct[1], + ], controlMode: control_mode ?? initialControlNet.controlMode, - resizeMode: resize_mode ?? initialControlNet.resizeMode, - controlImage: image?.image_name ?? null, - processedControlImage: processedImage?.image_name ?? null, - processorType, - processorNode, - shouldAutoConfig: true, - id: uuidv4(), }; return controlNet; @@ -314,14 +293,6 @@ const parseT2IAdapter: MetadataParseFunc = async (meta const key = await getModelKey(t2i_adapter_model, 't2i_adapter'); const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig); - const image = zT2IAdapterField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'image')); - const processedImage = zT2IAdapterField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'processed_image')); const weight = zT2IAdapterField.shape.weight .nullish() .catch(null) @@ -334,27 +305,15 @@ const parseT2IAdapter: MetadataParseFunc = async (meta .nullish() .catch(null) .parse(await getProperty(metadataItem, 'end_step_percent')); - const resize_mode = zT2IAdapterField.shape.resize_mode - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'resize_mode')); - - const { processorType, processorNode } = buildControlAdapterProcessor(t2iAdapterModel); const t2iAdapter: T2IAdapterConfigMetadata = { type: 't2i_adapter', - isEnabled: true, model: zModelIdentifierField.parse(t2iAdapterModel), weight: typeof weight === 'number' ? weight : initialT2IAdapter.weight, - beginStepPct: begin_step_percent ?? initialT2IAdapter.beginStepPct, - endStepPct: end_step_percent ?? initialT2IAdapter.endStepPct, - resizeMode: resize_mode ?? initialT2IAdapter.resizeMode, - controlImage: image?.image_name ?? null, - processedControlImage: processedImage?.image_name ?? null, - processorType, - processorNode, - shouldAutoConfig: true, - id: uuidv4(), + beginEndStepPct: [ + begin_step_percent ?? initialT2IAdapter.beginEndStepPct[0], + end_step_percent ?? initialT2IAdapter.beginEndStepPct[1], + ], }; return t2iAdapter; @@ -378,10 +337,10 @@ const parseIPAdapter: MetadataParseFunc = async (metada const key = await getModelKey(ip_adapter_model, 'ip_adapter'); const ipAdapterModel = await fetchModelConfigWithTypeGuard(key, isIPAdapterModelConfig); - const image = zIPAdapterField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'image')); + // const image = zIPAdapterField.shape.image + // .nullish() + // .catch(null) + // .parse(await getProperty(metadataItem, 'image')); const weight = zIPAdapterField.shape.weight .nullish() .catch(null) @@ -400,16 +359,15 @@ const parseIPAdapter: MetadataParseFunc = async (metada .parse(await getProperty(metadataItem, 'end_step_percent')); const ipAdapter: IPAdapterConfigMetadata = { - id: uuidv4(), - type: 'ip_adapter', - isEnabled: true, model: zModelIdentifierField.parse(ipAdapterModel), clipVisionModel: 'ViT-H', - controlImage: image?.image_name ?? null, + image: null, //TODO(psyche): need an ImageWithDims weight: weight ?? initialIPAdapter.weight, method: method ?? initialIPAdapter.method, - beginStepPct: begin_step_percent ?? initialIPAdapter.beginStepPct, - endStepPct: end_step_percent ?? initialIPAdapter.endStepPct, + beginEndStepPct: [ + begin_step_percent ?? initialIPAdapter.beginEndStepPct[0], + end_step_percent ?? initialIPAdapter.beginEndStepPct[1], + ], }; return ipAdapter; @@ -429,16 +387,35 @@ const parseAllIPAdapters: MetadataParseFunc = async ( }; //#region Control Layers -const parseLayer: MetadataParseFunc = (metadataItem) => - zCanvasRasterLayerState.parseAsync(metadataItem); +const parseLayer: MetadataParseFunc< + | CanvasRasterLayerState + | CanvasControlLayerState + | CanvasIPAdapterState + | CanvasRegionalGuidanceState + | CanvasInpaintMaskState +> = (metadataItem) => zCanvasRasterLayerState.parseAsync(metadataItem); -const parseLayers: MetadataParseFunc = async (metadata) => { +const parseLayers: MetadataParseFunc< + ( + | CanvasRasterLayerState + | CanvasControlLayerState + | CanvasIPAdapterState + | CanvasRegionalGuidanceState + | CanvasInpaintMaskState + )[] +> = async (metadata) => { // We need to support recalling pre-Control Layers metadata into Control Layers. A separate set of parsers handles // taking pre-CL metadata and parsing it into layers. It doesn't always map 1-to-1, so this is best-effort. For // example, CL Control Adapters don't support resize mode, so we simply omit that property. try { - const layers: CanvasRasterLayerState[] = []; + const layers: ( + | CanvasRasterLayerState + | CanvasControlLayerState + | CanvasIPAdapterState + | CanvasRegionalGuidanceState + | CanvasInpaintMaskState + )[] = []; try { const control_layers = await getProperty(metadata, 'control_layers'); @@ -458,7 +435,7 @@ const parseLayers: MetadataParseFunc = async (metadata controlNetsRaw.map(async (cn) => await parseControlNetToControlAdapterLayer(cn)) ); const controlNetsAsLayers = controlNetsParseResults - .filter((result): result is PromiseFulfilledResult => result.status === 'fulfilled') + .filter((result): result is PromiseFulfilledResult => result.status === 'fulfilled') .map((result) => result.value); layers.push(...controlNetsAsLayers); } catch { @@ -471,7 +448,7 @@ const parseLayers: MetadataParseFunc = async (metadata t2iAdaptersRaw.map(async (cn) => await parseT2IAdapterToControlAdapterLayer(cn)) ); const t2iAdaptersAsLayers = t2iAdaptersParseResults - .filter((result): result is PromiseFulfilledResult => result.status === 'fulfilled') + .filter((result): result is PromiseFulfilledResult => result.status === 'fulfilled') .map((result) => result.value); layers.push(...t2iAdaptersAsLayers); } catch { @@ -491,62 +468,16 @@ const parseLayers: MetadataParseFunc = async (metadata // no-op } - try { - const initialImageLayer = await parseInitialImageToInitialImageLayer(metadata); - layers.push(initialImageLayer); - } catch { - // no-op - } - return layers; } catch { return []; } }; -const parseInitialImageToInitialImageLayer: MetadataParseFunc = async (metadata) => { - // TODO(psyche): recall denoise strength - // const denoisingStrength = await getProperty(metadata, 'strength', isParameterStrength); - const imageName = await getProperty(metadata, 'init_image', isString); - const imageDTO = await getImageDTO(imageName); - assert(imageDTO, 'ImageDTO is null'); - const id = getLayerId(uuidv4()); - const layer: CanvasRasterLayerState = { - id, - type: 'raster_layer', - bbox: null, - bboxNeedsUpdate: true, - x: 0, - y: 0, - isEnabled: true, - opacity: 1, - objects: [ - { - type: 'image', - id: getImageObjectId(id, imageDTO.image_name), - width: imageDTO.width, - height: imageDTO.height, - image: imageDTOToImageWithDims(imageDTO), - x: 0, - y: 0, - }, - ], - }; - return layer; -}; - -const parseControlNetToControlAdapterLayer: MetadataParseFunc = async (metadataItem) => { +const parseControlNetToControlAdapterLayer: MetadataParseFunc = async (metadataItem) => { const control_model = await getProperty(metadataItem, 'control_model'); const key = await getModelKey(control_model, 'controlnet'); const controlNetModel = await fetchModelConfigWithTypeGuard(key, isControlNetModelConfig); - const image = zControlField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'image')); - const processedImage = zControlField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'processed_image')); const control_weight = zControlField.shape.control_weight .nullish() .catch(null) @@ -564,52 +495,37 @@ const parseControlNetToControlAdapterLayer: MetadataParseFunc = async (metadataItem) => { +const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc = async (metadataItem) => { const t2i_adapter_model = await getProperty(metadataItem, 't2i_adapter_model'); const key = await getModelKey(t2i_adapter_model, 't2i_adapter'); const t2iAdapterModel = await fetchModelConfigWithTypeGuard(key, isT2IAdapterModelConfig); - const image = zT2IAdapterField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'image')); - const processedImage = zT2IAdapterField.shape.image - .nullish() - .catch(null) - .parse(await getProperty(metadataItem, 'processed_image')); const weight = zT2IAdapterField.shape.weight .nullish() .catch(null) @@ -623,33 +539,26 @@ const parseT2IAdapterToControlAdapterLayer: MetadataParseFunc = const imageDTO = image ? await getImageDTO(image.image_name) : null; const layer: CanvasIPAdapterState = { - id: getIPAId(uuidv4()), + id: getPrefixedId('ip_adapter'), type: 'ip_adapter', isEnabled: true, - model: zModelIdentifierField.parse(ipAdapterModel), - weight: typeof weight === 'number' ? weight : initialIPAdapter.weight, - beginEndStepPct, - imageObject: imageDTO ? imageDTOToImageWithDims(imageDTO) : null, - clipVisionModel: initialIPAdapter.clipVisionModel, // TODO: This needs to be added to the zIPAdapterField... - method: method ?? initialIPAdapter.method, + name: null, + ipAdapter: { + model: zModelIdentifierField.parse(ipAdapterModel), + weight: typeof weight === 'number' ? weight : initialIPAdapter.weight, + beginEndStepPct, + clipVisionModel: initialIPAdapter.clipVisionModel, // TODO: This needs to be added to the zIPAdapterField... + method: method ?? initialIPAdapter.method, + image: imageDTO ? imageDTOToImageWithDims(imageDTO) : null, + }, }; return layer; diff --git a/invokeai/frontend/web/src/features/metadata/util/recallers.ts b/invokeai/frontend/web/src/features/metadata/util/recallers.ts index 4b4b6aeba8..41d092d0c5 100644 --- a/invokeai/frontend/web/src/features/metadata/util/recallers.ts +++ b/invokeai/frontend/web/src/features/metadata/util/recallers.ts @@ -1,13 +1,4 @@ -import { logger } from 'app/logging/logger'; import { getStore } from 'app/store/nanostores/store'; -import { deepClone } from 'common/util/deepClone'; -import { - getBrushLineId, - getEraserLineId, - getImageObjectId, - getRectShapeId, - getRGId, -} from 'features/controlLayers/konva/naming'; import { bboxHeightChanged, bboxWidthChanged, @@ -17,7 +8,6 @@ import { negativePromptChanged, positivePrompt2Changed, positivePromptChanged, - rasterLayerRecalled, refinerModelChanged, setCfgRescaleMultiplier, setCfgScale, @@ -33,14 +23,9 @@ import { setSteps, vaeSelected, } from 'features/controlLayers/store/canvasV2Slice'; -import type { CanvasRasterLayerState, LoRA } from 'features/controlLayers/store/types'; +import type { LoRA } from 'features/controlLayers/store/types'; import { setHrfEnabled, setHrfMethod, setHrfStrength } from 'features/hrf/store/hrfSlice'; -import type { - ControlNetConfigMetadata, - IPAdapterConfigMetadata, - MetadataRecallFunc, - T2IAdapterConfigMetadata, -} from 'features/metadata/types'; +import type { MetadataRecallFunc } from 'features/metadata/types'; import { modelSelected } from 'features/parameters/store/actions'; import type { ParameterCFGRescaleMultiplier, @@ -64,10 +49,6 @@ import type { ParameterVAEModel, ParameterWidth, } from 'features/parameters/types/parameterSchemas'; -import { getImageDTO } from 'services/api/endpoints/images'; -import { v4 as uuidv4 } from 'uuid'; - -const log = logger('metadata'); const recallPositivePrompt: MetadataRecallFunc = (positivePrompt) => { getStore().dispatch(positivePromptChanged(positivePrompt)); @@ -190,172 +171,6 @@ const recallAllLoRAs: MetadataRecallFunc = (loras) => { }); }; -const recallControlNet: MetadataRecallFunc = (controlNet) => { - getStore().dispatch(controlAdapterRecalled(controlNet)); -}; - -const recallControlNets: MetadataRecallFunc = (controlNets) => { - const { dispatch } = getStore(); - dispatch(controlNetsReset()); - if (!controlNets.length) { - return; - } - controlNets.forEach((controlNet) => { - dispatch(controlAdapterRecalled(controlNet)); - }); -}; - -const recallT2IAdapter: MetadataRecallFunc = (t2iAdapter) => { - getStore().dispatch(controlAdapterRecalled(t2iAdapter)); -}; - -const recallT2IAdapters: MetadataRecallFunc = (t2iAdapters) => { - const { dispatch } = getStore(); - dispatch(t2iAdaptersReset()); - if (!t2iAdapters.length) { - return; - } - t2iAdapters.forEach((t2iAdapter) => { - dispatch(controlAdapterRecalled(t2iAdapter)); - }); -}; - -const recallIPAdapter: MetadataRecallFunc = (ipAdapter) => { - getStore().dispatch(controlAdapterRecalled(ipAdapter)); -}; - -const recallIPAdapters: MetadataRecallFunc = (ipAdapters) => { - const { dispatch } = getStore(); - dispatch(ipAdaptersReset()); - if (!ipAdapters.length) { - return; - } - ipAdapters.forEach((ipAdapter) => { - dispatch(controlAdapterRecalled(ipAdapter)); - }); -}; - -// const recallCA: MetadataRecallFunc = async (ca) => { -// const { dispatch } = getStore(); -// const clone = deepClone(ca); -// if (clone.image) { -// const imageDTO = await getImageDTO(clone.image.name); -// if (!imageDTO) { -// clone.image = null; -// } -// } -// if (clone.processedImage) { -// const imageDTO = await getImageDTO(clone.processedImage.name); -// if (!imageDTO) { -// clone.processedImage = null; -// } -// } -// if (clone.model) { -// try { -// await fetchModelConfigByIdentifier(clone.model); -// } catch { -// // MODEL SMITED! -// clone.model = null; -// } -// } -// // No clobber -// clone.id = getCAId(uuidv4()); -// // dispatch(caRecalled({ data: clone })); -// return; -// }; - -// const recallIPA: MetadataRecallFunc = async (ipa) => { -// const { dispatch } = getStore(); -// const clone = deepClone(ipa); -// if (clone.imageObject) { -// const imageDTO = await getImageDTO(clone.imageObject.name); -// if (!imageDTO) { -// clone.imageObject = null; -// } -// } -// if (clone.model) { -// try { -// await fetchModelConfigByIdentifier(clone.model); -// } catch { -// // MODEL SMITED! -// clone.model = null; -// } -// } -// // No clobber -// clone.id = getIPAId(uuidv4()); -// dispatch(ipaRecalled({ data: clone })); -// return; -// }; - -// const recallRG: MetadataRecallFunc = async (rg) => { -// const { dispatch } = getStore(); -// const clone = deepClone(rg); -// // Strip out the uploaded mask image property - this is an intermediate image -// clone.imageCache = null; - -// for (const ipAdapter of clone.ipAdapters) { -// if (ipAdapter.imageObject) { -// const imageDTO = await getImageDTO(ipAdapter.imageObject.name); -// if (!imageDTO) { -// ipAdapter.imageObject = null; -// } -// } -// if (ipAdapter.model) { -// try { -// await fetchModelConfigByIdentifier(ipAdapter.model); -// } catch { -// // MODEL SMITED! -// ipAdapter.model = null; -// } -// } -// // No clobber -// ipAdapter.id = uuidv4(); -// } -// clone.id = getRGId(uuidv4()); -// dispatch(rgRecalled({ data: clone })); -// return; -// }; - -//#region Control Layers -const recallLayer: MetadataRecallFunc = async (layer) => { - const { dispatch } = getStore(); - const clone = deepClone(layer); - const invalidObjects: string[] = []; - for (const obj of clone.objects) { - if (obj.type === 'image') { - const imageDTO = await getImageDTO(obj.image.image_name); - if (!imageDTO) { - invalidObjects.push(obj.id); - } - } - } - clone.objects = clone.objects.filter(({ id }) => !invalidObjects.includes(id)); - for (const obj of clone.objects) { - if (obj.type === 'brush_line') { - obj.id = getBrushLineId(clone.id, uuidv4()); - } else if (obj.type === 'eraser_line') { - obj.id = getEraserLineId(clone.id, uuidv4()); - } else if (obj.type === 'image') { - obj.id = getImageObjectId(clone.id, uuidv4()); - } else if (obj.type === 'rect') { - obj.id = getRectShapeId(clone.id, uuidv4()); - } else { - log.error(`Unknown object type ${obj.type}`); - } - } - clone.id = getRGId(uuidv4()); - dispatch(rasterLayerRecalled({ data: clone })); - return; -}; - -const recallLayers: MetadataRecallFunc = (layers) => { - const { dispatch } = getStore(); - dispatch(rasterLayerAllDeleted()); - for (const l of layers) { - recallLayer(l); - } -}; - export const recallers = { positivePrompt: recallPositivePrompt, negativePrompt: recallNegativePrompt, @@ -383,12 +198,4 @@ export const recallers = { vae: recallVAE, lora: recallLoRA, loras: recallAllLoRAs, - controlNets: recallControlNets, - controlNet: recallControlNet, - t2iAdapters: recallT2IAdapters, - t2iAdapter: recallT2IAdapter, - ipAdapters: recallIPAdapters, - ipAdapter: recallIPAdapter, - layer: recallLayer, - layers: recallLayers, } as const; diff --git a/invokeai/frontend/web/src/features/metadata/util/validators.ts b/invokeai/frontend/web/src/features/metadata/util/validators.ts index 41510a8fcf..2defbbfb0e 100644 --- a/invokeai/frontend/web/src/features/metadata/util/validators.ts +++ b/invokeai/frontend/web/src/features/metadata/util/validators.ts @@ -1,5 +1,5 @@ import { getStore } from 'app/store/nanostores/store'; -import type { CanvasRasterLayerState, LoRA } from 'features/controlLayers/store/types'; +import type { LoRA } from 'features/controlLayers/store/types'; import type { ControlNetConfigMetadata, IPAdapterConfigMetadata, @@ -9,7 +9,6 @@ import type { import { InvalidModelConfigError } from 'features/metadata/util/modelFetchingHelpers'; import type { ParameterSDXLRefinerModel, ParameterVAEModel } from 'features/parameters/types/parameterSchemas'; import type { BaseModelType } from 'services/api/types'; -import { assert } from 'tsafe'; /** * Checks the given base model type against the currently-selected model's base type and throws an error if they are @@ -21,7 +20,7 @@ const validateBaseCompatibility = (base?: BaseModelType, message?: string) => { if (!base) { throw new InvalidModelConfigError(message || 'Missing base'); } - const currentBase = getStore().getState().params.model?.base; + const currentBase = getStore().getState().canvasV2.params.model?.base; if (currentBase && base !== currentBase) { throw new InvalidModelConfigError(message || `Incompatible base models: ${base} and ${currentBase}`); } @@ -129,43 +128,6 @@ const validateIPAdapters: MetadataValidateFunc = (ipA }); }; -const validateLayer: MetadataValidateFunc = (layer) => { - if (layer.type === 'control_adapter_layer') { - const model = layer.controlAdapter.model; - assert(model, 'Control Adapter layer missing model'); - validateBaseCompatibility(model.base, 'Layer incompatible with currently-selected model'); - } - if (layer.type === 'ip_adapter_layer') { - const model = layer.ipAdapter.model; - assert(model, 'IP Adapter layer missing model'); - validateBaseCompatibility(model.base, 'Layer incompatible with currently-selected model'); - } - if (layer.type === 'regional_guidance_layer') { - for (const ipa of layer.ipAdapters) { - const model = ipa.model; - assert(model, 'IP Adapter layer missing model'); - validateBaseCompatibility(model.base, 'Layer incompatible with currently-selected model'); - } - } - - return layer; -}; - -const validateLayers: MetadataValidateFunc = async (layers) => { - const validatedLayers: CanvasRasterLayerState[] = []; - for (const l of layers) { - try { - const validated = await validateLayer(l); - validatedLayers.push(validated); - } catch { - // This is a no-op - we want to continue validating the rest of the layers, and an empty list is valid. - } - } - return new Promise((resolve) => { - resolve(validatedLayers); - }); -}; - export const validators = { refinerModel: validateRefinerModel, vaeModel: validateVAEModel, @@ -177,6 +139,4 @@ export const validators = { t2iAdapters: validateT2IAdapters, ipAdapter: validateIPAdapter, ipAdapters: validateIPAdapters, - layer: validateLayer, - layers: validateLayers, } as const; diff --git a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts index 01d28ee63f..3f767874ef 100644 --- a/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts +++ b/invokeai/frontend/web/src/features/parameters/types/parameterSchemas.ts @@ -111,21 +111,6 @@ const zParameterLoRAModel = zModelIdentifierField; export type ParameterLoRAModel = z.infer; // #endregion -// #region ControlNet Model -const zParameterControlNetModel = zModelIdentifierField; -export type ParameterControlNetModel = z.infer; -// #endregion - -// #region IP Adapter Model -const zParameterIPAdapterModel = zModelIdentifierField; -export type ParameterIPAdapterModel = z.infer; -// #endregion - -// #region T2I Adapter Model -const zParameterT2IAdapterModel = zModelIdentifierField; -export type ParameterT2IAdapterModel = z.infer; -// #endregion - // #region VAE Model const zParameterSpandrelImageToImageModel = zModelIdentifierField; export type ParameterSpandrelImageToImageModel = z.infer;