update README en/ja and description & tooltips
This commit is contained in:
+166
@@ -0,0 +1,166 @@
|
||||
# ComfyUI-List-Utils
|
||||
|
||||
[English](README.md)
|
||||
|
||||
ComfyUI で「複数の値を順番に処理する」「Python の list 値としてまとめて扱う」「型つきの値セットを受け渡す」ためのプリミティブなカスタムノード集です。
|
||||
|
||||
この拡張では、似ているけれど役割が違う 3 種類のコンテナを扱います。
|
||||
|
||||
| 名前 | 意味 | 主な用途 |
|
||||
| --- | --- | --- |
|
||||
| `List` | ComfyUI 公式の Data list / List processing | 複数の値を ComfyUI の逐次処理として流す |
|
||||
| `PyList` | 生の Python `list` 値 | 値の配列を 1 つの値として保持・加工する |
|
||||
| `Pack` | List-Utils 独自の、型情報つきコンテナ | 複数の異なる型の値をまとめて渡し、後で元の型で取り出す |
|
||||
|
||||
## Installation
|
||||
|
||||
`ComfyUI/custom_nodes` ディレクトリで clone して、ComfyUI を再起動してください。
|
||||
|
||||
```bash
|
||||
git clone https://github.com/godmt/ComfyUI-List-Utils.git
|
||||
```
|
||||
|
||||
ノードは `list_utils` カテゴリに追加されます。
|
||||
|
||||
## GUI Help
|
||||
|
||||
各ノードには ComfyUI 上で確認できる説明を追加しています。
|
||||
|
||||
- ノード自体の説明は、ノードにマウスを重ねたときの説明として表示されます。
|
||||
- widget / input には、用途を説明する tooltip を追加しています。
|
||||
- output には、何が出力されるかを説明する tooltip を追加しています。
|
||||
- `Create List`、`Create PyList`、`Merge List`、`Merge PyList`、`Pack`、`Exec` の動的入力にも tooltip が付きます。
|
||||
|
||||
## List / PyList / Pack の使い分け
|
||||
|
||||
### List
|
||||
|
||||
`List` は ComfyUI の List processing 用です。たとえば 10 個の prompt、seed、画像、パスなどを順番に処理したいときに使います。
|
||||
|
||||
List-Utils の `List` 系ノードは、ComfyUI の `OUTPUT_IS_LIST` / `INPUT_IS_LIST` を使います。出力ソケットの型は `STRING`、`INT`、`IMAGE` など元の型として扱われます。
|
||||
|
||||
よく使う場面:
|
||||
|
||||
- 複数の文字列を 1 件ずつ downstream ノードへ流す
|
||||
- `Create Range` で連番 seed を作る
|
||||
- `List Dir` でファイルパスを列挙して順番に処理する
|
||||
- `List: Get By Index` / `List: Slice` で ComfyUI List を取り出す
|
||||
|
||||
### PyList
|
||||
|
||||
`PyList` は Python の `list` そのものを 1 つの値として受け渡す型です。ComfyUI の逐次処理にはならず、配列をまとめたまま扱いたいときに使います。
|
||||
|
||||
よく使う場面:
|
||||
|
||||
- 文字列や数値の配列をまとめて保持する
|
||||
- Python list として index / slice / merge / cast する
|
||||
- `List To PyList` で ComfyUI List を 1 つの Python list にまとめる
|
||||
- `PyList To List` で Python list を ComfyUI の逐次処理へ戻す
|
||||
|
||||
### Pack
|
||||
|
||||
`Pack` は複数の値を 1 本の `PACK` ソケットにまとめるためのコンテナです。各入力の値だけでなく、入力名と ComfyUI の型も保持します。
|
||||
|
||||
`Pack` / `Unpack` は、型の違う値をまとめて受け渡したいときに便利です。たとえば `MODEL`、`CLIP`、`VAE`、`CONDITIONING`、`IMAGE` のように、通常は 1 つの list に入れづらい値をまとめて運べます。
|
||||
|
||||
## Typical Workflows
|
||||
|
||||
### 文字列を分割して順番に処理する
|
||||
|
||||
1. `Split String` に複数行テキストや区切り文字つきテキストを入力します。
|
||||
2. `STRING` 出力を使うと、ComfyUI の `List` として順番に流れます。
|
||||
3. `PYLIST` 出力を使うと、Python list 値としてまとめて扱えます。
|
||||
4. `length` 出力で要素数を取得できます。
|
||||
|
||||
### PyList を ComfyUI List に変換する
|
||||
|
||||
1. `Create PyList`、`Split String`、`Create Range` などで `PYLIST` を作ります。
|
||||
2. `PyList To List` に接続します。
|
||||
3. 出力は ComfyUI の `List` になり、下流で逐次処理できます。
|
||||
|
||||
逆に、ComfyUI の `List` を Python list としてまとめたい場合は `List To PyList` を使います。
|
||||
|
||||
### 複数の型をまとめて渡す
|
||||
|
||||
1. `Pack` に値を接続します。
|
||||
2. 最後の空ソケットに接続すると、次の入力ソケットが自動で追加されます。
|
||||
3. `Unpack` に接続すると、`Pack` 側の入力数と型に合わせて出力が作られます。
|
||||
|
||||
`Unpack` は一度 `Pack` に接続すると出力型を確定できます。`Switch` ノードや `Anything Everywhere` 系ノードを間に挟んだ構成でも、上流の `Pack` をたどれる場合は型を復元できます。
|
||||
|
||||
## Nodes
|
||||
|
||||
### Create / Generate
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Split String` | `STRING` List, `PYLIST`, `length` | 文字列を delimiter または行で分割します。空要素は除去されます。 |
|
||||
| `Create List` | `List` | 複数入力を ComfyUI List として作成します。 |
|
||||
| `Create PyList` | `PYLIST` | 複数入力を Python list として作成します。 |
|
||||
| `Create Range` | `INT` List, `PYLIST`, `length` | Python `range(start, stop, step)` で整数列を作ります。 |
|
||||
| `Create Arange` | `FLOAT` List, `PYLIST`, `length` | `numpy.arange(start, stop, step)` で数値列を作ります。 |
|
||||
| `Create Linspace` | `FLOAT` List, `PYLIST`, `length` | `numpy.linspace(start, stop, num)` で等間隔の数値列を作ります。 |
|
||||
| `List Dir` | `STRING` List, `PYLIST`, `length` | 指定フォルダから `glob` pattern に一致する項目を列挙します。 |
|
||||
|
||||
### Merge / Convert
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Merge List` | `List` | 複数の ComfyUI List を連結します。 |
|
||||
| `Merge PyList` | `PYLIST` | 複数の PyList を連結します。 |
|
||||
| `List To PyList` | `PYLIST` | ComfyUI List を Python list 値に変換します。 |
|
||||
| `PyList To List` | `List` | PyList を ComfyUI List processing 用に展開します。 |
|
||||
|
||||
### Get / Slice
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `List: Get By Index` | item | ComfyUI List から指定 index の要素を取り出します。 |
|
||||
| `PyList: Get By Index` | item | PyList から指定 index の要素を取り出します。 |
|
||||
| `List: Slice` | `List` | ComfyUI List を `start:end` で切り出します。 |
|
||||
| `PyList: Slice` | `PYLIST` | PyList を `start:end` で切り出します。 |
|
||||
|
||||
### Pack / Unpack
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Pack` | `PACK` | 複数入力を、名前・型・値つきで 1 つの Pack にまとめます。 |
|
||||
| `Unpack` | original types | Pack から元の値を取り出します。出力型は接続元の Pack に合わせて動的に変わります。 |
|
||||
|
||||
### Inspect / Utility
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Get Length` | `INT` | `len(value)` を返し、ノード上にも表示します。 |
|
||||
| `Get Shape` | `width`, `height`, `PyList_size`, `channels` | `IMAGE`、`LATENT`、`MASK` の形状を取得します。 |
|
||||
| `Any To Dict` | `DICT`, `str()` | オブジェクトを dict または文字列に変換して確認します。 |
|
||||
| `Get Widgets Values` | `LIST` | 接続元ノードの widget values を取得して表示します。 |
|
||||
| `Any Cast` | selected type | 値を指定型として出力します。基本的な `STRING` / `INT` / `FLOAT` / `BOOLEAN` 変換にも使えます。 |
|
||||
| `PyList Item Cast` | `PYLIST` | PyList 内の各要素を `STRING` / `INT` / `FLOAT` / `BOOLEAN` などへ変換します。 |
|
||||
| `Exec` | any | 入力値 `x[0]`, `x[1]`, ... を使って Python コードを実行し、`result` を返します。 |
|
||||
|
||||
## Dynamic Inputs
|
||||
|
||||
一部のノードは入力ソケットを動的に増やします。
|
||||
|
||||
- `Create List`
|
||||
- `Create PyList`
|
||||
- `Merge List`
|
||||
- `Merge PyList`
|
||||
- `Pack`
|
||||
- `Exec`
|
||||
|
||||
最後の空ソケットに接続すると次のソケットが追加されます。接続を外すと未使用ソケットは整理されます。
|
||||
|
||||
`Create List` / `Merge List` は、最初に接続した入力の型に合わせて出力型が変わります。`Pack` は入力ごとの型を保持します。
|
||||
|
||||
## Notes
|
||||
|
||||
- `List` と `PyList` は別物です。接続できない、または期待どおりに逐次処理されない場合は `List To PyList` / `PyList To List` で変換してください。
|
||||
- `List: Get By Index` と `PyList: Get By Index` は、index が範囲外の場合 `None` を返します。
|
||||
- Python の slice と同じく、`start:end` の `end` は含まれません。
|
||||
- `Exec` は任意の Python コードを実行します。信頼できる workflow でだけ使ってください。
|
||||
|
||||
## Example
|
||||
|
||||

