feat: Add Seam Painting Options

This commit is contained in:
blessedcoolant
2023-08-16 17:25:55 +12:00
parent 611e241ca7
commit e98d7a52d4
10 changed files with 337 additions and 1 deletions

View File

@ -0,0 +1,36 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setSeamBlur } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamSeamBlur = () => {
const dispatch = useAppDispatch();
const seamBlur = useAppSelector(
(state: RootState) => state.generation.seamBlur
);
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.seamBlur')}
min={0}
max={64}
step={8}
sliderNumberInputProps={{ max: 512 }}
value={seamBlur}
onChange={(v) => {
dispatch(setSeamBlur(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
dispatch(setSeamBlur(8));
}}
/>
);
};
export default memo(ParamSeamBlur);

View File

@ -0,0 +1,27 @@
import { Flex } from '@chakra-ui/react';
import IAICollapse from 'common/components/IAICollapse';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import ParamSeamBlur from './ParamSeamBlur';
import ParamSeamSize from './ParamSeamSize';
import ParamSeamSteps from './ParamSeamSteps';
import ParamSeamStrength from './ParamSeamStrength';
import ParamSeamThreshold from './ParamSeamThreshold';
const ParamSeamPaintingCollapse = () => {
const { t } = useTranslation();
return (
<IAICollapse label={t('parameters.seamPaintingHeader')}>
<Flex sx={{ flexDirection: 'column', gap: 2, paddingBottom: 2 }}>
<ParamSeamSize />
<ParamSeamBlur />
<ParamSeamSteps />
<ParamSeamStrength />
<ParamSeamThreshold />
</Flex>
</IAICollapse>
);
};
export default memo(ParamSeamPaintingCollapse);

View File

@ -0,0 +1,36 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setSeamSize } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamSeamSize = () => {
const dispatch = useAppDispatch();
const seamSize = useAppSelector(
(state: RootState) => state.generation.seamSize
);
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.seamSize')}
min={0}
max={128}
step={8}
sliderNumberInputProps={{ max: 512 }}
value={seamSize}
onChange={(v) => {
dispatch(setSeamSize(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
dispatch(setSeamSize(16));
}}
/>
);
};
export default memo(ParamSeamSize);

View File

@ -0,0 +1,36 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setSeamSteps } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamSeamSteps = () => {
const dispatch = useAppDispatch();
const seamSteps = useAppSelector(
(state: RootState) => state.generation.seamSteps
);
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.seamSteps')}
min={0}
max={100}
step={1}
sliderNumberInputProps={{ max: 999 }}
value={seamSteps}
onChange={(v) => {
dispatch(setSeamSteps(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
dispatch(setSeamSteps(20));
}}
/>
);
};
export default memo(ParamSeamSteps);

View File

@ -0,0 +1,36 @@
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAISlider from 'common/components/IAISlider';
import { setSeamStrength } from 'features/parameters/store/generationSlice';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
const ParamSeamStrength = () => {
const dispatch = useAppDispatch();
const seamStrength = useAppSelector(
(state: RootState) => state.generation.seamStrength
);
const { t } = useTranslation();
return (
<IAISlider
label={t('parameters.seamStrength')}
min={0}
max={1}
step={0.01}
sliderNumberInputProps={{ max: 999 }}
value={seamStrength}
onChange={(v) => {
dispatch(setSeamStrength(v));
}}
withInput
withSliderMarks
withReset
handleReset={() => {
dispatch(setSeamStrength(0.7));
}}
/>
);
};
export default memo(ParamSeamStrength);

View File

@ -0,0 +1,121 @@
import {
FormControl,
FormLabel,
HStack,
RangeSlider,
RangeSliderFilledTrack,
RangeSliderMark,
RangeSliderThumb,
RangeSliderTrack,
Tooltip,
} from '@chakra-ui/react';
import type { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIIconButton from 'common/components/IAIIconButton';
import {
setSeamHighThreshold,
setSeamLowThreshold,
} from 'features/parameters/store/generationSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { BiReset } from 'react-icons/bi';
const ParamSeamThreshold = () => {
const dispatch = useAppDispatch();
const seamLowThreshold = useAppSelector(
(state: RootState) => state.generation.seamLowThreshold
);
const seamHighThreshold = useAppSelector(
(state: RootState) => state.generation.seamHighThreshold
);
const { t } = useTranslation();
const handleSeamThresholdChange = useCallback(
(v: number[]) => {
dispatch(setSeamLowThreshold(v[0] as number));
dispatch(setSeamHighThreshold(v[1] as number));
},
[dispatch]
);
const handleSeamThresholdReset = () => {
dispatch(setSeamLowThreshold(100));
dispatch(setSeamHighThreshold(200));
};
return (
<FormControl>
<FormLabel>{t('parameters.seamThreshold')}</FormLabel>
<HStack w="100%" gap={4} mt={-2}>
<RangeSlider
aria-label={[
t('parameters.seamLowThreshold'),
t('parameters.seamHighThreshold'),
]}
value={[seamLowThreshold, seamHighThreshold]}
min={0}
max={255}
step={1}
minStepsBetweenThumbs={1}
onChange={handleSeamThresholdChange}
>
<RangeSliderTrack>
<RangeSliderFilledTrack />
</RangeSliderTrack>
<Tooltip label={seamLowThreshold} placement="top" hasArrow>
<RangeSliderThumb index={0} />
</Tooltip>
<Tooltip label={seamHighThreshold} placement="top" hasArrow>
<RangeSliderThumb index={1} />
</Tooltip>
<RangeSliderMark
value={0}
sx={{
insetInlineStart: '0 !important',
insetInlineEnd: 'unset !important',
}}
>
0
</RangeSliderMark>
<RangeSliderMark
value={0.392}
sx={{
insetInlineStart: '38.4% !important',
transform: 'translateX(-38.4%)',
}}
>
100
</RangeSliderMark>
<RangeSliderMark
value={0.784}
sx={{
insetInlineStart: '79.8% !important',
transform: 'translateX(-79.8%)',
}}
>
200
</RangeSliderMark>
<RangeSliderMark
value={1}
sx={{
insetInlineStart: 'unset !important',
insetInlineEnd: '0 !important',
}}
>
255
</RangeSliderMark>
</RangeSlider>
<IAIIconButton
size="sm"
aria-label={t('accessibility.reset')}
tooltip={t('accessibility.reset')}
icon={<BiReset />}
onClick={handleSeamThresholdReset}
/>
</HStack>
</FormControl>
);
};
export default memo(ParamSeamThreshold);

View File

@ -37,6 +37,12 @@ export interface GenerationState {
scheduler: SchedulerParam;
maskBlur: number;
maskBlurMethod: MaskBlurMethodParam;
seamSize: number;
seamBlur: number;
seamSteps: number;
seamStrength: StrengthParam;
seamLowThreshold: number;
seamHighThreshold: number;
seed: SeedParam;
seedWeights: string;
shouldFitToWidthHeight: boolean;
@ -74,6 +80,12 @@ export const initialGenerationState: GenerationState = {
scheduler: 'euler',
maskBlur: 16,
maskBlurMethod: 'box',
seamSize: 16,
seamBlur: 8,
seamSteps: 20,
seamStrength: 0.7,
seamLowThreshold: 100,
seamHighThreshold: 200,
seed: 0,
seedWeights: '',
shouldFitToWidthHeight: true,
@ -200,6 +212,24 @@ export const generationSlice = createSlice({
setMaskBlurMethod: (state, action: PayloadAction<MaskBlurMethodParam>) => {
state.maskBlurMethod = action.payload;
},
setSeamSize: (state, action: PayloadAction<number>) => {
state.seamSize = action.payload;
},
setSeamBlur: (state, action: PayloadAction<number>) => {
state.seamBlur = action.payload;
},
setSeamSteps: (state, action: PayloadAction<number>) => {
state.seamSteps = action.payload;
},
setSeamStrength: (state, action: PayloadAction<number>) => {
state.seamStrength = action.payload;
},
setSeamLowThreshold: (state, action: PayloadAction<number>) => {
state.seamLowThreshold = action.payload;
},
setSeamHighThreshold: (state, action: PayloadAction<number>) => {
state.seamHighThreshold = action.payload;
},
setTileSize: (state, action: PayloadAction<number>) => {
state.tileSize = action.payload;
},
@ -306,6 +336,12 @@ export const {
setScheduler,
setMaskBlur,
setMaskBlurMethod,
setSeamSize,
setSeamBlur,
setSeamSteps,
setSeamStrength,
setSeamLowThreshold,
setSeamHighThreshold,
setSeed,
setSeedWeights,
setShouldFitToWidthHeight,