From d4122a75100be0987b4fdcc381ecedb1946854f1 Mon Sep 17 00:00:00 2001 From: Chenlei Hu Date: Mon, 10 Feb 2025 22:06:11 -0500 Subject: [PATCH] [Refactor] useFloatWidget composable (#2504) --- src/composables/widgets/useFloatWidget.ts | 59 +++++++++++++++++++++++ src/scripts/widgets.ts | 36 +------------- src/utils/mathUtil.ts | 32 ++++++++++++ 3 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 src/composables/widgets/useFloatWidget.ts create mode 100644 src/utils/mathUtil.ts diff --git a/src/composables/widgets/useFloatWidget.ts b/src/composables/widgets/useFloatWidget.ts new file mode 100644 index 000000000..66407d580 --- /dev/null +++ b/src/composables/widgets/useFloatWidget.ts @@ -0,0 +1,59 @@ +import type { LGraphNode } from '@comfyorg/litegraph' +import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets' + +import type { ComfyWidgetConstructor } from '@/scripts/widgets' +import { useSettingStore } from '@/stores/settingStore' +import type { InputSpec } from '@/types/apiTypes' +import { getNumberDefaults } from '@/utils/mathUtil' + +export const useFloatWidget = () => { + const widgetConstructor: ComfyWidgetConstructor = ( + node: LGraphNode, + inputName: string, + inputData: InputSpec + ) => { + // 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 widgetType = sliderEnabled + ? inputOptions.display === 'slider' + ? 'slider' + : 'number' + : 'number' + + const precision = + settingStore.get('Comfy.FloatRoundingPrecision') || undefined + const enableRounding = !settingStore.get('Comfy.DisableFloatRounding') + + const { val, config } = getNumberDefaults(inputOptions, { + defaultStep: 0.5, + precision, + enableRounding + }) + + return { + widget: node.addWidget( + widgetType, + inputName, + val, + function (this: INumericWidget, v: number) { + if (config.round) { + this.value = + Math.round((v + Number.EPSILON) / config.round) * config.round + if (this.value > config.max) this.value = config.max + if (this.value < config.min) this.value = config.min + } else { + this.value = v + } + }, + config + ) + } + } + + return widgetConstructor +} diff --git a/src/scripts/widgets.ts b/src/scripts/widgets.ts index a1f92c8f8..78783edfc 100644 --- a/src/scripts/widgets.ts +++ b/src/scripts/widgets.ts @@ -14,6 +14,7 @@ import TiptapTableRow from '@tiptap/extension-table-row' import TiptapStarterKit from '@tiptap/starter-kit' import { Markdown as TiptapMarkdown } from 'tiptap-markdown' +import { useFloatWidget } from '@/composables/widgets/useFloatWidget' import { useRemoteWidget } from '@/composables/widgets/useRemoteWidget' import { useStringWidget } from '@/composables/widgets/useStringWidget' import { useSettingStore } from '@/stores/settingStore' @@ -434,40 +435,7 @@ function isSlider(display, app) { export const ComfyWidgets: Record = { 'INT:seed': seedWidget, 'INT:noise_seed': seedWidget, - FLOAT(node, inputName, inputData: InputSpec, app) { - let widgetType: 'number' | 'slider' = isSlider(inputData[1]['display'], app) - let precision = app.ui.settings.getSettingValue( - 'Comfy.FloatRoundingPrecision' - ) - let disable_rounding = app.ui.settings.getSettingValue( - 'Comfy.DisableFloatRounding' - ) - if (precision == 0) precision = undefined - const { val, config } = getNumberDefaults( - inputData, - 0.5, - precision, - !disable_rounding - ) - return { - widget: node.addWidget( - widgetType, - inputName, - val, - function (v) { - if (config.round) { - this.value = - Math.round((v + Number.EPSILON) / config.round) * config.round - if (this.value > config.max) this.value = config.max - if (this.value < config.min) this.value = config.min - } else { - this.value = v - } - }, - config - ) - } - }, + FLOAT: useFloatWidget(), INT(node, inputName, inputData: InputSpec, app) { return createIntWidget(node, inputName, inputData, app) }, diff --git a/src/utils/mathUtil.ts b/src/utils/mathUtil.ts new file mode 100644 index 000000000..16903562f --- /dev/null +++ b/src/utils/mathUtil.ts @@ -0,0 +1,32 @@ +import type { InputSpec } from '@/types/apiTypes' + +export function getNumberDefaults( + inputOptions: InputSpec[1], + 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, step: 10.0 * step, round, precision } + } +}