diff --git a/invokeai/app/invocations/latent.py b/invokeai/app/invocations/latent.py
index 90a9137dd3..e9b1425464 100644
--- a/invokeai/app/invocations/latent.py
+++ b/invokeai/app/invocations/latent.py
@@ -260,7 +260,7 @@ class TextToLatentsInvocation(BaseInvocation):
print("type of control input: ", type(self.control))
if (self.control is None):
- control_model_name = None
+ control_model = None
control_image_field = None
control_weight = None
else:
diff --git a/invokeai/frontend/web/src/common/util/parseMetadata.ts b/invokeai/frontend/web/src/common/util/parseMetadata.ts
index c27833218b..c1be165eac 100644
--- a/invokeai/frontend/web/src/common/util/parseMetadata.ts
+++ b/invokeai/frontend/web/src/common/util/parseMetadata.ts
@@ -1,5 +1,5 @@
import { forEach, size } from 'lodash-es';
-import { ImageField, LatentsField, ConditioningField } from 'services/api';
+import { ImageField, LatentsField, ConditioningField, ControlField} from 'services/api';
const OBJECT_TYPESTRING = '[object Object]';
const STRING_TYPESTRING = '[object String]';
@@ -98,6 +98,29 @@ const parseConditioningField = (
};
};
+const parseControlField = (controlField: unknown): ControlField | undefined => {
+ // Must be an object
+ if (!isObject(controlField)) {
+ return;
+ }
+
+ // A ControlField must have a `control`
+ if (!('control' in controlField)) {
+ return;
+ }
+ console.log(typeof controlField.control);
+ // A ControlField's `controlnets` must be a array
+ // TODO: check type - array of tuples
+ //if (Array.isArray(controlField.control)) {
+ //return;
+ // }
+
+ // Build a valid ControlField
+ return {
+ control: controlField.control,
+ };
+};
+
type NodeMetadata = {
[key: string]:
| string
@@ -105,7 +128,8 @@ type NodeMetadata = {
| boolean
| ImageField
| LatentsField
- | ConditioningField;
+ | ConditioningField
+ | ControlField;
};
type InvokeAIMetadata = {
@@ -131,7 +155,7 @@ export const parseNodeMetadata = (
return;
}
- // the only valid object types are ImageField, LatentsField and ConditioningField
+ // the only valid object types are ImageField, LatentsField, ConditioningField, ControlField
if (isObject(nodeItem)) {
if ('image_name' in nodeItem || 'image_type' in nodeItem) {
const imageField = parseImageField(nodeItem);
@@ -156,6 +180,14 @@ export const parseNodeMetadata = (
}
return;
}
+
+ if ('control' in nodeItem) {
+ const controlField = parseControlField(nodeItem);
+ if (controlField) {
+ parsed[nodeKey] = controlField;
+ }
+ return;
+ }
}
// otherwise we accept any string, number or boolean
diff --git a/invokeai/frontend/web/src/features/nodes/components/InputFieldComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/InputFieldComponent.tsx
index 9527708c40..f8e9800f76 100644
--- a/invokeai/frontend/web/src/features/nodes/components/InputFieldComponent.tsx
+++ b/invokeai/frontend/web/src/features/nodes/components/InputFieldComponent.tsx
@@ -7,6 +7,12 @@ import EnumInputFieldComponent from './fields/EnumInputFieldComponent';
import ImageInputFieldComponent from './fields/ImageInputFieldComponent';
import LatentsInputFieldComponent from './fields/LatentsInputFieldComponent';
import ConditioningInputFieldComponent from './fields/ConditioningInputFieldComponent';
+<<<<<<< HEAD
+=======
+import ControlNetInputFieldComponent from './fields/ControlNetInputFieldComponent';
+import ControlInputFieldComponent from './fields/ControlInputFieldComponent';
+
+>>>>>>> 5b9fa636 (Refactored controlnet node to output ControlField that bundles control info.)
import ModelInputFieldComponent from './fields/ModelInputFieldComponent';
import NumberInputFieldComponent from './fields/NumberInputFieldComponent';
import StringInputFieldComponent from './fields/StringInputFieldComponent';
@@ -97,6 +103,29 @@ const InputFieldComponent = (props: InputFieldComponentProps) => {
);
}
+<<<<<<< HEAD
+=======
+ if (type === 'controlnet' && template.type === 'controlnet') {
+ return (
+
+ );
+ }
+
+ if (type === 'control' && template.type === 'control') {
+ return (
+
+ );
+ }
+
+>>>>>>> 5b9fa636 (Refactored controlnet node to output ControlField that bundles control info.)
if (type === 'model' && template.type === 'model') {
return (
+) => {
+ const { nodeId, field } = props;
+
+ return null;
+};
+
+export default memo(ControlInputFieldComponent);
diff --git a/invokeai/frontend/web/src/features/nodes/types/constants.ts b/invokeai/frontend/web/src/features/nodes/types/constants.ts
index 7e4dadc21d..603f68f35e 100644
--- a/invokeai/frontend/web/src/features/nodes/types/constants.ts
+++ b/invokeai/frontend/web/src/features/nodes/types/constants.ts
@@ -15,6 +15,7 @@ export const FIELD_TYPE_MAP: Record = {
array: 'array',
item: 'item',
ColorField: 'color',
+ ControlField: 'control',
};
const COLOR_TOKEN_VALUE = 500;
@@ -22,6 +23,9 @@ const COLOR_TOKEN_VALUE = 500;
const getColorTokenCssVariable = (color: string) =>
`var(--invokeai-colors-${color}-${COLOR_TOKEN_VALUE})`;
+// @ts-ignore
+// @ts-ignore
+// @ts-ignore
export const FIELDS: Record = {
integer: {
color: 'red',
@@ -71,6 +75,12 @@ export const FIELDS: Record = {
title: 'Conditioning',
description: 'Conditioning may be passed between nodes.',
},
+ control: {
+ color: 'cyan',
+ colorCssVar: getColorTokenCssVariable('cyan'), // TODO: no free color left
+ title: 'Control',
+ description: 'Control info passed between nodes.',
+ },
model: {
color: 'teal',
colorCssVar: getColorTokenCssVariable('teal'),
diff --git a/invokeai/frontend/web/src/features/nodes/types/types.ts b/invokeai/frontend/web/src/features/nodes/types/types.ts
index efb4a5518d..998d8a7956 100644
--- a/invokeai/frontend/web/src/features/nodes/types/types.ts
+++ b/invokeai/frontend/web/src/features/nodes/types/types.ts
@@ -61,6 +61,7 @@ export type FieldType =
| 'image'
| 'latents'
| 'conditioning'
+ | 'control'
| 'model'
| 'array'
| 'item'
@@ -82,6 +83,7 @@ export type InputFieldValue =
| ImageInputFieldValue
| LatentsInputFieldValue
| ConditioningInputFieldValue
+ | ControlInputFieldValue
| EnumInputFieldValue
| ModelInputFieldValue
| ArrayInputFieldValue
@@ -102,6 +104,7 @@ export type InputFieldTemplate =
| ImageInputFieldTemplate
| LatentsInputFieldTemplate
| ConditioningInputFieldTemplate
+ | ControlInputFieldTemplate
| EnumInputFieldTemplate
| ModelInputFieldTemplate
| ArrayInputFieldTemplate
@@ -177,6 +180,10 @@ export type LatentsInputFieldValue = FieldValueBase & {
export type ConditioningInputFieldValue = FieldValueBase & {
type: 'conditioning';
+};
+
+export type ControlInputFieldValue = FieldValueBase & {
+ type: 'control';
value?: undefined;
};
@@ -262,6 +269,11 @@ export type ConditioningInputFieldTemplate = InputFieldTemplateBase & {
type: 'conditioning';
};
+export type ControlInputFieldTemplate = InputFieldTemplateBase & {
+ default: undefined;
+ type: 'control';
+};
+
export type EnumInputFieldTemplate = InputFieldTemplateBase & {
default: string | number;
type: 'enum';
diff --git a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts
index 11f0087488..28a9c8ec7c 100644
--- a/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/fieldTemplateBuilders.ts
@@ -10,6 +10,7 @@ import {
IntegerInputFieldTemplate,
LatentsInputFieldTemplate,
ConditioningInputFieldTemplate,
+ ControlInputFieldTemplate,
StringInputFieldTemplate,
ModelInputFieldTemplate,
ArrayInputFieldTemplate,
@@ -215,6 +216,21 @@ const buildConditioningInputFieldTemplate = ({
return template;
};
+const buildControlInputFieldTemplate = ({
+ schemaObject,
+ baseField,
+}: BuildInputFieldArg): ControlInputFieldTemplate => {
+ const template: ControlInputFieldTemplate = {
+ ...baseField,
+ type: 'control',
+ inputRequirement: 'always',
+ inputKind: 'connection',
+ default: schemaObject.default ?? undefined,
+ };
+
+ return template;
+};
+
const buildEnumInputFieldTemplate = ({
schemaObject,
baseField,
@@ -331,6 +347,9 @@ export const buildInputFieldTemplate = (
if (['conditioning'].includes(fieldType)) {
return buildConditioningInputFieldTemplate({ schemaObject, baseField });
}
+ if (['control'].includes(fieldType)) {
+ return buildControlInputFieldTemplate({ schemaObject, baseField });
+ }
if (['model'].includes(fieldType)) {
return buildModelInputFieldTemplate({ schemaObject, baseField });
}
diff --git a/invokeai/frontend/web/src/features/nodes/util/fieldValueBuilders.ts b/invokeai/frontend/web/src/features/nodes/util/fieldValueBuilders.ts
index 9221e5f7ac..0b10a3e464 100644
--- a/invokeai/frontend/web/src/features/nodes/util/fieldValueBuilders.ts
+++ b/invokeai/frontend/web/src/features/nodes/util/fieldValueBuilders.ts
@@ -52,6 +52,10 @@ export const buildInputFieldValue = (
fieldValue.value = undefined;
}
+ if (template.type === 'control') {
+ fieldValue.value = undefined;
+ }
+
if (template.type === 'model') {
fieldValue.value = undefined;
}