feat(ui): add IAICollapse for parameters

This commit is contained in:
psychedelicious
2023-05-08 19:05:43 +10:00
parent 864f4bb4af
commit 33c69359c2
66 changed files with 1076 additions and 572 deletions

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setSeamBlur } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function SeamBlur() {
export default function ParamSeamBlur() {
const dispatch = useAppDispatch();
const seamBlur = useAppSelector(
(state: RootState) => state.generation.seamBlur

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setSeamSize } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function SeamSize() {
export default function ParamSeamSize() {
const dispatch = useAppDispatch();
const { t } = useTranslation();

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setSeamSteps } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function SeamSteps() {
export default function ParamSeamSteps() {
const { t } = useTranslation();
const seamSteps = useAppSelector(
(state: RootState) => state.generation.seamSteps

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setSeamStrength } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function SeamStrength() {
export default function ParamSeamStrength() {
const dispatch = useAppDispatch();
const { t } = useTranslation();
const seamStrength = useAppSelector(

View File

@ -1,16 +1,16 @@
import { VStack } from '@chakra-ui/react';
import SeamBlur from './SeamBlur';
import SeamSize from './SeamSize';
import SeamSteps from './SeamSteps';
import SeamStrength from './SeamStrength';
import ParamSeamBlur from './ParamSeamBlur';
import ParamSeamSize from './ParamSeamSize';
import ParamSeamSteps from './ParamSeamSteps';
import ParamSeamStrength from './ParamSeamStrength';
const SeamCorrectionSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<SeamSize />
<SeamBlur />
<SeamStrength />
<SeamSteps />
<ParamSeamSize />
<ParamSeamBlur />
<ParamSeamStrength />
<ParamSeamSteps />
</VStack>
);
};

View File

@ -1,12 +0,0 @@
import { VStack } from '@chakra-ui/react';
import SeamlessSettings from './SeamlessSettings';
const ImageToImageOutputSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<SeamlessSettings />
</VStack>
);
};
export default ImageToImageOutputSettings;

View File

@ -1,15 +0,0 @@
import { VStack } from '@chakra-ui/react';
import { HiresStrength, HiresToggle } from './HiresSettings';
import SeamlessSettings from './SeamlessSettings';
const OutputSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<SeamlessSettings />
<HiresToggle />
<HiresStrength />
</VStack>
);
};
export default OutputSettings;

View File

@ -1,54 +0,0 @@
import { VStack } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import {
setHorizontalSymmetrySteps,
setVerticalSymmetrySteps,
} from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function SymmetrySettings() {
const horizontalSymmetrySteps = useAppSelector(
(state: RootState) => state.generation.horizontalSymmetrySteps
);
const verticalSymmetrySteps = useAppSelector(
(state: RootState) => state.generation.verticalSymmetrySteps
);
const steps = useAppSelector((state: RootState) => state.generation.steps);
const dispatch = useAppDispatch();
const { t } = useTranslation();
return (
<VStack gap={2} alignItems="stretch">
<IAISlider
label={t('parameters.hSymmetryStep')}
value={horizontalSymmetrySteps}
onChange={(v) => dispatch(setHorizontalSymmetrySteps(v))}
min={0}
max={steps}
step={1}
withInput
withSliderMarks
withReset
handleReset={() => dispatch(setHorizontalSymmetrySteps(0))}
/>
<IAISlider
label={t('parameters.vSymmetryStep')}
value={verticalSymmetrySteps}
onChange={(v) => dispatch(setVerticalSymmetrySteps(v))}
min={0}
max={steps}
step={1}
withInput
withSliderMarks
withReset
handleReset={() => dispatch(setVerticalSymmetrySteps(0))}
/>
</VStack>
);
}

View File

@ -1,20 +0,0 @@
import { VStack } from '@chakra-ui/react';
import Perlin from './Perlin';
import RandomizeSeed from './RandomizeSeed';
import Seed from './Seed';
import Threshold from './Threshold';
/**
* Seed & variation options. Includes iteration, seed, seed randomization, variation options.
*/
const SeedSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<Seed />
<Threshold />
<Perlin />
</VStack>
);
};
export default SeedSettings;

View File

@ -1,25 +0,0 @@
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISwitch from 'common/components/IAISwitch';
import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice';
import { ChangeEvent } from 'react';
export default function GenerateVariationsToggle() {
const shouldGenerateVariations = useAppSelector(
(state: RootState) => state.generation.shouldGenerateVariations
);
const dispatch = useAppDispatch();
const handleChangeShouldGenerateVariations = (
e: ChangeEvent<HTMLInputElement>
) => dispatch(setShouldGenerateVariations(e.target.checked));
return (
<IAISwitch
isChecked={shouldGenerateVariations}
width="auto"
onChange={handleChangeShouldGenerateVariations}
/>
);
}

