create range and cast nodes
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
+1
-1
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user