mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
build out the rest of the accordions
This commit is contained in:
parent
a0a54348e8
commit
fd91b83d86
@ -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);
|
@ -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);
|
@ -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);
|
@ -14,7 +14,7 @@ interface UpscaleState {
|
|||||||
const initialUpscaleState: UpscaleState = {
|
const initialUpscaleState: UpscaleState = {
|
||||||
_version: 1,
|
_version: 1,
|
||||||
upscaleModel: null,
|
upscaleModel: null,
|
||||||
upscaleInitialImage: null
|
upscaleInitialImage: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const upscaleSlice = createSlice({
|
export const upscaleSlice = createSlice({
|
||||||
|
@ -14,6 +14,10 @@ import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/
|
|||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useGetModelConfigQuery } from 'services/api/endpoints/models';
|
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 = {
|
const formLabelProps: FormLabelProps = {
|
||||||
minW: '9.2rem',
|
minW: '9.2rem',
|
||||||
@ -26,6 +30,8 @@ const formLabelProps2: FormLabelProps = {
|
|||||||
export const AdvancedSettingsAccordion = memo(() => {
|
export const AdvancedSettingsAccordion = memo(() => {
|
||||||
const vaeKey = useAppSelector((state) => state.generation.vae?.key);
|
const vaeKey = useAppSelector((state) => state.generation.vae?.key);
|
||||||
const { currentData: vaeConfig } = useGetModelConfigQuery(vaeKey ?? skipToken);
|
const { currentData: vaeConfig } = useGetModelConfigQuery(vaeKey ?? skipToken);
|
||||||
|
const activeTabName = useAppSelector(activeTabNameSelector);
|
||||||
|
|
||||||
const selectBadges = useMemo(
|
const selectBadges = useMemo(
|
||||||
() =>
|
() =>
|
||||||
createMemoizedSelector(selectGenerationSlice, (generation) => {
|
createMemoizedSelector(selectGenerationSlice, (generation) => {
|
||||||
@ -48,9 +54,12 @@ export const AdvancedSettingsAccordion = memo(() => {
|
|||||||
if (generation.seamlessXAxis || generation.seamlessYAxis) {
|
if (generation.seamlessXAxis || generation.seamlessYAxis) {
|
||||||
badges.push('seamless');
|
badges.push('seamless');
|
||||||
}
|
}
|
||||||
|
if (activeTabName === 'upscaling' && !generation.shouldRandomizeSeed) {
|
||||||
|
badges.push('Manual Seed');
|
||||||
|
}
|
||||||
return badges;
|
return badges;
|
||||||
}),
|
}),
|
||||||
[vaeConfig]
|
[vaeConfig, activeTabName]
|
||||||
);
|
);
|
||||||
const badges = useAppSelector(selectBadges);
|
const badges = useAppSelector(selectBadges);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -66,16 +75,27 @@ export const AdvancedSettingsAccordion = memo(() => {
|
|||||||
<ParamVAEModelSelect />
|
<ParamVAEModelSelect />
|
||||||
<ParamVAEPrecision />
|
<ParamVAEPrecision />
|
||||||
</Flex>
|
</Flex>
|
||||||
<FormControlGroup formLabelProps={formLabelProps}>
|
{activeTabName === 'upscaling' && (
|
||||||
<ParamClipSkip />
|
<Flex gap={4} alignItems="center">
|
||||||
<ParamCFGRescaleMultiplier />
|
<ParamSeedNumberInput />
|
||||||
</FormControlGroup>
|
<ParamSeedShuffle />
|
||||||
<Flex gap={4} w="full">
|
<ParamSeedRandomize />
|
||||||
<FormControlGroup formLabelProps={formLabelProps2}>
|
</Flex>
|
||||||
<ParamSeamlessXAxis />
|
)}
|
||||||
<ParamSeamlessYAxis />
|
{activeTabName !== 'upscaling' && (
|
||||||
</FormControlGroup>
|
<>
|
||||||
</Flex>
|
<FormControlGroup formLabelProps={formLabelProps}>
|
||||||
|
<ParamClipSkip />
|
||||||
|
<ParamCFGRescaleMultiplier />
|
||||||
|
</FormControlGroup>
|
||||||
|
<Flex gap={4} w="full">
|
||||||
|
<FormControlGroup formLabelProps={formLabelProps2}>
|
||||||
|
<ParamSeamlessXAxis />
|
||||||
|
<ParamSeamlessYAxis />
|
||||||
|
</FormControlGroup>
|
||||||
|
</Flex>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
</StandaloneAccordion>
|
</StandaloneAccordion>
|
||||||
);
|
);
|
||||||
|
@ -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 { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/useStandaloneAccordionToggle';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import ParamSpandrelModel from '../../../parameters/components/Upscale/ParamSpandrelModel';
|
import ParamSpandrelModel from '../../../parameters/components/Upscale/ParamSpandrelModel';
|
||||||
import { UpscaleInitialImage } from './UpscaleInitialImage';
|
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(() => {
|
export const UpscaleSettingsAccordion = memo(() => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { badges } = useAppSelector(selector);
|
||||||
const { isOpen: isOpenAccordion, onToggle: onToggleAccordion } = useStandaloneAccordionToggle({
|
const { isOpen: isOpenAccordion, onToggle: onToggleAccordion } = useStandaloneAccordionToggle({
|
||||||
id: 'upscale-settings',
|
id: 'upscale-settings',
|
||||||
defaultIsOpen: true,
|
defaultIsOpen: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { isOpen: isOpenExpander, onToggle: onToggleExpander } = useExpanderToggle({
|
||||||
|
id: 'upscale-settings-advanced',
|
||||||
|
defaultIsOpen: false,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StandaloneAccordion label="Upscale" isOpen={isOpenAccordion} onToggle={onToggleAccordion}>
|
<StandaloneAccordion label="Upscale" badges={badges} isOpen={isOpenAccordion} onToggle={onToggleAccordion}>
|
||||||
<Flex p={4} w="full" h="full" flexDir="column" data-testid="image-settings-accordion">
|
<Flex pt={4} px={4} w="full" h="full" flexDir="column" data-testid="image-settings-accordion">
|
||||||
<Flex gap={4}>
|
<Flex gap={4}>
|
||||||
<UpscaleInitialImage />
|
<UpscaleInitialImage />
|
||||||
<ParamSpandrelModel />
|
<Flex direction="column" w="full" alignItems="center" gap={4}>
|
||||||
|
<ParamSpandrelModel />
|
||||||
|
<UpscaleSizeDetails />
|
||||||
|
</Flex>
|
||||||
</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>
|
</Flex>
|
||||||
</StandaloneAccordion>
|
</StandaloneAccordion>
|
||||||
);
|
);
|
||||||
|
@ -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>
|
||||||
|
);
|
||||||
|
};
|
@ -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 { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||||
import { Prompts } from 'features/parameters/components/Prompts/Prompts';
|
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}>
|
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||||
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
<OverlayScrollbarsComponent defer style={overlayScrollbarsStyles} options={overlayScrollbarsParams.options}>
|
||||||
<Flex gap={2} flexDirection="column" h="full" w="full">
|
<Flex gap={2} flexDirection="column" h="full" w="full">
|
||||||
<UpscaleSettingsAccordion />
|
|
||||||
{isSDXL ? <SDXLPrompts /> : <Prompts />}
|
{isSDXL ? <SDXLPrompts /> : <Prompts />}
|
||||||
|
<UpscaleSettingsAccordion />
|
||||||
<GenerationSettingsAccordion />
|
<GenerationSettingsAccordion />
|
||||||
<AdvancedSettingsAccordion />
|
<AdvancedSettingsAccordion />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
Loading…
Reference in New Issue
Block a user