From 7be5743011b5cd2b2a07cbc2eff97dca9381f204 Mon Sep 17 00:00:00 2001
From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com>
Date: Sun, 17 Sep 2023 11:53:05 +1200
Subject: [PATCH] feat: Add IP Adapter Begin & End Percent to Linear UI
---
.../components/ipAdapter/IPAdapterPanel.tsx | 2 +
.../ipAdapter/ParamIPAdapterBeginEnd.tsx | 100 ++++++++++++++++++
.../controlNet/store/controlNetSlice.ts | 12 +++
.../addIPAdapterToLinearGraph.ts | 8 +-
.../frontend/web/src/services/api/schema.d.ts | 68 ++++++++----
5 files changed, 165 insertions(+), 25 deletions(-)
create mode 100644 invokeai/frontend/web/src/features/controlNet/components/ipAdapter/ParamIPAdapterBeginEnd.tsx
diff --git a/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/IPAdapterPanel.tsx b/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/IPAdapterPanel.tsx
index 9dbd7e2ffa..b0a1fcc731 100644
--- a/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/IPAdapterPanel.tsx
+++ b/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/IPAdapterPanel.tsx
@@ -1,5 +1,6 @@
import { Flex } from '@chakra-ui/react';
import { memo } from 'react';
+import ParamIPAdapterBeginEnd from './ParamIPAdapterBeginEnd';
import ParamIPAdapterFeatureToggle from './ParamIPAdapterFeatureToggle';
import ParamIPAdapterImage from './ParamIPAdapterImage';
import ParamIPAdapterModelSelect from './ParamIPAdapterModelSelect';
@@ -26,6 +27,7 @@ const IPAdapterPanel = () => {
+
);
};
diff --git a/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/ParamIPAdapterBeginEnd.tsx b/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/ParamIPAdapterBeginEnd.tsx
new file mode 100644
index 0000000000..5bef23b66c
--- /dev/null
+++ b/invokeai/frontend/web/src/features/controlNet/components/ipAdapter/ParamIPAdapterBeginEnd.tsx
@@ -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 (
+
+ {t('controlnet.beginEndStepPercent')}
+
+
+
+
+
+
+
+
+
+
+
+
+ 0%
+
+
+ 50%
+
+
+ 100%
+
+
+
+
+ );
+};
+
+export default memo(ParamIPAdapterBeginEnd);
diff --git a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts
index df55c44cf3..3fe57f4a84 100644
--- a/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts
+++ b/invokeai/frontend/web/src/features/controlNet/store/controlNetSlice.ts
@@ -64,6 +64,8 @@ export type IPAdapterConfig = {
adapterImage: ImageDTO | null;
model: IPAdapterModelParam | null;
weight: number;
+ beginStepPct: number;
+ endStepPct: number;
};
export type ControlNetState = {
@@ -78,6 +80,8 @@ export const initialIPAdapterState: IPAdapterConfig = {
adapterImage: null,
model: null,
weight: 1,
+ beginStepPct: 0,
+ endStepPct: 1,
};
export const initialControlNetState: ControlNetState = {
@@ -388,6 +392,12 @@ export const controlNetSlice = createSlice({
) => {
state.ipAdapterInfo.model = action.payload;
},
+ ipAdapterBeginStepPctChanged: (state, action: PayloadAction) => {
+ state.ipAdapterInfo.beginStepPct = action.payload;
+ },
+ ipAdapterEndStepPctChanged: (state, action: PayloadAction) => {
+ state.ipAdapterInfo.endStepPct = action.payload;
+ },
ipAdapterStateReset: (state) => {
state.isIPAdapterEnabled = false;
state.ipAdapterInfo = { ...initialIPAdapterState };
@@ -455,6 +465,8 @@ export const {
ipAdapterImageChanged,
ipAdapterWeightChanged,
ipAdapterModelChanged,
+ ipAdapterBeginStepPctChanged,
+ ipAdapterEndStepPctChanged,
ipAdapterStateReset,
} = controlNetSlice.actions;
diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addIPAdapterToLinearGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addIPAdapterToLinearGraph.ts
index 95b63e7c3f..da67b1d34d 100644
--- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addIPAdapterToLinearGraph.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addIPAdapterToLinearGraph.ts
@@ -14,16 +14,18 @@ export const addIPAdapterToLinearGraph = (
// | MetadataAccumulatorInvocation
// | undefined;
- if (isIPAdapterEnabled) {
+ if (isIPAdapterEnabled && ipAdapterInfo.model) {
const ipAdapterNode: IPAdapterInvocation = {
id: IP_ADAPTER,
type: 'ip_adapter',
is_intermediate: true,
weight: ipAdapterInfo.weight,
ip_adapter_model: {
- base_model: 'sd-1',
- model_name: 'ip_adapter_plus_sd15',
+ base_model: ipAdapterInfo.model?.base_model,
+ model_name: ipAdapterInfo.model?.model_name,
},
+ begin_step_percent: ipAdapterInfo.beginStepPct,
+ end_step_percent: ipAdapterInfo.endStepPct,
};
if (ipAdapterInfo.adapterImage) {
diff --git a/invokeai/frontend/web/src/services/api/schema.d.ts b/invokeai/frontend/web/src/services/api/schema.d.ts
index 91749c585f..b36f64e90c 100644
--- a/invokeai/frontend/web/src/services/api/schema.d.ts
+++ b/invokeai/frontend/web/src/services/api/schema.d.ts
@@ -2564,10 +2564,22 @@ export type components = {
image_encoder_model: components["schemas"]["CLIPVisionModelField"];
/**
* Weight
- * @description The weight of the IP-Adapter.
+ * @description The weight given to the ControlNet
* @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
@@ -2602,10 +2614,22 @@ export type components = {
ip_adapter_model: components["schemas"]["IPAdapterModelField"];
/**
* Weight
- * @description The weight of the IP-Adapter.
+ * @description The weight given to the IP-Adapter
* @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
* @default ip_adapter
@@ -7706,18 +7730,6 @@ export type components = {
/** Ui Order */
ui_order?: number;
};
- /**
- * CLIPVisionModelFormat
- * @description An enumeration.
- * @enum {string}
- */
- CLIPVisionModelFormat: "diffusers";
- /**
- * StableDiffusion2ModelFormat
- * @description An enumeration.
- * @enum {string}
- */
- StableDiffusion2ModelFormat: "checkpoint" | "diffusers";
/**
* StableDiffusionXLModelFormat
* @description An enumeration.
@@ -7725,17 +7737,17 @@ export type components = {
*/
StableDiffusionXLModelFormat: "checkpoint" | "diffusers";
/**
- * ControlNetModelFormat
+ * StableDiffusionOnnxModelFormat
* @description An enumeration.
* @enum {string}
*/
- ControlNetModelFormat: "checkpoint" | "diffusers";
+ StableDiffusionOnnxModelFormat: "olive" | "onnx";
/**
- * IPAdapterModelFormat
+ * CLIPVisionModelFormat
* @description An enumeration.
* @enum {string}
*/
- IPAdapterModelFormat: "invokeai";
+ CLIPVisionModelFormat: "diffusers";
/**
* StableDiffusion1ModelFormat
* @description An enumeration.
@@ -7743,11 +7755,23 @@ export type components = {
*/
StableDiffusion1ModelFormat: "checkpoint" | "diffusers";
/**
- * StableDiffusionOnnxModelFormat
+ * IPAdapterModelFormat
* @description An enumeration.
* @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;
parameters: never;