mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-03 14:54:37 +00:00
Add logic to compute widget.prompted
NOTE: Currently fails to track state with nested subgraphs The event for "Leaving a graph" does not indicate the direction
This commit is contained in:
@@ -28,4 +28,5 @@ export function promoteWidget(widget: IBaseWidget, node: LGraphNode) {
|
||||
pushWidgets(onode, [`${node.id}`, widget.name])
|
||||
}
|
||||
}
|
||||
widget.promoted = true
|
||||
}
|
||||
|
||||
@@ -1865,13 +1865,13 @@ export class LGraphCanvas
|
||||
this.#dirty()
|
||||
}
|
||||
|
||||
openSubgraph(subgraph: Subgraph): void {
|
||||
openSubgraph(subgraph: Subgraph, fromNode: SubgraphNode): void {
|
||||
const { graph } = this
|
||||
if (!graph) throw new NullGraphError()
|
||||
|
||||
const options = {
|
||||
bubbles: true,
|
||||
detail: { subgraph, closingGraph: graph },
|
||||
detail: { subgraph, closingGraph: graph, fromNode },
|
||||
cancelable: true
|
||||
}
|
||||
const mayContinue = this.canvas.dispatchEvent(
|
||||
@@ -2792,7 +2792,7 @@ export class LGraphCanvas
|
||||
if (pos[1] < 0 && !inCollapse) {
|
||||
node.onNodeTitleDblClick?.(e, pos, this)
|
||||
} else if (node instanceof SubgraphNode) {
|
||||
this.openSubgraph(node.subgraph)
|
||||
this.openSubgraph(node.subgraph, node)
|
||||
}
|
||||
|
||||
node.onDblClick?.(e, pos, this)
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { LGraphGroup } from '@/lib/litegraph/src/LGraphGroup'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type { ConnectingLink } from '@/lib/litegraph/src/interfaces'
|
||||
import type { Subgraph } from '@/lib/litegraph/src/subgraph/Subgraph'
|
||||
import type { SubgraphNode } from '@/lib/litegraph/src/subgraph/SubgraphNode'
|
||||
import type { CanvasPointerEvent } from '@/lib/litegraph/src/types/events'
|
||||
|
||||
export interface LGraphCanvasEventMap {
|
||||
@@ -14,6 +15,11 @@ export interface LGraphCanvasEventMap {
|
||||
/** The old active graph, or `null` if there was no active graph. */
|
||||
oldGraph: LGraph | Subgraph | null | undefined
|
||||
}
|
||||
'subgraph-opened': {
|
||||
subgraph: Subgraph
|
||||
closingGraph: LGraph
|
||||
fromNode: SubgraphNode
|
||||
}
|
||||
|
||||
'litegraph:canvas':
|
||||
| { subType: 'before-change' | 'after-change' }
|
||||
|
||||
@@ -164,7 +164,7 @@ export class SubgraphNode extends LGraphNode implements BaseLGraph {
|
||||
canvas: LGraphCanvas
|
||||
): void {
|
||||
if (button.name === 'enter_subgraph') {
|
||||
canvas.openSubgraph(this.subgraph)
|
||||
canvas.openSubgraph(this.subgraph, this)
|
||||
} else {
|
||||
super.onTitleButtonClick(button, canvas)
|
||||
}
|
||||
|
||||
@@ -297,6 +297,12 @@ export interface IBaseWidget<
|
||||
|
||||
hidden?: boolean
|
||||
advanced?: boolean
|
||||
/**
|
||||
* Set if the node is displayed on the parent subgraphNode
|
||||
* Promoted widgets have a green border
|
||||
* @readonly [Computed] This property is computed on graph change
|
||||
*/
|
||||
promoted?: boolean
|
||||
|
||||
tooltip?: string
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ import { getFromIsobmffFile } from '@/scripts/metadata/isobmff'
|
||||
import { getMp3Metadata } from '@/scripts/metadata/mp3'
|
||||
import { getOggMetadata } from '@/scripts/metadata/ogg'
|
||||
import { getSvgMetadata } from '@/scripts/metadata/svg'
|
||||
import { registerProxyWidgets } from '@/scripts/proxyWidget'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { useExtensionService } from '@/services/extensionService'
|
||||
import { useLitegraphService } from '@/services/litegraphService'
|
||||
@@ -862,6 +863,7 @@ export class ComfyApp {
|
||||
}
|
||||
}
|
||||
)
|
||||
registerProxyWidgets(this.canvas)
|
||||
|
||||
this.graph.start()
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { useNodeImage } from '@/composables/node/useNodeImage'
|
||||
import type { LGraph, LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import type {
|
||||
LGraph,
|
||||
LGraphCanvas,
|
||||
LGraphNode
|
||||
} from '@/lib/litegraph/src/litegraph'
|
||||
import { SubgraphNode } from '@/lib/litegraph/src/subgraph/SubgraphNode'
|
||||
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets.ts'
|
||||
import { disconnectedWidget } from '@/lib/litegraph/src/widgets/DisconnectedWidget'
|
||||
@@ -10,54 +14,67 @@ import { useCanvasStore } from '@/stores/graphStore'
|
||||
import { useNodeOutputStore } from '@/stores/imagePreviewStore'
|
||||
import { getNodeByExecutionId } from '@/utils/graphTraversalUtil'
|
||||
|
||||
const originalOnConfigure = SubgraphNode.prototype.onConfigure
|
||||
SubgraphNode.prototype.onConfigure = function (serialisedNode) {
|
||||
if (!this.isSubgraphNode())
|
||||
throw new Error("Can't add proxyWidgets to non-subgraphNode")
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
const subgraphNode = this
|
||||
//Must give value to proxyWidgets prior to defining or it won't serialize
|
||||
subgraphNode.properties.proxyWidgets ??= '[]'
|
||||
let proxyWidgets = subgraphNode.properties.proxyWidgets
|
||||
|
||||
originalOnConfigure?.bind(this)?.(serialisedNode)
|
||||
|
||||
Object.defineProperty(subgraphNode.properties, 'proxyWidgets', {
|
||||
get: () => {
|
||||
return proxyWidgets
|
||||
},
|
||||
set: (property: string) => {
|
||||
const parsed = parseProxyWidgets(property)
|
||||
const { widgetStates } = useDomWidgetStore()
|
||||
for (const w of subgraphNode.widgets.filter((w) => isProxyWidget(w))) {
|
||||
if (w instanceof DOMWidgetImpl && widgetStates.has(w.id)) {
|
||||
const widgetState = widgetStates.get(w.id)
|
||||
if (!widgetState) continue
|
||||
widgetState.active = false
|
||||
}
|
||||
export function registerProxyWidgets(canvas: LGraphCanvas) {
|
||||
//NOTE: canvasStore hasn't been initialized yet
|
||||
canvas.canvas.addEventListener<'subgraph-opened'>('subgraph-opened', (e) => {
|
||||
const { subgraph, fromNode } = e.detail
|
||||
const pw = parseProxyWidgets(fromNode.properties.proxyWidgets)
|
||||
for (const node of subgraph.nodes) {
|
||||
for (const widget of node.widgets ?? []) {
|
||||
widget.promoted = pw.some(([n, w]) => node.id == n && widget.name == w)
|
||||
}
|
||||
//NOTE: This does not apply to pushed entries, only initial load
|
||||
subgraphNode.widgets = subgraphNode.widgets.filter(
|
||||
(w) => !isProxyWidget(w)
|
||||
)
|
||||
for (const [nodeId, widgetName] of parsed) {
|
||||
const w = addProxyWidget(subgraphNode, `${nodeId}`, widgetName)
|
||||
if (w instanceof DOMWidgetImpl) {
|
||||
const widgetState = widgetStates.get(w.id)
|
||||
if (!widgetState) continue
|
||||
widgetState.active = true
|
||||
widgetState.widget = w
|
||||
}
|
||||
}
|
||||
proxyWidgets = property
|
||||
canvasStore.canvas?.setDirty(true, true)
|
||||
subgraphNode._setConcreteSlots()
|
||||
subgraphNode.arrange()
|
||||
}
|
||||
})
|
||||
subgraphNode.properties.proxyWidgets = proxyWidgets
|
||||
const originalOnConfigure = SubgraphNode.prototype.onConfigure
|
||||
SubgraphNode.prototype.onConfigure = function onConfigure(serialisedNode) {
|
||||
if (!this.isSubgraphNode())
|
||||
throw new Error("Can't add proxyWidgets to non-subgraphNode")
|
||||
|
||||
const canvasStore = useCanvasStore()
|
||||
const subgraphNode = this
|
||||
//Must give value to proxyWidgets prior to defining or it won't serialize
|
||||
subgraphNode.properties.proxyWidgets ??= '[]'
|
||||
let proxyWidgets = subgraphNode.properties.proxyWidgets
|
||||
|
||||
originalOnConfigure?.bind(this)?.(serialisedNode)
|
||||
|
||||
Object.defineProperty(subgraphNode.properties, 'proxyWidgets', {
|
||||
get: () => {
|
||||
return proxyWidgets
|
||||
},
|
||||
set: (property: string) => {
|
||||
const parsed = parseProxyWidgets(property)
|
||||
const { widgetStates } = useDomWidgetStore()
|
||||
for (const w of subgraphNode.widgets.filter((w) => isProxyWidget(w))) {
|
||||
if (w instanceof DOMWidgetImpl && widgetStates.has(w.id)) {
|
||||
const widgetState = widgetStates.get(w.id)
|
||||
if (!widgetState) continue
|
||||
widgetState.active = false
|
||||
}
|
||||
}
|
||||
//NOTE: This does not apply to pushed entries, only initial load
|
||||
subgraphNode.widgets = subgraphNode.widgets.filter(
|
||||
(w) => !isProxyWidget(w)
|
||||
)
|
||||
for (const [nodeId, widgetName] of parsed) {
|
||||
const w = addProxyWidget(subgraphNode, `${nodeId}`, widgetName)
|
||||
if (w instanceof DOMWidgetImpl) {
|
||||
const widgetState = widgetStates.get(w.id)
|
||||
if (!widgetState) continue
|
||||
widgetState.active = true
|
||||
widgetState.widget = w
|
||||
}
|
||||
}
|
||||
proxyWidgets = property
|
||||
canvasStore.canvas?.setDirty(true, true)
|
||||
subgraphNode._setConcreteSlots()
|
||||
subgraphNode.arrange()
|
||||
}
|
||||
})
|
||||
subgraphNode.properties.proxyWidgets = proxyWidgets
|
||||
}
|
||||
}
|
||||
|
||||
type Overlay = Partial<IBaseWidget> & {
|
||||
graph: LGraph
|
||||
nodeId: string
|
||||
@@ -89,7 +106,8 @@ function addProxyWidget(
|
||||
computedHeight: undefined,
|
||||
afterQueued: undefined,
|
||||
onRemove: undefined,
|
||||
node: subgraphNode
|
||||
node: subgraphNode,
|
||||
promoted: undefined
|
||||
}
|
||||
return addProxyFromOverlay(subgraphNode, overlay)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import { useSettingStore } from '@/stores/settingStore'
|
||||
import type { ComfyApp } from './app'
|
||||
import './domWidget'
|
||||
import './errorNodeWidgets'
|
||||
import './proxyWidget'
|
||||
|
||||
export type ComfyWidgetConstructorV2 = (
|
||||
node: LGraphNode,
|
||||
|
||||
Reference in New Issue
Block a user