243 lines
10 KiB
JavaScript
243 lines
10 KiB
JavaScript
import { app } from "/scripts/app.js";
|
|
import { ConnectionAnimation, DEFAULT_CONFIG } from "./ConnectionAnimationCore.js";
|
|
|
|
// 确保全局唯一实例
|
|
function getOrCreateAnimationInstance() {
|
|
if (!app.canvas._connectionAnimation) {
|
|
app.canvas._connectionAnimation = new ConnectionAnimation();
|
|
}
|
|
return app.canvas._connectionAnimation;
|
|
}
|
|
|
|
// 应用设置配置
|
|
function applySettings(connectionAnimation) {
|
|
connectionAnimation.setEnabled(app.extensionManager.setting.get("ConnectionAnimation.enabled") ?? DEFAULT_CONFIG.enabled);
|
|
connectionAnimation.setLineWidth(app.extensionManager.setting.get("ConnectionAnimation.lineWidth") ?? DEFAULT_CONFIG.lineWidth);
|
|
connectionAnimation.setEffect(app.extensionManager.setting.get("ConnectionAnimation.effect") ?? DEFAULT_CONFIG.effect);
|
|
connectionAnimation.setSpeed(app.extensionManager.setting.get("ConnectionAnimation.speed") ?? 2);
|
|
connectionAnimation.setSamplingLevel(app.extensionManager.setting.get("ConnectionAnimation.samplingLevel") ?? 2);
|
|
connectionAnimation.setEffectExtra(app.extensionManager.setting.get("ConnectionAnimation.effectExtra") ?? false);
|
|
connectionAnimation.setRenderStyle(app.extensionManager.setting.get("ConnectionAnimation.renderStyle") ?? "曲线");
|
|
connectionAnimation.setUseGradient(app.extensionManager.setting.get("ConnectionAnimation.useGradient") ?? true);
|
|
connectionAnimation.setDisplayMode(app.extensionManager.setting.get("ConnectionAnimation.displayMode") ?? DEFAULT_CONFIG.displayMode);
|
|
connectionAnimation.setStaticRenderMode(app.extensionManager.setting.get("ConnectionAnimation.staticRenderMode") ?? "独立渲染");
|
|
}
|
|
|
|
// 设置节点悬停监听
|
|
function setupNodeHoverListeners(connectionAnimation) {
|
|
// 设置节点悬停和选择监听
|
|
const originalOnNodeMouseEnter = app.canvas.onNodeMouseEnter;
|
|
if (originalOnNodeMouseEnter) {
|
|
app.canvas.onNodeMouseEnter = function(node, e) {
|
|
try {
|
|
connectionAnimation.setHoveredNode(node);
|
|
} catch (e) {
|
|
console.warn("Connection Animation: Error setting hovered node:", e);
|
|
}
|
|
return originalOnNodeMouseEnter?.call(this, node, e);
|
|
};
|
|
}
|
|
|
|
const originalOnNodeMouseLeave = app.canvas.onNodeMouseLeave;
|
|
if (originalOnNodeMouseLeave) {
|
|
app.canvas.onNodeMouseLeave = function(node, e) {
|
|
try {
|
|
connectionAnimation.setHoveredNode(null);
|
|
} catch (e) {
|
|
console.warn("Connection Animation: Error clearing hovered node:", e);
|
|
}
|
|
return originalOnNodeMouseLeave?.call(this, node, e);
|
|
};
|
|
}
|
|
|
|
// 重写 node_over 属性以捕获节点悬停
|
|
if (app.canvas && !app.canvas._connectionAnimationNodeOverPatched) {
|
|
let _node_over = app.canvas.node_over;
|
|
Object.defineProperty(app.canvas, 'node_over', {
|
|
get: () => _node_over,
|
|
set: (value) => {
|
|
_node_over = value;
|
|
try {
|
|
connectionAnimation.setHoveredNode(value);
|
|
} catch (e) {
|
|
console.warn("Connection Animation: Error setting hovered node:", e);
|
|
}
|
|
}
|
|
});
|
|
app.canvas._connectionAnimationNodeOverPatched = true;
|
|
}
|
|
}
|
|
|
|
app.registerExtension({
|
|
name: "ComfyUI.ConnectionAnimation",
|
|
setup() {
|
|
const connectionAnimation = getOrCreateAnimationInstance();
|
|
connectionAnimation.initOverrides(app.canvas);
|
|
|
|
// 应用所有设置
|
|
applySettings(connectionAnimation);
|
|
|
|
// 设置节点悬停监听
|
|
setupNodeHoverListeners(connectionAnimation);
|
|
},
|
|
settings: [
|
|
{
|
|
id: "ConnectionAnimation.enabled",
|
|
name: "动画开关",
|
|
type: "boolean",
|
|
defaultValue: true,
|
|
tooltip: "开启或关闭连线动画效果",
|
|
category: ["🍺连线动画", "1·功能", "动画开关"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setEnabled(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.lineWidth",
|
|
name: "动画大小",
|
|
type: "slider",
|
|
defaultValue: 2,
|
|
attrs: { min: 1, max: 3, step: 1 },
|
|
tooltip: "设置连线动画的粗细大小(1~3)",
|
|
category: ["🍺连线动画", "3·设置", "动画大小"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setLineWidth(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.effect",
|
|
name: "动画效果",
|
|
type: "combo",
|
|
options: ["流动", "波浪", "律动", "脉冲"],
|
|
defaultValue: "律动",
|
|
tooltip: "选择连线动画的视觉样式(流动/波浪/律动)",
|
|
category: ["🍺连线动画", "2·样式", "动画效果"],
|
|
onChange(value) {
|
|
if (!value) return;
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setEffect(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
}
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.speed",
|
|
name: "动画速度",
|
|
type: "slider",
|
|
defaultValue: 2,
|
|
attrs: { min: 1, max: 3, step: 1 },
|
|
tooltip: "设置连线动画的速度(1~3,数值越大越快)",
|
|
category: ["🍺连线动画", "3·设置", "动画速度"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setSpeed(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.samplingLevel",
|
|
name: "采样强度",
|
|
type: "slider",
|
|
defaultValue: 2,
|
|
attrs: { min: 1, max: 3, step: 1 },
|
|
tooltip: "控制所有动画效果的采样点数量,1=极致性能,3=极致流畅。采样点越少性能越高,采样点越多动画越细腻。",
|
|
category: ["🍺连线动画", "3·设置", "采样强度"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setSamplingLevel(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.effectExtra",
|
|
name: "动效开关",
|
|
type: "boolean",
|
|
defaultValue: false,
|
|
tooltip: "是否启用额外的动画特效(如发光、尾迹等)【注意!开启后会有更大的性能开销可能会导致工作流卡顿,低配置电脑谨慎开启!】",
|
|
category: ["🍺连线动画", "1·功能", "动效开关"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setEffectExtra(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.renderStyle",
|
|
name: "渲染样式",
|
|
type: "combo",
|
|
options: ["直线", "直角线", "曲线", "电路板"],
|
|
defaultValue: "曲线",
|
|
tooltip: "改变连线动画的渲染路径样式(直线/直角线/曲线/电路板)",
|
|
category: ["🍺连线动画", "2·样式", "动画渲染"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setRenderStyle(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.useGradient",
|
|
name: "连线渐变",
|
|
type: "boolean",
|
|
defaultValue: true,
|
|
tooltip: "开启后连线将使用渐变色彩,关闭则为纯主色。",
|
|
category: ["🍺连线动画", "1·功能", "连线渐变"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setUseGradient(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
}, {
|
|
id: "ConnectionAnimation.displayMode",
|
|
name: "动画显示",
|
|
type: "combo",
|
|
options: ["全部显示", "悬停节点"],
|
|
defaultValue: "全部显示",
|
|
tooltip: "控制动画连线的显示方式:全部显示=所有连线都显示动画;悬停节点=只有鼠标悬停节点的连线显示动画",
|
|
category: ["🍺连线动画", "2·样式", "动画显示"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setDisplayMode(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
},
|
|
{
|
|
id: "ConnectionAnimation.staticRenderMode",
|
|
name: "静态渲染",
|
|
type: "combo",
|
|
options: ["官方实现", "独立渲染"],
|
|
defaultValue: "独立渲染",
|
|
tooltip: "控制悬停模式下的静态连线渲染方式:官方实现=使用ComfyUI官方默认连线渲染;独立渲染=使用独立静态+动态混合渲染",
|
|
category: ["🍺连线动画", "2·样式", "静态渲染"],
|
|
onChange(value) {
|
|
const connectionAnim = app.canvas?._connectionAnimation;
|
|
if (connectionAnim) {
|
|
connectionAnim.setStaticRenderMode(value);
|
|
app.graph.setDirtyCanvas(true, true);
|
|
}
|
|
},
|
|
}
|
|
]
|
|
});
|