diff --git a/README.MD b/README.MD index 94972dd..c9c3604 100644 --- a/README.MD +++ b/README.MD @@ -147,6 +147,8 @@ When this error has occurred, please check the network environment. **If the dependency package error after updating, please double clicking ```repair_dependency.bat``` (for Official ComfyUI Protable) or ```repair_dependency_aki.bat``` (for ComfyUI-aki-v1.x) in the plugin folder to reinstall the dependency packages.
+* Commit [ChoiceTextPreset](#ChoiceTextPreset) and [TextPreseter](#TextPreseter) nodes, used for preset text and selecting preset text output. +* [StringCondition](#StringCondition) add the option of comparing strings to determine if they are the same. * Commit [NameToColor](#NameToColor) node, Output colors based on their names. * Commit [ImageMaskScaleAsV2](#ImageMaskScaleAsV2) node, Add background color settings on the basis of the original node. * Commit [RoundedRectangle](#RoundedRectangle) node, Used to create rounded rectangle and mask. @@ -1495,6 +1497,32 @@ Node Options: * select: Select the output image or mask at the batch index value, where 0 is the first image. Multiple values can be entered, separated by any non numeric character, including but not limited to commas, periods, semicolons, spaces or letters, and even Chinese characters. Note: If the value exceeds the batch size, the last image will be output. If there is no corresponding input, an empty 64x64 image or a 64x64 black mask will be output. +### ChoiceTextPreset +Select output from the preset text dictionary. +![image](image/choice_text_preset_example.jpg) + +Node Options: +![image](image/chioce_text_preset_node.jpg) +* text_preset: Preset text. Set the output by the [TextPreseter](#TextPreseter) node. +* choice_title: Select a preset title to output the corresponding text content. +* random_choice: Whether to randomly select a preset. +* default: Default output text, 0 corresponds to the first paragraph, and so on. Note that exceeding the preset text paragraph length will result in errors. +* seed: The random seed used for random selection. +* control_after_generate: Whether to change the seed every time it runs. + +Outputs: +* title: Text paragraph title. +* content: Text paragraph content. + +### TextPreseter +Preset text dictionary, set a section of text for each node, supporting multiple nodes to be concatenated. + +Node Options: +![image](image/text_preseter_node.jpg) +* text_preset: Preset text input, optional input. Multiple preset text nodes can be concatenated. +* title: Text paragraph title. +* content: Text paragraph content. + ### TextJoin ![image](image/text_join_example.jpg) @@ -1611,7 +1639,7 @@ Node Options: ![image](image/string_condition_node.jpg) * text: Input text. -* condition: Judgment conditions. ```include``` determines whether it contains a substring, and ```exclude``` determines whether it does not. +* condition: Judgment conditions. ```include``` determines whether it contains a substring, ```exclude``` determines whether it does not, and ```equal``` determine whether it is equal to the substring. * sub_string: Substring. ### CheckMask diff --git a/README_CN.MD b/README_CN.MD index 01263b9..c75e0b1 100644 --- a/README_CN.MD +++ b/README_CN.MD @@ -128,6 +128,8 @@ os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com' ## 更新说明 **如果本插件更新后出现依赖包错误,请双击运行插件目录下的```install_requirements.bat```(官方便携包),或 ```install_requirements_aki.bat```(秋叶整合包) 重新安装依赖包。 +* 添加 [ChoiceTextPreset](#ChoiceTextPreset) 和 [TextPreseter](#TextPreseter) 节点,用于预设文本和选择预设文本输出。 +* [StringCondition](#StringCondition) 节点增加比较字符串是否相同功能。 * 添加 [NameToColor](#NameToColor)节点,根据颜色名称输出颜色。 * 添加 [ImageMaskScaleAsV2](#ImageMaskScaleAsV2)节点,在原节点基础上增加背景颜色设置。 * 添加 [RoundedRectangle](#RoundedRectangle) 节点,用于创建圆角矩形及遮罩。 @@ -1333,6 +1335,32 @@ GradientImage的V2升级版。 注意:如果数值超出批量,将输出最后一张。如果没有对应的输入,将输出一个空的64x64图片或64x64黑色遮罩。 +### ChoiceTextPreset +从预设文本字典选择输出。 +![image](image/choice_text_preset_example.jpg) + +节点选项说明: +![image](image/chioce_text_preset_node.jpg) +* text_preset: 预设的文本。由[TextPreseter](#TextPreseter) 节点设置输出。 +* choice_title: 选择预设标题,将输出此标题对应的文本内容。 +* random_choice: 是否随机选择预设。 +* default: 默认输出文本,0对应第一段,依次类推。注意此数值超出预设文本段落长度将导致错误。 +* seed: 随机选择时使用的随机种子。 +* control_after_generate: 是否在每次运行时改变种子。 + +输出: +* title: 文本段落标题。 +* content: 文本段落内容。 + +### TextPreseter +预设文本字典,每个节点设置一段文本,支持多个节点串联。 + +节点选项说明: +![image](image/text_preseter_node.jpg) +* text_preset: 预设的文本,可选输入。多个预设文本节点可以串联。 +* title: 文本段落标题。 +* content: 文本段落内容。 + ### TextJoin ![image](image/text_join_example.jpg) 将多段文字组合为一段。 @@ -1434,7 +1462,7 @@ BooleanOperator的升级版,增加了节点内数值输入,增加了大于 节点选项说明: ![image](image/string_condition_node.jpg) * text: 输入的文本。 -* condition: 判断条件。```include```判断是否包含子字符串,```exclude```判断是否不包含子字符串。 +* condition: 判断条件。```include```判断是否包含子字符串,```exclude```判断是否不包含子字符串, ```equal```判断是否与子字符串相等。 * sub_string: 子字符串文本。 diff --git a/image/chioce_text_preset_node.jpg b/image/chioce_text_preset_node.jpg new file mode 100644 index 0000000..3cd675a Binary files /dev/null and b/image/chioce_text_preset_node.jpg differ diff --git a/image/choice_text_preset_example.jpg b/image/choice_text_preset_example.jpg new file mode 100644 index 0000000..b69730a Binary files /dev/null and b/image/choice_text_preset_example.jpg differ diff --git a/image/text_preseter_node.jpg b/image/text_preseter_node.jpg new file mode 100644 index 0000000..19126e8 Binary files /dev/null and b/image/text_preseter_node.jpg differ diff --git a/py/data_nodes.py b/py/data_nodes.py index dc2d459..e0f5106 100644 --- a/py/data_nodes.py +++ b/py/data_nodes.py @@ -268,7 +268,7 @@ class StringCondition: pass @classmethod def INPUT_TYPES(self): - string_condition_list = ["include", "exclude",] + string_condition_list = ["include", "exclude", "equal"] return {"required": { "text": ("STRING", {"multiline": False}), "condition": (string_condition_list,), @@ -286,6 +286,8 @@ class StringCondition: ret = sub_string in text if condition == "exclude": ret = sub_string not in text + if condition == "equal": + ret = text == sub_string return (ret, str(ret)) diff --git a/py/text_node.py b/py/text_node.py new file mode 100644 index 0000000..6bf0f48 --- /dev/null +++ b/py/text_node.py @@ -0,0 +1,86 @@ +import os +import json +import random +from .imagefunc import AnyType, log, extract_all_numbers_from_str, extract_numbers, extract_substr_from_str +from .imagefunc import tokenize_string, find_best_match_by_similarity, remove_empty_lines, remove_duplicate_string +from .imagefunc import get_files, file_is_extension, is_contain_chinese + +any = AnyType("*") + +class LS_TextPreseter: + def __init__(self): + self.NODE_NAME = "TextPreseter" + @classmethod + def INPUT_TYPES(self): + return { + "required": + { + "title": ("STRING", {"default": "", "multiline": False}), + "content": ("STRING", {"default": '', "multiline": True}), + }, + "optional": { + "text_preset": ("LS_TEXT_PRESET", ), + } + } + + RETURN_TYPES = ("LS_TEXT_PRESET",) + RETURN_NAMES = ("text_preset",) + FUNCTION = 'text_preseter' + CATEGORY = '😺dzNodes/LayerUtility/Data' + + def text_preseter(self, title, content, text_preset=None): + + if text_preset is None: + text_preset = {} + + if title: + text_preset[title] = content + + return (text_preset,) + +class LS_ChoiceTextPreset: + def __init__(self): + self.NODE_NAME = "ChoicePresetText" + @classmethod + def INPUT_TYPES(self): + return { + "required": + { "text_preset": ("LS_TEXT_PRESET", ), + "choice_title": ("STRING", {"default": '', "multiline": False}), + "random_choice": ("BOOLEAN", {"default": False}), + "default": ("INT", {"default": 0, "min": 0, "max": 1e4, "step": 1}), + "seed": ("INT", {"default": 0, "min": 0, "max": 1e18, "step": 1}), + }, + "optional": { + } + } + + RETURN_TYPES = ("STRING", "STRING",) + RETURN_NAMES = ("title", "content",) + FUNCTION = 'choice_preset_text' + CATEGORY = '😺dzNodes/LayerUtility/Data' + + def choice_preset_text(self, text_preset, choice_title, random_choice, default, seed): + keys = list(text_preset.keys()) + ret_key = keys[default] + ret_value = '' + + if choice_title in text_preset and not random_choice: + ret_key = choice_title + elif random_choice: + random.seed(seed) + ret_key = random.choice(list(text_preset.keys())) + + ret_value = text_preset[ret_key] + + return (ret_key, ret_value) + +NODE_CLASS_MAPPINGS = { + "LayerUtility: ChoiceTextPreset": LS_ChoiceTextPreset, + "LayerUtility: TextPreseter": LS_TextPreseter, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "LayerUtility: ChoiceTextPreset": "LayerUtility: Choice Text Preset", + "LayerUtility: TextPreseter": "LayerUtility: Text Preseter", +} \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9da3493..a7b1442 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 = "2.0.12" +version = "2.0.13" license = "MIT" dependencies = ["numpy", "pillow", "torch", "matplotlib", "Scipy", "scikit_image", "scikit_learn", "opencv-contrib-python", "pymatting", "timm", "colour-science", "transformers", "blend_modes", "huggingface_hub", "loguru"] diff --git a/workflow/choice_text_preset_example.json b/workflow/choice_text_preset_example.json new file mode 100644 index 0000000..dd49a94 --- /dev/null +++ b/workflow/choice_text_preset_example.json @@ -0,0 +1,314 @@ +{ + "last_node_id": 6, + "last_link_id": 5, + "nodes": [ + { + "id": 1, + "type": "LayerUtility: TextPreseter", + "pos": [ + -2816.744384765625, + -73.45758056640625 + ], + "size": [ + 370.747802734375, + 183.99403381347656 + ], + "flags": {}, + "order": 0, + "mode": 0, + "inputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "link": null, + "shape": 7 + } + ], + "outputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "links": [ + 1 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: TextPreseter" + }, + "widgets_values": [ + "New York", + "a vibrant, multicultural, and boundless global metropolis." + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 2, + "type": "LayerUtility: TextPreseter", + "pos": [ + -2814.857421875, + 173.76841735839844 + ], + "size": [ + 370.747802734375, + 183.99403381347656 + ], + "flags": {}, + "order": 1, + "mode": 0, + "inputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "link": 1, + "shape": 7 + } + ], + "outputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "links": [ + 2 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: TextPreseter" + }, + "widgets_values": [ + "Beijing", + "a city that blends ancient history with modern innovation, showcasing a rich cultural heritage and vibrant energy." + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 3, + "type": "LayerUtility: TextPreseter", + "pos": [ + -2806.807861328125, + 432.1820983886719 + ], + "size": [ + 370.747802734375, + 183.99403381347656 + ], + "flags": {}, + "order": 2, + "mode": 0, + "inputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "link": 2, + "shape": 7 + } + ], + "outputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "links": [ + 3 + ], + "slot_index": 0 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: TextPreseter" + }, + "widgets_values": [ + "Dubai", + "a city that symbolizes luxury, the future, and innovation, with some of the world’s most advanced architecture and facilities." + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 4, + "type": "LayerUtility: ChoiceTextPreset", + "pos": [ + -2317.017578125, + 131.33035278320312 + ], + "size": [ + 403.1999816894531, + 174 + ], + "flags": {}, + "order": 3, + "mode": 0, + "inputs": [ + { + "name": "text_preset", + "type": "LS_TEXT_PRESET", + "link": 3 + } + ], + "outputs": [ + { + "name": "title", + "type": "STRING", + "links": [ + 4 + ], + "slot_index": 0 + }, + { + "name": "content", + "type": "STRING", + "links": [ + 5 + ], + "slot_index": 1 + } + ], + "properties": { + "Node name for S&R": "LayerUtility: ChoiceTextPreset" + }, + "widgets_values": [ + "Beijing", + false, + 0, + 739495926040636, + "randomize" + ], + "color": "rgba(38, 73, 116, 0.7)" + }, + { + "id": 6, + "type": "ShowText|pysssss", + "pos": [ + -1750.7901611328125, + 271.31744384765625 + ], + "size": [ + 339.7099304199219, + 106.7203598022461 + ], + "flags": {}, + "order": 5, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 5, + "widget": { + "name": "text" + } + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null, + "shape": 6 + } + ], + "properties": { + "Node name for S&R": "ShowText|pysssss" + }, + "widgets_values": [ + "", + "a city that blends ancient history with modern innovation, showcasing a rich cultural heritage and vibrant energy." + ] + }, + { + "id": 5, + "type": "ShowText|pysssss", + "pos": [ + -1749.0072021484375, + 65.63809967041016 + ], + "size": [ + 331, + 83.1112060546875 + ], + "flags": {}, + "order": 4, + "mode": 0, + "inputs": [ + { + "name": "text", + "type": "STRING", + "link": 4, + "widget": { + "name": "text" + } + } + ], + "outputs": [ + { + "name": "STRING", + "type": "STRING", + "links": null, + "shape": 6 + } + ], + "properties": { + "Node name for S&R": "ShowText|pysssss" + }, + "widgets_values": [ + "", + "Beijing" + ] + } + ], + "links": [ + [ + 1, + 1, + 0, + 2, + 0, + "LS_TEXT_PRESET" + ], + [ + 2, + 2, + 0, + 3, + 0, + "LS_TEXT_PRESET" + ], + [ + 3, + 3, + 0, + 4, + 0, + "LS_TEXT_PRESET" + ], + [ + 4, + 4, + 0, + 5, + 0, + "STRING" + ], + [ + 5, + 4, + 1, + 6, + 0, + "STRING" + ] + ], + "groups": [], + "config": {}, + "extra": { + "ds": { + "scale": 1, + "offset": [ + 3930.093726936615, + 706.5574798546296 + ] + } + }, + "version": 0.4 +} \ No newline at end of file