feat: Add IP Adapter Begin & End Percent to Linear UI

This commit is contained in:
blessedcoolant 2023-09-17 11:53:05 +12:00
parent c48e648cbb
commit 7be5743011
5 changed files with 165 additions and 25 deletions

View File

@ -1,5 +1,6 @@
import { Flex } from '@chakra-ui/react'; import { Flex } from '@chakra-ui/react';
import { memo } from 'react'; import { memo } from 'react';
import ParamIPAdapterBeginEnd from './ParamIPAdapterBeginEnd';
import ParamIPAdapterFeatureToggle from './ParamIPAdapterFeatureToggle'; import ParamIPAdapterFeatureToggle from './ParamIPAdapterFeatureToggle';
import ParamIPAdapterImage from './ParamIPAdapterImage'; import ParamIPAdapterImage from './ParamIPAdapterImage';
import ParamIPAdapterModelSelect from './ParamIPAdapterModelSelect'; import ParamIPAdapterModelSelect from './ParamIPAdapterModelSelect';
@ -26,6 +27,7 @@ const IPAdapterPanel = () => {
<ParamIPAdapterImage /> <ParamIPAdapterImage />
<ParamIPAdapterModelSelect /> <ParamIPAdapterModelSelect />
<ParamIPAdapterWeight /> <ParamIPAdapterWeight />
<ParamIPAdapterBeginEnd />
</Flex> </Flex>
); );
}; };

View File

