From 643bf5d843ce93e6a1a616347e8b0a7438fb48f0 Mon Sep 17 00:00:00 2001 From: justumen Date: Sat, 6 Jul 2024 12:05:16 +0200 Subject: [PATCH] first commit --- CUSTOM_STRING.py.txt | 11 +++ README.md | 1 + SaveText/SaveText.txt | 1 + SaveText/SaveText_001.txt | 1 + SaveText/SaveText_002.txt | 1 + SaveText/SaveText_003.txt | 0 SaveText/SaveText_004.txt | 0 SaveText/SaveText_005.txt | 0 __init__.py | 86 +++++++++++++++++ __pycache__/CUSTOM_STRING.cpython-311.pyc | Bin 0 -> 926 bytes __pycache__/__init__.cpython-311.pyc | Bin 0 -> 3717 bytes __pycache__/combine_texts.cpython-311.pyc | Bin 0 -> 2968 bytes .../convert_16to4_channels.cpython-311.pyc | Bin 0 -> 2087 bytes .../convert_16to8_channels.cpython-311.pyc | Bin 0 -> 1579 bytes __pycache__/create_video.cpython-311.pyc | Bin 0 -> 4545 bytes __pycache__/loop_basic_batch.cpython-311.pyc | Bin 0 -> 1217 bytes __pycache__/loop_float.cpython-311.pyc | Bin 0 -> 1361 bytes __pycache__/loop_integer.cpython-311.pyc | Bin 0 -> 1329 bytes ...combos_samplers_schedulers.cpython-311.pyc | Bin 0 -> 2378 bytes __pycache__/loop_samplers.cpython-311.pyc | Bin 0 -> 1338 bytes __pycache__/loop_schedulers.cpython-311.pyc | Bin 0 -> 1358 bytes __pycache__/loop_texts.cpython-311.pyc | Bin 0 -> 1787 bytes __pycache__/ollama.cpython-311.pyc | Bin 0 -> 1801 bytes .../random_model_clip_vae.cpython-311.pyc | Bin 0 -> 2466 bytes __pycache__/random_texts.cpython-311.pyc | Bin 0 -> 2090 bytes __pycache__/save_api_image.cpython-311.pyc | Bin 0 -> 2430 bytes __pycache__/save_image.cpython-311.pyc | Bin 0 -> 1464 bytes __pycache__/save_text.cpython-311.pyc | Bin 0 -> 2175 bytes __pycache__/save_tmp_image.cpython-311.pyc | Bin 0 -> 1758 bytes __pycache__/show_float.cpython-311.pyc | Bin 0 -> 986 bytes __pycache__/show_int.cpython-311.pyc | Bin 0 -> 970 bytes __pycache__/show_text.cpython-311.pyc | Bin 0 -> 980 bytes __pycache__/video_pingpong.cpython-311.pyc | Bin 0 -> 1335 bytes .../write_image_allinone.cpython-311.pyc | Bin 0 -> 2319 bytes .../write_image_character.cpython-311.pyc | Bin 0 -> 1238 bytes .../write_image_characters.cpython-311.pyc | Bin 0 -> 1778 bytes .../write_image_environment.cpython-311.pyc | Bin 0 -> 1491 bytes __pycache__/write_text.cpython-311.pyc | Bin 0 -> 1018 bytes __pycache__/write_texts.cpython-311.pyc | Bin 0 -> 2699 bytes combine_texts.py | 46 +++++++++ create_video.py | 91 ++++++++++++++++++ loop_basic_batch.py | 21 ++++ loop_float.py | 24 +++++ loop_integer.py | 32 ++++++ loop_my_combos_samplers_schedulers.py | 82 ++++++++++++++++ loop_samplers.py | 23 +++++ loop_schedulers.py | 23 +++++ loop_texts.py | 22 +++++ ollama.py | 28 ++++++ random_checkpoint.py | 28 ++++++ random_model_clip_vae.py | 33 +++++++ random_texts.py | 27 ++++++ save_api_image.py | 47 +++++++++ save_text.py | 37 +++++++ save_tmp_image.py | 38 ++++++++ show_float.py | 18 ++++ show_int.py | 18 ++++ show_text.py | 18 ++++ video_pingpong.py | 23 +++++ web/js/BJORNULF_TYPES.js.txt | 29 ++++++ web/js/CUSTOM_STRING.js.txt | 52 ++++++++++ web/js/combine_texts.js | 52 ++++++++++ web/js/loop_texts.js | 52 ++++++++++ web/js/random_model_clip_vae.js | 65 +++++++++++++ web/js/random_texts.js | 58 +++++++++++ web/js/show_float.js | 76 +++++++++++++++ web/js/show_int.js | 76 +++++++++++++++ web/js/show_text.js | 76 +++++++++++++++ web/js/write_image_characters.js | 53 ++++++++++ write_image_allinone.py | 84 ++++++++++++++++ write_image_character.py | 22 +++++ write_image_characters.py | 32 ++++++ write_image_environment.py | 27 ++++++ write_text.py | 19 ++++ 74 files changed, 1553 insertions(+) create mode 100644 CUSTOM_STRING.py.txt create mode 100644 README.md create mode 100644 SaveText/SaveText.txt create mode 100644 SaveText/SaveText_001.txt create mode 100644 SaveText/SaveText_002.txt create mode 100644 SaveText/SaveText_003.txt create mode 100644 SaveText/SaveText_004.txt create mode 100644 SaveText/SaveText_005.txt create mode 100644 __init__.py create mode 100644 __pycache__/CUSTOM_STRING.cpython-311.pyc create mode 100644 __pycache__/__init__.cpython-311.pyc create mode 100644 __pycache__/combine_texts.cpython-311.pyc create mode 100644 __pycache__/convert_16to4_channels.cpython-311.pyc create mode 100644 __pycache__/convert_16to8_channels.cpython-311.pyc create mode 100644 __pycache__/create_video.cpython-311.pyc create mode 100644 __pycache__/loop_basic_batch.cpython-311.pyc create mode 100644 __pycache__/loop_float.cpython-311.pyc create mode 100644 __pycache__/loop_integer.cpython-311.pyc create mode 100644 __pycache__/loop_my_combos_samplers_schedulers.cpython-311.pyc create mode 100644 __pycache__/loop_samplers.cpython-311.pyc create mode 100644 __pycache__/loop_schedulers.cpython-311.pyc create mode 100644 __pycache__/loop_texts.cpython-311.pyc create mode 100644 __pycache__/ollama.cpython-311.pyc create mode 100644 __pycache__/random_model_clip_vae.cpython-311.pyc create mode 100644 __pycache__/random_texts.cpython-311.pyc create mode 100644 __pycache__/save_api_image.cpython-311.pyc create mode 100644 __pycache__/save_image.cpython-311.pyc create mode 100644 __pycache__/save_text.cpython-311.pyc create mode 100644 __pycache__/save_tmp_image.cpython-311.pyc create mode 100644 __pycache__/show_float.cpython-311.pyc create mode 100644 __pycache__/show_int.cpython-311.pyc create mode 100644 __pycache__/show_text.cpython-311.pyc create mode 100644 __pycache__/video_pingpong.cpython-311.pyc create mode 100644 __pycache__/write_image_allinone.cpython-311.pyc create mode 100644 __pycache__/write_image_character.cpython-311.pyc create mode 100644 __pycache__/write_image_characters.cpython-311.pyc create mode 100644 __pycache__/write_image_environment.cpython-311.pyc create mode 100644 __pycache__/write_text.cpython-311.pyc create mode 100644 __pycache__/write_texts.cpython-311.pyc create mode 100644 combine_texts.py create mode 100644 create_video.py create mode 100644 loop_basic_batch.py create mode 100644 loop_float.py create mode 100644 loop_integer.py create mode 100644 loop_my_combos_samplers_schedulers.py create mode 100644 loop_samplers.py create mode 100644 loop_schedulers.py create mode 100644 loop_texts.py create mode 100644 ollama.py create mode 100644 random_checkpoint.py create mode 100644 random_model_clip_vae.py create mode 100644 random_texts.py create mode 100644 save_api_image.py create mode 100644 save_text.py create mode 100644 save_tmp_image.py create mode 100644 show_float.py create mode 100644 show_int.py create mode 100644 show_text.py create mode 100644 video_pingpong.py create mode 100644 web/js/BJORNULF_TYPES.js.txt create mode 100644 web/js/CUSTOM_STRING.js.txt create mode 100644 web/js/combine_texts.js create mode 100644 web/js/loop_texts.js create mode 100644 web/js/random_model_clip_vae.js create mode 100644 web/js/random_texts.js create mode 100644 web/js/show_float.js create mode 100644 web/js/show_int.js create mode 100644 web/js/show_text.js create mode 100644 web/js/write_image_characters.js create mode 100644 write_image_allinone.py create mode 100644 write_image_character.py create mode 100644 write_image_characters.py create mode 100644 write_image_environment.py create mode 100644 write_text.py diff --git a/CUSTOM_STRING.py.txt b/CUSTOM_STRING.py.txt new file mode 100644 index 0000000..a643868 --- /dev/null +++ b/CUSTOM_STRING.py.txt @@ -0,0 +1,11 @@ +class CustomStringType: + @classmethod + def INPUT_TYPES(s): + return {"required": {"value": ("STRING", {"multiline": True})}} + + RETURN_TYPES = ("CUSTOM_STRING",) + FUNCTION = "passthrough" + CATEGORY = "Bjornulf" + + def passthrough(self, value): + return (value,) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ + diff --git a/SaveText/SaveText.txt b/SaveText/SaveText.txt new file mode 100644 index 0000000..c67368e --- /dev/null +++ b/SaveText/SaveText.txt @@ -0,0 +1 @@ +saluts \ No newline at end of file diff --git a/SaveText/SaveText_001.txt b/SaveText/SaveText_001.txt new file mode 100644 index 0000000..5688a8f --- /dev/null +++ b/SaveText/SaveText_001.txt @@ -0,0 +1 @@ +encule \ No newline at end of file diff --git a/SaveText/SaveText_002.txt b/SaveText/SaveText_002.txt new file mode 100644 index 0000000..d47fd5e --- /dev/null +++ b/SaveText/SaveText_002.txt @@ -0,0 +1 @@ +connard \ No newline at end of file diff --git a/SaveText/SaveText_003.txt b/SaveText/SaveText_003.txt new file mode 100644 index 0000000..e69de29 diff --git a/SaveText/SaveText_004.txt b/SaveText/SaveText_004.txt new file mode 100644 index 0000000..e69de29 diff --git a/SaveText/SaveText_005.txt b/SaveText/SaveText_005.txt new file mode 100644 index 0000000..e69de29 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..a49a6ff --- /dev/null +++ b/__init__.py @@ -0,0 +1,86 @@ +from .create_video import imgs2vid +from .write_text import WriteText +from .write_image_environment import WriteImageEnvironment +from .write_image_characters import WriteImageCharacters +from .write_image_character import WriteImageCharacter +from .write_image_allinone import WriteImageAllInOne +from .combine_texts import CombineTexts +from .loop_texts import LoopTexts +from .random_texts import RandomTexts +from .random_model_clip_vae import RandomModelClipVae +from .video_pingpong import VideoPingPong +from .loop_float import LoopFloat +from .loop_integer import LoopInteger +from .loop_basic_batch import LoopBasicBatch +from .loop_samplers import LoopSamplers +from .loop_schedulers import LoopSchedulers +from .ollama import ollamaLoader +from .show_text import ShowText +from .show_int import ShowInt +from .show_float import ShowFloat +from .save_text import SaveText +from .save_tmp_image import SaveTmpImage +from .save_api_image import SaveApiImage +from .loop_my_combos_samplers_schedulers import LoopCombosSamplersSchedulers + +# from .CUSTOM_STRING import CustomStringType + +NODE_CLASS_MAPPINGS = { + # "Bjornulf_CustomStringType": CustomStringType, + "Bjornulf_ollamaLoader": ollamaLoader, + "Bjornulf_WriteText": WriteText, + # "Bjornulf_WriteImageEnvironment": WriteImageEnvironment, + # "Bjornulf_WriteImageCharacters": WriteImageCharacters, + # "Bjornulf_WriteImageCharacter": WriteImageCharacter, + # "Bjornulf_WriteImageAllInOne": WriteImageAllInOne, + "Bjornulf_ShowText": ShowText, + "Bjornulf_ShowInt": ShowInt, + "Bjornulf_ShowFloat": ShowFloat, + "Bjornulf_SaveText": SaveText, + "Bjornulf_SaveTmpImage": SaveTmpImage, + "Bjornulf_SaveApiImage": SaveApiImage, + "Bjornulf_CombineTexts": CombineTexts, + "Bjornulf_LoopTexts": LoopTexts, + "Bjornulf_RandomTexts": RandomTexts, + "Bjornulf_RandomModelClipVae": RandomModelClipVae, + "Bjornulf_imgs2vid": imgs2vid, + "Bjornulf_VideoPingPong": VideoPingPong, + "Bjornulf_LoopFloat": LoopFloat, + "Bjornulf_LoopInteger": LoopInteger, + "Bjornulf_LoopBasicBatch": LoopBasicBatch, + "Bjornulf_LoopSamplers": LoopSamplers, + "Bjornulf_LoopSchedulers": LoopSchedulers, + "Bjornulf_LoopCombosSamplersSchedulers": LoopCombosSamplersSchedulers, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + # "Bjornulf_CustomStringType": "!!! CUSTOM STRING TYPE !!!", + "Bjornulf_ollamaLoader": "πŸ¦™ Ollama (Description)", + "Bjornulf_ShowText": "πŸ‘ Show (Text)", + "Bjornulf_ShowInt": "πŸ‘ Show (Int)", + "Bjornulf_ShowFloat": "πŸ‘ Show (Float)", + "Bjornulf_SaveTmpImage": "πŸ–Ό Save Image (tmp_api.png)", + "Bjornulf_SaveApiImage": "πŸ–Ό Save Image (API_IMAGES/00001.png...)", + "Bjornulf_SaveText": "πŸ’Ύ Save Text", #Make SaveCharacter, SaveLocation, SaveCamera, SaveAction, SaveClothes, SaveEmotion... + "Bjornulf_LoadText": "πŸ“₯ Load Text", #Make LoadCharacter, LoadLocation, LoadCamera, LoadAction, LoadClothes, LoadEmotion... + "Bjornulf_WriteText": "βœ’ Write Text", + # "Bjornulf_WriteImageEnvironment": "βœ’ Write Image Environment", + # "Bjornulf_WriteImageCharacters": "βœ’ Write Image Characters", + # "Bjornulf_WriteImageCharacter": "βœ’ Write Image Character", + # "Bjornulf_WriteImageAllInOne": "βœ’ Write Image All-in-one", + "Bjornulf_CombineTexts": "πŸ”— Combine (Texts)", + "Bjornulf_LoopTexts": "β™» Loop (Texts)", + "Bjornulf_RandomTexts": "🎲 Random (Texts)", + "Bjornulf_RandomModelClipVae": "🎲 Random (Model+Clip+Vae)", + "Bjornulf_imgs2vid": "πŸ“Ή imgs2vid (FFmpeg)", + "Bjornulf_VideoPingPong": "πŸ“Ή video PingPong", + "Bjornulf_LoopFloat": "β™» Loop (Float)", + "Bjornulf_LoopInteger": "β™» Loop (Integer)", + "Bjornulf_LoopBasicBatch": "β™» Loop", + "Bjornulf_LoopSamplers": "β™» Loop (All Samplers)", + "Bjornulf_LoopSchedulers": "β™» Loop (All Schedulers)", + "Bjornulf_LoopCombosSamplersSchedulers": "β™» Loop (My combos Samplerβš”Scheduler)", +} + +WEB_DIRECTORY = "./web" +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS', 'WEB_DIRECTORY'] \ No newline at end of file diff --git a/__pycache__/CUSTOM_STRING.cpython-311.pyc b/__pycache__/CUSTOM_STRING.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2893bde9eec2f8efbb2db080a0b84034706d8b12 GIT binary patch literal 926 zcmZuv&5zPR6rX8nw|oUm)aZr-7dIiAC0_JmOceP_v=AsUTMrFkhNY&Z?39|tc;GOc6yUCdibiOz;Gqg6~Y6 z3dM{N$yA7Jsw86W5M_c)ji``uho=jHKlI$@klFo1V>F;0;CLwtXfmwjU4SX@A`+2F zgeW%dN;bAJjzHPy5=pknnvx7waUIf81Z;jueS`#IH(t! zA2Zv%>|cqBarqg5G5Vd}{qpwf@sEeUhO@`7W_!h1rZh{HXIgm)altcrtq_k7+P**R zF)ujmacx7bvv~n=NwgJCN&{tzKH;vI4c1u{?3~0SK6ScG1;ZEDvRM{~jimr?;C-c@ z_<4MhWQ^wNJ155{DV79F&qcXrS^c(4EsMu2%k@a$2t8q0M?u?JN8%j^xVv=N^9W18 zMV@FBjaEZn&5UcMmR>NbHF(6r3!_-BH4Z{jA@8u#im2#~2@s9?b%62ZH&@aN2`d%6 zKmyNYq~4mmTf0edKJ%__mTO2O5XR9Wkv)v7m Yr=TokjPXK>VaWJDoD1LI8viYv*qxS~i(mhHN(n}+&uN>s80GmVi&fd$PSOIz%4 zi6v>*JrwD!rvikTWh_=jvI-Li(L1Q3q(m2Qh4S>8w z6CgKf5@eC4L5ei{IzV$YPpit-n~5(2(hjbwpvA1R4RS?6yE&x-GOtuY3d#=1Rb?0C zZDkK+M!5rWO}PtlUAYHxL-`)ao63EV1?Br7Zz&HzZYnX6Tr`blt4ED4@bPPSpclt4V*a-g$kYMU>Hlc$e$y@M;G zGW(?2R&+L07hUy4SEzQNshtm+Xd(K6s!;t*ZJ(d%?en3DN1EP5Cuh-Kz1^ed)Btr3 z)%|8yZS6OEtqWix$TXU)qq*Mm5slUbRr&)aqH9`{HIMbC!fk{b7y8S==7bP~d0ZCZ zaM^I9`C_<%5sq1hZy~OTdaa`l^%e90w?Xd?{TQ!rC-#4?8|}XKT=u$QFOF!wt>}&& z8*xJq?FAnNj(R4J{Pj*8xb0ci>-`ma7=(xRrqi<)hRD-sFO59%B-hSfVZAx_xHqg( zdwDe8m;Ea%@@#lkL@x%lU?)cwkoAi&$$)X&vEwm{}3=;0xvD0 z*kc{J*-Tu|LO0fBa9^-j(vgqkz<4)ax$= zWP}m*_RYrvFH4tN;y^)cdCuJXJ_N_Y{J z@FwUl^8v5_CJd`YC_Z|`Iuv4eZ9*5^Z&VkCmj&PSu>*sxTm(B~a!@Z~KkT9VNsl5F z;XZ?X8eAbf&*S;LZ+xBfi@upBuY?vq`NR2dKmTM@S)w>;lwi2AjiQXA0^*m!O7$gu zCQjJ#$ESx!^1*Sf(U4DSXJ_@t?=|cUClBk5v*X%_^5fdc(YP=A^k`o`tUozAc>nat zhmXZOcBEy{W{=8zV~hzfZ_m8M+h6WMf{jTek}jd*6Cl&^8(;*nciG$98a)ICeuvnJ zYdeh)_APn)nwqAz^)@wdo9!rW3cL#3iLNn?+>8cQG9d8l$Br2Mbr?{yNF@do!zV&+ zL21Y@n$(D3-y9E7?!ZIQfrr9~j*ULY$HKspw*Xcq}{+{Y0tadDBT9ul0D_#+y+*mJ>7-#?QSlf3p>npSkOqII>S}hAuMPZ4+q*E zk40zCxjLL|o)056CgG?LNW5z7b?yv%CA$?S4_%eJWB)QR(AYt-i{duU3&}EMLze$c zz6O{sCgKY#VpdbQQ>_H-twJWm#>jJz1`FUVR&W2pNI* z^c~|AEaDeO_peZE&O{&(u*kaUZx&fI{mmi|On2DUvoBn2zoat}Z`SahiiYDbHbVAjekvMFMs9)0Xb77n7$O95aIj5cMaOHK%t zFobBPL}wb68Cc59l$}{rA`pO?d+0<_nd8cjoq1Gni_Em>#881f;z}G9+$1xzm3sun9G%fC>Z-)^?puR3P%4xw_|ws6go4KnWFy w9SrO^WmGCe*s^l>to#G3{M5ON6d4MWWSj>imij1a&77IMeH6mKaRMj!JG--~k^lez literal 0 HcmV?d00001 diff --git a/__pycache__/combine_texts.cpython-311.pyc b/__pycache__/combine_texts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d057813484ef7d70921468ead3e3077b852a6b62 GIT binary patch literal 2968 zcma)8O>7fK6rTNa{2Rw1!A>Z_DS_0GCJlsEB#6=`1gr-0V@DLzYH>a5u;8DtyKW%_ z$*NM3R2)*ZRVxVZIax#c^P5P4AM5(#f{i&-S^0*ecWMi({0LxFG9F*B(_31SfTW;P&*-> zG+-%}$fq^JW#lYC;ws@)O`4=rS?QxR?1u=+Tqctsf;yQoRKw2AvO&-68qQQ`z&PHz~~lu zR$m5KKr)&}@4IinQB5;np|4q!JdV=yIeW_kTjPmfT2p+WuQUV1zC$6Fu)VJlMpo&L zgTZH`eHU{XsV|?AvVCw)scYlmzGPn2av3q3!;;$f_NAPX&8JhMWfXQ!k5r^9sJ)Zd zo;eR;IjO<$|vL__f0)`q&~e0+GvFa&WZ~F_GDM2D|uOwFtJ^fF_y9+h6qX` zJ0XFg1V~&PJemspm#>r`^%H;sGVEyg-iOSi&Y#}a-#w@I#Obf=e5GSp zH-C?0{d8PEdS2iDUS-?P#q@&_eb+&~ebCY|970>8fhf3He`Cem>#w`?Q>XRl_|HAR z^uYE?&1cKaXAKVK4X?AwX`m`NoJt3H5@O7=BpwUQ=?5r@0QZ&8op9*tm5oVunbL?H7JFsdPfqq%71eDVIvn|D3&Z7Yu4=_>iU%f4;{ zapv%2e`v`cx)&<>2g?3|$Nqy${)0d6d^qt)D-Dj72ggeO6J`Giz3Ig7{`TU)XV<>C zrZ)x6Xt%@wy(!G%Hwwa+>;jsgGLcG#WoJ_j*P(lN==L4Y2M#R`G}TsL2Uvih!OUf| zU?@U~?Z`tMRhqPNfm7JY#wkFT4p8tOgHbQoP}cF;8O?iI$|@ z1)r;L02I)&tEK2za&_vi&dL`5{6NLCwb;Gn>C_>8wrri>zq!9mmCSucLT+Lg#cU!Y zi6U`|VkU?4X)3!#@k&0CUYl_x(+O40NZQ35R_MyaedcIv{7j^JDHHqXcw{&hJ{cj6 zC&y#-vJOYZv2Zj-?89%xjvhOC=A1&Kg1Dg;X>xMSk{NL{d8%dRIs}oe*`{tSV)(6bdswdQm2xPbEjMc$s_Cr;Y4l5&|WqL`E!QdE%G1ylbu>L$erDK2n I%Y?b!Kho~ae*gdg literal 0 HcmV?d00001 diff --git a/__pycache__/convert_16to4_channels.cpython-311.pyc b/__pycache__/convert_16to4_channels.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3d18a142ab1941f1fe8c5c775738300617869b1c GIT binary patch literal 2087 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 literal 0 HcmV?d00001 diff --git a/__pycache__/create_video.cpython-311.pyc b/__pycache__/create_video.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..21cd95bb0f7af8c7a84d326ec93290ee2984dac6 GIT binary patch literal 4545 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 X*VeLmn&ZIk7sIa&`oCT>YOL%(%`rmj literal 0 HcmV?d00001 diff --git a/__pycache__/loop_basic_batch.cpython-311.pyc b/__pycache__/loop_basic_batch.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c4cf0aa64ee73aafa7d03ff6e6f635be05e876ad GIT binary patch literal 1217 zcmZ`%%}*0S6rb6Tb}36KidGP%HfroadNeV{M39drxR`c(U_ES>&Qz+~ZrN>#5YQet zpf?kfa`3aT_gxr6&9X$obssU6>_6iB{!eL9UhztY!P;I z2%rv;5rK$AA~FG6B=}a!3k6)j+>XW+mo8KbE+tGU&6ze>^_ZB_^gV8I4>l_N1Y-$_ z1qsbtRlCB(Vxa_JJ!6trq2>1|ff@EZPKX_(lJicHCaXnSN{%_j{8BcR%vHULQ#4Bs zpij>H^+jPI?2A$)o5iH5VYw7CwLP8HS{fd@%7@H#dWn2KEKiT%3ik{>V>cB@Mm>+6Ms_U zU)1=n8gHom8~Eje^(kLQz0vkNXiwjz^%uL!W%mr2(h?!2m}bc;QqyE1(=0lqYV*5l znhRCSKGbyQY|HbCv@-7yw-1O+O^@r@wAP*t7M{uKd{R;wb2^pLnKF^p#`M$-O!wG5 zeSC5zJ=@CF4Fk93xt%{RhRcCh-Ae=1j(*?eh%d-8%nHE1hys0UkJ^GT>L032H_pXt zTBG+yZK}~bP@D24SsvzZPea=sccQ_twLG4T;y}66PW!GK?}Ty-F20B{_Jw{77XOBQ LF8lQlMa$oB-L@%o literal 0 HcmV?d00001 diff --git a/__pycache__/loop_float.cpython-311.pyc b/__pycache__/loop_float.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f42329f48a49aeb93a665f34c7f20343812e0bde GIT binary patch literal 1361 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 literal 0 HcmV?d00001 diff --git a/__pycache__/loop_schedulers.cpython-311.pyc b/__pycache__/loop_schedulers.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a63a75893760f71c05f3057ab1f5fddb861a450c GIT binary patch literal 1358 zcmb_b&rcIU6rS1L!qS#fY)e250YZ>!V)dXgkr1&~+E5qlwg=YertWNox@B>&j6Fuk^Ly-Tam>!x*Oh`O&E5Q>d-)y@DgrhUrZ{EBgGvB=T_Iq!y7s0r9xLNqb zA@rMV+#$4u<4F)cBZ3Gvkb*cgiwL)c2)_*xyYRJ!f(e#UR5)Z?No#AJ#q~LU1>4U^ zN8pPTPUi{ULffF*?RYDK?kRS;+hTV|5?!f)l^((=UcxIrA}D_1QF=+&7E%JF8}1ir zAZ?nfvbLm?ilJM!hTTY5*_(Ly+Dr(3gUe^^WtSOMMCv^~Bg#=;Gi>VZ9AMjw>Bz`QGPY!v^jM{&uf*c)tXwLlRqV1^Qddl( z+p)(*(^{z*1@)ZPfOM&+r`=v%qrQ~1kjtvs#f5~te)W7lZ=bQTbl497s_0-~q87Qa zH@;W-v00Bjt;e44-^|o+X7(eQ58ea+KqGkVOYzIgCeIB8n!FJ7Hj&WdJ%(5m#TKh> z6lZBfv-EsfSI={zqRU+C6a@lUSS8KYf!m-{i0G;J3)v;rh^>`q0Du z@KilKRSQkm{L=@K;g544K^nDKs1)s^qN=XsOS-C3ud0?z*6kqsRrOsZZ?r8w&B)t! zNiQ#%#JU23mXCp-K`(;<0QF}Q*<40y)w{EkW}YQv8ko;zSudnyHJy^PRD7C~;@Q-^ zM8)__HZeP&S#+MggB)V5Jg~m77_jo#uK}u^+3*CLT$cyx4{*ezuKukTEkzJTu6~m0 z;am0a{aWZjHQfk}0z|G?rAFUGHQDGJswSI);2DG7xd5%}*`-mg^-3mNqYPNe9A+ot nR4Y@{))?s64{SdIX!0222J%;(*%ZPU?zjj?O!wy!gLA`QS~EPM literal 0 HcmV?d00001 diff --git a/__pycache__/loop_texts.cpython-311.pyc b/__pycache__/loop_texts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eb131ae471ad6c636fc6a928525f8669f64548a9 GIT binary patch literal 1787 zcmaJ>O>7%Q6rTODz23x02sTZcN;Q<0nxcdTBm|BkB_VCBSesz40lQR-+1X7T*4|{- zhBiut50OZv9)b{ZBvL6CN~<2=f|O&AMFMGqau!|d$6b>4dob&a;(N-W*t2M*<*UjZ8;vZIUnY7e$3|r*q0Nqe;wt5H~?A&5=@%r zvaH=I+bYxg1l|D{U@&Ux05vcQv+!`3$G&Y|XR#j#uuxz+X2ET)fUvlZ$|p48F5KPe z(EI-}@COEmwyBFf65$e(d_bK$pm95(dSW~YU`@|gj56Vhg%Uvi7UAu(woLqKIhByE z6HzxURZEnXD`mpVRz-_(q_0#dex_N9sVfD#VH1BD+*Ga}y+=Fz^}|gs!f3t%P(uZ@ zhHiG>fuOE2-=q7i>pw^R{g%BK0$X|FbG2C^IB)e(=mmI$Vk}{Y-y}@Irfx)|hf^bq zW>Fid6t&XGlv&hoXA&c7#V(sgrDS5w9+_M+ty0C%l@6%^X;J7E_VDuULvaij)Us+8 zm&aFQ#~B+=Nb?z4k+bvD>ESWMRP%;CKHNUq1s2$^15}aIpY{5amCg9p)y?>3d}rWc za`%#RWx|P09&b0{G&-P}KcHWOH-e?DR0@`ciGQ(xu~vG-5TBJVEod=@aH?V3G)qxy z0FZQ@uxK@Ms-ZM2_6k51H3W3&$}aQd<)@R*$64o%9PO{(s1IG(F@C=0T#P$s$2t~` z06*B%KomswOi$f)>i20Um3A^8{hItO34ZMLXZQQF4G#7jpnz+FW89Px zu^r$TBNL&O1(n*@YLpc;49yvUuh|;fV08vcOz2=Zy9U*<3Mc-b=Xba@PG@K-OC8kn z!Iv)e-iFC{Obsni@`c;vyUTuoehS`YTVx!Bb6)#~y%zz6j1`8p6#iZ#|b7KpQNhocLDwZDutK4{_q1wR-8|6QiQG+ z9GUjb54UD_Cbnj`X7?kPJrSTAd`kco)_DLZAl}vt-Rh%~*8oV+Ehu`WO@EEi=%*g3 ztP8MO4WDKzb=#(41GDNav%t7tF77f;eD-O6FFv<7I=??U55m3h(tdbpBUtYn+*osj zA=e@)CK5qWO8KIuC`440qKPX8op&qBN+oX`?R2R|-nNTcdC|lc{YQ}Q)U=#QNnZ64 z;aWzTk`r?h>6y#Ov?>#6C7DPAv!*8G>FaZ;tm}uHBrg`UU@V#%7ibaLDS+znQ}^{X zSkVUz26)CH{|oCkJi!18pRXqCy+hTRdgNSHs`n07XBs@~JJ&$ZgLfUhNdl_4H`08z mtvD3MJh#WKw_w9Hp)SMk4Q4$mk6 literal 0 HcmV?d00001 diff --git a/__pycache__/ollama.cpython-311.pyc b/__pycache__/ollama.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..048de21b00910f124811d28c02b2c2d1cdec4455 GIT binary patch literal 1801 zcmZux%WoS+7@ze%va$1U=qoXbx}eg^5Mt7XKms%>QD`Dsw1VoXuwNv0&B6uOGAyos=~okC~_deY1k zmX=Xo{YS9HycB73)FpoC9O&brW4$*6>?1^wDPd%$h>WF8v<W zq%(5A<}!k#OpOy}RaxLw!$?~$EiD$WM!jB*hAwq|Qu+-+HnKxG7jBIG*+M1oNTKEt zzc3eg<+YW?f>YyR;8}iv2`_xP8Zf^`%hnNT67YC+Ey^qwZ?2TA(yg2G%k|;IiHsl8 zh&=dvKpLp6q5d1V$y&G)}(p1s_b<&lB5tY*_~r1qxwz!2hOz3~tYCc9dU z@M_?55@nsh_lXl)7p+7U>76j0&Z&qkbm(#Q_F*Ebw~-1DRd=;JKYCglawy_GXzTJe z*zI&}B^35_bO^BY?3jK-Syvu+u=m;!X5!q|r7-haxSl$?H`eN)eAcrK>vy_)Y^aCh z!TP$2dq=vP97V2#j%v#SA?YF$WvQR8gkg22P?)&*$@oX`P0UP8OkSDV^_(T zu?h$>97gPr7?^~%OSxg+32LF?hQ^HH1T)zc<&{YF0I@XE_!T0A2I=RP>lfxjK zzLj~Q_ix>MuIG03TvN}z7&_A&{kSQ*H2ceJGe6x%XioBE7#_%1 zlz-tNQ@&AvTT;GLUJCAegU-Y#9GX!Bi*um+as10r7cm68Wr47HWP@8j) zgp~lZ0azIIEzOr!mWs(M(&dU*uFo$=`d2H(xzgedc;)7H8`oMVE&v&Pr?K$Y;7DVkt@WrE z+UQM^xD!tDGJ6|_7#p$IW8v)UpC{R0W*>l^cs=5n+Oi}`E!5wLzZM#49{tR)&D5snEnHxU&apr literal 0 HcmV?d00001 diff --git a/__pycache__/random_model_clip_vae.cpython-311.pyc b/__pycache__/random_model_clip_vae.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0319a197db9059517b3553c9964fdae85bb6484 GIT binary patch literal 2466 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 Y2{jb$r!2N{pyNe&#(4j{WW!eeAEApH761SM literal 0 HcmV?d00001 diff --git a/__pycache__/save_api_image.cpython-311.pyc b/__pycache__/save_api_image.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8092ad89979895e7b4681d5c2f12e1d312fd4722 GIT binary patch literal 2430 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 R3xkjS=sDxPI6&Y!{})`r^qBwv literal 0 HcmV?d00001 diff --git a/__pycache__/save_tmp_image.cpython-311.pyc b/__pycache__/save_tmp_image.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3ef80431d4772e236b1ea1375e62a2b46f9ce38 GIT binary patch literal 1758 zcmZux%}*Og6rcUF*TyzBPC`*DD`_Z^FPI(*2}D&5rNnA#2$(~*Qde8gnk@0|n*C@C zB9c{6$wHAz5GtvZNIua-^pHQG{U7YeQmm0GAyqwab3{+Mv~Skf#i4I@-preMJHIz? zelx#>!$Ab{^X~VBT^^x7snHRzJvq4v%|5~iGesn|TSj8RW{aH8OFV;EG>0&^g)o1> zB6J9~Es}tlC6pA7shLeOM9ApMikd&2_L`3K$t0NjNJSEZk;JMTX134)j2(8pB_6Y| zBq#YWFZr<`iP*P=qyY8KS&&>D$)cyce8MS;UJlKp5KE77H{bIOwb)q(Oy~VLZkru~CgDu1df+ygJNYDfG zfUG_k$Puvgb2+W$7o_8qLxsQ>EkQr1w;+XEWXP?e*D!6L`RGva4M@%-;71 zW?gV7?y0PHNQXAr16cR4yY^dubN9WKtf5UxMD)X{c4&S&Ytd8pq`(bzx)6mE?iy&d zi`^52*zthXfh7l!l|z~tPpW}V?`+$H>|H84+q;Ke>jAgPRq1)06YRtOU&Y?5#2_31 zmIkvcp8Jvc$uW)Sn5My^>i8c}8y7}Xrt1JvQ%H}xt${4zdVkB>CsBlXZog*oaAJsjUjZ%WQ&NV(e97;$>pu zclI~2o=7(m>3U?k5t*)VaMJ>zAH{947Q6OBsEBoOydjR)#POs4SjDpXA>M28zI;)!ZC!Qlnb?ZJk3{@zIXjcf%x6hxaW=QSm~B4+ zq;GyXM<0aj{HL=-oJr?q=jIphdg=2H(1UHKloH*didK6ORJmK4LbSyS0=x&HUUSG7 z+xoIS5JA!R%D0;Fi{;zRflKAjoBc!OTP;2=47AXB)rO-0NgrWN+oD&>dKVP1D|6c; zi5J6L!Mzc0wo~!3H3rV~KHFb`YHSvA_Rk H!i)A_AOeij literal 0 HcmV?d00001 diff --git a/__pycache__/show_float.cpython-311.pyc b/__pycache__/show_float.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aeb7dbeced234a96da3473d2377469bed0dfa5fb GIT binary patch literal 986 zcmZuuJx|*}7{2pIa2!Gc1uBG4vvjaZ$=Ibug)~4^>LB6_xRtEPXNy#J40cQl?cgCl zpc@@K(N=7o_!$|kTl)u$(ut|>*#z3s*Yb1kJ@?-G@!Z#9QAS`F&m;Q>M(8Koj7_+9 zMip>Q5r;MrK?6ka8Hdn0{F&*9a4n?p=9pmX_;j=mn^R;V9TTK;7Eka1odI{wqEgcZ z!s#O6^&AoO3GgK%!ak?x$;1HZGLayAp5|No-n$LQ>-0@%^u|Q+c=$*20H@F#;RsIz zB6hLOb#WKN<(x_--#QGtzC~!kW;u+bjuTo`+}LieX;ij7-?SRNgRrlCM+&CA=>!2Q zQ@N^D_dVCDhOX7C);!lfZa1oC81y~Y=y}8ns_Sn(zZW{T@fRCFw?MtKrzsVV3W4R=ehz{I zmZnni3$Xa?_Q~w+0Jo*5S?CNvgyQn-r=!mwhVzexrRAZt>=%Jnl>(Ivqt|gQ!=SQZ zxE=`|=1&^NVc2o5PYR~f2?E#Z?|a0bgp0J8snlp0+l`h+CwJ>wdsofGq|!!Pt!a&> zN(;@l#za<|FX~jPt!eem=I&nFaXM7mMK%Q!!e_vqICujP-F&fFPB>8nnE@_&l$##B z&WI^Aw-CLG@6AQqacMEyif87dm+|Z(aHWN4D-p2xI6-$IE6mEN3Qo)Z)6bRkG!tXh cUm7>{1e}D&7$@8`hO~F#l5xNObCA~i4F~e^F#rGn literal 0 HcmV?d00001 diff --git a/__pycache__/show_int.cpython-311.pyc b/__pycache__/show_int.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3281544cdb0f53a7347c552af3c8527f466835f GIT binary patch literal 970 zcmZuuOK;Oa5Z?78b&{q{pQx%T<C zT_Bt;5?(J6L7xC$A|k{ky-X&CNUsnHx|iuh=g@nvxSJH~z{7z|(*+>qn=ws;GNi&Cm|^ zTAj1G+ZU|=kz_grs{k=dOQ`lBsV`qxpY8A4qt(Zwl_x3BEls7oP_Lv&C|AZ%h%~

