Skip to content

Commit dd87a74

Browse files
authored
Merge pull request #9 from StableLlama/dynamic_nodes2
Add flow selection nodes
2 parents e1ee38f + 39de69d commit dd87a74

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "basic_data_handling"
7-
version = "0.3.1"
7+
version = "0.3.2"
88
description = """NOTE: Still in development! Expect breaking changes!
99
Basic Python functions for manipulating data that every programmer is used to.
1010
Currently supported ComfyUI data types: BOOLEAN, FLOAT, INT, STRING and data lists.

src/basic_data_handling/control_flow_nodes.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from typing import Any
22
from inspect import cleandoc
33
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
4+
from comfy_execution.graph import ExecutionBlocker
5+
46

57
class IfElse(ComfyNodeABC):
68
"""
@@ -53,11 +55,11 @@ class IfElifElse(ComfyNodeABC):
5355
def INPUT_TYPES(cls):
5456
return {
5557
"required": {
56-
"if": (IO.BOOLEAN, {}),
58+
"if": (IO.BOOLEAN, {"forceInput": True}),
5759
"then": (IO.ANY, {"lazy": True}),
5860
},
5961
"optional": {
60-
"elif_0": (IO.BOOLEAN, {"lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
62+
"elif_0": (IO.BOOLEAN, {"forceInput": True, "lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
6163
"then_0": (IO.ANY, {"lazy": True, "_dynamic": "number", "_dynamicGroup": 0}),
6264
"else": (IO.ANY, {"lazy": True}),
6365
}
@@ -191,6 +193,38 @@ def execute(self, selector: int, **kwargs) -> tuple[Any]:
191193
# If selector is out of range or the selected case is None, return default
192194
return (kwargs.get("default"),)
193195

196+
197+
class FlowSelect(ComfyNodeABC):
198+
"""
199+
Select the direction of the flow.
200+
201+
This node takes a value and directs it to either the "true" or "false" output.
202+
203+
Note: for dynamic switching in a Data Flow you might want to use
204+
"filter select" instead.
205+
"""
206+
@classmethod
207+
def INPUT_TYPES(cls):
208+
return {
209+
"required": {
210+
"value": (IO.ANY, {}),
211+
"select": (IO.BOOLEAN, {}),
212+
}
213+
}
214+
215+
RETURN_TYPES = (IO.ANY, IO.ANY)
216+
RETURN_NAMES = ("true", "false")
217+
CATEGORY = "Basic/flow control"
218+
DESCRIPTION = cleandoc(__doc__ or "")
219+
FUNCTION = "select"
220+
221+
def select(self, value, select = True) -> tuple[Any, Any]:
222+
if select:
223+
return value, ExecutionBlocker(None)
224+
else:
225+
return ExecutionBlocker(None), value
226+
227+
194228
class ExecutionOrder(ComfyNodeABC):
195229
"""
196230
Force execution order in the workflow.
@@ -222,12 +256,14 @@ def execute(self, **kwargs) -> tuple[Any]:
222256
"Basic data handling: IfElse": IfElse,
223257
"Basic data handling: IfElifElse": IfElifElse,
224258
"Basic data handling: SwitchCase": SwitchCase,
259+
"Basic data handling: FlowSelect": FlowSelect,
225260
"Basic data handling: ExecutionOrder": ExecutionOrder,
226261
}
227262

228263
NODE_DISPLAY_NAME_MAPPINGS = {
229264
"Basic data handling: IfElse": "if/else",
230265
"Basic data handling: IfElifElse": "if/elif/.../else",
231266
"Basic data handling: SwitchCase": "switch/case",
267+
"Basic data handling: FlowSelect": "flow select",
232268
"Basic data handling: ExecutionOrder": "force execution order",
233269
}

src/basic_data_handling/data_list_nodes.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,46 @@ def filter_data(self, **kwargs: list[Any]) -> tuple[list[Any]]:
295295
return (result,)
296296

297297

298+
class DataListFilterSelect(ComfyNodeABC):
299+
"""
300+
Filters a Data List using boolean values.
301+
302+
This node takes a value Data List and a filter Data List (containing only boolean values).
303+
It returns two new Data Lists containing only the elements from the value list where the
304+
corresponding element in the filter list is true or false.
305+
306+
If the lists have different lengths, the last element of the shorter list is repeated
307+
till the lengths are matching.
308+
"""
309+
@classmethod
310+
def INPUT_TYPES(cls):
311+
return {
312+
"required": {
313+
"value": (IO.ANY, {}),
314+
"select": (IO.BOOLEAN, {}),
315+
}
316+
}
317+
318+
RETURN_TYPES = (IO.ANY, IO.ANY)
319+
RETURN_NAMES = ("true", "false")
320+
CATEGORY = "Basic/Data List"
321+
DESCRIPTION = cleandoc(__doc__ or "")
322+
FUNCTION = "select"
323+
INPUT_IS_LIST = True
324+
OUTPUT_IS_LIST = (True, True,)
325+
326+
def select(self, **kwargs: list[Any]) -> tuple[list[Any]]:
327+
values = kwargs.get('value', [])
328+
selects = kwargs.get('select', [])
329+
330+
# Create a new list with only items where the filter is False
331+
result_true, result_false = [], []
332+
for value, select in zip(values, selects):
333+
(result_true if select else result_false).append(value)
334+
335+
return result_true, result_false
336+
337+
298338
class DataListGetItem(ComfyNodeABC):
299339
"""
300340
Retrieves an item at a specified position in a list.
@@ -771,7 +811,7 @@ def INPUT_TYPES(cls):
771811
INPUT_IS_LIST = True
772812

773813
def convert(self, **kwargs: list[Any]) -> tuple[list[Any]]:
774-
return (kwargs.get('list', []).copy(),)
814+
return (list(kwargs.get('list', [])).copy(),)
775815

776816

777817
class DataListToSet(ComfyNodeABC):
@@ -810,6 +850,7 @@ def convert(self, **kwargs: list[Any]) -> tuple[set[Any]]:
810850
"Basic data handling: DataListCount": DataListCount,
811851
"Basic data handling: DataListExtend": DataListExtend,
812852
"Basic data handling: DataListFilter": DataListFilter,
853+
"Basic data handling: DataListFilterSelect": DataListFilterSelect,
813854
"Basic data handling: DataListGetItem": DataListGetItem,
814855
"Basic data handling: DataListIndex": DataListIndex,
815856
"Basic data handling: DataListInsert": DataListInsert,
@@ -838,6 +879,7 @@ def convert(self, **kwargs: list[Any]) -> tuple[set[Any]]:
838879
"Basic data handling: DataListCount": "count",
839880
"Basic data handling: DataListExtend": "extend",
840881
"Basic data handling: DataListFilter": "filter",
882+
"Basic data handling: DataListFilterSelect": "filter select",
841883
"Basic data handling: DataListGetItem": "get item",
842884
"Basic data handling: DataListIndex": "index",
843885
"Basic data handling: DataListInsert": "insert",

0 commit comments

Comments
 (0)