From df0a98b94a4a9388811bc8786e820ec892919c1a Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Sat, 23 Mar 2024 22:04:05 +0100 Subject: [PATCH 1/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20make=20image=20feed?= =?UTF-8?q?=20of=20by=20default?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Still here, just reverting the default. Local Storage on some context isn't perserved so I will use some fallback but in the meantime this is better off. --- web/imageFeed.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/web/imageFeed.js b/web/imageFeed.js index c5894e4..626fec6 100644 --- a/web/imageFeed.js +++ b/web/imageFeed.js @@ -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) From 9ce34b47fd99b18db7997ccce44e6063f00b6801 Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Mon, 25 Mar 2024 00:57:10 +0100 Subject: [PATCH 2/7] =?UTF-8?q?docs:=20=F0=9F=93=9A=20add=20banodoco=20cha?= =?UTF-8?q?nnel=20link?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/bug_report.yml | 10 ++++++---- README.md | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 3af1031..c159071 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -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)](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: diff --git a/README.md b/README.md index 4448a34..1e8c335 100644 --- a/README.md +++ b/README.md @@ -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)](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: dynamic inputs + # Node List From 991af4f45ff8c660b2c45466bb219186699170ed Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Mon, 25 Mar 2024 01:01:14 +0100 Subject: [PATCH 3/7] =?UTF-8?q?docs:=20=F0=9F=93=9A=20use=20flat=20icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c159071..c00daf8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -13,7 +13,7 @@ body: - 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)](https://discord.gg/IAXhsabmDhn) + [![](https://dcbadge.vercel.app/api/server/AXhsabmDhn?style=flat)](https://discord.gg/IAXhsabmDhn) ### Try using the debug mode to get more info diff --git a/README.md b/README.md index 1e8c335..8204aff 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ [**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)](https://discord.gg/IAXhsabmDhn) +[![](https://dcbadge.vercel.app/api/server/AXhsabmDhn?style=flat)](https://discord.gg/IAXhsabmDhn) --- From eeac8c002ad1f9e461418fb66b9338e969259e58 Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Thu, 28 Mar 2024 20:17:02 +0100 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20add=20category=20for?= =?UTF-8?q?=20virtual=20note+?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Should fix: https://github.com/Nuked88/ComfyUI-N-Sidebar/issues/19 --- web/note_plus.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/note_plus.js b/web/note_plus.js index ff89108..e3c206f 100644 --- a/web/note_plus.js +++ b/web/note_plus.js @@ -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 }, }) From 9a4b27d2e05e8ebe31f58a21db94bd3a54ed23d9 Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Mon, 1 Apr 2024 13:57:01 +0200 Subject: [PATCH 5/7] =?UTF-8?q?fix:=20=F0=9F=90=9B=20allow=20smaller=20val?= =?UTF-8?q?ues=20in=20BatchTransform?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using a smaller step to avoid 0 division on low values. Also added some typing --- nodes/batch.py | 55 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/nodes/batch.py b/nodes/batch.py index 1d4abc1..d301a84 100644 --- a/nodes/batch.py +++ b/nodes/batch.py @@ -206,8 +206,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) @@ -351,13 +354,13 @@ class Batch2dTransform: def transform_batch( self, image: torch.Tensor, - border_handling, - constant_color, - x=None, - y=None, - zoom=None, - angle=None, - shear=None, + border_handling: str, + constant_color: str, + x: list[float] | None = None, + y: list[float] | None = None, + zoom: list[float] | None = None, + angle: list[float] | None = None, + shear: list[float] | None = None, ): if all( self.get_num_elements(param) <= 0 @@ -367,19 +370,25 @@ 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: + if x and self.get_num_elements(x) > 0: keyframes["x"] = x - if self.get_num_elements(y) > 0: + if y and self.get_num_elements(y) > 0: keyframes["y"] = y - if self.get_num_elements(zoom) > 0: + if zoom and self.get_num_elements(zoom) > 0: keyframes["zoom"] = zoom - if self.get_num_elements(angle) > 0: + if angle and self.get_num_elements(angle) > 0: keyframes["angle"] = angle - if self.get_num_elements(shear) > 0: + if shear and self.get_num_elements(shear) > 0: keyframes["shear"] = shear for name, values in keyframes.items(): @@ -585,10 +594,12 @@ class BatchShake: interpolant: The interpolation function, defaults to t*t*t*(t*(t*6 - 15) + 10). - Returns: + Returns + ------- A numpy array of shape shape with the generated noise. - Raises: + Raises + ------ ValueError: If shape is not a multiple of res. """ interpolant = interpolant or DEFAULT_INTERPOLANT @@ -651,11 +662,13 @@ class BatchShake: interpolant: The, interpolation function, defaults to t*t*t*(t*(t*6 - 15) + 10). - Returns: + Returns + ------- A numpy array of fractal noise and of shape shape generated by combining several octaves of perlin noise. - Raises: + Raises + ------ ValueError: If shape is not a multiple of (lacunarity**(octaves-1)*res). """ From 71bfdd61d731ce15f9bd0bb19d65b5af208d5dcf Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Mon, 1 Apr 2024 13:59:20 +0200 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20=F0=9F=A7=B9=20wip=20dynamic=20mul?= =?UTF-8?q?titype?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This just allow to pass a list of types to dynamic widgets. Not used yet. The idea is to use "*" but then limit it to the given types. Used in SaveDataBundle --- web/comfy_shared.js | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/web/comfy_shared.js b/web/comfy_shared.js index 3ab6522..03ea3f7 100644 --- a/web/comfy_shared.js +++ b/web/comfy_shared.js @@ -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, ) } From edd7c3f5d075b640e9cdb067ebfe51c42ff61791 Mon Sep 17 00:00:00 2001 From: Mel Massadian Date: Mon, 1 Apr 2024 14:09:21 +0200 Subject: [PATCH 7/7] =?UTF-8?q?chore:=20=F0=9F=A7=B9=20add=20savedatabundl?= =?UTF-8?q?e=20js=20part?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wip --- web/mtb_widgets.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/web/mtb_widgets.js b/web/mtb_widgets.js index 2962d90..90300eb 100644 --- a/web/mtb_widgets.js +++ b/web/mtb_widgets.js @@ -17,7 +17,7 @@ import * as shared from './comfy_shared.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': @@ -897,6 +897,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