diff --git a/browser_tests/tests/viewport.spec.ts-snapshots/viewport-fits-when-saved-offscreen-chromium-linux.png b/browser_tests/tests/viewport.spec.ts-snapshots/viewport-fits-when-saved-offscreen-chromium-linux.png index f6ac2afd0..cbbdab631 100644 Binary files a/browser_tests/tests/viewport.spec.ts-snapshots/viewport-fits-when-saved-offscreen-chromium-linux.png and b/browser_tests/tests/viewport.spec.ts-snapshots/viewport-fits-when-saved-offscreen-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png index 6f9da202b..63a7665fe 100644 Binary files a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png and b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-create-group-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png index 503618abd..31502cf37 100644 Binary files a/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png and b/browser_tests/tests/vueNodes/groups/groups.spec.ts-snapshots/vue-groups-fit-to-contents-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png b/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png index 6a98eafc4..f965a5bbf 100644 Binary files a/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png and b/browser_tests/tests/vueNodes/interactions/canvas/pan.spec.ts-snapshots/vue-nodes-paned-with-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png index 47dfca47b..584e0c3b3 100644 Binary files a/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/canvas/zoom.spec.ts-snapshots/zoomed-in-ctrl-shift-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png index 3374a86a4..483251f59 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-dragging-link-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png index 2cf7fe9de..21afb2c03 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-ctrl-alt-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png index 3cde4d5a8..6b236bd60 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-input-drag-reuses-origin-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png index 0cccea1b4..eb05d40fc 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-input-drag-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png index d70462889..4dfd064c9 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-reroute-output-shift-drag-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png index 51e805054..9c5874347 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-shift-output-multi-link-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png index e0f85f133..47282cee6 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-node-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png index 4981d113c..d3ad77b7b 100644 Binary files a/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png and b/browser_tests/tests/vueNodes/interactions/links/linkInteraction.spec.ts-snapshots/vue-node-snap-to-slot-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png index bbf212657..d7508564c 100644 Binary files a/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png and b/browser_tests/tests/vueNodes/interactions/node/move.spec.ts-snapshots/vue-node-moved-node-touch-mobile-chrome-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png index ec5c0a6a3..62c59f12c 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-dark-all-colors-chromium-linux.png differ diff --git a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png index 514d42eec..cf9fbba14 100644 Binary files a/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png and b/browser_tests/tests/vueNodes/nodeStates/colors.spec.ts-snapshots/vue-node-custom-colors-light-all-colors-chromium-linux.png differ diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 27c038076..aad7d6f24 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -76,6 +76,13 @@ /> + + @@ -111,6 +118,7 @@ import BottomPanel from '@/components/bottomPanel/BottomPanel.vue' import ExtensionSlot from '@/components/common/ExtensionSlot.vue' import DomWidgets from '@/components/graph/DomWidgets.vue' import GraphCanvasMenu from '@/components/graph/GraphCanvasMenu.vue' +import LinkOverlayCanvas from '@/components/graph/LinkOverlayCanvas.vue' import NodeTooltip from '@/components/graph/NodeTooltip.vue' import SelectionToolbox from '@/components/graph/SelectionToolbox.vue' import TitleEditor from '@/components/graph/TitleEditor.vue' @@ -241,6 +249,18 @@ const allNodes = computed((): VueNodeData[] => Array.from(vueNodeLifecycle.nodeManager.value?.vueNodeData?.values() ?? []) ) +function onLinkOverlayReady(el: HTMLCanvasElement) { + if (!canvasStore.canvas) return + canvasStore.canvas.overlayCanvas = el + canvasStore.canvas.overlayCtx = el.getContext('2d') +} + +function onLinkOverlayDispose() { + if (!canvasStore.canvas) return + canvasStore.canvas.overlayCanvas = null + canvasStore.canvas.overlayCtx = null +} + watchEffect(() => { LiteGraph.nodeOpacity = settingStore.get('Comfy.Node.Opacity') }) diff --git a/src/components/graph/LinkOverlayCanvas.vue b/src/components/graph/LinkOverlayCanvas.vue new file mode 100644 index 000000000..a29726b25 --- /dev/null +++ b/src/components/graph/LinkOverlayCanvas.vue @@ -0,0 +1,43 @@ + + + diff --git a/src/lib/litegraph/src/LGraphCanvas.ts b/src/lib/litegraph/src/LGraphCanvas.ts index e131d877b..130a27809 100644 --- a/src/lib/litegraph/src/LGraphCanvas.ts +++ b/src/lib/litegraph/src/LGraphCanvas.ts @@ -688,6 +688,8 @@ export class LGraphCanvas implements CustomEventDispatcher canvas: HTMLCanvasElement & ICustomEventTarget bgcanvas: HTMLCanvasElement + overlayCanvas: HTMLCanvasElement | null = null + overlayCtx: CanvasRenderingContext2D | null = null ctx: CanvasRenderingContext2D _events_binded?: boolean _mousedown_callback?(e: PointerEvent): void @@ -4849,7 +4851,7 @@ export class LGraphCanvas implements CustomEventDispatcher drawFrontCanvas(): void { this.dirty_canvas = false - const { ctx, canvas, graph, linkConnector } = this + const { ctx, canvas, graph } = this // @ts-expect-error start2D method not in standard CanvasRenderingContext2D if (ctx.start2D && !this.viewport) { @@ -4949,78 +4951,14 @@ export class LGraphCanvas implements CustomEventDispatcher this.drawConnections(ctx) } - if (linkConnector.isConnecting) { - // current connection (the one being dragged by the mouse) - const { renderLinks } = linkConnector - const highlightPos = this._getHighlightPosition() - ctx.lineWidth = this.connections_width - - for (const renderLink of renderLinks) { - const { - fromSlot, - fromPos: pos, - fromDirection, - dragDirection - } = renderLink - const connShape = fromSlot.shape - const connType = fromSlot.type - - const colour = resolveConnectingLinkColor(connType) - - // the connection being dragged by the mouse - if (this.linkRenderer) { - this.linkRenderer.renderDraggingLink( - ctx, - pos, - highlightPos, - colour, - fromDirection, - dragDirection, - { - ...this.buildLinkRenderContext(), - linkMarkerShape: LinkMarkerShape.None - } - ) - } - - ctx.fillStyle = colour - ctx.beginPath() - if (connType === LiteGraph.EVENT || connShape === RenderShape.BOX) { - ctx.rect(pos[0] - 6 + 0.5, pos[1] - 5 + 0.5, 14, 10) - ctx.rect( - highlightPos[0] - 6 + 0.5, - highlightPos[1] - 5 + 0.5, - 14, - 10 - ) - } else if (connShape === RenderShape.ARROW) { - ctx.moveTo(pos[0] + 8, pos[1] + 0.5) - ctx.lineTo(pos[0] - 4, pos[1] + 6 + 0.5) - ctx.lineTo(pos[0] - 4, pos[1] - 6 + 0.5) - ctx.closePath() - } else { - ctx.arc(pos[0], pos[1], 4, 0, Math.PI * 2) - ctx.arc(highlightPos[0], highlightPos[1], 4, 0, Math.PI * 2) - } - ctx.fill() - } - - // Gradient half-border over target node - this._renderSnapHighlight(ctx, highlightPos) - } - - // on top of link center - if ( - !this.isDragging && - this.over_link_center && - this.render_link_tooltip - ) { - this.drawLinkTooltip(ctx, this.over_link_center) + if (!LiteGraph.vueNodesMode || !this.overlayCtx) { + this._drawConnectingLinks(ctx) } else { - this.onDrawLinkTooltip?.(ctx, null) + this._drawOverlayLinks() } - // custom info + this._drawLinkTooltip(ctx) + this.onDrawForeground?.(ctx, this.visible_area) ctx.restore() @@ -5031,9 +4969,7 @@ export class LGraphCanvas implements CustomEventDispatcher if (area) ctx.restore() } - /** @returns If the pointer is over a link centre marker, the link segment it belongs to. Otherwise, `undefined`. */ private _getLinkCentreOnPos(e: CanvasPointerEvent): LinkSegment | undefined { - // Skip hit detection if center markers are disabled if (this.linkMarkerShape === LinkMarkerShape.None) { return undefined } @@ -5050,6 +4986,90 @@ export class LGraphCanvas implements CustomEventDispatcher } } + private _drawConnectingLinks(ctx: CanvasRenderingContext2D): void { + const { linkConnector } = this + if (!linkConnector.isConnecting) return + + const { renderLinks } = linkConnector + const highlightPos = this._getHighlightPosition() + ctx.lineWidth = this.connections_width + + for (const renderLink of renderLinks) { + const { + fromSlot, + fromPos: pos, + fromDirection, + dragDirection + } = renderLink + const connShape = fromSlot.shape + const connType = fromSlot.type + + const colour = resolveConnectingLinkColor(connType) + + if (this.linkRenderer) { + this.linkRenderer.renderDraggingLink( + ctx, + pos, + highlightPos, + colour, + fromDirection, + dragDirection, + { + ...this.buildLinkRenderContext(), + linkMarkerShape: LinkMarkerShape.None + } + ) + } + + ctx.fillStyle = colour + ctx.beginPath() + if (connType === LiteGraph.EVENT || connShape === RenderShape.BOX) { + ctx.rect(pos[0] - 6 + 0.5, pos[1] - 5 + 0.5, 14, 10) + ctx.rect(highlightPos[0] - 6 + 0.5, highlightPos[1] - 5 + 0.5, 14, 10) + } else if (connShape === RenderShape.ARROW) { + ctx.moveTo(pos[0] + 8, pos[1] + 0.5) + ctx.lineTo(pos[0] - 4, pos[1] + 6 + 0.5) + ctx.lineTo(pos[0] - 4, pos[1] - 6 + 0.5) + ctx.closePath() + } else { + ctx.arc(pos[0], pos[1], 4, 0, Math.PI * 2) + ctx.arc(highlightPos[0], highlightPos[1], 4, 0, Math.PI * 2) + } + ctx.fill() + } + + this._renderSnapHighlight(ctx, highlightPos) + } + + private _drawLinkTooltip(ctx: CanvasRenderingContext2D): void { + if (!this.isDragging && this.over_link_center && this.render_link_tooltip) { + this.drawLinkTooltip(ctx, this.over_link_center) + } else { + this.onDrawLinkTooltip?.(ctx, null) + } + } + + private _drawOverlayLinks(): void { + const octx = this.overlayCtx + const overlayCanvas = this.overlayCanvas + if (!octx || !overlayCanvas) return + + octx.clearRect(0, 0, overlayCanvas.width, overlayCanvas.height) + + if (!this.linkConnector.isConnecting) return + + octx.save() + + const scale = window.devicePixelRatio + octx.setTransform(scale, 0, 0, scale, 0, 0) + + this.ds.toCanvasContext(octx) + + this._drawConnectingLinks(octx) + + octx.restore() + } + /** Get the target snap / highlight point in graph space */ private _getHighlightPosition(): Readonly { return LiteGraph.snaps_for_comfy