diff --git a/src/composables/graph/useGraphNodeManager.ts b/src/composables/graph/useGraphNodeManager.ts index 4482f9433..a7755afa6 100644 --- a/src/composables/graph/useGraphNodeManager.ts +++ b/src/composables/graph/useGraphNodeManager.ts @@ -34,6 +34,7 @@ import type { } from '@/lib/litegraph/src/litegraph' import type { TitleMode } from '@/lib/litegraph/src/types/globalEnums' import { NodeSlotType } from '@/lib/litegraph/src/types/globalEnums' +import { app } from '@/scripts/app' export interface WidgetSlotMetadata { index: number @@ -47,6 +48,7 @@ export interface SafeWidgetData { borderStyle?: string callback?: ((value: unknown) => void) | undefined controlWidget?: SafeControlWidget + hasLayoutSize?: boolean isDOMWidget?: boolean label?: string nodeType?: string @@ -171,7 +173,12 @@ export function safeWidgetMapper( const callback = (v: unknown) => { const value = normalizeWidgetValue(v) widget.value = value ?? undefined - widget.callback?.(value) + // Match litegraph callback signature: (value, canvas, node, pos, event) + // Some extensions (e.g., Impact Pack) expect node as the 3rd parameter + widget.callback?.(value, app.canvas, node) + // Trigger redraw for all legacy widgets on this node (e.g., mask preview) + // This ensures widgets that depend on other widget values get updated + node.widgets?.forEach((w) => w.triggerDraw?.()) } return { @@ -181,6 +188,7 @@ export function safeWidgetMapper( borderStyle, callback, controlWidget: getControlWidget(widget), + hasLayoutSize: typeof widget.computeLayoutSize === 'function', isDOMWidget: isDOMWidget(widget), label: widget.label, nodeType: getNodeType(node, widget), diff --git a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue index 102f67945..9975ec864 100644 --- a/src/renderer/extensions/vueNodes/components/NodeWidgets.vue +++ b/src/renderer/extensions/vueNodes/components/NodeWidgets.vue @@ -203,10 +203,13 @@ const processedWidgets = computed((): ProcessedWidget[] => { }) const gridTemplateRows = computed((): string => { - const widgets = toValue(processedWidgets) - return widgets - .filter((w) => !w.simplified.options?.hidden) - .map((w) => (shouldExpand(w.type) ? 'auto' : 'min-content')) + if (!nodeData?.widgets) return '' + const processedNames = new Set(toValue(processedWidgets).map((w) => w.name)) + return nodeData.widgets + .filter((w) => processedNames.has(w.name) && !w.options?.hidden) + .map((w) => + shouldExpand(w.type) || w.hasLayoutSize ? 'auto' : 'min-content' + ) .join(' ') }) diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue index 512c182c8..fb6be5cb8 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetInputNumberInput.vue @@ -31,10 +31,17 @@ const precision = computed(() => { // Calculate the step value based on precision or widget options const stepValue = computed(() => { - // Use step2 (correct input spec value) instead of step (legacy 10x value) + // Use step2 (correct input spec value) if available if (props.widget.options?.step2 !== undefined) { return Number(props.widget.options.step2) } + // Use step / 10 for custom large step values (> 10) to match litegraph behavior + // This is important for extensions like Impact Pack that use custom step values (e.g., 640) + // We skip default step values (1, 10) to avoid affecting normal widgets + const step = props.widget.options?.step + if (step !== undefined && step > 10) { + return Number(step) / 10 + } // Otherwise, derive from precision if (precision.value !== undefined) { if (precision.value === 0) { diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetLegacy.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetLegacy.vue index d82665cdd..64b673519 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetLegacy.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetLegacy.vue @@ -17,6 +17,7 @@ const props = defineProps<{ }>() const canvasEl = ref() +const containerHeight = ref(20) const canvas: LGraphCanvas = useCanvasStore().canvas as LGraphCanvas let node: LGraphNode | undefined @@ -52,9 +53,19 @@ onBeforeUnmount(() => { function draw() { if (!widgetInstance || !node) return const width = canvasEl.value.parentElement.clientWidth - const height = widgetInstance.computeSize - ? widgetInstance.computeSize(width)[1] - : 20 + // Priority: computedHeight (from litegraph) > computeLayoutSize > computeSize + let height = 20 + if (widgetInstance.computedHeight) { + height = widgetInstance.computedHeight + } else if (widgetInstance.computeLayoutSize) { + height = widgetInstance.computeLayoutSize(node).minHeight + } else if (widgetInstance.computeSize) { + height = widgetInstance.computeSize(width)[1] + } + containerHeight.value = height + // Set node.canvasHeight for legacy widgets that use it (e.g., Impact Pack) + // @ts-expect-error canvasHeight is a custom property used by some extensions + node.canvasHeight = height widgetInstance.y = 0 canvasEl.value.height = (height + 2) * scaleFactor canvasEl.value.width = width * scaleFactor @@ -87,7 +98,10 @@ function handleMove(e: PointerEvent) { }