|
||||
@@ -1,14 +1,167 @@
|
||||
# ComfyUI-List-Utils
|
||||
Comfy List and Python list (PyList) utilities which support: create, merge, convert, get or slice
|
||||
## Installation
|
||||
goto ComfyUI/custom_nodes dir in terminal(cmd)
|
||||
git clone https://github.com/godmt/ComfyUI-List-Utils.git
|
||||
Restart ComfyUI
|
||||
## Usage
|
||||
### Pack/Unpack
|
||||
Unpack node must be connected to Pack node at once to determine the output types.
|
||||
Once connected, Unpack node maintains its output types even when disconnected.
|
||||
(You can connect Pack and Unpack through Switch nodes or Anything Everywhere nodes!)
|
||||
|
||||
## Examples
|
||||

|
||||
[Japanese](README.ja.md)
|
||||
|
||||
Primitive ComfyUI custom nodes for working with ComfyUI List processing, raw Python list values, and typed value bundles.
|
||||
|
||||
This extension uses three similar-looking but very different container concepts:
|
||||
|
||||
| Name | Meaning | Main Use |
|
||||
| --- | --- | --- |
|
||||
| `List` | ComfyUI's official Data list / List processing | Run downstream nodes once per item |
|
||||
| `PyList` | A raw Python `list` value | Keep an array as one value and manipulate it directly |
|
||||
| `Pack` | A List-Utils typed container | Bundle values of different ComfyUI types and restore them later |
|
||||
|
||||
## Installation
|
||||
|
||||
Clone this repository into `ComfyUI/custom_nodes`, then restart ComfyUI.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/godmt/ComfyUI-List-Utils.git
|
||||
```
|
||||
|
||||
Nodes are added under the `list_utils` category.
|
||||
|
||||
## GUI Help
|
||||
|
||||
The nodes include inline help for the ComfyUI interface:
|
||||
|
||||
- Node-level descriptions explain what each node is for.
|
||||
- Inputs and widgets include tooltips for expected values.
|
||||
- Outputs include tooltips for what they return.
|
||||
- Dynamic inputs created by `Create List`, `Create PyList`, `Merge List`, `Merge PyList`, `Pack`, and `Exec` also receive tooltips.
|
||||
|
||||
## Choosing List, PyList, Or Pack
|
||||
|
||||
### List
|
||||
|
||||
`List` means ComfyUI List processing. Use it when you want ComfyUI to process several prompts, seeds, images, paths, or other values one item at a time.
|
||||
|
||||
List-Utils `List` nodes use ComfyUI's `OUTPUT_IS_LIST` / `INPUT_IS_LIST` behavior. The output socket type remains the original item type, such as `STRING`, `INT`, or `IMAGE`.
|
||||
|
||||
Common uses:
|
||||
|
||||
- Send several strings downstream one by one
|
||||
- Generate sequential seeds with `Create Range`
|
||||
- Enumerate files with `List Dir`
|
||||
- Extract or slice a ComfyUI List with `List: Get By Index` / `List: Slice`
|
||||
|
||||
### PyList
|
||||
|
||||
`PyList` is a raw Python `list` passed as one ComfyUI value. It does not trigger ComfyUI List processing by itself.
|
||||
|
||||
Common uses:
|
||||
|
||||
- Keep strings, numbers, paths, or other values as one array
|
||||
- Use Python-style index, slice, merge, or cast operations
|
||||
- Convert a ComfyUI List into one Python list with `List To PyList`
|
||||
- Convert a Python list back into ComfyUI List processing with `PyList To List`
|
||||
|
||||
### Pack
|
||||
|
||||
`Pack` bundles multiple values into one `PACK` socket while preserving each input's name, type, and value.
|
||||
|
||||
Use `Pack` / `Unpack` when you need to pass different ComfyUI types together. For example, a single Pack can carry `MODEL`, `CLIP`, `VAE`, `CONDITIONING`, and `IMAGE` values, then restore them as separate typed outputs later.
|
||||
|
||||
## Typical Workflows
|
||||
|
||||
### Split Text And Process Each Item
|
||||
|
||||
1. Put multiline or delimiter-separated text into `Split String`.
|
||||
2. Use the `STRING` output when you want ComfyUI List processing.
|
||||
3. Use the `PYLIST` output when you want one raw Python list value.
|
||||
4. Use `length` when you need the item count.
|
||||
|
||||
### Convert PyList To ComfyUI List
|
||||
|
||||
1. Create a `PYLIST` with `Create PyList`, `Split String`, `Create Range`, or a similar node.
|
||||
2. Connect it to `PyList To List`.
|
||||
3. The output becomes a ComfyUI List-processing output and downstream nodes run once per item.
|
||||
|
||||
Use `List To PyList` for the opposite direction, when you want to collect a ComfyUI List into one Python list value.
|
||||
|
||||
### Bundle Different Types
|
||||
|
||||
1. Connect values to `Pack`.
|
||||
2. Connecting the last empty socket adds another input automatically.
|
||||
3. Connect `Pack` to `Unpack`.
|
||||
4. `Unpack` creates outputs matching the input count and types from `Pack`.
|
||||
|
||||
`Unpack` can determine its output types after being connected to `Pack` once. It can also trace through some intermediate nodes such as switch-style nodes or Anything Everywhere-style nodes when the upstream `Pack` is discoverable.
|
||||
|
||||
## Nodes
|
||||
|
||||
### Create / Generate
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Split String` | `STRING` List, `PYLIST`, `length` | Splits text by delimiter and/or lines. Empty items are removed. |
|
||||
| `Create List` | `List` | Creates a ComfyUI List from multiple dynamic inputs. |
|
||||
| `Create PyList` | `PYLIST` | Creates a raw Python list value from multiple dynamic inputs. |
|
||||
| `Create Range` | `INT` List, `PYLIST`, `length` | Creates integer values with Python `range(start, stop, step)`. |
|
||||
| `Create Arange` | `FLOAT` List, `PYLIST`, `length` | Creates values with `numpy.arange(start, stop, step)`. |
|
||||
| `Create Linspace` | `FLOAT` List, `PYLIST`, `length` | Creates evenly spaced values with `numpy.linspace(start, stop, num)`. |
|
||||
| `List Dir` | `STRING` List, `PYLIST`, `length` | Lists path matches from a folder using a `glob` pattern. |
|
||||
|
||||
### Merge / Convert
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Merge List` | `List` | Concatenates multiple ComfyUI Lists. |
|
||||
| `Merge PyList` | `PYLIST` | Concatenates multiple PyLists. |
|
||||
| `List To PyList` | `PYLIST` | Collects a ComfyUI List into one Python list value. |
|
||||
| `PyList To List` | `List` | Expands a PyList into ComfyUI List processing. |
|
||||
|
||||
### Get / Slice
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `List: Get By Index` | item | Reads one item from a ComfyUI List by index. |
|
||||
| `PyList: Get By Index` | item | Reads one item from a PyList by index. |
|
||||
| `List: Slice` | `List` | Slices a ComfyUI List with Python-style `start:end`. |
|
||||
| `PyList: Slice` | `PYLIST` | Slices a PyList with Python-style `start:end`. |
|
||||
|
||||
### Pack / Unpack
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Pack` | `PACK` | Bundles multiple inputs with their names, types, and values. |
|
||||
| `Unpack` | original types | Restores values from a Pack. Output types change dynamically to match the connected Pack. |
|
||||
|
||||
### Inspect / Utility
|
||||
|
||||
| Node | Output | Description |
|
||||
| --- | --- | --- |
|
||||
| `Get Length` | `INT` | Returns `len(value)` and displays it on the node. |
|
||||
| `Get Shape` | `width`, `height`, `PyList_size`, `channels` | Reads shape information from `IMAGE`, `LATENT`, or `MASK`. |
|
||||
| `Any To Dict` | `DICT`, `str()` | Converts an object to a dict when possible and also returns `str(value)`. |
|
||||
| `Get Widgets Values` | `LIST` | Reads and displays widget values from the connected upstream node. |
|
||||
| `Any Cast` | selected type | Relabels a value as a selected type and converts basic scalar types when possible. |
|
||||
| `PyList Item Cast` | `PYLIST` | Converts each item inside a PyList to `STRING`, `INT`, `FLOAT`, `BOOLEAN`, and similar types. |
|
||||
| `Exec` | any | Runs Python code using inputs as `x[0]`, `x[1]`, ... and returns `result`. |
|
||||
|
||||
## Dynamic Inputs
|
||||
|
||||
These nodes add input sockets dynamically:
|
||||
|
||||
- `Create List`
|
||||
- `Create PyList`
|
||||
- `Merge List`
|
||||
- `Merge PyList`
|
||||
- `Pack`
|
||||
- `Exec`
|
||||
|
||||
Connect the last empty socket to add the next socket. Disconnecting sockets cleans up unused inputs.
|
||||
|
||||
`Create List` / `Merge List` adapt their output type from the first connected input. `Pack` preserves the type of each input separately.
|
||||
|
||||
## Notes
|
||||
|
||||
- `List` and `PyList` are different. If a connection does not work, or execution is not happening in the expected mode, use `List To PyList` or `PyList To List`.
|
||||
- `List: Get By Index` and `PyList: Get By Index` return `None` when the index is out of range.
|
||||
- Slices use Python behavior: `start:end` does not include the item at `end`.
|
||||
- `Exec` runs arbitrary Python code. Use it only in workflows you trust.
|
||||
|
||||
## Example
|
||||
|
||||

