Skip to content

Commit

Permalink
Major Refactoring, Lora load fix, Added features
Browse files Browse the repository at this point in the history
  • Loading branch information
TinyTerra committed Jul 2, 2023
1 parent a5f44f4 commit 4c7f13c
Show file tree
Hide file tree
Showing 19 changed files with 3,206 additions and 1,705 deletions.
41 changes: 34 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# tinyterraNodes
A selection of custom nodes for [ComfyUI](https://github.com/comfyanonymous/ComfyUI).

<img src="https://github.com/TinyTerra/ComfyUI_tinyterraNodes/blob/main/workflows/tinyterra_trueHRFix.png?raw=true">
![tinyterra_trueHRFix](workflows/tinyterra_trueHRFix.png)
![tinyterra_xyPlot](workflows/tinyterra_xyPlot.png)

## Installation
Navigate to the **_ComfyUI/custom_nodes_** directory, and run:
Navigate to the **_ComfyUI/custom_nodes_** directory with cmd, and run:

`git clone https://github.com/TinyTerra/ComfyUI_tinyterraNodes.git`

Expand All @@ -22,13 +23,31 @@ Navigate to the **_ComfyUI/custom_nodes_** directory, and run:
+ Automatically hides and shows widgets depending on their relevancy
+ Option to disable ([ttNodes] enable_dynamic_widgets = True | False)

**ttNstyles**
**ttNinterface**

*Enabled by default*

+ Sets the link color for PIPE_LINE and INT (customizable within config.ini [ttNstyles])
+ Option to update default node background color automatically when added ([ttNstyles] node_bg_override = default | red | brown | green | blue | pale_blue | cyan | purple | yellow | black)
+ Option to change the default link line type ([ttNstyles] link_type = spline | straight | direct)
+ <details><summary>Adds 'Node Dimensions (ttN)' to the node right-click context menu</summary> Allows setting specific node Width and Height values as long as they are above the minimum size for the given node.
+ <details><summary>Adds support for 'ctrl + arrow key' Node movement</summary> This aligns the node(s) to the set ComfyUI grid spacing size and move the node in the direction of the arrow key by the grid spacing value. Holding shift in addition will move the node by the grid spacing size * 10.
+ <details><summary>Adds 'Reload Node (ttN)' to the node right-click context menu</summary> Creates a new instance of the node with the same position, size, color and title (will disconnect any IO wires). It attempts to retain set widget values which is useful for replacing nodes when a node/widget update occurs </details>
+ <details><summary>Adds 'Slot Type Color (ttN)' to the Link right-click context menu</summary> Opens a color picker dialog menu to update the color of the selected link type. </details>
+ <details><summary>Adds 'Link Style (ttN)' to the Link right-click context menu</summary> Sets the default link line type. </details>

**Save image prefix parsing**

+ Add date/time info to filenames by using: %date:yyyy-MM-dd-hh-mm-ss%
+ Parse any upstream setting into filenames by using %[widget_name]% (for the current node) <br>
or %[input_name]>[input_name]>[widget_name]% (for inputting nodes) <br>
<details><summary>Example:
</summary>

![tinyterra_prefixParsing](workflows/tinyterra_prefixParsing.png)
</details>

**Node Versioning**

+ All tinyterraNodes now have a version property so that if any future changes are made to widgets that would break workflows the nodes will be highlighted on load
+ Will only work with workflows created/saved after the v1.0.0 release

**AutoUpdate**

Expand Down Expand Up @@ -110,13 +129,21 @@ Convert ttN pipe line to detailer pipe (to be compatible with [ImpactPack](https
+ _**Outputs -** detailer_pipe[model, vae, conditioning, conditioning, bbox_detector, sam_model_opt], pipe_
</details>

<details>
<summary>pipe > xyPlot</summary>

pipeKSampler input to generate xy plots using sampler and loader values. (Any values not set by xyPlot will be taken from the corresponding pipeKSampler or pipeLoader)
+ _**Inputs -** grid_spacing, latent_id, flip_xy, x_axis, x_values, y_axis, y_values_
+ _**Outputs -** xyPlot_
</details>

## ttN/image

<details>
<summary>imageOutput</summary>

Preview or Save an image with one node, with image throughput.
+ _**Inputs -** image, image output[Preview, Save], save prefix_
+ _**Inputs -** image, image output[Hide, Preview, Save, Hide/Save], output path, save prefix, number padding[None, 2-9], overwrite existing[True, False], embed workflow[True, False]_
+ _**Outputs -** image_

</details>
Expand Down
86 changes: 17 additions & 69 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,28 @@
from pathlib import Path
from .tinyterraNodes import TTN_VERSIONS
import configparser
import folder_paths
import subprocess
import shutil
import json
import sys
import os

# ------- CONFIG -------- #
cwd_path = Path(__file__).parent
comfy_path = cwd_path.parent.parent
sitepkg = comfy_path.parent / 'python_embeded' / 'Lib' / 'site-packages'
script_path = comfy_path.parent / 'python_embeded' / 'Scripts'
cwd_path = os.path.dirname(os.path.realpath(__file__))
comfy_path = folder_paths.base_path

sys.path.append(str(sitepkg))
sys.path.append(str(script_path))

config_path = cwd_path / "config.ini"

default_pipe_color = "#7737AA"
default_int_color = "#29699C"
config_path = os.path.join(cwd_path, "config.ini")

optionValues = {
"auto_update": ('true', 'false'),
"install_rembg": ('true', 'false'),
"enable_embed_autocomplete": ('true', 'false'),
"apply_custom_styles": ('true', 'false'),
"enable_interface": ('true', 'false'),
"enable_dynamic_widgets": ('true', 'false'),
"enable_dev_nodes": ('true', 'false'),
"link_type": ('spline', 'straight', 'direct'),
"default_node_bg_color": ('default', 'red', 'brown', 'green', 'blue', 'pale_blue', 'cyan', 'purple', 'yellow', 'black'),
"pipe_line": "HEX Color Code (pipe_line link color)",
"int": "HEX Color Code (int link color)",
"xyplot": "HEX Color Code (xyplot link color)",
}

def get_config():
Expand All @@ -42,23 +33,20 @@ def get_config():

def update_config():
#section > option > value
for node, version in TTN_VERSIONS.items():
config_write("Versions", node, version)

for option, value in optionValues.items():
config_write("Option Values", option, value)

section_data = {
"ttNodes": {
"auto_update": False,
"install_rembg": True,
"apply_custom_styles": True,
"enable_interface": True,
"enable_embed_autocomplete": True,
"enable_dynamic_widgets": True,
"enable_dev_nodes": False,
},
"ttNstyles": {
"default_node_bg_color": 'default',
"link_type": "spline",
"pipe_line": default_pipe_color,
"int": default_int_color,
}
}

Expand All @@ -72,6 +60,8 @@ def update_config():

# Iterate through the configuration data.
for section, options in config_data.items():
if section == "Versions":
continue
for option in options:
# If the option is not in `optionValues` or in `section_data`, remove it.
if (option not in optionValues and
Expand Down Expand Up @@ -110,17 +100,6 @@ def copy_to_web(file):
"""Copy a file to the web extension path."""
shutil.copy(file, web_extension_path)

def config_hex_code_validator(section, option, default):
hex_code = config_read(section, option)
try:
int(hex_code[1:], 16) # Convert hex code without the '#' symbol
if len(hex_code) == 7 and hex_code.startswith('#'):
return hex_code
except ValueError:
print(f'\033[92m[{section} Config]\033[91m {option} - \'{hex_code}\' is not a valid hex code, reverting to default.\033[0m')
config_write(section, option, default)
return default

def config_value_validator(section, option, default):
value = str(config_read(section, option)).lower()
if value not in optionValues[option]:
Expand Down Expand Up @@ -168,16 +147,15 @@ def config_value_validator(section, option, default):
# --------- WEB ---------- #
web_extension_path = os.path.join(comfy_path, "web", "extensions", "tinyterraNodes")

embedLISTfile = os.path.join(web_extension_path, "embeddingsList.json")
ttNstyles_JS_file_web = os.path.join(web_extension_path, "ttNstyles.js")

ttN_JS_file = os.path.join(cwd_path, "js", "ttN.js")
ttNstyles_JS_file = os.path.join(cwd_path, "js", "ttNstyles.js")
ttNxyPlot_JS_file = os.path.join(cwd_path, "js", "ttNxyPlot.js")
ttNembedAC_JS_file = os.path.join(cwd_path, "js", "ttNembedAC.js")
ttNwidgets_JS_file = os.path.join(cwd_path, "js", "ttNwidgets.js")
ttNinterface_JS_file = os.path.join(cwd_path, "js", "ttNinterface.js")
ttNdynamicWidgets_JS_file = os.path.join(cwd_path, "js", "ttNdynamicWidgets.js")


if not os.path.exists(web_extension_path):
os.makedirs(web_extension_path)
else:
Expand All @@ -186,44 +164,14 @@ def config_value_validator(section, option, default):

copy_to_web(ttN_JS_file)
copy_to_web(ttNwidgets_JS_file)
copy_to_web(ttNxyPlot_JS_file)

# Enable Custom Styles if True
if config_value_validator("ttNodes", "apply_custom_styles", 'true') == 'true':
link_type = config_read("ttNstyles", "link_type")
if link_type == "straight":
link_type = 0
elif link_type == "direct":
link_type = 1
else:
link_type = 2

pipe_line_color = config_hex_code_validator("ttNstyles", "pipe_line", default_pipe_color)
int_color = config_hex_code_validator("ttNstyles", "int", default_int_color)
bg_override_color = config_value_validator("ttNstyles", "default_node_bg_color", 'default')

# Apply config values to styles JS
with open(ttNstyles_JS_file, 'r') as file:
stylesJSlines = file.readlines()

for i in range(len(stylesJSlines)):
if "const customPipeLineLink" in stylesJSlines[i]:
stylesJSlines[i] = f'const customPipeLineLink = "{pipe_line_color}"\n'
if "const customIntLink" in stylesJSlines[i]:
stylesJSlines[i] = f'const customIntLink = "{int_color}"\n'
if "const customLinkType" in stylesJSlines[i]:
stylesJSlines[i] = f'const customLinkType = {link_type}\n'
if "const overrideBGColor" in stylesJSlines[i]:
stylesJSlines[i] = f'const overrideBGColor = "{bg_override_color}"\n'

with open(ttNstyles_JS_file_web, 'w') as file:
file.writelines(stylesJSlines)
if config_value_validator("ttNodes", "enable_interface", 'true') == 'true':
copy_to_web(ttNinterface_JS_file)

# Enable Embed Autocomplete if True
if config_value_validator("ttNodes", "enable_embed_autocomplete", "true") == 'true':
embeddings_list = folder_paths.get_filename_list("embeddings")
with open(embedLISTfile, 'w') as file:
json.dump(embeddings_list, file)

copy_to_web(ttNembedAC_JS_file)

# Enable Dynamic Widgets if True
Expand Down
2 changes: 1 addition & 1 deletion adv_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ def advanced_encode_from_tokens(clip, tokenized, token_normalization, weight_int
weights = scale_to_norm(weights, word_ids, w_max)
weighted_emb = down_weight(unweighted_tokens, weights, word_ids, base_emb, clip)

return weighted_emb
return [[weighted_emb,{}]]

def advanced_encode(clip, text, token_normalization, weight_interpretation, w_max=1.0):
tokenized = clip.tokenize(text, return_word_ids=True)
Expand Down
Loading

0 comments on commit 4c7f13c

Please sign in to comment.