From 56279cdc7533522f33899446c484efd359d04547 Mon Sep 17 00:00:00 2001 From: kk8bit Date: Sat, 29 Mar 2025 23:53:15 +0800 Subject: [PATCH] v0.50.6 --- locales/zh/settings.json | 6 +-- pyproject.toml | 2 +- web/nodealign.js | 104 +++++++++++++++++++++++++++++++++++---- web/settings.js | 2 +- 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/locales/zh/settings.json b/locales/zh/settings.json index d5bbb9e..edc833c 100644 --- a/locales/zh/settings.json +++ b/locales/zh/settings.json @@ -34,8 +34,7 @@ "Permanent": "常驻", "Show on Node Selection": "在选中多个节点时", "Disabled": "禁用" - }, - "tooltip": "切换模式后点击画布空白处或刷新页面即可" + } }, "KayTool_NodeAlignBackgroundOpacity": { "name": "工具栏背景不透明度" @@ -44,7 +43,8 @@ "name": "工具栏背景颜色" }, "KayTool_NodeAlignIconBackgroundColor": { - "name": "图标背景颜色" + "name": "图标背景颜色", + "tooltip": "数值“363636”接近ComfyUI菜单栏颜色,可模拟隐藏背景效果" }, "KayTool_NodeAlignIconColor": { "name": "图标颜色" diff --git a/pyproject.toml b/pyproject.toml index 368823a..777c9d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "kaytool" description ="KayTool enhances ComfyUI workflow efficiency with practical tools, including: image processing (resize, color, blur, expand, merge, crop), background/mask tasks via BiRefNet/RemBG, wireless data transfer (Get & Out), AI translation (Tencent/Baidu), dynamic math operations, flexible text handling, precision sliders, metadata/color profile-supported image saving, batch processing via image folder loading, canvas workflow node map export as PNG with embedded metadata, quick Run options via right-click (Run Group/Node), node alignment toolbar with custom styled styles, and custom ComfyUI logo integration." -version = "0.50.5" +version = "0.50.6" license = {file = "LICENSE"} dependencies = ["rembg, timm"] diff --git a/web/nodealign.js b/web/nodealign.js index f041aa1..47d2f8a 100644 --- a/web/nodealign.js +++ b/web/nodealign.js @@ -1,7 +1,6 @@ import { app } from "../../../scripts/app.js"; -// Based on /NodeAligner by Tenney95 GitHub:https://github.com/Tenney95/ComfyUI-NodeAligner - +// SVG 定义(已包含你的现有 SVG,新增参考代码中的两个) const kayAlignBottomSvg = ``; const kayAlignCenterHorizontallySvg = ``; const kayAlignCenterVerticallySvg = ``; @@ -10,6 +9,8 @@ const kayAlignRightSvg = ``; const kayEqualWidthSvg = ``; const kayEqualHeightSvg = ``; +const kayHorizontalDistributionSvg = ``; +const kayVerticalDistributionSvg = ``; let stylesInjected = false; @@ -87,7 +88,7 @@ const KayNodeAlignmentManager = { transition: background-color 0.3s ease-in-out, transform 0.1s ease; flex-shrink: 0; } - .kay-align-button svg { width: 70%; height: 70%; } + .kay-align-button svg { width: 66%; height: 66%; } .kay-toolbar-divider { width: 3.2px; height: 15px; @@ -156,7 +157,7 @@ const KayNodeAlignmentManager = { const menuChildren = Array.from(this.menuElement.children).filter(child => child !== this.insertionIndicator); const insertIndex = Math.min(this.position.insertIndex, menuChildren.length); const insertBeforeElement = menuChildren[insertIndex] || null; - this.menuElement.insertBefore(this.toolbarContainer, insertBeforeElement);; + this.menuElement.insertBefore(this.toolbarContainer, insertBeforeElement); } else { document.body.appendChild(this.toolbarContainer); } @@ -219,7 +220,10 @@ const KayNodeAlignmentManager = { { id: 'kay-align-bottom', svg: kayAlignBottomSvg, action: this.alignBottom }, { type: 'divider' }, { id: 'kay-equal-width', svg: kayEqualWidthSvg, action: this.equalWidth }, - { id: 'kay-equal-height', svg: kayEqualHeightSvg, action: this.equalHeight } + { id: 'kay-equal-height', svg: kayEqualHeightSvg, action: this.equalHeight }, + { type: 'divider' }, + { id: 'kay-horizontal-distribution', svg: kayHorizontalDistributionSvg, action: this.horizontalDistribution }, + { id: 'kay-vertical-distribution', svg: kayVerticalDistributionSvg, action: this.verticalDistribution } ]; }, @@ -278,14 +282,23 @@ const KayNodeAlignmentManager = { onDragStart(e) { e.preventDefault(); const { toolbarRect } = this.getRect(); - this.dragState = { isDragging: true, offsetX: e.clientX - toolbarRect.left, offsetY: e.clientY - toolbarRect.top }; - if (this.position.isAttached) this.detachFromMenu(true); - if (this.menuElement) this.menuElement.style.backgroundColor = '#d0ff00'; + this.dragState = { + isDragging: true, + offsetX: e.clientX - toolbarRect.left, + offsetY: e.clientY - toolbarRect.top + }; }, onDragging(e) { if (!this.dragState.isDragging) return; + const { windowRect, toolbarRect, menuRect } = this.getRect(); + + if (this.position.isAttached) { + this.detachFromMenu(true); + this.menuElement.style.backgroundColor = '#d0ff00'; + } + let left = e.clientX - this.dragState.offsetX; let top = e.clientY - this.dragState.offsetY; left = Math.max(0, Math.min(left, windowRect.width - toolbarRect.width)); @@ -317,6 +330,7 @@ const KayNodeAlignmentManager = { onDragEnd() { if (!this.dragState.isDragging) return; + this.dragState.isDragging = false; this.dragState.offsetX = 0; this.dragState.offsetY = 0; @@ -441,13 +455,85 @@ const KayNodeAlignmentManager = { this.redraw(); }, + horizontalDistribution() { + const nodes = this.getSelectedNodes(); + const axis = 0; + if (nodes.length > 1) { + nodes.sort((a, b) => a.pos[axis] - b.pos[axis]); + const min = Math.min(...nodes.map(node => node.pos[axis])); + const max = Math.max(...nodes.map(node => node.pos[axis] + node.size[axis])); + const totalSize = nodes.reduce((sum, node) => sum + node.size[axis], 0); + const spacing = (max - min - totalSize) / (nodes.length - 1); + let current = min; + nodes.forEach(node => { + node.pos[axis] = current; + current += node.size[axis] + spacing; + }); + this.redraw(); + } + }, + + verticalDistribution() { + const nodes = this.getSelectedNodes(); + if (nodes.length > 1) { + const axis = 1; + const otherAxis = 0; + const tolerance = 100; + const minSpacing = 20; + + const columns = []; + nodes.forEach(node => { + let foundColumn = null; + for (let column of columns) { + const columnX = column[0].pos[otherAxis]; + if (Math.abs(columnX - node.pos[otherAxis]) <= tolerance) { + foundColumn = column; + break; + } + } + if (foundColumn) { + foundColumn.push(node); + } else { + columns.push([node]); + } + }); + + const columnHeights = columns.map(column => { + const minY = Math.min(...column.map(node => node.pos[axis])); + const maxY = Math.max(...column.map(node => node.pos[axis] + node.size[axis])); + return maxY - minY; + }); + const maxColumnHeight = Math.max(...columnHeights); + + columns.forEach(column => { + if (column.length > 1) { + column.sort((a, b) => a.pos[axis] - b.pos[axis]); + const minY = Math.min(...column.map(node => node.pos[axis])); + const totalSize = column.reduce((sum, node) => sum + node.size[axis], 0); + let spacing = (maxColumnHeight - totalSize) / (column.length - 1); + spacing = Math.max(spacing, minSpacing); + let currentY = column[0].pos[axis]; + column.forEach((node, idx) => { + if (idx === 0) { + currentY += node.size[axis] + spacing; + } else { + node.pos[axis] = currentY; + currentY += node.size[axis] + spacing; + } + node.pos[otherAxis] = column[0].pos[otherAxis]; + }); + } + }); + this.redraw(); + } + }, + redraw() { if (app.canvas) app.canvas.setDirty(true, true); }, updateDisplayMode(mode) { const effectiveMode = mode || "permanent"; - if (effectiveMode === "disabled") { this.hide(); } else if (effectiveMode === "permanent") { diff --git a/web/settings.js b/web/settings.js index 85b80b8..45ca678 100644 --- a/web/settings.js +++ b/web/settings.js @@ -93,7 +93,6 @@ app.registerExtension({ ], defaultValue: "permanent", category: ["KayTool", "NodeAlignment", "DisplayMode"], - tooltip: "Controls when the node alignment toolbar is displayed.", onChange: (value) => { const manager = window.KayNodeAlignmentManager; const initFn = window.initializeKayNodeAlignment; @@ -152,6 +151,7 @@ app.registerExtension({ type: "color", defaultValue: "2b2b2b", category: ["KayTool", "NodeAlignment", "IconBackgroundColor"], + tooltip: "Use parameter “363636” to match ComfyUI menu bar color for an icon-free background effect", onChange: (newVal) => { if (/^[0-9A-Fa-f]{6}$/.test(newVal)) { const buttons = document.querySelectorAll('.kay-align-button');