Merge pull request #9 from StableLlama/dynamic_nodes2

Add flow selection nodes
This commit is contained in:
StableLlama
2025-05-18 16:45:55 +02:00
committed by GitHub
3 changed files with 82 additions and 4 deletions
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "basic_data_handling"
version = "0.3.1"
version = "0.3.2"
description = """NOTE: Still in development! Expect breaking changes!
Basic Python functions for manipulating data that every programmer is used to.
Currently supported ComfyUI data types: BOOLEAN, FLOAT, INT, STRING and data lists.
+38 -2
View File
@@ -1,6 +1,8 @@
from typing import Any
from inspect import cleandoc
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
from comfy_execution.graph import ExecutionBlocker
class IfElse(ComfyNodeABC):
"""
@@ -53,11 +55,11 @@ class IfElifElse(ComfyNodeABC):
def INPUT_TYPES(cls):
return {
"required": {
"if": (IO.BOOLEAN, {}),
"if": (IO.BOOLEAN, {"forceInput": True}),
"then": (IO.ANY, {"lazy": True}),
},
"optional": {
"elif_0": (IO.BOOLEAN, {"lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
"elif_0": (IO.BOOLEAN, {"forceInput": True, "lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
"then_0": (IO.ANY, {"lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
"else": (IO.ANY, {"lazy": True}),
}
@@ -191,6 +193,38 @@ class SwitchCase(ComfyNodeABC):
# If selector is out of range or the selected case is None, return default
return (kwargs.get("default"),)
class FlowSelect(ComfyNodeABC):
"""
Select the direction of the flow.
This node takes a value and directs it to either the "true" or "false" output.
Note: for dynamic switching in a Data Flow you might want to use
"filter select" instead.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"value": (IO.ANY, {}),
"select": (IO.BOOLEAN, {}),
}
}
RETURN_TYPES = (IO.ANY, IO.ANY)
RETURN_NAMES = ("true", "false")
CATEGORY = "Basic/flow control"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "select"
def select(self, value, select = True) -> tuple[Any, Any]:
if select:
return value, ExecutionBlocker(None)
else:
return ExecutionBlocker(None), value
class ExecutionOrder(ComfyNodeABC):
"""
Force execution order in the workflow.
@@ -222,6 +256,7 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: IfElse": IfElse,
"Basic data handling: IfElifElse": IfElifElse,
"Basic data handling: SwitchCase": SwitchCase,
"Basic data handling: FlowSelect": FlowSelect,
"Basic data handling: ExecutionOrder": ExecutionOrder,
}
@@ -229,5 +264,6 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: IfElse": "if/else",
"Basic data handling: IfElifElse": "if/elif/.../else",
"Basic data handling: SwitchCase": "switch/case",
"Basic data handling: FlowSelect": "flow select",
"Basic data handling: ExecutionOrder": "force execution order",
}
+43 -1
View File
@@ -295,6 +295,46 @@ class DataListFilter(ComfyNodeABC):
return (result,)
class DataListFilterSelect(ComfyNodeABC):
"""
Filters a Data List using boolean values.
This node takes a value Data List and a filter Data List (containing only boolean values).
It returns two new Data Lists containing only the elements from the value list where the
corresponding element in the filter list is true or false.
If the lists have different lengths, the last element of the shorter list is repeated
till the lengths are matching.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"value": (IO.ANY, {}),
"select": (IO.BOOLEAN, {}),
}
}
RETURN_TYPES = (IO.ANY, IO.ANY)
RETURN_NAMES = ("true", "false")
CATEGORY = "Basic/Data List"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "select"
INPUT_IS_LIST = True
OUTPUT_IS_LIST = (True, True,)
def select(self, **kwargs: list[Any]) -> tuple[list[Any]]:
values = kwargs.get('value', [])
selects = kwargs.get('select', [])
# Create a new list with only items where the filter is False
result_true, result_false = [], []
for value, select in zip(values, selects):
(result_true if select else result_false).append(value)
return result_true, result_false
class DataListGetItem(ComfyNodeABC):
"""
Retrieves an item at a specified position in a list.
@@ -771,7 +811,7 @@ class DataListToList(ComfyNodeABC):
INPUT_IS_LIST = True
def convert(self, **kwargs: list[Any]) -> tuple[list[Any]]:
return (kwargs.get('list', []).copy(),)
return (list(kwargs.get('list', [])).copy(),)
class DataListToSet(ComfyNodeABC):
@@ -810,6 +850,7 @@ NODE_CLASS_MAPPINGS = {
"Basic data handling: DataListCount": DataListCount,
"Basic data handling: DataListExtend": DataListExtend,
"Basic data handling: DataListFilter": DataListFilter,
"Basic data handling: DataListFilterSelect": DataListFilterSelect,
"Basic data handling: DataListGetItem": DataListGetItem,
"Basic data handling: DataListIndex": DataListIndex,
"Basic data handling: DataListInsert": DataListInsert,
@@ -838,6 +879,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: DataListCount": "count",
"Basic data handling: DataListExtend": "extend",
"Basic data handling: DataListFilter": "filter",
"Basic data handling: DataListFilterSelect": "filter select",
"Basic data handling: DataListGetItem": "get item",
"Basic data handling: DataListIndex": "index",
"Basic data handling: DataListInsert": "insert",