_pf)R_V&SLY*WlBvS0l#2#b2(1rc)==iC5LkBKFF|p@+B6z| z6*iyUKC2hxi?K7TY!)C!Nqzp)$;IhtQ65dNjifcd25D8UQpqsfo?{sXtr&*mk;rEL zq+uLKJ^S{gYTCUZaIEmqBmN{@q_tchrDN%sI;}AwRYP32N~P!K^cqu1xy5=0sFDRTY&iPOT>E0i6RILaLuFA%K`|*>XnO}w+3sV7$4^wm>^1*DJD&uVIKYVVar@0u<{FQ>#BXCk4 UW1Mm`7~0;4YnJ=B0q(Wj8Hqp(#YA4oaLw-AY#EaYQOR20NyJy6_?& z&>egMZH2n)qMwnaHQWAxQMzK)J2sBm(rfwn&Y3&+o;m(pDk%u!`?IL~4I}iEE%Feq zlW_%-Q^cVyM9>fse9j?s0dE!tB3uipyp2lO3si3Hc^`E9XkdZPNr;f~@Q#-NPC*;t2u}ne z_HdW$;U0#wl163UJ_vihO{g+}7Up5c32iF1^k!Y#qDt5EExX>|4+r{Jq+-fjP7ts$ zm8*^Fp6A-t(6#&3P0#Hfx9e3a33#u_7ABKatW!BxW92`9l`?};lV%{vO!^4cq~`D%<-#5nnAWtT%26S(ovtrIalqPC zDt-|@K0AFfKaoEfJjV*>0U{Ka7d{=Hos5Ly@`_&qT2qTuHqCy=wM~;Mrs;Yl zbXY!Zng?OWx!x&SPA3Rld$8vbe;N+bQf5)TW$x5lI-PFT^mbFrjHL3*wzjF)8yYP( z+B!2>YrLpYdGonm+iEo5qc#Ltv&0%PJ6D}F|>pvUmyx(k)@1Fnw literal 0 HcmV?d00001 diff --git a/__pycache__/video_pingpong.cpython-311.pyc b/__pycache__/video_pingpong.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..75661b1277c5c43148c2aa7d004a18efaa90b050 GIT binary patch literal 1335 zcmZux&2Ljj5TAV?j$_BMp+JeMK9Yh|3=$RxN=2)xG<8Fy+Kz%#3HR`1-ma4uy^mzq zMkR7uAA*!)Z|NbGIME_{@Sl)lkBQ`iwGt9iPq{smp171*J9gv1toHY2XJ=<-XJ+3Y zsZ;`xK0o}q*3tm}QHuc?$IQ`HWOjf8B_32jgE^qu7Et{eo_K+?PZdJReaISzYFTuS zrM=HU=jbzB?f?VSg^I>>O19t`%3ch$D+bjnCekXGPDr2r+U1s7rk>-5i?p*#kWQo)r zPY7jh`psN!CG=UY;jL@`Kx*v(x0?OLR3Q46Koe-9ZS#N!NdtdwIod+CtK>_GiQs+y#JLUVP9z3O;5G%MaG!I(g`75m}vDz TWSk@D<6U^IWdFWrqv!lBhT23G literal 0 HcmV?d00001 diff --git a/__pycache__/write_image_allinone.cpython-311.pyc b/__pycache__/write_image_allinone.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e09b40bfd2c3d57332d8a325ba06025ea1e7908 GIT binary patch literal 2319 zcmb7F&u`OK9DjD=#CDP3WP!of3nPU6Xl%dCC=B>@LYAsj4)u}~6ms3hSC7I(Rl3?rluMntd-D@N(W zcf@e?TwSZ`E2f!idwv0ygZ3G)t!_myNMjRU1tXYm#CE8|fn}!O-^_+5p z$`y;0^;~1K>Cj-2G<7P~o2Fx!Mnf;cgc6KYZD-rmsc2ed%`vP7SVpzxzydT{*6KRZ zRIO2k9)ji6bduqzNc0CygXoxw)+QUGnJ-X=qnvHC3rN4cvskn0`eL)LHx^f|dS!bf zw^(l4j#XD17S`>>uYRydqiI&uBkUHtP}N{Js%j?e5l(w~bDKtT%GyRzE#6(r7Fwr1 zy!Ok7+L`a|DnJ|cL^QL;bx-A4nf}I|KKDHOs?weNyqmhlDv?*k?%Z-W^{IP0^ZeHD z$?nB#-SihdNthbzAqHb;{6y!%lY6gbyR%ojQ=jw#Jg{*&A@`6El6(M5!P$xAeQ40p zA2~ER>Lf)f4vtMxnW3+VdSz>lGw5Dx6{eytTl$YX*#f%h0; zCwPPrhy)`;JHin*RN+8LVWkyWAx^r$+`gP{@v_{KZ}*+Q%BiuOZ*4PMp8=#Hc z_(JDyH@@JPy`U>byNQKP4Ztt2#fAT5m!3e!CBM8Dm!NMX(LZ`~#36Qk$W9z$j}6(R&sGKS<3|dOtr4ScIL1R=fv_S>Q!Q!eTPl>T`h6=C@EQp7 z0}%lr?uCb%3CTb(wfnjWqTSwvwBpCI?YT1(pmN#NY+Lo(LIz7AHVs)#2Mm&eX{b05 zjpt`bC*%xU;w*z%22ln~7tpn@DNiA-=wVrTdZB`+EMGRBxHuXpoBf31>4r|Ou4h+@ zS#>q9DB0Cw_PVO%uR})2jF8gkt~0O~y9eMWhs%FXpLeG(xT&-5%+0P>Ao@R^fanK^ zqSRdHQg2*}K{{YCiDqELj5|H&rp~yh&mHZ1zO(Ru`@%v}Y~tO#7e~!I-#s}$YU0^Z zozHeMhx!({D=bxAkz`N93ZyCKIQZ`pRkZ<;t*TU3)w+e7CbOfe`k<+q{g#O5|GMtf zEKH6wFGkn1#f^2vPsGETvT`R|pyJmX%4#u}S7;=^QDo_wIfsg?;ISL|^}AlwlS?p- zmpi--`RRZ~5@EppJM1lh_VDKli5?#j;1B?B0w^@Td(S6MqU22bwtFlE5I@(x=}t_x zZ@KZQ_RU@}EFABlqc8zOd;Aic31B$WfbdvF+J?nJsiO*Wup-Zd8tfQsM}<5+Rjfh9+7gM?< z?h4yE5Y`ZnW)Maz2y+|Y`5jh5I>P)M$_r-Kz<76edlHm2M3By5r1M0;+zQ$N+jr&_ zlP+Rjm$0DASkzNk(iJT0X`EU?dIl>HIZa3BJu4t(r~Zr-7wTT!42WlP-2lK-umo7! zR{_?bM9gCWix$`5V@dk2B!2=gNRm>i;*nP^%OjY|b6T~m&d{{evIEPunnatdWn@g$36kg_c8_g`(>;-qgwkv*ib_ zV>DfeSGfD!^_nfaVeGRmvW5+db!?d3man{gL$hV|aZNL{Cyz^WODB7r%ay+z*cAK< zKpRCe>OUOjE_}WDL+o6<-8nfK9y_!CV)I((+>OrBiSYQ@^|za)&iRSXv77spC@mcs zh!6uIHI#`^DxKMekgUs*yZ0+qwf1n@D9%n*r;1vs3fAGhf(=Z9x@G(HP|toes&u*ERkdOhKr&l0{W zhC^eki>m|P5PYEKvs5vRX5Ar%K{JNoxVU9Axz8|Owd(fnPS&*RzVDD=!NuMnd`SDM zC9PIfld11%>eQps995=kYEdg!RGO{SG$ z?2`KP0PVdel!hW+kzmpQTLO}YSDq$@aWr?pUAW0>?#b?dnfLL_h;7x9NU2zwB=nC*9ujX2*QdgMo5 literal 0 HcmV?d00001 diff --git a/__pycache__/write_image_characters.cpython-311.pyc b/__pycache__/write_image_characters.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4960fb4f329ef960bdee1031d34242711ba308b9 GIT binary patch literal 1778 zcmZ`(O-vg{6rTOXzt|2G0!ho_qBgV@v>_^L6IC@o0SB@s##R+4>1yj)!?yl`-E|3; zseC}H4>_b&C6G$0o@gsB9D2x+-g;cBNVP_)RH?miGa{#)`eq#yqquKozS(*2&Ac~n z-rJx2eh&g#|LyC{zdSjuTI&V5GHZex+z72p5$T zN7RKQ0brOX9azh##jHiRoSp|z?-Sm%w3T6&bmxn?&oo0RWRz1ACh?wrEAJ7ZU@dC~ z5f>Bjs5}FE+&MT)&+2*2a8m;uaT(fbQ8zS9T!j@&FXYuM5tnt0wLItxhMHf}h*(^~ zs-=NCm(H5R-;gUhb=oA1Zqk>LB7qj4UD|d~)zM|9TZ@J6J$~y5z<%MKIN!(tTUMxxNvSg%1gGSx_6`+FtKHp#U z{}t+axVk;~&4uqS)DiCvI8cq$e0_iVq(6L8Ehuf@vV#)sua7@|=Xc)z;HDjx>l_#E zJVu;9@RUOR1^CcgqmLs8s=aW_zH`@p_a5z+KCMYt_R9we`~4gCz+7G6`#QlCfDeVv zZ(rIUI>7eO9PNGcb&dsrh7y5Y-$Q#ZodeU1&b zlmgz*^EErZsvF$6Ho8htPkZb`F-MaXI`n=wLE+C|yo z7i+4qWEz8%^D2NzZw5IAWV}Y1VSv)xZBwFs&@R$bFhB*>0^#jf>_E8DtGtsacK^tJ z=&=9tVQB10XsnJH_caG-!UP|FxmEhMWQQ;Ryb1t)f8wxr{7LV)-F>yu4}DjwQ`MVpb6sl$;v?e<2pp%z;iJwm3{z(Z7&!Z7IHtU(Z3NE2 F{{fR9(8>S+ literal 0 HcmV?d00001 diff --git a/__pycache__/write_image_environment.cpython-311.pyc b/__pycache__/write_image_environment.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3b09cf87d1a2cb79ddbf3f723aa31ad25eb4b19a GIT binary patch literal 1491 zcmaJ>O>f&q5M6$XB4x{NoVX5>MgbBuLfzMSWGb>noo`#3W@J3Bl3$X}+W zR0QqM-@dQ?B_Q;QDU&9Sg;5TKBgCV1gwX-Q+*2N*=P;6HBFvXjUZ_qC>^+$st$=cb z9At7BnY<%l?f^Xn+jHg>H&evCDPh5sv1q2SWGYxT(>Qg2Ocg5-IZe+$Aa3N8ns(hO z`cGUE_)W);s@x<5yk!`005rM_aD?iR=FeP>!#ozS=yEmwOi4Nsu?#aJJgF1D#=9I= zPS|nMdS0L@Ozb_^uXi-;*4@bVayE&m)@lS%P$zb)u}|f)u~X95X}a0=BG+?$$H1T7ZD_I^cqj&fnhPM>?TU1$VNr_hFi6xM=fZNE|~RNG+`G%Y{CPFT46 zC?I~@t68V4d#s?A%PML)?@D^JwNJH@zFjdaV|Tk)?p!^y@;CqG!frZz1kgi61zp+T z`k$<`ez`QbeEpgB!svgx+`n}Dv~o57Z1eZI{%0%w+!w>Nv@ktH45rcS$HzBbT>As} zuWhovaDOQ9Fp*Vf)FDbBt&U(fC;~~vFDgdPw-KHHz>y59OiECd*ursR?ABn6z6Lk~ zx^%f8fXP1!-^pDW3tc|ZI#US67O^Y*$0Bvb)0P?s#F6!mwo0O0nceK0F}Slvq?Q97eEQw@pDNd z=a|bpK*cer;rP0mAnJ+D#4vV1tOWl`0#ngMQmOwL%=VGJ^<*weFoCZkk=$28^CJ;$+HI!6T?L`ccpi4aPAU7_C{}G@X>|d<{-P!+Zc+H zG!F!R50X9EPCBqP-j?0)yHwsNcak!!kn1oJ=W`2$p}=w6kiW=5*!STzv;BR>L>%}Z D$itT~ literal 0 HcmV?d00001 diff --git a/__pycache__/write_text.cpython-311.pyc b/__pycache__/write_text.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79a0cde84563c1291079d7763a2e328f9b276d72 GIT binary patch literal 1018 zcmZuvOK;Oa5Z?7G&Z`Y2eF+MY5Qkiv8!Zw-YD3yaEl!mTW&V2KYzvlB91R{O^*!_VK`pFI> z5pIoP35-+3p-n_k9}#@cA#?#N5e*Tph01(q`v@}U+86x+QmL+M(o}uYiuIU@9@xku^(6NYM@vw$-piTiC z;RsIzBAU3%nb^c|SyHI%8i#@D8iWcyq@YquZPt}dnzjSWH!ZVgsNYZ-Q|x&xd+DZH zIdE*F64*wsQg!U^QM+F01fK8Mde0$-S6P4SxV^yY>VJ9PGmttfvHb3cX6wpsTh-OQ z-CFB-cHF@7A8tmJ_ZU=&A_?W^2Zgz_g)iHe#j8h8t`=4zo?D!Xc%hJqkdV#{;X{Dw zrjkv9jbSJSKPl~>(7gp_iQ z%DUd$w+&sV8C|y>5?IX6>H1-?Z{0?+9c$n7Y{Nfrh?|3pG}o-D?WU6OIzB0DFKaC- zZ?u)FT5l*c+i0tdeWmfDMyGBM^_IRdzSuBo-nMsqK2BJMK=l{ChPa+zZPg7*eg zIDQ6VA>u?4<^k%ON79}C>%>t&#fRa};O>1;)Az!y!OUE^J(yhzmBI94xD^Rld>WyD wRZ^IhQ(&}lZN~cq&yD;n;pVyf00J?n6)++mV;pfa7}EZ$u9@%Ge*$sh-%$zq5dZ)H literal 0 HcmV?d00001 diff --git a/__pycache__/write_texts.cpython-311.pyc b/__pycache__/write_texts.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..458349b84cd8800529f7e65a722af0d8019aede8 GIT binary patch literal 2699 zcmd5;J#5=X6h4ZSL{YLOIc|!iNv$+U9K}u?J2qN4MOsyse-MWbY`JMv6a=B8ep*Si zNve(o1@K^?8ai~d(K@IRAU{PGj~P97q<{>`! z_uhBp9p6Vi?&%Q_l<33nGN1Yo`hyPIg==*VBGB1FE;NHM+C-Rn`w96lk#EjCQ1pI z2WB4;Zfki%Nh)^@JP;>Y=H-jE9sSu==#C8ru{R+Cq9>%_B^ zT$~eUh_6^K82LiJq$CMDCnjIeZF}Jch;qQAWMr5pY%yN~kna*sHeuMbo1}a_n#(PNTB^qBN|^i`+mt4`5Z9iqpbqQ{-0#~q?4oT4Y3q9 zQ5WGgWwo5w6ij$^h3fnf2wlk#t!%)S^^U zv7(QB_O+^&%7u*7WnH6rBN;StF0ZT;|D1ShIVmOY+)6A}jvpn}nw5Mk%HK*y@gPoS&!*?Zoq z7qeBDJ*xB|WLdZ>`wxq|%5_={`rfn(_EbUhDlqC+?kV(D=^hXK-YO5V{C)P2-&ghQ zb}+P=5W<4x>%Y(9KsOsO^mH)vzJ($9R))}97{ZPWuxIvDe6Lo$83weoPptT3nh{x| zvNjp1xCEgh%(ujClJ;Bj2L0Z+C2)}#6}U-3qhH605N~T71cQ?=ZY$elga}76M)&hL623l9WyDE^EAu?|GHdqF+qE8;|F{0z-~L?rv0`3~?X3dX zb$_frF#UXBx|_c?^?RtlwpQ!aF2ZJsQ9m4?RD#z+l87KlMHQC|v>%Y9)v{b@&G^#= zS=Wn-kyEi2g+LNmOeB{VMO$qTM`G+|Vu|q6%VIn^w;&S#!g7*ovbZpnAbdQQOw24S z-m#8QI}bG0P1wgu|LJHHXkzNO0X7bQ4R@&NI_U-_0(i+HPk8f7+wc+UAJ~|096JRN zd~aj6(RX~~Mk9D)W46f!-0wEg>tL@*R}w+WtYy1z8`ngie!X7^dmE R!T{~-@RHj8a+t8z`x_QB7v2B> literal 0 HcmV?d00001 diff --git a/combine_texts.py b/combine_texts.py new file mode 100644 index 0000000..0e83a4a --- /dev/null +++ b/combine_texts.py @@ -0,0 +1,46 @@ +class CombineTexts: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "number_of_inputs": ("INT", {"default": 2, "min": 2, "max": 10, "step": 1}), + "delimiter": (["newline", "comma", "space", "test"], {"default": "newline"}), + "text_1": ("STRING", {"forceInput": True}), + "text_2": ("STRING", {"forceInput": True}), + }, + "hidden": { + **{f"text_{i}": ("STRING", {"forceInput": True}) for i in range(3, 11)} + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "combine_texts" + OUTPUT_IS_LIST = (False,) + CATEGORY = "Bjornulf" + + def combine_texts(self, number_of_inputs, delimiter, **kwargs): + def flatten(item): + if isinstance(item, str): + return item + elif isinstance(item, list): + return self.get_delimiter(delimiter).join(map(flatten, item)) + else: + return str(item) + + combined_text = self.get_delimiter(delimiter).join([ + flatten(kwargs[f"text_{i}"]) + for i in range(1, number_of_inputs + 1) + if f"text_{i}" in kwargs + ]) + return (combined_text,) + + @staticmethod + def get_delimiter(delimiter): + if delimiter == "newline": + return "\n" + elif delimiter == "comma": + return "," + elif delimiter == "space": + return " " + else: + return "\n" \ No newline at end of file diff --git a/create_video.py b/create_video.py new file mode 100644 index 0000000..791d66a --- /dev/null +++ b/create_video.py @@ -0,0 +1,91 @@ +import os +import numpy as np +import torch +import subprocess +from PIL import Image + +class imgs2vid: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "images": ("IMAGE",), + "fps": ("INT", {"default": 30, "min": 1, "max": 60}), + "video_name_NO_format": ("STRING", {"default": "output"}), + "format": (["mp4", "webm"],), + "audio_path": ("STRING", {"default": "/home/umen/6sec.wav"}), # New audio input + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("comment",) + FUNCTION = "create_video" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def create_video(self, images, fps, video_name_NO_format, format, audio_path): + # Remove any existing extension + video_name_NO_format = os.path.splitext(video_name_NO_format)[0] + # Add the correct extension + output_file = f"{video_name_NO_format}.{format}" + temp_dir = "temp_images" + os.makedirs(temp_dir, exist_ok=True) + # Ensure the output directory exists + os.makedirs(os.path.dirname(output_file) if os.path.dirname(output_file) else ".", exist_ok=True) + + # Save the tensor images as PNG files + for i, img_tensor in enumerate(images): + img = Image.fromarray((img_tensor.cpu().numpy() * 255).astype(np.uint8)) + if format == "webm": + img = img.convert("RGBA") # Ensure alpha channel for WebM + img.save(os.path.join(temp_dir, f"frame_{i:04d}.png")) + + # Construct the FFmpeg command based on the selected format + if format == "mp4": + ffmpeg_cmd = [ + "ffmpeg", + "-y", + "-framerate", str(fps), + "-i", os.path.join(temp_dir, "frame_%04d.png"), + "-i", str(audio_path), + "-crf", "19", + "-c:v", "libx264", + "-pix_fmt", "yuv420p", + output_file + ] + comment = "MP4 format: Widely compatible, efficient compression, no transparency support." + elif format == "webm": + ffmpeg_cmd = [ + "ffmpeg", + "-y", + "-framerate", str(fps), + "-i", os.path.join(temp_dir, "frame_%04d.png"), + "-i", str(audio_path), + "-crf", "19", + "-c:v", "libvpx", + "-b:v", "1M", # Set video bitrate + "-auto-alt-ref", "0", # Disable auto alt ref + "-c:a", "libvorbis", + "-pix_fmt", "yuva420p", + "-shortest", + output_file + ] + comment = "WebM format: Supports transparency, open format, smaller file size, but less compatible than MP4." + + # Run FFmpeg + try: + subprocess.run(ffmpeg_cmd, check=True) + print(f"Video created successfully: {output_file}") + except subprocess.CalledProcessError as e: + print(f"Error creating video: {e}") + finally: + # Clean up temporary files + for file in os.listdir(temp_dir): + os.remove(os.path.join(temp_dir, file)) + os.rmdir(temp_dir) + + return (comment,) + +# Example usage +# images = [torch.rand(256, 256, 3) for _ in range(10)] # Replace with actual image tensors +# imgs2vid().create_video(images, 30, "output", "webm", "/home/ diff --git a/loop_basic_batch.py b/loop_basic_batch.py new file mode 100644 index 0000000..6b37969 --- /dev/null +++ b/loop_basic_batch.py @@ -0,0 +1,21 @@ +class LoopBasicBatch: + + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "nb_loops": ("INT", {"default": 1, "min": 0, "max": 1000, "step": 1}), + }, + } + + RETURN_TYPES = ("INT",) + OUTPUT_IS_LIST = (True, False) + FUNCTION = "create_loop_basic_batch" + CATEGORY = "Bjornulf" + + def create_loop_basic_batch(self, nb_loops): + range_values = list() + while nb_loops > 0: + range_values.append(1) + nb_loops -= 1 + return (range_values,) \ No newline at end of file diff --git a/loop_float.py b/loop_float.py new file mode 100644 index 0000000..13ff9f3 --- /dev/null +++ b/loop_float.py @@ -0,0 +1,24 @@ +class LoopFloat: + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "from_this": ("FLOAT", {"default": 0.00, "min": 0.00, "max": 1000.00, "step": 0.01}), + "to_that": ("FLOAT", {"default": 10.00, "min": 0.00, "max": 1000.00, "step": 0.01}), + "jump": ("FLOAT", {"default": 1.00, "min": 0.00, "max": 1000.00, "step": 0.01}), + }, + } + + RETURN_TYPES = ("FLOAT",) + OUTPUT_IS_LIST = (True, False) + FUNCTION = "create_loop_float" + CATEGORY = "Bjornulf" + + def create_loop_float(self, from_this, to_that, jump): + range_values = [] + current_value = from_this + while current_value <= to_that: + range_values.append(round(current_value, 2)) # Round to two decimal places + current_value += jump + return (range_values,) diff --git a/loop_integer.py b/loop_integer.py new file mode 100644 index 0000000..a34b459 --- /dev/null +++ b/loop_integer.py @@ -0,0 +1,32 @@ +# class AnyType(str): +# def __ne__(self, __value: object) -> bool: +# return False +# any_type = AnyType("*") + +class LoopInteger: + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "from_this": ("INT", {"default": 0, "min": 0, "max": 1000, "step": 1}), + "to_that": ("INT", {"default": 10, "min": 0, "max": 1000, "step": 1}), + "jump": ("INT", {"default": 1, "min": 0, "max": 1000, "step": 1}), + }, + # "optional": { + # "nb_loops": (any_type,) + # } + } + + RETURN_TYPES = ("INT",) + OUTPUT_IS_LIST = (True, False) + FUNCTION = "create_loop_integer" + CATEGORY = "Bjornulf" + + def create_loop_integer(self, from_this, to_that, jump): + range_values = list() + current_value = from_this + while current_value <= to_that: + range_values.append(current_value) + current_value += jump + return (range_values,) \ No newline at end of file diff --git a/loop_my_combos_samplers_schedulers.py b/loop_my_combos_samplers_schedulers.py new file mode 100644 index 0000000..fbc3660 --- /dev/null +++ b/loop_my_combos_samplers_schedulers.py @@ -0,0 +1,82 @@ +import comfy + +class LoopCombosSamplersSchedulers: + combinations = [ + "sgm_uniform/euler", "sgm_uniform/dpm_2", "sgm_uniform/dpmpp_2m", "sgm_uniform/lcm", + "sgm_uniform/ddim", "sgm_uniform/uni_pc", + + "normal/ddim", "normal/uni_pc", "normal/euler", "normal/heunpp2", "normal/dpm_2", + + "ddim_uniform/euler", "ddim_uniform/dpm_2", "ddim_uniform/lcm", "ddim_uniform/uni_pc", + + "simple/euler", "simple/heun", "simple/heunpp2", "simple/dpmpp_2m", "simple/lcm", "simple/ipndm", "simple/uni_pc", + + "exponential/dpm_adaptive" + ] + # "normal/uni_pc_bh2", "ddim_uniform/uni_pc_bh2", "simple/uni_pc_bh2", "sgm_uniform/uni_pc_bh2" + @classmethod + def INPUT_TYPES(cls): + # Generate the list of combinations from specified pairs + combi_list = ["ALL 6 COMBINATIONS (sgm_uniform)", "ALL 5 COMBINATIONS (normal)", "ALL 5 COMBINATIONS (ddim_uniform)", "ALL 7 COMBINATIONS (simple)"] + cls.combinations + return { + "required": { + "combination": (combi_list,), + } + } + + RETURN_TYPES = (comfy.samplers.KSampler.SAMPLERS, comfy.samplers.KSampler.SCHEDULERS,) + RETURN_NAMES = ("sampler_name", "scheduler",) + OUTPUT_IS_LIST = (True, False) + FUNCTION = "create_loop_combination" + CATEGORY = "Bjornulf" + + def create_loop_combination(self, combination): + if combination == "ALL 6 COMBINATIONS (sgm_uniform)": + return (["euler", "dpm_2", "dpmpp_2m", "lcm", "ddim", "uni_pc"], "sgm_uniform",) #, "uni_pc_bh2" uni_pc_bh2 is too similar to exist.... + elif combination == "ALL 5 COMBINATIONS (normal)": + return (["ddim", "uni_pc", "euler", "heunpp2", "dpm_2"], "normal",) #, "uni_pc_bh2" + elif combination == "ALL 5 COMBINATIONS (ddim_uniform)": + return (["euler", "dpm_2", "lcm", "ddim", "uni_pc"], "ddim_uniform",) #, "uni_pc_bh2" + elif combination == "ALL 7 COMBINATIONS (simple)": + return (["euler", "heun", "heunpp2", "dpmpp_2m", "lcm", "ipndm", "uni_pc"], "simple",) #, "uni_pc_bh2" + else: + # Split the input and output the selected sampler and scheduler + scheduler, sampler = combination.split("/") + # return [(sampler, scheduler,)] + return ([sampler], scheduler,) + +# + ("exponential", "dpm_adaptive") + +# TESTED GOOD WITH SD3, modelsampling 5 / CFG 3 / 28 steps + +# sgm_uniform + euler +# sgm_uniform + dpm_2 +# sgm_uniform + dpmpp_2m +# sgm_uniform + lcm +# sgm_uniform + ddim +# sgm_uniform + uni_pc +# sgm_uniform + uni_pc_bh2 + +# normal + ddim +# normal + uni_pc +# normal + uni_pc_bh2 +# normal + euler +# normal + heunpp2 +# normal + dpm_2 + +# ddim_uniform + euler +# ddim_uniform + dpm_2 +# ddim_uniform + lcm +# ddim_uniform + uni_pc +# ddim_uniform + uni_pc_bh2 + +# simple + euler +# simple + heun +# simple + heunpp2 +# simple + dpmpp_2m +# simple + lcm +# simple + ipndm +# simple + uni_pc +# simple + uni_pc_bh2 + +# exponential + dpm_adaptive \ No newline at end of file diff --git a/loop_samplers.py b/loop_samplers.py new file mode 100644 index 0000000..87b8d22 --- /dev/null +++ b/loop_samplers.py @@ -0,0 +1,23 @@ +import comfy + +class LoopSamplers: + @classmethod + def INPUT_TYPES(cls): + samplers = ["ALL SAMPLERS"] + list(comfy.samplers.KSampler.SAMPLERS) + return { + "required": { + "sampler_name": (samplers,), + } + } + + RETURN_TYPES = (comfy.samplers.KSampler.SAMPLERS,) + RETURN_NAMES = ("sampler_name",) + OUTPUT_IS_LIST = (True,) + FUNCTION = "create_loop_sampler" + CATEGORY = "Bjornulf" + + def create_loop_sampler(self, sampler_name): + if sampler_name == "ALL SAMPLERS": + return (list(comfy.samplers.KSampler.SAMPLERS),) + else: + return ([sampler_name],) \ No newline at end of file diff --git a/loop_schedulers.py b/loop_schedulers.py new file mode 100644 index 0000000..1ade307 --- /dev/null +++ b/loop_schedulers.py @@ -0,0 +1,23 @@ +import comfy + +class LoopSchedulers: + @classmethod + def INPUT_TYPES(cls): + schedulers = ["ALL SCHEDULERS"] + list(comfy.samplers.KSampler.SCHEDULERS) + return { + "required": { + "scheduler": (schedulers,), + } + } + + RETURN_TYPES = (comfy.samplers.KSampler.SCHEDULERS,) + RETURN_NAMES = ("scheduler",) + OUTPUT_IS_LIST = (True,) + FUNCTION = "create_loop_scheduler" + CATEGORY = "Bjornulf" + + def create_loop_scheduler(self, scheduler): + if scheduler == "ALL SCHEDULERS": + return (list(comfy.samplers.KSampler.SCHEDULERS),) + else: + return ([scheduler],) \ No newline at end of file diff --git a/loop_texts.py b/loop_texts.py new file mode 100644 index 0000000..80267f8 --- /dev/null +++ b/loop_texts.py @@ -0,0 +1,22 @@ +class LoopTexts: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "number_of_inputs": ("INT", {"default": 2, "min": 2, "max": 10, "step": 1}), + "text_1": ("STRING", {"forceInput": "True"}), + "text_2": ("STRING", {"forceInput": "True"}), + }, + "hidden": { + **{f"text_{i}": ("STRING", {"forceInput": "True"}) for i in range(3, 11)} + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "loop_texts" + OUTPUT_IS_LIST = (True,) + CATEGORY = "Bjornulf" + + def loop_texts(self, number_of_inputs, **kwargs): + text_list = [kwargs[f"text_{i}"] for i in range(1, number_of_inputs + 1) if f"text_{i}" in kwargs] + return (text_list,) diff --git a/ollama.py b/ollama.py new file mode 100644 index 0000000..22901e1 --- /dev/null +++ b/ollama.py @@ -0,0 +1,28 @@ +import ollama +from ollama import Client # pip install ollama + +class ollamaLoader: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "user_prompt": ("STRING", {"multiline": True}), + # "selected_model": ((), {}), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("ollama_response",) + FUNCTION = "connect_2_ollama" + # INPUT_NODE = True # Changed from OUTPUT_NODE to INPUT_NODE + CATEGORY = "Bjornulf" + + # @classmethod + def connect_2_ollama(self, user_prompt): + keep_alive = 0 + list_models=ollama.list() #{'models': [{'name': 'dolphin-llama3:latest', 'model': 'dolphin-llama3:latest', 'modified_at': '2024-04-24T06:56:57.498527412+02:00', 'size': 4661235994, 'digest': '613f068e29f863bb900e568f920401b42678efca873d7a7c87b0d6ef4945fadd', 'details': {'parent_model': '', 'format': 'gguf', 'family': 'llama', 'families': ['llama'], 'parameter_size': '8B', 'quantization_level': 'Q4_0'}}]} + print(list_models) + client = Client(host="http://127.0.0.1:11434") + response = client.generate(model="dolphin-llama3", system="I will give you an object, animal, person or landscape, just create details about it : colors, size, clothes, eyes and other physical details or features in 1 sentence.", prompt=user_prompt, keep_alive=str(keep_alive) + "m") + print("Ollama response : ", response['response']) + return (response['response'],) diff --git a/random_checkpoint.py b/random_checkpoint.py new file mode 100644 index 0000000..decbd8d --- /dev/null +++ b/random_checkpoint.py @@ -0,0 +1,28 @@ +import random + +class RandomCheckpoint: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "number_of_inputs": ("INT", {"default": 2, "min": 2, "max": 10, "step": 1}), + "model_1": ("MODEL", {"forceInput": True}), + "clip_1": ("CLIP", {"forceInput": True}), + "vae_1": ("VAE", {"forceInput": True}), + "model_2": ("MODEL", {"forceInput": True}), + "clip_2": ("CLIP", {"forceInput": True}), + "vae_2": ("VAE", {"forceInput": True}), + } + } + + RETURN_TYPES = ("MODEL", "CLIP", "VAE") + FUNCTION = "random_select" + + def random_select(self, number_of_inputs, **kwargs): + selected_index = random.randint(1, number_of_inputs) + + selected_model = kwargs[f"model_{selected_index}"] + selected_clip = kwargs[f"clip_{selected_index}"] + selected_vae = kwargs[f"vae_{selected_index}"] + + return (selected_model, selected_clip, selected_vae) diff --git a/random_model_clip_vae.py b/random_model_clip_vae.py new file mode 100644 index 0000000..869df78 --- /dev/null +++ b/random_model_clip_vae.py @@ -0,0 +1,33 @@ +import random + +class RandomModelClipVae: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "number_of_inputs": ("INT", {"default": 2, "min": 2, "max": 10, "step": 1}), + "model_1": ("MODEL", {"forceInput": True}), + "clip_1": ("CLIP", {"forceInput": True}), + "vae_1": ("VAE", {"forceInput": True}), + "model_2": ("MODEL", {"forceInput": True}), + "clip_2": ("CLIP", {"forceInput": True}), + "vae_2": ("VAE", {"forceInput": True}), + }, + "hidden": { + **{f"model_{i}": ("MODEL", {"forceInput": True}) for i in range(3, 11)}, + **{f"clip_{i}": ("CLIP", {"forceInput": True}) for i in range(3, 11)}, + **{f"vae_{i}": ("VAE", {"forceInput": True}) for i in range(3, 11)} + } + } + + RETURN_TYPES = ("MODEL", "CLIP", "VAE") + FUNCTION = "random_select" + + def random_select(self, number_of_inputs, **kwargs): + selected_index = random.randint(1, number_of_inputs) + + selected_model = kwargs[f"model_{selected_index}"] + selected_clip = kwargs[f"clip_{selected_index}"] + selected_vae = kwargs[f"vae_{selected_index}"] + + return (selected_model, selected_clip, selected_vae) diff --git a/random_texts.py b/random_texts.py new file mode 100644 index 0000000..30a6902 --- /dev/null +++ b/random_texts.py @@ -0,0 +1,27 @@ +import random + +class RandomTexts: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "number_of_inputs": ("INT", {"default": 2, "min": 2, "max": 30, "step": 1}), + "number_of_random": ("INT", {"default": 1, "min": 1, "max": 30, "step": 1}), + "text_1": ("STRING", {"forceInput": "True"}), + "text_2": ("STRING", {"forceInput": "True"}), + "seed": ("INT", {"default": "1"}), #Used with control_after_generate, + }, + "hidden": { + **{f"text_{i}": ("STRING", {"forceInput": "True"}) for i in range(3, 31)} + } + } + + RETURN_TYPES = ("STRING",) + FUNCTION = "random_texts" + OUTPUT_IS_LIST = (False,) + CATEGORY = "Bjornulf" + + def random_texts(self, number_of_inputs, number_of_random, **kwargs): + texts = [kwargs[f"text_{i}"] for i in range(1, number_of_inputs + 1) if f"text_{i}" in kwargs] + random_texts = random.sample(texts, min(number_of_random, len(texts))) + return (random_texts,) \ No newline at end of file diff --git a/save_api_image.py b/save_api_image.py new file mode 100644 index 0000000..4df46a9 --- /dev/null +++ b/save_api_image.py @@ -0,0 +1,47 @@ +import os +import numpy as np +from PIL import Image + +class SaveApiImage: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "image": ("IMAGE", {"forceInput": True}), + } + } + + FUNCTION = "save_api_image" + RETURN_TYPES = () + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def save_api_image(self, image): + # Ensure the output directory exists + os.makedirs("./output/", exist_ok=True) + + # Convert the image from ComfyUI format to PIL Image + i = 255. * image.cpu().numpy() + if i.ndim > 3: + i = np.squeeze(i) + if i.ndim == 2: + i = i[:, :, np.newaxis] + + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + + # Determine the next available filename + counter = 1 + while True: + filename = f"./output/api_{counter:05d}.png" + if not os.path.exists(filename): + break + counter += 1 + + # Save the image with the determined filename + img.save(filename, format="PNG") + + # Write the number of the last image to a text file with leading zeroes + with open("./output/api_next_image.txt", "w") as f: + f.write(f"api_{counter+1:05d}.png") + + return () diff --git a/save_text.py b/save_text.py new file mode 100644 index 0000000..4e4d23f --- /dev/null +++ b/save_text.py @@ -0,0 +1,37 @@ +import os + +class SaveText: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "text": ("STRING", {"multiline": True, "forceInput": True}), + "filename": ("STRING", {"default": "001.txt"}) + } + } + + # INPUT_IS_LIST = True + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("text",) + FUNCTION = "save_text" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + # OUTPUT_IS_LIST = (True,) + + def save_text(self, text, filename): + directory = "custom_nodes/Bjornulf_custom_nodes/SaveText/" + if not os.path.exists(directory): + os.makedirs(directory) + + base, ext = os.path.splitext(filename) + counter = 1 + new_filename = os.path.join(directory, filename) + + while os.path.exists(new_filename): + new_filename = os.path.join(directory, f"{base}_{counter:03d}{ext}") + counter += 1 + + with open(new_filename, 'w') as file: + file.write(text) + + return {"ui": {"text": text}, "result": (text,)} \ No newline at end of file diff --git a/save_tmp_image.py b/save_tmp_image.py new file mode 100644 index 0000000..9838dde --- /dev/null +++ b/save_tmp_image.py @@ -0,0 +1,38 @@ +import os +import numpy as np +from PIL import Image + +class SaveTmpImage: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "image": ("IMAGE", {"forceInput": True}), + } + } + + FUNCTION = "save_image" + RETURN_TYPES = () + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def save_image(self, image): + # Ensure the output directory exists + # os.makedirs("./output", exist_ok=True) + + # Convert the image from ComfyUI format to PIL Image + # Assuming the first two dimensions are extra, and we need to keep the last two + i = 255. * image.cpu().numpy() + # Reshape the image if it's not in the expected format, remove any leading dimensions of size 1 + if i.ndim > 3: + i = np.squeeze(i) + # Ensure the image is 3D (height, width, channels) + if i.ndim == 2: + i = i[:, :, np.newaxis] # Add a channel dimension if it's missing + + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + + # Save the image, overwriting if it exists + img.save("./output/tmp_api.png", format="PNG") + + return () diff --git a/show_float.py b/show_float.py new file mode 100644 index 0000000..fc42d2e --- /dev/null +++ b/show_float.py @@ -0,0 +1,18 @@ +class ShowFloat: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "float_value": ("FLOAT", {"forceInput": True}), + }, + } + + INPUT_IS_LIST = True + RETURN_TYPES = () + FUNCTION = "show_float" + OUTPUT_NODE = True + INPUT_IS_LIST = (True,) + CATEGORY = "Bjornulf" + + def show_float(self, float_value): + return {"ui": {"text": float_value}} diff --git a/show_int.py b/show_int.py new file mode 100644 index 0000000..8ba1735 --- /dev/null +++ b/show_int.py @@ -0,0 +1,18 @@ +class ShowInt: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "int_value": ("INT", {"forceInput": True}), + }, + } + + INPUT_IS_LIST = True + RETURN_TYPES = () + FUNCTION = "show_int" + OUTPUT_NODE = True + INPUT_IS_LIST = (True,) + CATEGORY = "Bjornulf" + + def show_int(self, int_value): + return {"ui": {"text": int_value}} diff --git a/show_text.py b/show_text.py new file mode 100644 index 0000000..32662c5 --- /dev/null +++ b/show_text.py @@ -0,0 +1,18 @@ +class ShowText: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "text_value": ("STRING", {"forceInput": True}), + }, + } + + INPUT_IS_LIST = True + RETURN_TYPES = () + FUNCTION = "show_text" + OUTPUT_NODE = True + INPUT_IS_LIST = (True,) + CATEGORY = "Bjornulf" + + def show_text(self, text_value): + return {"ui": {"text": text_value}} diff --git a/video_pingpong.py b/video_pingpong.py new file mode 100644 index 0000000..0b7f3c3 --- /dev/null +++ b/video_pingpong.py @@ -0,0 +1,23 @@ +import torch + +class VideoPingPong: + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "images": ("IMAGE",), + }, + } + + RETURN_TYPES = ("IMAGE",) + FUNCTION = "pingpong_images" + CATEGORY = "Bjornulf" + + def pingpong_images(self, images): + if isinstance(images, torch.Tensor): + reversed_images = torch.flip(images, [0]) + combined_images = torch.cat((images, reversed_images[1:]), dim=0) + else: + reversed_images = images[::-1] + combined_images = images + reversed_images[1:] + return (combined_images,) \ No newline at end of file diff --git a/web/js/BJORNULF_TYPES.js.txt b/web/js/BJORNULF_TYPES.js.txt new file mode 100644 index 0000000..db6345c --- /dev/null +++ b/web/js/BJORNULF_TYPES.js.txt @@ -0,0 +1,29 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.CustomBjornulfType", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Bjornulf_WriteImageCharacters") { + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + onNodeCreated?.apply(this, arguments); + const myInput = this.inputs.find(input => input.name === "BJORNULF_CHARACTER"); + if (myInput) { + myInput.type = "BJORNULF_CHARACTER"; + } + }; + } + else if (nodeData.name === "Bjornulf_WriteImageCharacter") { + + } + }, + async setup(app) { + app.registerCustomNodeType("BJORNULF_CHARACTER", (value) => { + return { + type: "BJORNULF_CHARACTER", + data: { value: value || "" }, + name: "BJORNULF_CHARACTER" + }; + }); + } +}); \ No newline at end of file diff --git a/web/js/CUSTOM_STRING.js.txt b/web/js/CUSTOM_STRING.js.txt new file mode 100644 index 0000000..5202e8b --- /dev/null +++ b/web/js/CUSTOM_STRING.js.txt @@ -0,0 +1,52 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.CustomStringType", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Bjornulf_WriteImageAllInOne") { + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + onNodeCreated?.apply(this, arguments); + const locationInput = this.inputs.find(input => input.name === "location"); + if (locationInput) { + locationInput.type = "CUSTOM_STRING"; + } + }; + } + }, + async setup(app) { + app.registerCustomNodeType("CUSTOM_STRING", (value) => { + return { + type: "CustomStringType", + data: { value: value || "" }, + name: "CustomStringType" + }; + }); + } +}); + + + // Override the default onConnectionCreated method + const originalOnConnectionCreated = LGraphCanvas.prototype.onConnectionCreated; + LGraphCanvas.prototype.onConnectionCreated = function(connection, e, node_for_click) { + if (node_for_click && node_for_click.type === "WriteImageAllInOne" && connection.targetInput.name === "location") { + // Check if the connected node is not already a CustomString + if (connection.origin_node.type !== "CustomString") { + // Create a new CustomString node + const customStringNode = LiteGraph.createNode("CustomString"); + // Position the new node + customStringNode.pos = [connection.origin_node.pos[0] + 200, connection.origin_node.pos[1]]; + this.graph.add(customStringNode); + + // Connect the new CustomString node + connection.origin_node.connect(connection.origin_slot, customStringNode, 0); + customStringNode.connect(0, node_for_click, connection.target_slot); + + // Remove the original connection + connection.origin_node.disconnectOutput(connection.origin_slot, node_for_click); + + return true; // Prevent the original connection + } + } + return originalOnConnectionCreated.apply(this, arguments); + }; \ No newline at end of file diff --git a/web/js/combine_texts.js b/web/js/combine_texts.js new file mode 100644 index 0000000..f44b1af --- /dev/null +++ b/web/js/combine_texts.js @@ -0,0 +1,52 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.CombineTexts", + async nodeCreated(node) { + if (node.comfyClass === "Bjornulf_CombineTexts") { + const updateInputs = () => { + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (!numInputsWidget) return; + + const numInputs = numInputsWidget.value; + + // Initialize node.inputs if it doesn't exist + if (!node.inputs) { + node.inputs = []; + } + + // Filter existing text inputs + const existingInputs = node.inputs.filter(input => input.name.startsWith('text_')); + + // Determine if we need to add or remove inputs + if (existingInputs.length < numInputs) { + // Add new text inputs if not enough existing + for (let i = existingInputs.length + 1; i <= numInputs; i++) { + const inputName = `text_${i}`; + if (!node.inputs.find(input => input.name === inputName)) { + node.addInput(inputName, "STRING"); + } + } + } else { + // Remove excess text inputs if too many + node.inputs = node.inputs.filter(input => !input.name.startsWith('text_') || parseInt(input.name.split('_')[1]) <= numInputs); + } + + node.setSize(node.computeSize()); + }; + + // Move number_of_inputs to the top initially + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (numInputsWidget) { + node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)]; + numInputsWidget.callback = () => { + updateInputs(); + app.graph.setDirtyCanvas(true); + }; + } + + // Delay the initial update to ensure node is fully initialized + setTimeout(updateInputs, 0); + } + } +}); diff --git a/web/js/loop_texts.js b/web/js/loop_texts.js new file mode 100644 index 0000000..931d53a --- /dev/null +++ b/web/js/loop_texts.js @@ -0,0 +1,52 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.LoopTexts", + async nodeCreated(node) { + if (node.comfyClass === "Bjornulf_LoopTexts") { + const updateInputs = () => { + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (!numInputsWidget) return; + + const numInputs = numInputsWidget.value; + + // Initialize node.inputs if it doesn't exist + if (!node.inputs) { + node.inputs = []; + } + + // Filter existing text inputs + const existingInputs = node.inputs.filter(input => input.name.startsWith('text_')); + + // Determine if we need to add or remove inputs + if (existingInputs.length < numInputs) { + // Add new text inputs if not enough existing + for (let i = existingInputs.length + 1; i <= numInputs; i++) { + const inputName = `text_${i}`; + if (!node.inputs.find(input => input.name === inputName)) { + node.addInput(inputName, "STRING"); + } + } + } else { + // Remove excess text inputs if too many + node.inputs = node.inputs.filter(input => !input.name.startsWith('text_') || parseInt(input.name.split('_')[1]) <= numInputs); + } + + node.setSize(node.computeSize()); + }; + + // Move number_of_inputs to the top initially + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (numInputsWidget) { + node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)]; + numInputsWidget.callback = () => { + updateInputs(); + app.graph.setDirtyCanvas(true); + }; + } + + // Delay the initial update to ensure node is fully initialized + setTimeout(updateInputs, 0); + } + } +}); diff --git a/web/js/random_model_clip_vae.js b/web/js/random_model_clip_vae.js new file mode 100644 index 0000000..5924c5a --- /dev/null +++ b/web/js/random_model_clip_vae.js @@ -0,0 +1,65 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.RandomModelClipVae", + async nodeCreated(node) { + if (node.comfyClass === "Bjornulf_RandomModelClipVae") { + const updateInputs = () => { + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (!numInputsWidget) return; + + const numInputs = numInputsWidget.value; + + // Initialize node.inputs if it doesn't exist + if (!node.inputs) { + node.inputs = []; + } + + // Filter existing model, clip, and vae inputs + const existingModelInputs = node.inputs.filter(input => input.name.startsWith('model_')); + const existingClipInputs = node.inputs.filter(input => input.name.startsWith('clip_')); + const existingVaeInputs = node.inputs.filter(input => input.name.startsWith('vae_')); + + // Determine if we need to add or remove inputs + if (existingModelInputs.length < numInputs || existingClipInputs.length < numInputs || existingVaeInputs.length < numInputs) { + // Add new model, clip, and vae inputs if not enough existing + for (let i = Math.max(existingModelInputs.length, existingClipInputs.length, existingVaeInputs.length) + 1; i <= numInputs; i++) { + const modelInputName = `model_${i}`; + const clipInputName = `clip_${i}`; + const vaeInputName = `vae_${i}`; + if (!node.inputs.find(input => input.name === modelInputName)) { + node.addInput(modelInputName, "MODEL"); + } + if (!node.inputs.find(input => input.name === clipInputName)) { + node.addInput(clipInputName, "CLIP"); + } + if (!node.inputs.find(input => input.name === vaeInputName)) { + node.addInput(vaeInputName, "VAE"); + } + } + } else { + // Remove excess model, clip, and vae inputs if too many + node.inputs = node.inputs.filter(input => + (!input.name.startsWith('model_') && !input.name.startsWith('clip_') && !input.name.startsWith('vae_')) || + (parseInt(input.name.split('_')[1]) <= numInputs) + ); + } + + node.setSize(node.computeSize()); + }; + + // Move number_of_inputs to the top initially + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (numInputsWidget) { + node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)]; + numInputsWidget.callback = () => { + updateInputs(); + app.graph.setDirtyCanvas(true); + }; + } + + // Delay the initial update to ensure node is fully initialized + setTimeout(updateInputs, 0); + } + } +}); \ No newline at end of file diff --git a/web/js/random_texts.js b/web/js/random_texts.js new file mode 100644 index 0000000..e5718cd --- /dev/null +++ b/web/js/random_texts.js @@ -0,0 +1,58 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.RandomTexts", + async nodeCreated(node) { + if (node.comfyClass === "Bjornulf_RandomTexts") { + const updateInputs = () => { + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (!numInputsWidget) return; + + const numInputs = numInputsWidget.value; + + // Initialize node.inputs if it doesn't exist + if (!node.inputs) { + node.inputs = []; + } + + // Filter existing text inputs + const existingInputs = node.inputs.filter(input => input.name.startsWith('text_')); + + // Determine if we need to add or remove inputs + if (existingInputs.length < numInputs) { + // Add new text inputs if not enough existing + for (let i = existingInputs.length + 1; i <= numInputs; i++) { + const inputName = `text_${i}`; + if (!node.inputs.find(input => input.name === inputName)) { + node.addInput(inputName, "STRING"); + } + } + } else { + // Remove excess text inputs if too many + node.inputs = node.inputs.filter(input => !input.name.startsWith('text_') || parseInt(input.name.split('_')[1]) <= numInputs); + } + + node.setSize(node.computeSize()); + }; + + // Set seed widget to hidden input + const seedWidget = node.widgets.find(w => w.name === "seed"); + if (seedWidget) { + seedWidget.type = "HIDDEN"; + } + + // Move number_of_inputs to the top initially + const numInputsWidget = node.widgets.find(w => w.name === "number_of_inputs"); + if (numInputsWidget) { + node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)]; + numInputsWidget.callback = () => { + updateInputs(); + app.graph.setDirtyCanvas(true); + }; + } + + // Delay the initial update to ensure node is fully initialized + setTimeout(updateInputs, 0); + } + } +}); diff --git a/web/js/show_float.js b/web/js/show_float.js new file mode 100644 index 0000000..471b8f1 --- /dev/null +++ b/web/js/show_float.js @@ -0,0 +1,76 @@ +import { app } from "../../../scripts/app.js"; +import { ComfyWidgets } from "../../../scripts/widgets.js"; + +// Styles for the text area +const textAreaStyles = { + readOnly: true, + opacity: 1, + padding: '10px', + border: '1px solid #ccc', + borderRadius: '5px', + backgroundColor: '#222', + color: 'Lime', + fontFamily: 'Arial, sans-serif', + fontSize: '14px', + lineHeight: '1.4', + resize: 'vertical', + overflowY: 'auto', +}; + +// Displays input text on a node +app.registerExtension({ + name: "Bjornulf.ShowFloat", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Bjornulf_ShowFloat") { + function createStyledTextArea(text) { + const widget = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget; + widget.inputEl.readOnly = true; + const textArea = widget.inputEl; + + Object.assign(textArea.style, textAreaStyles); + textArea.classList.add('bjornulf-show-text'); + widget.value = text; + return widget; + } + + function populate(text) { + if (this.widgets) { + for (let i = 1; i < this.widgets.length; i++) { + this.widgets[i].onRemove?.(); + } + this.widgets.length = 1; + } + + const v = Array.isArray(text) ? text : [text]; + for (const list of v) { + if (list) { + createStyledTextArea.call(this, list); + } + } + + requestAnimationFrame(() => { + const sz = this.computeSize(); + if (sz[0] < this.size[0]) sz[0] = this.size[0]; + if (sz[1] < this.size[1]) sz[1] = this.size[1]; + this.onResize?.(sz); + app.graph.setDirtyCanvas(true, false); + }); + } + + // When the node is executed we will be sent the input text, display this in the widget + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + populate.call(this, message.text); + }; + + const onConfigure = nodeType.prototype.onConfigure; + nodeType.prototype.onConfigure = function () { + onConfigure?.apply(this, arguments); + if (this.widgets_values?.length) { + populate.call(this, this.widgets_values); + } + }; + } + }, +}); \ No newline at end of file diff --git a/web/js/show_int.js b/web/js/show_int.js new file mode 100644 index 0000000..6234708 --- /dev/null +++ b/web/js/show_int.js @@ -0,0 +1,76 @@ +import { app } from "../../../scripts/app.js"; +import { ComfyWidgets } from "../../../scripts/widgets.js"; + +// Styles for the text area +const textAreaStyles = { + readOnly: true, + opacity: 1, + padding: '10px', + border: '1px solid #ccc', + borderRadius: '5px', + backgroundColor: '#222', + color: 'Lime', + fontFamily: 'Arial, sans-serif', + fontSize: '14px', + lineHeight: '1.4', + resize: 'vertical', + overflowY: 'auto', +}; + +// Displays input text on a node +app.registerExtension({ + name: "Bjornulf.ShowInt", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Bjornulf_ShowInt") { + function createStyledTextArea(text) { + const widget = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget; + widget.inputEl.readOnly = true; + const textArea = widget.inputEl; + + Object.assign(textArea.style, textAreaStyles); + textArea.classList.add('bjornulf-show-text'); + widget.value = text; + return widget; + } + + function populate(text) { + if (this.widgets) { + for (let i = 1; i < this.widgets.length; i++) { + this.widgets[i].onRemove?.(); + } + this.widgets.length = 1; + } + + const v = Array.isArray(text) ? text : [text]; + for (const list of v) { + if (list) { + createStyledTextArea.call(this, list); + } + } + + requestAnimationFrame(() => { + const sz = this.computeSize(); + if (sz[0] < this.size[0]) sz[0] = this.size[0]; + if (sz[1] < this.size[1]) sz[1] = this.size[1]; + this.onResize?.(sz); + app.graph.setDirtyCanvas(true, false); + }); + } + + // When the node is executed we will be sent the input text, display this in the widget + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + populate.call(this, message.text); + }; + + const onConfigure = nodeType.prototype.onConfigure; + nodeType.prototype.onConfigure = function () { + onConfigure?.apply(this, arguments); + if (this.widgets_values?.length) { + populate.call(this, this.widgets_values); + } + }; + } + }, +}); \ No newline at end of file diff --git a/web/js/show_text.js b/web/js/show_text.js new file mode 100644 index 0000000..2f2a01a --- /dev/null +++ b/web/js/show_text.js @@ -0,0 +1,76 @@ +import { app } from "../../../scripts/app.js"; +import { ComfyWidgets } from "../../../scripts/widgets.js"; + +// Styles for the text area +const textAreaStyles = { + readOnly: true, + opacity: 1, + padding: '10px', + border: '1px solid #ccc', + borderRadius: '5px', + backgroundColor: '#222', + color: 'Lime', + fontFamily: 'Arial, sans-serif', + fontSize: '14px', + lineHeight: '1.4', + resize: 'vertical', + overflowY: 'auto', +}; + +// Displays input text on a node +app.registerExtension({ + name: "Bjornulf.ShowText", + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "Bjornulf_ShowText") { + function createStyledTextArea(text) { + const widget = ComfyWidgets["STRING"](this, "text", ["STRING", { multiline: true }], app).widget; + widget.inputEl.readOnly = true; + const textArea = widget.inputEl; + + Object.assign(textArea.style, textAreaStyles); + textArea.classList.add('bjornulf-show-text'); + widget.value = text; + return widget; + } + + function populate(text) { + if (this.widgets) { + for (let i = 1; i < this.widgets.length; i++) { + this.widgets[i].onRemove?.(); + } + this.widgets.length = 1; + } + + const v = Array.isArray(text) ? text : [text]; + for (const list of v) { + if (list) { + createStyledTextArea.call(this, list); + } + } + + requestAnimationFrame(() => { + const sz = this.computeSize(); + if (sz[0] < this.size[0]) sz[0] = this.size[0]; + if (sz[1] < this.size[1]) sz[1] = this.size[1]; + this.onResize?.(sz); + app.graph.setDirtyCanvas(true, false); + }); + } + + // When the node is executed we will be sent the input text, display this in the widget + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + populate.call(this, message.text); + }; + + const onConfigure = nodeType.prototype.onConfigure; + nodeType.prototype.onConfigure = function () { + onConfigure?.apply(this, arguments); + if (this.widgets_values?.length) { + populate.call(this, this.widgets_values); + } + }; + } + }, +}); \ No newline at end of file diff --git a/web/js/write_image_characters.js b/web/js/write_image_characters.js new file mode 100644 index 0000000..0f3a0cd --- /dev/null +++ b/web/js/write_image_characters.js @@ -0,0 +1,53 @@ +import { app } from "../../../scripts/app.js"; + +app.registerExtension({ + name: "Bjornulf.WriteImageCharacters", + async nodeCreated(node) { + if (node.comfyClass === "Bjornulf_WriteImageCharacters") { + const updateInputs = () => { + const numInputsWidget = node.widgets.find(w => w.name === "number_of_characters"); + if (!numInputsWidget) return; + + const numInputs = numInputsWidget.value; + + // Initialize node.inputs if it doesn't exist + if (!node.inputs) { + node.inputs = []; + } + + // Filter existing text inputs + const existingInputs = node.inputs.filter(input => input.name.startsWith('character_')); + + // Determine if we need to add or remove inputs + if (existingInputs.length < numInputs) { + // Add new text inputs if not enough existing + for (let i = existingInputs.length + 1; i <= numInputs; i++) { + const inputName = `character_${i}`; + if (!node.inputs.find(input => input.name === inputName)) { + // node.addInput(inputName, "STRING"); + node.addInput(inputName, "BJORNULF_CHARACTER"); + } + } + } else { + // Remove excess text inputs if too many + node.inputs = node.inputs.filter(input => !input.name.startsWith('character_') || parseInt(input.name.split('_')[1]) <= numInputs); + } + + node.setSize(node.computeSize()); + }; + + // Move number_of_inputs to the top initially + const numInputsWidget = node.widgets.find(w => w.name === "number_of_characters"); + if (numInputsWidget) { + node.widgets = [numInputsWidget, ...node.widgets.filter(w => w !== numInputsWidget)]; + numInputsWidget.callback = () => { + updateInputs(); + app.graph.setDirtyCanvas(true); + }; + } + + // Delay the initial update to ensure node is fully initialized + setTimeout(updateInputs, 0); + } + } +}); diff --git a/write_image_allinone.py b/write_image_allinone.py new file mode 100644 index 0000000..17dbeeb --- /dev/null +++ b/write_image_allinone.py @@ -0,0 +1,84 @@ +class WriteImageAllInOne: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "art_style": (["none", "drawing", "digital art", "photography"],), + "location": ("STRING", {"forceInput": "True"}), + "lighting": ("STRING", {"multiline": True}), + "camera_angle": ("STRING", {"multiline": True}), + }, + "optional": { + "other": ("STRING", {"multiline": True},), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("text",) + FUNCTION = "write_image_allinone" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def write_image_allinone(self, art_style, location, lighting, camera_angle, other=""): + text = f"Art Style: {art_style}\n\n" + text += f"Location:\n{location}\n\n" + text += f"Lighting:\n{lighting}\n\n" + text += f"Camera Angle:\n{camera_angle}\n\n" + if other: + text += f"Other:\n{other}\n\n" + return (text,) + + @classmethod + def CREATE_CONNECTED_NODES(cls): + return [ + { + "class_type": "PrimitiveNode", + "inputs": { + "value": "drawing", + "label": "Art Style", + "type": "combo", + "options": ["drawing", "digital art", "photography"] + }, + "output": ["art_style"] + }, + { + "class_type": "PrimitiveNode", + "inputs": { + "value": "", + "label": "Location", + "type": "text", + "multiline": True + }, + "output": ["location"] + }, + { + "class_type": "PrimitiveNode", + "inputs": { + "value": "", + "label": "Lighting", + "type": "text", + "multiline": True + }, + "output": ["lighting"] + }, + { + "class_type": "PrimitiveNode", + "inputs": { + "value": "", + "label": "Camera Angle", + "type": "text", + "multiline": True + }, + "output": ["camera_angle"] + }, + { + "class_type": "PrimitiveNode", + "inputs": { + "value": "", + "label": "Other", + "type": "text", + "multiline": True + }, + "output": ["other"] + } + ] \ No newline at end of file diff --git a/write_image_character.py b/write_image_character.py new file mode 100644 index 0000000..2f28d81 --- /dev/null +++ b/write_image_character.py @@ -0,0 +1,22 @@ +class WriteImageCharacter: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "description": ("STRING", {"multiline": True}), + "action": ("STRING", {"multiline": False}), + "emotion": ("STRING", {"multiline": False}), + "clothes": ("STRING", {"multiline": False}), + }, + } + + # RETURN_TYPES = ("STRING",) + RETURN_TYPES = ("BJORNULF_CHARACTER",) + RETURN_NAMES = ("character_details",) + FUNCTION = "write_image_character" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def write_image_character(self, description, action, emotion, clothes): + text = f"{description}, {action}, {emotion}, {clothes}" + return (text,) \ No newline at end of file diff --git a/write_image_characters.py b/write_image_characters.py new file mode 100644 index 0000000..c6d9342 --- /dev/null +++ b/write_image_characters.py @@ -0,0 +1,32 @@ +class WriteImageCharacters: + @classmethod + def INPUT_TYPES(cls): + hidden_inputs = {} + for i in range(2, 6): # Notice the range starts at 2 and ends at 6 to include 5 + hidden_inputs.update({ + f"character_{i}": ("BJORNULF_CHARACTER", {"forceInput": True}), + # f"character_{i}": ("STRING", {"forceInput": True}), + }) + return { + "required": { + "number_of_characters": ("INT", {"default": 1, "min": 1, "max": 5, "step": 1}), + "character_1": ("BJORNULF_CHARACTER", {"forceInput": True}), + # "character_1": ("STRING", {"forceInput": True}), + }, + "optional": { + "other": ("STRING", {"multiline": True, "forceInput": True}), + }, + "hidden": hidden_inputs + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("text",) + FUNCTION = "write_image_characters" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def write_image_characters(self, number_of_characters, other="", **kwargs): + text = f"Other: {other}\n" + for i in range(1, number_of_characters + 1): + text += f"{kwargs.get(f'character_{i}', '')}\n" + return (text,) diff --git a/write_image_environment.py b/write_image_environment.py new file mode 100644 index 0000000..8b9bedb --- /dev/null +++ b/write_image_environment.py @@ -0,0 +1,27 @@ +class WriteImageEnvironment: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "art_style": (["drawing", "digital art", "photography"],), + "location": ("STRING", {"multiline": True}), + "lighting": ("STRING", {"multiline": True}), + "camera_angle": ("STRING", {"multiline": True}), + }, + "optional": { + "other": ("STRING", {"multiline": True, "forceInput": True},), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("text",) + FUNCTION = "write_image_environment" + OUTPUT_NODE = True + CATEGORY = "Bjornulf" + + def write_image_environment(self, art_style, location, lighting, camera_angle, **kwargs): + text = f"Art Style: {art_style}\n\n" + text += f"Location:\n{location}\n\n" + text += f"Lighting:\n{lighting}\n\n" + text += f"Camera Angle:\n{camera_angle}\n\n" + return (text,) \ No newline at end of file diff --git a/write_text.py b/write_text.py new file mode 100644 index 0000000..a9860da --- /dev/null +++ b/write_text.py @@ -0,0 +1,19 @@ +class WriteText: + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "text": ("STRING", {"multiline": True}), + } + } + + # INPUT_IS_LIST = True + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("text",) + FUNCTION = "write_text" + OUTPUT_NODE = True + OUTPUT_IS_LIST = (False,) + CATEGORY = "Bjornulf" + + def write_text(self, text): + return {"ui": {"text": text}, "result": (text,)}