Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5af095c418 | ||
|
|
b9a3b28f9f | ||
|
|
f6c8efb9f1 | ||
|
|
2910671fed | ||
|
|
089b4572f8 | ||
|
|
2891304232 | ||
|
|
34258bc89e | ||
|
|
96f6f60b55 | ||
|
|
55fce04e4b | ||
|
|
c99c095b50 | ||
|
|
a07b2fdf91 | ||
|
|
e1b1729c88 |
@@ -0,0 +1,14 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [blib-la]
|
||||
patreon: Blib_la
|
||||
open_collective: blibla
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
polar: # Replace with a single Polar username
|
||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
@@ -0,0 +1,22 @@
|
||||
name: Publish to Comfy registry
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- master
|
||||
paths:
|
||||
- "pyproject.toml"
|
||||
|
||||
jobs:
|
||||
publish-node:
|
||||
name: Publish Custom Node to registry
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish Custom Node
|
||||
uses: Comfy-Org/publish-node-action@main
|
||||
with:
|
||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||
@@ -1,10 +1,15 @@
|
||||
# ComfyUI Extensions by Failfa.st
|
||||
# DEPRECATED - THIS PROJECT IS NO LONGER MAINTAINED AND WILL NOT RECEIVE ANY UPDATES
|
||||
# ComfyUI Extensions by Blibla
|
||||
|
||||
Chack out Captain: The AI Platform
|
||||
- https://github.com/blib-la/captain
|
||||
- https://get-captain.com
|
||||
|
||||

