mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
feat(ui): add w/h to default model settings
This commit is contained in:
parent
1adaf63253
commit
2584a950aa
@ -1,19 +1,23 @@
|
||||
import type { AppStartListening } from 'app/store/middleware/listenerMiddleware';
|
||||
import { setDefaultSettings } from 'features/parameters/store/actions';
|
||||
import {
|
||||
heightChanged,
|
||||
setCfgRescaleMultiplier,
|
||||
setCfgScale,
|
||||
setScheduler,
|
||||
setSteps,
|
||||
vaePrecisionChanged,
|
||||
vaeSelected,
|
||||
widthChanged,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import {
|
||||
isParameterCFGRescaleMultiplier,
|
||||
isParameterCFGScale,
|
||||
isParameterHeight,
|
||||
isParameterPrecision,
|
||||
isParameterScheduler,
|
||||
isParameterSteps,
|
||||
isParameterWidth,
|
||||
zParameterVAEModel,
|
||||
} from 'features/parameters/types/parameterSchemas';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
@ -42,7 +46,7 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
|
||||
}
|
||||
|
||||
if (isNonRefinerMainModelConfig(modelConfig) && modelConfig.default_settings) {
|
||||
const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler } =
|
||||
const { vae, vae_precision, cfg_scale, cfg_rescale_multiplier, steps, scheduler, width, height } =
|
||||
modelConfig.default_settings;
|
||||
|
||||
if (vae) {
|
||||
@ -93,6 +97,18 @@ export const addSetDefaultSettingsListener = (startAppListening: AppStartListeni
|
||||
}
|
||||
}
|
||||
|
||||
if (width) {
|
||||
if (isParameterWidth(width)) {
|
||||
dispatch(widthChanged(width));
|
||||
}
|
||||
}
|
||||
|
||||
if (height) {
|
||||
if (isParameterHeight(height)) {
|
||||
dispatch(heightChanged(height));
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(addToast(makeToast({ title: t('toast.parameterSet', { parameter: 'Default settings' }) })));
|
||||
}
|
||||
},
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { skipToken } from '@reduxjs/toolkit/query';
|
||||
import { createMemoizedSelector } from 'app/store/createMemoizedSelector';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { getOptimalDimension } from 'features/parameters/util/optimalDimension';
|
||||
import { selectConfigSlice } from 'features/system/store/configSlice';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { useMemo } from 'react';
|
||||
@ -8,7 +9,7 @@ import { useGetModelConfigWithTypeGuard } from 'services/api/hooks/useGetModelCo
|
||||
import { isNonRefinerMainModelConfig } from 'services/api/types';
|
||||
|
||||
const initialStatesSelector = createMemoizedSelector(selectConfigSlice, (config) => {
|
||||
const { steps, guidance, scheduler, cfgRescaleMultiplier, vaePrecision } = config.sd;
|
||||
const { steps, guidance, scheduler, cfgRescaleMultiplier, vaePrecision, width, height } = config.sd;
|
||||
|
||||
return {
|
||||
initialSteps: steps.initial,
|
||||
@ -16,14 +17,23 @@ const initialStatesSelector = createMemoizedSelector(selectConfigSlice, (config)
|
||||
initialScheduler: scheduler,
|
||||
initialCfgRescaleMultiplier: cfgRescaleMultiplier.initial,
|
||||
initialVaePrecision: vaePrecision,
|
||||
initialWidth: width.initial,
|
||||
initialHeight: height.initial,
|
||||
};
|
||||
});
|
||||
|
||||
export const useMainModelDefaultSettings = (modelKey?: string | null) => {
|
||||
const { modelConfig, isLoading } = useGetModelConfigWithTypeGuard(modelKey ?? skipToken, isNonRefinerMainModelConfig);
|
||||
|
||||
const { initialSteps, initialCfg, initialScheduler, initialCfgRescaleMultiplier, initialVaePrecision } =
|
||||
useAppSelector(initialStatesSelector);
|
||||
const {
|
||||
initialSteps,
|
||||
initialCfg,
|
||||
initialScheduler,
|
||||
initialCfgRescaleMultiplier,
|
||||
initialVaePrecision,
|
||||
initialWidth,
|
||||
initialHeight,
|
||||
} = useAppSelector(initialStatesSelector);
|
||||
|
||||
const defaultSettingsDefaults = useMemo(() => {
|
||||
return {
|
||||
@ -51,15 +61,25 @@ export const useMainModelDefaultSettings = (modelKey?: string | null) => {
|
||||
isEnabled: !isNil(modelConfig?.default_settings?.cfg_rescale_multiplier),
|
||||
value: modelConfig?.default_settings?.cfg_rescale_multiplier || initialCfgRescaleMultiplier,
|
||||
},
|
||||
width: {
|
||||
isEnabled: !isNil(modelConfig?.default_settings?.width),
|
||||
value: modelConfig?.default_settings?.width || initialWidth,
|
||||
},
|
||||
height: {
|
||||
isEnabled: !isNil(modelConfig?.default_settings?.height),
|
||||
value: modelConfig?.default_settings?.height || initialHeight,
|
||||
},
|
||||
};
|
||||
}, [
|
||||
modelConfig?.default_settings,
|
||||
modelConfig,
|
||||
initialVaePrecision,
|
||||
initialScheduler,
|
||||
initialSteps,
|
||||
initialCfg,
|
||||
initialScheduler,
|
||||
initialCfgRescaleMultiplier,
|
||||
initialVaePrecision,
|
||||
initialWidth,
|
||||
initialHeight,
|
||||
]);
|
||||
|
||||
return { defaultSettingsDefaults, isLoading };
|
||||
return { defaultSettingsDefaults, isLoading, optimalDimension: getOptimalDimension(modelConfig) };
|
||||
};
|
||||
|
@ -0,0 +1,81 @@
|
||||
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useController } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||
|
||||
type DefaultHeightType = MainModelDefaultSettingsFormData['height'];
|
||||
|
||||
type Props = {
|
||||
control: UseControllerProps<MainModelDefaultSettingsFormData>['control'];
|
||||
optimalDimension: number;
|
||||
};
|
||||
|
||||
export function DefaultHeight({ control, optimalDimension }: Props) {
|
||||
const { field } = useController({ control, name: 'height' });
|
||||
const sliderMin = useAppSelector((s) => s.config.sd.height.sliderMin);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.height.sliderMax);
|
||||
const numberInputMin = useAppSelector((s) => s.config.sd.height.numberInputMin);
|
||||
const numberInputMax = useAppSelector((s) => s.config.sd.height.numberInputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.height.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.height.fineStep);
|
||||
const { t } = useTranslation();
|
||||
const marks = useMemo(() => [sliderMin, optimalDimension, sliderMax], [sliderMin, optimalDimension, sliderMax]);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
const updatedValue = {
|
||||
...(field.value as DefaultHeightType),
|
||||
value: v,
|
||||
};
|
||||
field.onChange(updatedValue);
|
||||
},
|
||||
[field]
|
||||
);
|
||||
|
||||
const value = useMemo(() => {
|
||||
return field.value.value;
|
||||
}, [field.value]);
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
return !field.value.isEnabled;
|
||||
}, [field.value]);
|
||||
|
||||
return (
|
||||
<FormControl flexDir="column" gap={2} alignItems="flex-start">
|
||||
<Flex justifyContent="space-between" w="full">
|
||||
<InformationalPopover feature="paramHeight">
|
||||
<FormLabel>{t('parameters.height')}</FormLabel>
|
||||
</InformationalPopover>
|
||||
<SettingToggle control={control} name="height" />
|
||||
</Flex>
|
||||
|
||||
<Flex w="full" gap={4}>
|
||||
<CompositeSlider
|
||||
value={value}
|
||||
min={sliderMin}
|
||||
max={sliderMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
marks={marks}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
<CompositeNumberInput
|
||||
value={value}
|
||||
min={numberInputMin}
|
||||
max={numberInputMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</Flex>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
import { CompositeNumberInput, CompositeSlider, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { InformationalPopover } from 'common/components/InformationalPopover/InformationalPopover';
|
||||
import { SettingToggle } from 'features/modelManagerV2/subpanels/ModelPanel/SettingToggle';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import type { UseControllerProps } from 'react-hook-form';
|
||||
import { useController } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import type { MainModelDefaultSettingsFormData } from './MainModelDefaultSettings';
|
||||
|
||||
type DefaultWidthType = MainModelDefaultSettingsFormData['width'];
|
||||
|
||||
type Props = {
|
||||
control: UseControllerProps<MainModelDefaultSettingsFormData>['control'];
|
||||
optimalDimension: number;
|
||||
};
|
||||
|
||||
export function DefaultWidth({ control, optimalDimension }: Props) {
|
||||
const { field } = useController({ control, name: 'width' });
|
||||
const sliderMin = useAppSelector((s) => s.config.sd.width.sliderMin);
|
||||
const sliderMax = useAppSelector((s) => s.config.sd.width.sliderMax);
|
||||
const numberInputMin = useAppSelector((s) => s.config.sd.width.numberInputMin);
|
||||
const numberInputMax = useAppSelector((s) => s.config.sd.width.numberInputMax);
|
||||
const coarseStep = useAppSelector((s) => s.config.sd.width.coarseStep);
|
||||
const fineStep = useAppSelector((s) => s.config.sd.width.fineStep);
|
||||
const { t } = useTranslation();
|
||||
const marks = useMemo(() => [sliderMin, optimalDimension, sliderMax], [sliderMin, optimalDimension, sliderMax]);
|
||||
|
||||
const onChange = useCallback(
|
||||
(v: number) => {
|
||||
const updatedValue = {
|
||||
...(field.value as DefaultWidthType),
|
||||
value: v,
|
||||
};
|
||||
field.onChange(updatedValue);
|
||||
},
|
||||
[field]
|
||||
);
|
||||
|
||||
const value = useMemo(() => {
|
||||
return (field.value as DefaultWidthType).value;
|
||||
}, [field.value]);
|
||||
|
||||
const isDisabled = useMemo(() => {
|
||||
return !(field.value as DefaultWidthType).isEnabled;
|
||||
}, [field.value]);
|
||||
|
||||
return (
|
||||
<FormControl flexDir="column" gap={2} alignItems="flex-start">
|
||||
<Flex justifyContent="space-between" w="full">
|
||||
<InformationalPopover feature="paramWidth">
|
||||
<FormLabel>{t('parameters.width')}</FormLabel>
|
||||
</InformationalPopover>
|
||||
<SettingToggle control={control} name="width" />
|
||||
</Flex>
|
||||
|
||||
<Flex w="full" gap={4}>
|
||||
<CompositeSlider
|
||||
value={value}
|
||||
min={sliderMin}
|
||||
max={sliderMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
marks={marks}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
<CompositeNumberInput
|
||||
value={value}
|
||||
min={numberInputMin}
|
||||
max={numberInputMax}
|
||||
step={coarseStep}
|
||||
fineStep={fineStep}
|
||||
onChange={onChange}
|
||||
isDisabled={isDisabled}
|
||||
/>
|
||||
</Flex>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
import { Button, Flex, Heading, Text } from '@invoke-ai/ui-library';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { useMainModelDefaultSettings } from 'features/modelManagerV2/hooks/useMainModelDefaultSettings';
|
||||
import { DefaultHeight } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultHeight';
|
||||
import { DefaultWidth } from 'features/modelManagerV2/subpanels/ModelPanel/MainModelDefaultSettings/DefaultWidth';
|
||||
import type { ParameterScheduler } from 'features/parameters/types/parameterSchemas';
|
||||
import { addToast } from 'features/system/store/systemSlice';
|
||||
import { makeToast } from 'features/system/util/makeToast';
|
||||
@ -25,11 +27,13 @@ export interface FormField<T> {
|
||||
|
||||
export type MainModelDefaultSettingsFormData = {
|
||||
vae: FormField<string>;
|
||||
vaePrecision: FormField<string>;
|
||||
vaePrecision: FormField<'fp16' | 'fp32'>;
|
||||
scheduler: FormField<ParameterScheduler>;
|
||||
steps: FormField<number>;
|
||||
cfgScale: FormField<number>;
|
||||
cfgRescaleMultiplier: FormField<number>;
|
||||
width: FormField<number>;
|
||||
height: FormField<number>;
|
||||
};
|
||||
|
||||
export const MainModelDefaultSettings = () => {
|
||||
@ -37,8 +41,11 @@ export const MainModelDefaultSettings = () => {
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const { defaultSettingsDefaults, isLoading: isLoadingDefaultSettings } =
|
||||
useMainModelDefaultSettings(selectedModelKey);
|
||||
const {
|
||||
defaultSettingsDefaults,
|
||||
isLoading: isLoadingDefaultSettings,
|
||||
optimalDimension,
|
||||
} = useMainModelDefaultSettings(selectedModelKey);
|
||||
|
||||
const [updateModel, { isLoading: isLoadingUpdateModel }] = useUpdateModelMutation();
|
||||
|
||||
@ -59,6 +66,8 @@ export const MainModelDefaultSettings = () => {
|
||||
cfg_rescale_multiplier: data.cfgRescaleMultiplier.isEnabled ? data.cfgRescaleMultiplier.value : null,
|
||||
steps: data.steps.isEnabled ? data.steps.value : null,
|
||||
scheduler: data.scheduler.isEnabled ? data.scheduler.value : null,
|
||||
width: data.width.isEnabled ? data.width.value : null,
|
||||
height: data.height.isEnabled ? data.height.value : null,
|
||||
};
|
||||
|
||||
updateModel({
|
||||
@ -139,6 +148,14 @@ export const MainModelDefaultSettings = () => {
|
||||
<DefaultCfgRescaleMultiplier control={control} name="cfgRescaleMultiplier" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex gap={8}>
|
||||
<Flex gap={4} w="full">
|
||||
<DefaultWidth control={control} optimalDimension={optimalDimension} />
|
||||
</Flex>
|
||||
<Flex gap={4} w="full">
|
||||
<DefaultHeight control={control} optimalDimension={optimalDimension} />
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user