Merge branch 'main' into dev/uv-tools
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
name: 🐞 Bug Report
|
||||
title: "[bug] "
|
||||
title: '[bug] '
|
||||
description: Report a bug
|
||||
labels: ["type: 🐛 bug", "status: 🧹 needs triage"]
|
||||
labels: ['type: 🐛 bug', 'status: 🧹 needs triage']
|
||||
assignees:
|
||||
- melMass
|
||||
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
@@ -12,6 +12,8 @@ body:
|
||||
## Before submiting an issue
|
||||
- Make sure to read the README & INSTALL instructions.
|
||||
- Please search for [existing issues](https://github.com/melMass/comfy_mtb/issues?q=is%3Aissue) around your problem before filing a report.
|
||||
- Optionally check the `#mtb-nodes` channel on the Banodoco discord:
|
||||
[](https://discord.gg/IAXhsabmDhn)
|
||||
|
||||
### Try using the debug mode to get more info
|
||||
|
||||
@@ -54,7 +56,7 @@ body:
|
||||
default: 0
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
- type: dropdown
|
||||
id: comfy_mode
|
||||
attributes:
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
|
||||
[**Install Guide**](./INSTALL.md) | [**Examples**](https://github.com/melMass/comfy_mtb/wiki/Examples)
|
||||
|
||||
There is now a dedicated `#mtb-nodes` channel on the Banodoco discord:
|
||||
[](https://discord.gg/IAXhsabmDhn)
|
||||
|
||||
---
|
||||
|
||||
Welcome to the MTB Nodes project! This codebase is open for you to explore and utilize as you wish. Its primary purpose is to build proof-of-concepts (POCs) for implementation in [MLOPs](https://github.com/Bismuth-Consultancy-BV/MLOPs). Many nodes in this project are inspired by existing community contributions or built-in functionalities.
|
||||
|
||||
Before proceeding, please be aware of the licenses associated with certain libraries used in this project. For example, the `deepbump` library is licensed under [GPLv3](https://github.com/HugoTini/DeepBump/blob/master/LICENSE).
|
||||
@@ -41,6 +46,7 @@ mtb add a few widgets like `COLOR`
|
||||
A few nodes have the concept of "dynamic" inputs:
|
||||
<img alt="dynamic inputs" width=450 src="https://github.com/melMass/comfy_mtb/assets/7041726/10b3976e-b212-4968-91eb-f34c02bb80c3" />
|
||||
|
||||
<!-- NOTE: Here it should just be some examples and warnings, move the rest to the wiki -->
|
||||
|
||||
# Node List
|
||||
|
||||
|
||||
+24
-15
@@ -199,8 +199,8 @@ class BatchFloat:
|
||||
{"default": "Steps"},
|
||||
),
|
||||
"count": ("INT", {"default": 1}),
|
||||
"min": ("FLOAT", {"default": 0.0}),
|
||||
"max": ("FLOAT", {"default": 1.0}),
|
||||
"min": ("FLOAT", {"default": 0.0, "step": 0.001}),
|
||||
"max": ("FLOAT", {"default": 1.0, "step": 0.001}),
|
||||
"easing": (
|
||||
[
|
||||
"Linear",
|
||||
@@ -276,7 +276,7 @@ class BatchMerge:
|
||||
FUNCTION = "merge_batches"
|
||||
CATEGORY = "mtb/batch"
|
||||
|
||||
def merge_batches(self, fusion_mode, fill, **kwargs):
|
||||
def merge_batches(self, fusion_mode: str, fill: str, **kwargs):
|
||||
images = kwargs.values()
|
||||
max_frames = max(img.shape[0] for img in images)
|
||||
|
||||
@@ -340,9 +340,12 @@ class Batch2dTransform:
|
||||
FUNCTION = "transform_batch"
|
||||
CATEGORY = "mtb/batch"
|
||||
|
||||
def get_num_elements(self, param) -> int:
|
||||
def get_num_elements(
|
||||
self, param: None | torch.Tensor | list[torch.Tensor] | list[float]
|
||||
) -> int:
|
||||
if isinstance(param, torch.Tensor):
|
||||
return torch.numel(param)
|
||||
|
||||
elif isinstance(param, list):
|
||||
return len(param)
|
||||
|
||||
@@ -367,20 +370,26 @@ class Batch2dTransform:
|
||||
"At least one transform parameter must be provided"
|
||||
)
|
||||
|
||||
keyframes = {"x": [], "y": [], "zoom": [], "angle": [], "shear": []}
|
||||
keyframes: dict[str, list[float]] = {
|
||||
"x": [],
|
||||
"y": [],
|
||||
"zoom": [],
|
||||
"angle": [],
|
||||
"shear": [],
|
||||
}
|
||||
|
||||
default_vals = {"x": 0, "y": 0, "zoom": 1.0, "angle": 0, "shear": 0}
|
||||
|
||||
if self.get_num_elements(x) > 0:
|
||||
keyframes["x"] = x # type: ignore
|
||||
if self.get_num_elements(y) > 0:
|
||||
keyframes["y"] = y # type: ignore
|
||||
if self.get_num_elements(zoom) > 0:
|
||||
keyframes["zoom"] = zoom # type: ignore
|
||||
if self.get_num_elements(angle) > 0:
|
||||
keyframes["angle"] = angle # type: ignore
|
||||
if self.get_num_elements(shear) > 0:
|
||||
keyframes["shear"] = shear # type: ignore
|
||||
if x and self.get_num_elements(x) > 0:
|
||||
keyframes["x"] = x
|
||||
if y and self.get_num_elements(y) > 0:
|
||||
keyframes["y"] = y
|
||||
if zoom and self.get_num_elements(zoom) > 0:
|
||||
keyframes["zoom"] = zoom
|
||||
if angle and self.get_num_elements(angle) > 0:
|
||||
keyframes["angle"] = angle
|
||||
if shear and self.get_num_elements(shear) > 0:
|
||||
keyframes["shear"] = shear
|
||||
|
||||
for name, values in keyframes.items():
|
||||
count = len(values)
|
||||
|
||||
+19
-14
@@ -54,7 +54,7 @@ export class LocalStorageManager {
|
||||
// - log utilities
|
||||
|
||||
function createLogger(emoji, color, consoleMethod = 'log') {
|
||||
return function (message, ...args) {
|
||||
return function(message, ...args) {
|
||||
if (window.MTB?.DEBUG) {
|
||||
console[consoleMethod](
|
||||
`%c${emoji} ${message}`,
|
||||
@@ -155,14 +155,16 @@ export function getWidgetType(config) {
|
||||
}
|
||||
export const setupDynamicConnections = (nodeType, prefix, inputType) => {
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
// check if it's a list
|
||||
const inputList = typeof inputType === 'object'
|
||||
nodeType.prototype.onNodeCreated = function() {
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
this.addInput(`${prefix}_1`, inputType)
|
||||
this.addInput(`${prefix}_1`, inputList ? '*' : inputType)
|
||||
return r
|
||||
}
|
||||
|
||||
const onConnectionsChange = nodeType.prototype.onConnectionsChange
|
||||
nodeType.prototype.onConnectionsChange = function (
|
||||
nodeType.prototype.onConnectionsChange = function(
|
||||
type,
|
||||
index,
|
||||
connected,
|
||||
@@ -171,7 +173,7 @@ export const setupDynamicConnections = (nodeType, prefix, inputType) => {
|
||||
const r = onConnectionsChange
|
||||
? onConnectionsChange.apply(this, arguments)
|
||||
: undefined
|
||||
dynamic_connection(this, index, connected, `${prefix}_`, inputType)
|
||||
dynamic_connection(this, index, connected, `${prefix}_`, inputList)
|
||||
}
|
||||
}
|
||||
export const dynamic_connection = (
|
||||
@@ -182,9 +184,12 @@ export const dynamic_connection = (
|
||||
connectionType = 'PSDLAYER',
|
||||
nameArray = [],
|
||||
) => {
|
||||
|
||||
if (!node.inputs[index].name.startsWith(connectionPrefix)) {
|
||||
return
|
||||
}
|
||||
const listConnection = typeof connectionType === 'object'
|
||||
|
||||
// remove all non connected inputs
|
||||
if (!connected && node.inputs.length > 1) {
|
||||
log(`Removing input ${index} (${node.inputs[index].name})`)
|
||||
@@ -198,12 +203,12 @@ export const dynamic_connection = (
|
||||
node.removeInput(index)
|
||||
|
||||
// make inputs sequential again
|
||||
for (let i = 0; i < node.inputs.length; i++) {
|
||||
const name =
|
||||
i < nameArray.length ? nameArray[i] : `${connectionPrefix}${i + 1}`
|
||||
node.inputs[i].label = name
|
||||
node.inputs[i].name = name
|
||||
}
|
||||
// for (let i = 0; i < node.inputs.length; i++) {
|
||||
// const name =
|
||||
// i < nameArray.length ? nameArray[i] : `${connectionPrefix}${i + 1}`
|
||||
// node.inputs[i].label = name
|
||||
// node.inputs[i].name = name
|
||||
// }
|
||||
}
|
||||
|
||||
// add an extra input
|
||||
@@ -216,7 +221,7 @@ export const dynamic_connection = (
|
||||
|
||||
log(`Adding input ${nextIndex + 1} (${name})`)
|
||||
|
||||
node.addInput(name, connectionType)
|
||||
node.addInput(name, listConnection ? '*' : connectionType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +251,7 @@ export function calculateTotalChildrenHeight(parentElement) {
|
||||
*/
|
||||
export function addMenuHandler(nodeType, cb) {
|
||||
const getOpts = nodeType.prototype.getExtraMenuOptions
|
||||
nodeType.prototype.getExtraMenuOptions = function () {
|
||||
nodeType.prototype.getExtraMenuOptions = function() {
|
||||
const r = getOpts.apply(this, arguments)
|
||||
cb.apply(this, arguments)
|
||||
return r
|
||||
@@ -409,7 +414,7 @@ function getBrightness(rgbObj) {
|
||||
(parseInt(rgbObj[0]) * 299 +
|
||||
parseInt(rgbObj[1]) * 587 +
|
||||
parseInt(rgbObj[2]) * 114) /
|
||||
1000,
|
||||
1000,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+14
-11
@@ -11,7 +11,7 @@
|
||||
|
||||
import { api } from '../../scripts/api.js'
|
||||
import { app } from '../../scripts/app.js'
|
||||
import { LocalStorageManager } from "./comfy_shared.js"
|
||||
import { LocalStorageManager } from './comfy_shared.js'
|
||||
const styles = {
|
||||
lighbox: {
|
||||
position: 'fixed',
|
||||
@@ -53,9 +53,9 @@ let currentImageIndex = 0
|
||||
const imageUrls = []
|
||||
|
||||
let image_menu = null
|
||||
const storage = new LocalStorageManager('mtb');
|
||||
const storage = new LocalStorageManager('mtb')
|
||||
|
||||
let activated = storage.get("image_feed", true)
|
||||
let activated = storage.get('image_feed', false)
|
||||
|
||||
app.registerExtension({
|
||||
name: 'mtb.ImageFeed',
|
||||
@@ -71,19 +71,21 @@ app.registerExtension({
|
||||
},
|
||||
},
|
||||
async onChange(value) {
|
||||
storage.set("image_feed", value)
|
||||
storage.set('image_feed', value)
|
||||
activated = value
|
||||
},
|
||||
})
|
||||
},
|
||||
init: async () => {
|
||||
if (!activated) { return }
|
||||
if (!activated) {
|
||||
return
|
||||
}
|
||||
const pythongossFeed = app.extensions.find(
|
||||
(e) => e.name == 'pysssss.ImageFeed'
|
||||
(e) => e.name === 'pysssss.ImageFeed',
|
||||
)
|
||||
if (pythongossFeed) {
|
||||
console.warn(
|
||||
"[mtb] - Aborting the loading of mtb's imageFeed in favor of pysssss.ImageFeed"
|
||||
"[mtb] - Aborting the loading of mtb's imageFeed in favor of pysssss.ImageFeed",
|
||||
)
|
||||
activated = false // just in case other methods are added later on
|
||||
return
|
||||
@@ -114,7 +116,7 @@ app.registerExtension({
|
||||
const lightboxCloseBtn = document.createElement('button')
|
||||
Object.assign(
|
||||
lightboxCloseBtn.style,
|
||||
styles.lightboxBtn({ right: '0', top: '0' })
|
||||
styles.lightboxBtn({ right: '0', top: '0' }),
|
||||
)
|
||||
lightboxCloseBtn.textContent = '❌'
|
||||
|
||||
@@ -184,7 +186,7 @@ app.registerExtension({
|
||||
//- append to DOM
|
||||
document.body.append(imageListContainer)
|
||||
|
||||
showBtn.textContent = '🖼️'
|
||||
showBtn.textContent = '🖼'
|
||||
showBtn.onclick = () => {
|
||||
imageListContainer.style.display = 'block'
|
||||
showBtn.style.display = 'none'
|
||||
@@ -250,8 +252,9 @@ app.registerExtension({
|
||||
objectFit: 'cover',
|
||||
})
|
||||
|
||||
img.src = `/view?filename=${encodeURIComponent(src.filename)}&type=${src.type
|
||||
}&subfolder=${encodeURIComponent(src.subfolder)}`
|
||||
img.src = `/view?filename=${encodeURIComponent(src.filename)}&type=${
|
||||
src.type
|
||||
}&subfolder=${encodeURIComponent(src.subfolder)}`
|
||||
|
||||
imageUrls.push(img.src)
|
||||
|
||||
|
||||
+5
-1
@@ -20,7 +20,7 @@ import * as THREE from './extern/three.module.js'
|
||||
import { log } from './comfy_shared.js'
|
||||
|
||||
// NOTE: new widget types registered by MTB Widgets
|
||||
const newTypes = [, /*'BOOL'*/ 'COLOR', 'BBOX']
|
||||
const newTypes = [/*'BOOL'n,*/ 'COLOR', 'BBOX']
|
||||
|
||||
const deprecated_nodes = {
|
||||
// 'Animation Builder':
|
||||
@@ -1060,6 +1060,10 @@ const mtb_widgets = {
|
||||
shared.setupDynamicConnections(nodeType, 'var', '*')
|
||||
break
|
||||
}
|
||||
case 'Save Data Bundle (mtb)': {
|
||||
shared.setupDynamicConnections(nodeType, 'data', '*') // [MASK,IMAGE]
|
||||
break
|
||||
}
|
||||
case 'Add To Playlist (mtb)': {
|
||||
shared.setupDynamicConnections(nodeType, 'video', 'VIDEO')
|
||||
break
|
||||
|
||||
+3
-3
@@ -140,9 +140,6 @@ const themes = [
|
||||
'vscode',
|
||||
]
|
||||
class NotePlus extends LiteGraph.LGraphNode {
|
||||
title = 'Note+ (mtb)'
|
||||
category = 'mtb/utils'
|
||||
|
||||
// same values as the comfy note
|
||||
color = LGraphCanvas.node_colors.yellow.color
|
||||
bgcolor = LGraphCanvas.node_colors.yellow.bgcolor
|
||||
@@ -692,6 +689,9 @@ app.registerExtension({
|
||||
registerCustomNodes() {
|
||||
LiteGraph.registerNodeType('Note Plus (mtb)', NotePlus)
|
||||
|
||||
NotePlus.category = 'mtb/utils'
|
||||
NotePlus.title = 'Note+ (mtb)'
|
||||
|
||||
NotePlus.title_mode = LiteGraph.NO_TITLE
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user