Revert "Support associated socket for widgets" (#896)

Reverts Comfy-Org/litegraph.js#891

Temporary revert to unblock other PRs (causing test failures; frontend
PR for this has not yet been merged).
This commit is contained in:
filtered
2025-04-06 22:38:18 +10:00
committed by GitHub
parent 981979335e
commit ee625b4112
12 changed files with 53 additions and 77 deletions

View File

@@ -576,6 +576,11 @@ export class LGraphCanvas implements ConnectionColorContext {
onNodeSelected?: (node: LGraphNode) => void
onNodeDeselected?: (node: LGraphNode) => void
onRender?: (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) => void
/** Implement this function to allow conversion of widget types to input types, e.g. number -> INT or FLOAT for widget link validation checks */
getWidgetLinkType?: (
widget: IWidget,
node: LGraphNode,
) => string | null | undefined
/**
* Creates a new instance of LGraphCanvas.
@@ -2596,6 +2601,20 @@ export class LGraphCanvas implements ConnectionColorContext {
// No link, or none of the dragged links may be dropped here
} else if (linkConnector.state.connectingTo === "input") {
if (inputId === -1 && outputId === -1) {
// Allow support for linking to widgets, handled externally to LiteGraph
if (this.getWidgetLinkType && overWidget) {
const widgetLinkType = this.getWidgetLinkType(overWidget, node)
if (
widgetLinkType &&
LiteGraph.isValidConnection(linkConnector.renderLinks[0]?.fromSlot.type, widgetLinkType) &&
firstLink.node.isValidWidgetLink?.(firstLink.fromSlotIndex, node, overWidget) !== false
) {
const { pos: [nodeX, nodeY] } = node
highlightPos = [nodeX + 10, nodeY + 10 + overWidget.y]
linkConnector.overWidget = overWidget
linkConnector.overWidgetType = widgetLinkType
}
}
// Node background / title under the pointer
if (!linkConnector.overWidget) {
const result = node.findInputByType(firstLink.fromSlot.type)
@@ -5185,7 +5204,12 @@ export class LGraphCanvas implements ConnectionColorContext {
posY: number,
ctx: CanvasRenderingContext2D,
): void {
const { linkConnector } = this
node.drawWidgets(ctx, {
colorContext: this,
linkOverWidget: linkConnector.overWidget,
linkOverWidgetType: linkConnector.overWidgetType,
lowQuality: this.low_quality,
editorAlpha: this.editor_alpha,
})

View File

@@ -1585,7 +1585,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
let widgets_height = 0
if (this.widgets?.length) {
for (const widget of this.widgets) {
if (!this.isWidgetVisible(widget)) continue
if (widget.hidden || (widget.advanced && !this.showAdvanced)) continue
let widget_height = 0
if (widget.computeSize) {
@@ -1929,8 +1929,9 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
for (const widget of widgets) {
if (
(widget.computedDisabled && !includeDisabled) ||
!this.isWidgetVisible(widget)
(widget.disabled && !includeDisabled) ||
widget.hidden ||
(widget.advanced && !this.showAdvanced)
) {
continue
}
@@ -3363,25 +3364,16 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
}
}
/**
* Returns `true` if the widget is visible, otherwise `false`.
*/
isWidgetVisible(widget: IWidget): boolean {
const isHidden = (
this.collapsed ||
widget.hidden ||
(widget.advanced && !this.showAdvanced)
)
return !isHidden
}
drawWidgets(ctx: CanvasRenderingContext2D, options: {
colorContext: ConnectionColorContext
linkOverWidget: IWidget | null | undefined
linkOverWidgetType?: ISlotType
lowQuality?: boolean
editorAlpha?: number
}): void {
if (!this.widgets) return
const { lowQuality = false, editorAlpha = 1 } = options
const { colorContext, linkOverWidget, linkOverWidgetType, lowQuality = false, editorAlpha = 1 } = options
const width = this.size[0]
const widgets = this.widgets
@@ -3392,19 +3384,25 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
const margin = 15
for (const w of widgets) {
if (!this.isWidgetVisible(w)) continue
if (w.hidden || (w.advanced && !this.showAdvanced)) continue
const y = w.y
const outline_color = w.advanced ? LiteGraph.WIDGET_ADVANCED_OUTLINE_COLOR : LiteGraph.WIDGET_OUTLINE_COLOR
w.last_y = y
// Disable widget if it is disabled or if the value is passed from socket connection.
w.computedDisabled = w.disabled || this.getSlotFromWidget(w)?.link != null
if (w === linkOverWidget) {
// Manually draw a slot next to the widget simulating an input
new NodeInputSlot({
name: "",
// @ts-expect-error https://github.com/Comfy-Org/litegraph.js/issues/616
type: linkOverWidgetType,
link: 0,
}).draw(ctx, { pos: [10, y + 10], colorContext })
}
w.last_y = y
ctx.strokeStyle = outline_color
ctx.fillStyle = "#222"
ctx.textAlign = "left"
if (w.computedDisabled) ctx.globalAlpha *= 0.5
if (w.disabled) ctx.globalAlpha *= 0.5
const widget_width = w.width || width
const WidgetClass: typeof WIDGET_TYPE_MAP[string] = WIDGET_TYPE_MAP[w.type]
@@ -3526,25 +3524,6 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
return this.#getMouseOverSlot(slot) === slot
}
#isMouseOverWidget(widget: IWidget): boolean {
return this.mouseOver?.overWidget === widget
}
/**
* Returns the input slot that is associated with the given widget.
*/
getSlotFromWidget(widget: IWidget): INodeInputSlot | undefined {
return this.inputs.find(slot => isWidgetInputSlot(slot) && slot.widget.name === widget.name)
}
/**
* Returns the widget that is associated with the given input slot.
*/
getWidgetFromSlot(slot: INodeInputSlot): IWidget | undefined {
if (!isWidgetInputSlot(slot)) return
return this.widgets?.find(w => w.name === slot.widget.name)
}
/**
* Draws the node's input and output slots.
*/
@@ -3565,18 +3544,7 @@ export class LGraphNode implements Positionable, IPinnable, IColorable {
const labelColor = highlight
? this.highlightColor
: LiteGraph.NODE_TEXT_COLOR
// Show slot if it's not a widget input slot
// or if it's a widget input slot and satisfies one of the following:
// - the mouse is over the widget
// - the slot is valid during link drop
// - the slot is connected
const showSlot = !isWidgetInputSlot(slot) ||
this.#isMouseOverWidget(this.getWidgetFromSlot(slot)!) ||
(fromSlot && slotInstance.isValidTarget(fromSlot)) ||
slotInstance.isConnected()
ctx.globalAlpha = showSlot ? (isValid ? editorAlpha : 0.4 * editorAlpha) : 0
ctx.globalAlpha = isValid ? editorAlpha : 0.4 * editorAlpha
slotInstance.draw(ctx, {
pos: layoutElement?.center ?? [0, 0],

View File

@@ -214,8 +214,7 @@ export abstract class NodeSlot implements INodeSlot {
if (!lowQuality && doStroke) ctx.stroke()
// render slot label
const hideLabel = lowQuality || isWidgetInputSlot(this)
if (!hideLabel) {
if (!lowQuality) {
const text = this.renderingLabel
if (text) {
// TODO: Finish impl. Highlight text on mouseover unless we're connecting links.

View File

@@ -153,38 +153,24 @@ export interface IBaseWidget {
/**
* The computed height of the widget. Used by customized node resize logic.
* See scripts/domWidget.ts for more details.
* @readonly [Computed] This property is computed by the node.
*/
computedHeight?: number
/**
* The starting y position of the widget after layout.
* @readonly [Computed] This property is computed by the node.
*/
y: number
/**
* The y position of the widget after drawing (rendering).
* @readonly [Computed] This property is computed by the node.
* @deprecated There is no longer dynamic y adjustment on rendering anymore.
* Use {@link IBaseWidget.y} instead.
*/
last_y?: number
width?: number
/**
* Whether the widget is disabled. Disabled widgets are rendered at half opacity.
* See also {@link IBaseWidget.computedDisabled}.
*/
disabled?: boolean
/**
* The disabled state used for rendering based on various conditions including
* {@link IBaseWidget.disabled}.
* @readonly [Computed] This property is computed by the node.
*/
computedDisabled?: boolean
hidden?: boolean
advanced?: boolean

View File

@@ -23,7 +23,6 @@ export abstract class BaseWidget implements IBaseWidget {
last_y?: number
width?: number
disabled?: boolean
computedDisabled?: boolean
hidden?: boolean
advanced?: boolean
tooltip?: string

View File

@@ -33,7 +33,7 @@ export class BooleanWidget extends BaseWidget implements IBooleanWidget {
ctx.roundRect(margin, y, width - margin * 2, height, [height * 0.5])
else ctx.rect(margin, y, width - margin * 2, height)
ctx.fill()
if (show_text && !this.computedDisabled) ctx.stroke()
if (show_text && !this.disabled) ctx.stroke()
ctx.fillStyle = this.value ? "#89A" : "#333"
ctx.beginPath()
ctx.arc(

View File

@@ -45,7 +45,7 @@ export class ButtonWidget extends BaseWidget implements IButtonWidget {
ctx.fillRect(margin, y, width - margin * 2, height)
// Draw button outline if not disabled
if (show_text && !this.computedDisabled) {
if (show_text && !this.disabled) {
ctx.strokeStyle = this.outline_color
ctx.strokeRect(margin, y, width - margin * 2, height)
}

View File

@@ -49,7 +49,7 @@ export class ComboWidget extends BaseWidget implements IComboWidget {
ctx.fill()
if (show_text) {
if (!this.computedDisabled) {
if (!this.disabled) {
ctx.stroke()
// Draw left arrow
ctx.fillStyle = this.text_color

View File

@@ -158,7 +158,7 @@ export class KnobWidget extends BaseWidget implements IKnobWidget {
ctx.closePath()
// Draw outline if not disabled
if (show_text && !this.computedDisabled) {
if (show_text && !this.disabled) {
ctx.strokeStyle = this.outline_color
// Draw value
ctx.beginPath()

View File

@@ -64,7 +64,7 @@ export class NumberWidget extends BaseWidget implements INumericWidget {
ctx.fill()
if (show_text) {
if (!this.computedDisabled) {
if (!this.disabled) {
ctx.stroke()
// Draw left arrow
ctx.fillStyle = this.text_color

View File

@@ -54,7 +54,7 @@ export class SliderWidget extends BaseWidget implements ISliderWidget {
ctx.fillRect(margin, y, nvalue * (width - margin * 2), height)
// Draw outline if not disabled
if (show_text && !this.computedDisabled) {
if (show_text && !this.disabled) {
ctx.strokeStyle = this.outline_color
ctx.strokeRect(margin, y, width - margin * 2, height)
}

View File

@@ -47,7 +47,7 @@ export class TextWidget extends BaseWidget implements IStringWidget {
ctx.fill()
if (show_text) {
if (!this.computedDisabled) ctx.stroke()
if (!this.disabled) ctx.stroke()
ctx.save()
ctx.beginPath()
ctx.rect(margin, y, width - margin * 2, height)