From 911c313350ec8ef4d08c91e51c8f5dcd99d9bece Mon Sep 17 00:00:00 2001 From: hetima <33700+hetima@users.noreply.github.com> Date: Mon, 26 Jan 2026 15:43:29 +0900 Subject: [PATCH] add files --- .github/workflows/publish.yml | 25 +++ README-ja.md | 32 ++++ README.md | 31 ++++ __init__.py | 18 ++ assets/lora.svg | 3 + assets/slp01.jpg | Bin 0 -> 35039 bytes assets/slp02.jpg | Bin 0 -> 30925 bytes js/single_line_picker.js | 320 ++++++++++++++++++++++++++++++++++ single_line_picker.py | 35 ++++ slp_lora_loader.py | 78 +++++++++ 10 files changed, 542 insertions(+) create mode 100644 .github/workflows/publish.yml create mode 100644 __init__.py create mode 100644 assets/lora.svg create mode 100644 assets/slp01.jpg create mode 100644 assets/slp02.jpg create mode 100644 js/single_line_picker.js create mode 100644 single_line_picker.py create mode 100644 slp_lora_loader.py diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9d80b87 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,25 @@ +name: Publish to Comfy registry +on: + workflow_dispatch: + push: + branches: + - main + paths: + - "pyproject.toml" + +permissions: + issues: write + +jobs: + publish-node: + name: Publish Custom Node to registry + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'hetima' }} + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Publish Custom Node + uses: Comfy-Org/publish-node-action@v1 + with: + ## Add your own personal access token to your Github Repository secrets and reference it here. + personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} diff --git a/README-ja.md b/README-ja.md index 5057bf1..c4119c2 100644 --- a/README-ja.md +++ b/README-ja.md @@ -4,3 +4,35 @@

# ComfyUI-SingleLinePicker + +リストからワンクリックでテキストを選択できるComfyUIのカスタムノードです。LoRAやプロンプトの切り替え作業を劇的に改善します。 + +![screecshot01](./assets/slp01.jpg) + +## Nodes + +### Single Line Picker + +入力されたテキストを個々の行のリストとして表示します。選択された行を出力します。 + +表示されるテキストは、複数行テキストを出力する適当なノードからINPUTの`text`に繋げることで反映されます。最初の実行時やテキストの内容が変わると選択状態がリセットされ、何も出力しません。ノードを選択したときに出てくるツールボックスから部分実行を行えば全体の工程を行わずにテキストが流れ込みます。内容が固定の場合は一度読み込まれたら接続を切っても大丈夫です。 + +ノード情報パネルのParametersで`source_text`を直接編集することでも内容を変更できます。 + +ノードを選択したときに出てくるツールボックスに ![icon](./assets/lora.svg) マークのボタンが追加されます。これをクリックすると、インストールしているLoRAの一覧を取得しリストに表示します。後述するSLP Lora Loaderに直接出力できます。 + +**辞書モード**:テキストの一行目に`#dict`と記入すると2行目以降をコロンを挟んで「表示テキスト: 出力されるテキスト」と解釈して処理します。長い文章を簡潔なタイトルで把握することができます。 + +![screecshot02](./assets/slp02.jpg) + + +### SLP Lora Loader / SLP Lora Loader (Model Only) + +デフォルトのローダーとほぼ同じです。LoRAファイルの指定部分がコンボボックスではなくテキストになっているのでSingle Line Pickerを直接繋げることができます。 + +出力パラメータ`stem`を持っています。LoRAファイルの拡張子を除いたファイル名を出力します([audioscavenger/save-image-extended-comfyui](https://github.com/audioscavenger/save-image-extended-comfyui) はLoRAの名前を参照することができますが、SLP Lora Loaderの`lora_name`を参照しようとするとエラーが出たため名前を`lora_name_text`に変更しています。この`lora_name_text`を参照したとしてもエラーにはなりませんが、正常な値は取得できません。`stem`出力を加工するなりして対応してください)。 + +## Changelog + +### 1.0.0 +- 最初のリリース diff --git a/README.md b/README.md index 5057bf1..9a87eac 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,34 @@

