mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-05 13:41:59 +00:00
fix: simplify ensureCorrectLayoutScale and fix link sync during Vue node drag (#9680)
## Summary Fix node layout drift from repeated `ensureCorrectLayoutScale` scaling, simplify it to a pure one-time normalizer, and fix links not following Vue nodes during drag. ## Changes - **What**: - `ensureCorrectLayoutScale` simplified to a one-time normalizer: unprojects legacy Vue-scaled coordinates back to canonical LiteGraph coordinates, marks the graph as corrected, and does nothing else. No longer touches the layout store, syncs reroutes, or changes canvas scale. - Removed no-op calls from `useVueNodeLifecycle.ts` (a renderer version string was passed where an `LGraph` was expected). - `layoutStore.finalizeOperation` now calls `notifyChange` synchronously instead of via `setTimeout`. This ensures `useLayoutSync`'s `onChange` callback pushes positions to LiteGraph `node.pos` and calls `canvas.setDirty()` within the same RAF frame as a drag update, fixing links not following Vue nodes during drag. - **Tests**: Added tests for `ensureCorrectLayoutScale` (idempotency, round-trip, unknown-renderer no-op) and `graphRenderTransform` (project/unproject round-trips, anchor caching). ## Review Focus - The `setTimeout(() => this.notifyChange(change), 0)` → `this.notifyChange(change)` change in `layoutStore.ts` is the key fix for the drag-link-sync bug. The listener (`useLayoutSync`) only writes to LiteGraph, not back to the layout store, so synchronous notification is safe. - `ensureCorrectLayoutScale` no longer has any side effects beyond normalizing coordinates and setting `workflowRendererVersion` metadata. --------- Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: jaeone94 <89377375+jaeone94@users.noreply.github.com> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Hunter <huntcsg@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
@@ -9,7 +9,6 @@ import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
|
||||
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
|
||||
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
|
||||
import { useLayoutSync } from '@/renderer/core/layout/sync/useLayoutSync'
|
||||
import { ensureCorrectLayoutScale } from '@/renderer/extensions/vueNodes/layout/ensureCorrectLayoutScale'
|
||||
import { app as comfyApp } from '@/scripts/app'
|
||||
|
||||
function useVueNodeLifecycleIndividual() {
|
||||
@@ -17,7 +16,7 @@ function useVueNodeLifecycleIndividual() {
|
||||
const layoutMutations = useLayoutMutations()
|
||||
const { shouldRenderVueNodes } = useVueFeatureFlags()
|
||||
const nodeManager = shallowRef<GraphNodeManager | null>(null)
|
||||
const { startSync } = useLayoutSync()
|
||||
const { startSync, stopSync } = useLayoutSync()
|
||||
|
||||
const initializeNodeManager = () => {
|
||||
// Use canvas graph if available (handles subgraph contexts), fallback to app graph
|
||||
@@ -55,11 +54,13 @@ function useVueNodeLifecycleIndividual() {
|
||||
)
|
||||
}
|
||||
|
||||
// Initialize layout sync (one-way: Layout Store → LiteGraph)
|
||||
// Start sync AFTER seeding so bootstrap operations don't trigger
|
||||
// the Layout→LiteGraph writeback loop redundantly.
|
||||
startSync(canvasStore.canvas)
|
||||
}
|
||||
|
||||
const disposeNodeManagerAndSyncs = () => {
|
||||
stopSync()
|
||||
if (!nodeManager.value) return
|
||||
|
||||
try {
|
||||
@@ -76,9 +77,6 @@ function useVueNodeLifecycleIndividual() {
|
||||
(enabled) => {
|
||||
if (enabled) {
|
||||
initializeNodeManager()
|
||||
ensureCorrectLayoutScale(
|
||||
comfyApp.canvas?.graph?.extra.workflowRendererVersion
|
||||
)
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
@@ -87,26 +85,17 @@ function useVueNodeLifecycleIndividual() {
|
||||
whenever(
|
||||
() => !shouldRenderVueNodes.value,
|
||||
() => {
|
||||
ensureCorrectLayoutScale(
|
||||
comfyApp.canvas?.graph?.extra.workflowRendererVersion
|
||||
)
|
||||
disposeNodeManagerAndSyncs()
|
||||
comfyApp.canvas?.setDirty(true, true)
|
||||
}
|
||||
)
|
||||
|
||||
// Consolidated watch for slot layout sync management
|
||||
// Clear stale slot layouts when switching modes
|
||||
watch(
|
||||
() => shouldRenderVueNodes.value,
|
||||
(vueMode, oldVueMode) => {
|
||||
const modeChanged = vueMode !== oldVueMode
|
||||
|
||||
// Clear stale slot layouts when switching modes
|
||||
if (modeChanged) {
|
||||
layoutStore.clearAllSlotLayouts()
|
||||
}
|
||||
},
|
||||
{ immediate: true, flush: 'sync' }
|
||||
() => {
|
||||
layoutStore.clearAllSlotLayouts()
|
||||
}
|
||||
)
|
||||
|
||||
// Handle case where Vue nodes are enabled but graph starts empty
|
||||
|
||||
Reference in New Issue
Block a user