build out the rest of the accordions

This commit is contained in:
Mary Hipp 2024-07-17 12:05:11 -04:00 committed by psychedelicious
parent a0a54348e8
commit fd91b83d86
8 changed files with 268 additions and 18 deletions

View File

@ -0,0 +1,55 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setSteps } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamCreativity = () => {
const steps = useAppSelector((s) => s.generation.steps);
const initial = useAppSelector((s) => s.config.sd.steps.initial);
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
const sliderMax = useAppSelector((s) => s.config.sd.steps.sliderMax);
const numberInputMin = useAppSelector((s) => s.config.sd.steps.numberInputMin);
const numberInputMax = useAppSelector((s) => s.config.sd.steps.numberInputMax);
const coarseStep = useAppSelector((s) => s.config.sd.steps.coarseStep);
const fineStep = useAppSelector((s) => s.config.sd.steps.fineStep);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const marks = useMemo(() => [sliderMin, Math.floor(sliderMax / 2), sliderMax], [sliderMax, sliderMin]);
const onChange = useCallback(
(v: number) => {
dispatch(setSteps(v));
},
[dispatch]
);
return (
<FormControl>
<InformationalPopover feature="paramSteps">
<FormLabel>Creativity</FormLabel>
</InformationalPopover>
<CompositeSlider
value={steps}
defaultValue={initial}
min={sliderMin}
max={sliderMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
marks={marks}
/>
<CompositeNumberInput
value={steps}
defaultValue={initial}
min={numberInputMin}
max={numberInputMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
/>
</FormControl>
);
};
export default memo(ParamCreativity);

View File

@ -0,0 +1,55 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setSteps } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamSharpness = () => {
const steps = useAppSelector((s) => s.generation.steps);
const initial = useAppSelector((s) => s.config.sd.steps.initial);
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
const sliderMax = useAppSelector((s) => s.config.sd.steps.sliderMax);
const numberInputMin = useAppSelector((s) => s.config.sd.steps.numberInputMin);
const numberInputMax = useAppSelector((s) => s.config.sd.steps.numberInputMax);
const coarseStep = useAppSelector((s) => s.config.sd.steps.coarseStep);
const fineStep = useAppSelector((s) => s.config.sd.steps.fineStep);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const marks = useMemo(() => [sliderMin, Math.floor(sliderMax / 2), sliderMax], [sliderMax, sliderMin]);
const onChange = useCallback(
(v: number) => {
dispatch(setSteps(v));
},
[dispatch]
);
return (
<FormControl>
<InformationalPopover feature="paramSteps">
<FormLabel>Sharpness</FormLabel>
</InformationalPopover>
<CompositeSlider
value={steps}
defaultValue={initial}
min={sliderMin}
max={sliderMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
marks={marks}
/>
<CompositeNumberInput
value={steps}
defaultValue={initial}
min={numberInputMin}
max={numberInputMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
/>
</FormControl>
);
};
export default memo(ParamSharpness);

View File

@ -0,0 +1,55 @@
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
import { setSteps } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamStructure = () => {
const steps = useAppSelector((s) => s.generation.steps);
const initial = useAppSelector((s) => s.config.sd.steps.initial);
const sliderMin = useAppSelector((s) => s.config.sd.steps.sliderMin);
const sliderMax = useAppSelector((s) => s.config.sd.steps.sliderMax);
const numberInputMin = useAppSelector((s) => s.config.sd.steps.numberInputMin);
const numberInputMax = useAppSelector((s) => s.config.sd.steps.numberInputMax);
const coarseStep = useAppSelector((s) => s.config.sd.steps.coarseStep);
const fineStep = useAppSelector((s) => s.config.sd.steps.fineStep);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const marks = useMemo(() => [sliderMin, Math.floor(sliderMax / 2), sliderMax], [sliderMax, sliderMin]);
const onChange = useCallback(
(v: number) => {
dispatch(setSteps(v));
},
[dispatch]
);
return (
<FormControl>
<InformationalPopover feature="paramSteps">
<FormLabel>Structure</FormLabel>
</InformationalPopover>
<CompositeSlider
value={steps}
defaultValue={initial}
min={sliderMin}
max={sliderMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
marks={marks}
/>
<CompositeNumberInput
value={steps}
defaultValue={initial}
min={numberInputMin}
max={numberInputMax}
step={coarseStep}
fineStep={fineStep}
onChange={onChange}
/>
</FormControl>
);
};
export default memo(ParamStructure);

View File

@ -14,7 +14,7 @@ interface UpscaleState {
const initialUpscaleState: UpscaleState = {
_version: 1,
upscaleModel: null,
upscaleInitialImage: null
upscaleInitialImage: null,
};
export const upscaleSlice = createSlice({

View File

@ -14,6 +14,10 @@ import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/
import { memo, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
import { activeTabNameSelector } from '../../../ui/store/uiSelectors';
import { ParamSeedNumberInput } from '../../../parameters/components/Seed/ParamSeedNumberInput';
import { ParamSeedRandomize } from '../../../parameters/components/Seed/ParamSeedRandomize';
import { ParamSeedShuffle } from '../../../parameters/components/Seed/ParamSeedShuffle';
const formLabelProps: FormLabelProps = {
minW: '9.2rem',
@ -26,6 +30,8 @@ const formLabelProps2: FormLabelProps = {
export const AdvancedSettingsAccordion = memo(() => {
const vaeKey = useAppSelector((state) => state.generation.vae?.key);
const { currentData: vaeConfig } = useGetModelConfigQuery(vaeKey ?? skipToken);
const activeTabName = useAppSelector(activeTabNameSelector);
const selectBadges = useMemo(
() =>
createMemoizedSelector(selectGenerationSlice, (generation) => {
@ -48,9 +54,12 @@ export const AdvancedSettingsAccordion = memo(() => {
if (generation.seamlessXAxis || generation.seamlessYAxis) {
badges.push('seamless');
}
if (activeTabName === 'upscaling' && !generation.shouldRandomizeSeed) {
badges.push('Manual Seed');
}
return badges;
}),
[vaeConfig]
[vaeConfig, activeTabName]
);
const badges = useAppSelector(selectBadges);
const { t } = useTranslation();
@ -66,16 +75,27 @@ export const AdvancedSettingsAccordion = memo(() => {
<ParamVAEModelSelect />
<ParamVAEPrecision />
</Flex>
<FormControlGroup formLabelProps={formLabelProps}>
<ParamClipSkip />
<ParamCFGRescaleMultiplier />
</FormControlGroup>
<Flex gap={4} w="full">
<FormControlGroup formLabelProps={formLabelProps2}>
<ParamSeamlessXAxis />
<ParamSeamlessYAxis />
</FormControlGroup>
</Flex>
{activeTabName === 'upscaling' && (
<Flex gap={4} alignItems="center">
<ParamSeedNumberInput />
<ParamSeedShuffle />
<ParamSeedRandomize />
</Flex>
)}
{activeTabName !== 'upscaling' && (
<>
<FormControlGroup formLabelProps={formLabelProps}>
<ParamClipSkip />
<ParamCFGRescaleMultiplier />
</FormControlGroup>
<Flex gap={4} w="full">
<FormControlGroup formLabelProps={formLabelProps2}>
<ParamSeamlessXAxis />
<ParamSeamlessYAxis />
</FormControlGroup>
</Flex>
</>
)}
</Flex>
</StandaloneAccordion>
);

View File

@ -1,24 +1,58 @@
import { Flex, StandaloneAccordion } from '@invoke-ai/ui-library';
import { Expander, Flex, StandaloneAccordion } from '@invoke-ai/ui-library';
import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/useStandaloneAccordionToggle';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import ParamSpandrelModel from '../../../parameters/components/Upscale/ParamSpandrelModel';
import { UpscaleInitialImage } from './UpscaleInitialImage';
import { UpscaleSizeDetails } from './UpscaleSizeDetails';
import { useExpanderToggle } from '../../hooks/useExpanderToggle';
import ParamSharpness from '../../../parameters/components/Upscale/ParamSharpness';
import ParamCreativity from '../../../parameters/components/Upscale/ParamCreativity';
import ParamStructure from '../../../parameters/components/Upscale/ParamStructure';
import { selectUpscalelice } from '../../../parameters/store/upscaleSlice';
import { createMemoizedSelector } from '../../../../app/store/createMemoizedSelector';
import { useAppSelector } from '../../../../app/store/storeHooks';
const selector = createMemoizedSelector([selectUpscalelice], (upscale) => {
const badges: string[] = [];
if (upscale.upscaleModel) {
badges.push(upscale.upscaleModel.name);
}
return { badges };
});
export const UpscaleSettingsAccordion = memo(() => {
const { t } = useTranslation();
const { badges } = useAppSelector(selector);
const { isOpen: isOpenAccordion, onToggle: onToggleAccordion } = useStandaloneAccordionToggle({
id: 'upscale-settings',
defaultIsOpen: true,
});
const { isOpen: isOpenExpander, onToggle: onToggleExpander } = useExpanderToggle({
id: 'upscale-settings-advanced',
defaultIsOpen: false,
});
return (
<StandaloneAccordion label="Upscale" isOpen={isOpenAccordion} onToggle={onToggleAccordion}>
<Flex p={4} w="full" h="full" flexDir="column" data-testid="image-settings-accordion">
<StandaloneAccordion label="Upscale" badges={badges} isOpen={isOpenAccordion} onToggle={onToggleAccordion}>
<Flex pt={4} px={4} w="full" h="full" flexDir="column" data-testid="image-settings-accordion">
<Flex gap={4}>
<UpscaleInitialImage />
<ParamSpandrelModel />
<Flex direction="column" w="full" alignItems="center" gap={4}>
<ParamSpandrelModel />
<UpscaleSizeDetails />
</Flex>
</Flex>
<Expander label={t('accordions.advanced.options')} isOpen={isOpenExpander} onToggle={onToggleExpander}>
<Flex gap={4} pb={4} flexDir="column">
<ParamSharpness />
<ParamCreativity />
<ParamStructure />
</Flex>
</Expander>
</Flex>
</StandaloneAccordion>
);

View File

@ -0,0 +1,31 @@
import { Flex, Text } from '@invoke-ai/ui-library';
import { useAppSelector } from '../../../../app/store/storeHooks';
import { useMemo } from 'react';
export const UpscaleSizeDetails = () => {
const { upscaleInitialImage, upscaleModel } = useAppSelector((s) => s.upscale);
const scaleFactor = useMemo(() => {
if (upscaleModel) {
const upscaleFactor = upscaleModel.name.match(/x(\d+)/);
if (upscaleFactor && upscaleFactor[1]) {
return parseInt(upscaleFactor[1], 10);
}
}
}, [upscaleModel]);
if (!upscaleInitialImage || !upscaleModel || !scaleFactor) {
return <></>;
}
return (
<Flex direction="column">
<Text variant="subtext" fontWeight="bold">
Current image size: {upscaleInitialImage.width} x {upscaleInitialImage.height}
</Text>
<Text variant="subtext" fontWeight="bold">
Output image size: {upscaleInitialImage.width * scaleFactor} x {upscaleInitialImage.height * scaleFactor}
</Text>
</Flex>
);
};

View File

@ -1,4 +1,4 @@
import { Box, Flex, Switch } from '@invoke-ai/ui-library';
import { Box, Divider, Flex } from '@invoke-ai/ui-library';
import { useAppSelector } from 'app/store/storeHooks';
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
@ -29,8 +29,8 @@ const ParametersPanelUpscale = () => {
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
<Flex gap={2} flexDirection="column" h="full" w="full">
<UpscaleSettingsAccordion />
{isSDXL ? <SDXLPrompts /> : <Prompts />}
<UpscaleSettingsAccordion />
<GenerationSettingsAccordion />
<AdvancedSettingsAccordion />
</Flex>