Merge branch 'main' into dev/uv-tools

This commit is contained in:
Mel Massadian
2024-04-01 14:13:58 +02:00
7 changed files with 77 additions and 48 deletions
+6 -4
View File
@@ -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://dcbadge.vercel.app/api/server/AXhsabmDhn?style=flat)](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:
+6
View File
@@ -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://dcbadge.vercel.app/api/server/AXhsabmDhn?style=flat)](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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
},
})