Merge branch 'main' into release/make-web-dist-startable

This commit is contained in:
Lincoln Stein 2023-05-25 21:52:05 -04:00 committed by GitHub
commit dd157bce85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 57 additions and 55 deletions

View File

@ -56,7 +56,7 @@ class TextToImageInvocation(BaseInvocation, SDImageInvocation):
width: int = Field(default=512, multiple_of=8, gt=0, description="The width of the resulting image", ) width: int = Field(default=512, multiple_of=8, gt=0, description="The width of the resulting image", )
height: int = Field(default=512, multiple_of=8, gt=0, description="The height of the resulting image", ) height: int = Field(default=512, multiple_of=8, gt=0, description="The height of the resulting image", )
cfg_scale: float = Field(default=7.5, ge=1, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", ) cfg_scale: float = Field(default=7.5, ge=1, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", )
scheduler: SAMPLER_NAME_VALUES = Field(default="lms", description="The scheduler to use" ) scheduler: SAMPLER_NAME_VALUES = Field(default="euler", description="The scheduler to use" )
model: str = Field(default="", description="The model to use (currently ignored)") model: str = Field(default="", description="The model to use (currently ignored)")
# fmt: on # fmt: on

View File

@ -167,7 +167,7 @@ class TextToLatentsInvocation(BaseInvocation):
noise: Optional[LatentsField] = Field(description="The noise to use") noise: Optional[LatentsField] = Field(description="The noise to use")
steps: int = Field(default=10, gt=0, description="The number of steps to use to generate the image") steps: int = Field(default=10, gt=0, description="The number of steps to use to generate the image")
cfg_scale: float = Field(default=7.5, gt=0, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", ) cfg_scale: float = Field(default=7.5, gt=0, description="The Classifier-Free Guidance, higher values may result in a result closer to the prompt", )
scheduler: SAMPLER_NAME_VALUES = Field(default="lms", description="The scheduler to use" ) scheduler: SAMPLER_NAME_VALUES = Field(default="euler", description="The scheduler to use" )
model: str = Field(default="", description="The model to use (currently ignored)") model: str = Field(default="", description="The model to use (currently ignored)")
# seamless: bool = Field(default=False, description="Whether or not to generate an image that can tile without seams", ) # seamless: bool = Field(default=False, description="Whether or not to generate an image that can tile without seams", )
# seamless_axes: str = Field(default="", description="The axes to tile the image on, 'x' and/or 'y'") # seamless_axes: str = Field(default="", description="The axes to tile the image on, 'x' and/or 'y'")

View File

@ -109,8 +109,9 @@ const currentImageButtonsSelector = createSelector(
isLightboxOpen, isLightboxOpen,
shouldHidePreview, shouldHidePreview,
image: selectedImage, image: selectedImage,
seed: selectedImage?.metadata?.invokeai?.node?.seed, seed: selectedImage?.metadata?.seed,
prompt: selectedImage?.metadata?.invokeai?.node?.prompt, prompt: selectedImage?.metadata?.positive_conditioning,
negativePrompt: selectedImage?.metadata?.negative_conditioning,
}; };
}, },
{ {
@ -245,13 +246,16 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
); );
const handleUseSeed = useCallback(() => { const handleUseSeed = useCallback(() => {
recallSeed(image?.metadata?.invokeai?.node?.seed); recallSeed(image?.metadata?.seed);
}, [image, recallSeed]); }, [image, recallSeed]);
useHotkeys('s', handleUseSeed, [image]); useHotkeys('s', handleUseSeed, [image]);
const handleUsePrompt = useCallback(() => { const handleUsePrompt = useCallback(() => {
recallPrompt(image?.metadata?.invokeai?.node?.prompt); recallPrompt(
image?.metadata?.positive_conditioning,
image?.metadata?.negative_conditioning
);
}, [image, recallPrompt]); }, [image, recallPrompt]);
useHotkeys('p', handleUsePrompt, [image]); useHotkeys('p', handleUsePrompt, [image]);
@ -454,7 +458,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
{t('parameters.copyImageToLink')} {t('parameters.copyImageToLink')}
</IAIButton> </IAIButton>
<Link download={true} href={getUrl(image?.url ?? '')}> <Link download={true} href={getUrl(image?.image_url ?? '')}>
<IAIButton leftIcon={<FaDownload />} size="sm" w="100%"> <IAIButton leftIcon={<FaDownload />} size="sm" w="100%">
{t('parameters.downloadImage')} {t('parameters.downloadImage')}
</IAIButton> </IAIButton>
@ -500,7 +504,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
icon={<FaQuoteRight />} icon={<FaQuoteRight />}
tooltip={`${t('parameters.usePrompt')} (P)`} tooltip={`${t('parameters.usePrompt')} (P)`}
aria-label={`${t('parameters.usePrompt')} (P)`} aria-label={`${t('parameters.usePrompt')} (P)`}
isDisabled={!image?.metadata?.invokeai?.node?.prompt} isDisabled={!image?.metadata?.positive_conditioning}
onClick={handleUsePrompt} onClick={handleUsePrompt}
/> />
@ -508,7 +512,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
icon={<FaSeedling />} icon={<FaSeedling />}
tooltip={`${t('parameters.useSeed')} (S)`} tooltip={`${t('parameters.useSeed')} (S)`}
aria-label={`${t('parameters.useSeed')} (S)`} aria-label={`${t('parameters.useSeed')} (S)`}
isDisabled={!image?.metadata?.invokeai?.node?.seed} isDisabled={!image?.metadata?.seed}
onClick={handleUseSeed} onClick={handleUseSeed}
/> />
@ -517,9 +521,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
tooltip={`${t('parameters.useAll')} (A)`} tooltip={`${t('parameters.useAll')} (A)`}
aria-label={`${t('parameters.useAll')} (A)`} aria-label={`${t('parameters.useAll')} (A)`}
isDisabled={ isDisabled={
!['txt2img', 'img2img', 'inpaint'].includes( // not sure what this list should be
String(image?.metadata?.invokeai?.node?.type) !['t2l', 'l2l', 'inpaint'].includes(String(image?.metadata?.type))
)
} }
onClick={handleClickUseAllParameters} onClick={handleClickUseAllParameters}
/> />

View File

@ -155,7 +155,10 @@ const HoverableImage = memo((props: HoverableImageProps) => {
// Recall parameters handlers // Recall parameters handlers
const handleRecallPrompt = useCallback(() => { const handleRecallPrompt = useCallback(() => {
recallPrompt(image.metadata?.positive_conditioning); recallPrompt(
image.metadata?.positive_conditioning,
image.metadata?.negative_conditioning
);
}, [image, recallPrompt]); }, [image, recallPrompt]);
const handleRecallSeed = useCallback(() => { const handleRecallSeed = useCallback(() => {
@ -248,7 +251,8 @@ const HoverableImage = memo((props: HoverableImageProps) => {
icon={<IoArrowUndoCircleOutline />} icon={<IoArrowUndoCircleOutline />}
onClickCapture={handleUseAllParameters} onClickCapture={handleUseAllParameters}
isDisabled={ isDisabled={
!['txt2img', 'img2img', 'inpaint'].includes( // what should these be
!['t2l', 'l2l', 'inpaint'].includes(
String(image?.metadata?.type) String(image?.metadata?.type)
) )
} }

View File

@ -8,29 +8,20 @@ import {
Text, Text,
Tooltip, Tooltip,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import * as InvokeAI from 'app/types/invokeai';
import { useAppDispatch } from 'app/store/storeHooks'; import { useAppDispatch } from 'app/store/storeHooks';
import { useGetUrl } from 'common/util/getUrl'; import { useGetUrl } from 'common/util/getUrl';
import promptToString from 'common/util/promptToString'; import promptToString from 'common/util/promptToString';
import { seedWeightsToString } from 'common/util/seedWeightPairs';
import useSetBothPrompts from 'features/parameters/hooks/usePrompt';
import { import {
setCfgScale, setCfgScale,
setHeight, setHeight,
setImg2imgStrength, setImg2imgStrength,
setNegativePrompt, setNegativePrompt,
setPerlin,
setPositivePrompt, setPositivePrompt,
setScheduler, setScheduler,
setSeamless,
setSeed, setSeed,
setSeedWeights,
setShouldFitToWidthHeight,
setSteps, setSteps,
setThreshold,
setWidth, setWidth,
} from 'features/parameters/store/generationSlice'; } from 'features/parameters/store/generationSlice';
import { setHiresFix } from 'features/parameters/store/postprocessingSlice';
import { setShouldShowImageDetails } from 'features/ui/store/uiSlice'; import { setShouldShowImageDetails } from 'features/ui/store/uiSlice';
import { memo } from 'react'; import { memo } from 'react';
import { useHotkeys } from 'react-hotkeys-hook'; import { useHotkeys } from 'react-hotkeys-hook';
@ -39,7 +30,6 @@ import { FaCopy } from 'react-icons/fa';
import { IoArrowUndoCircleOutline } from 'react-icons/io5'; import { IoArrowUndoCircleOutline } from 'react-icons/io5';
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react'; import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
import { ImageDTO } from 'services/api'; import { ImageDTO } from 'services/api';
import { filter } from 'lodash-es';
import { Scheduler } from 'app/constants'; import { Scheduler } from 'app/constants';
type MetadataItemProps = { type MetadataItemProps = {
@ -126,8 +116,6 @@ const memoEqualityCheck = (
const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => { const ImageMetadataViewer = memo(({ image }: ImageMetadataViewerProps) => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const setBothPrompts = useSetBothPrompts();
useHotkeys('esc', () => { useHotkeys('esc', () => {
dispatch(setShouldShowImageDetails(false)); dispatch(setShouldShowImageDetails(false));
}); });

View File

@ -33,7 +33,7 @@ export const nextPrevImageButtonsSelector = createSelector(
} }
const currentImageIndex = state[currentCategory].ids.findIndex( const currentImageIndex = state[currentCategory].ids.findIndex(
(i) => i === selectedImage.name (i) => i === selectedImage.image_name
); );
const nextImageIndex = clamp( const nextImageIndex = clamp(

View File

@ -11,7 +11,7 @@ import { addNoiseNodes } from '../nodeBuilders/addNoiseNodes';
const POSITIVE_CONDITIONING = 'positive_conditioning'; const POSITIVE_CONDITIONING = 'positive_conditioning';
const NEGATIVE_CONDITIONING = 'negative_conditioning'; const NEGATIVE_CONDITIONING = 'negative_conditioning';
const TEXT_TO_LATENTS = 'text_to_latents'; const TEXT_TO_LATENTS = 'text_to_latents';
const LATENTS_TO_IMAGE = 'latnets_to_image'; const LATENTS_TO_IMAGE = 'latents_to_image';
/** /**
* Builds the Text to Image tab graph. * Builds the Text to Image tab graph.

View File

@ -21,8 +21,8 @@ export const useParameters = () => {
* Sets prompt with toast * Sets prompt with toast
*/ */
const recallPrompt = useCallback( const recallPrompt = useCallback(
(prompt: unknown) => { (prompt: unknown, negativePrompt?: unknown) => {
if (!isString(prompt)) { if (!isString(prompt) || !isString(negativePrompt)) {
toaster({ toaster({
title: t('toast.promptNotSet'), title: t('toast.promptNotSet'),
description: t('toast.promptNotSetDesc'), description: t('toast.promptNotSetDesc'),
@ -33,7 +33,7 @@ export const useParameters = () => {
return; return;
} }
setBothPrompts(prompt); setBothPrompts(prompt, negativePrompt);
toaster({ toaster({
title: t('toast.promptSet'), title: t('toast.promptSet'),
status: 'info', status: 'info',
@ -112,12 +112,13 @@ export const useParameters = () => {
const recallAllParameters = useCallback( const recallAllParameters = useCallback(
(image: ImageDTO | undefined) => { (image: ImageDTO | undefined) => {
const type = image?.metadata?.type; const type = image?.metadata?.type;
if (['txt2img', 'img2img', 'inpaint'].includes(String(type))) { // not sure what this list should be
if (['t2l', 'l2l', 'inpaint'].includes(String(type))) {
dispatch(allParametersSet(image)); dispatch(allParametersSet(image));
if (image?.metadata?.type === 'img2img') { if (image?.metadata?.type === 'l2l') {
dispatch(setActiveTab('img2img')); dispatch(setActiveTab('img2img'));
} else if (image?.metadata?.type === 'txt2img') { } else if (image?.metadata?.type === 't2l') {
dispatch(setActiveTab('txt2img')); dispatch(setActiveTab('txt2img'));
} }

View File

@ -12,15 +12,8 @@ const useSetBothPrompts = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
return useCallback( return useCallback(
(inputPrompt: InvokeAI.Prompt) => { (inputPrompt: InvokeAI.Prompt, negativePrompt: InvokeAI.Prompt) => {
const promptString = dispatch(setPositivePrompt(inputPrompt));
typeof inputPrompt === 'string'
? inputPrompt
: promptToString(inputPrompt);
const [prompt, negativePrompt] = getPromptAndNegative(promptString);
dispatch(setPositivePrompt(prompt));
dispatch(setNegativePrompt(negativePrompt)); dispatch(setNegativePrompt(negativePrompt));
}, },
[dispatch] [dispatch]

View File

@ -52,7 +52,7 @@ export const initialGenerationState: GenerationState = {
perlin: 0, perlin: 0,
positivePrompt: '', positivePrompt: '',
negativePrompt: '', negativePrompt: '',
scheduler: 'lms', scheduler: 'euler',
seamBlur: 16, seamBlur: 16,
seamSize: 96, seamSize: 96,
seamSteps: 30, seamSteps: 30,

View File

@ -7,19 +7,29 @@ export const setAllParametersReducer = (
state: Draft<GenerationState>, state: Draft<GenerationState>,
action: PayloadAction<ImageDTO | undefined> action: PayloadAction<ImageDTO | undefined>
) => { ) => {
const node = action.payload?.metadata.invokeai?.node; const metadata = action.payload?.metadata;
if (!node) { if (!metadata) {
return; return;
} }
// not sure what this list should be
if ( if (
node.type === 'txt2img' || metadata.type === 't2l' ||
node.type === 'img2img' || metadata.type === 'l2l' ||
node.type === 'inpaint' metadata.type === 'inpaint'
) { ) {
const { cfg_scale, height, model, prompt, scheduler, seed, steps, width } = const {
node; cfg_scale,
height,
model,
positive_conditioning,
negative_conditioning,
scheduler,
seed,
steps,
width,
} = metadata;
if (cfg_scale !== undefined) { if (cfg_scale !== undefined) {
state.cfgScale = Number(cfg_scale); state.cfgScale = Number(cfg_scale);
@ -30,8 +40,11 @@ export const setAllParametersReducer = (
if (model !== undefined) { if (model !== undefined) {
state.model = String(model); state.model = String(model);
} }
if (prompt !== undefined) { if (positive_conditioning !== undefined) {
state.positivePrompt = String(prompt); state.positivePrompt = String(positive_conditioning);
}
if (negative_conditioning !== undefined) {
state.negativePrompt = String(negative_conditioning);
} }
if (scheduler !== undefined) { if (scheduler !== undefined) {
const schedulerString = String(scheduler); const schedulerString = String(scheduler);
@ -51,8 +64,8 @@ export const setAllParametersReducer = (
} }
} }
if (node.type === 'img2img') { if (metadata.type === 'l2l') {
const { fit, image } = node as ImageToImageInvocation; const { fit, image } = metadata as ImageToImageInvocation;
if (fit !== undefined) { if (fit !== undefined) {
state.shouldFitToWidthHeight = Boolean(fit); state.shouldFitToWidthHeight = Boolean(fit);