diff --git a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts b/invokeai/frontend/web/src/app/selectors/readinessSelector.ts index 6fd212494f..2b77fe9f47 100644 --- a/invokeai/frontend/web/src/app/selectors/readinessSelector.ts +++ b/invokeai/frontend/web/src/app/selectors/readinessSelector.ts @@ -10,7 +10,7 @@ export const readinessSelector = createSelector( [generationSelector, systemSelector, activeTabNameSelector], (generation, system, activeTabName) => { const { - prompt, + positivePrompt: prompt, shouldGenerateVariations, seedWeights, initialImage, diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx index b87fdcb90e..b4bf9a6d25 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetaDataViewer/ImageMetadataViewer.tsx @@ -20,7 +20,7 @@ import { setImg2imgStrength, setNegativePrompt, setPerlin, - setPrompt, + setPositivePrompt, setScheduler, setSeamless, setSeed, @@ -199,7 +199,7 @@ const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => { ? metadata.positive_conditioning : promptToString(metadata.positive_conditioning) } - onClick={() => setPrompt(metadata.positive_conditioning!)} + onClick={() => setPositivePrompt(metadata.positive_conditioning!)} /> )} {metadata.negative_conditioning && ( diff --git a/invokeai/frontend/web/src/features/nodes/types/types.ts b/invokeai/frontend/web/src/features/nodes/types/types.ts index d2c7c7e704..efb4a5518d 100644 --- a/invokeai/frontend/web/src/features/nodes/types/types.ts +++ b/invokeai/frontend/web/src/features/nodes/types/types.ts @@ -1,7 +1,10 @@ import { OpenAPIV3 } from 'openapi-types'; import { RgbaColor } from 'react-colorful'; -import { ImageDTO } from 'services/api'; +import { Graph, ImageDTO } from 'services/api'; import { AnyInvocationType } from 'services/events/types'; +import { O } from 'ts-toolbelt'; + +export type NonNullableGraph = O.Required; export type InvocationValue = { id: string; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts index d7a0fc66d3..003069ea89 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildImageToImageGraph.ts @@ -1,35 +1,132 @@ +import { v4 as uuidv4 } from 'uuid'; import { RootState } from 'app/store/store'; -import { Graph } from 'services/api'; -import { buildImg2ImgNode } from '../nodeBuilders/buildImageToImageNode'; -import { buildRangeNode } from '../nodeBuilders/buildRangeNode'; -import { buildIterateNode } from '../nodeBuilders/buildIterateNode'; -import { buildEdges } from '../edgeBuilders/buildEdges'; +import { + CompelInvocation, + Graph, + ImageToLatentsInvocation, + LatentsToImageInvocation, + LatentsToLatentsInvocation, +} from 'services/api'; +import { NonNullableGraph } from 'features/nodes/types/types'; +import { addNoiseNodes } from '../nodeBuilders/addNoiseNodes'; +import { log } from 'app/logging/useLogger'; + +const moduleLog = log.child({ namespace: 'buildImageToImageGraph' }); + +const POSITIVE_CONDITIONING = 'positive_conditioning'; +const NEGATIVE_CONDITIONING = 'negative_conditioning'; +const IMAGE_TO_LATENTS = 'image_to_latents'; +const LATENTS_TO_LATENTS = 'latents_to_latents'; +const LATENTS_TO_IMAGE = 'latents_to_image'; /** - * Builds the Linear workflow graph. + * Builds the Image to Image tab graph. */ export const buildImageToImageGraph = (state: RootState): Graph => { - const baseNode = buildImg2ImgNode(state); + const { + positivePrompt, + negativePrompt, + model, + cfgScale: cfg_scale, + scheduler, + steps, + initialImage, + img2imgStrength: strength, + } = state.generation; - // We always range and iterate nodes, no matter the iteration count - // This is required to provide the correct seeds to the backend engine - const rangeNode = buildRangeNode(state); - const iterateNode = buildIterateNode(); + if (!initialImage) { + moduleLog.error('No initial image found in state'); + throw new Error('No initial image found in state'); + } - // Build the edges for the nodes selected. - const edges = buildEdges(baseNode, rangeNode, iterateNode); - - // Assemble! - const graph = { - nodes: { - [rangeNode.id]: rangeNode, - [iterateNode.id]: iterateNode, - [baseNode.id]: baseNode, - }, - edges, + let graph: NonNullableGraph = { + nodes: {}, + edges: [], }; - // TODO: hires fix requires latent space upscaling; we don't have nodes for this yet + // Create the conditioning, t2l and l2i nodes + const positiveConditioningNode: CompelInvocation = { + id: POSITIVE_CONDITIONING, + type: 'compel', + prompt: positivePrompt, + model, + }; + + const negativeConditioningNode: CompelInvocation = { + id: NEGATIVE_CONDITIONING, + type: 'compel', + prompt: negativePrompt, + model, + }; + + const imageToLatentsNode: ImageToLatentsInvocation = { + id: IMAGE_TO_LATENTS, + type: 'i2l', + model, + image: { + image_name: initialImage?.image_name, + image_type: initialImage?.image_type, + }, + }; + + const latentsToLatentsNode: LatentsToLatentsInvocation = { + id: LATENTS_TO_LATENTS, + type: 'l2l', + cfg_scale, + model, + scheduler, + steps, + strength, + }; + + const latentsToImageNode: LatentsToImageInvocation = { + id: LATENTS_TO_IMAGE, + type: 'l2i', + model, + }; + + // Add to the graph + graph.nodes[POSITIVE_CONDITIONING] = positiveConditioningNode; + graph.nodes[NEGATIVE_CONDITIONING] = negativeConditioningNode; + graph.nodes[IMAGE_TO_LATENTS] = imageToLatentsNode; + graph.nodes[LATENTS_TO_LATENTS] = latentsToLatentsNode; + graph.nodes[LATENTS_TO_IMAGE] = latentsToImageNode; + + // Connect them + graph.edges.push({ + source: { node_id: POSITIVE_CONDITIONING, field: 'conditioning' }, + destination: { + node_id: LATENTS_TO_LATENTS, + field: 'positive_conditioning', + }, + }); + + graph.edges.push({ + source: { node_id: NEGATIVE_CONDITIONING, field: 'conditioning' }, + destination: { + node_id: LATENTS_TO_LATENTS, + field: 'negative_conditioning', + }, + }); + + graph.edges.push({ + source: { node_id: IMAGE_TO_LATENTS, field: 'latents' }, + destination: { + node_id: LATENTS_TO_LATENTS, + field: 'latents', + }, + }); + + graph.edges.push({ + source: { node_id: LATENTS_TO_LATENTS, field: 'latents' }, + destination: { + node_id: LATENTS_TO_IMAGE, + field: 'latents', + }, + }); + + // Create and add the noise nodes + graph = addNoiseNodes(graph, latentsToLatentsNode.id, state); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts index 8b1d8edcc9..2fc3ea3975 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildTextToImageGraph.ts @@ -1,35 +1,99 @@ import { RootState } from 'app/store/store'; -import { Graph } from 'services/api'; -import { buildTxt2ImgNode } from '../nodeBuilders/buildTextToImageNode'; -import { buildRangeNode } from '../nodeBuilders/buildRangeNode'; -import { buildIterateNode } from '../nodeBuilders/buildIterateNode'; -import { buildEdges } from '../edgeBuilders/buildEdges'; +import { + CompelInvocation, + Graph, + LatentsToImageInvocation, + TextToLatentsInvocation, +} from 'services/api'; +import { NonNullableGraph } from 'features/nodes/types/types'; +import { addNoiseNodes } from '../nodeBuilders/addNoiseNodes'; + +const POSITIVE_CONDITIONING = 'positive_conditioning'; +const NEGATIVE_CONDITIONING = 'negative_conditioning'; +const TEXT_TO_LATENTS = 'text_to_latents'; +const LATENTS_TO_IMAGE = 'latnets_to_image'; /** - * Builds the Linear workflow graph. + * Builds the Text to Image tab graph. */ export const buildTextToImageGraph = (state: RootState): Graph => { - const baseNode = buildTxt2ImgNode(state); + const { + positivePrompt, + negativePrompt, + model, + cfgScale: cfg_scale, + scheduler, + steps, + } = state.generation; - // We always range and iterate nodes, no matter the iteration count - // This is required to provide the correct seeds to the backend engine - const rangeNode = buildRangeNode(state); - const iterateNode = buildIterateNode(); - - // Build the edges for the nodes selected. - const edges = buildEdges(baseNode, rangeNode, iterateNode); - - // Assemble! - const graph = { - nodes: { - [rangeNode.id]: rangeNode, - [iterateNode.id]: iterateNode, - [baseNode.id]: baseNode, - }, - edges, + let graph: NonNullableGraph = { + nodes: {}, + edges: [], }; - // TODO: hires fix requires latent space upscaling; we don't have nodes for this yet + // Create the conditioning, t2l and l2i nodes + const positiveConditioningNode: CompelInvocation = { + id: POSITIVE_CONDITIONING, + type: 'compel', + prompt: positivePrompt, + model, + }; + const negativeConditioningNode: CompelInvocation = { + id: NEGATIVE_CONDITIONING, + type: 'compel', + prompt: negativePrompt, + model, + }; + + const textToLatentsNode: TextToLatentsInvocation = { + id: TEXT_TO_LATENTS, + type: 't2l', + cfg_scale, + model, + scheduler, + steps, + }; + + const latentsToImageNode: LatentsToImageInvocation = { + id: LATENTS_TO_IMAGE, + type: 'l2i', + model, + }; + + // Add to the graph + graph.nodes[POSITIVE_CONDITIONING] = positiveConditioningNode; + graph.nodes[NEGATIVE_CONDITIONING] = negativeConditioningNode; + graph.nodes[TEXT_TO_LATENTS] = textToLatentsNode; + graph.nodes[LATENTS_TO_IMAGE] = latentsToImageNode; + + // Connect them + graph.edges.push({ + source: { node_id: POSITIVE_CONDITIONING, field: 'conditioning' }, + destination: { + node_id: TEXT_TO_LATENTS, + field: 'positive_conditioning', + }, + }); + + graph.edges.push({ + source: { node_id: NEGATIVE_CONDITIONING, field: 'conditioning' }, + destination: { + node_id: TEXT_TO_LATENTS, + field: 'negative_conditioning', + }, + }); + + graph.edges.push({ + source: { node_id: TEXT_TO_LATENTS, field: 'latents' }, + destination: { + node_id: LATENTS_TO_IMAGE, + field: 'latents', + }, + }); + + // Create and add the noise nodes + graph = addNoiseNodes(graph, TEXT_TO_LATENTS, state); + console.log(graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/addNoiseNodes.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/addNoiseNodes.ts new file mode 100644 index 0000000000..ba3d4d8168 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/addNoiseNodes.ts @@ -0,0 +1,208 @@ +import { RootState } from 'app/store/store'; +import { + IterateInvocation, + NoiseInvocation, + RandomIntInvocation, + RangeOfSizeInvocation, +} from 'services/api'; +import { NonNullableGraph } from 'features/nodes/types/types'; +import { cloneDeep } from 'lodash-es'; + +const NOISE = 'noise'; +const RANDOM_INT = 'rand_int'; +const RANGE_OF_SIZE = 'range_of_size'; +const ITERATE = 'iterate'; +/** + * Adds the appropriate noise nodes to a linear UI t2l or l2l graph. + * + * @param graph The graph to add the noise nodes to. + * @param baseNodeId The id of the base node to connect the noise nodes to. + * @param state The app state.. + */ +export const addNoiseNodes = ( + graph: NonNullableGraph, + baseNodeId: string, + state: RootState +): NonNullableGraph => { + const graphClone = cloneDeep(graph); + + // Create and add the noise nodes + const { width, height, seed, iterations, shouldRandomizeSeed } = + state.generation; + + // Single iteration, explicit seed + if (!shouldRandomizeSeed && iterations === 1) { + const noiseNode: NoiseInvocation = { + id: NOISE, + type: 'noise', + seed: seed, + width, + height, + }; + + graphClone.nodes[NOISE] = noiseNode; + + // Connect them + graphClone.edges.push({ + source: { node_id: NOISE, field: 'noise' }, + destination: { + node_id: baseNodeId, + field: 'noise', + }, + }); + } + + // Single iteration, random seed + if (shouldRandomizeSeed && iterations === 1) { + // TODO: This assumes the `high` value is the max seed value + const randomIntNode: RandomIntInvocation = { + id: RANDOM_INT, + type: 'rand_int', + }; + + const noiseNode: NoiseInvocation = { + id: NOISE, + type: 'noise', + width, + height, + }; + + graphClone.nodes[RANDOM_INT] = randomIntNode; + graphClone.nodes[NOISE] = noiseNode; + + graphClone.edges.push({ + source: { node_id: RANDOM_INT, field: 'a' }, + destination: { + node_id: NOISE, + field: 'seed', + }, + }); + + graphClone.edges.push({ + source: { node_id: NOISE, field: 'noise' }, + destination: { + node_id: baseNodeId, + field: 'noise', + }, + }); + } + + // Multiple iterations, explicit seed + if (!shouldRandomizeSeed && iterations > 1) { + const rangeOfSizeNode: RangeOfSizeInvocation = { + id: RANGE_OF_SIZE, + type: 'range_of_size', + start: seed, + size: iterations, + }; + + const iterateNode: IterateInvocation = { + id: ITERATE, + type: 'iterate', + }; + + const noiseNode: NoiseInvocation = { + id: NOISE, + type: 'noise', + width, + height, + }; + + graphClone.nodes[RANGE_OF_SIZE] = rangeOfSizeNode; + graphClone.nodes[ITERATE] = iterateNode; + graphClone.nodes[NOISE] = noiseNode; + + graphClone.edges.push({ + source: { node_id: RANGE_OF_SIZE, field: 'collection' }, + destination: { + node_id: ITERATE, + field: 'collection', + }, + }); + + graphClone.edges.push({ + source: { + node_id: ITERATE, + field: 'item', + }, + destination: { + node_id: NOISE, + field: 'seed', + }, + }); + + graphClone.edges.push({ + source: { node_id: NOISE, field: 'noise' }, + destination: { + node_id: baseNodeId, + field: 'noise', + }, + }); + } + + // Multiple iterations, random seed + if (shouldRandomizeSeed && iterations > 1) { + // TODO: This assumes the `high` value is the max seed value + const randomIntNode: RandomIntInvocation = { + id: RANDOM_INT, + type: 'rand_int', + }; + + const rangeOfSizeNode: RangeOfSizeInvocation = { + id: RANGE_OF_SIZE, + type: 'range_of_size', + size: iterations, + }; + + const iterateNode: IterateInvocation = { + id: ITERATE, + type: 'iterate', + }; + + const noiseNode: NoiseInvocation = { + id: NOISE, + type: 'noise', + width, + height, + }; + + graphClone.nodes[RANDOM_INT] = randomIntNode; + graphClone.nodes[RANGE_OF_SIZE] = rangeOfSizeNode; + graphClone.nodes[ITERATE] = iterateNode; + graphClone.nodes[NOISE] = noiseNode; + + graphClone.edges.push({ + source: { node_id: RANDOM_INT, field: 'a' }, + destination: { node_id: RANGE_OF_SIZE, field: 'start' }, + }); + + graphClone.edges.push({ + source: { node_id: RANGE_OF_SIZE, field: 'collection' }, + destination: { + node_id: ITERATE, + field: 'collection', + }, + }); + + graphClone.edges.push({ + source: { + node_id: ITERATE, + field: 'item', + }, + destination: { + node_id: NOISE, + field: 'seed', + }, + }); + + graphClone.edges.push({ + source: { node_id: NOISE, field: 'noise' }, + destination: { + node_id: baseNodeId, + field: 'noise', + }, + }); + } + + return graphClone; +}; diff --git a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildCompelNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildCompelNode.ts new file mode 100644 index 0000000000..02ac148181 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildCompelNode.ts @@ -0,0 +1,26 @@ +import { v4 as uuidv4 } from 'uuid'; +import { RootState } from 'app/store/store'; +import { CompelInvocation } from 'services/api'; +import { O } from 'ts-toolbelt'; + +export const buildCompelNode = ( + prompt: string, + state: RootState, + overrides: O.Partial = {} +): CompelInvocation => { + const nodeId = uuidv4(); + const { generation } = state; + + const { model } = generation; + + const compelNode: CompelInvocation = { + id: nodeId, + type: 'compel', + prompt, + model, + }; + + Object.assign(compelNode, overrides); + + return compelNode; +}; diff --git a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts index 02480289d4..5f00d12a23 100644 --- a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildImageToImageNode.ts @@ -18,8 +18,8 @@ export const buildImg2ImgNode = ( const activeTabName = activeTabNameSelector(state); const { - prompt, - negativePrompt, + positivePrompt: prompt, + negativePrompt: negativePrompt, seed, steps, width, diff --git a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts index 36658ef58f..b3f6cca933 100644 --- a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildInpaintNode.ts @@ -13,8 +13,8 @@ export const buildInpaintNode = ( const activeTabName = activeTabNameSelector(state); const { - prompt, - negativePrompt, + positivePrompt: prompt, + negativePrompt: negativePrompt, seed, steps, width, diff --git a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts index 761c909776..64e7aaa831 100644 --- a/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/nodeBuilders/buildTextToImageNode.ts @@ -11,8 +11,8 @@ export const buildTxt2ImgNode = ( const { generation } = state; const { - prompt, - negativePrompt, + positivePrompt: prompt, + negativePrompt: negativePrompt, seed, steps, width, diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx index b4a5c1f09a..365bade0aa 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamPositiveConditioning.tsx @@ -8,7 +8,7 @@ import { readinessSelector } from 'app/selectors/readinessSelector'; import { GenerationState, clampSymmetrySteps, - setPrompt, + setPositivePrompt, } from 'features/parameters/store/generationSlice'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; @@ -22,7 +22,7 @@ const promptInputSelector = createSelector( [(state: RootState) => state.generation, activeTabNameSelector], (parameters: GenerationState, activeTabName) => { return { - prompt: parameters.prompt, + prompt: parameters.positivePrompt, activeTabName, }; }, @@ -46,7 +46,7 @@ const ParamPositiveConditioning = () => { const { t } = useTranslation(); const handleChangePrompt = (e: ChangeEvent) => { - dispatch(setPrompt(e.target.value)); + dispatch(setPositivePrompt(e.target.value)); }; useHotkeys( diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx index 9ae1ff55e2..be40f548e6 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx @@ -57,7 +57,7 @@ const InitialImagePreview = () => { const name = e.dataTransfer.getData('invokeai/imageName'); const type = e.dataTransfer.getData('invokeai/imageType') as ImageType; - dispatch(initialImageSelected({ name, type })); + dispatch(initialImageSelected({ image_name: name, image_type: type })); }, [dispatch] ); @@ -73,10 +73,10 @@ const InitialImagePreview = () => { }} onDrop={handleDrop} > - {initialImage?.url && ( + {initialImage?.image_url && ( <> } onError={handleError} @@ -92,7 +92,7 @@ const InitialImagePreview = () => { )} - {!initialImage?.url && ( + {!initialImage?.image_url && ( { const [prompt, negativePrompt] = getPromptAndNegative(promptString); - dispatch(setPrompt(prompt)); + dispatch(setPositivePrompt(prompt)); dispatch(setNegativePrompt(negativePrompt)); }, [dispatch] diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index b471ffc783..f5054f1969 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -16,7 +16,7 @@ export interface GenerationState { initialImage?: ImageDTO; iterations: number; perlin: number; - prompt: string; + positivePrompt: string; negativePrompt: string; scheduler: Scheduler; seamBlur: number; @@ -50,7 +50,7 @@ export const initialGenerationState: GenerationState = { infillMethod: 'patchmatch', iterations: 1, perlin: 0, - prompt: '', + positivePrompt: '', negativePrompt: '', scheduler: 'lms', seamBlur: 16, @@ -83,12 +83,15 @@ export const generationSlice = createSlice({ name: 'generation', initialState, reducers: { - setPrompt: (state, action: PayloadAction) => { + setPositivePrompt: ( + state, + action: PayloadAction + ) => { const newPrompt = action.payload; if (typeof newPrompt === 'string') { - state.prompt = newPrompt; + state.positivePrompt = newPrompt; } else { - state.prompt = promptToString(newPrompt); + state.positivePrompt = promptToString(newPrompt); } }, setNegativePrompt: ( @@ -244,7 +247,7 @@ export const { setInfillMethod, setIterations, setPerlin, - setPrompt, + setPositivePrompt, setNegativePrompt, setScheduler, setSeamBlur, diff --git a/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts b/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts index dc147090b4..d6d1af0f8e 100644 --- a/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts +++ b/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts @@ -31,7 +31,7 @@ export const setAllParametersReducer = ( state.model = String(model); } if (prompt !== undefined) { - state.prompt = String(prompt); + state.positivePrompt = String(prompt); } if (scheduler !== undefined) { const schedulerString = String(scheduler); diff --git a/invokeai/frontend/web/src/services/api/index.ts b/invokeai/frontend/web/src/services/api/index.ts index 0b97a97fb7..ecf8621ed6 100644 --- a/invokeai/frontend/web/src/services/api/index.ts +++ b/invokeai/frontend/web/src/services/api/index.ts @@ -66,6 +66,7 @@ export type { PromptOutput } from './models/PromptOutput'; export type { RandomIntInvocation } from './models/RandomIntInvocation'; export type { RandomRangeInvocation } from './models/RandomRangeInvocation'; export type { RangeInvocation } from './models/RangeInvocation'; +export type { RangeOfSizeInvocation } from './models/RangeOfSizeInvocation'; export type { ResizeLatentsInvocation } from './models/ResizeLatentsInvocation'; export type { RestoreFaceInvocation } from './models/RestoreFaceInvocation'; export type { ScaleLatentsInvocation } from './models/ScaleLatentsInvocation'; diff --git a/invokeai/frontend/web/src/services/api/models/Graph.ts b/invokeai/frontend/web/src/services/api/models/Graph.ts index 4399725680..039923e585 100644 --- a/invokeai/frontend/web/src/services/api/models/Graph.ts +++ b/invokeai/frontend/web/src/services/api/models/Graph.ts @@ -31,6 +31,7 @@ import type { PasteImageInvocation } from './PasteImageInvocation'; import type { RandomIntInvocation } from './RandomIntInvocation'; import type { RandomRangeInvocation } from './RandomRangeInvocation'; import type { RangeInvocation } from './RangeInvocation'; +import type { RangeOfSizeInvocation } from './RangeOfSizeInvocation'; import type { ResizeLatentsInvocation } from './ResizeLatentsInvocation'; import type { RestoreFaceInvocation } from './RestoreFaceInvocation'; import type { ScaleLatentsInvocation } from './ScaleLatentsInvocation'; @@ -48,7 +49,7 @@ export type Graph = { /** * The nodes in this graph */ - nodes?: Record; + nodes?: Record; /** * The connections between nodes and their fields in this graph */ diff --git a/invokeai/frontend/web/src/services/api/models/ImageDTO.ts b/invokeai/frontend/web/src/services/api/models/ImageDTO.ts index c5fad70d8a..c5377b4c76 100644 --- a/invokeai/frontend/web/src/services/api/models/ImageDTO.ts +++ b/invokeai/frontend/web/src/services/api/models/ImageDTO.ts @@ -59,7 +59,7 @@ export type ImageDTO = { */ node_id?: string; /** - * A limited subset of the image's metadata. Retrieve the image's session for full metadata. + * A limited subset of the image's generation metadata. Retrieve the image's session for full metadata. */ metadata?: ImageMetadata; }; diff --git a/invokeai/frontend/web/src/services/api/models/MaskOutput.ts b/invokeai/frontend/web/src/services/api/models/MaskOutput.ts index 645fb8d1cb..d4594fe6e9 100644 --- a/invokeai/frontend/web/src/services/api/models/MaskOutput.ts +++ b/invokeai/frontend/web/src/services/api/models/MaskOutput.ts @@ -13,5 +13,13 @@ export type MaskOutput = { * The output mask */ mask: ImageField; + /** + * The width of the mask in pixels + */ + width?: number; + /** + * The height of the mask in pixels + */ + height?: number; }; diff --git a/invokeai/frontend/web/src/services/api/models/RangeInvocation.ts b/invokeai/frontend/web/src/services/api/models/RangeInvocation.ts index 72bc4806da..1c37ca7fe3 100644 --- a/invokeai/frontend/web/src/services/api/models/RangeInvocation.ts +++ b/invokeai/frontend/web/src/services/api/models/RangeInvocation.ts @@ -3,7 +3,7 @@ /* eslint-disable */ /** - * Creates a range + * Creates a range of numbers from start to stop with step */ export type RangeInvocation = { /** diff --git a/invokeai/frontend/web/src/services/api/models/RangeOfSizeInvocation.ts b/invokeai/frontend/web/src/services/api/models/RangeOfSizeInvocation.ts new file mode 100644 index 0000000000..b918f17130 --- /dev/null +++ b/invokeai/frontend/web/src/services/api/models/RangeOfSizeInvocation.ts @@ -0,0 +1,27 @@ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ + +/** + * Creates a range from start to start + size with step + */ +export type RangeOfSizeInvocation = { + /** + * The id of this node. Must be unique among all nodes. + */ + id: string; + type?: 'range_of_size'; + /** + * The start of the range + */ + start?: number; + /** + * The number of values + */ + size?: number; + /** + * The step of the range + */ + step?: number; +}; + diff --git a/invokeai/frontend/web/src/services/api/services/ImagesService.ts b/invokeai/frontend/web/src/services/api/services/ImagesService.ts index a172c022f4..13b2ef836a 100644 --- a/invokeai/frontend/web/src/services/api/services/ImagesService.ts +++ b/invokeai/frontend/web/src/services/api/services/ImagesService.ts @@ -89,6 +89,39 @@ export class ImagesService { }); } + /** + * Get Image Full + * Gets a full-resolution image file + * @returns any Return the full-resolution image + * @throws ApiError + */ + public static getImageFull({ + imageType, + imageName, + }: { + /** + * The type of full-resolution image file to get + */ + imageType: ImageType, + /** + * The name of full-resolution image file to get + */ + imageName: string, + }): CancelablePromise { + return __request(OpenAPI, { + method: 'GET', + url: '/api/v1/images/{image_type}/{image_name}', + path: { + 'image_type': imageType, + 'image_name': imageName, + }, + errors: { + 404: `Image not found`, + 422: `Validation Error`, + }, + }); + } + /** * Delete Image * Deletes an image @@ -150,39 +183,6 @@ export class ImagesService { }); } - /** - * Get Image Full - * Gets a full-resolution image file - * @returns any Return the full-resolution image - * @throws ApiError - */ - public static getImageFull({ - imageType, - imageName, - }: { - /** - * The type of full-resolution image file to get - */ - imageType: ImageType, - /** - * The name of full-resolution image file to get - */ - imageName: string, - }): CancelablePromise { - return __request(OpenAPI, { - method: 'GET', - url: '/api/v1/images/{image_type}/{image_name}/full', - path: { - 'image_type': imageType, - 'image_name': imageName, - }, - errors: { - 404: `Image not found`, - 422: `Validation Error`, - }, - }); - } - /** * Get Image Thumbnail * Gets a thumbnail image file diff --git a/invokeai/frontend/web/src/services/api/services/SessionsService.ts b/invokeai/frontend/web/src/services/api/services/SessionsService.ts index 1925b0800f..23597c9e9e 100644 --- a/invokeai/frontend/web/src/services/api/services/SessionsService.ts +++ b/invokeai/frontend/web/src/services/api/services/SessionsService.ts @@ -33,6 +33,7 @@ import type { PasteImageInvocation } from '../models/PasteImageInvocation'; import type { RandomIntInvocation } from '../models/RandomIntInvocation'; import type { RandomRangeInvocation } from '../models/RandomRangeInvocation'; import type { RangeInvocation } from '../models/RangeInvocation'; +import type { RangeOfSizeInvocation } from '../models/RangeOfSizeInvocation'; import type { ResizeLatentsInvocation } from '../models/ResizeLatentsInvocation'; import type { RestoreFaceInvocation } from '../models/RestoreFaceInvocation'; import type { ScaleLatentsInvocation } from '../models/ScaleLatentsInvocation'; @@ -150,7 +151,7 @@ export class SessionsService { * The id of the session */ sessionId: string, - requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), + requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | CvInpaintInvocation | RangeInvocation | RangeOfSizeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), }): CancelablePromise { return __request(OpenAPI, { method: 'POST', @@ -187,7 +188,7 @@ export class SessionsService { * The path to the node in the graph */ nodePath: string, - requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | CvInpaintInvocation | RangeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), + requestBody: (LoadImageInvocation | ShowImageInvocation | CropImageInvocation | PasteImageInvocation | MaskFromAlphaInvocation | BlurInvocation | LerpInvocation | InverseLerpInvocation | CompelInvocation | AddInvocation | SubtractInvocation | MultiplyInvocation | DivideInvocation | RandomIntInvocation | ParamIntInvocation | NoiseInvocation | TextToLatentsInvocation | LatentsToImageInvocation | ResizeLatentsInvocation | ScaleLatentsInvocation | ImageToLatentsInvocation | CvInpaintInvocation | RangeInvocation | RangeOfSizeInvocation | RandomRangeInvocation | UpscaleInvocation | RestoreFaceInvocation | TextToImageInvocation | InfillColorInvocation | InfillTileInvocation | InfillPatchMatchInvocation | GraphInvocation | IterateInvocation | CollectInvocation | LatentsToLatentsInvocation | ImageToImageInvocation | InpaintInvocation), }): CancelablePromise { return __request(OpenAPI, { method: 'PUT',