diff --git a/src/composables/widgets/useFloatWidget.ts b/src/composables/widgets/useFloatWidget.ts index 52a9692626..2000a8117f 100644 --- a/src/composables/widgets/useFloatWidget.ts +++ b/src/composables/widgets/useFloatWidget.ts @@ -2,10 +2,9 @@ import type { LGraphNode } from '@comfyorg/litegraph' import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets' import _ from 'lodash' -import type { FloatInputOptions, InputSpec } from '@/schemas/nodeDefSchema' +import { type InputSpec, isFloatInputSpec } from '@/schemas/nodeDefSchema' import type { ComfyWidgetConstructor } from '@/scripts/widgets' import { useSettingStore } from '@/stores/settingStore' -import { getNumberDefaults } from '@/utils/mathUtil' function onFloatValueChange(this: INumericWidget, v: number) { this.value = this.options.round @@ -28,40 +27,48 @@ export const useFloatWidget = () => { inputName: string, inputData: InputSpec ) => { + if (!isFloatInputSpec(inputData)) { + throw new Error(`Invalid input data: ${inputData}`) + } + // TODO: Move to outer scope to avoid re-initializing on every call // Blocked on ComfyWidgets lazy initialization. const settingStore = useSettingStore() const sliderEnabled = !settingStore.get('Comfy.DisableSliders') - const inputOptions = inputData[1] + const inputOptions = inputData[1] ?? {} const widgetType = sliderEnabled - ? inputOptions?.display === 'slider' + ? inputOptions.display === 'slider' ? 'slider' : 'number' : 'number' + const step = inputOptions.step ?? 0.5 const precision = - settingStore.get('Comfy.FloatRoundingPrecision') || undefined + settingStore.get('Comfy.FloatRoundingPrecision') || + Math.max(0, -Math.floor(Math.log10(step))) const enableRounding = !settingStore.get('Comfy.DisableFloatRounding') - const { val, config } = getNumberDefaults( - inputOptions as FloatInputOptions, - { - defaultStep: 0.5, - precision, - enableRounding - } - ) - + const defaultValue = inputOptions.default ?? 0 return { widget: node.addWidget( widgetType, inputName, - val, + defaultValue, onFloatValueChange, - // @ts-expect-error InputSpec is not typed correctly - config + { + min: inputOptions.min ?? 0, + max: inputOptions.max ?? 2048, + round: + enableRounding && precision && !inputOptions.round + ? (1_000_000 * Math.pow(0.1, precision)) / 1_000_000 + : (inputOptions.round as number), + /** @deprecated Use step2 instead. The 10x value is a legacy implementation. */ + step: step * 10.0, + step2: step, + precision + } ) } } diff --git a/src/composables/widgets/useIntWidget.ts b/src/composables/widgets/useIntWidget.ts index b97c6a73d5..52f9691bc7 100644 --- a/src/composables/widgets/useIntWidget.ts +++ b/src/composables/widgets/useIntWidget.ts @@ -1,14 +1,13 @@ import type { LGraphNode } from '@comfyorg/litegraph' import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets' -import type { InputSpec, IntInputOptions } from '@/schemas/nodeDefSchema' +import { type InputSpec, isIntInputSpec } from '@/schemas/nodeDefSchema' import type { ComfyApp } from '@/scripts/app' import { type ComfyWidgetConstructor, addValueControlWidget } from '@/scripts/widgets' import { useSettingStore } from '@/stores/settingStore' -import { getNumberDefaults } from '@/utils/mathUtil' function onValueChange(this: INumericWidget, v: number) { // For integers, always round to the nearest step @@ -41,28 +40,39 @@ export const useIntWidget = () => { app: ComfyApp, widgetName?: string ) => { + if (!isIntInputSpec(inputData)) { + throw new Error(`Invalid input data: ${inputData}`) + } + const settingStore = useSettingStore() const sliderEnabled = !settingStore.get('Comfy.DisableSliders') - const inputOptions = inputData[1] + const inputOptions = inputData[1] ?? {} const widgetType = sliderEnabled ? inputOptions?.display === 'slider' ? 'slider' : 'number' : 'number' - const { val, config } = getNumberDefaults(inputOptions as IntInputOptions, { - defaultStep: 1, - precision: 0, - enableRounding: true - }) - config.precision = 0 - + const step = inputOptions.step ?? 1 + const defaultValue = inputOptions.default ?? 0 const result = { - // @ts-expect-error InputSpec is not typed correctly - widget: node.addWidget(widgetType, inputName, val, onValueChange, config) + widget: node.addWidget( + widgetType, + inputName, + defaultValue, + onValueChange, + { + min: inputOptions.min ?? 0, + max: inputOptions.max ?? 2048, + /** @deprecated Use step2 instead. The 10x value is a legacy implementation. */ + step: step * 10, + step2: step, + precision: 0 + } + ) } - if (inputData[1]?.control_after_generate) { + if (inputOptions.control_after_generate) { const seedControl = addValueControlWidget( node, result.widget, diff --git a/src/schemas/nodeDefSchema.ts b/src/schemas/nodeDefSchema.ts index 1ebdc28acf..c991c40aaa 100644 --- a/src/schemas/nodeDefSchema.ts +++ b/src/schemas/nodeDefSchema.ts @@ -31,7 +31,8 @@ const zNumericInputOptions = zBaseInputOptions.extend({ max: z.number().optional(), step: z.number().optional(), // Note: Many node authors are using INT/FLOAT to pass list of INT/FLOAT. - default: z.union([z.number(), z.array(z.number())]).optional() + default: z.union([z.number(), z.array(z.number())]).optional(), + display: z.enum(['slider', 'number']).optional() }) const zIntInputOptions = zNumericInputOptions.extend({ diff --git a/src/utils/mathUtil.ts b/src/utils/mathUtil.ts deleted file mode 100644 index 7eeee096bb..0000000000 --- a/src/utils/mathUtil.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { - FloatInputOptions, - IntInputOptions -} from '@/schemas/nodeDefSchema' - -export function getNumberDefaults( - inputOptions: IntInputOptions | FloatInputOptions, - options: { - defaultStep: number - precision?: number - enableRounding: boolean - } -) { - const { defaultStep } = options - const { - default: defaultVal = 0, - min = 0, - max = 2048, - step = defaultStep - } = inputOptions - // precision is the number of decimal places to show. - // by default, display the the smallest number of decimal places such that changes of size step are visible. - const { precision = Math.max(-Math.floor(Math.log10(step)), 0) } = options - - let round = inputOptions.round - if (options.enableRounding && (round == undefined || round === true)) { - // by default, round the value to those decimal places shown. - round = Math.round(1000000 * Math.pow(0.1, precision)) / 1000000 - } - - return { - val: defaultVal, - config: { - min, - max, - /** @deprecated Use step2 instead. The 10x value is a legacy implementation. */ - step: step * 10.0, - step2: step, - round, - precision - } - } -}