├── .gitignore ├── BatWarning.webp ├── LICENSE.txt ├── LatentCoupleHelper.bat ├── LatentCoupleHelper.ps1 ├── LatentCoupleHelper.webp ├── LatentCoupleHelperUp.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /LatentCoupleHelper.json 2 | 3 | -------------------------------------------------------------------------------- /BatWarning.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zuntan03/LatentCoupleHelper/246b89b6555ad853d3a619756f6635431a989627/BatWarning.webp -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Zuntan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LatentCoupleHelper.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | PowerShell -Version 5.1 -ExecutionPolicy Bypass -File "%~dp0LatentCoupleHelper.ps1" 3 | -------------------------------------------------------------------------------- /LatentCoupleHelper.ps1: -------------------------------------------------------------------------------- 1 | Add-Type -AssemblyName System.Windows.Forms; 2 | 3 | $config = [ordered]@{ 4 | location = $null; 5 | size = "320, 496"; 6 | divX = 8; 7 | divY = 12; 8 | maxDivX = 32; 9 | maxDivY = 32; 10 | posX0 = 0; 11 | posX1 = 0; 12 | posY0 = 0; 13 | posY1 = 0; 14 | formOpacity = 0.5; 15 | transColor = "#777777"; 16 | }; 17 | 18 | $configPath = [System.IO.Path]::ChangeExtension($PSCommandPath, ".json"); 19 | function SaveConfig() { 20 | $json = ConvertTo-Json $config; 21 | Set-Content -Path $configPath -Value $json -Encoding UTF8; 22 | } 23 | 24 | if ([System.IO.File]::Exists($configPath)) { 25 | $json = Get-Content -Path $configPath -Encoding UTF8 -Raw | ConvertFrom-Json; 26 | foreach ($prop in $json.PsObject.Properties) { $config[$prop.Name] = $prop.Value; } 27 | } 28 | SaveConfig; 29 | 30 | function GetConfig() { return $config; } 31 | 32 | function GetPadding($l, $t, $r, $b) { return [System.Windows.Forms.Padding]::new($l, $t, $r, $b); } 33 | 34 | function Activate() { 35 | $latentCoupleHelper.form.TransparencyKey = [System.Drawing.Color]::Empty; 36 | $latentCoupleHelper.isActive = $true; 37 | $latentCoupleHelper.canvas.Invalidate(); 38 | } 39 | function Deactivate() { 40 | $cfg = GetConfig; 41 | $latentCoupleHelper.form.TransparencyKey = $cfg.transColor; 42 | $latentCoupleHelper.isActive = $false; 43 | $latentCoupleHelper.canvas.Invalidate(); 44 | } 45 | 46 | class LatentCoupleHelper { 47 | $form; 48 | $canvas; 49 | $font; 50 | $divTextBox; 51 | $areaTextBox; 52 | 53 | $isActive = $false; 54 | $basePen; 55 | $activePen; 56 | 57 | $mDragX = -1; 58 | $mDragY = -1; 59 | 60 | [void] InitializeForm() { 61 | $cfg = GetConfig; 62 | $frm = New-Object System.Windows.Forms.Form; 63 | $frm.Text = "LatentCoupleHelper"; 64 | $frm.Topmost = $true; 65 | $frm.Opacity = $cfg.formOpacity; 66 | $frm.TransparencyKey = $cfg.transColor; 67 | $frm.Padding = GetPadding 8 0 8 0; 68 | $frm.ClientSize = $cfg.size; 69 | if ($null -ne $cfg.location) { 70 | $frm.StartPosition = "Manual"; 71 | $frm.Location = $cfg.location; 72 | } 73 | $frm.Tag = $this; 74 | $frm.add_ResizeEnd({ 75 | $cfg = GetConfig; 76 | $cfg.location = "$($this.Location.X), $($this.Location.Y)"; 77 | $cfg.size = "$($this.ClientSize.Width), $($this.ClientSize.Height)"; 78 | SaveConfig; 79 | $this.Tag.canvas.Invalidate(); 80 | }); 81 | $frm.add_Resize({ $this.Tag.canvas.Invalidate(); }); 82 | $frm.add_MouseEnter({ Deactivate; }); 83 | $frm.add_Deactivate({ Deactivate; }); 84 | $this.form = $frm; 85 | 86 | $cnvsPanel = New-Object System.Windows.Forms.Panel; 87 | $cnvsPanel.Dock = "Fill"; 88 | $cnvsPanel.Padding = GetPadding 16 4 16 0; #36; 89 | $cnvsPanel.add_MouseEnter({ Activate; }); 90 | $frm.Controls.Add($cnvsPanel); 91 | 92 | $cnvs = New-Object System.Windows.Forms.PictureBox; 93 | $this.canvas = $cnvs; 94 | $cnvs.BackColor = $cfg.transColor; 95 | $cnvs.Dock = "Fill"; 96 | $cnvs.Tag = $this; 97 | $cnvs.add_MouseEnter({ Activate; }); 98 | $cnvs.add_MouseLeave({ Deactivate; }); 99 | $cnvs.Add_Paint({ $this.Tag.RepaintCanvas($_, $this.Tag.canvas); }); 100 | $cnvs.add_MouseDown({ $this.Tag.MouseEvent($_, $this.Tag.canvas); }); 101 | $cnvs.add_MouseMove({ $this.Tag.MouseEvent($_, $this.Tag.canvas); }); 102 | $cnvsPanel.Controls.Add($cnvs); 103 | 104 | $pnl = New-Object System.Windows.Forms.Panel; 105 | $pnl.Dock = "Top"; 106 | $pnl.Height = 32; 107 | $pnl.Tag = $frm; 108 | $pnl.add_MouseEnter({ Deactivate; }); 109 | $frm.Controls.Add($pnl); 110 | 111 | $pnlPosX = 0; 112 | $pnlPosY = 0; 113 | $btnWidth = 28; 114 | $btnHeight = 28; 115 | 116 | $btnDivYUp = New-Object System.Windows.Forms.Button; 117 | $btnDivYUp.Size = "$btnWidth, $btnHeight"; 118 | $btnDivYUp.Location = "$pnlPosX, $pnlPosY"; 119 | $pnlPosX += $btnWidth; 120 | $btnDivYUp.Text = "═"; 121 | $btnDivYUp.Tag = $this; 122 | $btnDivYUp.add_Click({ 123 | $cfg = GetConfig; 124 | if ($cfg.divY -lt $cfg.maxDivY) { $cfg.divY++; SaveConfig; $this.Tag.SetDivText(); } 125 | }); 126 | $pnl.Controls.Add($btnDivYUp); 127 | 128 | $btnDivYDown = New-Object System.Windows.Forms.Button; 129 | $btnDivYDown.Size = "$btnWidth, $btnHeight"; 130 | $btnDivYDown.Location = "$pnlPosX, $pnlPosY"; 131 | $pnlPosX += $btnWidth; 132 | $btnDivYDown.Text = "─"; 133 | $btnDivYDown.Tag = $this; 134 | $btnDivYDown.add_Click({ 135 | $cfg = GetConfig; 136 | if ($cfg.divY -gt 1) { $cfg.divY--; SaveConfig; $this.Tag.SetDivText(); } 137 | }); 138 | $pnl.Controls.Add($btnDivYDown); 139 | 140 | $tbxDiv = New-Object System.Windows.Forms.TextBox; 141 | $this.divTextBox = $tbxDiv; 142 | $this.font = New-Object System.Drawing.Font($tbxDiv.Font.Name, 14.0); 143 | $this.SetDivText(); 144 | $tbxDiv.Font = $this.font; 145 | $tbxDiv.Width = 52; 146 | $tbxDiv.Location = "$pnlPosX, $($pnlPosY + 2)"; 147 | $pnlPosX += 52; 148 | $tbxDiv.Readonly = $true; 149 | $tbxDiv.add_Click({ $this.SelectAll(); $this.Copy(); }); 150 | $pnl.Controls.Add($tbxDiv); 151 | 152 | $btnDivXUp = New-Object System.Windows.Forms.Button; 153 | $btnDivXUp.Size = "$btnWidth, $btnHeight"; 154 | $btnDivXUp.Location = "$pnlPosX, $pnlPosY"; 155 | $pnlPosX += $btnWidth; 156 | $btnDivXUp.Text = "║"; 157 | $btnDivXUp.Tag = $this; 158 | $btnDivXUp.add_Click({ 159 | $cfg = GetConfig; 160 | if ($cfg.divX -lt $cfg.maxDivX) { $cfg.divX++; SaveConfig; $this.Tag.SetDivText(); } 161 | }); 162 | $pnl.Controls.Add($btnDivXUp); 163 | 164 | $btnDivXDown = New-Object System.Windows.Forms.Button; 165 | $btnDivXDown.Size = "$btnWidth, $btnHeight"; 166 | $btnDivXDown.Location = "$pnlPosX, $pnlPosY"; 167 | $pnlPosX += $btnWidth + 8; 168 | $btnDivXDown.Text = "│"; 169 | $btnDivXDown.Tag = $this; 170 | $btnDivXDown.add_Click({ 171 | $cfg = GetConfig; 172 | if ($cfg.divX -gt 1) { $cfg.divX--; SaveConfig; $this.Tag.SetDivText(); } 173 | }); $pnl.Controls.Add($btnDivXDown); 174 | 175 | $tbxArea = New-Object System.Windows.Forms.TextBox; 176 | $this.areaTextBox = $tbxArea; 177 | $this.SetAreaText(); 178 | $tbxArea.Font = $this.font; 179 | $tbxArea.Width = 120; 180 | $tbxArea.Location = "$pnlPosX, $($pnlPosY + 2)"; 181 | $tbxArea.Readonly = $true; 182 | $tbxArea.add_Click({ $this.SelectAll(); $this.Copy(); }); 183 | $pnl.Controls.Add($tbxArea); 184 | 185 | $this.basePen = New-Object System.Drawing.Pen("#000000", 1.0); 186 | $this.activePen = New-Object System.Drawing.Pen("#FFFFFF", 1.0); 187 | 188 | } 189 | 190 | [void] SetDivText() { 191 | $cfg = GetConfig; 192 | $this.divTextBox.Text = "$($cfg.divY):$($cfg.divX)"; 193 | $this.canvas.Invalidate(); 194 | } 195 | 196 | [void] SetAreaText() { 197 | $cfg = GetConfig; 198 | $txt = "$($cfg.posY0)"; 199 | if ($cfg.posY0 -ne $cfg.posY1) { $txt += "-$($cfg.posY1)"; } 200 | $txt += ":$($cfg.posX0)"; 201 | if ($cfg.posX0 -ne $cfg.posX1) { $txt += "-$($cfg.posX1)"; } 202 | $this.areaTextBox.Text = $txt; 203 | $this.canvas.Invalidate(); 204 | } 205 | 206 | [void] RepaintCanvas($e, $canvas) { 207 | $cfg = GetConfig; 208 | $gfx = $e.Graphics; 209 | $pad = 8; 210 | $cWidth = $canvas.Width - $pad * 2; 211 | $cHeight = $canvas.Height - $pad * 2; 212 | 213 | if ($this.isActive) { 214 | $gfx.DrawRectangle($this.basePen, $pad, $pad, $cWidth, $cHeight); 215 | 216 | $xSpan = $cWidth / $cfg.divX; 217 | for ($x = 1; $x -le $cfg.divX; $x++) { 218 | $xPos = $pad + $xSpan * $x; 219 | $gfx.DrawLine($this.basePen, $xPos, $pad, $xPos, $pad + $cHeight); 220 | } 221 | 222 | $ySpan = $cHeight / $cfg.divY; 223 | for ($y = 1; $y -le $cfg.divY; $y++) { 224 | $yPos = $pad + $ySpan * $y; 225 | $gfx.DrawLine($this.basePen, $pad, $yPos, $pad + $cWidth, $yPos); 226 | } 227 | 228 | $subX = $cfg.posX1 - $cfg.posX0; 229 | if ($subX -le 0) { $subX = 1; } 230 | $subY = $cfg.posY1 - $cfg.posY0; 231 | if ($subY -le 0) { $subY = 1; } 232 | $gfx.DrawRectangle($this.activePen, 233 | $pad + $cfg.posX0 * $xSpan, $pad + $cfg.posY0 * $ySpan, 234 | $xSpan * $subX , $ySpan * $subY); 235 | } 236 | else { 237 | $gfx.DrawRectangle($this.activePen, $pad, $pad, $cWidth, $cHeight); 238 | } 239 | } 240 | 241 | [void] MouseEvent($e, $canvas) { 242 | if ($e.Button -ne "Left") { 243 | $this.mDragX = $this.mDragY = -1; 244 | return; 245 | } 246 | $clamp = { 247 | param([double] $value, [int] $maxValue) 248 | $val = [Math]::Truncate($value); 249 | if ($val -lt 0) { return 0; } 250 | if ($val -gt $maxValue) { return $maxValue; } 251 | return $val; 252 | } 253 | 254 | $cfg = GetConfig; 255 | $pad = 8; 256 | $cWidth = $canvas.Width - $pad * 2; 257 | $cHeight = $canvas.Height - $pad * 2; 258 | $xSpan = $cWidth / $cfg.divX; 259 | $ySpan = $cHeight / $cfg.divY; 260 | if ($this.mDragX -eq -1) { 261 | $this.mDragX = $e.X; 262 | $this.mDragY = $e.Y; 263 | $cfg.posX0 = $cfg.posX1 = &$clamp (($e.X - $pad) / $xSpan) ($cfg.divX - 1); 264 | $cfg.posY0 = $cfg.posY1 = &$clamp (($e.Y - $pad) / $ySpan) ($cfg.divY - 1); 265 | Write-Host "$($e.X - $pad) $xSpan $($cfg.posX0) $([int]1.3) $([int]1.8)" 266 | } 267 | else { 268 | if ($e.X -lt $this.mDragX) { 269 | $cfg.posX0 = &$clamp (($e.X - $pad) / $xSpan) ($cfg.divX - 1); 270 | $cfg.posX1 = &$clamp (($this.mDragX - $pad) / $xSpan + 1) $cfg.divX; 271 | } 272 | else { 273 | $cfg.posX0 = &$clamp (($this.mDragX - $pad) / $xSpan) ($cfg.divX - 1); 274 | $cfg.posX1 = &$clamp (($e.X - $pad) / $xSpan + 1) $cfg.divX; 275 | } 276 | if ($cfg.posX1 - $cfg.posX0 -eq 1) { $cfg.posX1 = $cfg.posX0; } 277 | 278 | if ($e.Y -lt $this.mDragY) { 279 | $cfg.posY0 = &$clamp (($e.Y - $pad) / $ySpan) ($cfg.divY - 1); 280 | $cfg.posY1 = &$clamp (($this.mDragY - $pad) / $ySpan + 1) $cfg.divY; 281 | } 282 | else { 283 | $cfg.posY0 = &$clamp (($this.mDragY - $pad) / $ySpan) ($cfg.divY - 1); 284 | $cfg.posY1 = &$clamp (($e.Y - $pad) / $ySpan + 1) $cfg.divY; 285 | } 286 | if ($cfg.posY1 - $cfg.posY0 -eq 1) { $cfg.posY1 = $cfg.posY0; } 287 | } 288 | SaveConfig; 289 | $this.SetAreaText(); 290 | } 291 | } 292 | 293 | [System.Windows.Forms.Application]::EnableVisualStyles(); 294 | $latentCoupleHelper = New-Object LatentCoupleHelper; 295 | $latentCoupleHelper.InitializeForm(); 296 | 297 | Add-Type -Name Window -Namespace Console -MemberDefinition ' 298 | [DllImport("Kernel32.dll")] public static extern IntPtr GetConsoleWindow(); 299 | [DllImport("user32.dll")] public static extern void ShowWindow(IntPtr hWnd, Int32 nCmdShow);' 300 | [Console.Window]::ShowWindow([Console.Window]::GetConsoleWindow(), 0); 301 | 302 | [System.Windows.Forms.Application]::Run($latentCoupleHelper.form); 303 | $latentCoupleHelper.form.Dispose(); 304 | -------------------------------------------------------------------------------- /LatentCoupleHelper.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zuntan03/LatentCoupleHelper/246b89b6555ad853d3a619756f6635431a989627/LatentCoupleHelper.webp -------------------------------------------------------------------------------- /LatentCoupleHelperUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Zuntan03/LatentCoupleHelper/246b89b6555ad853d3a619756f6635431a989627/LatentCoupleHelperUp.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LatentCoupleHelper README 2 | 3 | This tool is language-independent. Please translate this page in your browser. 4 | 5 | Stable Diffusion web UI の Latent Couple 拡張で、好きな位置にプロンプトを置くためのツールです。 6 | スクリプトなので中身が見えて、安心です。 7 | 8 | ---- 9 | 「画面を分割しているようじゃダメだな」
10 | 「ん?そー思わんか?」 11 | 12 | 「プロンプトを!」
13 | 「置いてくる!!!」 14 | 15 | ![LatentCoupleHelper](LatentCoupleHelper.webp) 16 | 17 | ---- 18 | 19 | ## 使い方 20 | 21 | Windows で LatentCoupleHelper.bat と LatentCoupleHelper.ps1 があれば動作します。 22 | 23 | - LatentCoupleHelper.bat をダブルクリックすると LatentCoupleHelper が立ち上がります。 24 | - 初回起動時に警告が表示された場合は「詳細情報」>「実行」します。
![BatWarning](BatWarning.webp) 25 | - 参考にしたい画像のサイズに合うように、ウィンドウを移動してリサイズします。
![LatentCoupleHelperUp](LatentCoupleHelperUp.png) 26 | - 「═」「─」ボタンで縦の分割数を、「║」「│」ボタンで横の分割数を増減できます。 27 | - ボタンの間にある縦横分割数のテキストボックスをクリックすると、分割数を自動でクリップボードにコピーします。 28 | - 分割数を Latent Couple の「Divisions」に貼り付けます。 29 | - 真ん中のエリアを左ドラッグすると、領域を選択できます。 30 | - 右上のテキストボックスをクリックすると、選択した領域を自動でクリップボードにコピーします。 31 | - 選択した領域を Latent Couple の「Positions」に貼り付けます。 32 | - Latent Couple の「Weight」を追加し、AND でプロンプトを追記すると、選択した領域に AND のプロンプトを置いた絵を生成できます。 33 | - 上の画像を参考にしてください。 34 | 35 | ## 他のツール 36 | 37 | - [GenImageViewer](https://github.com/Zuntan03/GenImageViewer) 38 | - Stable Diffusion web UI が生成した画像を、自動で大きく表示するツールです。タイトル画像右側の表示が、画像の生成に合わせて自動で更新されます。 39 | - [MaiNovel](https://github.com/Zuntan03/MaiNovel) 40 | - AI で生成した音声と画像で、ビジュアルノベルを作るツールです。 41 | 42 | ## ライセンス 43 | 44 | [MIT License](./LICENSE.txt) です。 45 | 46 | This software is released under the MIT License, see [LICENSE.txt](./LICENSE.txt). 47 | --------------------------------------------------------------------------------