mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 19:21:54 +00:00
Inline numeric widget configurations (#2792)
This commit is contained in:
@@ -2,10 +2,9 @@ import type { LGraphNode } from '@comfyorg/litegraph'
|
|||||||
import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import type { FloatInputOptions, InputSpec } from '@/schemas/nodeDefSchema'
|
import { type InputSpec, isFloatInputSpec } from '@/schemas/nodeDefSchema'
|
||||||
import type { ComfyWidgetConstructor } from '@/scripts/widgets'
|
import type { ComfyWidgetConstructor } from '@/scripts/widgets'
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
import { getNumberDefaults } from '@/utils/mathUtil'
|
|
||||||
|
|
||||||
function onFloatValueChange(this: INumericWidget, v: number) {
|
function onFloatValueChange(this: INumericWidget, v: number) {
|
||||||
this.value = this.options.round
|
this.value = this.options.round
|
||||||
@@ -28,40 +27,48 @@ export const useFloatWidget = () => {
|
|||||||
inputName: string,
|
inputName: string,
|
||||||
inputData: InputSpec
|
inputData: InputSpec
|
||||||
) => {
|
) => {
|
||||||
|
if (!isFloatInputSpec(inputData)) {
|
||||||
|
throw new Error(`Invalid input data: ${inputData}`)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Move to outer scope to avoid re-initializing on every call
|
// TODO: Move to outer scope to avoid re-initializing on every call
|
||||||
// Blocked on ComfyWidgets lazy initialization.
|
// Blocked on ComfyWidgets lazy initialization.
|
||||||
|
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
const sliderEnabled = !settingStore.get('Comfy.DisableSliders')
|
const sliderEnabled = !settingStore.get('Comfy.DisableSliders')
|
||||||
const inputOptions = inputData[1]
|
const inputOptions = inputData[1] ?? {}
|
||||||
|
|
||||||
const widgetType = sliderEnabled
|
const widgetType = sliderEnabled
|
||||||
? inputOptions?.display === 'slider'
|
? inputOptions.display === 'slider'
|
||||||
? 'slider'
|
? 'slider'
|
||||||
: 'number'
|
: 'number'
|
||||||
: 'number'
|
: 'number'
|
||||||
|
|
||||||
|
const step = inputOptions.step ?? 0.5
|
||||||
const precision =
|
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 enableRounding = !settingStore.get('Comfy.DisableFloatRounding')
|
||||||
|
|
||||||
const { val, config } = getNumberDefaults(
|
const defaultValue = inputOptions.default ?? 0
|
||||||
inputOptions as FloatInputOptions,
|
|
||||||
{
|
|
||||||
defaultStep: 0.5,
|
|
||||||
precision,
|
|
||||||
enableRounding
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
widget: node.addWidget(
|
widget: node.addWidget(
|
||||||
widgetType,
|
widgetType,
|
||||||
inputName,
|
inputName,
|
||||||
val,
|
defaultValue,
|
||||||
onFloatValueChange,
|
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
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
import type { LGraphNode } from '@comfyorg/litegraph'
|
import type { LGraphNode } from '@comfyorg/litegraph'
|
||||||
import type { INumericWidget } from '@comfyorg/litegraph/dist/types/widgets'
|
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 { ComfyApp } from '@/scripts/app'
|
||||||
import {
|
import {
|
||||||
type ComfyWidgetConstructor,
|
type ComfyWidgetConstructor,
|
||||||
addValueControlWidget
|
addValueControlWidget
|
||||||
} from '@/scripts/widgets'
|
} from '@/scripts/widgets'
|
||||||
import { useSettingStore } from '@/stores/settingStore'
|
import { useSettingStore } from '@/stores/settingStore'
|
||||||
import { getNumberDefaults } from '@/utils/mathUtil'
|
|
||||||
|
|
||||||
function onValueChange(this: INumericWidget, v: number) {
|
function onValueChange(this: INumericWidget, v: number) {
|
||||||
// For integers, always round to the nearest step
|
// For integers, always round to the nearest step
|
||||||
@@ -41,28 +40,39 @@ export const useIntWidget = () => {
|
|||||||
app: ComfyApp,
|
app: ComfyApp,
|
||||||
widgetName?: string
|
widgetName?: string
|
||||||
) => {
|
) => {
|
||||||
|
if (!isIntInputSpec(inputData)) {
|
||||||
|
throw new Error(`Invalid input data: ${inputData}`)
|
||||||
|
}
|
||||||
|
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
const sliderEnabled = !settingStore.get('Comfy.DisableSliders')
|
const sliderEnabled = !settingStore.get('Comfy.DisableSliders')
|
||||||
const inputOptions = inputData[1]
|
const inputOptions = inputData[1] ?? {}
|
||||||
const widgetType = sliderEnabled
|
const widgetType = sliderEnabled
|
||||||
? inputOptions?.display === 'slider'
|
? inputOptions?.display === 'slider'
|
||||||
? 'slider'
|
? 'slider'
|
||||||
: 'number'
|
: 'number'
|
||||||
: 'number'
|
: 'number'
|
||||||
|
|
||||||
const { val, config } = getNumberDefaults(inputOptions as IntInputOptions, {
|
const step = inputOptions.step ?? 1
|
||||||
defaultStep: 1,
|
const defaultValue = inputOptions.default ?? 0
|
||||||
precision: 0,
|
|
||||||
enableRounding: true
|
|
||||||
})
|
|
||||||
config.precision = 0
|
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
// @ts-expect-error InputSpec is not typed correctly
|
widget: node.addWidget(
|
||||||
widget: node.addWidget(widgetType, inputName, val, onValueChange, config)
|
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(
|
const seedControl = addValueControlWidget(
|
||||||
node,
|
node,
|
||||||
result.widget,
|
result.widget,
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ const zNumericInputOptions = zBaseInputOptions.extend({
|
|||||||
max: z.number().optional(),
|
max: z.number().optional(),
|
||||||
step: z.number().optional(),
|
step: z.number().optional(),
|
||||||
// Note: Many node authors are using INT/FLOAT to pass list of INT/FLOAT.
|
// 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({
|
const zIntInputOptions = zNumericInputOptions.extend({
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user