diff --git a/src/core/graph/subgraph/proxyWidgetUtils.ts b/src/core/graph/subgraph/proxyWidgetUtils.ts index 8274182b5..9d12513b2 100644 --- a/src/core/graph/subgraph/proxyWidgetUtils.ts +++ b/src/core/graph/subgraph/proxyWidgetUtils.ts @@ -1,4 +1,7 @@ -import type { LGraphNode } from '@/lib/litegraph/src/litegraph' +import type { + IContextMenuValue, + 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 { parseProxyWidgets } from '@/schemas/proxyWidget' @@ -15,18 +18,75 @@ function getProxyWidgets(node: SubgraphNode) { /** * Enables display of a widget on the parent subgraphNode - * @param {{IBaseWidget}} widget - The widget to be promoted - * @param {{LGraphNode}} node - the node which owns the widget + * @param {IBaseWidget} widget - The widget to be promoted + * @param {LGraphNode} node - the node which owns the widget */ -export function promoteWidget(widget: IBaseWidget, node: LGraphNode) { +function promoteWidget( + widget: IBaseWidget, + node: LGraphNode, + parents: SubgraphNode[] +) { + for (const parent of parents) pushWidgets(parent, [`${node.id}`, widget.name]) + widget.promoted = true +} + +function demoteWidget( + widget: IBaseWidget, + node: LGraphNode, + parents: SubgraphNode[] +) { + for (const parent of parents) { + const pw = getProxyWidgets(parent).filter( + ([id, name]) => node.id != id || widget.name !== name + ) + parent.properties.proxyWidgets = JSON.stringify(pw) + } + widget.promoted = false +} + +function getParentNodes(): SubgraphNode[] { + //NOTE: support for determining parents of a subgraph is limited + //This function will require rework to properly support linked subgraphs + //Either by including actual parents in the navigation stack, + //or by adding a new event for parent listeners to collect from const { navigationStack } = useSubgraphNavigationStore() const subgraph = navigationStack.at(-1) if (!subgraph) throw new Error("Can't promote widget when not in subgraph") + const validNodes = [] const parentGraph = navigationStack.at(-2) ?? subgraph.rootGraph for (const onode of parentGraph.nodes) { if (onode.type === subgraph.id && onode.isSubgraphNode()) { - pushWidgets(onode, [`${node.id}`, widget.name]) + validNodes.push(onode) } } - widget.promoted = true + return validNodes +} + +export function addWidgetPromotionOptions( + options: (IContextMenuValue | null)[], + widget: IBaseWidget, + node: LGraphNode +) { + const parents = getParentNodes() + const promotableParents = parents.filter( + (s) => + !getProxyWidgets(s).some( + ([id, name]) => node.id == id && widget.name === name + ) + ) + if (promotableParents.length > 0) + options.unshift({ + content: `Promote Widget: ${widget.label ?? widget.name}`, + callback: () => { + promoteWidget(widget, node, promotableParents) + } + }) + else { + options.unshift({ + content: `Un-Promote Widget: ${widget.label ?? widget.name}`, + callback: () => { + demoteWidget(widget, node, parents) + } + }) + } } diff --git a/src/services/litegraphService.ts b/src/services/litegraphService.ts index f01739c78..8658b472b 100644 --- a/src/services/litegraphService.ts +++ b/src/services/litegraphService.ts @@ -4,7 +4,7 @@ import { useSelectedLiteGraphItems } from '@/composables/canvas/useSelectedLiteG import { useNodeAnimatedImage } from '@/composables/node/useNodeAnimatedImage' import { useNodeCanvasImagePreview } from '@/composables/node/useNodeCanvasImagePreview' import { useNodeImage, useNodeVideo } from '@/composables/node/useNodeImage' -import { promoteWidget } from '@/core/graph/subgraph/proxyWidgetUtils' +import { addWidgetPromotionOptions } from '@/core/graph/subgraph/proxyWidgetUtils' import { st, t } from '@/i18n' import { type IContextMenuValue, @@ -837,12 +837,7 @@ export const useLitegraphService = () => { const [x, y] = canvas.canvas_mouse const overWidget = this.getWidgetOnPos(x, y, true) if (overWidget) { - options.unshift({ - content: `Promote Widget: ${overWidget.label ?? overWidget.name}`, - callback: () => { - promoteWidget(overWidget, this) - } - }) + addWidgetPromotionOptions(options, overWidget, this) } }