@ -0,0 +1,100 @@
import {
FormControl,
FormLabel,
HStack,
RangeSlider,
RangeSliderFilledTrack,
RangeSliderMark,
RangeSliderThumb,
RangeSliderTrack,
Tooltip,
} from '@chakra-ui/react';
import { RootState } from 'app/store/store';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import {
ipAdapterBeginStepPctChanged,
ipAdapterEndStepPctChanged,
} from 'features/controlNet/store/controlNetSlice';
import { memo, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
const formatPct = (v: number) => `${Math.round(v * 100)}%`;
const ParamIPAdapterBeginEnd = () => {
const isEnabled = useAppSelector(
(state: RootState) => state.controlNet.isIPAdapterEnabled
);
const beginStepPct = useAppSelector(
(state: RootState) => state.controlNet.ipAdapterInfo.beginStepPct
);
const endStepPct = useAppSelector(
(state: RootState) => state.controlNet.ipAdapterInfo.endStepPct
);
const dispatch = useAppDispatch();
const { t } = useTranslation();
const handleStepPctChanged = useCallback(
(v: number[]) => {
dispatch(ipAdapterBeginStepPctChanged(v[0] as number));
dispatch(ipAdapterEndStepPctChanged(v[1] as number));
},
[dispatch]
);
return (
<FormControl isDisabled={!isEnabled}>
<FormLabel>{t('controlnet.beginEndStepPercent')}</FormLabel>
<HStack w="100%" gap={2} alignItems="center">
<RangeSlider
aria-label={['Begin Step %', 'End Step %!']}
value={[beginStepPct, endStepPct]}
onChange={handleStepPctChanged}
min={0}
max={1}
step={0.01}
minStepsBetweenThumbs={5}
isDisabled={!isEnabled}
>
<RangeSliderTrack>
<RangeSliderFilledTrack />
</RangeSliderTrack>
<Tooltip label={formatPct(beginStepPct)} placement="top" hasArrow>
<RangeSliderThumb index={0} />
</Tooltip>
<Tooltip label={formatPct(endStepPct)} placement="top" hasArrow>
<RangeSliderThumb index={1} />
</Tooltip>
<RangeSliderMark
value={0}
sx={{
insetInlineStart: '0 !important',
insetInlineEnd: 'unset !important',
}}
>
0%
</RangeSliderMark>
<RangeSliderMark
value={0.5}
sx={{
insetInlineStart: '50% !important',
transform: 'translateX(-50%)',
}}
>
50%
</RangeSliderMark>
<RangeSliderMark
value={1}
sx={{
insetInlineStart: 'unset !important',
insetInlineEnd: '0 !important',
}}
>
100%
</RangeSliderMark>
</RangeSlider>
</HStack>
</FormControl>
);
};
export default memo(ParamIPAdapterBeginEnd);

View File

@ -64,6 +64,8 @@ export type IPAdapterConfig = {
adapterImage: ImageDTO | null; adapterImage: ImageDTO | null;
model: IPAdapterModelParam | null; model: IPAdapterModelParam | null;
weight: number; weight: number;
beginStepPct: number;
endStepPct: number;
}; };
export type ControlNetState = { export type ControlNetState = {
@ -78,6 +80,8 @@ export const initialIPAdapterState: IPAdapterConfig = {
adapterImage: null, adapterImage: null,
model: null, model: null,
weight: 1, weight: 1,
beginStepPct: 0,
endStepPct: 1,
}; };
export const initialControlNetState: ControlNetState = { export const initialControlNetState: ControlNetState = {
@ -388,6 +392,12 @@ export const controlNetSlice = createSlice({
) => { ) => {
state.ipAdapterInfo.model = action.payload; state.ipAdapterInfo.model = action.payload;
}, },
ipAdapterBeginStepPctChanged: (state, action: PayloadAction<number>) => {
state.ipAdapterInfo.beginStepPct = action.payload;
},
ipAdapterEndStepPctChanged: (state, action: PayloadAction<number>) => {
state.ipAdapterInfo.endStepPct = action.payload;
},
ipAdapterStateReset: (state) => { ipAdapterStateReset: (state) => {
state.isIPAdapterEnabled = false; state.isIPAdapterEnabled = false;
state.ipAdapterInfo = { ...initialIPAdapterState }; state.ipAdapterInfo = { ...initialIPAdapterState };
@ -455,6 +465,8 @@ export const {
ipAdapterImageChanged, ipAdapterImageChanged,
ipAdapterWeightChanged, ipAdapterWeightChanged,
ipAdapterModelChanged, ipAdapterModelChanged,
ipAdapterBeginStepPctChanged,
ipAdapterEndStepPctChanged,
ipAdapterStateReset, ipAdapterStateReset,
} = controlNetSlice.actions; } = controlNetSlice.actions;

View File

@ -14,16 +14,18 @@ export const addIPAdapterToLinearGraph = (
// | MetadataAccumulatorInvocation // | MetadataAccumulatorInvocation
// | undefined; // | undefined;
if (isIPAdapterEnabled) { if (isIPAdapterEnabled && ipAdapterInfo.model) {
const ipAdapterNode: IPAdapterInvocation = { const ipAdapterNode: IPAdapterInvocation = {
id: IP_ADAPTER, id: IP_ADAPTER,
type: 'ip_adapter', type: 'ip_adapter',
is_intermediate: true, is_intermediate: true,
weight: ipAdapterInfo.weight, weight: ipAdapterInfo.weight,
ip_adapter_model: { ip_adapter_model: {
base_model: 'sd-1', base_model: ipAdapterInfo.model?.base_model,
model_name: 'ip_adapter_plus_sd15', model_name: ipAdapterInfo.model?.model_name,
}, },
begin_step_percent: ipAdapterInfo.beginStepPct,
end_step_percent: ipAdapterInfo.endStepPct,
}; };
if (ipAdapterInfo.adapterImage) { if (ipAdapterInfo.adapterImage) {

View File

@ -2564,10 +2564,22 @@ export type components = {
image_encoder_model: components["schemas"]["CLIPVisionModelField"]; image_encoder_model: components["schemas"]["CLIPVisionModelField"];
/** /**
* Weight * Weight
* @description The weight of the IP-Adapter. * @description The weight given to the ControlNet
* @default 1 * @default 1
*/ */
weight?: number; weight?: number | number[];
/**
* Begin Step Percent
* @description When the IP-Adapter is first applied (% of total steps)
* @default 0
*/
begin_step_percent?: number;
/**
* End Step Percent
* @description When the IP-Adapter is last applied (% of total steps)
* @default 1
*/
end_step_percent?: number;
}; };
/** /**
* IP-Adapter * IP-Adapter
@ -2602,10 +2614,22 @@ export type components = {
ip_adapter_model: components["schemas"]["IPAdapterModelField"]; ip_adapter_model: components["schemas"]["IPAdapterModelField"];
/** /**
* Weight * Weight
* @description The weight of the IP-Adapter. * @description The weight given to the IP-Adapter
* @default 1 * @default 1
*/ */
weight?: number; weight?: number | number[];
/**
* Begin Step Percent
* @description When the IP-Adapter is first applied (% of total steps)
* @default 0
*/
begin_step_percent?: number;
/**
* End Step Percent
* @description When the IP-Adapter is last applied (% of total steps)
* @default 1
*/
end_step_percent?: number;
/** /**
* Type * Type
* @default ip_adapter * @default ip_adapter
@ -7706,18 +7730,6 @@ export type components = {
/** Ui Order */ /** Ui Order */
ui_order?: number; ui_order?: number;
}; };
/**
* CLIPVisionModelFormat
* @description An enumeration.
* @enum {string}
*/
CLIPVisionModelFormat: "diffusers";
/**
* StableDiffusion2ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/** /**
* StableDiffusionXLModelFormat * StableDiffusionXLModelFormat
* @description An enumeration. * @description An enumeration.
@ -7725,17 +7737,17 @@ export type components = {
*/ */
StableDiffusionXLModelFormat: "checkpoint" | "diffusers"; StableDiffusionXLModelFormat: "checkpoint" | "diffusers";
/** /**
* ControlNetModelFormat * StableDiffusionOnnxModelFormat
* @description An enumeration. * @description An enumeration.
* @enum {string} * @enum {string}
*/ */
ControlNetModelFormat: "checkpoint" | "diffusers"; StableDiffusionOnnxModelFormat: "olive" | "onnx";
/** /**
* IPAdapterModelFormat * CLIPVisionModelFormat
* @description An enumeration. * @description An enumeration.
* @enum {string} * @enum {string}
*/ */
IPAdapterModelFormat: "invokeai"; CLIPVisionModelFormat: "diffusers";
/** /**
* StableDiffusion1ModelFormat * StableDiffusion1ModelFormat
* @description An enumeration. * @description An enumeration.
@ -7743,11 +7755,23 @@ export type components = {
*/ */
StableDiffusion1ModelFormat: "checkpoint" | "diffusers"; StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
/** /**
* StableDiffusionOnnxModelFormat * IPAdapterModelFormat
* @description An enumeration. * @description An enumeration.
* @enum {string} * @enum {string}
*/ */
StableDiffusionOnnxModelFormat: "olive" | "onnx"; IPAdapterModelFormat: "invokeai";
/**
* StableDiffusion2ModelFormat
* @description An enumeration.
* @enum {string}
*/
StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/**
* ControlNetModelFormat
* @description An enumeration.
* @enum {string}
*/
ControlNetModelFormat: "checkpoint" | "diffusers";
}; };
responses: never; responses: never;
parameters: never; parameters: never;