From 2f8a36f0258e9e2aa021dc077718ac6778734ae5 Mon Sep 17 00:00:00 2001 From: godmt <55956803+godmt@users.noreply.github.com> Date: Tue, 24 Sep 2024 18:34:56 +0900 Subject: [PATCH] create range and cast nodes --- js/web.js | 202 ++++++++++++++++++--- nodes.py | 469 ++++++++++++++++++++++++++++++------------------- pyproject.toml | 2 +- 3 files changed, 463 insertions(+), 210 deletions(-) diff --git a/js/web.js b/js/web.js index f7cbc53..62d1347 100644 --- a/js/web.js +++ b/js/web.js @@ -1,20 +1,20 @@ // https://gist.github.com/Amorano/9871fb3be1aa75defdfad013e1f95e0e -import { app } from "../../scripts/app.js"; -// import { api } from "../../scripts/api.js"; -import { ComfyWidgets } from "../../scripts/widgets.js"; -// import { addConnectionLayoutSupport } from "./utils.js"; +import { app } from "../../scripts/app.js" +// import { api } from "../../scripts/api.js" +import { ComfyWidgets } from "../../scripts/widgets.js" +// import { addConnectionLayoutSupport } from "./utils.js" -const _prefix = 'value'; +const _prefix = 'value' const TypeSlot = { Input: 1, Output: 2, -}; +} const TypeSlotEvent = { Connect: true, Disconnect: false, -}; +} const dynamic_connection = (node, index, event, prefix = 'in_', type = '*', names = [] ) => { @@ -51,11 +51,29 @@ const dynamic_connection = (node, index, event, prefix = 'in_', type = '*', name } } +/** + * Get all unique types in the workflow. + * @returns {Set} Unique set of all types used in the workflow + */ +function getWorkflowTypes(app) { + // 実装 + const types = new Set(["*", "STRING", "INT", "FLOAT", "IMAGE", "LATENT", "MASK", "NOISE", "SAMPLER", "SIGMAS", "GUIDER", "MODEL", "CLIP", "VAE", "CONDITIONING"]) + app.graph._nodes.forEach(node => { + node.inputs.forEach(slot => { + types.add(slot.type) + }) + node.outputs.forEach(slot => { + types.add(slot.type) + }) + }) + return Array.from(types) +} + app.registerExtension({ name: "godmt.ListUtils", async beforeRegisterNodeDef(nodeType, nodeData, app) { - if (nodeData.name === "GODMT_Pack" || nodeData.name === "GODMT_CreateList" || nodeData.name == "GODMT_CreateBatch") { + if (nodeData.name === "GODMT_Pack" || nodeData.name == "GODMT_CreateBatch") { const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined @@ -93,13 +111,80 @@ app.registerExtension({ this.inputs[slot].label = `${_prefix}_${slot + 1}` } } - return me; + return me } - } else if (nodeData.name === "GODMT_CreateStringList") { + } else if (nodeData.name === "GODMT_CreateList" || nodeData.name === "GODMT_MergeList") { const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined - this.addInput(`${_prefix}_1`, 'STRING') + this.addInput(`${_prefix}_1`, '*') + return r + } + + // TODO might be buggy on load + // on copy, paste, load + const onConfigure = nodeType.prototype.onConfigure + nodeType.prototype.onConfigure = function () { + const r = onConfigure ? onConfigure.apply(this, arguments) : undefined + if (!app.configuringGraph && this.inputs) { + const length = this.inputs.length + for (let i = length - 1; i >= 0; i--) { + this.removeInput(i) + } + this.addInput(`${_prefix}_1`, '*') + } + return r + } + + const onConnectionsChange = nodeType.prototype.onConnectionsChange + nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) { + const me = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined + if (slotType === TypeSlot.Input) { + if (!this.inputs[slot].name.startsWith(_prefix)) { + return + } + + if (event == TypeSlotEvent.Connect && link_info) { + if (slot == 0) { + const node = app.graph.getNodeById(link_info.origin_id) + const origin_type = node.outputs[link_info.origin_slot].type + this.inputs[0].type = origin_type + this.outputs[0].type = origin_type + this.outputs[0].label = origin_type + this.outputs[0].name = origin_type + } + } + + // remove all non connected inputs + if (event == TypeSlotEvent.Disconnect && this.inputs.length > 0) { + if (this.widgets) { + const widget = this.widgets.find((w) => w.name === this.inputs[slot].name) + if (widget) { + widget.onRemoved?.() + this.widgets.length = this.widgets.length - 1 + } + } + this.removeInput(slot) + // make inputs sequential again + for (let i = 0; i < this.inputs.length; i++) { + this.inputs[i].label = `${_prefix}_${i + 1}` + this.inputs[i].name = `${_prefix}_${i + 1}` + } + } + + // add an extra input + if (this.inputs[this.inputs.length - 1].link != undefined) { + const nextIndex = this.inputs.length + this.addInput(`${_prefix}_${nextIndex + 1}`, this.inputs[0].type) + } + } + return me + } + } else if (nodeData.name == "GODMT_MergeBatch") { + const onNodeCreated = nodeType.prototype.onNodeCreated + nodeType.prototype.onNodeCreated = function () { + const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined + this.addInput(`${_prefix}_1`, 'LIST') return r } @@ -112,7 +197,7 @@ app.registerExtension({ for (let i = length - 1; i >= 0; i--) { this.removeInput(i) } - this.addInput(`${_prefix}_1`, 'STRING') + this.addInput(`${_prefix}_1`, 'LIST') } return r } @@ -121,7 +206,7 @@ app.registerExtension({ nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) { const me = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined if (slotType === TypeSlot.Input) { - dynamic_connection(this, slot, event, `${_prefix}_`, 'STRING') + dynamic_connection(this, slot, event, `${_prefix}_`, 'LIST') if (event === TypeSlotEvent.Connect && link_info) { const fromNode = this.graph._nodes.find( (otherNode) => otherNode.id == link_info.origin_id @@ -129,11 +214,11 @@ app.registerExtension({ const type = fromNode.outputs[link_info.origin_slot].type this.inputs[slot].type = type } else if (event === TypeSlotEvent.Disconnect) { - this.inputs[slot].type = 'STRING' + this.inputs[slot].type = 'LIST' this.inputs[slot].label = `${_prefix}_${slot + 1}` } } - return me; + return me } } else if (nodeData.name === "GODMT_Unpack") { const onNodeCreated = nodeType.prototype.onNodeCreated @@ -159,7 +244,7 @@ app.registerExtension({ this.addOutput(`${_prefix}_1`, "*") } this.outputs[0].type = "*" - const output_len = this.outputs.length; + const output_len = this.outputs.length for (let i = output_len - 1; i > 0; i--) { this.removeOutput(i) } @@ -198,19 +283,86 @@ app.registerExtension({ } } - return me; + return me + } + } else if (nodeData.name == "GODMT_AnyCast") { + const onNodeCreated = nodeType.prototype.onNodeCreated + nodeType.prototype.onNodeCreated = function () { + const me = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined + const onWidgetChanged = this.widgets[0].callback + const thisNode = this + this.widgets[0].callback = function () { + const me = onWidgetChanged ? onWidgetChanged.apply(this, arguments) : undefined + const output_type = thisNode.widgets[0].value + thisNode.outputs[0].type = output_type + thisNode.outputs[0].label = output_type + thisNode.outputs[0].name = output_type + return me + } + return me + } + // on copy, paste, load + const onConfigure = nodeType.prototype.onConfigure + nodeType.prototype.onConfigure = function () { + const me = onConfigure ? onConfigure.apply(this, arguments) : undefined + const output_type = this.widgets[0].value + this.outputs[0].type = output_type + this.outputs[0].label = output_type + this.outputs[0].name = output_type + return me + } + const onConnectionsChange = nodeType.prototype.onConnectionsChange + nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) { + const me = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined + if (slotType === TypeSlot.Input) { + if (event === TypeSlotEvent.Connect && link_info) { + const origin_node = app.graph.getNodeById(link_info.origin_id) + const origin_slot = origin_node.outputs[link_info.origin_slot] + const origin_type = origin_slot.type + const types = getWorkflowTypes(app) + this.widgets[0].options.values = types + const output_type = this.widgets[0].value + this.outputs[0].type = output_type + this.outputs[0].label = output_type + this.outputs[0].name = origin_type + } else if (event === TypeSlotEvent.Disconnect) { + this.outputs[0].type = "*" + this.outputs[0].label = "*" + this.outputs[0].name = "*" + } + } + return me } } else if (nodeData.name === "GODMT_GetShape") { - const onNodeCreated = nodeType.prototype.onNodeCreated; + const onNodeCreated = nodeType.prototype.onNodeCreated nodeType.prototype.onNodeCreated = function () { - onNodeCreated ? onNodeCreated.apply(this, []) : undefined; - this.showValueWidget = ComfyWidgets["STRING"](this, "WHBC", ["STRING", { multiline: false }], app).widget; - }; - const onExecuted = nodeType.prototype.onExecuted; + onNodeCreated ? onNodeCreated.apply(this, []) : undefined + this.showValueWidget = ComfyWidgets["STRING"](this, "WHBC", ["STRING", { multiline: false }], app).widget + } + const onExecuted = nodeType.prototype.onExecuted nodeType.prototype.onExecuted = function (message) { - onExecuted === null || onExecuted === void 0 ? void 0 : onExecuted.apply(this, [message]); - this.showValueWidget.value = message.text[0]; - }; + onExecuted === null || onExecuted === void 0 ? void 0 : onExecuted.apply(this, [message]) + this.showValueWidget.value = message.text[0] + } + } else if (nodeData.name === "GODMT_ListGetByIndex" || nodeData.name === "GODMT_ListSlice") { + const onConnectionsChange = nodeType.prototype.onConnectionsChange + nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) { + const me = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined + if (slotType === TypeSlot.Input) { + if (event === TypeSlotEvent.Connect && link_info) { + const node = app.graph.getNodeById(link_info.origin_id) + let origin_type = node.outputs[link_info.origin_slot].type + this.outputs[0].type = origin_type + this.outputs[0].label = origin_type + this.outputs[0].name = origin_type + } else if (event === TypeSlotEvent.Disconnect) { + this.outputs[0].type = "*" + this.outputs[0].label = "*" + this.outputs[0].name = "*" + } + } + return me + } } } }) diff --git a/nodes.py b/nodes.py index ac82511..023ac42 100644 --- a/nodes.py +++ b/nodes.py @@ -1,3 +1,4 @@ +import numpy as np import itertools @@ -91,35 +92,7 @@ class SplitString: return (result, result, length) -class StringListSelectByIndex: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "STRING": ("STRING", {"forceInput": True}), - "index": ("INT", {"forceInput": False, "default": 0}), - } - } - - TITLE = "String List: Select By Index" - RETURN_TYPES = ("STRING", ) - RETURN_NAMES = ("STRING", ) - INPUT_IS_LIST = True - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, STRING: list[str], index: list[int]): - index = index[0] - if index >= len(STRING): - print("Error: index out of range") - return ("", ) - return (STRING[index], ) - - -class ListSelectByIndex: +class ListGetByIndex: def __init__(self): pass @@ -132,7 +105,7 @@ class ListSelectByIndex: } } - TITLE = "List: Select By Index" + TITLE = "List: Get By Index" RETURN_TYPES = (ANY_TYPE, ) INPUT_IS_LIST = True FUNCTION = "run" @@ -146,7 +119,7 @@ class ListSelectByIndex: return (ANY[index], ) -class BatchSelectByIndex: +class BatchGetByIndex: def __init__(self): pass @@ -159,7 +132,7 @@ class BatchSelectByIndex: } } - TITLE = "Batch: Select By Index" + TITLE = "Batch: Get By Index" RETURN_TYPES = (ANY_TYPE, ) FUNCTION = "run" CATEGORY = "list_utils" @@ -171,36 +144,6 @@ class BatchSelectByIndex: return (LIST[index], ) -class StringListSlice: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "STRING": ("STRING", {"forceInput": True}), - "start": ("INT", {"default": 0}), - "end": ("INT", {"default": 0, "min": -9007199254740991}), - } - } - - TITLE = "String List: Slice" - RETURN_TYPES = ("STRING", ) - RETURN_NAMES = ("STRING", ) - INPUT_IS_LIST = True - OUTPUT_IS_LIST = (True, ) - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, STRING: list[str], start: list[int], end: list[int]): - start = start[0] - end = end[0] - if end == 0: - return (STRING[start:], ) - return (STRING[start:end], ) - - class ListSlice: def __init__(self): pass @@ -209,8 +152,8 @@ class ListSlice: def INPUT_TYPES(s): return { "required": { - "ANY": ("ANY_TYPE", {"forceInput": True}), - "start": ("INT", {"default": 0}), + "ANY": (ANY_TYPE, {"forceInput": True}), + "start": ("INT", {"default": 0, "min": -9007199254740991}), "end": ("INT", {"default": 0, "min": -9007199254740991}), } } @@ -239,7 +182,7 @@ class BatchSlice: return { "required": { "LIST": ("LIST", {"forceInput": True}), - "start": ("INT", {"default": 0}), + "start": ("INT", {"default": 0, "min": -9007199254740991}), "end": ("INT", {"default": 0, "min": -9007199254740991}), } } @@ -255,53 +198,6 @@ class BatchSlice: return (LIST[start:end], ) -class BatchToStringList: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "LIST": ("LIST", ), - } - } - - TITLE = "Batch To String List" - RETURN_TYPES = ("STRING", ) - RETURN_NAMES = ("STRING", ) - OUTPUT_IS_LIST = (True,) - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, LIST: list): - str_list = [str(i) for i in LIST] - return (str_list, ) - - -class StringListToBatch: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "STRING": ("STRING", {"forceInput": True}), - } - } - - TITLE = "String List To Batch" - RETURN_TYPES = ("LIST", ) - RETURN_NAMES = ("LIST", ) - INPUT_IS_LIST = True - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, STRING: list[str]): - return (STRING, ) - - class BatchToList: def __init__(self): pass @@ -443,6 +339,151 @@ class CreateBatch: return (output_list, ) +class MergeList: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": {}, + "optional": {}, + "hidden": { + "unique_id": "UNIQUE_ID", + "prompt": "PROMPT", + "extra_pnginfo": "EXTRA_PNGINFO", + }, + } + + TITLE = "Merge List" + INPUT_IS_LIST = True + RETURN_TYPES = (ANY_TYPE, ) + OUTPUT_IS_LIST = (True, ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, unique_id, prompt, extra_pnginfo, **kwargs): + unique_id = unique_id[0] + prompt = prompt[0] + extra_pnginfo = extra_pnginfo[0] + node_list = extra_pnginfo["workflow"]["nodes"] # list of dict including id, type + cur_node = next(n for n in node_list if str(n["id"]) == unique_id) + output_list = [] + for k, v in kwargs.items(): + if k.startswith(PACK_PREFIX): + output_list += v + return (output_list, ) + + +class MergeBatch: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": {}, + "optional": {}, + "hidden": { + "unique_id": "UNIQUE_ID", + "prompt": "PROMPT", + "extra_pnginfo": "EXTRA_PNGINFO", + }, + } + + TITLE = "Merge Batch" + RETURN_TYPES = ("LIST", ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, unique_id, prompt, extra_pnginfo, **kwargs): + node_list = extra_pnginfo["workflow"]["nodes"] # list of dict including id, type + cur_node = next(n for n in node_list if str(n["id"]) == unique_id) + output_list = [] + for k, v in kwargs.items(): + if k.startswith(PACK_PREFIX): + output_list += v + return (output_list, ) + + +class CreateRange: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start": ("INT", {"default": 0, "min": -9007199254740991}), + "stop": ("INT", {"default": 1, "min": -9007199254740991}), + "step": ("INT", {"default": 1, "min": -9007199254740991}), + }, + } + + TITLE = "Create Range" + RETURN_TYPES = ("INT", "LIST", "INT") + RETURN_NAMES = ("INT", "LIST", "length") + OUTPUT_IS_LIST = (True, False, False, ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, start: int, stop: int, step: int): + range_list = list(range(start, stop, step)) + return (range_list, range_list, len(range_list)) + + +class CreateArange: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start": ("FLOAT", {"default": 0}), + "stop": ("FLOAT", {"default": 1}), + "step": ("FLOAT", {"default": 1}), + }, + } + + TITLE = "Create Arange" + RETURN_TYPES = ("FLOAT", "LIST", "INT") + RETURN_NAMES = ("FLOAT", "LIST", "length") + OUTPUT_IS_LIST = (True, False, False, ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, start: float, stop: float, step: float): + range_list = list(np.arange(start, stop, step)) + return (range_list, range_list, len(range_list)) + + +class CreateLinspace: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "start": ("FLOAT", {"default": 0}), + "stop": ("FLOAT", {"default": 1}), + "num": ("INT", {"default": 10, "min": 2}), + }, + } + + TITLE = "Create Linspace" + RETURN_TYPES = ("FLOAT", "LIST", "INT") + RETURN_NAMES = ("FLOAT", "LIST", "length") + OUTPUT_IS_LIST = (True, False, False, ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, start: float, stop: float, num: int): + range_list = list(np.linspace(start, stop, num)) + return (range_list, range_list, len(range_list)) + + PACK_PREFIX = 'value' class Pack: def __init__(self): @@ -522,69 +563,6 @@ class Unpack: return tuple(outputs) -class AnyToDict: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "ANY" : (ANY_TYPE, {}), - }, - } - - TITLE = "Any To Dict" - RETURN_TYPES = ("DICT", "STRING") - RETURN_NAMES = ("DICT", "str()") - OUTPUT_NODE = True - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, ANY): - if type(ANY) is dict: - return (ANY, str(ANY)) - elif not hasattr(ANY, '__dict__'): - print(f"Object of type {type(ANY).__name__} doesn't have a __dict__ attribute") - return ({}, str(ANY)) - else: - return (vars(ANY), str(ANY)) - - -class GetWidgetsValues: - def __init__(self): - pass - - @classmethod - def INPUT_TYPES(s): - return { - "required": { - "ANY" : (ANY_TYPE, {}), - }, - "hidden": { - "unique_id": "UNIQUE_ID", - "prompt": "PROMPT", - "extra_pnginfo": "EXTRA_PNGINFO", - }, - } - - TITLE = "Get Widgets Values" - RETURN_TYPES = ("LIST", ) - RETURN_NAMES = ("LIST", ) - OUTPUT_NODE = True - FUNCTION = "run" - CATEGORY = "list_utils" - - def run(self, ANY, unique_id, prompt, extra_pnginfo): - node_list = extra_pnginfo["workflow"]["nodes"] # list of dict including id, type - cur_node = next(n for n in node_list if str(n["id"]) == unique_id) - link_id = cur_node["inputs"][0]["link"] - link = next(l for l in extra_pnginfo["workflow"]["links"] if l[0] == link_id) - in_node_id, in_socket_id = link[1], link[2] - in_node = next(n for n in node_list if n["id"] == in_node_id) - return (in_node["widgets_values"], ) - - class GetLength: def __init__(self): pass @@ -670,25 +648,148 @@ class GetShape: return { "ui": {"text": (f"{W}, {H}, {B}, {C}",)}, "result": (W, H, B, C) } +class AnyToDict: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "ANY" : (ANY_TYPE, {}), + }, + } + + TITLE = "Any To Dict" + RETURN_TYPES = ("DICT", "STRING") + RETURN_NAMES = ("DICT", "str()") + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, ANY): + if type(ANY) is dict: + return (ANY, str(ANY)) + elif not hasattr(ANY, '__dict__'): + print(f"Object of type {type(ANY).__name__} doesn't have a __dict__ attribute") + return ({}, str(ANY)) + else: + return (vars(ANY), str(ANY)) + + +class GetWidgetsValues: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "ANY" : (ANY_TYPE, {}), + }, + "hidden": { + "unique_id": "UNIQUE_ID", + "prompt": "PROMPT", + "extra_pnginfo": "EXTRA_PNGINFO", + }, + } + + TITLE = "Get Widgets Values" + RETURN_TYPES = ("LIST", ) + RETURN_NAMES = ("LIST", ) + OUTPUT_NODE = True + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, ANY, unique_id, prompt, extra_pnginfo): + node_list = extra_pnginfo["workflow"]["nodes"] # list of dict including id, type + cur_node = next(n for n in node_list if str(n["id"]) == unique_id) + link_id = cur_node["inputs"][0]["link"] + link = next(l for l in extra_pnginfo["workflow"]["links"] if l[0] == link_id) + in_node_id, in_socket_id = link[1], link[2] + in_node = next(n for n in node_list if n["id"] == in_node_id) + return (in_node["widgets_values"], ) + + +class AnyCast: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "ANY" : (ANY_TYPE, {}), + "TYPE": (["*", "STRING", "INT", "FLOAT", "IMAGE", "LATENT", "MASK", "NOISE", "SAMPLER", "SIGMAS", "GUIDER", "MODEL", "CLIP", "VAE", "CONDITIONING"], {}), + }, + } + + TITLE = "Any Cast" + RETURN_TYPES = (ANY_TYPE,) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, ANY, TYPE): + result = ANY + if TYPE == "STRING": + result = str(ANY) + elif TYPE == "INT": + result = int(ANY) + elif TYPE == "FLOAT" or TYPE == "NUMBER": + result = float(ANY) + return (result, ) + + +class BatchItemCast: + def __init__(self): + pass + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "LIST": ("LIST", {"forceInput": True}), + "TYPE": (["STRING", "INT", "FLOAT", "NUMBER"], {}), + }, + } + + TITLE = "Batch Item Cast" + RETURN_TYPES = ("LIST", ) + RETURN_NAMES = ("LIST", ) + FUNCTION = "run" + CATEGORY = "list_utils" + + def run(self, LIST: list, TYPE: str): + converted_list = [] + if TYPE == "STRING": + converted_list = [str(v) for v in LIST] + elif TYPE == "INT": + converted_list = [int(v) for v in LIST] + elif TYPE == "FLOAT" or TYPE == "NUMBER": + converted_list = [float(v) for v in LIST] + return (converted_list, ) + + NODE_CLASS_MAPPINGS = { "GODMT_SplitString": SplitString, - "GODMT_StringListSelectByIndex": StringListSelectByIndex, - "GODMT_ListSelectByIndex": ListSelectByIndex, - "GODMT_BatchSelectByIndex": BatchSelectByIndex, - "GODMT_StringListSlice": StringListSlice, + "GODMT_ListGetByIndex": ListGetByIndex, + "GODMT_BatchGetByIndex": BatchGetByIndex, "GODMT_ListSlice": ListSlice, "GODMT_BatchSlice": BatchSlice, - "GODMT_BatchToStringList": BatchToStringList, - "GODMT_StringListToBatch": StringListToBatch, - "GODMT_BatchToList": BatchToList, "GODMT_ListToBatch": ListToBatch, - "GODMT_CreateStringList": CreateStringList, + "GODMT_BatchToList": BatchToList, "GODMT_CreateList": CreateList, "GODMT_CreateBatch": CreateBatch, + "GODMT_MergeList": MergeList, + "GODMT_MergeBatch": MergeBatch, + "GODMT_CreateRange": CreateRange, + "GODMT_CreateArange": CreateArange, + "GODMT_CreateLinspace": CreateLinspace, "GODMT_Pack": Pack, "GODMT_Unpack": Unpack, - "GODMT_AnyToDict": AnyToDict, "GODMT_GetLength": GetLength, "GODMT_GetShape": GetShape, + "GODMT_AnyToDict": AnyToDict, "GODMT_GetWidgetsValues": GetWidgetsValues, + "GODMT_AnyCast": AnyCast, + "GODMT_BatchItemCast": BatchItemCast, } diff --git a/pyproject.toml b/pyproject.toml index 8fc01f9..4b59f92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-list-utils" description = "LIST and BATCH utilities which support: create, convert, get or slice items" -version = "1.0.1" +version = "1.1.0" license = { file = "LICENSE" } [project.urls]