Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62539f80be | ||
|
|
73da0b966f | ||
|
|
63a46a8e71 | ||
|
|
d05cd5a605 | ||
|
|
6f8729c9f5 | ||
|
|
0cc642dd60 | ||
|
|
8b399da4c3 | ||
|
|
a4e03cc8a2 | ||
|
|
dd6b847298 | ||
|
|
45d7a61241 | ||
|
|
853e00fe82 | ||
|
|
b8173975ba | ||
|
|
2986bb3f82 | ||
|
|
fb59959bef | ||
|
|
499886dbab | ||
|
|
6fe090cc9c | ||
|
|
44d9b6672d | ||
|
|
c91e903cda | ||
|
|
5c68912153 | ||
|
|
28b0da0c9a |
+1
-1
@@ -6,7 +6,7 @@ root = true
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = false
|
||||
insert_final_newline = false
|
||||
@@ -0,0 +1,69 @@
|
||||
# s: set *.js and other as js file for js project
|
||||
# disable other with linguist-detectable for ps1
|
||||
*.ps1 linguist-language=false
|
||||
*.md linguist-detectable=false
|
||||
*.py linguist-detectable=true
|
||||
*.html linguist-detectable=false
|
||||
*.js linguist-detectable=false
|
||||
*.css linguist-detectable=false
|
||||
# s: set *.js and other as js file for js project
|
||||
|
||||
# refer:
|
||||
# https://huggingface.co/guoyww/animatediff/blob/main/.gitattributes
|
||||
# https://huggingface.co/datasets/hdparmar/itt_specdata/blob/main/.gitattributes
|
||||
# https://github.com/Richienb/git-files/blob/master/files/.gitattributes
|
||||
|
||||
*.7z filter=lfs diff=lfs merge=lfs -text
|
||||
*.arrow filter=lfs diff=lfs merge=lfs -text
|
||||
*.bin filter=lfs diff=lfs merge=lfs -text
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
||||
*.ftz filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.h5 filter=lfs diff=lfs merge=lfs -text
|
||||
*.joblib filter=lfs diff=lfs merge=lfs -text
|
||||
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
||||
*.model filter=lfs diff=lfs merge=lfs -text
|
||||
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
||||
*.npy filter=lfs diff=lfs merge=lfs -text
|
||||
*.npz filter=lfs diff=lfs merge=lfs -text
|
||||
*.onnx filter=lfs diff=lfs merge=lfs -text
|
||||
*.ot filter=lfs diff=lfs merge=lfs -text
|
||||
*.parquet filter=lfs diff=lfs merge=lfs -text
|
||||
*.pb filter=lfs diff=lfs merge=lfs -text
|
||||
*.pickle filter=lfs diff=lfs merge=lfs -text
|
||||
*.pkl filter=lfs diff=lfs merge=lfs -text
|
||||
*.pt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pth filter=lfs diff=lfs merge=lfs -text
|
||||
*.rar filter=lfs diff=lfs merge=lfs -text
|
||||
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
||||
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
||||
*.tflite filter=lfs diff=lfs merge=lfs -text
|
||||
*.tgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.wasm filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
||||
*.zst filter=lfs diff=lfs merge=lfs -text
|
||||
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
||||
# Audio files - uncompressed
|
||||
*.pcm filter=lfs diff=lfs merge=lfs -text
|
||||
*.sam filter=lfs diff=lfs merge=lfs -text
|
||||
*.raw filter=lfs diff=lfs merge=lfs -text
|
||||
# Audio files - compressed
|
||||
*.aac filter=lfs diff=lfs merge=lfs -text
|
||||
*.flac filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
# Image files - uncompressed
|
||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
||||
# Image files - compressed
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.webp filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -0,0 +1,21 @@
|
||||
name: Publish to Comfy registry
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "pyproject.toml"
|
||||
|
||||
jobs:
|
||||
publish-node:
|
||||
name: Publish Custom Node to registry
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish Custom Node
|
||||
uses: Comfy-Org/publish-node-action@main
|
||||
with:
|
||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||
personal_access_token: ${{ secrets.COMFY_REGISTRY_TOKEN }}
|
||||
@@ -0,0 +1,37 @@
|
||||
- feat(core): NodePlainTextList - input text preset
|
||||
- feat(core): NodePlainTextListAdv - input text preset - adv
|
||||
- feat(core): NodePlainTextListJoinTextAdv - join text to text preset - adv
|
||||
- feat(core): NodePlainTextJoin - join text
|
||||
- feat(core): NodePlainTextRandom - random text in list
|
||||
- feat(core): NodePlainTextLoop - get text in list (loop)
|
||||
- feat(core): NodePlainTextReplace - replace text
|
||||
- feat(core): do nothing when action no
|
||||
- feat(core): replace text
|
||||
- feat(core): NodeNumStrToNum - text to number
|
||||
- feat(core): NodeNumStrToBool - text to bool
|
||||
- feat(core): NodePlainTextSwitchWithBool - text switch with bool
|
||||
- feat(core): NodePlainTextSwitchWithText - text switch with text
|
||||
- feat(core): NodeTextShow - show text
|
||||
- feat(core): NodeTextCalcSize - cacluate width and height
|
||||
- feat(core): NodePromptAdd - prompt add some text
|
||||
- feat(core): NodePromptAdvAdd - prompt add some text (adv)
|
||||
- feat(core): NodePromptSearch - prompt search some text
|
||||
- feat(core): NodePromptDup - prompt dup some text
|
||||
- feat(core): NodePromptAdvDup - prompt dup some text (adv)
|
||||
- feat(core): NodePromptShuffle - prompt shuffle some text
|
||||
- feat(core): NodePromptDel - prompt del some text
|
||||
- feat(core): NodePromptStd - prompt std
|
||||
- feat(core): NodePromptInput - prompt input
|
||||
- feat(core): NodePromptUnweight - prompt unweight
|
||||
- feat(core): NodePromptJoin - prompt join
|
||||
- feat(core): NodePromptRandom - prompt random
|
||||
- feat(core): NodePromptWeight - prompt add weight
|
||||
- feat(core): NodePyioFilenameListDetect - pyio - detect filename list
|
||||
- feat(core): NodePyioFilenameListOutmDetect - pyio - detect filename list (outm)
|
||||
- feat(core): IoUtilFileListGetText - io - get file list and read as text
|
||||
- feat(core): NodeRegionCropLocationBurnNumz - num - burn crop location (center & size)
|
||||
- feat(core): NodeRegionCropLocationBurnTxtz - txt - burn crop location (center & size)
|
||||
- feat(core): NodeRegionCropLocationBurnLtwh - int - burn crop location (lt & size)
|
||||
- feat(core): NodeRegionPaddingSquareLocationBurn - int - burn padding location as square (size)
|
||||
- feat(core): NodeCutoffRegionTextBurn - cutoff - region text burn
|
||||
- feat(core): NodeCutoffRegionColorTextPreset - cutoff - color preset of region text
|
||||
@@ -1,239 +0,0 @@
|
||||
## basic do
|
||||
|
||||
- [x] set git default branch
|
||||
```bash
|
||||
git config --global init.defaultBranch main
|
||||
```
|
||||
|
||||
- [x] ini git repo
|
||||
```bash
|
||||
[ ! -e .git ] && git init;
|
||||
```
|
||||
|
||||
- [x] set user name and email
|
||||
```bash
|
||||
git config --global user.name "yemiancheng" ;git config --global user.email "ymc.github@gmail.com";
|
||||
```
|
||||
|
||||
- [ ] change the master bransh to "main" from "master"
|
||||
```bash
|
||||
git branch -M main
|
||||
```
|
||||
|
||||
- [x] add github repo (in plan)
|
||||
```bash
|
||||
# copy token files to current project
|
||||
# cp /d/code/shell/github-cli/secrets/* ./secrets
|
||||
|
||||
|
||||
workspace=$(pwd);
|
||||
cd /d/code/shell/github-cli;shfile=./index.sh;
|
||||
repourl="ymc-github/ymc-node-suite-comfyui";repodesc="custom nodes for comfyui,like AI painting in comfyui";
|
||||
|
||||
# add repo with default desc
|
||||
$shfile $repourl add # (in plan)
|
||||
# put repo desc
|
||||
# $shfile "$repourl" put "$repodesc" # (process)
|
||||
# $shfile $repourl del
|
||||
|
||||
cd "$workspace"
|
||||
```
|
||||
|
||||
|
||||
|
||||
- [x] add remote repo url
|
||||
```bash
|
||||
# git remote add origin https://github.com/YMC-GitHub/ymc-node-suite-comfyui.git
|
||||
git remote add origin git@github.com:YMC-GitHub/ymc-node-suite-comfyui.git
|
||||
```
|
||||
|
||||
- [x] set gitignore and commit it
|
||||
```bash
|
||||
git add .gitignore;git commit -m "build(core): add gitignore";
|
||||
git add .gitignore;git commit -m "build(core): set note for go allow list";
|
||||
git add .gitignore;git commit -m "build(core): put gitignore to design project dirs";
|
||||
```
|
||||
|
||||
[fefer: some gitignore template](https://github.com/github/gitignore)
|
||||
|
||||
|
||||
- [x] set edifotconfig and commit it
|
||||
```bash
|
||||
git add .editorconfig ; git commit -m "build(core): add editor config";
|
||||
```
|
||||
|
||||
- [x] set license and commit it
|
||||
```bash
|
||||
git add LICENSE ; git commit -m "build(core): add license";
|
||||
```
|
||||
|
||||
- [x] set readmd and commit it
|
||||
```bash
|
||||
git add README.md ; git commit -m "docs(core): add readme";
|
||||
```
|
||||
|
||||
- [ ] get time with format
|
||||
```bash
|
||||
format="+%Y-%m-%d %H:%M:%S";time="2021-05-18 13:12:19";date -d "$time" "$format";
|
||||
```
|
||||
|
||||
- [ ] git commit files with custom date
|
||||
```bash
|
||||
git commit -m "chore(core): update readme in github action" --date "$(date "+%Y-%m-%d %H:%M:%S" -d "+8 hour") +0800"
|
||||
```
|
||||
|
||||
- [ ] design project dirs
|
||||
```bash
|
||||
git add release_win/.gitignore;git commit -m "build(core): add gitignore to design project dirs";
|
||||
git add release_win/README.md;git commit -m "docs(core): output *.exe files here";
|
||||
git add release_win/*.ico;git commit -m "build(core): output icon files here";
|
||||
|
||||
|
||||
git add icons/.gitignore;git commit -m "build(core): add gitignore to design project dirs";
|
||||
git add icons/README.md;git commit -m "docs(core): put icon files here as resources";
|
||||
git add icons/*.ico;git commit -m "build(core): add resources files icon";
|
||||
|
||||
git add .vscode/.gitignore;git commit -m "build(core): add gitignore to design project dirs";
|
||||
git add .vscode/README.md;git commit -m "docs(core): put vscode editor config files of project level here";
|
||||
```
|
||||
|
||||
- [ ] add docs about how to setup this
|
||||
```bash
|
||||
git add README.01-SETUP.md ; git commit -m "docs(core): add readme to setup this";
|
||||
```
|
||||
|
||||
- [ ] add docs about how to code before coding
|
||||
```bash
|
||||
git add README.02-BEFORE-CODE.md ; git commit -m "docs(core): add readme to code this";
|
||||
```
|
||||
|
||||
- [ ] add docs about some libs i noted
|
||||
```bash
|
||||
git add README.03-LIB-NOTE.md ; git commit -m "docs(core): add readme to note libs";
|
||||
```
|
||||
|
||||
- [ ] add go code snippets in project level
|
||||
```bash
|
||||
git add .vscode/.gitignore;git commit -m "build(core): add go code snippets in project level";
|
||||
git add .vscode/go.code-snippets;git commit -m "docs(core): add go code snippets";
|
||||
```
|
||||
|
||||
- [ ] add hello world in root dirs
|
||||
```bash
|
||||
git add main.go;git commit -m "build(core): add hello world in root dirs";
|
||||
```
|
||||
|
||||
- [ ] add go mod and workspace
|
||||
```bash
|
||||
git add go.mod go.sum go.work.sum;git commit -m "build(core): add mod and workspace";
|
||||
```
|
||||
|
||||
- [ ] add mod chapter01
|
||||
```bash
|
||||
git add src/chapter01/higo;git commit -m "build(core): add mod chapter01";
|
||||
```
|
||||
|
||||
- [x] push to github repo (the first)
|
||||
```bash
|
||||
git push -u origin main
|
||||
```
|
||||
|
||||
- [ ] replace git protocol with https when failed
|
||||
```bash
|
||||
# set
|
||||
git config --global url."https://".insteadof git://
|
||||
# unset
|
||||
# git config --global --unset url."https://".insteadof
|
||||
```
|
||||
|
||||
- [x] rename github repo remote name from "origin" to "github"
|
||||
```bash
|
||||
git remote rename origin github
|
||||
```
|
||||
|
||||
- [ ] remove github repo remote
|
||||
```bash
|
||||
git remote remove github
|
||||
```
|
||||
|
||||
- [ ] set remote repo url from https to git
|
||||
```bash
|
||||
git remote set-url origin git@github.com:YMC-GitHub/ymc-node-suite-comfyui.git
|
||||
# git remote set-url github git@github.com:YMC-GitHub/ymc-node-suite-comfyui.git
|
||||
```
|
||||
|
||||
|
||||
- [x] speedup github for `git clone`
|
||||
```bash
|
||||
# set
|
||||
git config --global url."https://ghproxy.com/https://github.com".insteadOf "https://github.com"
|
||||
# unset
|
||||
# git config --global --unset url."https://ghproxy.com/https://github.com".insteadOf
|
||||
# get
|
||||
# git config --global url."https://ghproxy.com/https://github.com".insteadOf
|
||||
```
|
||||
|
||||
- [x] unset speedup github for `git clone` when pushing
|
||||
```bash
|
||||
# unset
|
||||
git config --global --unset url."https://ghproxy.com/https://github.com".insteadOf
|
||||
```
|
||||
|
||||
|
||||
- [x] mgnt git credential
|
||||
```powershell
|
||||
# git config --global credential.helper manager
|
||||
# git config --global credential.helper cache
|
||||
# git config --global --unset credential.helper
|
||||
# https://zhuanlan.zhihu.com/p/157751660
|
||||
```
|
||||
|
||||
- [x] add docs about using git for this repo i noted
|
||||
```bash
|
||||
git add README.04-GIT.md ; git commit -m "docs(core): add readme to note git for this repo";
|
||||
git add README.04-GIT.md ; git commit -m "docs(core): put readme to note git for this repo";
|
||||
|
||||
```
|
||||
|
||||
|
||||
- [ ] add docs about using ssh in github i noted
|
||||
```bash
|
||||
git add README.05-SSH.md ; git commit -m "docs(core): add readme to note ssh";
|
||||
```
|
||||
|
||||
- [x] set pull action for this repo
|
||||
```bash
|
||||
# zero:knowledge:s:pull-action
|
||||
# you must know .
|
||||
# git config pull.rebase false # merge
|
||||
git config pull.rebase true # rebase
|
||||
# git config pull.ff only # fast-forward only
|
||||
# zero:knowledge:e:pull-action
|
||||
```
|
||||
|
||||
- [x] keep workspace clean before pulling
|
||||
```bash
|
||||
# git stash
|
||||
```
|
||||
|
||||
- [x] pull remote github repo before pushing again
|
||||
```bash
|
||||
git pull origin main
|
||||
# git pull github main
|
||||
```
|
||||
|
||||
- [x] push remote github repo (no the first time)
|
||||
```bash
|
||||
git push origin main
|
||||
```
|
||||
|
||||
|
||||
- [x] add requirements
|
||||
```bash
|
||||
git add requirements.txt ; git commit -m "build(core): add requirements nodes";
|
||||
```
|
||||
|
||||
- [x] add current custom nodes
|
||||
```bash
|
||||
git add __init__.py YMC_Node_Suite.py; git commit -m "feat(core): add custom nodes";
|
||||
```
|
||||
@@ -2,6 +2,45 @@
|
||||
|
||||
ymc 's nodes for comfyui
|
||||
|
||||
## Usage
|
||||
|
||||
- you can find it in search box : double click + typing keywords( eg. `ymc suite` ,`text` ,`cutoff`,`region`)
|
||||
- you can find it in right mouse menu : `ymc suite`
|
||||
- ~~you can find it in right mouse menu : `ymc/utils` (as alias)~~
|
||||
|
||||
## Nodes
|
||||
- nodes show in console:
|
||||
<div style="text-align: center;">
|
||||
<img src="./shotscreen/nodes.console.png" alt="console" width="256">
|
||||
<!-- <img src="./shotscreen/nodes.right.menu.png" alt="right mouse menu" width="256"> -->
|
||||
</div>
|
||||
|
||||
- nodes show in right mouse menu:
|
||||
|
||||
<div style="text-align: center;">
|
||||
<!-- <img src="./shotscreen/nodes.console.png" alt="console" width="256"> -->
|
||||
<img src="./shotscreen/nodes.right.menu.png" alt="right mouse menu" width="256">
|
||||
</div>
|
||||
|
||||
## Based-on
|
||||
|
||||
- pypi package [yors_comfyui_node_setup](https://pypi.org/project/yors_comfyui_node_setup/) - setup comfyui custom nodes easily
|
||||
|
||||
- pypi package [yors_pano_ansi_color](https://pypi.org/project/yors_pano_ansi_color/) - info msg in console with color in your comfyui custom nodes easily
|
||||
|
||||
- pypi package [yors_pano_zero_field](https://pypi.org/project/yors_pano_zero_field/) - set nodes input field to be HQ in your comfyui custom nodes easily
|
||||
|
||||
- pypi package [yors_pano_list_util](https://pypi.org/project/yors_pano_list_util/) - enjoy python list for python starter in your comfyui custom nodes easily.
|
||||
|
||||
|
||||
## Published to Comfy registry
|
||||
|
||||
- get more details in [publish_to_comfy.yml](.github/workflows/publish_to_comfy.yml)
|
||||
|
||||
- [docs for publishing to comfy registey](https://docs.comfy.org/registry/overview)
|
||||
|
||||
- installed with comfy-cli ? `comfy node registry-install ymc-node-suite-comfyui`
|
||||
|
||||
## Author
|
||||
|
||||
name|email|desciption
|
||||
@@ -12,3 +51,25 @@ WASasquatch|<jordanslost@gmail.com>|refer to its code [was-node-suite-comfyui](h
|
||||
|
||||
## License
|
||||
MIT
|
||||
|
||||
## Changelog
|
||||
|
||||
### 3.0.0
|
||||
|
||||
- [x] refator(core): rename project dirs and all nodes name for hight qulity nodes.
|
||||
|
||||
### 2.0.0
|
||||
|
||||
- [x] feat(core): rename 'Save Text File' to io-text-save for issue 3
|
||||
|
||||
### 1.1.0
|
||||
- [x] feat(core): add feat that noted in issue 1
|
||||
|
||||
|
||||
### 1.0.0
|
||||
|
||||
~~get more on [changelog of feat](./CHANGELOG.FEAT.md)~~
|
||||
|
||||
## todo
|
||||
|
||||
todo: add details of feat in markdown file and show node list in image
|
||||
|
||||
-2108
File diff suppressed because it is too large
Load Diff
+70
-2
@@ -1,3 +1,71 @@
|
||||
from .YMC_Node_Suite import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
# v1
|
||||
# from yors_comfyui_node_setup import entry,node_install_requirements # global
|
||||
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
|
||||
# # install requirements
|
||||
# node_install_requirements(__file__)
|
||||
|
||||
# # export comfyui node vars
|
||||
# __all__,NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = entry(__name__,__file__)
|
||||
|
||||
# v4
|
||||
import os
|
||||
from yors_comfyui_node_setup import custom_nodes_get_path,custom_nodes_add_to_sys,import_custom_node_module,node_install_requirements,get_module_name_contains_x_in_sys,get_node_class_in_sys_modules,register_node_list_local
|
||||
from yors_pano_ansi_color import info_status,info_step,msg_padd,log_msg
|
||||
import importlib
|
||||
|
||||
info_step("add comfui/custom_nodes to sys.path")
|
||||
custom_nodes_path = [custom_nodes_get_path(__file__,'../../custom_nodes')]
|
||||
custom_nodes_add_to_sys(custom_nodes_path)
|
||||
|
||||
info_step("import modules in sub diretory modules")
|
||||
import_custom_node_module(os.path.dirname(__file__),__name__,"modules")
|
||||
|
||||
# info_step(f"install deps (not installed) in requirements.txt if file exits")
|
||||
# node_install_requirements(__file__)
|
||||
|
||||
# info_step(f"read name in sys.modules if name including name")
|
||||
# - custom_node_module_class_name_list = read_module_class_name(__name__)
|
||||
# custom_node_module_class_name_list = get_module_name_contains_x_in_sys(__name__)
|
||||
|
||||
info_step(f"read valid node class if key in sys.modules including this module name")
|
||||
# - NodeClassList,NodeClassNameList = read_module_valid_node_class(__name__)
|
||||
NodeClassList,NodeClassNameList = get_node_class_in_sys_modules(__name__)
|
||||
|
||||
info_step(f"make node_class_mappings and node_display_name_mappings {__name__}")
|
||||
NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = register_node_list_local(NodeClassList)
|
||||
|
||||
info_step(f"print node name of {__name__}")
|
||||
NODE_MENU_NAMES.sort()
|
||||
# print("\n".join(NODE_MENU_NAMES))
|
||||
|
||||
|
||||
# register node with default category
|
||||
# - NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = register_node_list(this_module_all_classes,False)
|
||||
# NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = register_node_list_local(this_module_all_classes,False)
|
||||
|
||||
# addtional register node with custom category
|
||||
# NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = register_node_list_local(this_module_all_classes,True,"ymc/suite")
|
||||
# print(NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES)
|
||||
# print("\n".join(NODE_MENU_NAMES))
|
||||
|
||||
# info_step(f"define __all__ (not web ext) {__name__}")
|
||||
# __all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
|
||||
|
||||
info_step(f"define __all__ (support web ext) {__name__}")
|
||||
WEB_DIRECTORY = "./web"
|
||||
# docs(core): export NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,WEB_DIRECTORY
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
|
||||
|
||||
# get version from pyproject.toml
|
||||
# ...
|
||||
version="3.0.0"
|
||||
|
||||
log_msg(msg_padd("=",60,"="))
|
||||
log_msg(msg_padd("welocme to ymc_node_suite_comfyui",60,"="))
|
||||
log_msg(f'version: {version}')
|
||||
log_msg(f'node counts:{len(NODE_MENU_NAMES)}')
|
||||
log_msg(f'node menu names:')
|
||||
for node_name in NODE_MENU_NAMES:
|
||||
# log_msg(f'node name:{node_name}')
|
||||
info_status(f'{node_name}',0)
|
||||
log_msg(msg_padd("=",60,"="))
|
||||
@@ -0,0 +1,141 @@
|
||||
以下是代码中定义的 ComfyUI 节点(Nodes)及其功能的解读:
|
||||
|
||||
---
|
||||
|
||||
### **1. IO 相关节点**
|
||||
- **`io-text-save` (save text file)**
|
||||
- **功能**:将文本保存到文件中,支持路径和文件名生成规则(如时间戳、自定义前缀等)。
|
||||
- **输入**:文本内容、路径、文件名前缀、扩展名等。
|
||||
- **输出**:保存的文本内容、文件名(不含扩展名)、扩展名。
|
||||
- **特点**:支持历史记录管理,路径自动创建。
|
||||
|
||||
- **`io-util-file-list-get`**
|
||||
- **功能**:获取指定目录下匹配特定模式的文件列表(如 `*.txt`)。
|
||||
- **输入**:目录路径、文件匹配模式(如 `*.txt`)。
|
||||
- **输出**:文件列表(每行一个文件名或绝对路径)。
|
||||
|
||||
- **`io-util-file-list-get-text`**
|
||||
- **功能**:读取指定目录下所有匹配文件的文本内容并合并。
|
||||
- **输入**:目录路径、文件匹配模式。
|
||||
- **输出**:合并后的多行文本。
|
||||
|
||||
---
|
||||
|
||||
### **2. 文本处理节点**
|
||||
- **`text-util-join-text`**
|
||||
- **功能**:将多个输入文本用分隔符连接成一个字符串。
|
||||
- **输入**:分隔符和最多 7 个文本字段。
|
||||
- **输出**:合并后的字符串。
|
||||
|
||||
- **`text-util-search-text`**
|
||||
- **功能**:在文本中搜索并替换内容。
|
||||
- **输入**:原始文本、搜索字符串、替换字符串。
|
||||
- **输出**:替换后的文本。
|
||||
|
||||
- **`text-util-random-text`**
|
||||
- **功能**:从分隔符(如 `|`)分隔的文本中随机选择一项。
|
||||
- **输入**:文本、随机种子、分隔符。
|
||||
- **输出**:随机选择的文本和种子。
|
||||
|
||||
- **`text-util-loop-text`**
|
||||
- **功能**:按顺序循环选择分隔符分隔的文本项(基于种子)。
|
||||
- **输入**:文本、种子、分隔符。
|
||||
- **输出**:选择的文本、种子、当前索引。
|
||||
|
||||
- **`text-util-switch-text`**
|
||||
- **功能**:根据布尔值切换输出两个文本之一。
|
||||
- **输入**:两个文本、布尔值(0 或 1)。
|
||||
- **输出**:选择的文本。
|
||||
|
||||
---
|
||||
|
||||
### **3. 提示词(Prompt)处理节点**
|
||||
- **`text-util-prompt-join`**
|
||||
- **功能**:合并多个提示词,自动去重和标准化格式。
|
||||
- **输入**:最多 7 个提示词字段。
|
||||
- **输出**:合并后的提示词。
|
||||
|
||||
- **`text-util-prompt-del`**
|
||||
- **功能**:从提示词中删除指定内容。
|
||||
- **输入**:原始提示词、待删除内容。
|
||||
- **输出**:清理后的提示词。
|
||||
|
||||
- **`text-util-prompt-std`**
|
||||
- **功能**:标准化提示词(去除多余空格、换行等)。
|
||||
- **输入**:原始提示词。
|
||||
- **输出**:标准化后的提示词。
|
||||
|
||||
- **`text-util-prompt-shuffle`**
|
||||
- **功能**:随机打乱提示词顺序(可选保留前 N 项)。
|
||||
- **输入**:提示词、随机种子、保留项数。
|
||||
- **输出**:打乱后的提示词。
|
||||
|
||||
---
|
||||
|
||||
### **4. 区域(Region)工具节点**
|
||||
- **`region-util-get-by-center-and-size`**
|
||||
- **功能**:根据中心点坐标和宽高计算裁剪区域的边界(左、上、右、下)。
|
||||
- **输入**:中心点坐标 `(cx, cy)`、宽 `w`、高 `h`。
|
||||
- **输出**:边界坐标和中心点信息。
|
||||
|
||||
- **`region-util-get-by-lt`**
|
||||
- **功能**:根据左上角坐标和宽高计算裁剪区域的边界。
|
||||
- **输入**:左上角坐标 `(left, top)`、宽 `w`、高 `h`。
|
||||
- **输出**:边界坐标和中心点信息。
|
||||
|
||||
- **`region-util-get-pad-out-location-by-size`**
|
||||
- **功能**:根据宽高计算填充(Padding)后的边界坐标(用于图像扩展)。
|
||||
- **输入**:宽 `w`、高 `h`。
|
||||
- **输出**:填充后的边界坐标。
|
||||
|
||||
---
|
||||
|
||||
### **5. 画布(Canvas)工具节点**
|
||||
- **`canvas-util-cal-size`**
|
||||
- **功能**:根据宽高比例(如 `1:1`、`9:16`)调整画布尺寸。
|
||||
- **输入**:原始宽高、比例、锁定模式(固定宽或高)。
|
||||
- **输出**:调整后的宽高。
|
||||
|
||||
---
|
||||
|
||||
### **6. 图像处理节点**
|
||||
- **`img-util-get-image-size`**
|
||||
- **功能**:获取图像的宽度和高度。
|
||||
- **输入**:图像张量。
|
||||
- **输出**:宽、高。
|
||||
|
||||
- **`img-util-switch-input-image`**
|
||||
- **功能**:根据布尔值切换输出两张图像之一。
|
||||
- **输入**:两张图像、布尔值。
|
||||
- **输出**:选择的图像。
|
||||
|
||||
---
|
||||
|
||||
### **7. 条件(Conditioning)工具节点**
|
||||
- **`conditioning-util-input-switch`**
|
||||
- **功能**:根据布尔值切换输出两个条件(Conditioning)之一。
|
||||
- **输入**:两个条件、布尔值。
|
||||
- **输出**:选择的条件。
|
||||
|
||||
---
|
||||
|
||||
### **8. 其他工具节点**
|
||||
- **`number-util-random-num`**
|
||||
- **功能**:生成随机数(整数、浮点数或布尔值)。
|
||||
- **输入**:范围、随机种子。
|
||||
- **输出**:随机数。
|
||||
|
||||
- **`xyz-util-txt-to-int`**
|
||||
- **功能**:将文本描述的数值范围(如 `1-10[5]`)解析为整数或浮点数列表。
|
||||
- **输入**:文本范围、键名(如 `Steps`)。
|
||||
- **输出**:解析后的数值列表和网格标注文本。
|
||||
|
||||
- **`pipe-util-to-basic-pipe`**
|
||||
- **功能**:将模型、CLIP、VAE、条件等组合成基础管道(Basic Pipe)。
|
||||
- **输入**:模型、CLIP、VAE、正负条件。
|
||||
- **输出**:基础管道及各组件。
|
||||
|
||||
---
|
||||
|
||||
### **总结**
|
||||
这些节点覆盖了文本处理、图像操作、区域计算、条件控制、随机生成等常见需求,适合在 ComfyUI 工作流中实现复杂的逻辑组合。每个节点均支持 ComfyUI 的输入输出规范,可直接与其他节点连接使用。
|
||||
@@ -0,0 +1,33 @@
|
||||
## attempted relative import with no known parent package
|
||||
|
||||
### 终端输出内容
|
||||
```terminal
|
||||
Traceback (most recent call last):
|
||||
File "D:\code\python\panz\comfyui-nodes\ymc-node-suite-comfyui\node_demo.py", line 1, in <module>
|
||||
from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
ImportError: attempted relative import with no known parent package
|
||||
```
|
||||
|
||||
### 错误解释
|
||||
- `Traceback (most recent call last)`:这是 Python 错误堆栈跟踪的起始行,表明 Python 开始回溯错误发生的位置。
|
||||
- `File "D:\code\python\panz\comfyui-nodes\ymc-node-suite-comfyui\node_demo.py", line 1, in <module>`:指出错误发生在 `node_demo.py` 文件的第 1 行。
|
||||
- `from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION`:这是出错的代码行,尝试使用相对导入从 `conf` 模块导入 `CURRENT_CATEGORY` 和 `CURRENT_FUNCTION`。
|
||||
- `ImportError: attempted relative import with no known parent package`:错误类型为 `ImportError`,提示使用相对导入时没有找到已知的父包。相对导入需要在包的上下文中使用,当直接运行脚本时,Python 不会将其视为包的一部分,所以会报错。
|
||||
|
||||
### 修复建议
|
||||
#### 方法一:将项目作为包运行
|
||||
如果你想使用相对导入,可以将项目作为包运行。在项目根目录下使用 `-m` 选项:
|
||||
```powershell
|
||||
python -m ymc-node-suite-comfyui.node_demo
|
||||
```
|
||||
|
||||
#### 方法二:使用绝对导入
|
||||
修改 `node_demo.py` 文件,将相对导入改为绝对导入:
|
||||
```python:d:\code\python\panz\comfyui-nodes\ymc-node-suite-comfyui\node_demo.py
|
||||
# 修改前
|
||||
# from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
|
||||
# 修改后
|
||||
from ymc_node_suite_comfyui.conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
```
|
||||
请根据实际的包名调整绝对导入路径。
|
||||
@@ -0,0 +1,22 @@
|
||||
CURRENT_CATEGORY="ymc/suite"
|
||||
CURRENT_FUNCTION="exec"
|
||||
|
||||
class TextInput:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"text": ("STRING",{"multiline": True,"default": ""}),
|
||||
},
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
NODE_DESC = "text - input with multiline input"
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
|
||||
def exec(self,text):
|
||||
|
||||
return (text,)
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
```powershell
|
||||
# 1
|
||||
python __init__.py
|
||||
|
||||
python nodes.py
|
||||
|
||||
|
||||
#
|
||||
python -m main; # run module main done
|
||||
python main.py; # run module main done
|
||||
|
||||
# python node_demo.py
|
||||
|
||||
python -m ymc_node_suite_comfyui.node_demo
|
||||
|
||||
# yours touch docs/ask.for.ai.py.faqs.01.md
|
||||
# yours touch docs/ask.for.ai.py.faqs.02.md
|
||||
|
||||
yours touch docs/ask.for.ai.node-01-the-old-nodes.md
|
||||
yours touch docs/ask.for.ai.node-02-refactor-nodes.md
|
||||
|
||||
yours touch nodes/text/__init__.py
|
||||
yours touch nodes/text/conf.py
|
||||
yours touch nodes/text/join.py
|
||||
yours touch nodes/text/search.py
|
||||
yours touch nodes/text/random.py
|
||||
yours touch nodes/text/loop.py
|
||||
yours touch nodes/text/switch.py
|
||||
yours touch nodes/text/prompts.py #join,std,del,dup,shuffle
|
||||
yours touch nodes/text/input.py
|
||||
|
||||
yours touch nodes/area/__init__.py
|
||||
yours touch nodes/area/conf.py
|
||||
yours touch nodes/area/from_center_and_size.py
|
||||
yours touch nodes/area/from_lefttop_and_size.py
|
||||
yours touch nodes/area/padd.py
|
||||
|
||||
# canvas cal size
|
||||
|
||||
yours touch nodes/image/__init__.py
|
||||
yours touch nodes/image/conf.py
|
||||
yours touch nodes/image/get_image_size.py
|
||||
yours touch nodes/image/switch_image.py
|
||||
|
||||
|
||||
yours touch nodes/utils/__init__.py
|
||||
yours touch nodes/utils/conf.py
|
||||
yours touch nodes/utils/random_num.py
|
||||
yours touch nodes/utils/text_to_int.py
|
||||
yours touch nodes/utils/basic_pipe.py
|
||||
|
||||
yours touch nodes/file/__init__.py
|
||||
yours touch nodes/file/conf.py
|
||||
yours touch nodes/file/get_file_list.py
|
||||
yours touch nodes/file/get_text_of_file_list.py
|
||||
|
||||
|
||||
yours touch nodes/cutoff/__init__.py
|
||||
sh -c "cp nodes/text/__init__.py nodes/cutoff/__init__.py"
|
||||
sh -c "cp nodes/text/conf.py nodes/cutoff/conf.py"
|
||||
|
||||
yours touch nodes/cutoff/text_from.py
|
||||
yours touch nodes/cutoff/text_list_color.py
|
||||
|
||||
python -c "import sys;print(sys.path)"
|
||||
|
||||
# sh -c "rm -rf nodes/text/{input,join,loop,random,search,switch}.py"
|
||||
# sh -c "rm -rf nodes/cutoff"
|
||||
|
||||
# sh -c "rm -rf nodes/cutoff"
|
||||
|
||||
```
|
||||
## fags
|
||||
- ImportError: attempted relative import with no known parent package
|
||||
|
||||
|
||||
## depoy to comfyui (local + debug)
|
||||
```bash
|
||||
# del local nodes in comfyui custom_nodes
|
||||
sh -c "rm -rf /o//app/ComfyUI/custom_nodes/ymc-node-suite-comfyui"
|
||||
# copy local nodes to comfyui custom_nodes
|
||||
sh -c "cp -r /d/code/python/panz/comfyui-nodes/ymc-node-suite-comfyui /o/app/ComfyUI/custom_nodes/"
|
||||
|
||||
|
||||
# conda activate sdwa;cd O:\app\ComfyUI;python main.py;
|
||||
```
|
||||
|
||||
## opv - docs
|
||||
```bash
|
||||
git add README.md ; git commit -m "docs(core): put usage"
|
||||
git add . ; git commit -m "build(core): use shotscreen"
|
||||
git add docs/opv.*.md ; git commit -m "docs(core): put note"
|
||||
|
||||
git add . ; git commit -m "refactor(core): reset dirs"
|
||||
git add . ; git commit -m "refactor(core): rename nodes map"
|
||||
git add . ; git commit -m "refactor(core): rename nodes display name"
|
||||
|
||||
git add . ; git commit -m "refactor(core): put dirs and category"
|
||||
|
||||
# get git msg log with oneline and short hash and msg head and time
|
||||
git log --pretty=format:"%h %ad %s" --date=short -n 5
|
||||
|
||||
git log --oneline -n 5
|
||||
|
||||
git rm CHANGELOG.*.md
|
||||
git rm conf.py
|
||||
git mv node_demo.py docs/node_demo.py.md
|
||||
git rm README.*.md
|
||||
```
|
||||
|
||||
## opv - shotscreen
|
||||
```bash
|
||||
sh -c "mkdir -p shotscreen"
|
||||
|
||||
sh -c "cp -r /o/app/ComfyUI/my_workflows/nodes*.png shotscreen/"
|
||||
|
||||
```
|
||||
|
||||
## changelog
|
||||
|
||||
|
||||
## clog - gen feat of from source code
|
||||
|
||||
```powershell
|
||||
# yours edit-docs -h
|
||||
yours feat --field feat --src-file modules/text/node_plain.py --out-file CHANGELOG.md --mode overide
|
||||
|
||||
yours feat --field feat --src-file modules/text/node_prompt.py --out-file CHANGELOG.md --mode tail
|
||||
|
||||
yours feat --field feat --src-file modules/text/node_pyio.py --out-file CHANGELOG.md --mode tail
|
||||
|
||||
yours feat --field feat --src-file modules/text/node_region.py --out-file CHANGELOG.md --mode tail
|
||||
|
||||
yours feat --field feat --src-file modules/text/node_cutoff_region.py --out-file CHANGELOG.md --mode tail
|
||||
|
||||
# add commit msg for this work:
|
||||
# git add CHANGELOG.md ; git commit -m "chore(core): gen feat of from source code"
|
||||
```
|
||||
|
||||
## clog - code size/feat/docs - name
|
||||
|
||||
```powershell
|
||||
# set description in markdown file ?
|
||||
# yours edit-docs --tpl-file docs.template.md --data "$pkgdesc" --label "<!-- inject-desc -->" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
yours edit-docs --tpl-file docs.template.md --data "$pkgdesc" --label "{description}" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
# set file size in markdown file ?
|
||||
# yours edit-docs --tpl-file README.md --data-file lib-size.md --label "<!-- inject-file-size -->" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
# set features in markdown file ?
|
||||
yours edit-docs --tpl-file README.md --data-file CHANGELOG.md --label "<!-- inject-features -->" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
# set installing package in markdown file ?
|
||||
yours edit-docs --tpl-file README.md --data "$name" --label "{package}" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
|
||||
# set demo in markdown file ?
|
||||
# yours edit-docs --tpl-file README.md --data-file examples/main.py --label "<!-- inject-demo -->" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
# set demo in markdown file ? (demo.md)
|
||||
yours edit-docs --tpl-file README.md --data-file demo.md --label "<!-- inject-demo -->" --out-file README.md --workspace "$wsroot/$pkgsloc/$name"
|
||||
|
||||
|
||||
# add and set msg for this
|
||||
# git add "packages/$name/*.md" ; git commit -m "docs(core): gen docs";
|
||||
|
||||
# git add "packages/$name/*.md" ; git commit -m "docs(core): put docs";
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
from yors_comfyui_node_setup import entry,node_install_requirements
|
||||
node_install_requirements(__file__)
|
||||
__all__,NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = entry(__name__,__file__,False)
|
||||
|
||||
# from . import *
|
||||
@@ -0,0 +1,5 @@
|
||||
from yors_comfyui_node_setup import entry,node_install_requirements
|
||||
node_install_requirements(__file__)
|
||||
__all__,NODE_CLASS_MAPPINGS,NODE_DISPLAY_NAME_MAPPINGS,NODE_MENU_NAMES = entry(__name__,__file__,False)
|
||||
|
||||
# from . import *
|
||||
@@ -0,0 +1,2 @@
|
||||
CURRENT_CATEGORY="ymc suite/text"
|
||||
CURRENT_FUNCTION="exec"
|
||||
@@ -0,0 +1,101 @@
|
||||
# import random
|
||||
from yors_pano_list_util import ListDelExclude,ListFillOne,ListToTupe,ListShuffle
|
||||
|
||||
# from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
|
||||
CURRENT_CATEGORY="ymc suite/text"
|
||||
CURRENT_FUNCTION="exec"
|
||||
|
||||
def StrSetUndefinedAsEmpty(text,deft:str=""):
|
||||
"""
|
||||
target_text=StrSetUndefinedAsEmpty(target_text)
|
||||
|
||||
when text is "undefined", return ""
|
||||
"""
|
||||
if text == "undefined":
|
||||
return deft
|
||||
return text
|
||||
|
||||
# code(core): about shift + tap and tap in vscode
|
||||
|
||||
def CutoffRegionTextBurn(main_text, target_text, weight):
|
||||
"""
|
||||
CutoffRegionTextBurn(main_text,target_text,weight)
|
||||
|
||||
burn region text
|
||||
"""
|
||||
# Converted inputs are sent as the string of 'undefined' if not connected
|
||||
target_text = StrSetUndefinedAsEmpty(target_text)
|
||||
main_text = StrSetUndefinedAsEmpty(main_text)
|
||||
|
||||
region_text = ""
|
||||
if weight is None or weight == "" or weight == "1.0":
|
||||
region_text = (" ").join(filter(None, [target_text, main_text]))
|
||||
else:
|
||||
# region_text = (" ").join(filter(None, ["(",target_text, main_text,":",weight,")"]))
|
||||
region_text = (" ").join(filter(None, [target_text, main_text]))
|
||||
region_text = ("").join(filter(None, ["(", region_text, ":", weight, ")"]))
|
||||
# return {"ui": {"text": (region_text,)}, "result": (region_text,)}
|
||||
return region_text, target_text, weight
|
||||
|
||||
|
||||
# feat(core): NodeCutoffRegionTextBurn - cutoff - region text burn
|
||||
class NodeCutoffRegionTextBurn:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"main_text": ("STRING", {"default": "dress", "multiline": True}),
|
||||
"target_text":("STRING", {"default": "white", "multiline": False}),
|
||||
"weight": ("STRING", {"default": "1.0", "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING","STRING",)
|
||||
RETURN_NAMES = ('region_text','target_text','prompt_weight')
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "cutoff - region text burn"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, main_text,target_text,weight):
|
||||
return CutoffRegionTextBurn(main_text,target_text,weight)
|
||||
|
||||
|
||||
TEXT_BASE_COLORS=['red','orange','yellow','green','cyan','blue','purple','black','white','pink','custom']
|
||||
TEXT_BASE_COLORS_COUNT=len(TEXT_BASE_COLORS)
|
||||
|
||||
|
||||
def CutoffColorTextPreset(custom:str="sliver"):
|
||||
"""
|
||||
CutoffColorTextList(custom)
|
||||
|
||||
color text preset will update the last one will custom
|
||||
"""
|
||||
# return red,orange,yellow,green,cyan,blue,purple,black,white,pink,custom
|
||||
TEXT_BASE_COLORS_VALUE = TEXT_BASE_COLORS.copy()
|
||||
TEXT_BASE_COLORS_VALUE[TEXT_BASE_COLORS_COUNT-1]=custom
|
||||
return ListToTupe(TEXT_BASE_COLORS_VALUE)
|
||||
|
||||
# feat(core): NodeCutoffRegionColorTextPreset - cutoff - color preset of region text
|
||||
class NodeCutoffRegionColorTextPreset:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"custom": ("STRING", {"default": "red", "multiline": False})
|
||||
}
|
||||
}
|
||||
|
||||
# RETURN_TYPES = ("STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING","STRING",)
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('STRING',TEXT_BASE_COLORS_COUNT))
|
||||
RETURN_NAMES = ListToTupe(TEXT_BASE_COLORS)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "cutoff - color preset of region text"
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, custom):
|
||||
# Converted inputs are sent as the string of 'undefined' if not connected
|
||||
custom=StrSetUndefinedAsEmpty(custom,"sliver")
|
||||
return CutoffColorTextPreset(custom)
|
||||
@@ -0,0 +1,503 @@
|
||||
import random
|
||||
from yors_pano_list_util import ListDelExclude,ListFillOne,ListToTupe,ListShuffle
|
||||
|
||||
from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
|
||||
def TextListRandom(text:str, seed,char='|'):
|
||||
"""
|
||||
item,seed = TextListRandom(text,seed,'|')
|
||||
|
||||
TextListRandom(text,seed,',')
|
||||
"""
|
||||
iteml = text.split(char)
|
||||
random.seed(seed)
|
||||
choice = random.choice(iteml)
|
||||
return ListToTupe([choice,seed])
|
||||
|
||||
|
||||
def range_safe(i:int,s:int,e:int):
|
||||
'''
|
||||
ensure i is in [s,e]
|
||||
'''
|
||||
res=i
|
||||
if res <s:
|
||||
res=s
|
||||
if res >e:
|
||||
res=e
|
||||
return res
|
||||
|
||||
def range_safe_loop(i:int,s:int,e:int):
|
||||
'''
|
||||
ensure i is in [s,e] for loop
|
||||
'''
|
||||
res=i
|
||||
if res <s:
|
||||
res=s
|
||||
if res >=e:
|
||||
res = res % e
|
||||
res = s + res
|
||||
return res
|
||||
|
||||
def TextListLoop(text, seed,char='|'):
|
||||
iteml = text.split(char)
|
||||
# get loop index with de/cr seed
|
||||
length=len(iteml)
|
||||
index=range_safe_loop(seed-1,0,length)
|
||||
choice = iteml[index]
|
||||
# print(maxindex,seed,index,choice)
|
||||
return ListToTupe([choice,seed,str(index+1),length])
|
||||
|
||||
|
||||
|
||||
def TextReplace(text, find, replace):
|
||||
"""
|
||||
text replace find with re.sub
|
||||
"""
|
||||
import re
|
||||
result = re.sub(find, replace, text)
|
||||
return result
|
||||
|
||||
|
||||
|
||||
TEXT_LIST_RETURN_NAMES=['a','b','c','d','e','f','g']
|
||||
TEXT_LIST_COUNT=len(TEXT_LIST_RETURN_NAMES)
|
||||
TEXT_LIST_ADV_RETURN_NAMES=TEXT_LIST_RETURN_NAMES.copy()
|
||||
TEXT_LIST_ADV_RETURN_NAMES.insert(0,"prefix")
|
||||
# feat(core): NodePlainTextList - input text preset
|
||||
class NodePlainTextList:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"a": ("STRING",{"forceInput":False}),
|
||||
"b": ("STRING",{"forceInput":False}),
|
||||
"c": ("STRING",{"forceInput":False}),
|
||||
"d": ("STRING",{"forceInput":False}),
|
||||
"e": ("STRING",{"forceInput":False}),
|
||||
"f": ("STRING",{"forceInput":False}),
|
||||
"g": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('STRING',TEXT_LIST_COUNT))
|
||||
RETURN_NAMES = ListToTupe(TEXT_LIST_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - input text preset"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, a,b,c,d,e,f,g):
|
||||
return ListToTupe([a,b,c,d,e,f,g])
|
||||
|
||||
# feat(core): NodePlainTextListAdv - input text preset - adv
|
||||
class NodePlainTextListAdv:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"prefix": ("STRING",{"forceInput":False}),
|
||||
"a": ("STRING",{"forceInput":False}),
|
||||
"b": ("STRING",{"forceInput":False}),
|
||||
"c": ("STRING",{"forceInput":False}),
|
||||
"d": ("STRING",{"forceInput":False}),
|
||||
"e": ("STRING",{"forceInput":False}),
|
||||
"f": ("STRING",{"forceInput":False}),
|
||||
"g": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('STRING',TEXT_LIST_COUNT+1))
|
||||
RETURN_NAMES = ListToTupe(TEXT_LIST_ADV_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - input text preset - adv"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self,prefix, a,b,c,d,e,f,g):
|
||||
joined = list(map(lambda x: prefix+x,[a,b,c,d,e,f,g]))
|
||||
import datetime
|
||||
# import time
|
||||
joined.insert(0,prefix)
|
||||
joined = list(map(lambda x: datetime.datetime.now().strftime(x),joined)) # replace time exp like %Y %M %D
|
||||
return ListToTupe(joined)
|
||||
|
||||
# feat(core): NodePlainTextListJoinTextAdv - join text to text preset - adv
|
||||
class NodePlainTextListJoinTextAdv:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
|
||||
},
|
||||
"optional": {
|
||||
"text": ("STRING",{"forceInput": True}),
|
||||
"a": ("STRING",{"forceInput":True}),
|
||||
"b": ("STRING",{"forceInput":True}),
|
||||
"c": ("STRING",{"forceInput":True}),
|
||||
"d": ("STRING",{"forceInput":True}),
|
||||
"e": ("STRING",{"forceInput":True}),
|
||||
"f": ("STRING",{"forceInput":True}),
|
||||
"g": ("STRING",{"forceInput":True}),
|
||||
"action": (["none","text-as-head","text-as-tail"],),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('STRING',TEXT_LIST_COUNT+1))
|
||||
RETURN_NAMES = ListToTupe(['text','a','b','c','d','e','f','g'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - join text to text preset - adv"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self,text, a,b,c,d,e,f,g,action="none"):
|
||||
joined=[]
|
||||
if "none" in action:
|
||||
joined = [a,b,c,d,e,f,g]
|
||||
elif "text-as-head" in action:
|
||||
joined = list(map(lambda x: text+x,[a,b,c,d,e,f,g]))
|
||||
elif "text-as-tail" in action:
|
||||
joined = list(map(lambda x: x+text,[a,b,c,d,e,f,g]))
|
||||
import datetime
|
||||
# import time
|
||||
joined.insert(0,text)
|
||||
joined = list(map(lambda x: datetime.datetime.now().strftime(x),joined)) # replace time exp like %Y %M %D
|
||||
return ListToTupe(joined)
|
||||
|
||||
# feat(core): NodePlainTextJoin - join text
|
||||
class NodePlainTextJoin:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"splitchar": ("STRING", {"default": "_", "multiline": False}),
|
||||
"a": ("STRING",{"forceInput":False}),
|
||||
"b": ("STRING",{"forceInput":False}),
|
||||
"c": ("STRING",{"forceInput":False}),
|
||||
"d": ("STRING",{"forceInput":False}),
|
||||
"e": ("STRING",{"forceInput":False}),
|
||||
"f": ("STRING",{"forceInput":False}),
|
||||
"g": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('STRING',1))
|
||||
RETURN_NAMES = ListToTupe(['text'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - join text"
|
||||
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, splitchar,a,b,c,d,e,f,g):
|
||||
# args to list
|
||||
ls=[a,b,c,d,e,f,g]
|
||||
# ignore none
|
||||
ls = list(filter(None, ls))
|
||||
# join with splitChar
|
||||
joinedtxt=splitchar.join(ls)
|
||||
return ListToTupe([joinedtxt])
|
||||
|
||||
# feat(core): NodePlainTextRandom - random text in list
|
||||
class NodePlainTextRandom:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"default": '', "multiline": False}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"char": ("STRING", {"default": '|', "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",'INT',)
|
||||
RETURN_NAMES = ListToTupe(['text','seed'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - random text in list"
|
||||
def exec(self, text, seed,char='|'):
|
||||
return TextListRandom(text,seed,char)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
# feat(core): NodePlainTextLoop - get text in list (loop)
|
||||
class NodePlainTextLoop:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"default": '', "multiline": False}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
"char": ("STRING", {"default": '|', "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",'INT','STRING','INT')
|
||||
RETURN_NAMES = ListToTupe(['text','seed','index','count'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - get text in list (loop)"
|
||||
|
||||
def exec(self, text, seed,char='|'):
|
||||
return TextListLoop(text, seed,char)
|
||||
|
||||
@classmethod
|
||||
def IS_CHANGED(cls, **kwargs):
|
||||
return float("NaN")
|
||||
|
||||
# feat(core): NodePlainTextReplace - replace text
|
||||
class NodePlainTextReplace:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"default": '', "multiline": False}),
|
||||
"find": ("STRING", {"default": '', "multiline": False}),
|
||||
"replace": ("STRING", {"default": '', "multiline": False}),
|
||||
"action": (["yes",'no'],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ListToTupe(['text'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - replace"
|
||||
|
||||
|
||||
def exec(self, text, find, replace,action='yes'):
|
||||
# feat(core): do nothing when action no
|
||||
if 'no' in action:
|
||||
return ListToTupe([text])
|
||||
# feat(core): replace text
|
||||
return ListToTupe([TextReplace(text, find, replace)])
|
||||
|
||||
|
||||
def NumStrToNumInt(str:str="1",roundit:bool=True):
|
||||
"""
|
||||
NumStrToNumInt(0.5)
|
||||
NumStrToNumInt(float(str))
|
||||
"""
|
||||
if roundit == True:
|
||||
return int(round(str))
|
||||
return int(str)
|
||||
|
||||
def NumStrIsRoundToA(a='1', isRoundTo='1'):
|
||||
"""
|
||||
NumStrIsRoundToA("0.8","1")
|
||||
NumStrIsRoundToA("0.4","1")
|
||||
"""
|
||||
if NumStrToNumInt(a) == NumStrToNumInt(isRoundTo):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def BoolStr2BoolNum(str:str="true"):
|
||||
"""
|
||||
BoolStr2BoolNum("TRUE")
|
||||
BoolStr2BoolNum("false")
|
||||
"""
|
||||
# true,TRUE
|
||||
if str=="true":
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
# feat(core): NodeNumStrToNum - text to number
|
||||
class NodeNumStrToNum:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"default": '', "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
# RETURN_TYPES = ('NUMBER',)
|
||||
RETURN_TYPES = ("NUMBER", "FLOAT", "INT")
|
||||
RETURN_NAMES = ListToTupe(["number", "float", "roundInt"])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - to number"
|
||||
|
||||
def exec(self, text=''):
|
||||
strInt = int(text)
|
||||
strFlo = float(text)
|
||||
strRoundInt = int(round(strFlo))
|
||||
return ListToTupe([strInt,strFlo,strRoundInt])
|
||||
|
||||
# feat(core): NodeNumStrToBool - text to bool
|
||||
class NodeNumStrToBool:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"default": '1', "multiline": False}),
|
||||
"isRoundTo":("STRING", {"default": '1', "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ('STRING',)
|
||||
RETURN_NAMES = ListToTupe(["boolean"])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - is round to x"
|
||||
|
||||
def exec(self, a='1', isRoundTo='1'):
|
||||
return ListToTupe([NumStrIsRoundToA(a,isRoundTo)])
|
||||
|
||||
# feat(core): NodePlainTextSwitchWithBool - text switch with bool
|
||||
class NodePlainTextSwitchWithBool:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"a": ("STRING", {"default": '', "multiline": False}),
|
||||
"b": ("STRING", {"default": '', "multiline": False}),
|
||||
"boolean": ("BOOL",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ('STRING',)
|
||||
RETURN_NAMES = ListToTupe(["text"])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - switch a and b"
|
||||
|
||||
def exec(self, a='', b='', boolean:bool=True):
|
||||
if boolean==True:
|
||||
return (a, )
|
||||
else:
|
||||
return (b, )
|
||||
|
||||
# feat(core): NodePlainTextSwitchWithText - text switch with text
|
||||
class NodePlainTextSwitchWithText:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"a": ("STRING", {"default": '', "multiline": False}),
|
||||
"b": ("STRING", {"default": '', "multiline": False}),
|
||||
"text": ("STRING", {"default": '1', "multiline": False}),
|
||||
"isRoundTo":("STRING", {"default": '1', "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ('STRING',)
|
||||
RETURN_NAMES = ListToTupe(["text"])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - switch a and b (isRoundTo)"
|
||||
def exec(self, a='', b='', text='1',isRoundTo='1'):
|
||||
if NumStrIsRoundToA(text,isRoundTo):
|
||||
return (a, )
|
||||
else:
|
||||
return (b, )
|
||||
|
||||
# class NodeTextShow:
|
||||
# @classmethod
|
||||
# def INPUT_TYPES(s):
|
||||
# return {"required": {
|
||||
# "text": ("STRING", {"forceInput": True}),
|
||||
# }}
|
||||
|
||||
# # INPUT_IS_LIST = True
|
||||
# FUNCTION = CURRENT_FUNCTION
|
||||
# CATEGORY = CURRENT_CATEGORY
|
||||
# NODE_DESC = "plain - show text"
|
||||
# OUTPUT_NODE = True
|
||||
# RETURN_TYPES = ('STRING',)
|
||||
# # OUTPUT_IS_LIST = (True,)
|
||||
|
||||
# def exec(self, text):
|
||||
# return {"ui": {"text": text}, "result": (text,)}
|
||||
# refer: pythongosssss /ComfyUI-Custom-Scripts/py/show_text.py
|
||||
|
||||
# feat(core): NodeTextShow - show text
|
||||
class NodeTextShow:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING", {"forceInput": True}),
|
||||
},
|
||||
"hidden": {
|
||||
"unique_id": "UNIQUE_ID",
|
||||
"extra_pnginfo": "EXTRA_PNGINFO",
|
||||
},
|
||||
}
|
||||
|
||||
INPUT_IS_LIST = True
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - show text"
|
||||
OUTPUT_NODE = True
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
def exec(self, text, unique_id = None, extra_pnginfo=None):
|
||||
if unique_id and extra_pnginfo and "workflow" in extra_pnginfo[0]:
|
||||
workflow = extra_pnginfo[0]["workflow"]
|
||||
node = next((x for x in workflow["nodes"] if str(x["id"]) == unique_id[0]), None)
|
||||
if node:
|
||||
node["widgets_values"] = [text]
|
||||
return {"ui": {"text": text}, "result": (text,)}
|
||||
|
||||
# feat(core): NodeTextCalcSize - cacluate width and height
|
||||
class NodeTextCalcSize:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"w": ("INT", {"default":512, "max": 10000000, "min":0, "step":1}),
|
||||
"h": ("INT", {"default":512, "max": 10000000, "min":0, "step":1}),
|
||||
"lockoff": (["false", "w","h"],),
|
||||
# "rate": (["1:1", "2:3","9:16"],),
|
||||
"rate": ("STRING", {"default": "1:1", "multiline": False}),
|
||||
"reverse": (["false", "true"],),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('INT',2))
|
||||
RETURN_NAMES = ListToTupe(['w','h'])
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "plain - cacluate width and height"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self,w=512, h=512,lockoff='false',rate='1:1',reverse='false'):
|
||||
rw=w
|
||||
rh=h
|
||||
# get h or w with lockoff
|
||||
if lockoff != "false":
|
||||
ratel=list(map(int,rate.split(":")))
|
||||
raten=(ratel[0]/ratel[1])
|
||||
if lockoff == "w":
|
||||
rh=int(w/raten)
|
||||
if lockoff == "h":
|
||||
rw=int(h*raten)
|
||||
|
||||
floatl=[rw,rh]
|
||||
# reverse result of w h
|
||||
if reverse == "true":
|
||||
floatl=[rh,rw]
|
||||
intl=list(map(int,floatl))
|
||||
return ListToTupe(intl)
|
||||
@@ -0,0 +1,615 @@
|
||||
import re
|
||||
import random
|
||||
|
||||
from yors_pano_list_util import ListDelExclude,ListFillOne,ListToTupe,ListShuffle
|
||||
|
||||
# use current_category and current_function from con.py in current directory
|
||||
# from .conf import CURRENT_CATEGORY,CURRENT_FUNCTION
|
||||
|
||||
# docs(core): use current_category and current_function in this file
|
||||
CURRENT_CATEGORY="ymc suite/text"
|
||||
CURRENT_FUNCTION="exec"
|
||||
|
||||
def tags_listify(s:str):
|
||||
ls = s.split(",")
|
||||
ls = list(filter(None, ls))
|
||||
return ls
|
||||
|
||||
def tags_strify(l:list[str]):
|
||||
return ','.join(l)
|
||||
|
||||
def tag_trim(s:str):
|
||||
trimedtag=s
|
||||
trimedtag=re.sub(r'^ *', '', trimedtag,0)
|
||||
trimedtag=re.sub(r' *$', '', trimedtag,0)
|
||||
return trimedtag
|
||||
|
||||
def tag_ms2os(s:str):
|
||||
return re.sub(re.compile(r' {1,}'), ' ', s,0)
|
||||
|
||||
def tag_unweight(s:str):
|
||||
# unweight,trim,
|
||||
unwdtag=s.replace("(","").replace(")","")
|
||||
unwdtag=re.sub(r':\d.*', '', unwdtag,0)
|
||||
unwdtag=tag_trim(unwdtag)
|
||||
unwdtag=tag_ms2os(unwdtag)
|
||||
return unwdtag
|
||||
|
||||
def tags_unweight(s:str):
|
||||
ls=tags_listify(s)
|
||||
nls=[]
|
||||
for tag in ls:
|
||||
stdedtag=tag_unweight(tag)
|
||||
if stdedtag !="":
|
||||
nls.append(stdedtag)
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_onelineify(s:str):
|
||||
return re.sub(r'\n', ',', s,0)
|
||||
|
||||
def tag_std(s:str):
|
||||
# trim,ms2os
|
||||
stdedtag=s
|
||||
stdedtag=tag_trim(stdedtag)
|
||||
stdedtag=tag_ms2os(stdedtag)
|
||||
return stdedtag
|
||||
|
||||
|
||||
def tags_dup(s:str):
|
||||
nls=tags_listify(s)
|
||||
nls=list(dict.fromkeys(nls))
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_std(s:str):
|
||||
ls=tags_listify(s)
|
||||
nls=[]
|
||||
for tag in ls:
|
||||
stdedtag=tag_std(tag)
|
||||
if stdedtag !="":
|
||||
nls.append(stdedtag)
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_ignore(s:str,i:str):
|
||||
ls=tags_listify(s)
|
||||
li=tags_listify(i)
|
||||
|
||||
nls=[]
|
||||
for tag in ls:
|
||||
stdedtag=tag_unweight(tag)
|
||||
if stdedtag !="" and not(stdedtag in li):
|
||||
nls.append(tag)
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_replace(s:str,i:str,r:str):
|
||||
ls=tags_listify(s)
|
||||
li=tags_listify(i)
|
||||
# lr=tags_listify(r)
|
||||
|
||||
nls=[]
|
||||
for tag in ls:
|
||||
stdedtag=tag_unweight(tag)
|
||||
if stdedtag !="":
|
||||
if stdedtag in li:
|
||||
# replace found with r
|
||||
nls.append(r)
|
||||
else:
|
||||
nls.append(tag)
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_search(s:str,i:str):
|
||||
ls=tags_listify(s)
|
||||
li=tags_listify(i)
|
||||
nls=[]
|
||||
for tag in ls:
|
||||
stdedtag=tag_unweight(tag)
|
||||
if stdedtag !="" :
|
||||
for pattern in li:
|
||||
if pattern in stdedtag:
|
||||
nls.append(tag)
|
||||
return ",".join(nls)
|
||||
|
||||
def tags_head(s:str,i:str):
|
||||
"""
|
||||
move some tags to head
|
||||
"""
|
||||
head=tags_listify(i)
|
||||
tails=tags_listify(tags_ignore(s,i))
|
||||
return ",".join(head+tails)
|
||||
|
||||
def tags_tail(s:str,i:str):
|
||||
"""
|
||||
move some tags to head
|
||||
"""
|
||||
tails=tags_listify(i)
|
||||
head=tags_listify(tags_ignore(s,i))
|
||||
return ",".join(head+tails)
|
||||
|
||||
|
||||
# feat(core): NodePromptAdd - prompt add some text
|
||||
class NodePromptAdd:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
"toadd": ("STRING",{"forceInput":False}),
|
||||
"action": (["add2head",'add2tail','del|add2head','del|add2tail','none'],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - add"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, text='',toadd='',action='add2head'):
|
||||
# if action =="add2head":
|
||||
# return list_2_tupe([tags_head(text,prev)])
|
||||
# if action =="add2tail":
|
||||
# return list_2_tupe([tags_tail(text,prev)])
|
||||
if 'none' in action:
|
||||
return ListToTupe([text])
|
||||
prev=toadd
|
||||
if 'del' in action:
|
||||
prev=tags_ignore(text,toadd)
|
||||
if 'add2head' in action:
|
||||
prev=tags_head(text,prev)
|
||||
if 'add2tail' in action:
|
||||
prev=tags_tail(text,prev)
|
||||
return ListToTupe([prev])
|
||||
|
||||
# feat(core): NodePromptAdvAdd - prompt add some text (adv)
|
||||
class NodePromptAdvSearch:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
"search": ("STRING",{"forceInput":False}),
|
||||
"action": (['none',"del", "move2head",'move2tail',"replace","search"],),
|
||||
"replace": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - search (adv)"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, text='',search='',action='none',replace=''):
|
||||
if action == "none":
|
||||
return ListToTupe([text])
|
||||
|
||||
if action == "search":
|
||||
return ListToTupe([tags_search(text,search)])
|
||||
searchedtags=tags_search(text,search)
|
||||
if action =="replace":
|
||||
return ListToTupe([tags_replace(text,searchedtags,replace)])
|
||||
if action =="del":
|
||||
return ListToTupe([tags_ignore(text,searchedtags)])
|
||||
if action =="move2head":
|
||||
return ListToTupe([tags_head(text,searchedtags)])
|
||||
if action =="move2tail":
|
||||
return ListToTupe([tags_tail(text,searchedtags)])
|
||||
|
||||
# feat(core): NodePromptSearch - prompt search some text
|
||||
class NodePromptSearch:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
"search": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - search"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, text='',search=''):
|
||||
return ListToTupe([tags_search(text,search)])
|
||||
|
||||
# feat(core): NodePromptDup - prompt dup some text
|
||||
class NodePromptDup:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - dup"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, text):
|
||||
return ListToTupe([tags_dup(text)])
|
||||
|
||||
# feat(core): NodePromptAdvDup - prompt dup some text (adv)
|
||||
class NodePromptAdvDup:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
# "mode": (["alline", "in-each-line"],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING",)
|
||||
RETURN_NAMES = ('STRING',"STRING",)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - dup (adv)"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
def exec(self, text):
|
||||
a=''
|
||||
res=[]
|
||||
textl=text.split("\n")
|
||||
for line in textl:
|
||||
res.append(tags_dup(line))
|
||||
a='\n'.join(res)
|
||||
|
||||
tags_dup(tags_onelineify(text))
|
||||
return ListToTupe([tags_dup(tags_onelineify(a)),a])
|
||||
|
||||
# feat(core): NodePromptShuffle - prompt shuffle some text
|
||||
class NodePromptShuffle:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
"keep_n_token": ("STRING", {"default": "0", "multiline": False}),
|
||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - shuffle"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, text='',keep_n_token='0',seed=0):
|
||||
random.seed(seed)
|
||||
textl=tags_listify(tags_onelineify(text))
|
||||
el=ListShuffle(textl,int(keep_n_token))
|
||||
return ListToTupe([','.join(el)])
|
||||
|
||||
# feat(core): NodePromptDel - prompt del some text
|
||||
class NodePromptDel:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"search": ("STRING",{"forceInput":False}),
|
||||
"todel": ("STRING",{"forceInput":False}),
|
||||
"action": (["yes",'no'],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - del"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, search='',todel='',action='yes'):
|
||||
# https://www.geeksforgeeks.org/python-remove-empty-strings-from-list-of-strings/
|
||||
if 'no' in action:
|
||||
return ListToTupe([search])
|
||||
ca=tags_ignore(search,tags_unweight(todel))
|
||||
return ListToTupe([ca])
|
||||
|
||||
# feat(core): NodePromptStd - prompt std
|
||||
class NodePromptStd:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - std"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, text):
|
||||
return ListToTupe([tags_std(text)])
|
||||
|
||||
# feat(core): NodePromptInput - prompt input
|
||||
class NodePromptInput:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"default": "","multiline":True}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('text',)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - input"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, text=''):
|
||||
return ListToTupe([tags_std(text)])
|
||||
|
||||
# feat(core): NodePromptUnweight - prompt unweight
|
||||
class NodePromptUnweight:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"text": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - unweight"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, text):
|
||||
return ListToTupe([tags_unweight(text)])
|
||||
|
||||
# feat(core): NodePromptJoin - prompt join
|
||||
class NodePromptJoin:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"a": ("STRING",{"forceInput":False}),
|
||||
"b": ("STRING",{"forceInput":False}),
|
||||
"c": ("STRING",{"forceInput":False}),
|
||||
"d": ("STRING",{"forceInput":False}),
|
||||
"e": ("STRING",{"forceInput":False}),
|
||||
"f": ("STRING",{"forceInput":False}),
|
||||
"g": ("STRING",{"forceInput":False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - join"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, a,b,c,d,e,f,g):
|
||||
vl=[a,b,c,d,e,f,g]
|
||||
vs = (",").join(vl)
|
||||
vs=tags_std(vs)
|
||||
# vs = vs.replace(" ", " ").replace(" ,", ",").replace(", ", ",").replace(",,", ",").replace(",,", ",")
|
||||
return {"ui": {"text": (vs,)}, "result": (vs,)}
|
||||
|
||||
|
||||
|
||||
class AnyType(str):
|
||||
"""A special class that is always equal in not equal comparisons. Credit to pythongosssss"""
|
||||
|
||||
def __ne__(self, __value: object) -> bool:
|
||||
return False
|
||||
|
||||
any_type = AnyType("*")
|
||||
|
||||
|
||||
default_prompt1='''Swing
|
||||
Slide
|
||||
Climbing frame
|
||||
Sandbox
|
||||
See-saw
|
||||
Merry-go-round
|
||||
Jungle gym
|
||||
Trampoline
|
||||
Monkey bars
|
||||
Rocking horse
|
||||
Playhouse
|
||||
Hopscotch
|
||||
Balance beam
|
||||
Spring rider
|
||||
Water play area
|
||||
Ball pit
|
||||
Tunnel
|
||||
Zip line
|
||||
Basketball hoop
|
||||
Bicycle rack
|
||||
Spinner
|
||||
Climbing wall
|
||||
Rope ladder
|
||||
Tetherball
|
||||
Flying fox
|
||||
Swinging bridge
|
||||
Spiral slide
|
||||
Water sprinkler
|
||||
Pedal go-kart
|
||||
Miniature golf course
|
||||
'''
|
||||
default_prompt1="\n".join([p.strip() for p in default_prompt1.split('\n') if p.strip()!=''])
|
||||
|
||||
# refer comfyui-mixlab-nodes
|
||||
# feat(core): NodePromptRandom - prompt random
|
||||
class NodePromptRandom:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"max_count": ("INT", {"default": 9, "min": 1, "max": 1000}),
|
||||
# "image_field": ("IMAGE",),
|
||||
"mutable_prompt": ("STRING",
|
||||
{
|
||||
"multiline": True,
|
||||
"default": default_prompt1
|
||||
}),
|
||||
"immutable_prompt": ("STRING",
|
||||
{
|
||||
"multiline": True,
|
||||
"default": 'sticker, Cartoon, ``'
|
||||
}),
|
||||
"random_sample": (["enable", "disable"],),
|
||||
# "seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "step": 1}),
|
||||
},
|
||||
"optional":{
|
||||
"seed": (any_type, {"default": 0, "min": 0, "max": 0xffffffffffffffff}),
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - random"
|
||||
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
|
||||
# CATEGORY = "♾️Mixlab/Prompt"
|
||||
|
||||
OUTPUT_IS_LIST = (True,)
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self,max_count,mutable_prompt,immutable_prompt,random_sample,seed=0):
|
||||
|
||||
# Split the text into an array of words
|
||||
words1 = mutable_prompt.split("\n")
|
||||
|
||||
# Split the text into an array of words
|
||||
words2 = immutable_prompt.split("\n")
|
||||
|
||||
# progress bar
|
||||
# pbar = comfy.utils.ProgressBar(len(words1)*len(words2))
|
||||
|
||||
# Select a random word from the array
|
||||
# random_word = random.choice(words)
|
||||
|
||||
prompts=[]
|
||||
for w1 in words1:
|
||||
w1=w1.strip()
|
||||
for w2 in words2:
|
||||
w2=w2.strip()
|
||||
if '``' not in w2:
|
||||
if w2=="":
|
||||
w2='``'
|
||||
else:
|
||||
w2=w2+',``'
|
||||
if w1!='' and w2!='':
|
||||
prompts.append(w2.replace('``', w1))
|
||||
# pbar.update(1)
|
||||
|
||||
if len(prompts)==0:
|
||||
prompts.append(immutable_prompt)
|
||||
|
||||
if random_sample=='enable':
|
||||
# random - get x-count element in array
|
||||
prompts = random.sample(prompts, min(max_count,len(prompts)))
|
||||
else:
|
||||
prompts = prompts[:min(max_count,len(prompts))]
|
||||
|
||||
prompts= [elem.strip() for elem in prompts if elem.strip()]
|
||||
|
||||
# return (new_prompt)
|
||||
return {"ui": {"prompts": prompts}, "result": (prompts,)}
|
||||
|
||||
def addWeight(text, weight=1):
|
||||
if weight == 1:
|
||||
return text
|
||||
else:
|
||||
return f"({text}:{round(weight,3)})"
|
||||
|
||||
# feat(core): NodePromptWeight - prompt add weight
|
||||
class NodePromptWeight:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
|
||||
"prompt_keyword": ("STRING",
|
||||
{
|
||||
"multiline": False,
|
||||
"default": '',
|
||||
"dynamicPrompts": False
|
||||
}),
|
||||
|
||||
"weight":("FLOAT", {"default": 1, "min": -3,"max": 3,"step": 0.01,"display": "slider"}),
|
||||
|
||||
# "min_value":("FLOAT", {
|
||||
# "default": -2,
|
||||
# "min": -10,
|
||||
# "max": 0xffffffffffffffff,
|
||||
# "step": 0.01,
|
||||
# "display": "number"
|
||||
# }),
|
||||
# "max_value":("FLOAT", {
|
||||
# "default": 2,
|
||||
# "min": -10,
|
||||
# "max": 0xffffffffffffffff,
|
||||
# "step": 0.01,
|
||||
# "display": "number"
|
||||
# }),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "prompt - add weight"
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("prompt",)
|
||||
|
||||
# FUNCTION = "run"
|
||||
# CATEGORY = "♾️Mixlab/Prompt"
|
||||
|
||||
INPUT_IS_LIST = False
|
||||
OUTPUT_IS_LIST = (False,)
|
||||
OUTPUT_NODE = False
|
||||
|
||||
def exec(self,prompt_keyword,weight):
|
||||
# if weight < min_value:
|
||||
# weight= min_value
|
||||
# elif weight > max_value:
|
||||
# weight= max_value
|
||||
p=addWeight(prompt_keyword,weight)
|
||||
return (p,)
|
||||
@@ -0,0 +1,160 @@
|
||||
import glob
|
||||
import hashlib
|
||||
# import json
|
||||
# import numpy as np
|
||||
# from numba import jit
|
||||
import os
|
||||
from pathlib import Path
|
||||
from yors_pano_list_util import ListDelExclude,ListFillOne,ListToTupe,ListShuffle
|
||||
CURRENT_CATEGORY="ymc suite/text"
|
||||
CURRENT_FUNCTION="exec"
|
||||
|
||||
def pyioReadDirectory(dir='',pattern='*.txt'):
|
||||
"""
|
||||
pyio - get path at dir and pattern
|
||||
"""
|
||||
res=[]
|
||||
for filename in glob.glob(os.path.join(dir,pattern)):
|
||||
res.append(filename)
|
||||
return res
|
||||
|
||||
def pyioReadAsText(loc):
|
||||
"""
|
||||
pyio - read text at location
|
||||
"""
|
||||
res=''
|
||||
with open(loc) as f:
|
||||
res = f.read()
|
||||
f.close()
|
||||
return res
|
||||
|
||||
def pyioGetFilesInDir(input_dir):
|
||||
"""
|
||||
files = pyioGetFilesInDir(input_dir)
|
||||
"""
|
||||
return [f for f in os.listdir(input_dir) if os.path.isfile(os.path.join(input_dir, f))]
|
||||
|
||||
|
||||
def pyioParseFilename(filename:str):
|
||||
"""
|
||||
pyioParseFilename('config.txt')
|
||||
"""
|
||||
name, suffix = os.path.splitext(filename)
|
||||
return (name, suffix)
|
||||
|
||||
def pyioGetFilename(filename:str):
|
||||
"""
|
||||
pyioGetFilename('config.txt')
|
||||
"""
|
||||
name, suffix = os.path.splitext(filename)
|
||||
return name
|
||||
|
||||
def pyioPlibParseFilename(filename:str):
|
||||
"""
|
||||
pyioPlibParseFilename('config.txt')
|
||||
"""
|
||||
p=Path(filename)
|
||||
return (p.suffix, p.stem)
|
||||
|
||||
def StrmFromList(txtl:list[str],eof:str='\n'):
|
||||
"""
|
||||
strm - from text list
|
||||
|
||||
StrmFromList(fileAbsPathList)
|
||||
"""
|
||||
return eof.join(txtl)
|
||||
|
||||
|
||||
# feat(core): NodePyioFilenameListDetect - pyio - detect filename list
|
||||
class NodePyioFilenameListDetect:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"path": ("STRING", {"default": "", "multiline": False}),
|
||||
"pattern": ("STRING", {"default": "*.txt", "multiline": False}),
|
||||
# "mode": ("STRING", {"default": "filename", "multiline": False}),
|
||||
"mode": (["filename", "abspath","filename-no-ext"],),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",'INT')
|
||||
RETURN_NAMES = ('STRING','count')
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "pyio - detect filename list"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, path='',pattern='*.txt',mode='filename'):
|
||||
|
||||
fileAbsPathList=pyioReadDirectory(path,pattern)
|
||||
resl = fileAbsPathList
|
||||
if mode=='filename':
|
||||
fileNameList=list(map(os.path.basename,fileAbsPathList))
|
||||
resl=fileNameList
|
||||
if mode=='filename-no-ext':
|
||||
filenameNoExtList=list(map(pyioGetFilename,fileNameList))
|
||||
resl=filenameNoExtList
|
||||
|
||||
|
||||
# resl='\n'.join(resl)
|
||||
# fileAbsPathListStrm = StrmFromList(fileAbsPathList)
|
||||
# fileNameListStrm = StrmFromList(fileNameList)
|
||||
# filenmeWithoutSuffixList=StrmFromList(filenameNoExtList)
|
||||
return ListToTupe([StrmFromList(resl),len(resl)])
|
||||
|
||||
# feat(core): NodePyioFilenameListOutmDetect - pyio - detect filename list (outm)
|
||||
class NodePyioFilenameListOutmDetect:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"path": ("STRING", {"default": "", "multiline": False}),
|
||||
"pattern": ("STRING", {"default": "*.txt", "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING","STRING","STRING","INT")
|
||||
RETURN_NAMES = ('absPath','name','nameNoExt','count')
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "pyio - detect filename list (outm)"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, path='',pattern='*.txt'):
|
||||
|
||||
absPathList=pyioReadDirectory(path,pattern)
|
||||
|
||||
nameList=list(map(os.path.basename,absPathList))
|
||||
|
||||
nameNoExtList=list(map(pyioGetFilename,nameList))
|
||||
|
||||
return ListToTupe([StrmFromList(absPathList),StrmFromList(nameList),StrmFromList(nameNoExtList),len(absPathList)])
|
||||
|
||||
# feat(core): IoUtilFileListGetText - io - get file list and read as text
|
||||
class IoUtilFileListGetText:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"path": ("STRING", {"default": "", "multiline": False}),
|
||||
"pattern": ("STRING", {"default": "*.txt", "multiline": False}),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ('STRING',)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, path='',pattern='*.txt'):
|
||||
plist=pyioReadDirectory(path,pattern)
|
||||
text=[]
|
||||
for loc in plist:
|
||||
text.append(pyioReadAsText(loc))
|
||||
# to multi line
|
||||
text='\n'.join(text)
|
||||
return ListToTupe([text])
|
||||
@@ -0,0 +1,149 @@
|
||||
|
||||
from yors_pano_list_util import ListDelExclude,ListFillOne,ListToTupe,ListShuffle
|
||||
# CURRENT_CATEGORY="Ymc Suite/region-util"
|
||||
CURRENT_CATEGORY="ymc suite/text"
|
||||
CURRENT_FUNCTION="exec"
|
||||
|
||||
def region_strify(l:list):
|
||||
tl=list(map(str,l))
|
||||
tl=list(filter(None, tl))
|
||||
return ','.join(tl)
|
||||
|
||||
def region_listfy(s:str):
|
||||
tl=s.split(",")
|
||||
tl=list(filter(None, tl))
|
||||
return tl
|
||||
|
||||
def region_intify(l:list):
|
||||
tl=list(map(int,l))
|
||||
return tl
|
||||
|
||||
def region_get_location_from_center_size(cx=128, cy=128, w=256, h=256):
|
||||
left=cx-w/2
|
||||
top=cy-h/2
|
||||
right=cx+w/2
|
||||
bottom=cy+h/2
|
||||
floatl=[left,top,right,bottom,cx,cy,w,h]
|
||||
intl=list(map(int,floatl))
|
||||
return intl
|
||||
|
||||
def region_burn_corp_location_as_square(w=256, h=256):
|
||||
c=0
|
||||
if w<h:
|
||||
c=1
|
||||
left=-1*c*(w-h)/2
|
||||
right=left
|
||||
|
||||
c=0
|
||||
if w>=h:
|
||||
c=1
|
||||
top=c*(w-h)/2
|
||||
bottom=top
|
||||
floatl=[left,top,right,bottom]
|
||||
intl=list(map(int,floatl))
|
||||
return ListToTupe(intl)
|
||||
|
||||
def region_burn_corp_location_from_lt_and_size(left=0, top=0, w=256, h=256):
|
||||
cx=left+w/2
|
||||
cy=top+h/2
|
||||
|
||||
right=cx+w/2
|
||||
bottom=cy+h/2
|
||||
floatl=[left,top,right,bottom,cx,cy,w,h]
|
||||
intl=list(map(int,floatl))
|
||||
return ListToTupe(intl)
|
||||
|
||||
|
||||
REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES=['left','top','right','bottom','cx','cy','w','h']
|
||||
REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES_COUNT=len(REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES)
|
||||
# feat(core): NodeRegionCropLocationBurnNumz - num - burn crop location (center & size)
|
||||
class NodeRegionCropLocationBurnNumz:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cx": ("INT", {"default":128, "max": 10000000, "min":0, "step":1}),
|
||||
"cy": ("INT", {"default":128, "max": 10000000, "min":0, "step":1}),
|
||||
"w": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
"h": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('INT',REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES_COUNT))
|
||||
RETURN_NAMES = ListToTupe(REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "num - burn crop location (center & size)"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, cx=128, cy=128, w=256, h=256):
|
||||
intl=region_get_location_from_center_size(cx,cy,w,h)
|
||||
return ListToTupe(intl)
|
||||
|
||||
# feat(core): NodeRegionCropLocationBurnTxtz - txt - burn crop location (center & size)
|
||||
class NodeRegionCropLocationBurnTxtz:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"cxcy": ("STRING", {"default": '128,128', "multiline": False}),
|
||||
"size": ("STRING", {"default": '256,256', "multiline": False}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('INT',REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES_COUNT))
|
||||
RETURN_NAMES = ListToTupe(REGION_GET_CROP_LOCATION_BY_CENTER_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "txt - burn crop location (cxcy & size)"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, cxcy='128,128',size='256,256'):
|
||||
cx,cy=region_intify(region_listfy(cxcy))
|
||||
w,h=region_intify(region_listfy(size))
|
||||
intl=region_get_location_from_center_size(cx,cy,w,h)
|
||||
return ListToTupe(intl)
|
||||
|
||||
REGION_GET_CROP_LOCATION_BY_LT_RETURN_NAMES=['left','top','right','bottom','cx','cy','w','h']
|
||||
REGION_GET_CROP_LOCATION_BY_LT_RETURN_NAMES_COUNT=len(REGION_GET_CROP_LOCATION_BY_LT_RETURN_NAMES)
|
||||
# feat(core): NodeRegionCropLocationBurnLtwh - int - burn crop location (lt & size)
|
||||
class NodeRegionCropLocationBurnLtwh:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"left": ("INT", {"default":0, "max": 10000000, "min":0, "step":1}),
|
||||
"top": ("INT", {"default":0, "max": 10000000, "min":0, "step":1}),
|
||||
"w": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
"h": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('INT',REGION_GET_CROP_LOCATION_BY_LT_RETURN_NAMES_COUNT))
|
||||
RETURN_NAMES = ListToTupe(REGION_GET_CROP_LOCATION_BY_LT_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "int - burn crop location (lt & size)"
|
||||
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, left=0, top=0, w=256, h=256):
|
||||
return region_burn_corp_location_from_lt_and_size(left,top,w,h)
|
||||
|
||||
REGION_LOCATION_RETURN_NAMES=['left','top','right','bottom']
|
||||
# feat(core): NodeRegionPaddingSquareLocationBurn - int - burn padding location as square (size)
|
||||
class NodeRegionPaddingSquareLocationBurn:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {
|
||||
"required": {
|
||||
"w": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
"h": ("INT", {"default":256, "max": 10000000, "min":0, "step":1}),
|
||||
}
|
||||
}
|
||||
RETURN_TYPES = ListToTupe(ListFillOne('INT',len(REGION_LOCATION_RETURN_NAMES)))
|
||||
RETURN_NAMES = ListToTupe(REGION_LOCATION_RETURN_NAMES)
|
||||
FUNCTION = CURRENT_FUNCTION
|
||||
CATEGORY = CURRENT_CATEGORY
|
||||
NODE_DESC = "int - burn padding location as square (size)"
|
||||
OUTPUT_NODE = True
|
||||
|
||||
def exec(self, w=256, h=256):
|
||||
return region_burn_corp_location_as_square(w,h)
|
||||
@@ -0,0 +1,15 @@
|
||||
[project]
|
||||
name = "ymc-node-suite-comfyui"
|
||||
description = "custom nodes for comfyui,like AI painting in comfyui"
|
||||
version = "3.0.0"
|
||||
|
||||
[project.license]
|
||||
file = "LICENSE"
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/ymc-github/ymc-node-suite-comfyui"
|
||||
|
||||
[tool.comfy]
|
||||
PublisherId = "ymc-github"
|
||||
DisplayName = "ymc-node-suite-comfyui"
|
||||
Icon = ""
|
||||
+4
-19
@@ -1,19 +1,4 @@
|
||||
cmake
|
||||
fairscale>=0.4.4
|
||||
git+https://github.com/WASasquatch/img2texture.git
|
||||
gitpython
|
||||
imageio
|
||||
joblib
|
||||
matplotlib
|
||||
numba
|
||||
numpy<1.24>=1.18
|
||||
opencv-python-headless[ffmpeg]<=4.7.0.72
|
||||
pilgram
|
||||
git+https://github.com/WASasquatch/ffmpy.git
|
||||
rembg
|
||||
scikit-image==0.20.0
|
||||
scikit-learn
|
||||
scipy
|
||||
timm>=0.4.12
|
||||
tqdm
|
||||
transformers==4.26.1
|
||||
yors_comfyui_node_setup
|
||||
yors_pano_ansi_color
|
||||
yors_pano_zero_field
|
||||
yors_pano_list_util
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:d1a847354bab2a5e949f420cea7774979bf59cd0ecd711b1f59b4010870849ab
|
||||
size 145662
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:645c0214b0f25a9f6b2bb150a8291678fac96d762cbbf0b9db06abd81b00129d
|
||||
size 99853
|
||||
Reference in New Issue
Block a user