diff --git a/src/lib/litegraph/src/LGraph.ts b/src/lib/litegraph/src/LGraph.ts index b3ad35c99..32494c615 100644 --- a/src/lib/litegraph/src/LGraph.ts +++ b/src/lib/litegraph/src/LGraph.ts @@ -1522,6 +1522,22 @@ export class LGraph } { if (items.size === 0) throw new Error('Cannot convert to subgraph: nothing to convert') + + // Record state before conversion for proper undo support + this.beforeChange() + + try { + return this._convertToSubgraphImpl(items) + } finally { + // Mark state change complete for proper undo support + this.afterChange() + } + } + + private _convertToSubgraphImpl(items: Set): { + subgraph: Subgraph + node: SubgraphNode + } { const { state, revision, config } = this const firstChild = [...items][0] if (items.size === 1 && firstChild instanceof LGraphGroup) { @@ -1728,6 +1744,7 @@ export class LGraph subgraphNode._setConcreteSlots() subgraphNode.arrange() + this.canvasAction((c) => c.canvas.dispatchEvent( new CustomEvent('subgraph-converted', { @@ -1746,9 +1763,23 @@ export class LGraph if (!(subgraphNode instanceof SubgraphNode)) throw new Error('Can only unpack Subgraph Nodes') + // Record state before unpacking for proper undo support + this.beforeChange() + + try { + this._unpackSubgraphImpl(subgraphNode, options) + } finally { + // Mark state change complete for proper undo support + this.afterChange() + } + } + + private _unpackSubgraphImpl( + subgraphNode: SubgraphNode, + options?: { skipMissingNodes?: boolean } + ) { const skipMissingNodes = options?.skipMissingNodes ?? false - this.beforeChange() //NOTE: Create bounds can not be called on positionables directly as the subgraph is not being displayed and boundingRect is not initialized. //NOTE: NODE_TITLE_HEIGHT is explicitly excluded here const positionables = [ @@ -2019,7 +2050,6 @@ export class LGraph } this.canvasAction((c) => c.selectItems(toSelect)) - this.afterChange() } /**