|
||||
|
||||
[](https://discord.com/invite/m3TBB9XEkb)
|
||||
|
||||
ComfyUI Extensions by Failfa.st is a robust suite of enhancements, designed to optimize your ComfyUI experience. It
|
||||
ComfyUI Extensions by Blibla is a robust suite of enhancements, designed to optimize your ComfyUI experience. It
|
||||
provides a range of features, including customizable render modes, dynamic node coloring, and versatile management
|
||||
tools. Whether for individual use or team collaboration, our extensions aim to enhance productivity, readability, and
|
||||
personalization in your ComfyUI environment.
|
||||
@@ -28,6 +33,8 @@ personalization in your ComfyUI environment.
|
||||
* [Colored Nodes](#colored-nodes)
|
||||
+ [Positive/Negative](#positivenegative)
|
||||
+ [Dynamic Colors](#dynamic-colors)
|
||||
- [Main Menu](#main-menu)
|
||||
* [Unload Models](#unload-models)
|
||||
- [Context Menu](#context-menu)
|
||||
* [Nodes](#nodes)
|
||||
+ [Custom Color Option (only available in "default" Color Mode)](#custom-color-option-only-available-in-default-color-mode)
|
||||
@@ -109,7 +116,6 @@ Different customization options available with their default settings and descri
|
||||
| Connections Width | `3` | Sets the width of connector lines |
|
||||
| Font Size | `10` | Sets the font size of textareas |
|
||||
| Colored Nodes | `default` | Applies dynamic coloring to nodes |
|
||||
| Batch Resize | `false` | Resizes multiple selected nodes to the same size synchronously |
|
||||
|
||||
### Colored Nodes
|
||||
|
||||
@@ -141,6 +147,23 @@ Several dynamic coloring modes are available:
|
||||
<p>Dynamic Colors Modes: plain, by type, rainbow</p>
|
||||
</div>
|
||||
|
||||
## Main Menu
|
||||
|
||||
### Unload Models
|
||||
|
||||
Free up GPU memory by unloading the models
|
||||
|
||||
<div align="center">
|
||||
<img src="https://github.com/blib-la/blibla-comfyui-extensions/assets/1148334/a81f3689-0291-4f2d-8ce5-3a9b4a8a2e76" alt="Unload Models Button" width="400px">
|
||||
<p>A new Button is available</p>
|
||||
</div>
|
||||
|
||||
<div align="center">
|
||||
<img src="https://github.com/blib-la/blibla-comfyui-extensions/assets/1148334/e8d848d5-c157-4574-8fac-7d30052451d0" alt="GPU freed" width="400px">
|
||||
<p>GPU Memory was freed</p>
|
||||
</div>
|
||||
|
||||
|
||||
## Context Menu
|
||||
|
||||
The context menu offers additional options for nodes, groups, colors, and the canvas:
|
||||
@@ -161,6 +184,7 @@ The context menu offers additional options for nodes, groups, colors, and the ca
|
||||
<p>Reroute show/hide Title</p>
|
||||
</div>
|
||||
|
||||
|
||||
#### Render Reroute as Dot
|
||||
|
||||
<div align="center">
|
||||
|
||||
+245
-62
@@ -184,45 +184,40 @@ function colorPositiveNegative(app) {
|
||||
* Colors
|
||||
*/
|
||||
let afterChange;
|
||||
let colorModeValue;
|
||||
function invokeAfterChange() {
|
||||
switch (colorModeValue) {
|
||||
case 1:
|
||||
uncolor(app);
|
||||
break;
|
||||
case 2:
|
||||
rainbowify(app);
|
||||
break;
|
||||
case 3:
|
||||
colorByType(app);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (getPosNegValue()) {
|
||||
colorPositiveNegative(app);
|
||||
}
|
||||
return afterChange?.apply(this, arguments);
|
||||
}
|
||||
|
||||
function setColorMode(value, app) {
|
||||
colorModeValue = value;
|
||||
switch (value) {
|
||||
case 1:
|
||||
app.graph.afterChange = function () {
|
||||
uncolor(app);
|
||||
if (getPosNegValue()) {
|
||||
colorPositiveNegative(app);
|
||||
}
|
||||
return afterChange?.apply(this, arguments);
|
||||
};
|
||||
uncolor(app);
|
||||
break;
|
||||
case 2:
|
||||
app.graph.afterChange = function () {
|
||||
rainbowify(app);
|
||||
if (getPosNegValue()) {
|
||||
colorPositiveNegative(app);
|
||||
}
|
||||
return afterChange?.apply(this, arguments);
|
||||
};
|
||||
rainbowify(app);
|
||||
break;
|
||||
case 3:
|
||||
app.graph.afterChange = function () {
|
||||
colorByType(app);
|
||||
if (getPosNegValue()) {
|
||||
colorPositiveNegative(app);
|
||||
}
|
||||
return afterChange?.apply(this, arguments);
|
||||
};
|
||||
colorByType(app);
|
||||
break;
|
||||
default:
|
||||
app.graph.afterChange = function () {
|
||||
if (getPosNegValue()) {
|
||||
colorPositiveNegative(app);
|
||||
}
|
||||
return afterChange?.apply(this, arguments);
|
||||
};
|
||||
app.graph._nodes.forEach((node) => {
|
||||
node.bgcolor = node._bgcolor ?? node.bgcolor;
|
||||
node.color = node._color ?? node.color;
|
||||
@@ -275,49 +270,157 @@ app.registerExtension({
|
||||
},
|
||||
async init(app) {
|
||||
afterChange = app.graph.afterChange;
|
||||
app.graph.afterChange = invokeAfterChange;
|
||||
const onMenuNodeColors = LGraphCanvas.onMenuNodeColors;
|
||||
LGraphCanvas.onMenuNodeColors = function (value, options, e, menu, node) {
|
||||
const response = onMenuNodeColors.apply(this, arguments);
|
||||
const menuRoot = menu.current_submenu.root;
|
||||
const isGroup = node instanceof LGraphGroup;
|
||||
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Custom",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.bgcolor = event.target.value;
|
||||
node.color = shadeHexColor(node.bgcolor);
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
if (!isGroup) {
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Custom Title",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
// node.bgcolor = event.target.value;
|
||||
node.color = shadeHexColor(event.target.value);
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Custom BG",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.bgcolor = event.target.value;
|
||||
// node.color = shadeHexColor(node.bgcolor);
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Custom All",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.bgcolor = event.target.value;
|
||||
node.color = shadeHexColor(node.bgcolor);
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
}
|
||||
if (isGroup) {
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Color Group",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.bgcolor = event.target.value;
|
||||
node.color = shadeHexColor(node.bgcolor);
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
@@ -331,7 +434,87 @@ app.registerExtension({
|
||||
},
|
||||
},
|
||||
[
|
||||
"Color all",
|
||||
"Color All Title",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.recomputeInsideNodes();
|
||||
// node.bgcolor = event.target.value;
|
||||
node.color = shadeHexColor(event.target.value);
|
||||
node._nodes.forEach((node_) => {
|
||||
// node_.bgcolor = node.bgcolor;
|
||||
node_.color = node.color;
|
||||
});
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Color All BG",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
style: {
|
||||
position: "absolute",
|
||||
right: "200%",
|
||||
},
|
||||
oninput(event) {
|
||||
node.recomputeInsideNodes();
|
||||
node.bgcolor = event.target.value;
|
||||
// node.color = shadeHexColor(node.bgcolor);
|
||||
node._nodes.forEach((node_) => {
|
||||
node_.bgcolor = node.bgcolor;
|
||||
// node_.color = node.color;
|
||||
});
|
||||
// TODO: check if we can adjust this
|
||||
// node.title_color = getContrastColor(node.bgcolor);
|
||||
|
||||
node.setDirtyCanvas(true, true);
|
||||
},
|
||||
}),
|
||||
],
|
||||
),
|
||||
]),
|
||||
);
|
||||
menuRoot.append(
|
||||
$el("div.litemenu-entry.submenu", [
|
||||
$el(
|
||||
"label",
|
||||
{
|
||||
style: {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
display: "block",
|
||||
paddingLeft: "4px",
|
||||
borderLeft: "8px solid #222",
|
||||
},
|
||||
},
|
||||
[
|
||||
"Color All",
|
||||
$el("input", {
|
||||
type: "color",
|
||||
value: node.bgcolor,
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/**
|
||||
* Coded with love by Failfa.st
|
||||
* LICENSE: AGPL 3.0
|
||||
* https://github.com/failfa-st/failfast-comfyui-extensions/blob/main/LICENSE
|
||||
*
|
||||
* Visit https://github.com/failfa-st/failfast-comfyui-extensions for more info
|
||||
*
|
||||
* Homepage: https://failfa.st
|
||||
* GitHub: https://github.com/failfa-st
|
||||
* Discord: https://discord.com/invite/m3TBB9XEkb
|
||||
*/
|
||||
import { app } from "/scripts/app.js";
|
||||
|
||||
/**
|
||||
* Render Shadow
|
||||
*/
|
||||
|
||||
const linkRenderModesName = "Failfast.linkRenderModes";
|
||||
|
||||
app.registerExtension({
|
||||
name: linkRenderModesName,
|
||||
async init() {
|
||||
if (LiteGraph?.LINK_RENDER_MODES) {
|
||||
LiteGraph.LINK_RENDER_MODES[3] = "Hidden";
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,82 +0,0 @@
|
||||
/**
|
||||
* Coded with love by Failfa.st
|
||||
* LICENSE: AGPL 3.0
|
||||
* https://github.com/failfa-st/failfast-comfyui-extensions/blob/main/LICENSE
|
||||
*
|
||||
* Visit https://github.com/failfa-st/failfast-comfyui-extensions for more info
|
||||
*
|
||||
* Homepage: https://failfa.st
|
||||
* GitHub: https://github.com/failfa-st
|
||||
* Discord: https://discord.com/invite/m3TBB9XEkb
|
||||
*/
|
||||
import { app } from "/scripts/app.js";
|
||||
|
||||
/**
|
||||
* Nodes
|
||||
*/
|
||||
|
||||
const nodesName = "Failfast.nodes";
|
||||
|
||||
const store = {
|
||||
stack: new Set(),
|
||||
};
|
||||
|
||||
app.registerExtension({
|
||||
name: nodesName,
|
||||
async init(app) {
|
||||
app.ui.settings.addSetting({
|
||||
id: nodesName,
|
||||
name: "Allow group selection resize",
|
||||
type: "boolean",
|
||||
tooltip: "Resize all selected nodes synchronous.",
|
||||
defaultValue: false,
|
||||
});
|
||||
},
|
||||
async setup(app) {
|
||||
app.graph._nodes.forEach(function (node) {
|
||||
let active = JSON.parse(
|
||||
window.localStorage.getItem(`Comfy.Settings.${nodesName}`) ?? "false"
|
||||
);
|
||||
const onResize = node.onResize;
|
||||
node.onResize = function (size) {
|
||||
if (active) {
|
||||
Array.from(store.stack)
|
||||
.filter((node_) => node_ !== node)
|
||||
.forEach((node_) => {
|
||||
if (app.shiftDown) {
|
||||
const w =
|
||||
LiteGraph.CANVAS_GRID_SIZE *
|
||||
Math.round(size[0] / LiteGraph.CANVAS_GRID_SIZE);
|
||||
const h =
|
||||
LiteGraph.CANVAS_GRID_SIZE *
|
||||
Math.round(size[1] / LiteGraph.CANVAS_GRID_SIZE);
|
||||
node_.size[0] = w;
|
||||
node_.size[1] = h;
|
||||
} else {
|
||||
node_.size[0] = size[0];
|
||||
node_.size[1] = size[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
return onResize?.apply(this, arguments);
|
||||
};
|
||||
const onMouseDown = node.onMouseDown;
|
||||
node.onMouseDown = function () {
|
||||
active = JSON.parse(
|
||||
window.localStorage.getItem(`Comfy.Settings.${nodesName}`) ?? "false"
|
||||
);
|
||||
return onMouseDown?.apply(this, arguments);
|
||||
};
|
||||
const onSelected = node.onSelected;
|
||||
node.onSelected = function () {
|
||||
store.stack.add(node);
|
||||
return onSelected?.apply(this, arguments);
|
||||
};
|
||||
const onDeselected = node.onDeselected;
|
||||
node.onDeselected = function () {
|
||||
store.stack.delete(node);
|
||||
return onDeselected?.apply(this, arguments);
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import { app } from "/scripts/app.js";
|
||||
import { $el } from "/scripts/ui.js";
|
||||
|
||||
const nodeName = "Failfast.unloadModels";
|
||||
|
||||
const button = $el(
|
||||
"button",
|
||||
{
|
||||
onclick() {
|
||||
fetch("/free", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ unload_models: true }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
},
|
||||
},
|
||||
["Unload Models"]
|
||||
);
|
||||
|
||||
app.registerExtension({
|
||||
name: nodeName,
|
||||
async init(app) {
|
||||
app.ui.menuContainer.append(button);
|
||||
},
|
||||
});
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "failfast-comfyui-extensions",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"scripts": {
|
||||
"changelog": "npx conventional-changelog-cli -p angular -i CHANGELOG.md -s",
|
||||
"toc": "npx markdown-toc README.md -i "
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[project]
|
||||
name = "blibla-comfyui-extensions"
|
||||
description = ""
|
||||
version = "1.0.0"
|
||||
license = "LICENSE"
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/blib-la/blibla-comfyui-extensions"
|
||||
# Used by Comfy Registry https://comfyregistry.org
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = ""
|
||||
DisplayName = "blibla-comfyui-extensions"
|
||||
Icon = ""
|
||||
Reference in New Issue
Block a user