View File

@ -1,17 +0,0 @@
import { VStack } from '@chakra-ui/react';
import SeedWeights from './SeedWeights';
import VariationAmount from './VariationAmount';
/**
* Seed & variation options. Includes iteration, seed, seed randomization, variation options.
*/
const VariationsSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<VariationAmount />
<SeedWeights />
</VStack>
);
};
export default VariationsSettings;

View File

@ -1,14 +1,15 @@
import { memo } from 'react';
import { Box, Flex, VStack } from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppSelector } from 'app/store/storeHooks';
import ModelSelect from 'features/system/components/ModelSelect';
import { memo } from 'react';
import HeightSlider from './HeightSlider';
import MainCFGScale from './MainCFGScale';
import MainIterations from './MainIterations';
import MainSampler from './MainSampler';
import MainSteps from './MainSteps';
import WidthSlider from './WidthSlider';
import ParamHeight from 'features/parameters/components/Parameters/ParamHeight';
import ParamCFGScale from 'features/parameters/components/Parameters/ParamCFGScale';
import ParamIterations from 'features/parameters/components/Parameters/ParamIterations';
import ParamScheduler from 'features/parameters/components/Parameters/ParamScheduler';
import ParamSteps from 'features/parameters/components/Parameters/ParamSteps';
import ParamWidth from 'features/parameters/components/Parameters/ParamWidth';
const MainSettings = () => {
const shouldUseSliders = useAppSelector(
@ -17,14 +18,14 @@ const MainSettings = () => {
return shouldUseSliders ? (
<VStack gap={2}>
<MainIterations />
<MainSteps />
<MainCFGScale />
<WidthSlider />
<HeightSlider />
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<MainSampler />
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />
@ -34,15 +35,15 @@ const MainSettings = () => {
) : (
<Flex gap={3} flexDirection="column">
<Flex gap={3}>
<MainIterations />
<MainSteps />
<MainCFGScale />
<ParamIterations />
<ParamSteps />
<ParamCFGScale />
</Flex>
<WidthSlider />
<HeightSlider />
<ParamWidth />
<ParamHeight />
<Flex gap={3} w="full">
<Box flexGrow={2}>
<MainSampler />
<ParamScheduler />
</Box>
<Box flexGrow={3}>
<ModelSelect />

View File

@ -0,0 +1,37 @@
import { Flex } from '@chakra-ui/react';
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { RootState } from 'app/store/store';
import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
import { ParamHiresStrength } from './ParamHiresStrength';
import { setHiresFix } from 'features/parameters/store/postprocessingSlice';
/**
* Seed & variation options. Includes iteration, seed, seed randomization, variation options.
*/
const ParamHiresCollapse = () => {
const { t } = useTranslation();
const hiresFix = useAppSelector(
(state: RootState) => state.postprocessing.hiresFix
);
const dispatch = useAppDispatch();
const handleToggle = () => dispatch(setHiresFix(!hiresFix));
return (
<IAICollapse
label={t('parameters.hiresOptim')}
isOpen={hiresFix}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamHiresStrength />
</Flex>
</IAICollapse>
);
};
export default memo(ParamHiresCollapse);

View File

@ -0,0 +1,3 @@
// TODO
export default {};

View File

@ -0,0 +1,3 @@
// TODO
export default {};

View File

@ -1,15 +1,9 @@
import { createSelector } from '@reduxjs/toolkit';
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import IAISwitch from 'common/components/IAISwitch';
import { postprocessingSelector } from 'features/parameters/store/postprocessingSelectors';
import {
setHiresFix,
setHiresStrength,
} from 'features/parameters/store/postprocessingSlice';
import { setHiresStrength } from 'features/parameters/store/postprocessingSlice';
import { isEqual } from 'lodash-es';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
const hiresStrengthSelector = createSelector(
@ -22,7 +16,7 @@ const hiresStrengthSelector = createSelector(
}
);
export const HiresStrength = () => {
export const ParamHiresStrength = () => {
const { hiresFix, hiresStrength } = useAppSelector(hiresStrengthSelector);
const dispatch = useAppDispatch();
@ -55,28 +49,3 @@ export const HiresStrength = () => {
/>
);
};
/**
* Hires Fix Toggle
*/
export const HiresToggle = () => {
const dispatch = useAppDispatch();
const hiresFix = useAppSelector(
(state: RootState) => state.postprocessing.hiresFix
);
const { t } = useTranslation();
const handleChangeHiresFix = (e: ChangeEvent<HTMLInputElement>) =>
dispatch(setHiresFix(e.target.checked));
return (
<IAISwitch
label={t('parameters.hiresOptim')}
fontSize="md"
isChecked={hiresFix}
onChange={handleChangeHiresFix}
/>
);
};

View File

@ -0,0 +1,31 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISwitch from 'common/components/IAISwitch';
import { setHiresFix } from 'features/parameters/store/postprocessingSlice';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
/**
* Hires Fix Toggle
*/
export const ParamHiresToggle = () => {
const dispatch = useAppDispatch();
const hiresFix = useAppSelector(
(state: RootState) => state.postprocessing.hiresFix
);
const { t } = useTranslation();
const handleChangeHiresFix = (e: ChangeEvent<HTMLInputElement>) =>
dispatch(setHiresFix(e.target.checked));
return (
<IAISwitch
label={t('parameters.hiresOptim')}
fontSize="md"
isChecked={hiresFix}
onChange={handleChangeHiresFix}
/>
);
};

View File

@ -0,0 +1,3 @@
// TODO
export default {};

View File

@ -0,0 +1,37 @@
import { useTranslation } from 'react-i18next';
import { Flex } from '@chakra-ui/react';
import IAICollapse from 'common/components/IAICollapse';
import ParamPerlinNoise from './ParamPerlinNoise';
import ParamNoiseThreshold from './ParamNoiseThreshold';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { setShouldUseNoiseSettings } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
const ParamNoiseCollapse = () => {
const { t } = useTranslation();
const shouldUseNoiseSettings = useAppSelector(
(state: RootState) => state.generation.shouldUseNoiseSettings
);
const dispatch = useAppDispatch();
const handleToggle = () =>
dispatch(setShouldUseNoiseSettings(!shouldUseNoiseSettings));
return (
<IAICollapse
label={t('parameters.noiseSettings')}
isOpen={shouldUseNoiseSettings}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamPerlinNoise />
<ParamNoiseThreshold />
</Flex>
</IAICollapse>
);
};
export default memo(ParamNoiseCollapse);

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setThreshold } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function Threshold() {
export default function ParamNoiseThreshold() {
const dispatch = useAppDispatch();
const threshold = useAppSelector(
(state: RootState) => state.generation.threshold

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setPerlin } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function Perlin() {
export default function ParamPerlinNoise() {
const dispatch = useAppDispatch();
const perlin = useAppSelector((state: RootState) => state.generation.perlin);
const { t } = useTranslation();

View File

@ -0,0 +1,18 @@
import { VStack } from '@chakra-ui/react';
import ParamSeamlessToggle from './Seamless/ParamSeamlessToggle';
// import ParamSeamlessAxes from '../../Parameters/Seamless/ParamSeamlessAxes';
import { ParamHiresToggle } from './Hires/ParamHiresToggle';
import { ParamHiresStrength } from './Hires/ParamHiresStrength';
const OtherSettings = () => {
return (
<VStack gap={2} alignItems="stretch">
<ParamSeamlessToggle />
{/* <ParamSeamlessAxes /> */}
<ParamHiresToggle />
<ParamHiresStrength />
</VStack>
);
};
export default OtherSettings;

View File

@ -30,7 +30,7 @@ const selector = createSelector(
}
);
const GuidanceScale = () => {
const ParamCFGScale = () => {
const {
cfgScale,
initial,
@ -82,4 +82,4 @@ const GuidanceScale = () => {
);
};
export default memo(GuidanceScale);
export default memo(ParamCFGScale);

View File

@ -31,7 +31,7 @@ const selector = createSelector(
}
);
const HeightSlider = () => {
const ParamHeight = () => {
const {
height,
initial,
@ -74,4 +74,4 @@ const HeightSlider = () => {
);
};
export default memo(HeightSlider);
export default memo(ParamHeight);

View File

@ -32,7 +32,7 @@ const selector = createSelector(
}
);
const MainIterations = () => {
const ParamIterations = () => {
const {
iterations,
initial,
@ -83,4 +83,4 @@ const MainIterations = () => {
);
};
export default memo(MainIterations);
export default memo(ParamIterations);

View File

@ -4,7 +4,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { setNegativePrompt } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
const NegativePromptInput = () => {
const ParamNegativeConditioning = () => {
const negativePrompt = useAppSelector(
(state: RootState) => state.generation.negativePrompt
);
@ -29,4 +29,4 @@ const NegativePromptInput = () => {
);
};
export default NegativePromptInput;
export default ParamNegativeConditioning;

View File

@ -35,7 +35,7 @@ const promptInputSelector = createSelector(
/**
* Prompt input text area.
*/
const PromptInput = () => {
const ParamPositiveConditioning = () => {
const dispatch = useAppDispatch();
const { prompt, activeTabName } = useAppSelector(promptInputSelector);
const { isReady } = useAppSelector(readinessSelector);
@ -88,4 +88,4 @@ const PromptInput = () => {
);
};
export default PromptInput;
export default ParamPositiveConditioning;

View File

@ -6,7 +6,7 @@ import { setSampler } from 'features/parameters/store/generationSlice';
import { ChangeEvent, memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const Scheduler = () => {
const ParamScheduler = () => {
const sampler = useAppSelector(
(state: RootState) => state.generation.sampler
);
@ -29,4 +29,4 @@ const Scheduler = () => {
);
};
export default memo(Scheduler);
export default memo(ParamScheduler);

View File

@ -36,7 +36,7 @@ const selector = createSelector(
}
);
const MainSteps = () => {
const ParamSteps = () => {
const { steps, initial, min, sliderMax, inputMax, step, shouldUseSliders } =
useAppSelector(selector);
const dispatch = useAppDispatch();
@ -84,4 +84,4 @@ const MainSteps = () => {
);
};
export default memo(MainSteps);
export default memo(ParamSteps);

View File

@ -30,7 +30,7 @@ const selector = createSelector(
}
);
const WidthSlider = () => {
const ParamWidth = () => {
const {
width,
initial,
@ -73,4 +73,4 @@ const WidthSlider = () => {
);
};
export default memo(WidthSlider);
export default memo(ParamWidth);

View File

@ -0,0 +1,51 @@
import { useTranslation } from 'react-i18next';
import { Box, Flex } from '@chakra-ui/react';
import IAICollapse from 'common/components/IAICollapse';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { setSeamless } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
import { createSelector } from '@reduxjs/toolkit';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import ParamSeamlessXAxis from './ParamSeamlessXAxis';
import ParamSeamlessYAxis from './ParamSeamlessYAxis';
const selector = createSelector(
generationSelector,
(generation) => {
const { shouldUseSeamless, seamlessXAxis, seamlessYAxis } = generation;
return { shouldUseSeamless, seamlessXAxis, seamlessYAxis };
},
defaultSelectorOptions
);
const ParamSeamlessCollapse = () => {
const { t } = useTranslation();
const { shouldUseSeamless, seamlessXAxis, seamlessYAxis } =
useAppSelector(selector);
const dispatch = useAppDispatch();
const handleToggle = () => dispatch(setSeamless(!shouldUseSeamless));
return (
<IAICollapse
label={t('parameters.seamlessTiling')}
isOpen={shouldUseSeamless}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 5 }}>
<Box flexGrow={1}>
<ParamSeamlessXAxis />
</Box>
<Box flexGrow={1}>
<ParamSeamlessYAxis />
</Box>
</Flex>
</IAICollapse>
);
};
export default memo(ParamSeamlessCollapse);

View File

@ -8,7 +8,7 @@ import { useTranslation } from 'react-i18next';
/**
* Seamless tiling toggle
*/
const SeamlessSettings = () => {
const ParamSeamlessToggle = () => {
const dispatch = useAppDispatch();
const seamless = useAppSelector(
@ -30,4 +30,4 @@ const SeamlessSettings = () => {
);
};
export default SeamlessSettings;
export default ParamSeamlessToggle;

View File

@ -0,0 +1,43 @@
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { ChangeEvent, memo, useCallback } from 'react';
import { createSelector } from '@reduxjs/toolkit';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch';
import { setSeamlessXAxis } from 'features/parameters/store/generationSlice';
const selector = createSelector(
generationSelector,
(generation) => {
const { seamlessXAxis } = generation;
return { seamlessXAxis };
},
defaultSelectorOptions
);
const ParamSeamlessXAxis = () => {
const { t } = useTranslation();
const { seamlessXAxis } = useAppSelector(selector);
const dispatch = useAppDispatch();
const handleChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
dispatch(setSeamlessXAxis(e.target.checked));
},
[dispatch]
);
return (
<IAISwitch
label={t('parameters.seamlessXAxis')}
aria-label={t('parameters.seamlessXAxis')}
isChecked={seamlessXAxis}
onChange={handleChange}
/>
);
};
export default memo(ParamSeamlessXAxis);

View File

@ -0,0 +1,43 @@
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { ChangeEvent, memo, useCallback } from 'react';
import { createSelector } from '@reduxjs/toolkit';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import IAISwitch from 'common/components/IAISwitch';
import { setSeamlessYAxis } from 'features/parameters/store/generationSlice';
const selector = createSelector(
generationSelector,
(generation) => {
const { seamlessYAxis } = generation;
return { seamlessYAxis };
},
defaultSelectorOptions
);
const ParamSeamlessYAxis = () => {
const { t } = useTranslation();
const { seamlessYAxis } = useAppSelector(selector);
const dispatch = useAppDispatch();
const handleChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
dispatch(setSeamlessYAxis(e.target.checked));
},
[dispatch]
);
return (
<IAISwitch
label={t('parameters.seamlessYAxis')}
aria-label={t('parameters.seamlessYAxis')}
isChecked={seamlessYAxis}
onChange={handleChange}
/>
);
};
export default memo(ParamSeamlessYAxis);

View File

@ -1,13 +1,14 @@
import { HStack } from '@chakra-ui/react';
import { Flex, HStack } from '@chakra-ui/react';
import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAINumberInput from 'common/components/IAINumberInput';
import { setSeed } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
import ShuffleSeed from './ShuffleSeed';
import ParamSeedShuffle from './ParamSeedShuffle';
import ParamSeedRandomize from './ParamSeedRandomize';
export default function Seed() {
export default function ParamSeed() {
const seed = useAppSelector((state: RootState) => state.generation.seed);
const shouldRandomizeSeed = useAppSelector(
(state: RootState) => state.generation.shouldRandomizeSeed
@ -23,25 +24,22 @@ export default function Seed() {
const handleChangeSeed = (v: number) => dispatch(setSeed(v));
return (
<HStack gap={2}>
<IAINumberInput
label={t('parameters.seed')}
step={1}
precision={0}
flexGrow={1}
min={NUMPY_RAND_MIN}
max={NUMPY_RAND_MAX}
isDisabled={shouldRandomizeSeed}
isInvalid={seed < 0 && shouldGenerateVariations}
onChange={handleChangeSeed}
value={seed}
formControlProps={{
display: 'flex',
alignItems: 'center',
gap: 3, // really this should work with 2 but seems to need to be 3 to match gap 2?
}}
/>
<ShuffleSeed />
</HStack>
<IAINumberInput
label={t('parameters.seed')}
step={1}
precision={0}
flexGrow={1}
min={NUMPY_RAND_MIN}
max={NUMPY_RAND_MAX}
isDisabled={shouldRandomizeSeed}
isInvalid={seed < 0 && shouldGenerateVariations}
onChange={handleChangeSeed}
value={seed}
formControlProps={{
display: 'flex',
alignItems: 'center',
gap: 3, // really this should work with 2 but seems to need to be 3 to match gap 2?
}}
/>
);
}

View File

@ -0,0 +1,48 @@
import { Flex } from '@chakra-ui/react';
import ParamSeed from './ParamSeed';
import { memo, useCallback } from 'react';
import ParamSeedShuffle from './ParamSeedShuffle';
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { createSelector } from '@reduxjs/toolkit';
import { generationSelector } from 'features/parameters/store/generationSelectors';
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice';
import IAICollapse from 'common/components/IAICollapse';
const selector = createSelector(
generationSelector,
(generation) => {
const { shouldRandomizeSeed } = generation;
return { shouldRandomizeSeed };
},
defaultSelectorOptions
);
const ParamSeedSettings = () => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { shouldRandomizeSeed } = useAppSelector(selector);
const handleToggle = useCallback(
() => dispatch(setShouldRandomizeSeed(!shouldRandomizeSeed)),
[dispatch, shouldRandomizeSeed]
);
return (
<IAICollapse
label={t('parameters.seed')}
isOpen={!shouldRandomizeSeed}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 4 }}>
<ParamSeed />
<ParamSeedShuffle />
</Flex>
</IAICollapse>
);
};
export default memo(ParamSeedSettings);

View File

@ -5,7 +5,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISwitch from 'common/components/IAISwitch';
import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
import { Switch } from '@chakra-ui/react';
import { FormControl, FormLabel, Switch } from '@chakra-ui/react';
// export default function RandomizeSeed() {
// const dispatch = useAppDispatch();
@ -27,7 +27,7 @@ import { Switch } from '@chakra-ui/react';
// );
// }
const SeedToggle = () => {
const ParamSeedRandomize = () => {
const dispatch = useAppDispatch();
const { t } = useTranslation();
@ -36,15 +36,33 @@ const SeedToggle = () => {
);
const handleChangeShouldRandomizeSeed = (e: ChangeEvent<HTMLInputElement>) =>
dispatch(setShouldRandomizeSeed(!e.target.checked));
dispatch(setShouldRandomizeSeed(e.target.checked));
return (
<Switch
aria-label={t('parameters.randomizeSeed')}
isChecked={!shouldRandomizeSeed}
onChange={handleChangeShouldRandomizeSeed}
/>
<FormControl
sx={{
display: 'flex',
gap: 4,
alignItems: 'center',
}}
>
<FormLabel
sx={{
mb: 0,
flexGrow: 1,
fontSize: 'sm',
fontWeight: 600,
color: 'base.100',
}}
>
{t('parameters.randomizeSeed')}
</FormLabel>
<Switch
isChecked={shouldRandomizeSeed}
onChange={handleChangeShouldRandomizeSeed}
/>
</FormControl>
);
};
export default memo(SeedToggle);
export default memo(ParamSeedRandomize);

View File

@ -1,14 +1,15 @@
import { Button } from '@chakra-ui/react';
import { Box } from '@chakra-ui/react';
import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIButton from 'common/components/IAIButton';
import IAIIconButton from 'common/components/IAIIconButton';
import randomInt from 'common/util/randomInt';
import { setSeed } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
import { FaRandom } from 'react-icons/fa';
export default function ShuffleSeed() {
export default function ParamSeedShuffle() {
const dispatch = useAppDispatch();
const shouldRandomizeSeed = useAppSelector(
(state: RootState) => state.generation.shouldRandomizeSeed
@ -19,20 +20,14 @@ export default function ShuffleSeed() {
dispatch(setSeed(randomInt(NUMPY_RAND_MIN, NUMPY_RAND_MAX)));
return (
<IAIIconButton
<IAIButton
size="sm"
isDisabled={shouldRandomizeSeed}
aria-label={t('parameters.shuffle')}
tooltip={t('parameters.shuffle')}
icon={<FaRandom />}
onClick={handleClickRandomizeSeed}
/>
// <Button
// size="sm"
// onClick={handleClickRandomizeSeed}
// padding="0 1.5rem"
// >
// <p>{t('parameters.shuffle')}</p>
// </Button>
>
<Box px={2}> {t('parameters.shuffle')}</Box>
</IAIButton>
);
}

View File

@ -0,0 +1,37 @@
import { memo } from 'react';
import { Flex } from '@chakra-ui/react';
import ParamSymmetryHorizontal from './ParamSymmetryHorizontal';
import ParamSymmetryVertical from './ParamSymmetryVertical';
import { useTranslation } from 'react-i18next';
import IAICollapse from 'common/components/IAICollapse';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { setShouldUseSymmetry } from 'features/parameters/store/generationSlice';
const ParamSymmetryCollapse = () => {
const { t } = useTranslation();
const shouldUseSymmetry = useAppSelector(
(state: RootState) => state.generation.shouldUseSymmetry
);
const dispatch = useAppDispatch();
const handleToggle = () => dispatch(setShouldUseSymmetry(!shouldUseSymmetry));
return (
<IAICollapse
label={t('parameters.symmetry')}
isOpen={shouldUseSymmetry}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamSymmetryHorizontal />
<ParamSymmetryVertical />
</Flex>
</IAICollapse>
);
};
export default memo(ParamSymmetryCollapse);

View File

@ -0,0 +1,32 @@
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setHorizontalSymmetrySteps } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function ParamSymmetryHorizontal() {
const horizontalSymmetrySteps = useAppSelector(
(state: RootState) => state.generation.horizontalSymmetrySteps
);
const steps = useAppSelector((state: RootState) => state.generation.steps);
const dispatch = useAppDispatch();
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.hSymmetryStep')}
value={horizontalSymmetrySteps}
onChange={(v) => dispatch(setHorizontalSymmetrySteps(v))}
min={0}
max={steps}
step={1}
withInput
withSliderMarks
withReset
handleReset={() => dispatch(setHorizontalSymmetrySteps(0))}
/>
);
}

View File

@ -3,7 +3,7 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISwitch from 'common/components/IAISwitch';
import { setShouldUseSymmetry } from 'features/parameters/store/generationSlice';
export default function SymmetryToggle() {
export default function ParamSymmetryToggle() {
const shouldUseSymmetry = useAppSelector(
(state: RootState) => state.generation.shouldUseSymmetry
);

View File

@ -0,0 +1,32 @@
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setVerticalSymmetrySteps } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function ParamSymmetryVertical() {
const verticalSymmetrySteps = useAppSelector(
(state: RootState) => state.generation.verticalSymmetrySteps
);
const steps = useAppSelector((state: RootState) => state.generation.steps);
const dispatch = useAppDispatch();
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.vSymmetryStep')}
value={verticalSymmetrySteps}
onChange={(v) => dispatch(setVerticalSymmetrySteps(v))}
min={0}
max={steps}
step={1}
withInput
withSliderMarks
withReset
handleReset={() => dispatch(setVerticalSymmetrySteps(0))}
/>
);
}

View File

@ -4,7 +4,7 @@ import IAISlider from 'common/components/IAISlider';
import { setVariationAmount } from 'features/parameters/store/generationSlice';
import { useTranslation } from 'react-i18next';
export default function VariationAmount() {
export default function ParamVariationAmount() {
const variationAmount = useAppSelector(
(state: RootState) => state.generation.variationAmount
);

View File

@ -0,0 +1,37 @@
import ParamVariationWeights from './ParamVariationWeights';
import ParamVariationAmount from './ParamVariationAmount';
import { useTranslation } from 'react-i18next';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { RootState } from 'app/store/store';
import { setShouldGenerateVariations } from 'features/parameters/store/generationSlice';
import { Flex } from '@chakra-ui/react';
import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
const ParamVariationCollapse = () => {
const { t } = useTranslation();
const shouldGenerateVariations = useAppSelector(
(state: RootState) => state.generation.shouldGenerateVariations
);
const dispatch = useAppDispatch();
const handleToggle = () =>
dispatch(setShouldGenerateVariations(!shouldGenerateVariations));
return (
<IAICollapse
label={t('parameters.variations')}
isOpen={shouldGenerateVariations}
onToggle={handleToggle}
withSwitch
>
<Flex sx={{ gap: 2, flexDirection: 'column' }}>
<ParamVariationAmount />
<ParamVariationWeights />
</Flex>
</IAICollapse>
);
};
export default memo(ParamVariationCollapse);

View File

@ -6,7 +6,7 @@ import { setSeedWeights } from 'features/parameters/store/generationSlice';
import { ChangeEvent } from 'react';
import { useTranslation } from 'react-i18next';
export default function SeedWeights() {
export default function ParamVariationWeights() {
const seedWeights = useAppSelector(
(state: RootState) => state.generation.seedWeights
);

View File

@ -20,7 +20,6 @@ export interface GenerationState {
negativePrompt: string;
sampler: string;
seamBlur: number;
seamless: boolean;
seamSize: number;
seamSteps: number;
seamStrength: number;
@ -29,6 +28,7 @@ export interface GenerationState {
shouldFitToWidthHeight: boolean;
shouldGenerateVariations: boolean;
shouldRandomizeSeed: boolean;
shouldUseNoiseSettings: boolean;
steps: number;
threshold: number;
tileSize: number;
@ -39,6 +39,9 @@ export interface GenerationState {
verticalSymmetrySteps: number;
isImageToImageEnabled: boolean;
model: string;
shouldUseSeamless: boolean;
seamlessXAxis: boolean;
seamlessYAxis: boolean;
}
export const initialGenerationState: GenerationState = {
@ -53,7 +56,6 @@ export const initialGenerationState: GenerationState = {
negativePrompt: '',
sampler: 'k_lms',
seamBlur: 16,
seamless: false,
seamSize: 96,
seamSteps: 30,
seamStrength: 0.7,
@ -62,6 +64,7 @@ export const initialGenerationState: GenerationState = {
shouldFitToWidthHeight: true,
shouldGenerateVariations: false,
shouldRandomizeSeed: true,
shouldUseNoiseSettings: false,
steps: 50,
threshold: 0,
tileSize: 32,
@ -72,6 +75,9 @@ export const initialGenerationState: GenerationState = {
verticalSymmetrySteps: 0,
isImageToImageEnabled: false,
model: '',
shouldUseSeamless: false,
seamlessXAxis: true,
seamlessYAxis: true,
};
const initialState: GenerationState = initialGenerationState;
@ -146,7 +152,13 @@ export const generationSlice = createSlice({
state.maskPath = action.payload;
},
setSeamless: (state, action: PayloadAction<boolean>) => {
state.seamless = action.payload;
state.shouldUseSeamless = action.payload;
},
setSeamlessXAxis: (state, action: PayloadAction<boolean>) => {
state.seamlessXAxis = action.payload;
},
setSeamlessYAxis: (state, action: PayloadAction<boolean>) => {
state.seamlessYAxis = action.payload;
},
setShouldFitToWidthHeight: (state, action: PayloadAction<boolean>) => {
state.shouldFitToWidthHeight = action.payload;
@ -348,6 +360,9 @@ export const generationSlice = createSlice({
setVerticalSymmetrySteps: (state, action: PayloadAction<number>) => {
state.verticalSymmetrySteps = action.payload;
},
setShouldUseNoiseSettings: (state, action: PayloadAction<boolean>) => {
state.shouldUseNoiseSettings = action.payload;
},
initialImageChanged: (state, action: PayloadAction<InvokeAI.Image>) => {
state.initialImage = action.payload;
state.isImageToImageEnabled = true;
@ -382,7 +397,6 @@ export const {
setNegativePrompt,
setSampler,
setSeamBlur,
setSeamless,
setSeamSize,
setSeamSteps,
setSeamStrength,
@ -402,6 +416,10 @@ export const {
initialImageChanged,
isImageToImageEnabledChanged,
modelSelected,
setShouldUseNoiseSettings,
setSeamless,
setSeamlessXAxis,
setSeamlessYAxis,
} = generationSlice.actions;
export default generationSlice.reducer;

View File

@ -0,0 +1,98 @@
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import { FACETOOL_TYPES } from 'app/constants';
export interface HiresState {
codeformerFidelity: number;
facetoolStrength: number;
facetoolType: FacetoolType;
hiresFix: boolean;
hiresStrength: number;
shouldLoopback: boolean;
shouldRunESRGAN: boolean;
shouldRunFacetool: boolean;
upscalingLevel: UpscalingLevel;
upscalingDenoising: number;
upscalingStrength: number;
}
export const initialHiresState: HiresState = {
codeformerFidelity: 0.75,
facetoolStrength: 0.75,
facetoolType: 'gfpgan',
hiresFix: false,
hiresStrength: 0.75,
hiresSteps: 30,
hiresWidth: 512,
hiresHeight: 512,
hiresModel: '',
shouldLoopback: false,
shouldRunESRGAN: false,
shouldRunFacetool: false,
upscalingLevel: 4,
upscalingDenoising: 0.75,
upscalingStrength: 0.75,
};
export const postprocessingSlice = createSlice({
name: 'postprocessing',
initialState: initialPostprocessingState,
reducers: {
setFacetoolStrength: (state, action: PayloadAction<number>) => {
state.facetoolStrength = action.payload;
},
setCodeformerFidelity: (state, action: PayloadAction<number>) => {
state.codeformerFidelity = action.payload;
},
setUpscalingLevel: (state, action: PayloadAction<UpscalingLevel>) => {
state.upscalingLevel = action.payload;
},
setUpscalingDenoising: (state, action: PayloadAction<number>) => {
state.upscalingDenoising = action.payload;
},
setUpscalingStrength: (state, action: PayloadAction<number>) => {
state.upscalingStrength = action.payload;
},
setHiresFix: (state, action: PayloadAction<boolean>) => {
state.hiresFix = action.payload;
},
setHiresStrength: (state, action: PayloadAction<number>) => {
state.hiresStrength = action.payload;
},
resetPostprocessingState: (state) => {
return {
...state,
...initialPostprocessingState,
};
},
setShouldRunFacetool: (state, action: PayloadAction<boolean>) => {
state.shouldRunFacetool = action.payload;
},
setFacetoolType: (state, action: PayloadAction<FacetoolType>) => {
state.facetoolType = action.payload;
},
setShouldRunESRGAN: (state, action: PayloadAction<boolean>) => {
state.shouldRunESRGAN = action.payload;
},
setShouldLoopback: (state, action: PayloadAction<boolean>) => {
state.shouldLoopback = action.payload;
},
},
});
export const {
resetPostprocessingState,
setCodeformerFidelity,
setFacetoolStrength,
setFacetoolType,
setHiresFix,
setHiresStrength,
setShouldLoopback,
setShouldRunESRGAN,
setShouldRunFacetool,
setUpscalingLevel,
setUpscalingDenoising,
setUpscalingStrength,
} = postprocessingSlice.actions;
export default postprocessingSlice.reducer;