diff --git a/web/js/snapToGrid.js b/web/js/snapToGrid.js index 8825b0d..07d5aa8 100644 --- a/web/js/snapToGrid.js +++ b/web/js/snapToGrid.js @@ -1,19 +1,7 @@ import { app } from "../../../scripts/app.js"; -import { $el } from "../../../scripts/ui.js"; -let setting, guide_setting, guide_config; +let setting; const id = "pysssss.SnapToGrid"; -const guide_id = id + ".Guide"; -const guide_config_default = { - lines: { - enabled: false, - fillStyle: "rgba(255, 0, 0, 0.5)", - }, - block: { - enabled: false, - fillStyle: "rgba(0, 0, 255, 0.5)", - }, -} /** Wraps the provided function call to set/reset shiftDown when setting is enabled. */ function wrapCallInSettingCheck(fn) { @@ -30,11 +18,6 @@ function wrapCallInSettingCheck(fn) { const ext = { name: id, init() { - if (localStorage.getItem(guide_id) === null) { - localStorage.setItem(guide_id, JSON.stringify(guide_config_default)); - } - guide_config = JSON.parse(localStorage.getItem(guide_id)); - setting = app.ui.settings.addSetting({ id, name: "🐍 Always snap to grid", @@ -45,81 +28,6 @@ const ext = { }, }); - guide_setting = app.ui.settings.addSetting({ - id: id + ".Guide", - name: "🐍 Display drag-and-drop guides", - type: (name, setter, value) => { - return $el("tr", [ - $el("td", [ - $el("label", { - for: id.replaceAll(".", "-"), - textContent: name, - }), - ]), - $el("td", [ - $el( - "label", - { - textContent: "Lines: ", - style: { - display: "inline-block", - }, - }, - [ - $el("input", { - id: id.replaceAll(".", "-") + "-line-text", - type: "text", - value: guide_config.lines.fillStyle, - onchange: (event) => { - guide_config.lines.fillStyle = event.target.value; - localStorage.setItem(guide_id, JSON.stringify(guide_config)); - } - }), - $el("input", { - id: id.replaceAll(".", "-") + "-line-checkbox", - type: "checkbox", - checked: guide_config.lines.enabled, - onchange: (event) => { - guide_config.lines.enabled = !!event.target.checked; - localStorage.setItem(guide_id, JSON.stringify(guide_config)); - }, - }), - ] - ), - $el( - "label", - { - textContent: "Block: ", - style: { - display: "inline-block", - }, - }, - [ - $el("input", { - id: id.replaceAll(".", "-") + "-block-text", - type: "text", - value: guide_config.block.fillStyle, - onchange: (event) => { - guide_config.block.fillStyle = event.target.value; - localStorage.setItem(guide_id, JSON.stringify(guide_config)); - } - }), - $el("input", { - id: id.replaceAll(".", "-") + '-block-checkbox', - type: "checkbox", - checked: guide_config.block.enabled, - onchange: (event) => { - guide_config.block.enabled = !!event.target.checked; - localStorage.setItem(guide_id, JSON.stringify(guide_config)); - }, - }), - ] - ), - ]), - ]); - } - }); - // We need to register our hooks after the core snap to grid extension runs // Do this from the graph configure function so we still get onNodeAdded calls const configure = LGraph.prototype.configure; @@ -159,62 +67,6 @@ const ext = { return configure.apply(this, arguments); }; - - // Override drag-and-drop behavior to show orthogonal guide lines around selected node(s) and preview of where the node(s) will be placed - const origDrawNode = LGraphCanvas.prototype.drawNode - LGraphCanvas.prototype.drawNode = function (node, ctx) { - const enabled = guide_config.lines.enabled || guide_config.block.enabled; - if (enabled && app.shiftDown && this.node_dragged && node.id in this.selected_nodes) { - // discretize the canvas into grid - let x = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[0] / LiteGraph.CANVAS_GRID_SIZE); - let y = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[1] / LiteGraph.CANVAS_GRID_SIZE); - - // calculate the width and height of the node - // (also need to shift the y position of the node, depending on whether the title is visible) - x -= node.pos[0]; - y -= node.pos[1]; - let w, h; - if (node.flags.collapsed) { - w = node._collapsed_width; - h = LiteGraph.NODE_TITLE_HEIGHT; - y -= LiteGraph.NODE_TITLE_HEIGHT; - } else { - w = node.size[0]; - h = node.size[1]; - let titleMode = node.constructor.title_mode; - if (titleMode !== LiteGraph.TRANSPARENT_TITLE && titleMode !== LiteGraph.NO_TITLE) { - h += LiteGraph.NODE_TITLE_HEIGHT; - y -= LiteGraph.NODE_TITLE_HEIGHT; - } - } - - // save the original fill style - const f = ctx.fillStyle; - - // draw preview for drag-and-drop (rectangle to show where the node will be placed) - if (guide_config.block.enabled) { - ctx.fillStyle = guide_config.block.fillStyle; - ctx.fillRect(x, y, w, h); - } - - // add guide lines around node (arbitrarily long enough to span most workflows) - if (guide_config.lines.enabled) { - const xd = 10000; - const yd = 10000; - const thickness = 3; - ctx.fillStyle = guide_config.lines.fillStyle; - ctx.fillRect(x - xd, y, 2*xd, thickness); - ctx.fillRect(x, y - yd, thickness, 2*yd); - ctx.fillRect(x - xd, y + h, 2*xd, thickness); - ctx.fillRect(x + w, y - yd, thickness, 2*yd); - } - - // restore the original fill style - ctx.fillStyle = f; - } - - return origDrawNode.apply(this, arguments); - }; }, }; diff --git a/web/js/snapToGridGuide.js b/web/js/snapToGridGuide.js new file mode 100644 index 0000000..75a975a --- /dev/null +++ b/web/js/snapToGridGuide.js @@ -0,0 +1,158 @@ +import { app } from "../../../scripts/app.js"; +import { $el } from "../../../scripts/ui.js"; + +let guide_config; +const id = "pysssss.SnapToGrid.Guide"; +const guide_config_default = { + lines: { + enabled: false, + fillStyle: "rgba(255, 0, 0, 0.5)", + }, + block: { + enabled: false, + fillStyle: "rgba(0, 0, 255, 0.5)", + }, +} + +const ext = { + name: id, + init() { + if (localStorage.getItem(id) === null) { + localStorage.setItem(id, JSON.stringify(guide_config_default)); + } + guide_config = JSON.parse(localStorage.getItem(id)); + + app.ui.settings.addSetting({ + id, + name: "🐍 Display drag-and-drop guides", + type: (name, setter, value) => { + return $el("tr", [ + $el("td", [ + $el("label", { + for: id.replaceAll(".", "-"), + textContent: name, + }), + ]), + $el("td", [ + $el( + "label", + { + textContent: "Lines: ", + style: { + display: "inline-block", + }, + }, + [ + $el("input", { + id: id.replaceAll(".", "-") + "-line-text", + type: "text", + value: guide_config.lines.fillStyle, + onchange: (event) => { + guide_config.lines.fillStyle = event.target.value; + localStorage.setItem(id, JSON.stringify(guide_config)); + } + }), + $el("input", { + id: id.replaceAll(".", "-") + "-line-checkbox", + type: "checkbox", + checked: guide_config.lines.enabled, + onchange: (event) => { + guide_config.lines.enabled = !!event.target.checked; + localStorage.setItem(id, JSON.stringify(guide_config)); + }, + }), + ] + ), + $el( + "label", + { + textContent: "Block: ", + style: { + display: "inline-block", + }, + }, + [ + $el("input", { + id: id.replaceAll(".", "-") + "-block-text", + type: "text", + value: guide_config.block.fillStyle, + onchange: (event) => { + guide_config.block.fillStyle = event.target.value; + localStorage.setItem(id, JSON.stringify(guide_config)); + } + }), + $el("input", { + id: id.replaceAll(".", "-") + '-block-checkbox', + type: "checkbox", + checked: guide_config.block.enabled, + onchange: (event) => { + guide_config.block.enabled = !!event.target.checked; + localStorage.setItem(id, JSON.stringify(guide_config)); + }, + }), + ] + ), + ]), + ]); + } + }); + + // Override drag-and-drop behavior to show orthogonal guide lines around selected node(s) and preview of where the node(s) will be placed + const origDrawNode = LGraphCanvas.prototype.drawNode + LGraphCanvas.prototype.drawNode = function (node, ctx) { + const enabled = guide_config.lines.enabled || guide_config.block.enabled; + if (enabled && app.shiftDown && this.node_dragged && node.id in this.selected_nodes) { + // discretize the canvas into grid + let x = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[0] / LiteGraph.CANVAS_GRID_SIZE); + let y = LiteGraph.CANVAS_GRID_SIZE * Math.round(node.pos[1] / LiteGraph.CANVAS_GRID_SIZE); + + // calculate the width and height of the node + // (also need to shift the y position of the node, depending on whether the title is visible) + x -= node.pos[0]; + y -= node.pos[1]; + let w, h; + if (node.flags.collapsed) { + w = node._collapsed_width; + h = LiteGraph.NODE_TITLE_HEIGHT; + y -= LiteGraph.NODE_TITLE_HEIGHT; + } else { + w = node.size[0]; + h = node.size[1]; + let titleMode = node.constructor.title_mode; + if (titleMode !== LiteGraph.TRANSPARENT_TITLE && titleMode !== LiteGraph.NO_TITLE) { + h += LiteGraph.NODE_TITLE_HEIGHT; + y -= LiteGraph.NODE_TITLE_HEIGHT; + } + } + + // save the original fill style + const f = ctx.fillStyle; + + // draw preview for drag-and-drop (rectangle to show where the node will be placed) + if (guide_config.block.enabled) { + ctx.fillStyle = guide_config.block.fillStyle; + ctx.fillRect(x, y, w, h); + } + + // add guide lines around node (arbitrarily long enough to span most workflows) + if (guide_config.lines.enabled) { + const xd = 10000; + const yd = 10000; + const thickness = 3; + ctx.fillStyle = guide_config.lines.fillStyle; + ctx.fillRect(x - xd, y, 2*xd, thickness); + ctx.fillRect(x, y - yd, thickness, 2*yd); + ctx.fillRect(x - xd, y + h, 2*xd, thickness); + ctx.fillRect(x + w, y - yd, thickness, 2*yd); + } + + // restore the original fill style + ctx.fillStyle = f; + } + + return origDrawNode.apply(this, arguments); + }; + }, +}; + +app.registerExtension(ext);