From fe8b5193de73fc2809d4b8922dbf1652b66e4d93 Mon Sep 17 00:00:00 2001
From: psychedelicious <4822129+psychedelicious@users.noreply.github.com>
Date: Tue, 9 May 2023 21:39:50 +1000
Subject: [PATCH] feat(ui): half-baked use all parameters
until we have a better system for metadata, this will remain half-baked
---
.../components/CurrentImageButtons.tsx | 39 ++---
.../gallery/components/HoverableImage.tsx | 18 +--
.../parameters/hooks/useParameters.ts | 42 +++++-
.../parameters/store/generationSlice.ts | 134 +-----------------
.../store/setAllParametersReducer.ts | 61 ++++++++
5 files changed, 118 insertions(+), 176 deletions(-)
create mode 100644 invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts
diff --git a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx
index a0ff83b8c6..32e631005d 100644
--- a/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/CurrentImageButtons.tsx
@@ -61,6 +61,7 @@ import { initialImageSelected } from 'features/parameters/store/actions';
import { requestedImageDeletion } from '../store/actions';
import FaceRestoreSettings from 'features/parameters/components/Parameters/FaceRestore/FaceRestoreSettings';
import UpscaleSettings from 'features/parameters/components/Parameters/Upscale/UpscaleSettings';
+import { allParametersSet } from 'features/parameters/store/generationSlice';
const currentImageButtonsSelector = createSelector(
[
@@ -157,7 +158,7 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
const toast = useToast();
const { t } = useTranslation();
- const { recallPrompt, recallSeed } = useParameters();
+ const { recallPrompt, recallSeed, recallAllParameters } = useParameters();
// const handleCopyImage = useCallback(async () => {
// if (!image?.url) {
@@ -228,39 +229,15 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
}, [dispatch, shouldHidePreview]);
const handleClickUseAllParameters = useCallback(() => {
- if (!image) return;
- // selectedImage.metadata &&
- // dispatch(setAllParameters(selectedImage.metadata));
- // if (selectedImage.metadata?.image.type === 'img2img') {
- // dispatch(setActiveTab('img2img'));
- // } else if (selectedImage.metadata?.image.type === 'txt2img') {
- // dispatch(setActiveTab('txt2img'));
- // }
- }, [image]);
+ recallAllParameters(image);
+ }, [image, recallAllParameters]);
useHotkeys(
'a',
() => {
- const type = image?.metadata?.invokeai?.node?.types;
- if (isString(type) && ['txt2img', 'img2img'].includes(type)) {
- handleClickUseAllParameters();
- toast({
- title: t('toast.parametersSet'),
- status: 'success',
- duration: 2500,
- isClosable: true,
- });
- } else {
- toast({
- title: t('toast.parametersNotSet'),
- description: t('toast.parametersNotSetDesc'),
- status: 'error',
- duration: 2500,
- isClosable: true,
- });
- }
+ handleClickUseAllParameters;
},
- [image]
+ [image, recallAllParameters]
);
const handleUseSeed = useCallback(() => {
@@ -530,8 +507,8 @@ const CurrentImageButtons = (props: CurrentImageButtonsProps) => {
tooltip={`${t('parameters.useAll')} (A)`}
aria-label={`${t('parameters.useAll')} (A)`}
isDisabled={
- !['txt2img', 'img2img'].includes(
- image?.metadata?.sd_metadata?.type
+ !['txt2img', 'img2img', 'inpaint'].includes(
+ String(image?.metadata?.invokeai?.node?.type)
)
}
onClick={handleClickUseAllParameters}
diff --git a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx
index 3c2dcdf818..d2fba22c3e 100644
--- a/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx
+++ b/invokeai/frontend/web/src/features/gallery/components/HoverableImage.tsx
@@ -105,7 +105,8 @@ const HoverableImage = memo((props: HoverableImageProps) => {
const { t } = useTranslation();
const { isFeatureEnabled: isLightboxEnabled } = useFeatureStatus('lightbox');
- const { recallSeed, recallPrompt, recallInitialImage } = useParameters();
+ const { recallSeed, recallPrompt, recallInitialImage, recallAllParameters } =
+ useParameters();
const handleMouseOver = () => setIsHovered(true);
const handleMouseOut = () => setIsHovered(false);
@@ -176,16 +177,9 @@ const HoverableImage = memo((props: HoverableImageProps) => {
});
};
- const handleUseAllParameters = () => {
- // metadata.invokeai?.node &&
- // dispatch(setAllParameters(metadata.invokeai?.node));
- // toast({
- // title: t('toast.parametersSet'),
- // status: 'success',
- // duration: 2500,
- // isClosable: true,
- // });
- };
+ const handleUseAllParameters = useCallback(() => {
+ recallAllParameters(image);
+ }, [image, recallAllParameters]);
const handleLightBox = () => {
// dispatch(setCurrentImage(image));
@@ -239,7 +233,7 @@ const HoverableImage = memo((props: HoverableImageProps) => {
icon={}
onClickCapture={handleUseAllParameters}
isDisabled={
- !['txt2img', 'img2img'].includes(
+ !['txt2img', 'img2img', 'inpaint'].includes(
String(image?.metadata?.invokeai?.node?.type)
)
}
diff --git a/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts
index 7b8dc455ac..a093010343 100644
--- a/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts
+++ b/invokeai/frontend/web/src/features/parameters/hooks/useParameters.ts
@@ -4,11 +4,12 @@ import { isFinite, isString } from 'lodash-es';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import useSetBothPrompts from './usePrompt';
-import { setSeed } from '../store/generationSlice';
+import { allParametersSet, setSeed } from '../store/generationSlice';
import { isImageField } from 'services/types/guards';
import { NUMPY_RAND_MAX } from 'app/constants';
import { initialImageSelected } from '../store/actions';
import { Image } from 'app/types/invokeai';
+import { setActiveTab } from 'features/ui/store/uiSlice';
export const useParameters = () => {
const dispatch = useAppDispatch();
@@ -110,5 +111,42 @@ export const useParameters = () => {
[dispatch]
);
- return { recallPrompt, recallSeed, recallInitialImage, sendToImageToImage };
+ const recallAllParameters = useCallback(
+ (image: Image | undefined) => {
+ const type = image?.metadata?.invokeai?.node?.type;
+ if (['txt2img', 'img2img', 'inpaint'].includes(String(type))) {
+ dispatch(allParametersSet(image));
+
+ if (image?.metadata?.invokeai?.node?.type === 'img2img') {
+ dispatch(setActiveTab('img2img'));
+ } else if (image?.metadata?.invokeai?.node?.type === 'txt2img') {
+ dispatch(setActiveTab('txt2img'));
+ }
+
+ toast({
+ title: t('toast.parametersSet'),
+ status: 'success',
+ duration: 2500,
+ isClosable: true,
+ });
+ } else {
+ toast({
+ title: t('toast.parametersNotSet'),
+ description: t('toast.parametersNotSetDesc'),
+ status: 'error',
+ duration: 2500,
+ isClosable: true,
+ });
+ }
+ },
+ [t, toast, dispatch]
+ );
+
+ return {
+ recallPrompt,
+ recallSeed,
+ recallInitialImage,
+ sendToImageToImage,
+ recallAllParameters,
+ };
};
diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
index 948ba4cc1e..e1bb20c1ab 100644
--- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
+++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts
@@ -3,6 +3,7 @@ import { createSlice } from '@reduxjs/toolkit';
import * as InvokeAI from 'app/types/invokeai';
import promptToString from 'common/util/promptToString';
import { clamp } from 'lodash-es';
+import { setAllParametersReducer } from './setAllParametersReducer';
export interface GenerationState {
cfgScale: number;
@@ -187,131 +188,7 @@ export const generationSlice = createSlice({
state.shouldGenerateVariations = true;
state.variationAmount = 0;
},
- setAllTextToImageParameters: (
- state,
- action: PayloadAction
- ) => {
- // const {
- // sampler,
- // prompt,
- // seed,
- // variations,
- // steps,
- // cfg_scale,
- // threshold,
- // perlin,
- // seamless,
- // _hires_fix,
- // width,
- // height,
- // } = action.payload.image;
- // if (variations && variations.length > 0) {
- // state.seedWeights = seedWeightsToString(variations);
- // state.shouldGenerateVariations = true;
- // state.variationAmount = 0;
- // } else {
- // state.shouldGenerateVariations = false;
- // }
- // if (seed) {
- // state.seed = seed;
- // state.shouldRandomizeSeed = false;
- // }
- // if (prompt) state.prompt = promptToString(prompt);
- // if (sampler) state.sampler = sampler;
- // if (steps) state.steps = steps;
- // if (cfg_scale) state.cfgScale = cfg_scale;
- // if (typeof threshold === 'undefined') {
- // state.threshold = 0;
- // } else {
- // state.threshold = threshold;
- // }
- // if (typeof perlin === 'undefined') {
- // state.perlin = 0;
- // } else {
- // state.perlin = perlin;
- // }
- // if (typeof seamless === 'boolean') state.seamless = seamless;
- // // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg
- // if (width) state.width = width;
- // if (height) state.height = height;
- },
- setAllImageToImageParameters: (
- state,
- action: PayloadAction
- ) => {
- // const { type, strength, fit, init_image_path, mask_image_path } =
- // action.payload.image;
- // if (type === 'img2img') {
- // if (init_image_path) state.initialImage = init_image_path;
- // if (mask_image_path) state.maskPath = mask_image_path;
- // if (strength) state.img2imgStrength = strength;
- // if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit;
- // }
- },
- setAllParameters: (state, action: PayloadAction) => {
- // const {
- // type,
- // sampler,
- // prompt,
- // seed,
- // variations,
- // steps,
- // cfg_scale,
- // threshold,
- // perlin,
- // seamless,
- // _hires_fix,
- // width,
- // height,
- // strength,
- // fit,
- // init_image_path,
- // mask_image_path,
- // } = action.payload.image;
- // if (type === 'img2img') {
- // if (init_image_path) state.initialImage = init_image_path;
- // if (mask_image_path) state.maskPath = mask_image_path;
- // if (strength) state.img2imgStrength = strength;
- // if (typeof fit === 'boolean') state.shouldFitToWidthHeight = fit;
- // }
- // if (variations && variations.length > 0) {
- // state.seedWeights = seedWeightsToString(variations);
- // state.shouldGenerateVariations = true;
- // state.variationAmount = 0;
- // } else {
- // state.shouldGenerateVariations = false;
- // }
- // if (seed) {
- // state.seed = seed;
- // state.shouldRandomizeSeed = false;
- // }
- // if (prompt) {
- // const [promptOnly, negativePrompt] = getPromptAndNegative(prompt);
- // if (promptOnly) state.prompt = promptOnly;
- // negativePrompt
- // ? (state.negativePrompt = negativePrompt)
- // : (state.negativePrompt = '');
- // }
- // if (sampler) state.sampler = sampler;
- // if (steps) state.steps = steps;
- // if (cfg_scale) state.cfgScale = cfg_scale;
- // if (typeof threshold === 'undefined') {
- // state.threshold = 0;
- // } else {
- // state.threshold = threshold;
- // }
- // if (typeof perlin === 'undefined') {
- // state.perlin = 0;
- // } else {
- // state.perlin = perlin;
- // }
- // if (typeof seamless === 'boolean') state.seamless = seamless;
- // // if (typeof hires_fix === 'boolean') state.hiresFix = hires_fix; // TODO: Needs to be fixed after reorg
- // if (width) state.width = width;
- // if (height) state.height = height;
- // // state.shouldRunESRGAN = false; // TODO: Needs to be fixed after reorg
- // // state.shouldRunFacetool = false; // TODO: Needs to be fixed after reorg
- },
+ allParametersSet: setAllParametersReducer,
resetParametersState: (state) => {
return {
...state,
@@ -321,12 +198,6 @@ export const generationSlice = createSlice({
setShouldRandomizeSeed: (state, action: PayloadAction) => {
state.shouldRandomizeSeed = action.payload;
},
- // setInitialImage: (
- // state,
- // action: PayloadAction
- // ) => {
- // state.initialImage = action.payload;
- // },
clearInitialImage: (state) => {
state.initialImage = undefined;
},
@@ -417,6 +288,7 @@ export const {
setSeamless,
setSeamlessXAxis,
setSeamlessYAxis,
+ allParametersSet,
} = generationSlice.actions;
export default generationSlice.reducer;
diff --git a/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts b/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts
new file mode 100644
index 0000000000..7b02647ebc
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/store/setAllParametersReducer.ts
@@ -0,0 +1,61 @@
+import { Draft, PayloadAction } from '@reduxjs/toolkit';
+import { Image } from 'app/types/invokeai';
+import { GenerationState } from './generationSlice';
+import { ImageToImageInvocation } from 'services/api';
+
+export const setAllParametersReducer = (
+ state: Draft,
+ action: PayloadAction
+) => {
+ const node = action.payload?.metadata.invokeai?.node;
+
+ if (!node) {
+ return;
+ }
+
+ if (
+ node.type === 'txt2img' ||
+ node.type === 'img2img' ||
+ node.type === 'inpaint'
+ ) {
+ const { cfg_scale, height, model, prompt, scheduler, seed, steps, width } =
+ node;
+
+ if (cfg_scale !== undefined) {
+ state.cfgScale = Number(cfg_scale);
+ }
+ if (height !== undefined) {
+ state.height = Number(height);
+ }
+ if (model !== undefined) {
+ state.model = String(model);
+ }
+ if (prompt !== undefined) {
+ state.prompt = String(prompt);
+ }
+ if (scheduler !== undefined) {
+ state.sampler = String(scheduler);
+ }
+ if (seed !== undefined) {
+ state.seed = Number(seed);
+ state.shouldRandomizeSeed = false;
+ }
+ if (steps !== undefined) {
+ state.steps = Number(steps);
+ }
+ if (width !== undefined) {
+ state.width = Number(width);
+ }
+ }
+
+ if (node.type === 'img2img') {
+ const { fit, image } = node as ImageToImageInvocation;
+
+ if (fit !== undefined) {
+ state.shouldFitToWidthHeight = Boolean(fit);
+ }
+ // if (image !== undefined) {
+ // state.initialImage = image;
+ // }
+ }
+};