From fb50a221f8138cf049d3899783c5a9ee375a7e88 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 4 Feb 2024 17:51:08 +1100 Subject: [PATCH] fix(ui): fix color input field alpha Closes #5647 The alpha values in the UI are `0-1` but the backend wants `0-255`. Previously, this was handled in `parseFIeldValue` when building the graph. In a recent release, field types were refactored and broke the alpha handling. The logic for handling alpha values is moved into `ColorFieldInputComponent`, and `parseFieldValue` now just does no value transformations. Though it would be a minor change, I'm leaving this function in because I don't want to change the rest of the logic except when necessary. --- .../inputs/ColorFieldInputComponent.tsx | 22 ++++++++++++++++--- .../nodes/util/graph/buildNodesGraph.ts | 19 ++-------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/ColorFieldInputComponent.tsx b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/ColorFieldInputComponent.tsx index 716c922939..147289772f 100644 --- a/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/ColorFieldInputComponent.tsx +++ b/invokeai/frontend/web/src/features/nodes/components/flow/nodes/Invocation/fields/inputs/ColorFieldInputComponent.tsx @@ -1,31 +1,47 @@ import { useAppDispatch } from 'app/store/storeHooks'; import { fieldColorValueChanged } from 'features/nodes/store/nodesSlice'; import type { ColorFieldInputInstance, ColorFieldInputTemplate } from 'features/nodes/types/field'; -import { memo, useCallback } from 'react'; +import { memo, useCallback, useMemo } from 'react'; import type { RgbaColor } from 'react-colorful'; import { RgbaColorPicker } from 'react-colorful'; import type { FieldComponentProps } from './types'; +const FALLBACK_COLOR: RgbaColor = { r: 0, g: 0, b: 0, a: 255 }; + const ColorFieldInputComponent = (props: FieldComponentProps) => { const { nodeId, field } = props; const dispatch = useAppDispatch(); + const color = useMemo(() => { + // For better or worse, zColorFieldValue is typed as optional. This means that `field.value` and `fieldTemplate.default` + // can be undefined. Rather than changing the schema (which could have other consequences), we can just provide a fallback. + if (!field.value) { + return FALLBACK_COLOR; + } + const { r, g, b, a } = field.value; + // We need to divide by 255 to convert from 0-255 to 0-1, which is what the UI component needs + return { r, g, b, a: a / 255 }; + }, [field.value]); + const handleValueChanged = useCallback( (value: RgbaColor) => { + // We need to multiply by 255 to convert from 0-1 to 0-255, which is what the backend needs + const { r, g, b, a: _a } = value; + const a = Math.round(_a * 255); dispatch( fieldColorValueChanged({ nodeId, fieldName: field.name, - value, + value: { r, g, b, a }, }) ); }, [dispatch, field.name, nodeId] ); - return ; + return ; }; export default memo(ColorFieldInputComponent); diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildNodesGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildNodesGraph.ts index 3dc8c8f735..582aa6b217 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildNodesGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildNodesGraph.ts @@ -1,8 +1,7 @@ import type { NodesState } from 'features/nodes/store/types'; import type { FieldInputInstance } from 'features/nodes/types/field'; -import { isColorFieldInputInstance } from 'features/nodes/types/field'; import { isInvocationNode } from 'features/nodes/types/invocation'; -import { cloneDeep, omit, reduce } from 'lodash-es'; +import { omit, reduce } from 'lodash-es'; import type { Graph } from 'services/api/types'; import type { AnyInvocation } from 'services/events/types'; import { v4 as uuidv4 } from 'uuid'; @@ -11,21 +10,7 @@ import { v4 as uuidv4 } from 'uuid'; * We need to do special handling for some fields */ export const parseFieldValue = (field: FieldInputInstance) => { - if (isColorFieldInputInstance(field)) { - if (field.value) { - const clonedValue = cloneDeep(field.value); - - const { r, g, b, a } = field.value; - - // scale alpha value to PIL's desired range 0-255 - const scaledAlpha = Math.max(0, Math.min(a * 255, 255)); - const transformedColor = { r, g, b, a: scaledAlpha }; - - Object.assign(clonedValue, transformedColor); - return clonedValue; - } - } - + // Currently, no special handling is needed. return field.value; };