diff --git a/image/boolean_node.jpg b/image/boolean_node.jpg index 2c749e8..8acd4b9 100644 Binary files a/image/boolean_node.jpg and b/image/boolean_node.jpg differ diff --git a/image/boolean_oprator_v2_node.jpg b/image/boolean_oprator_v2_node.jpg new file mode 100644 index 0000000..5e539b6 Binary files /dev/null and b/image/boolean_oprator_v2_node.jpg differ diff --git a/image/float_node.jpg b/image/float_node.jpg index 13509d6..17106da 100644 Binary files a/image/float_node.jpg and b/image/float_node.jpg differ diff --git a/image/integer_node.jpg b/image/integer_node.jpg index 24de5b3..4b1f37e 100644 Binary files a/image/integer_node.jpg and b/image/integer_node.jpg differ diff --git a/image/number_calculator_v2_node.jpg b/image/number_calculator_v2_node.jpg index b7220e4..d13a018 100644 Binary files a/image/number_calculator_v2_node.jpg and b/image/number_calculator_v2_node.jpg differ diff --git a/image/string_node.jpg b/image/string_node.jpg new file mode 100644 index 0000000..59dee0c Binary files /dev/null and b/image/string_node.jpg differ diff --git a/image/switch_case_example.jpg b/image/switch_case_example.jpg new file mode 100644 index 0000000..250b651 Binary files /dev/null and b/image/switch_case_example.jpg differ diff --git a/image/switch_case_node.jpg b/image/switch_case_node.jpg new file mode 100644 index 0000000..3a58ca7 Binary files /dev/null and b/image/switch_case_node.jpg differ diff --git a/py/data_nodes.py b/py/data_nodes.py index bccb32d..d70cbb2 100644 --- a/py/data_nodes.py +++ b/py/data_nodes.py @@ -85,8 +85,8 @@ class BooleanOperatorV2: } } - RETURN_TYPES = ("BOOLEAN",) - RETURN_NAMES = ("output",) + RETURN_TYPES = ("BOOLEAN", "STRING",) + RETURN_NAMES = ("output", "string",) FUNCTION = 'bool_operator_node_v2' CATEGORY = '😺dzNodes/LayerUtility/Data' @@ -137,7 +137,7 @@ class BooleanOperatorV2: if operator == "max": ret_value = max(a, b) - return (ret_value,) + return (ret_value, str(ret_value)) class NumberCalculator: def __init__(self): @@ -201,8 +201,8 @@ class NumberCalculatorV2: } } - RETURN_TYPES = ("INT", "FLOAT",) - RETURN_NAMES = ("int", "float",) + RETURN_TYPES = ("INT", "FLOAT", "STRING",) + RETURN_NAMES = ("int", "float", "string",) FUNCTION = 'number_calculator_node_v2' CATEGORY = '😺dzNodes/LayerUtility/Data' @@ -251,7 +251,7 @@ class NumberCalculatorV2: else: ret_value = 0 - return (int(ret_value), float(ret_value),) + return (int(ret_value), float(ret_value), str(ret_value)) class StringCondition: def __init__(self): @@ -265,16 +265,19 @@ class StringCondition: "sub_string": ("STRING", {"multiline": False}), },} - RETURN_TYPES = ("BOOLEAN",) - RETURN_NAMES = ("output",) + RETURN_TYPES = ("BOOLEAN", "STRING",) + RETURN_NAMES = ("output", "string",) FUNCTION = 'string_condition' CATEGORY = '😺dzNodes/LayerUtility/Data' def string_condition(self, text, condition, sub_string): + ret = False if condition == "include": - return (sub_string in text, ) + ret = sub_string in text if condition == "exclude": - return (sub_string not in text, ) + ret = sub_string not in text + return (ret, str(ret)) + class TextBoxNode: def __init__(self): @@ -293,6 +296,23 @@ class TextBoxNode: def text_box_node(self, text): return (text,) +class StringNode: + def __init__(self): + pass + @classmethod + def INPUT_TYPES(self): + return {"required": { + "string": ("STRING", {"multiline": False}), + },} + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("string",) + FUNCTION = 'string_node' + CATEGORY = '😺dzNodes/LayerUtility/Data' + + def string_node(self, string): + return (string,) + class IntegerNode: def __init__(self): pass @@ -302,13 +322,13 @@ class IntegerNode: "int_value":("INT", {"default": 0, "min": -99999999999999999999, "max": 99999999999999999999, "step": 1}), },} - RETURN_TYPES = ("INT",) - RETURN_NAMES = ("int",) + RETURN_TYPES = ("INT", "STRING",) + RETURN_NAMES = ("int", "string",) FUNCTION = 'integer_node' CATEGORY = '😺dzNodes/LayerUtility/Data' def integer_node(self, int_value): - return (int_value,) + return (int_value, str(int_value)) class FloatNode: def __init__(self): @@ -319,13 +339,13 @@ class FloatNode: "float_value": ("FLOAT", {"default": 0, "min": -99999999999999999999, "max": 99999999999999999999, "step": 0.00001}), },} - RETURN_TYPES = ("FLOAT",) - RETURN_NAMES = ("float",) + RETURN_TYPES = ("FLOAT", "STRING",) + RETURN_NAMES = ("float", "string",) FUNCTION = 'float_node' CATEGORY = '😺dzNodes/LayerUtility/Data' def float_node(self, float_value): - return (float_value,) + return (float_value, str(float_value)) class BooleanNode: def __init__(self): @@ -336,13 +356,13 @@ class BooleanNode: "bool_value": ("BOOLEAN", {"default": False}), },} - RETURN_TYPES = ("BOOLEAN",) - RETURN_NAMES = ("boolean",) + RETURN_TYPES = ("BOOLEAN", "STRING",) + RETURN_NAMES = ("boolean", "string",) FUNCTION = 'boolean_node' CATEGORY = '😺dzNodes/LayerUtility/Data' def boolean_node(self, bool_value): - return (bool_value,) + return (bool_value, str(bool_value)) class IfExecute: @@ -364,15 +384,53 @@ class IfExecute: def if_execute(self, if_condition, when_TRUE, when_FALSE): return (when_TRUE if if_condition else when_FALSE,) +class SwitchCaseNode: + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "switch_condition": ("STRING", {"default": "", "multiline": False}), + "case_1": ("STRING", {"default": "", "multiline": False}), + "case_2": ("STRING", {"default": "", "multiline": False}), + "case_3": ("STRING", {"default": "", "multiline": False}), + "input_default": (any,), + }, + "optional": { + "input_1": (any,), + "input_2": (any,), + "input_3": (any,), + } + } + + RETURN_TYPES = (any,) + RETURN_NAMES = "?" + FUNCTION = "switch_case" + CATEGORY = '😺dzNodes/LayerUtility/Data' + + def switch_case(self, switch_condition, case_1, case_2, case_3, input_default, input_1=None, input_2=None, input_3=None): + + output=input_default + if switch_condition == case_1 and input_1 is not None: + output=input_1 + elif switch_condition == case_2 and input_2 is not None: + output=input_2 + elif switch_condition == case_3 and input_3 is not None: + output=input_3 + + return (output,) + NODE_CLASS_MAPPINGS = { - "LayerUtility: StringCondition": StringCondition, + "LayerUtility: SwitchCase": SwitchCaseNode, "LayerUtility: If ": IfExecute, + "LayerUtility: StringCondition": StringCondition, "LayerUtility: BooleanOperator": BooleanOperator, "LayerUtility: NumberCalculator": NumberCalculator, "LayerUtility: BooleanOperatorV2": BooleanOperatorV2, "LayerUtility: NumberCalculatorV2": NumberCalculatorV2, "LayerUtility: TextBox": TextBoxNode, + "LayerUtility: String": StringNode, "LayerUtility: Integer": IntegerNode, "LayerUtility: Float": FloatNode, "LayerUtility: Boolean": BooleanNode, @@ -380,13 +438,15 @@ NODE_CLASS_MAPPINGS = { } NODE_DISPLAY_NAME_MAPPINGS = { - "LayerUtility: StringCondition": "LayerUtility: String Condition", + "LayerUtility: SwitchCase": "LayerUtility: Switch Case", "LayerUtility: If ": "LayerUtility: If", - "LayerUtility: BooleanOperator": "LayerUtility: BooleanOperator", - "LayerUtility: NumberCalculator": "LayerUtility: NumberCalculator", - "LayerUtility: BooleanOperatorV2": "LayerUtility: BooleanOperator V2", - "LayerUtility: NumberCalculatorV2": "LayerUtility: NumberCalculator V2", + "LayerUtility: StringCondition": "LayerUtility: String Condition", + "LayerUtility: BooleanOperator": "LayerUtility: Boolean Operator", + "LayerUtility: NumberCalculator": "LayerUtility: Number Calculator", + "LayerUtility: BooleanOperatorV2": "LayerUtility: Boolean Operator V2", + "LayerUtility: NumberCalculatorV2": "LayerUtility: Number Calculator V2", "LayerUtility: TextBox": "LayerUtility: TextBox", + "LayerUtility: String": "LayerUtility: String", "LayerUtility: Integer": "LayerUtility: Integer", "LayerUtility: Float": "LayerUtility: Float", "LayerUtility: Boolean": "LayerUtility: Boolean", diff --git a/pyproject.toml b/pyproject.toml index 498a6b2..0798e55 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui_layerstyle" description = "A set of nodes for ComfyUI it generate image like Adobe Photoshop's Layer Style. the Drop Shadow is first completed node, and follow-up work is in progress." -version = "1.0.7" +version = "1.0.8" license = "MIT" dependencies = ["numpy", "pillow", "torch", "matplotlib", "Scipy", "scikit_image", "opencv-contrib-python", "pymatting", "segment_anything", "timm", "addict", "yapf", "colour-science", "wget", "mediapipe", "loguru", "typer_config", "fastapi", "rich", "google-generativeai", "diffusers", "omegaconf", "tqdm", "transformers", "kornia", "image-reward", "ultralytics", "blend_modes", "blind-watermark", "qrcode", "pyzbar", "psd-tools"] diff --git a/workflow/switch_case_example.json b/workflow/switch_case_example.json new file mode 100644 index 0000000..2c236b3 --- /dev/null +++ b/workflow/switch_case_example.json @@ -0,0 +1,298 @@ +{ + "last_node_id": 13, + "last_link_id": 17, + "nodes": [ + { + "id": 12, + "type": "LoadImage", + "pos": [ + 728, + 201 + ], + "size": { + "0": 280.28167724609375, + "1": 314 + }, + "flags": {}, + "order": 0, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 13 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "girl_dino_1024.png", + "image" + ] + }, + { + "id": 8, + "type": "LoadImage", + "pos": [ + 720, + 560 + ], + "size": [ + 288.191231485162, + 302.38231903883286 + ], + "flags": {}, + "order": 1, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 14 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "1344x768_redcar (1).png", + "image" + ] + }, + { + "id": 7, + "type": "LoadImage", + "pos": [ + 720, + 909 + ], + "size": [ + 289.1216735839844, + 314 + ], + "flags": {}, + "order": 2, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 15 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "1344x768_yellowcar.png", + "image" + ] + }, + { + "id": 11, + "type": "LoadImage", + "pos": [ + 722, + 1269 + ], + "size": [ + 280.28167724609375, + 314 + ], + "flags": {}, + "order": 3, + "mode": 0, + "outputs": [ + { + "name": "IMAGE", + "type": "IMAGE", + "links": [ + 16 + ], + "shape": 3, + "slot_index": 0 + }, + { + "name": "MASK", + "type": "MASK", + "links": null, + "shape": 3 + } + ], + "properties": { + "Node name for S&R": "LoadImage" + }, + "widgets_values": [ + "1280x720car.jpg", + "image" + ] + }, + { + "id": 9, + "type": "PreviewImage", + "pos": [ + 1685, + 790 + ], + "size": { + "0": 328.4532775878906, + "1": 246 + }, + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "images", + "type": "IMAGE", + "link": 17 + } + ], + "properties": { + "Node name for S&R": "PreviewImage" + } + }, + { + "id": 13, + "type": "LayerUtility: SwitchCase", + "pos": [ + 1284, + 791 + ], + "size": { + "0": 315, + "1": 190 + }, + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "input_default", + "type": "*", + "link": 13 + }, + { + "name": "input_1", + "type": "*", + "link": 14 + }, + { + "name": "input_2", + "type": "*", + "link": 15 + }, + { + "name": "input_3", + "type": "*", + "link": 16 + } + ], + "outputs": [ + { + "name": "?", + "type": "*", + "links": [ + 17 + ], + "shape": 3, + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: SwitchCase" + }, + "widgets_values": [ + "blue", + "red", + "yellow", + "blue" + ] + } + ], + "links": [ + [ + 13, + 12, + 0, + 13, + 0, + "*" + ], + [ + 14, + 8, + 0, + 13, + 1, + "*" + ], + [ + 15, + 7, + 0, + 13, + 2, + "*" + ], + [ + 16, + 11, + 0, + 13, + 3, + "*" + ], + [ + 17, + 13, + 0, + 9, + 0, + "IMAGE" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 0.8264462809917354, + "offset": [ + 151.36545552655718, + -92.13907563062988 + ] + } + }, + "version": 0.4 +} \ No newline at end of file