# ComfyUI-SingleLinePicker + +This is a custom node for ComfyUI that lets you select single line from lists of text with a single click. It dramatically improves the process of switching LoRA or prompts. + +![screecshot01](./assets/slp01.jpg) + +## Nodes + +### Single Line Picker +Displays the input text as a list of individual lines. Outputs the selected line. + +The displayed text is reflected by connecting the `text` input to an appropriate node that outputs multi-line text. During the first execution or when the text content changes, the selection state resets and nothing is output. Performing a partial execution from the toolbox that appears when selecting the node allows text to flow in without running the entire process. If the content is static, it's fine to disconnect after it has been loaded once. + +You can also change the content by directly editing `source_text` in the Parameters section of the node information panel. + +When select this node, a button marked with the ![icon](./assets/lora.svg) icon will appear in the toolbox. Clicking this button retrieves a list of installed LoRA files and displays them. You can output directly to the SLP Lora Loader described later. + +**Dictionary Mode**: Entering `#dict` on the first line of text causes subsequent lines to be interpreted as “Display Text: Output Text” separated by colon. This allows you to grasp long contents with concise titles. + +![screecshot02](./assets/slp02.jpg) + + +### SLP Lora Loader / SLP Lora Loader (Model Only) + +It's almost identical to the default loader. Since the LoRA file selection part is text instead of a combo box so that connect a Single Line Picker directly. + +It has an output parameter called `stem`. It outputs LoRA filename without file extension ([audioscavenger/save-image-extended-comfyui](https://github.com/audioscavenger/save-image-extended-comfyui) can reference LoRA name, but since attempting to reference `lora_name` in the SLP Lora Loader caused an error, the name has been changed to `lora_name_text`. Referencing this `lora_name_text` will not cause an error, but it will not retrieve the correct value. Please handle this by modifying the `stem` output or similar means). + +## Changelog + +### 1.0.0 +- Initial release diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..4d5f563 --- /dev/null +++ b/__init__.py @@ -0,0 +1,18 @@ +from .single_line_picker import SLPSingleLinePicker +from .slp_lora_loader import SLPLoraLoader, SLPLoraLoaderModelOnly + + +NODE_CLASS_MAPPINGS = { + SLPSingleLinePicker.NAME: SLPSingleLinePicker, + SLPLoraLoader.NAME: SLPLoraLoader, + SLPLoraLoaderModelOnly.NAME: SLPLoraLoaderModelOnly, +} + +NODE_DISPLAY_NAME_MAPPINGS = { + SLPSingleLinePicker.NAME: SLPSingleLinePicker.DISPLAY_NAME, + SLPLoraLoader.NAME: SLPLoraLoader.DISPLAY_NAME, + SLPLoraLoaderModelOnly.NAME: SLPLoraLoaderModelOnly.DISPLAY_NAME, +} + + +WEB_DIRECTORY = "./js" diff --git a/assets/lora.svg b/assets/lora.svg new file mode 100644 index 0000000..5cf9ada --- /dev/null +++ b/assets/lora.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/slp01.jpg b/assets/slp01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..42ebe8bc0986ccebef840c175d22caf6dcf493a4 GIT binary patch literal 35039 zcmd>m1yEeuw%~zAg9UeY5AGI%2X_zd4#7Pk!J!F|;2I#%5ZnU<5AM*oTW|@^bnesp z=gpt@XKJQuYMMGlckgx9-plrqy-q*QKCS>y6=fA<0XR4~;1%o-c$^2M0Td)8WF$ls zWMpJiRFo&^co^ttXz0W^xLA1PB$O27BxGb%bR3LSG;FkFWK06gY|prOd3h-rg~SB8 zMLBqQxql;pLq$bJM?)vVz#!tLCZp#5FTWn!0c;dFdH7Kf91Q@E4F|%8d+Y)z0RRpW zw%Xqd{_6`49)y61gp7jv1PumI`xJnO1A*WXK!}J42r%eC*f@ZIjfg|dC542mZiYE+~Kwf`bVUgbhdl$4}*jkP*~X;$1#AKOFiN z2#)+vpjgKPJ_+{tR`8|i9)1A>pRwqGpoZ#)7%kAN`sBVbB-+j%`E zaC0rOBrzO9+;A|TR4>#`uW(yYeIf3Aq%uX+kG-U@KXB*kQ9G8MI@zMWMN+@>Ypfy<4`D51KEQUp_S4pF!)6c6+CDgxYY zF()z-zk<{@u0IJ8eU7o&qQf#v1D-1gG184kP(4NM*b}p}oZsRfY0hHq-}L2nVGJhq z$wAqn%PQj4+&DcIt&(pamK9M$NC`eU&yGJWX7QJ}x>4=D*1`iU*NN9cezQ+=e&96K zj{a;|hR#2rd-<2g5WovoQRwIW4Ux&P%vBe-aH9Cl^uv54R@O5nxDPn0nrY0ZjtjrB z?}@;Si8i+z@9M54`&q&>x6rJ~AAm+z2&y1Cav>ERS$G(W+-b|lOWd~11x<_jEsjT^ zIm;HV<~Q;W>k`a#{xO;nBg|DQcQJ0z5Mn913!xkf(etAIYS+_#T2S$kB<}7bus?sl zyvG7Dn0N$c>Tla7wG9An6>dMz92`uk4!q0LOOA1Gi!Gu&v8-2TsAyTPuvIq4EjEgH zWN47t#3eHxejAy*Zf=Ef!V^cKUx*y_4dd?qQL$}HLu*-iP zTYb141*FVB7zWQU!1(TR?eqv3rRC%xvKbQ7t-P{Mz!4_X0$-aleo(j$a*R7q{J9YD zU9w{b#!#mI9-eMw;`Kt&pQot^NBtw@#W1e_UiSwJ2`(ys^zr`sL8okQQ8jp^ziI)? zi_?}*0!eMLEn1$yZvp)linuB#?Eqa2`i4a<_O-9L8P%(GkQfYAVI+X#DvYJ5n0Qyg zAok{H+Zzv#=(nhtisb4CjUNGT(Qz`HO}couC?JjV>Z0Kh2!W}8SW)zYn6t!+#BdJL zh!_*_Tg!5zwh>}t$TSP)8hkAiLnplpqkmlAjmr(3u6V-~v0t!%cRb49*PqZ%r1A`1 z4FpHEL53|OEcVU(=(cey%`Hn<4emE9nPF;i8qYY`*WUdMCVm)~^fn_IC&w*gRxb86 zlsB)7e%yYD++3{(V+yv9_yJbLjKpHX>Z-wxb<< zR>debLM9m}mLD;iA?;Z*IP;3*%?K-%w28Vqc^w`CKdXa1F7N{Xz)@5DfA<^ra1>M~(lE`KbY>Hokt7KVfQ^jNDyGT|}nQL|sXePdsj!wdBj z9Z5^SERsU-A}Z9-4#&*d&@4>ebQ*S-?3V98e*`WL9*!>Xbs%Yxys_Kh)2v?VH9J7d)JB$-P9_|sc2>wg!ionM;MAA zErL!IRJM%Bxlf2}q9BysX;?vw>8sIThfw?Obku}AHh!`KTm%NsPq*OO>#1wd9fUkMv4|Kdi5XF(i7WIZ)iB21@vm^ymgx@~I<9J}LwCM69C zwntDCGujHlML)-c?M1qgpu^+}C~RCA>Aw zls_)*sjL*yEhIqu^a{rnNg=NWJV)!gpAqjzF-PY_S2zjbU*2AHlr1@g|ROm z!Gg9zarBnV^dQKK_IU+KK5nhw6WEH{=~mE_WbEjxWLIZ|D9&T;NVzPU={C+_NMB>} z#4$ls=>xJ^8Ep!=oM?5>1uV(pVCY6zv{plrN26ZiW?*JIsOaI?EL;zBDUq>a9=wUU zfboYT20JFMl~wu=$xnixS34~!^eV#G4WA;Yrf?1quDHg4JEIm7+%#-eH`kA*DA*V? zOR;za5**u(g5PSFsy_mK{HDL!zLzqybi7k@XM(dZK4q~X7964m$l$RW3i1+2UN4^< zCUciqKM_s}Rhtj)ZPGgV){ozcX+K84`Bk}%hs#A>YwLX{!??!+$)tY1)dHEt!nD^y zo_>%?hy`z#lreKn)r4m>Ytgu&n&JCj147ADYTKkpOK<#V_>38{5eJ{nFWBB}JbMR> z;LX6Z$1k(^m>msKC$H64Hw5Y^p_$RwynZmhFMRLQNZcbxM`=KNT)Pprke<#2UE>4e zgPkA@{%~<^MXh#2zD4Ono*le^f+eo|s*b+kVvT>s`4@xOL9F5(m86~l{2I6)4b&*2 z;X5*b&D>6^uDcPEtrK|mAkFX{w0N$EXa5|6CV^Q)@-3D8B*MX=UooELxir&J;_P;1 zsV+Bk&*97NzP}4XY>+bzShvfala{o}KdSa=SVzkq0-e);ru?Y&lnog)!miyimfW4$I$EK+`oMgoE6qBoi zkNiuoS%E`J)xtb)T*A-OEgh^g%ayo>93;-Socj6F9+uz%k`}I(Svzi?5U!b8&8o3- z7lgqPj2gANe)@*MDAL<+TeU9EkohjCXulhFoFJsL!R>7iPtrWTGwF^^%_KYZ!wA@` z4Qy%nonO8vri2dtL5vCXX_9yMd~TZg^64Hq1^+^MQ7-a$t<(AhM3fKXq9-F&Q^9=< z=d@`Bz&cJ;yNcM{1WzNS^xwU&tQ!h?(LcPfjeK0HbMv+G_yczLrGmA9ih)p~B@2I? zt6!ikyw>;u!z6EMv|E%GeP}?{!2!C_Q^x1$KJ zp#n*m)#P`Sy99Ns>(_B`Y(hkWv`Ambkve{hW$OpkLoc`A6t zv+O~43eYw`Ara`JqXM{R7B||_{zGDXQ&T!y5)2QF3NXtam6togEc93&9Yw-8d?%J! z(r6fMSd1UmJg?M3Ee2O)Z-CL0Oze;zZG24>X*G}_XJk<{U2{RaSwD7YZatQV%UzLb z6JZAk4Qpj!LDWuOo)|ftDIk=vS<%8JhJ#Kq*Fw08^Puptsv zCqboqqQ{}aZTCS9Df!FWP`7ZfFZrH*)ck|kc-f2GO>HsM(igE%`95SyMMWsU)J_Dd zwK2&nSmq>+aC<3ZU+eUF*+h2SV9rP-y2Eyj4S9nF;(4;zQDRp|aJ<*6+)%5^`6J1_ zXIp5w(T@^Bov}BsvL*SouZPM&@@Zy>7vuORG8eXJGTY&wu3z%$vL#tdLrl>Q{BM=) znjVIo26N2b4TSe1)3%!JNSr={x#o-G>_IgI&0T}o8d<|w@ja$qT`+-~1P)7HsR*Jr z+n_5zOgH0%=j~_R?CV`@`XbHOPU(fS_F&HTlc%^NwDtJ?FeImVwY_(js`n^rh`zL7 zViF;Bu#BLUSr}Hs=jo#NkHCiIWbl4-uyD(<9m&hrt|oH|UVL3jY*mp_zEVwypc2q@ zh!B*u#F(U0MR=_B?O{rP9+%k<0(3tzzZjeI;+kew!#?YVXsN7iZZf2X)78j8&^Fz@ zZ3Ee&{IL?5Ti=OrFM}cvGhF2ia;vS+JC$gqX{)+-;wJc$T>Zqry4c=u#Unto75=cX zd_xYHsT-156=wJu_ml*p8PU13akZDL@nC}$$X2iv)3#MBGkN!K4gKFA92Ri(I}x9e z>$@eqx#$zy0U;%8XNG-Au@(f-!48nN(G_8_&GzwZ74R%8wL|6s6(h3ymkN^H0!s~gjVJs>ijnQ&E5PPCZaY5%P zUXvD4B3>|d9gXMK#ovq0T>I3!z3d)#XTI*nSI02Vfy!(2ITXT>XUsXjL#!fUUZ)5mL8P3# zp6rL#w#A3MFH;bSd;j3(dl~H<tE;nEG(JrEiuEjhbBww5$gteTOF0Y7+9R$z zJY5jyiCNjo%L^s-zNt$N7VGY`<6%3)nSZ+t7a!o5%U3FtSNkwJp*(o`1)JP@mRwG< z6It-G+gx38$c}H-(p=qTk!`cINAzm@ zxT7qJ2_&sI`3Th3g1k50yGJ#HEYZ=m3#ZxWC)j=-@%A(D=Y};I{TyD;N>?@?lO(yk zsV!snvYlqT3G6_pKKte~>q&ibai9^8?MwI?%f^H61c?%nuJ_;XvE840rbl{49j z-FYE+8Q?%Wro4a8TK_Q8eU*P|Y`aC!38c1%HLM7y7oKUfji*ePG?Y>#wvu}tDG z;Bd*u>80bhT6sg+L>F)&b~3@IG4frfUZ>68{}Esz=~*Mss}aR^XE>HJJS8k2wt~VnzffiA-OsrN!us zZBeap2+7y2NM2Ui8lg4K9I#);c)0+^+sup=G^ckRTZi)pk^~2jz$7Q*SxGSN^`z_i4^of%44Zue z=<-x``J)Woscy@y1q){#4zKmB<}|+VrMb{lQ=|Ip*GxH} z6Nya9$h)0Vzld~?!UZ-$TO8R~OW>IVD>|%9r1_W8y{WiNj}p;-`_MEZ1DgT3Hzq}C zrIN@nyb`$AV=};R1Tc&;ct8;2Sw8F@JT#n?JVxg zh;rR_>GMITSf3d|X3bG|+jG#dU~7gE0Wtk4n{7;Do$Y}?X7+It`AMhqdR7B1g2kj3 zAyn%ourRi3h*)Vhrt&Ra0#BUJz9b$@8e=e;qpBT>mX?wEQ<7A0BbZu1yV<7pY=|yh z4_?_4H@|MCLlO0plaoKJCP$!%ztIVRm2;N&HF_fR|5f_T@fVGeH~&jb&RrrJIn@@;M2`^B2$Hj-<48Cz4Ag`izbFZBx-p34>{Orp7vNY za}`91A08tqP~^mn>s_^a-U>RJPgwA~v@CUv+Z@O=?8lUgc=fh=z&7p)hu5b*wmYZ# zeJ?y}F2^H7=9)q1{C5k1tOQX^K;HlSf|n;?%;L+EjiYH7`QpqX=9ZW}+!Sq!uYcuh zfB`?0CFIIs-6~`^bK9)7D#ti^JHsdgIGHTjxqUqHWN4c>jHHnl*i;Lyq@u3;DYtH* z=974E$L06Vc+z^(x#epjc)cHbO(%Z1KHezI1k%7zQ5tAS)tjtEt|4BolBTs7MH1XD zG)e7>cZ19;qsJG`8TL4>=#46xy${2}2xk|0XTWIYRjN10eyYwQed zgwaaoYJ1FtF07Xn`S_7@UtW~)i6SmjyT6}Xi4Rr+hs9YnaeZI(4%9<< z40nLUxDQ19Ey9gC?{Mvc+q^U5^ELMHxj;A<4KC^^+>hDc7oXF zM6^@24%bhmeH|pGvjfY-_6*jn1oxFy{tAFa6`wXJKae|vdbDZEW3ZUDn+{=b*9+J0Vy8w zpdYONr7HT~!k0v6;fG&|(C)!_$tau*Y%~2YT!`tc@7c>m2ciWJ*E=YT;(qY#CsWPn zuZbzCM0$EKggY<=@-rw;4DzGb|9Ey6dNkywUFxvrcKb-5W`imiz8Tn|Hm@5xC!X!h~a#|nC4K|gr*af%Q8Je`@ z4Znm*oz;g~%E7brl*RoaX*V~%sm>8M)&bsk9EWpkfkS}j67I-l>t(}n0e@YB60M^V z4G*)n_ONgNicSqwaME)GV`1^(NU64p)0=AraVbcBuQvyjwi-0$cBxu*eR`kq?Ga%0 zook*U=Q&bIc{uf#htM~DI)Hg}U0flSY^hN-1aA!7g&(8TaX1@!xZu((q@d)5D`~?C z_H(+LtSwUCTpJGhSGiSP8@MwNSFKkRd0)8Qyroroir!bS*JAi>ZOwd4w}00oknl|P z`n=pZ_~PgS@?<3Y-v8d7?x@&{A^t(C>JeytfYsyW9s#PkU|8(&gWa&-G%7#!F_yyIJ zi{S5+{_)P&Zue%)wbCT2a}jgE@`Lx3Zh2zv5W@N`1$~Kc~+k*5eu& z$$7YVk$Jr67)!oJ@T^dpX3xC}U%9$4l#wdcFQ2J_3Q0cxpVd^m91nE3=11QH^#m zFJ8@_nc3aRNhgi%E6MD7?_~_?W~w#`ix5;SeVzmD^1#eyFyYjyEc!sZ=JZOnN!V(5Ef+ zQ9XTeiypTP5OlQT7c$?Wkw@pfszGzjney1(T<8<88B1p4yuY|FG2WQqVP}u$ts&8m|{9)6+nUo zPr8*5={Plz6%PWW%IqmfQ=;iSouvC5&6%$(zdP^4Q7 zhl+$Etlan}(Js8>{pELBzf*~M74g9NxY4C~x4319nMr+BJYTt;3fWA$*RFS{rky zbTl*WV9aK9vp1+v_g3Iu;N8P*QSaZkiPD$IvbS`)J+2;6&!vO_EHfn%UNC~m=XbKP zKfZQi<|PpRp=U4K0)uKXen)btM-|f*xr}D3t!VOXqZdx5dd)3i%c?$vPG$B-j34!0 zIaAqelHWT7{c1Nr=P|Lngtp$LMeQDx7^c>%W54G(j`6k$T3Ru0L}PdP8ALKw6I^}t zFbYOK^Ijh~9U!wH+x9N*VYOBz_f1>3H=UbZEXWiXIJ>u)YZD13vp6YEIb5D;egyjQ zzR?G^tyGL}76+i&xmDPekZ-KZG*1NAST?;9co9`Js5ws^A%U&t)3XHSM7w!8eQ4E#C7L!6Oki8z zM37Wu|BbS-(TSfRlK!3gX*iNoSMuq|Ss}f*)!0M)X_Ki>s@&#-X;wb(BY?S+a)TIG zy2h?}y68nr&Tdg1YROXUIxfB@*uNtLK@Gqtw4J^gggz8{5-PXG%>{MiRAvYhYJjlA zV<=Q##yN;jbd!jt$<%!++wm}-pH-%-lVxpVPc}N_5`ua&i}hg0L42kI-8;3y*2V~w zZg&oU<)09}U@9ggJC+kV7*9WafR*gR@AVwK&hE1JUG}y{-UYxF`GkF6eAO^*a=69s z=0TAW)C&SsdK1>9i2wyD(J{{RlEoSjGqK1bB7{J(hOs1{_E@ax@l- zHJa~Qi?%y1di}O@Cjyv8WlyhC9)uLb`gn6X3>!w$M`rL1m`!t<$kziSRNv$JpxttG zc!q)uY0)gtQq-|sLk7D5mV5Cmw#^E9#A$TTaWO{#ZkHt4U0^Xb9O@wc1Z%`nse*&JbP`b zJsVFOEE@7-i`=)f$3J-5-y8&sJpwC1k}yN)ytz{uaymDCvV4^{jv*~y*&uKn9ejWy z`Ur5)yzSG1_LhcbJFDVnTD9@32T(vOmY=y+p-edE1Of&iMI(NVk9q?lk95_7sI!=&~HT1CEg|TC0M3 zXi@^E@HE{`m``>4&E~=8+Ze($qfrGH_QERZ+eWh7_Xi*rL0Zwwh**646;QHi}Zqx?q6jp0=GIapjh&b}vm zRheYnVDcb#snQ>#L>--g#G-ca(|)5KknTs8<*#js^>l~7DfYZH*VsUcCx4zVC2v5i z9GQjgl{eB+V)l=^qN{YwLWUxW+|R~x4n8OHZRV|9FGXvh_#4oGb~&RcN>|yVcP$bH zJ_227dkaRUVvCQY?Q^dwzJkL1r=*j_eO;n6mI|Wg6m$5@Oe?sRM9c0R>vzArQ zs6vh7Iz>Pssv3l!VR_zdZ@>4KJ>A4zaYYk5$~gx@sFJS*fZT85=Xr1EB>F%qCHpE8&VXEo4JmDLtvR2QUklb5L5c3Pbi_2le#~eO{QF0Mn>Q`I$8*h@x$r5V^mt&PdF1 z3r*A}Y==6EUSdJS=}*SQRGDnPKo?i)zK=)oehfqtQ+u<7xppniabgod_G z0r3)_&9M&`>*ob~YxPD0yoz=R68h~5jCzaZoJYULU8g`-668M7>4~Iged?Wv!Gg3w zUz49bRc4es z?r)nqav``cFLxYYg7R5$zmV)Vmn9VQ%aUcjG~t_ow-YePdh^Tgb0SW+1GllSTVJtz zmbnw%!6mKOKCSKvZ_{wBgOwYAE933vO}BcLSjZwjANNeIWM9RwIoM$L3c*|Vp(Yp- zd-T+YRC&}>lP%RRv5DYhFjaPhUo)lSbX=w%Ijaa1H&>3?oPDKIbL)ipFro}QzO-zs zz2*IyzIIu;O`1tVD-tJ?6t!9$jQf>6K^;~^`s)R!Q@WU)C@Y*+seL&4K|>fcWH|fR zLxIGu*o0gk5D1zm^+yYVN(y6ST|);gA4sgN0~&mp9pdP8@qT)Xfiz!^{HegeL!e-} zP45HpL`^HxUXzhBO6-(Xv>R)fTVj?}KlzE~6>jfqg0vTYCdCJ6hT)q7U#mWh0P7hs zH=YpA_kQ>VI!ZlVoTTndxvCVckM|W?3nN&7Zi1z-?(}j6sDush>gwhaqEQF_W z<`~vvFJ;fOSeh(^yX|ZcxS^z6cy0+e+#VgnO8#I6-Ipi!>Bms%mI=>$>7V&dEvf32mgK2aF~#S+GHbW1{Dt&Wt&pS3h!G)1o%y%7xv#5Muy&2^ z@!)Di<>=IxdL4@NpuN5>8;Xgn>%_yd+c4LWp{=Z`ldbD-(;z=NKVR77`zq$kHo``h z?-$rYHKg6d8Z8jUU+9^|IP20b(p{3Z04LYpS%vMEIRchTSKcK@PuN5ML3VYG!c zc#YJdIo+;orM}t{cfd<95;w?ILDXVXqR`IxPH?6yr^#12GzH3#F<%Jftw7mlDHdXm z^H4iqC@kq4GX{>W%a*9C$6(VCCP2El**?YQvlzZUdI`GLTA~|uJkJDm)~EbD;Ja@D zt0-A1=tB8V+Pg94gH=cF!fs}_Y|F!CkDW^(deO64!_c{nQ#0`CrWtPkeb+*e#f{c< z5W;jh_b|v+pJcq&8q5as8Z6Xjm5- zc3{B5x(adu_WWX77pI0RY*S7Z-p-+$Sf;=B7C|WBma)wzJ0f{JooSIPSAllz!uJ8^s4iLEiN=~GHmt~( z&N3!WLfzqOg_XzKyynDJb^*!y>53NV%jl0~oR2{DN_}0z3!5awdIG8yr;gpF$`-@C zxn06K4?FP7o1k3V)Yog~=U`?~`Wrs5t^JhXgtcBu;)4KAv{(%Vs zbKhnzrQO?XPbIdCQZo*E#cR%wks5An=8C1aL zW&FsO!yO$(;mka6^q2RAKQx>B)S@R}Pd)D?dIa=*J8ce=^fdxRrXX8yRNab*TF%3E z*IMLmX}Q{QR_=<5&qwfn9+?>%Y}3lThR$?0m#Pvj?m(RuYmNuLzQ^MGJ;Ad=PH%4DmehKkLA6sCR=5?6NkHZpg_*J6J`$<`UcC)w~yx$I;YTe3o zfrl;!+g2*sIhGUXEv6n}w69<<^Ugm4i1wEna|N=~cP7f0J|;b@)|yOvZ{pr%op*WE z=qeRo5$a9kDn!p2^=`AbKg^Dc9^%0K5XN`k1S5k%`Y1_EOd>xD468pCv=9v-zP~j0 zb?jT0_&NNxqw2p#dH(Ly{oS1&kS>75_Vk%>)&+?1>my*YeE0~c8>e>0Kb3Rw;s`A^ zD|4wTrp$5YiqFRsZ@4HIQ2iT_b|_27hlKVGY-mLJo2j8T{Hq{SOb4)j-B!Iz*5b$s zwZx#O#Jyi9LU@9!j9(2qVOKEXHOCLWX1ESf0>S8s(3a+bQ)dI#4_1~=f%NmyfYyJh-Jcl*Dd_=@km;7J8lpTMJ z1)xpan>UspRk#O&FdwJnz7q3he#=Q*nIIJc^36*doA^e5y65XUWL?h;YB$dId zV&cELntEr)FWAaZ&dloSapa9M5M!lw4;{GIyGI#5UJ84~9QV?l4C}1z3?||Up%Jx1 zd9EflPu`Y6Bl1~ytI?bkv=+MR^~|V*Fk|cEbCE*W+CmRhRJ#ZA7Q!-b2=qHer>&rXU@=TD|-9l(c(Q!Q5U_d2;Z@7*8Hs-}U|N1)4lz5oiLsQ>A^~Swv&bWnTn=J>4_@V%z-`Gm$}cjE z!46r~&&sCHVZAd`YzHk^YZ$`%b&HEb_M>t&nXAMD9x>>aUVIbEYnjA%TE9wt(>+$# zEh&ElUo6QkHuMDjBHlexf|V2ndMMI@9}t2sVC#BIx{jqR@d&_6+)QB^UOxho>;1L5yuITnq)tK9C5O5hfN{4%F(Z~lH4%$AZq++)=4o~1AKYg z)-1TTtzzF&O@Wu)`}>VbvR6fSky3%OaJ3RbOm){$v!9cOH`ZZ>_2(1QXx>&ArI~4{ zu0F?wJbjpebZV5KA^{^2v7q3vZ>hv_et_9-5iGKW6;Tc1uhhRiJBK~Ta7_CMK%{4G zU`@}|5R$;Q{))+|13G^!rBm)RhbqZ|JtE&es|YgApB$ z$aK{T-)kVeS1EEVnsl}7;~RejzQ>-t`<(puy( zH~qpwXlUpNo$h}krODK$!-xwVc5?4d*0sg}&!%ttDIraECQ8?NE8W$0j!tt)nRAzA z`~D-CK4HC`^}?TPc=ux|=<6FpSG;*-;~UYfq=>0jwu=n1AMjja#9+maI~17C!cyFS zQVav9QDtNOMCCPh*6vH_VRrE{#|P(Hi33vR&$5=cg-^ssZb zfBv;R>%h<2w$F?%T?OfIW#xQ#$l^bdj1Y$dOu;)I0WNm-%|`%q*Tx-@xdst=S#vC! z9y7ixAb?~1{fm^gFJ27JGZk(hvBqwD2NT+fgPKL@pMFcp!X~Pu^sNzK>J+`H&WG#E z@^P+tAqj)%|1lp+mR+dzjjz+(uZkqa8BWL&_v&0+DrE2ymEA1IdlBCIC|Fo+i|3HJ z+UH+YDA#8~tfw6hX`*FY>Q%q)ZlU1Vxt%fqY?$IFY7)Y*?zn#v(4TB*iiKG&*-^tu zRh^^jAmktyyLhZo|3cPB>BzTqpKT0S1v7D$)6f_w3%0+RiModL^ zf}>WRlf2w!?7#$%|L0rxjt~q6LvK(WOX{CQmH#IyHTQ$}i>`5!liOgXE9Kyu<728g z>2z>0d!fL`n(m&Z#my8!w6SEO+#ax47c)t4bCDjPJk6)a*Yugj+)0|4-Qetc#SvB0+?Y01s9#p#k}TUE5rAQTk@&+q*PJEc|NzAmgan9Ud@% z)W~w4{hz2>4iw9 zDy_iWJGLjdTYvZRga)@yB6SO{e7pOBqV9x0;~O*VWZ_7EM&N1jbvn60o467#Y5fnnm{kD3}3>%v! zwAc#@gn?#PdBlc;VF&+C3Cs%@oZ0l9jR@#0nAW#Cwbux4eko&57JDnHGE*_3h{CR! zHX$FWw)PRgGWBuMJUk*4!RN#gkd*3E2siQf~dG0X#RP#DW+> zINz<}yw9+2bubFQ4^rD2$;&=Z>@OtHRc4NnqITt$71n^SgAHp4i#n@MmSX0_V5>$g z*_~~^7zq!r(S*nN9Q(NpmOKl+dH!I#*X)}EHA0P%B|HO$7d)bXikh*SskWcDL)}3` z43hoV_JU3}4U3yEj_S*i6(yx$qZ4zAl{yH|1gYYZ&C09|@tfywtK7~hYTz{O^6g5o z?A*xA<=#$V$Xgjxu9SPq2(wMFpBBP$HI5?0lu{z7(SmDa>yI;MY@(Iw)F*2Tqc9zZd zi+zuX;LB8S^(ESFE7YEZ(5Lp2AokUJN1*wC9e+b_VSRd%G@C&d#5Yo&?3qOni*|zfGvhAXFcy#Z^bz-wkAR$^_i7mS zl2a6|VNl9~1uw)@#>X~@Wzy6N;*BVl?wMU`?`f4!zs;8zbZmXTy6Xp)8bP!(Ddb`f z+2H+K(r%L4gG1QVNVzVkb>O98g?^L*qK{1Um?}YzpoX)KFIgmGE{=Sr7|{a)nob1^ zrR2>iNOl&i6o(;i`))wbmv3NFr3#)|@xr}Im9CwfQO?$>j=OlT4jRm@@TI>w zO}R?F)j3@@s5<3i`t0A*ZDmmyj<-Yn`o|fbNF;z8fnY(j*8HhOceUX&80zwLSADQd zecfTUlhu*PXF=J~NFl)f+2`C;OAvG5Z0r9ao#`dj^uVV1)Z z$lm3QKxxrVw40OFQ?P!yGdhJ?&st?b3@Hfqm_vpQ#CpxO@9@3oi;cw(z}_p-e!PKi#6te4U0H?w8);MHCw*gudRXnN6Jbr3kLE>AX);o zF}Ox4OgR;lj&7?Ci(+WE#hQ@kEi7qrQ1xX`qqfTr)8Y#M>aK@Tre%35BPLN{{B702 zWxxJ9ee9|X3f)K6uO>(}&@zVsn(|r3hO+c^F$+zD(LLO~l*GA_hc6b~2TAu6%g5!xMh)@m;j&YAvHr@L z0iAfqv)5IIheWJwB1Wr~bN*h$+g#2Ug;ir4EmcXXF}3~R(*b#Im4b%3TS&P%H-~;z zQ5GhT+y!iIAJQP&li|#QU4CzV-8$UX^HTEaeu=}cD#ZOp8=L_;AHFe+^Ip_MYfhct z`j@QfKCym6D%Rr*RekP|IKg`_{eXQSW?9q5jfF!Rar=VQ@^rAw`>Ps2B-96ZD3w5s z^!Kx94Ey;iG4r(Zj3rc+J~YJtK;2B?svAdfCMxb2fsjj-52*GYW46tBSFCukuPw5R z8i)!`6t_N$lpB1eAj(+&)8o8UCyQpxGx&2~^IfTT600WX`3DYZhk2Zm@OeDjnb05_~uFgmz>PJk8t)Y<_)bA>om6 z<1wCI7M;#+s`k)dH<`7ywI=}nzO8b0z%l&PH%yI-0w6bfRk2u5TYoWs*K?B@d-VR? znE!&UqSjEvKea=z@RN4qZilE%o!`Xa#Uji1QxT=s=Sygx_+;1cZJv7n?mrJpImQwZ0mw6nruoEBMLtu{KK ze;K;$gRwuFc%CN=g~j2q52PSiPBWv`Mw(uE6)u;mC2Z-JnQw~3@(L$xKBS-M0#v+j zpuPP%Y;VA@wr2dGmN8_HlkSovBJ(4plZQu{ydChS!x#*5bTf&34qf^6^>6idEssZ_ zwsj)}RV}X1V4AzHQvT6SMR5#ru*ZT$VPYp4@mvO|ET~%oWC~J?2eo4&kJ6-auQ-iYZ+^TK6u|| zX^NHXT~%LmSv3lLnyDF-Yv8QML+=xwr5aL(2bD4}F`i>W%JsLSLE#&%(DjtXd?`@X z@ZbxuW1kp`5OG;d6gLz6#h|W$w}xWECs|hmeDi|PeT^77izkZkH9Uu40YOKy*J2L5 z{KB}h9!nv7hnAoN4aT|GKe(EQ=reG4v#=&Loh{`mZ-s|H%ZH^p#wh&63eZuJA;yFA zyDN)yq7hD@)}ngWM_VpuP^ge7D+5mu^)iZ^IiyCzQaw=;O@;vm3jCKo!0jp*GV*>v z|5M%F-jY}O?+?UOh3LV%^7NmVa{ayLGETI!JdkKg+%e3I%I5BNg|3lD=o(JUNS5~e z2`qj=<_&3u72F(LzRx7sEpd#wlxGjr*R_S&nIas>Bq|7!Wg**l{iUPo{^I6$_|*15 zh!q;V!y9~zNJ5$UVgXR1RZC6p())2kj`m}VFI#=Ev6a(Mq>zlDbXF>Rg zlyU}lidPPMh*9 z+6lZiu!_j#W~y()eD$h5sj{w4&e=YeLNZYKKLE?!aZtiP0;8}qh!wi!JDGrL-9u0R z0cDC_?N4|H%e>JbBn0p~jKujQNlI8z;rr?_=RH#V13U~*m!`z3^A$=)rjgA<%hn^X z#=7}~3AE?(A1ISpb-f~d2#3{D;28b@O8d8f+-VhP^56%%0Avr@l|Wct^(PwtyJfGh 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 G`Tqd**vq*9 literal 0 HcmV?d00001 diff --git a/assets/slp02.jpg b/assets/slp02.jpg new file mode 100644 index 0000000000000000000000000000000000000000..77e530cdea664076f0ebc93368064193f0253c26 GIT binary patch literal 30925 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 literal 0 HcmV?d00001 diff --git a/js/single_line_picker.js b/js/single_line_picker.js new file mode 100644 index 0000000..38bb18e --- /dev/null +++ b/js/single_line_picker.js @@ -0,0 +1,320 @@ +import { app } from "../../scripts/app.js" +import { api } from "../../scripts/api.js"; +import { ComfyWidgets } from "../../scripts/widgets.js"; + + + +app.registerExtension({ + name: "hetima.SLPSingleLinePicker", + commands: [ + { + id: "hetima-slpsinglelinepicker-get-loras", + label: "Get Lora List", + icon: "pi pi-file-plus", + tooltip: "Get Lora List", + function: () => { + const slp = Array.from(app.canvas.selectedItems)[0]; + slp?.listLoraFiles?.(); + } + } + ], + getSelectionToolboxCommands: (selectedItem) => { + // Return array of command IDs to show in the toolbox + if (selectedItem.type == "HetimaSingleLinePicker") { + return ["hetima-slpsinglelinepicker-get-loras"]; + } + return []; + }, + async beforeRegisterNodeDef(nodeType, nodeData, app) { + if (nodeData.name === "HetimaSingleLinePicker") { + const style = document.createElement("style"); + style.innerText = ` + .single-line-picker-container { + width: 100%; + height: 100%; + position: relative; + display: flex; + flex-direction: column; + + overflow-x: hidden; + overflow-y: auto; + white-space: nowrap; + + background-color: var(--bg-color); + color: var(--fg-color); + } + .single-line-picker-list-item { + cursor: default; + user-select: none; + padding: 3px; + font-size: 12px; + } + .single-line-picker-list-item-selected { + background-color: var(--fg-color); + color: var(--bg-color); + } + + `; + document.head.appendChild(style); + + const addListItem = function (container) { + const itm = document.createElement("div"); + itm.className = "single-line-picker-list-item"; + container.appendChild(itm); + }; + + const setItemData = function (itm, label, realText) { + itm.innerText = label; + itm.dataset.realText = realText; + } + + const selectItem = function (itm) { + if (!itm.classList.contains("single-line-picker-list-item-selected")) { + itm.classList.add("single-line-picker-list-item-selected"); + } + }; + + const deselectItem = function (itm) { + if (itm.classList.contains("single-line-picker-list-item-selected")){ + itm.classList.remove("single-line-picker-list-item-selected"); + } + }; + + const selectedText = function (container) { + var result = ""; + const lineCount = container.childElementCount; + for (let index = 0; index < lineCount; index++) { + const div = container.children[index]; + if (div.classList.contains("single-line-picker-list-item-selected")) { + if (result != "") { + result += "\n"; + } + result += div.dataset.realText; + } + } + return result; + } + + const selectedIndexes = function (container) { + var result = ""; + const lineCount = container.childElementCount; + for (let index = 0; index < lineCount; index++) { + const div = container.children[index]; + if (div.classList.contains("single-line-picker-list-item-selected")) { + if (result != "") { + result += ","; + } + result += index.toString(); + } + } + return result; + } + + + const onNodeCreated = nodeType.prototype.onNodeCreated; + nodeType.prototype.onNodeCreated = function () { + const ret = onNodeCreated ? onNodeCreated.apply(this, arguments) : undefined; + const node = this; + + node.properties = node.properties || {}; + node.properties.selected_indexes = node.properties.selected_indexes || ""; + + + this.textListWidget = ComfyWidgets["STRING"](this, "source_text", ["STRING", { multiline: true }], app).widget; + this.textListWidget.inputEl.readOnly = true; + this.textListWidget.callback = async (v) => { + this.textListChanged(); + } + this.textListWidget.hidden = true; + + this.selectedTextWidget = ComfyWidgets["STRING"](this, "selected_text", ["STRING", { multiline: true }], app).widget; + this.selectedTextWidget.inputEl.readOnly = true; + this.selectedTextWidget.hidden = true; + + // this.stemTextWidget = ComfyWidgets["STRING"](this, "stem", ["STRING", { multiline: false }], app).widget; + // this.stemTextWidget.hidden = true; + + const container = document.createElement("div"); + container.className = "single-line-picker-container"; + // container.style.width = "100%"; + // container.style.height = "100%"; + // container.style.position = "relative"; + // container.style.display = "flex"; + // container.style.flexDirection = "column"; + // container.style.overflowX = "hidden"; + // container.style.overflowY = "auto"; + // container.style.whiteSpace = "nowrap"; + // container.style.background = "transparent"; + + node.container = container; + node.container.addEventListener('click', (e) => { + const lists = Array.from(e.currentTarget.children); + const clicked_index = lists.findIndex(list => list === e.target); + // -1 is deselect all + const lineCount = this.container.childElementCount; + for (let index = 0; index < lineCount; index++) { + const div = this.container.children[index]; + if (index == clicked_index) { + selectItem(div); + }else{ + deselectItem(div); + } + } + if (clicked_index > 0) { + } + node.selectionChanged(null); + e.stopPropagation(); + }); + + node.listWidget = node.addDOMWidget("list", "TEXTLIST", container, { + serialize: false, + computeSize: () => { + const width = Math.max(node.size[0] || 200, 200); + const height = Math.max(node.size[1] || 200, 200); + return [width, height]; + }, + }); + + node.textListChanged(); + return ret; + }; + + const onExecuted = nodeType.prototype.onExecuted; + nodeType.prototype.onExecuted = function (message) { + onExecuted?.apply(this, arguments); + this.setTextList(message?.text); + }; + + nodeType.prototype.selectionChanged = function (forceValue = null) { + if (forceValue === null) { + forceValue = selectedIndexes(this.container); + } else { + const idxs = forceValue.split(",").map(str => parseInt(str, 10)); + const lineCount = this.container.childElementCount; + for (let index = 0; index < lineCount; index++) { + const div = this.container.children[index]; + if (idxs.includes(index)) { + selectItem(div); + } else { + deselectItem(div); + } + } + } + this.properties.selected_indexes = forceValue; + const text = selectedText(this.container); + this.selectedTextWidget.value = text; + + // const firstLine = text.split('\n')[0]; + // const stem = firstLine.substring( + // Math.max(firstLine.lastIndexOf("/"), firstLine.lastIndexOf("\\")) + 1, + // firstLine.lastIndexOf(".")); + // this.stemTextWidget.value = stem || firstLine; + } + + nodeType.prototype.textListChanged = function () { + if (!this.container) { + return; + } + + const text = this.textListWidget.value; + const texts = text.split('\n'); + let lineCount = texts.length; + let dictMode = false; + + if (lineCount > 1 && texts[0].toUpperCase().startsWith("#DICT")) { + texts.shift(); + lineCount--; + dictMode = true; + } + + + const needs = lineCount - this.container.childElementCount; + if (needs > 0){ + for (let index = 0; index < needs; index++) { + addListItem(this.container); + } + } else if (needs < 0) { + for (let index = 0; index > needs; index--) { + this.container.lastElementChild.remove(); + } + } + + for (let index = 0; index < lineCount; index++) { + const div = this.container.children[index]; + let realText = texts[index]; + let label = texts[index]; + if (dictMode) { + const items = texts[index].split(':'); + if (items.length > 1) { + label = items.shift().trim(); + realText = items.join(':').trim(); + } + } + + setItemData(div, label, realText); + deselectItem(div); + } + + this.properties.selected_indexes = ""; + this.selectedTextWidget.value = ""; + // this.stemTextWidget.value = ""; + this.setDirtyCanvas(true); + }; + + nodeType.prototype.setTextList = function (texts) { + var text = ''; + if (typeof texts === 'string') { + text = texts; + } else { + for (let i = 0; i < texts.length; i++) { + text += texts[i]; + } + } + if (this.textListWidget) { + if (this.textListWidget.value != text) { + this.textListWidget.value = text; + } + } + }; + + nodeType.prototype.listLoraFiles = function () { + async function fetchCheckpoints() { + try { + const response = await api.fetchApi("/models/loras"); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error("Failed to retrieve the model:", error); + } + } + + fetchCheckpoints().then((value) => { + this.setTextList(value?.join?.("\n")); + }); + }; + + + nodeType.prototype.onSerialize = function (info) { + info.properties = { + source_text: this.textListWidget.value || "", + selected_indexes: this.properties.selected_indexes || "" + }; + //info.widgets_values = [""]; + }; + + nodeType.prototype.onConfigure = function (info) { + this.properties = this.properties || {}; + + if (info.properties) { + this.textListWidget.value = info.properties.source_text || ""; //call textListChanged() + this.properties.selected_indexes = info.properties.selected_indexes || ""; + } + this.selectionChanged(this.properties.selected_indexes); + }; + } + }, +}); + + diff --git a/single_line_picker.py b/single_line_picker.py new file mode 100644 index 0000000..a0f32be --- /dev/null +++ b/single_line_picker.py @@ -0,0 +1,35 @@ + +class SLPSingleLinePicker: + + NAME = "HetimaSingleLinePicker" + DISPLAY_NAME = "Single Line Picker" + + CATEGORY = "SingleLinePicker" + DESCRIPTION = "Select one line from the text list with a single click." + + @classmethod + def INPUT_TYPES(cls): + return { + "optional": { + "text": ("STRING", {"multiline": True, "default": "", "forceInput": True, "tooltip": "text content for list"}), + }, + "hidden": { + "source_text": ("STRING", {}), + "selected_text": ("STRING", {}), + # "stem": ("STRING", {}), + }, + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("STRING",) + OUTPUT_TOOLTIPS = ("text content of selected line",) + OUTPUT_NODE = True + FUNCTION = "executed" + + def executed(self, text=None, source_text=None, selected_text=None, **kwargs): + if not text: + return {"ui": { "text": source_text }, "result": (selected_text,)} + if text == source_text: + return {"ui": { "text": source_text }, "result": (selected_text,)} + + return {"ui": { "text": text }, "result": ()} diff --git a/slp_lora_loader.py b/slp_lora_loader.py new file mode 100644 index 0000000..d4e4790 --- /dev/null +++ b/slp_lora_loader.py @@ -0,0 +1,78 @@ + +import folder_paths +import comfy.sd +import comfy.utils +from pathlib import Path + +class SLPLoraLoader: + + NAME = "HetimaSLPLoraLoader" + DISPLAY_NAME = "SLP Lora Loader" + CATEGORY = "SingleLinePicker" + + def __init__(self): + self.loaded_lora = None + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "model": ("MODEL", {"tooltip": "The diffusion model the LoRA will be applied to."}), + "clip": ("CLIP", {"tooltip": "The CLIP model the LoRA will be applied to."}), + "lora_name_text": ("STRING", {"tooltip": "The name of the LoRA."}), + "strength_model": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01, "tooltip": "How strongly to modify the diffusion model. This value can be negative."}), + "strength_clip": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01, "tooltip": "How strongly to modify the CLIP model. This value can be negative."}), + } + } + + RETURN_TYPES = ("MODEL", "CLIP", "STRING") + RETURN_NAMES = ("MODEL", "CLIP", "stem") + OUTPUT_TOOLTIPS = ("The modified diffusion model.", "The modified CLIP model.", "The stem of lora file") + FUNCTION = "load_lora" + + DESCRIPTION = "LoRAs are used to modify diffusion and CLIP models, altering the way in which latents are denoised such as applying styles. Multiple LoRA nodes can be linked together." + + def load_lora(self, model, clip, lora_name_text, strength_model, strength_clip): + if not lora_name_text: + return (model, clip, "") + if strength_model == 0 and strength_clip == 0: + return (model, clip, "") + + + lora_path = folder_paths.get_full_path_or_raise("loras", lora_name_text.splitlines()[0]) + lora = None + if self.loaded_lora is not None: + if self.loaded_lora[0] == lora_path: + lora = self.loaded_lora[1] + else: + self.loaded_lora = None + + if lora is None: + lora = comfy.utils.load_torch_file(lora_path, safe_load=True) + self.loaded_lora = (lora_path, lora) + + model_lora, clip_lora = comfy.sd.load_lora_for_models(model, clip, lora, strength_model, strength_clip) + return (model_lora, clip_lora, Path(lora_path).stem) + +class SLPLoraLoaderModelOnly(SLPLoraLoader): + + NAME = "HetimaSLPLoraLoaderModelOnly" + DISPLAY_NAME = "SLP Lora Loader (Model Only)" + + CATEGORY = "SingleLinePicker" + + @classmethod + def INPUT_TYPES(cls): + return {"required": { "model": ("MODEL",), + "lora_name_text": ("STRING",), + "strength_model": ("FLOAT", {"default": 1.0, "min": -100.0, "max": 100.0, "step": 0.01}), + }} + RETURN_TYPES = ("MODEL", "stem") + RETURN_NAMES = ("MODEL", "stem") + OUTPUT_TOOLTIPS = ("The modified diffusion model.", "The stem of lora file") + + FUNCTION = "load_lora_model_only" + + def load_lora_model_only(self, model, lora_name_text, strength_model): + result = self.load_lora(model, None, lora_name_text, strength_model, 0) + return (result[0], result[2])