[backport cloud/1.42] fix: resolve incorrect GLSL live preview for non-primitive widget types (#11116)

Backport of #11010 to `cloud/1.42`

Automatically created by backport workflow.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-11116-backport-cloud-1-42-fix-resolve-incorrect-GLSL-live-preview-for-non-primitive-widget--33e6d73d365081399958c929458eb840)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Terry Jia <terryjia88@gmail.com>
This commit is contained in:
Comfy Org PR Bot
2026-04-11 00:42:13 +09:00
committed by GitHub
parent 1f67eafa40
commit 228c2805f9
4 changed files with 83 additions and 32 deletions

View File

@@ -282,7 +282,44 @@ function createInnerPreview(
}
}
function getCustomResolution(): [number, number] | null {
const gId = graphId.value
if (!gId) return null
const sizeModeNodeId = innerGLSLNode
? (innerGLSLNode.id as NodeId)
: nodeId.value
if (sizeModeNodeId == null) return null
const sizeMode = widgetValueStore.getWidget(
gId,
sizeModeNodeId,
'size_mode'
)
if (sizeMode?.value !== 'custom') return null
const widthWidget = widgetValueStore.getWidget(
gId,
sizeModeNodeId,
'size_mode.width'
)
const heightWidget = widgetValueStore.getWidget(
gId,
sizeModeNodeId,
'size_mode.height'
)
if (!widthWidget || !heightWidget) return null
return clampResolution(
normalizeDimension(widthWidget.value),
normalizeDimension(heightWidget.value)
)
}
function getResolution(): [number, number] {
const custom = getCustomResolution()
if (custom) return custom
const node = nodeRef.value
if (!node?.inputs) return [DEFAULT_SIZE, DEFAULT_SIZE]
@@ -325,27 +362,6 @@ function createInnerPreview(
}
}
const gId = graphId.value
const nId = nodeId.value
if (gId && nId != null) {
const widthWidget = widgetValueStore.getWidget(
gId,
nId,
'size_mode.width'
)
const heightWidget = widgetValueStore.getWidget(
gId,
nId,
'size_mode.height'
)
if (widthWidget && heightWidget) {
return clampResolution(
normalizeDimension(widthWidget.value),
normalizeDimension(heightWidget.value)
)
}
}
return [DEFAULT_SIZE, DEFAULT_SIZE]
}

View File

@@ -10,6 +10,7 @@ import { useWidgetValueStore } from '@/stores/widgetValueStore'
import { isCurveData } from '@/components/curve/curveUtils'
import type { CurveData } from '@/components/curve/types'
import type { GLSLRendererConfig } from '@/renderer/glsl/useGLSLRenderer'
import { hexToInt } from '@/utils/colorUtil'
interface AutogrowGroup {
max: number
@@ -20,6 +21,8 @@ interface AutogrowGroup {
interface UniformSource {
nodeId: NodeId
widgetName: string
/** Fallback getter for widgets not registered in widgetValueStore (e.g. hidden computed widgets). */
directValue: () => unknown
}
interface UniformSources {
@@ -78,16 +81,19 @@ export function extractUniformSources(
if (!link || link.origin_id === SUBGRAPH_INPUT_ID) continue
const sourceNode = subgraph.getNodeById(link.origin_id)
if (!sourceNode?.widgets?.[0]) continue
if (!sourceNode?.widgets?.length) continue
const inputName = input.name ?? ''
const dotIndex = inputName.indexOf('.')
if (dotIndex === -1) continue
const prefix = inputName.slice(0, dotIndex)
if (link.origin_slot >= sourceNode.widgets.length) continue
const widget = sourceNode.widgets[link.origin_slot]
const source: UniformSource = {
nodeId: sourceNode.id as NodeId,
widgetName: sourceNode.widgets[0].name
widgetName: widget.name,
directValue: () => widget.value
}
if (prefix === 'floats') floats.push(source)
@@ -99,6 +105,11 @@ export function extractUniformSources(
return { floats, ints, bools, curves }
}
function toNumber(v: unknown): number {
if (typeof v === 'string' && v.startsWith('#')) return hexToInt(v)
return Number(v) || 0
}
export function useGLSLUniforms(
graphId: ComputedRef<UUID | undefined>,
nodeId: ComputedRef<NodeId | undefined>,
@@ -120,9 +131,9 @@ export function useGLSLUniforms(
if (!gId) return []
if (subgraphSources) {
return subgraphSources.map(({ nodeId: nId, widgetName }) => {
return subgraphSources.map(({ nodeId: nId, widgetName, directValue }) => {
const widget = widgetValueStore.getWidget(gId, nId, widgetName)
return coerce(widget?.value ?? defaultValue)
return coerce(widget?.value ?? directValue() ?? defaultValue)
})
}
@@ -142,19 +153,24 @@ export function useGLSLUniforms(
const slot = node.inputs?.findIndex((inp) => inp.name === inputName)
if (slot == null || slot < 0) break
const link = node.getInputLink(slot)
if (!link) break
const upstreamNode = node.getInputNode(slot)
if (!upstreamNode) break
const upstreamWidgets = widgetValueStore.getNodeWidgets(
gId,
upstreamNode.id as NodeId
)
if (upstreamWidgets.length === 0) break
values.push(coerce(upstreamWidgets[0].value))
if (
upstreamWidgets.length === 0 ||
link.origin_slot >= upstreamWidgets.length
)
break
values.push(coerce(upstreamWidgets[link.origin_slot].value))
}
return values
}
const toNumber = (v: unknown): number => Number(v) || 0
const toBool = (v: unknown): boolean => Boolean(v)
const floatValues = computed(() =>
@@ -197,11 +213,10 @@ export function useGLSLUniforms(
const sources = uniformSources.value?.curves
if (sources && sources.length > 0) {
return sources
.map(({ nodeId: nId, widgetName }) => {
.map(({ nodeId: nId, widgetName, directValue }) => {
const widget = widgetValueStore.getWidget(gId, nId, widgetName)
return widget && isCurveData(widget.value)
? (widget.value as CurveData)
: null
const value = widget?.value ?? directValue()
return isCurveData(value) ? (value as CurveData) : null
})
.filter((v): v is CurveData => v !== null)
}

View File

@@ -4,6 +4,7 @@ import type { ColorAdjustOptions } from '@/utils/colorUtil'
import {
adjustColor,
hexToHsva,
hexToInt,
hexToRgb,
hsbToRgb,
hsvaToHex,
@@ -95,6 +96,20 @@ describe('colorUtil conversions', () => {
})
})
describe('hexToInt', () => {
it('converts 6-digit hex to packed integer', () => {
expect(hexToInt('#ff0000')).toBe(0xff0000)
expect(hexToInt('#00ff00')).toBe(0x00ff00)
expect(hexToInt('#45edf5')).toBe(0x45edf5)
expect(hexToInt('#000000')).toBe(0)
})
it('converts 3-digit hex to packed integer', () => {
expect(hexToInt('#fff')).toBe(0xffffff)
expect(hexToInt('#f00')).toBe(0xff0000)
})
})
describe('parseToRgb', () => {
it('parses #hex', () => {
expect(parseToRgb('#ff0000')).toEqual({ r: 255, g: 0, b: 0 })

View File

@@ -82,6 +82,11 @@ export function hexToRgb(hex: string): RGB {
return { r, g, b }
}
export function hexToInt(hex: string): number {
const { r, g, b } = hexToRgb(hex)
return (r << 16) | (g << 8) | b
}
export function rgbToHex({ r, g, b }: RGB): string {
const toHex = (n: number) =>
Math.max(0, Math.min(255, Math.round(n)))