Extend core snapToGrid to LiteGraph Groups. (#3393)
Extends the core Comfy.SnapToGrid behavior for nodes to apply to LiteGraph's LGraphGroup with the same behavior. Also, pulls out redundant rounding code into util function.
This commit is contained in:
parent
16a493a190
commit
f6a203951f
|
@ -2,6 +2,13 @@ import { app } from "../../scripts/app.js";
|
||||||
|
|
||||||
// Shift + drag/resize to snap to grid
|
// Shift + drag/resize to snap to grid
|
||||||
|
|
||||||
|
/** Rounds a Vector2 in-place to the current CANVAS_GRID_SIZE. */
|
||||||
|
function roundVectorToGrid(vec) {
|
||||||
|
vec[0] = LiteGraph.CANVAS_GRID_SIZE * Math.round(vec[0] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
vec[1] = LiteGraph.CANVAS_GRID_SIZE * Math.round(vec[1] / LiteGraph.CANVAS_GRID_SIZE);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
app.registerExtension({
|
app.registerExtension({
|
||||||
name: "Comfy.SnapToGrid",
|
name: "Comfy.SnapToGrid",
|
||||||
init() {
|
init() {
|
||||||
|
@ -43,10 +50,7 @@ app.registerExtension({
|
||||||
const onResize = node.onResize;
|
const onResize = node.onResize;
|
||||||
node.onResize = function () {
|
node.onResize = function () {
|
||||||
if (app.shiftDown) {
|
if (app.shiftDown) {
|
||||||
const w = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.size[0] / LiteGraph.CANVAS_GRID_SIZE);
|
roundVectorToGrid(node.size);
|
||||||
const h = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.size[1] / LiteGraph.CANVAS_GRID_SIZE);
|
|
||||||
node.size[0] = w;
|
|
||||||
node.size[1] = h;
|
|
||||||
}
|
}
|
||||||
return onResize?.apply(this, arguments);
|
return onResize?.apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
@ -57,9 +61,7 @@ app.registerExtension({
|
||||||
const origDrawNode = LGraphCanvas.prototype.drawNode;
|
const origDrawNode = LGraphCanvas.prototype.drawNode;
|
||||||
LGraphCanvas.prototype.drawNode = function (node, ctx) {
|
LGraphCanvas.prototype.drawNode = function (node, ctx) {
|
||||||
if (app.shiftDown && this.node_dragged && node.id in this.selected_nodes) {
|
if (app.shiftDown && this.node_dragged && node.id in this.selected_nodes) {
|
||||||
const x = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[0] / LiteGraph.CANVAS_GRID_SIZE);
|
const [x, y] = roundVectorToGrid([...node.pos]);
|
||||||
const y = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[1] / LiteGraph.CANVAS_GRID_SIZE);
|
|
||||||
|
|
||||||
const shiftX = x - node.pos[0];
|
const shiftX = x - node.pos[0];
|
||||||
let shiftY = y - node.pos[1];
|
let shiftY = y - node.pos[1];
|
||||||
|
|
||||||
|
@ -85,5 +87,85 @@ app.registerExtension({
|
||||||
|
|
||||||
return origDrawNode.apply(this, arguments);
|
return origDrawNode.apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently moving, selected group only. Set after the `selected_group` has actually started
|
||||||
|
* moving.
|
||||||
|
*/
|
||||||
|
let selectedAndMovingGroup = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles moving a group; tracking when a group has been moved (to show the ghost in `drawGroups`
|
||||||
|
* below) as well as handle the last move call from LiteGraph's `processMouseUp`.
|
||||||
|
*/
|
||||||
|
const groupMove = LGraphGroup.prototype.move;
|
||||||
|
LGraphGroup.prototype.move = function(deltax, deltay, ignore_nodes) {
|
||||||
|
const v = groupMove.apply(this, arguments);
|
||||||
|
// When we've started moving, set `selectedAndMovingGroup` as LiteGraph sets `selected_group`
|
||||||
|
// too eagerly and we don't want to behave like we're moving until we get a delta.
|
||||||
|
if (!selectedAndMovingGroup && app.canvas.selected_group === this && (deltax || deltay)) {
|
||||||
|
selectedAndMovingGroup = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// LiteGraph will call group.move both on mouse-move as well as mouse-up though we only want
|
||||||
|
// to snap on a mouse-up which we can determine by checking if `app.canvas.last_mouse_dragging`
|
||||||
|
// has been set to `false`. Essentially, this check here is the equivilant to calling an
|
||||||
|
// `LGraphGroup.prototype.onNodeMoved` if it had existed.
|
||||||
|
if (app.canvas.last_mouse_dragging === false && app.shiftDown) {
|
||||||
|
// After moving a group (while app.shiftDown), snap all the child nodes and, finally,
|
||||||
|
// align the group itself.
|
||||||
|
this.recomputeInsideNodes();
|
||||||
|
for (const node of this._nodes) {
|
||||||
|
node.alignToGrid();
|
||||||
|
}
|
||||||
|
LGraphNode.prototype.alignToGrid.apply(this);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles drawing a group when, snapping the size when one is actively being resized tracking and/or
|
||||||
|
* drawing a ghost box when one is actively being moved. This mimics the node snapping behavior for
|
||||||
|
* both.
|
||||||
|
*/
|
||||||
|
const drawGroups = LGraphCanvas.prototype.drawGroups;
|
||||||
|
LGraphCanvas.prototype.drawGroups = function (canvas, ctx) {
|
||||||
|
if (this.selected_group && app.shiftDown) {
|
||||||
|
if (this.selected_group_resizing) {
|
||||||
|
roundVectorToGrid(this.selected_group.size);
|
||||||
|
} else if (selectedAndMovingGroup) {
|
||||||
|
const [x, y] = roundVectorToGrid([...selectedAndMovingGroup.pos]);
|
||||||
|
const f = ctx.fillStyle;
|
||||||
|
const s = ctx.strokeStyle;
|
||||||
|
ctx.fillStyle = "rgba(100, 100, 100, 0.33)";
|
||||||
|
ctx.strokeStyle = "rgba(100, 100, 100, 0.66)";
|
||||||
|
ctx.rect(x, y, ...selectedAndMovingGroup.size);
|
||||||
|
ctx.fill();
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.fillStyle = f;
|
||||||
|
ctx.strokeStyle = s;
|
||||||
|
}
|
||||||
|
} else if (!this.selected_group) {
|
||||||
|
selectedAndMovingGroup = null;
|
||||||
|
}
|
||||||
|
return drawGroups.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Handles adding a group in a snapping-enabled state. */
|
||||||
|
const onGroupAdd = LGraphCanvas.onGroupAdd;
|
||||||
|
LGraphCanvas.onGroupAdd = function() {
|
||||||
|
const v = onGroupAdd.apply(app.canvas, arguments);
|
||||||
|
if (app.shiftDown) {
|
||||||
|
const lastGroup = app.graph._groups[app.graph._groups.length - 1];
|
||||||
|
if (lastGroup) {
|
||||||
|
roundVectorToGrid(lastGroup.pos);
|
||||||
|
roundVectorToGrid(lastGroup.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue