Skip to content
Merged
10 changes: 9 additions & 1 deletion src/lib/litegraph/src/LGraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2542,7 +2542,15 @@ export class LGraph

// configure nodes afterwards so they can reach each other
for (const [id, nodeData] of nodeDataMap) {
this.getNodeById(id)?.configure(nodeData)
const node = this.getNodeById(id)
node?.configure(nodeData)

if (LiteGraph.alwaysSnapToGrid && node) {
const snapTo = this.getSnapToGridSize()
if (node.snapToGrid(snapTo)) {
node.pos = [node.pos[0], node.pos[1]]
Comment thread
christian-byrne marked this conversation as resolved.
}
}
Comment thread
christian-byrne marked this conversation as resolved.
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/lib/litegraph/src/LGraphCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2945,6 +2945,9 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>

// Enforce minimum size
const min = node.computeSize()
if (this._snapToGrid) {
snapPoint(min, this._snapToGrid, 'ceil')
Comment thread
christian-byrne marked this conversation as resolved.
}
if (newBounds.width < min[0]) {
// If resizing from left, adjust position to maintain right edge
if (resizeDirection.includes('W')) {
Expand Down
10 changes: 7 additions & 3 deletions src/lib/litegraph/src/measure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,15 @@ export function createBounds(
* @returns `true` if snapTo is truthy, otherwise `false`
* @remarks `NaN` propagates through this function and does not affect return value.
*/
export function snapPoint(pos: Point | Rect, snapTo: number): boolean {
export function snapPoint(
pos: Point | Rect,
snapTo: number,
method: 'round' | 'ceil' | 'floor' = 'round'
): boolean {
Comment thread
christian-byrne marked this conversation as resolved.
if (!snapTo) return false

pos[0] = snapTo * Math.round(pos[0] / snapTo)
pos[1] = snapTo * Math.round(pos[1] / snapTo)
pos[0] = snapTo * Math[method](pos[0] / snapTo)
pos[1] = snapTo * Math[method](pos[1] / snapTo)
return true
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function useNodeSnap() {
if (!gridSizeValue) return { ...size }

const sizeArray: [number, number] = [size.width, size.height]
if (snapPoint(sizeArray, gridSizeValue)) {
if (snapPoint(sizeArray, gridSizeValue, 'ceil')) {
return { width: sizeArray[0], height: sizeArray[1] }
}
return { ...size }
Expand Down
88 changes: 72 additions & 16 deletions src/renderer/extensions/vueNodes/layout/ensureCorrectLayoutScale.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useVueFeatureFlags } from '@/composables/useVueFeatureFlags'
import type { LGraph, RendererType } from '@/lib/litegraph/src/LGraph'
import { createBounds } from '@/lib/litegraph/src/measure'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import { createBounds, snapPoint } from '@/lib/litegraph/src/measure'
import { useSettingStore } from '@/platform/settings/settingStore'
import { layoutStore } from '@/renderer/core/layout/store/layoutStore'
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
Expand All @@ -16,7 +17,8 @@ export function ensureCorrectLayoutScale(
renderer: RendererType = 'LG',
targetGraph?: LGraph
) {
const autoScaleLayoutSetting = useSettingStore().get(
const settingStore = useSettingStore()
const autoScaleLayoutSetting = settingStore.get(
'Comfy.VueNodes.AutoScaleLayout'
)

Expand All @@ -38,6 +40,10 @@ export function ensureCorrectLayoutScale(
return
}

const alwaysSnapToGrid = settingStore.get('pysssss.SnapToGrid')
const snapSize =
settingStore.get('Comfy.SnapToGrid.GridSize') || LiteGraph.CANVAS_GRID_SIZE
Comment thread
christian-byrne marked this conversation as resolved.
Outdated

const lgBounds = createBounds(graph.nodes)

if (!lgBounds) return
Expand All @@ -52,6 +58,15 @@ export function ensureCorrectLayoutScale(

const onActiveGraph = !targetGraph || targetGraph === canvas?.graph

const applySnap = (
pos: [number, number],
method: 'round' | 'ceil' | 'floor' = 'round'
) => {
if (alwaysSnapToGrid) {
snapPoint(pos, snapSize, method)
}
}

//TODO: once we remove the need for LiteGraph.NODE_TITLE_HEIGHT in vue nodes we nned to remove everything here.
for (const node of graph.nodes) {
const lgNode = lgNodesById.get(node.id)
Expand All @@ -62,12 +77,23 @@ export function ensureCorrectLayoutScale(
const relativeX = oldX - originX
const relativeY = oldY - originY

const scaledX = originX + relativeX * scaleFactor
const scaledY = originY + relativeY * scaleFactor
const posTarget: [number, number] = [
originX + relativeX * scaleFactor,
originY + relativeY * scaleFactor
]
applySnap(posTarget)

const scaledX = posTarget[0]
const scaledY = posTarget[1]

const scaledWidth = lgNode.width * scaleFactor
const sizeTarget: [number, number] = [
lgNode.size[0] * scaleFactor,
lgNode.size[1] * scaleFactor
]
applySnap(sizeTarget, 'ceil')

const scaledHeight = lgNode.size[1] * scaleFactor
const scaledWidth = sizeTarget[0]
const scaledHeight = sizeTarget[1]

// Directly update LiteGraph node to ensure immediate consistency
// Dont need to reference vue directly because the pos and dims are already in yjs
Expand Down Expand Up @@ -101,8 +127,14 @@ export function ensureCorrectLayoutScale(
const relativeX = oldX - originX
const relativeY = oldY - originY

const scaledX = originX + relativeX * scaleFactor
const scaledY = originY + relativeY * scaleFactor
const posTarget: [number, number] = [
originX + relativeX * scaleFactor,
originY + relativeY * scaleFactor
]
applySnap(posTarget)

const scaledX = posTarget[0]
const scaledY = posTarget[1]

reroute.pos = [scaledX, scaledY]

Expand All @@ -128,11 +160,23 @@ export function ensureCorrectLayoutScale(
const relativeX = oldX - originX
const relativeY = oldY - originY

const scaledX = originX + relativeX * scaleFactor
const scaledY = originY + relativeY * scaleFactor
const posTarget: [number, number] = [
originX + relativeX * scaleFactor,
originY + relativeY * scaleFactor
]
applySnap(posTarget)

const scaledX = posTarget[0]
const scaledY = posTarget[1]

const scaledWidth = oldWidth * scaleFactor
const scaledHeight = oldHeight * scaleFactor
const sizeTarget: [number, number] = [
oldWidth * scaleFactor,
oldHeight * scaleFactor
]
applySnap(sizeTarget, 'ceil')

const scaledWidth = sizeTarget[0]
const scaledHeight = sizeTarget[1]

ioNode.pos = [scaledX, scaledY]
ioNode.size = [scaledWidth, scaledHeight]
Expand All @@ -146,11 +190,23 @@ export function ensureCorrectLayoutScale(
const relativeX = oldX - originX
const relativeY = oldY - originY

const scaledX = originX + relativeX * scaleFactor
const scaledY = originY + relativeY * scaleFactor
const posTarget: [number, number] = [
originX + relativeX * scaleFactor,
originY + relativeY * scaleFactor
]
applySnap(posTarget)

const scaledX = posTarget[0]
const scaledY = posTarget[1]

const sizeTarget: [number, number] = [
oldWidth * scaleFactor,
oldHeight * scaleFactor
]
applySnap(sizeTarget, 'ceil')

const scaledWidth = oldWidth * scaleFactor
const scaledHeight = oldHeight * scaleFactor
const scaledWidth = sizeTarget[0]
const scaledHeight = sizeTarget[1]

group.pos = [scaledX, scaledY]
group.size = [scaledWidth, scaledHeight]
Expand Down
5 changes: 5 additions & 0 deletions src/scripts/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
LGraphNode,
LiteGraph
} from '@/lib/litegraph/src/litegraph'
import { snapPoint } from '@/lib/litegraph/src/measure'
import type { Vector2 } from '@/lib/litegraph/src/litegraph'
import type { IBaseWidget } from '@/lib/litegraph/src/types/widgets'
import { isCloud } from '@/platform/distribution/types'
Expand Down Expand Up @@ -1343,10 +1344,14 @@ export class ComfyApp {
console.error(error)
return
}
const snapTo = LiteGraph.alwaysSnapToGrid
? this.rootGraph.getSnapToGridSize()
: 0
forEachNode(this.rootGraph, (node) => {
const size = node.computeSize()
size[0] = Math.max(node.size[0], size[0])
size[1] = Math.max(node.size[1], size[1])
snapPoint(size, snapTo, 'ceil')
node.setSize(size)
if (node.widgets) {
// If you break something in the backend and want to patch workflows in the frontend
Expand Down
Loading