Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/renderer/extensions/vueNodes/layout/useNodeDrag.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { storeToRefs } from 'pinia'
import { toValue } from 'vue'

import type { LGraphGroup } from '@/lib/litegraph/src/LGraphGroup'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
Expand All @@ -13,13 +14,14 @@ import type {
import { useNodeSnap } from '@/renderer/extensions/vueNodes/composables/useNodeSnap'
import { useShiftKeySync } from '@/renderer/extensions/vueNodes/composables/useShiftKeySync'
import { useTransformState } from '@/renderer/core/layout/transform/useTransformState'
import { isLGraphGroup } from '@/utils/litegraphUtil'
import { createSharedComposable } from '@vueuse/core'

export const useNodeDrag = createSharedComposable(useNodeDragIndividual)

function useNodeDragIndividual() {
const mutations = useLayoutMutations()
const { selectedNodeIds } = storeToRefs(useCanvasStore())
const { selectedNodeIds, selectedItems } = storeToRefs(useCanvasStore())

// Get transform utilities from TransformPane if available
const transformState = useTransformState()
Expand All @@ -37,6 +39,10 @@ function useNodeDragIndividual() {
let rafId: number | null = null
let stopShiftSync: (() => void) | null = null

// For groups: track the last applied canvas delta to compute frame delta
let lastCanvasDelta: Point | null = null
let selectedGroups: LGraphGroup[] | null = null

function startDrag(event: PointerEvent, nodeId: NodeId) {
const layout = toValue(layoutStore.getNodeLayoutRef(nodeId))
if (!layout) return
Expand Down Expand Up @@ -67,6 +73,10 @@ function useNodeDragIndividual() {
otherSelectedNodesStartPositions = null
}

// Capture selected groups (filter from selectedItems which only contains selected items)
selectedGroups = toValue(selectedItems).filter(isLGraphGroup)
lastCanvasDelta = { x: 0, y: 0 }

mutations.setSource(LayoutSource.Vue)
}

Expand Down Expand Up @@ -127,6 +137,21 @@ function useNodeDragIndividual() {
mutations.moveNode(otherNodeId, newOtherPosition)
}
}

// Move selected groups using frame delta (difference from last frame)
// This matches LiteGraph's behavior which uses delta-based movement
if (selectedGroups && selectedGroups.length > 0 && lastCanvasDelta) {
const frameDelta = {
x: canvasDelta.x - lastCanvasDelta.x,
y: canvasDelta.y - lastCanvasDelta.y
}

for (const group of selectedGroups) {
group.move(frameDelta.x, frameDelta.y, true)
}
}

lastCanvasDelta = canvasDelta
})
}

Expand Down Expand Up @@ -195,6 +220,8 @@ function useNodeDragIndividual() {
dragStartPos = null
dragStartMouse = null
otherSelectedNodesStartPositions = null
selectedGroups = null
lastCanvasDelta = null
Comment on lines +223 to +224
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

cat -n src/renderer/extensions/vueNodes/layout/useNodeDrag.ts | sed -n '150,230p'

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 3163


🏁 Script executed:

rg -n 'selectedGroups' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts -B 3 -A 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1411


🏁 Script executed:

rg -n 'class.*Group|interface.*Group|type.*Group' src/renderer/extensions/vueNodes/layout/ --type=ts | head -20

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 193


🏁 Script executed:

rg -n 'group\.move\|group\.position' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts -B 2 -A 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg -n 'applySnapToPosition|shouldSnap|snapToGrid' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts -B 2 -A 2

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 951


🏁 Script executed:

rg -n 'snap.*grid|grid.*size|GRID' src/renderer/extensions/vueNodes/ --type=ts -i | head -15

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1989


🏁 Script executed:

find . -name 'LGraphGroup*' -o -name '*litegraph*' | grep -E '\.(ts|js)$' | head -10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 491


🏁 Script executed:

cat src/lib/litegraph/src/LGraphGroup.ts | head -100

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2631


🏁 Script executed:

rg -n 'snapToGrid' src/lib/litegraph/src/litegraph.ts -B 3 -A 10 | head -50

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg -n 'snapToGrid' src/renderer/extensions/vueNodes/ --type=ts -B 2 -A 5

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 919


🏁 Script executed:

rg -n 'move\(' src/lib/litegraph/src/LGraphGroup.ts -B 3 -A 10

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 670


🏁 Script executed:

rg -n 'snapToGrid|snap.*[Gg]roup' src/lib/litegraph/src/ --type=ts -B 2 -A 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 9444


🏁 Script executed:

cat src/tests-ui/tests/litegraph/core/LGraphGroup.test.ts 2>/dev/null | head -150

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg -n 'getAllNestedItems' src/lib/litegraph/src/ --type=ts -B 2 -A 8

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 4096


🏁 Script executed:

sed -n '1151,1160p' src/lib/litegraph/src/LGraph.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 339


🏁 Script executed:

rg -n 'function getAllNestedItems|export.*getAllNestedItems' src/lib/litegraph/src/ --type=ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 150


🏁 Script executed:

rg -n 'addRecursively' src/lib/litegraph/src/utils/collections.ts -B 3 -A 15

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1001


🏁 Script executed:

cat src/lib/litegraph/src/utils/collections.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 3221


🏁 Script executed:

cat src/tests-ui/tests/litegraph/core/LGraphGroup.test.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 155


🏁 Script executed:

rg -n 'snapToGrid|snap.*grid' src/tests-ui/tests/litegraph/ --type=ts -B 2 -A 4

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 139


🏁 Script executed:

rg -n 'LGraph.*snapToGrid|graph\.snapToGrid' src/renderer/extensions/vueNodes/ --type=ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

sed -n '1,50p' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 2104


🏁 Script executed:

rg -n 'LGraph\|graph\.' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts | head -20

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg -n 'snap.*comment|TODO|FIXME|XXX' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 52


🏁 Script executed:

rg -n 'group.move|applySnapToPosition' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts -B 3 -A 3

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 1204


🏁 Script executed:

sed -n '140,160p' src/renderer/extensions/vueNodes/layout/useNodeDrag.ts

Repository: Comfy-Org/ComfyUI_frontend

Length of output: 794


Groups are not snapped to grid at drag end, unlike nodes.

While nodes receive snap-to-grid treatment in endDrag (lines 160-217), selected groups are only moved during drag via group.move() and are never snapped at drag completion. This creates an asymmetry in behavior. Both LGraphGroup and LGraphNode implement the snapToGrid interface, and the applySnapToPosition utility is available, so groups should also be snapped when shouldSnap(event) is true. Currently, the snap logic only executes when nodeId is present, which excludes the group snapping path.


// Stop tracking shift key state
stopShiftSync?.()
Expand Down
Loading