|
||||
|
||||
@@ -15,7 +15,39 @@ const TypeSlotEvent = {
|
||||
Disconnect: false,
|
||||
}
|
||||
|
||||
const dynamic_connection = (node, index, event, prefix = 'in_', type = '*', names = []
|
||||
const TOOLTIP_VALUE_INPUT = "Connect a value. Connecting the last empty socket adds another input."
|
||||
const TOOLTIP_PACK_VALUE_INPUT = "Value to store in the PACK. The input name, type, and value are preserved for Unpack."
|
||||
const TOOLTIP_PYLIST_INPUT = "Connect a PyList. Connecting the last empty socket adds another input."
|
||||
const TOOLTIP_EXEC_INPUT = "Input value available inside FUNC as x[index]. Connecting the last empty socket adds another input."
|
||||
const TOOLTIP_UNPACK_OUTPUT = "Value restored from the connected PACK. Output type is copied from the original Pack input."
|
||||
|
||||
const setTooltip = (slot, tooltip) => {
|
||||
if (slot && tooltip) {
|
||||
slot.tooltip = tooltip
|
||||
}
|
||||
return slot
|
||||
}
|
||||
|
||||
const addInputWithTooltip = (node, name, type, tooltip) => {
|
||||
const index = node.inputs?.length ?? 0
|
||||
node.addInput(name, type)
|
||||
return setTooltip(node.inputs?.[index], tooltip)
|
||||
}
|
||||
|
||||
const addOutputWithTooltip = (node, name, type, tooltip) => {
|
||||
const index = node.outputs?.length ?? 0
|
||||
node.addOutput(name, type)
|
||||
return setTooltip(node.outputs?.[index], tooltip)
|
||||
}
|
||||
|
||||
const dynamic_connection = (
|
||||
node,
|
||||
index,
|
||||
event,
|
||||
prefix = 'in_',
|
||||
type = '*',
|
||||
names = [],
|
||||
tooltip = ""
|
||||
) => {
|
||||
if (!node.inputs[index].name.startsWith(prefix)) {
|
||||
return
|
||||
@@ -37,6 +69,7 @@ const dynamic_connection = (node, index, event, prefix = 'in_', type = '*', name
|
||||
const name = i < names.length ? names[i] : `${prefix}${i + 1}`
|
||||
node.inputs[i].label = name
|
||||
node.inputs[i].name = name
|
||||
setTooltip(node.inputs[i], tooltip)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +79,7 @@ const dynamic_connection = (node, index, event, prefix = 'in_', type = '*', name
|
||||
const name = nextIndex < names.length
|
||||
? names[nextIndex]
|
||||
: `${prefix}${nextIndex + 1}`
|
||||
node.addInput(name, type)
|
||||
addInputWithTooltip(node, name, type, tooltip)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +126,13 @@ app.registerExtension({
|
||||
name: "godmt.ListUtils",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (nodeData.name === "GODMT_Pack" || nodeData.name === "GODMT_CreatePyList") {
|
||||
const inputTooltip = nodeData.name === "GODMT_Pack"
|
||||
? TOOLTIP_PACK_VALUE_INPUT
|
||||
: TOOLTIP_VALUE_INPUT
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
this.addInput(`${_prefix}_1`, '*')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, '*', inputTooltip)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -109,7 +145,7 @@ app.registerExtension({
|
||||
for (let i = length - 1; i >= 0; i--) {
|
||||
this.removeInput(i)
|
||||
}
|
||||
this.addInput(`${_prefix}_1`, '*')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, '*', inputTooltip)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -118,16 +154,18 @@ app.registerExtension({
|
||||
nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) {
|
||||
const r = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined
|
||||
if (slotType === TypeSlot.Input) {
|
||||
dynamic_connection(this, slot, event, `${_prefix}_`, '*')
|
||||
dynamic_connection(this, slot, event, `${_prefix}_`, '*', [], inputTooltip)
|
||||
if (event === TypeSlotEvent.Connect && link_info) {
|
||||
const fromNode = this.graph._nodes.find(
|
||||
(otherNode) => otherNode.id == link_info.origin_id
|
||||
)
|
||||
const type = fromNode.outputs[link_info.origin_slot].type
|
||||
this.inputs[slot].type = type
|
||||
setTooltip(this.inputs[slot], inputTooltip)
|
||||
} else if (event === TypeSlotEvent.Disconnect) {
|
||||
this.inputs[slot].type = '*'
|
||||
this.inputs[slot].label = `${_prefix}_${slot + 1}`
|
||||
setTooltip(this.inputs[slot], inputTooltip)
|
||||
}
|
||||
}
|
||||
return r
|
||||
@@ -136,7 +174,7 @@ app.registerExtension({
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
this.addInput(`x[0]`, '*')
|
||||
addInputWithTooltip(this, `x[0]`, '*', TOOLTIP_EXEC_INPUT)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -149,7 +187,7 @@ app.registerExtension({
|
||||
for (let i = length - 1; i > 0; i--) {
|
||||
this.removeInput(i)
|
||||
}
|
||||
this.addInput(`x[0]`, '*')
|
||||
addInputWithTooltip(this, `x[0]`, '*', TOOLTIP_EXEC_INPUT)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -173,6 +211,7 @@ app.registerExtension({
|
||||
const name = `x[${i-1}]`
|
||||
this.inputs[i].label = name
|
||||
this.inputs[i].name = name
|
||||
setTooltip(this.inputs[i], TOOLTIP_EXEC_INPUT)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +221,7 @@ app.registerExtension({
|
||||
if (this.inputs[this.inputs.length - 1].link != undefined) {
|
||||
const nextIndex = this.inputs.length - 1 // string widget is regarded as input also
|
||||
const name = `x[${nextIndex}]`
|
||||
this.addInput(name, type)
|
||||
addInputWithTooltip(this, name, type, TOOLTIP_EXEC_INPUT)
|
||||
}
|
||||
|
||||
if (event === TypeSlotEvent.Connect && link_info) {
|
||||
@@ -191,6 +230,7 @@ app.registerExtension({
|
||||
)
|
||||
const type = fromNode.outputs[link_info.origin_slot].type
|
||||
this.inputs[slot].type = type
|
||||
setTooltip(this.inputs[slot], TOOLTIP_EXEC_INPUT)
|
||||
} else if (event === TypeSlotEvent.Disconnect) {
|
||||
// this.inputs[slot].type = '*'
|
||||
// this.inputs[slot].label = `x[${slot}]`
|
||||
@@ -207,7 +247,7 @@ app.registerExtension({
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
this.addInput(`${_prefix}_1`, '*')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, '*', TOOLTIP_VALUE_INPUT)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -221,7 +261,7 @@ app.registerExtension({
|
||||
for (let i = length - 1; i >= 0; i--) {
|
||||
this.removeInput(i)
|
||||
}
|
||||
this.addInput(`${_prefix}_1`, '*')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, '*', TOOLTIP_VALUE_INPUT)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -259,13 +299,14 @@ app.registerExtension({
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
this.inputs[i].label = `${_prefix}_${i + 1}`
|
||||
this.inputs[i].name = `${_prefix}_${i + 1}`
|
||||
setTooltip(this.inputs[i], TOOLTIP_VALUE_INPUT)
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
addInputWithTooltip(this, `${_prefix}_${nextIndex + 1}`, this.inputs[0].type, TOOLTIP_VALUE_INPUT)
|
||||
}
|
||||
}
|
||||
return r
|
||||
@@ -274,7 +315,7 @@ app.registerExtension({
|
||||
const onNodeCreated = nodeType.prototype.onNodeCreated
|
||||
nodeType.prototype.onNodeCreated = function () {
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
this.addInput(`${_prefix}_1`, 'PYLIST')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, 'PYLIST', TOOLTIP_PYLIST_INPUT)
|
||||
return r
|
||||
}
|
||||
|
||||
@@ -287,7 +328,7 @@ app.registerExtension({
|
||||
for (let i = length - 1; i >= 0; i--) {
|
||||
this.removeInput(i)
|
||||
}
|
||||
this.addInput(`${_prefix}_1`, 'PYLIST')
|
||||
addInputWithTooltip(this, `${_prefix}_1`, 'PYLIST', TOOLTIP_PYLIST_INPUT)
|
||||
}
|
||||
return r
|
||||
}
|
||||
@@ -296,16 +337,18 @@ app.registerExtension({
|
||||
nodeType.prototype.onConnectionsChange = function (slotType, slot, event, link_info, data) {
|
||||
const r = onConnectionsChange ? onConnectionsChange.apply(this, arguments) : undefined
|
||||
if (slotType === TypeSlot.Input) {
|
||||
dynamic_connection(this, slot, event, `${_prefix}_`, 'PYLIST')
|
||||
dynamic_connection(this, slot, event, `${_prefix}_`, 'PYLIST', [], TOOLTIP_PYLIST_INPUT)
|
||||
if (event === TypeSlotEvent.Connect && link_info) {
|
||||
const fromNode = this.graph._nodes.find(
|
||||
(otherNode) => otherNode.id == link_info.origin_id
|
||||
)
|
||||
const type = fromNode.outputs[link_info.origin_slot].type
|
||||
this.inputs[slot].type = type
|
||||
setTooltip(this.inputs[slot], TOOLTIP_PYLIST_INPUT)
|
||||
} else if (event === TypeSlotEvent.Disconnect) {
|
||||
this.inputs[slot].type = 'PYLIST'
|
||||
this.inputs[slot].label = `${_prefix}_${slot + 1}`
|
||||
setTooltip(this.inputs[slot], TOOLTIP_PYLIST_INPUT)
|
||||
}
|
||||
}
|
||||
return r
|
||||
@@ -316,6 +359,7 @@ app.registerExtension({
|
||||
const r = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined
|
||||
// shrink outputs to 1
|
||||
this.outputs[0].type = "*"
|
||||
setTooltip(this.outputs[0], TOOLTIP_UNPACK_OUTPUT)
|
||||
const output_len = this.outputs.length
|
||||
for (let i = output_len - 1; i > 0; i--) {
|
||||
this.removeOutput(i)
|
||||
@@ -373,10 +417,11 @@ app.registerExtension({
|
||||
this.removeOutput(i)
|
||||
}
|
||||
for (let i = cur_len; i < output_len; i++) {
|
||||
this.addOutput(`${_prefix}_${i + 1}`, origin_inputs[i].type)
|
||||
addOutputWithTooltip(this, `${_prefix}_${i + 1}`, origin_inputs[i].type, TOOLTIP_UNPACK_OUTPUT)
|
||||
}
|
||||
for (let i = 0; i < cur_len && i < output_len; i++) {
|
||||
this.outputs[i].type = origin_inputs[i].type
|
||||
setTooltip(this.outputs[i], TOOLTIP_UNPACK_OUTPUT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,16 +62,22 @@ class SplitString:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"STRING": ("STRING", {"multiline": True}),
|
||||
"delimiter": ("STRING", {"default": ","}),
|
||||
"splitlines": ("BOOLEAN", {"default": False}),
|
||||
"strip": ("BOOLEAN", {"default": False})
|
||||
"STRING": ("STRING", {"multiline": True, "tooltip": "Text to split. Multiline text is supported."}),
|
||||
"delimiter": ("STRING", {"default": ",", "tooltip": "Delimiter used inside each line. Leave empty to skip delimiter splitting."}),
|
||||
"splitlines": ("BOOLEAN", {"default": False, "tooltip": "Split the input into lines before applying the delimiter."}),
|
||||
"strip": ("BOOLEAN", {"default": False, "tooltip": "Trim leading and trailing whitespace from each item."})
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "Split String"
|
||||
DESCRIPTION = "Split text into both a ComfyUI List-processing output and a PyList. Useful for prompt candidates, filenames, seed lists, and other simple batches."
|
||||
RETURN_TYPES = ("STRING", "PYLIST", "INT")
|
||||
RETURN_NAMES = ("STRING", "PYLIST", "length")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Split items as a ComfyUI List-processing output.",
|
||||
"Split items as one raw Python list value.",
|
||||
"Number of split items.",
|
||||
)
|
||||
OUTPUT_IS_LIST = (True, False, False, )
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -105,13 +111,15 @@ class ListGetByIndex:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY": (ANY_TYPE, {"forceInput": True}),
|
||||
"index": ("INT", {"forceInput": False, "default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"ANY": (ANY_TYPE, {"forceInput": True, "tooltip": "Connect a ComfyUI List-processing value."}),
|
||||
"index": ("INT", {"forceInput": False, "default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Item index to read. 0 is the first item, -1 is the last item."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "List: Get By Index"
|
||||
DESCRIPTION = "Read one item by index from a ComfyUI List-processing input. Use this for List values, not PyList values."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The item at the selected index. Returns None when the index is out of range.",)
|
||||
INPUT_IS_LIST = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -132,13 +140,15 @@ class PyListGetByIndex:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"PYLIST": ("PYLIST", {"forceInput": True}),
|
||||
"index": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"PYLIST": ("PYLIST", {"forceInput": True, "tooltip": "Connect a PyList, which is a raw Python list value."}),
|
||||
"index": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Item index to read. 0 is the first item, -1 is the last item."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "PyList: Get By Index"
|
||||
DESCRIPTION = "Read one item by index from a PyList. Use this for raw Python list values, not ComfyUI List-processing values."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The item at the selected index. Returns None when the index is out of range.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -157,14 +167,16 @@ class ListSlice:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY": (ANY_TYPE, {"forceInput": True}),
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"end": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"ANY": (ANY_TYPE, {"forceInput": True, "tooltip": "Connect the ComfyUI List-processing value to slice."}),
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Slice start index, matching Python list[start:end]."}),
|
||||
"end": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Slice end index. The item at this index is not included."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "List: Slice"
|
||||
DESCRIPTION = "Slice a ComfyUI List-processing input with Python-style start:end semantics and keep it as a List output."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The sliced ComfyUI List-processing output.",)
|
||||
INPUT_IS_LIST = True
|
||||
OUTPUT_IS_LIST = (True, )
|
||||
FUNCTION = "run"
|
||||
@@ -184,14 +196,16 @@ class PyListSlice:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"PYLIST": ("PYLIST", {"forceInput": True}),
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"end": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"PYLIST": ("PYLIST", {"forceInput": True, "tooltip": "Connect the PyList to slice."}),
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Slice start index, matching Python list[start:end]."}),
|
||||
"end": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Slice end index. The item at this index is not included."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "PyList: Slice"
|
||||
DESCRIPTION = "Slice a PyList with Python-style start:end semantics and keep it as a PyList output."
|
||||
RETURN_TYPES = ("PYLIST", )
|
||||
OUTPUT_TOOLTIPS = ("The sliced PyList.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -207,12 +221,14 @@ class PyListToList:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"PYLIST": ("PYLIST", {"forceInput": True}),
|
||||
"PYLIST": ("PYLIST", {"forceInput": True, "tooltip": "Python list value to expand into ComfyUI List processing."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "PyList To List"
|
||||
DESCRIPTION = "Convert a PyList into ComfyUI List processing. Use this when downstream nodes should run once per item."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("Each PyList item emitted as a ComfyUI List-processing item.",)
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -229,13 +245,15 @@ class ListToPyList:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY": (ANY_TYPE, {"forceInput": True}),
|
||||
"ANY": (ANY_TYPE, {"forceInput": True, "tooltip": "ComfyUI List-processing input to collect into one Python list value."}),
|
||||
}
|
||||
}
|
||||
|
||||
TITLE = "List To PyList"
|
||||
DESCRIPTION = "Collect a ComfyUI List-processing input into one PyList value. Use this when you want to stop per-item execution and treat the values as an array."
|
||||
RETURN_TYPES = ("PYLIST", )
|
||||
RETURN_NAMES = ("PYLIST", )
|
||||
OUTPUT_TOOLTIPS = ("The whole input List collected as one Python list value.",)
|
||||
INPUT_IS_LIST = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -261,7 +279,9 @@ class CreateList:
|
||||
}
|
||||
|
||||
TITLE = "Create List"
|
||||
DESCRIPTION = "Create a ComfyUI List-processing output from multiple inputs. Connect the last empty socket to add another input."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("Input values emitted as a ComfyUI List-processing output.",)
|
||||
OUTPUT_IS_LIST = (True, )
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -293,7 +313,9 @@ class CreatePyList:
|
||||
}
|
||||
|
||||
TITLE = "Create PyList"
|
||||
DESCRIPTION = "Create a PyList from multiple inputs. Use this when you want to keep an array as one value. Connect the last empty socket to add another input."
|
||||
RETURN_TYPES = ("PYLIST", )
|
||||
OUTPUT_TOOLTIPS = ("A raw Python list containing the input values.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -324,8 +346,10 @@ class MergeList:
|
||||
}
|
||||
|
||||
TITLE = "Merge List"
|
||||
DESCRIPTION = "Concatenate multiple ComfyUI List-processing inputs into one List output."
|
||||
INPUT_IS_LIST = True
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The concatenated ComfyUI List-processing output.",)
|
||||
OUTPUT_IS_LIST = (True, )
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -360,7 +384,9 @@ class MergePyList:
|
||||
}
|
||||
|
||||
TITLE = "Merge PyList"
|
||||
DESCRIPTION = "Concatenate multiple PyList inputs as raw Python lists."
|
||||
RETURN_TYPES = ("PYLIST", )
|
||||
OUTPUT_TOOLTIPS = ("The concatenated PyList.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -382,15 +408,21 @@ class CreateRange:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"stop": ("INT", {"default": 1, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"step": ("INT", {"default": 1, "min": -9007199254740992, "max": 9007199254740992}),
|
||||
"start": ("INT", {"default": 0, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "First integer to generate."}),
|
||||
"stop": ("INT", {"default": 1, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Stop boundary. This value is not included."}),
|
||||
"step": ("INT", {"default": 1, "min": -9007199254740992, "max": 9007199254740992, "tooltip": "Increment between values, matching Python range()."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Create Range"
|
||||
DESCRIPTION = "Generate integers with Python range(start, stop, step), output as both a ComfyUI List and a PyList. Useful for seeds and indexes."
|
||||
RETURN_TYPES = ("INT", "PYLIST", "INT")
|
||||
RETURN_NAMES = ("INT", "PYLIST", "length")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Generated integers as a ComfyUI List-processing output.",
|
||||
"Generated integers as one Python list value.",
|
||||
"Number of generated items.",
|
||||
)
|
||||
OUTPUT_IS_LIST = (True, False, False)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -408,15 +440,21 @@ class CreateArange:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"start": ("FLOAT", {"default": 0}),
|
||||
"stop": ("FLOAT", {"default": 1}),
|
||||
"step": ("FLOAT", {"default": 1}),
|
||||
"start": ("FLOAT", {"default": 0, "tooltip": "First value to generate."}),
|
||||
"stop": ("FLOAT", {"default": 1, "tooltip": "Stop boundary. This value is usually not included."}),
|
||||
"step": ("FLOAT", {"default": 1, "tooltip": "Increment between values, matching numpy.arange()."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Create Arange"
|
||||
DESCRIPTION = "Generate floating-point values with numpy.arange(start, stop, step), output as both a ComfyUI List and a PyList."
|
||||
RETURN_TYPES = ("FLOAT", "PYLIST", "INT")
|
||||
RETURN_NAMES = ("FLOAT", "PYLIST", "length")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Generated values as a ComfyUI List-processing output.",
|
||||
"Generated values as one Python list value.",
|
||||
"Number of generated items.",
|
||||
)
|
||||
OUTPUT_IS_LIST = (True, False, False)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -434,15 +472,21 @@ class CreateLinspace:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"start": ("FLOAT", {"default": 0}),
|
||||
"stop": ("FLOAT", {"default": 1}),
|
||||
"num": ("INT", {"default": 10, "min": 2}),
|
||||
"start": ("FLOAT", {"default": 0, "tooltip": "First value."}),
|
||||
"stop": ("FLOAT", {"default": 1, "tooltip": "Last value. numpy.linspace() includes this value."}),
|
||||
"num": ("INT", {"default": 10, "min": 2, "tooltip": "Number of values to generate."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Create Linspace"
|
||||
DESCRIPTION = "Generate evenly spaced values with numpy.linspace(start, stop, num), output as both a ComfyUI List and a PyList."
|
||||
RETURN_TYPES = ("FLOAT", "PYLIST", "INT")
|
||||
RETURN_NAMES = ("FLOAT", "PYLIST", "length")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Generated values as a ComfyUI List-processing output.",
|
||||
"Generated values as one Python list value.",
|
||||
"Number of generated items.",
|
||||
)
|
||||
OUTPUT_IS_LIST = (True, False, False)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -469,8 +513,10 @@ class Pack:
|
||||
}
|
||||
|
||||
TITLE = "Pack"
|
||||
DESCRIPTION = "Bundle multiple values, including different ComfyUI types, into one PACK with each input name, type, and value preserved. Use Unpack to restore them."
|
||||
RETURN_TYPES = ("PACK", )
|
||||
RETURN_NAMES = ("PACK", )
|
||||
OUTPUT_TOOLTIPS = ("A List-Utils container that preserves input names, types, and values.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -502,7 +548,7 @@ class Unpack:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"PACK": ("PACK", ),
|
||||
"PACK": ("PACK", {"tooltip": "Connect a PACK created by the Pack node. Outputs are rebuilt from its saved names and types."}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
@@ -512,8 +558,10 @@ class Unpack:
|
||||
}
|
||||
|
||||
TITLE = "Unpack"
|
||||
DESCRIPTION = "Extract the original values from a PACK. When connected to Pack, outputs are created from the Pack input names and types."
|
||||
RETURN_TYPES = ByPassTypeTuple(("*", ))
|
||||
RETURN_NAMES = ByPassTypeTuple(("value_1", ))
|
||||
OUTPUT_TOOLTIPS = ByPassTypeTuple(("A value stored in the PACK. Outputs grow dynamically to match the connected Pack.",))
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -538,13 +586,15 @@ class GetLength:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY" : (ANY_TYPE, {}),
|
||||
"ANY" : (ANY_TYPE, {"tooltip": "Value to pass to len(). Works with List, PyList, strings, and other values that support len()."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Get Length"
|
||||
DESCRIPTION = "Apply Python len() to the input and display the result on the node."
|
||||
RETURN_TYPES = ("INT", )
|
||||
RETURN_NAMES = ("length", )
|
||||
OUTPUT_TOOLTIPS = ("The result of len(value).",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
OUTPUT_NODE = True
|
||||
@@ -562,7 +612,7 @@ class GetShape:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"tensor" : ("IMAGE,LATENT,MASK", {}),
|
||||
"tensor" : ("IMAGE,LATENT,MASK", {"tooltip": "IMAGE, LATENT, or MASK whose shape you want to inspect."}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
@@ -572,8 +622,15 @@ class GetShape:
|
||||
}
|
||||
|
||||
TITLE = "Get Shape"
|
||||
DESCRIPTION = "Inspect width, height, batch size, and channels for IMAGE, LATENT, or MASK inputs. LATENT dimensions are converted to image-space size."
|
||||
RETURN_TYPES = ("INT", "INT", "INT", "INT")
|
||||
RETURN_NAMES = ("width", "height", "PyList_size", "channels")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Width. LATENT inputs are multiplied by 8 to report image-space width.",
|
||||
"Height. LATENT inputs are multiplied by 8 to report image-space height.",
|
||||
"Batch size. The output name is PyList_size for compatibility with existing workflows.",
|
||||
"Channel count. MASK inputs may be reported as 1 channel.",
|
||||
)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
OUTPUT_NODE = True
|
||||
@@ -625,13 +682,18 @@ class AnyToDict:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY" : (ANY_TYPE, {}),
|
||||
"ANY" : (ANY_TYPE, {"tooltip": "Any value to inspect. dict values pass through; objects with __dict__ are converted with vars()."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Any To Dict"
|
||||
DESCRIPTION = "Convert any value to a dict when possible and also return its string representation. Intended for debugging."
|
||||
RETURN_TYPES = ("DICT", "STRING")
|
||||
RETURN_NAMES = ("DICT", "str()")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"The value as a dict. Returns an empty dict when conversion is not available.",
|
||||
"The str() representation of the input value.",
|
||||
)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -653,7 +715,7 @@ class GetWidgetsValues:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY" : (ANY_TYPE, {}),
|
||||
"ANY" : (ANY_TYPE, {"tooltip": "Connect any output from the node whose widget values you want to inspect. The value is used only to locate the upstream node."}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
@@ -663,8 +725,10 @@ class GetWidgetsValues:
|
||||
}
|
||||
|
||||
TITLE = "Get Widgets Values"
|
||||
DESCRIPTION = "Read and display the upstream node's widgets_values. Intended for debugging node settings."
|
||||
RETURN_TYPES = ("LIST", )
|
||||
RETURN_NAMES = ("LIST", )
|
||||
OUTPUT_TOOLTIPS = ("The upstream node's widgets_values list.",)
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -716,13 +780,15 @@ class AnyCast:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"ANY" : (ANY_TYPE, {}),
|
||||
"TYPE": (["*", "STRING", "INT", "FLOAT", "BOOLEAN", "IMAGE", "LATENT", "MASK", "NOISE", "SAMPLER", "SIGMAS", "GUIDER", "MODEL", "CLIP", "VAE", "CONDITIONING", "PYLIST"], {}),
|
||||
"ANY" : (ANY_TYPE, {"tooltip": "Value to relabel or convert."}),
|
||||
"TYPE": (["*", "STRING", "INT", "FLOAT", "BOOLEAN", "IMAGE", "LATENT", "MASK", "NOISE", "SAMPLER", "SIGMAS", "GUIDER", "MODEL", "CLIP", "VAE", "CONDITIONING", "PYLIST"], {"tooltip": "ComfyUI type shown on the output socket. STRING, INT, FLOAT, and BOOLEAN also attempt Python conversion."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "Any Cast"
|
||||
DESCRIPTION = "Output any value as the selected ComfyUI type. STRING, INT, FLOAT, and BOOLEAN also perform Python conversion."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The value output as the selected TYPE.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -739,14 +805,16 @@ class PyListItemCast:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"PYLIST": ("PYLIST", {"forceInput": True}),
|
||||
"TYPE": (["STRING", "INT", "FLOAT", "NUMBER", "BOOLEAN", "PYLIST"], {}),
|
||||
"PYLIST": ("PYLIST", {"forceInput": True, "tooltip": "PyList whose items should be converted."}),
|
||||
"TYPE": (["STRING", "INT", "FLOAT", "NUMBER", "BOOLEAN", "PYLIST"], {"tooltip": "Conversion applied to each PyList item. NUMBER is the same as FLOAT."}),
|
||||
},
|
||||
}
|
||||
|
||||
TITLE = "PyList Item Cast"
|
||||
DESCRIPTION = "Convert each item inside a PyList to STRING, INT, FLOAT, BOOLEAN, and similar basic types."
|
||||
RETURN_TYPES = ("PYLIST", )
|
||||
RETURN_NAMES = ("PYLIST", )
|
||||
OUTPUT_TOOLTIPS = ("The PyList after converting each item.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
@@ -763,8 +831,8 @@ class ListDir:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"path": ("STRING", {"default": ""}),
|
||||
"pattern": ("STRING", {"default": "*"})
|
||||
"path": ("STRING", {"default": "", "tooltip": "Folder path to list."}),
|
||||
"pattern": ("STRING", {"default": "*", "tooltip": "Pattern passed to Path.glob, for example *.png or **/*.json."})
|
||||
},
|
||||
"optional": {},
|
||||
"hidden": {
|
||||
@@ -775,8 +843,14 @@ class ListDir:
|
||||
}
|
||||
|
||||
TITLE = "List Dir"
|
||||
DESCRIPTION = "List files and folders under a path using a glob pattern, output as both a ComfyUI List and a PyList."
|
||||
RETURN_TYPES = ("STRING", "PYLIST", "INT")
|
||||
RETURN_NAMES = ("STRING", "PYLIST", "length")
|
||||
OUTPUT_TOOLTIPS = (
|
||||
"Matched items as a ComfyUI List-processing output. Values are Path objects.",
|
||||
"Matched items as one Python list value.",
|
||||
"Number of matched items.",
|
||||
)
|
||||
OUTPUT_IS_LIST = (True, False, False, )
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
@@ -826,7 +900,7 @@ class Exec:
|
||||
def INPUT_TYPES(self):
|
||||
return {
|
||||
"required": {
|
||||
"FUNC": ("STRING", {"forceInput": False, "multiline": True, "default": "result = x[0]"})
|
||||
"FUNC": ("STRING", {"forceInput": False, "multiline": True, "default": "result = x[0]", "tooltip": "Python code to execute. Input values are x[0], x[1], ... Assign the value to return to result."})
|
||||
},
|
||||
"optional": {},
|
||||
"hidden": {
|
||||
@@ -837,7 +911,9 @@ class Exec:
|
||||
}
|
||||
|
||||
TITLE = "Exec"
|
||||
DESCRIPTION = "Execute Python code with input values available as x[0], x[1], ... and return result. Use only in trusted workflows."
|
||||
RETURN_TYPES = (ANY_TYPE, )
|
||||
OUTPUT_TOOLTIPS = ("The value assigned to result inside FUNC.",)
|
||||
FUNCTION = "run"
|
||||
CATEGORY = "list_utils"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user