renajon commited on
Commit
8df5cf7
1 Parent(s): 25495be

Upload 18 files

Browse files
Files changed (18) hide show
  1. .gitignore +33 -0
  2. .pylintrc +3 -0
  3. CODEOWNERS +13 -0
  4. README.md +165 -6
  5. artists.csv +0 -0
  6. environment-wsl2.yaml +11 -0
  7. launch.py +228 -0
  8. requirements.txt +29 -0
  9. requirements_versions.txt +26 -0
  10. screenshot.png +0 -0
  11. script.js +85 -0
  12. style.css +633 -0
  13. txt2img_Screenshot.png +0 -0
  14. webui-user.bat +8 -0
  15. webui-user.sh +43 -0
  16. webui.bat +62 -0
  17. webui.py +162 -0
  18. webui.sh +140 -0
.gitignore ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__
2
+ *.ckpt
3
+ *.pth
4
+ /ESRGAN/*
5
+ /SwinIR/*
6
+ /repositories
7
+ /venv
8
+ /tmp
9
+ /model.ckpt
10
+ /models/**/*
11
+ /GFPGANv1.3.pth
12
+ /gfpgan/weights/*.pth
13
+ /ui-config.json
14
+ /outputs
15
+ /config.json
16
+ /log
17
+ /webui.settings.bat
18
+ /embeddings
19
+ /styles.csv
20
+ /params.txt
21
+ /styles.csv.bak
22
+ /webui-user.bat
23
+ /webui-user.sh
24
+ /interrogate
25
+ /user.css
26
+ /.idea
27
+ notification.mp3
28
+ /SwinIR
29
+ /textual_inversion
30
+ .vscode
31
+ /extensions
32
+ /test/stdout.txt
33
+ /test/stderr.txt
.pylintrc ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ # See https://pylint.pycqa.org/en/latest/user_guide/messages/message_control.html
2
+ [MESSAGES CONTROL]
3
+ disable=C,R,W,E,I
CODEOWNERS ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * @AUTOMATIC1111
2
+ /localizations/ar_AR.json @xmodar @blackneoo
3
+ /localizations/de_DE.json @LunixWasTaken
4
+ /localizations/es_ES.json @innovaciones
5
+ /localizations/fr_FR.json @tumbly
6
+ /localizations/it_IT.json @EugenioBuffo
7
+ /localizations/ja_JP.json @yuuki76
8
+ /localizations/ko_KR.json @36DB
9
+ /localizations/pt_BR.json @M-art-ucci
10
+ /localizations/ru_RU.json @kabachuha
11
+ /localizations/tr_TR.json @camenduru
12
+ /localizations/zh_CN.json @dtlnor @bgluminous
13
+ /localizations/zh_TW.json @benlisquare
README.md CHANGED
@@ -1,9 +1,168 @@
1
- Hentai Diffusion
 
2
 
3
- !!!! IMPORTANT !!!!
4
- dfgfdg
5
 
6
- Updates will be posted every few weeks. The current focus is on hands and better poses like crouching and laying/sitting down.
7
- Feature suggestions are welcome.
8
 
9
- https://huggingface.co/Deltaadams/Hentai-Diffusion/tree/main
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Stable Diffusion web UI
2
+ A browser interface based on Gradio library for Stable Diffusion.
3
 
4
+ ![](txt2img_Screenshot.png)
 
5
 
6
+ Check the [custom scripts](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Scripts) wiki page for extra scripts developed by users.
 
7
 
8
+ ## Features
9
+ [Detailed feature showcase with images](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features):
10
+ - Original txt2img and img2img modes
11
+ - One click install and run script (but you still must install python and git)
12
+ - Outpainting
13
+ - Inpainting
14
+ - Color Sketch
15
+ - Prompt Matrix
16
+ - Stable Diffusion Upscale
17
+ - Attention, specify parts of text that the model should pay more attention to
18
+ - a man in a ((tuxedo)) - will pay more attention to tuxedo
19
+ - a man in a (tuxedo:1.21) - alternative syntax
20
+ - select text and press ctrl+up or ctrl+down to automatically adjust attention to selected text (code contributed by anonymous user)
21
+ - Loopback, run img2img processing multiple times
22
+ - X/Y plot, a way to draw a 2 dimensional plot of images with different parameters
23
+ - Textual Inversion
24
+ - have as many embeddings as you want and use any names you like for them
25
+ - use multiple embeddings with different numbers of vectors per token
26
+ - works with half precision floating point numbers
27
+ - train embeddings on 8GB (also reports of 6GB working)
28
+ - Extras tab with:
29
+ - GFPGAN, neural network that fixes faces
30
+ - CodeFormer, face restoration tool as an alternative to GFPGAN
31
+ - RealESRGAN, neural network upscaler
32
+ - ESRGAN, neural network upscaler with a lot of third party models
33
+ - SwinIR and Swin2SR([see here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2092)), neural network upscalers
34
+ - LDSR, Latent diffusion super resolution upscaling
35
+ - Resizing aspect ratio options
36
+ - Sampling method selection
37
+ - Adjust sampler eta values (noise multiplier)
38
+ - More advanced noise setting options
39
+ - Interrupt processing at any time
40
+ - 4GB video card support (also reports of 2GB working)
41
+ - Correct seeds for batches
42
+ - Live prompt token length validation
43
+ - Generation parameters
44
+ - parameters you used to generate images are saved with that image
45
+ - in PNG chunks for PNG, in EXIF for JPEG
46
+ - can drag the image to PNG info tab to restore generation parameters and automatically copy them into UI
47
+ - can be disabled in settings
48
+ - drag and drop an image/text-parameters to promptbox
49
+ - Read Generation Parameters Button, loads parameters in promptbox to UI
50
+ - Settings page
51
+ - Running arbitrary python code from UI (must run with --allow-code to enable)
52
+ - Mouseover hints for most UI elements
53
+ - Possible to change defaults/mix/max/step values for UI elements via text config
54
+ - Random artist button
55
+ - Tiling support, a checkbox to create images that can be tiled like textures
56
+ - Progress bar and live image generation preview
57
+ - Negative prompt, an extra text field that allows you to list what you don't want to see in generated image
58
+ - Styles, a way to save part of prompt and easily apply them via dropdown later
59
+ - Variations, a way to generate same image but with tiny differences
60
+ - Seed resizing, a way to generate same image but at slightly different resolution
61
+ - CLIP interrogator, a button that tries to guess prompt from an image
62
+ - Prompt Editing, a way to change prompt mid-generation, say to start making a watermelon and switch to anime girl midway
63
+ - Batch Processing, process a group of files using img2img
64
+ - Img2img Alternative, reverse Euler method of cross attention control
65
+ - Highres Fix, a convenience option to produce high resolution pictures in one click without usual distortions
66
+ - Reloading checkpoints on the fly
67
+ - Checkpoint Merger, a tab that allows you to merge up to 3 checkpoints into one
68
+ - [Custom scripts](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Scripts) with many extensions from community
69
+ - [Composable-Diffusion](https://energy-based-model.github.io/Compositional-Visual-Generation-with-Composable-Diffusion-Models/), a way to use multiple prompts at once
70
+ - separate prompts using uppercase `AND`
71
+ - also supports weights for prompts: `a cat :1.2 AND a dog AND a penguin :2.2`
72
+ - No token limit for prompts (original stable diffusion lets you use up to 75 tokens)
73
+ - DeepDanbooru integration, creates danbooru style tags for anime prompts (add --deepdanbooru to commandline args)
74
+ - [xformers](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers), major speed increase for select cards: (add --xformers to commandline args)
75
+ - via extension: [History tab](https://github.com/yfszzx/stable-diffusion-webui-images-browser): view, direct and delete images conveniently within the UI
76
+ - Generate forever option
77
+ - Training tab
78
+ - hypernetworks and embeddings options
79
+ - Preprocessing images: cropping, mirroring, autotagging using BLIP or deepdanbooru (for anime)
80
+ - Clip skip
81
+ - Use Hypernetworks
82
+ - Use VAEs
83
+ - Estimated completion time in progress bar
84
+ - API
85
+ - Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML.
86
+ - via extension: [Aesthetic Gradients](https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients), a way to generate images with a specific aesthetic by using clip images embds (implementation of [https://github.com/vicgalle/stable-diffusion-aesthetic-gradients](https://github.com/vicgalle/stable-diffusion-aesthetic-gradients))
87
+
88
+ ## Where are Aesthetic Gradients?!?!
89
+ Aesthetic Gradients are now an extension. You can install it using git:
90
+
91
+ ```commandline
92
+ git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients extensions/aesthetic-gradients
93
+ ```
94
+
95
+ After running this command, make sure that you have `aesthetic-gradients` dir in webui's `extensions` directory and restart
96
+ the UI. The interface for Aesthetic Gradients should appear exactly the same as it was.
97
+
98
+ ## Where is History/Image browser?!?!
99
+ Image browser is now an extension. You can install it using git:
100
+
101
+ ```commandline
102
+ git clone https://github.com/yfszzx/stable-diffusion-webui-images-browser extensions/images-browser
103
+ ```
104
+
105
+ After running this command, make sure that you have `images-browser` dir in webui's `extensions` directory and restart
106
+ the UI. The interface for Image browser should appear exactly the same as it was.
107
+
108
+ ## Installation and Running
109
+ Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs.
110
+
111
+ Alternatively, use online services (like Google Colab):
112
+
113
+ - [List of Online Services](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Online-Services)
114
+
115
+ ### Automatic Installation on Windows
116
+ 1. Install [Python 3.10.6](https://www.python.org/downloads/windows/), checking "Add Python to PATH"
117
+ 2. Install [git](https://git-scm.com/download/win).
118
+ 3. Download the stable-diffusion-webui repository, for example by running `git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git`.
119
+ 4. Place `model.ckpt` in the `models` directory (see [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) for where to get it).
120
+ 5. _*(Optional)*_ Place `GFPGANv1.4.pth` in the base directory, alongside `webui.py` (see [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) for where to get it).
121
+ 6. Run `webui-user.bat` from Windows Explorer as normal, non-administrator, user.
122
+
123
+ ### Automatic Installation on Linux
124
+ 1. Install the dependencies:
125
+ ```bash
126
+ # Debian-based:
127
+ sudo apt install wget git python3 python3-venv
128
+ # Red Hat-based:
129
+ sudo dnf install wget git python3
130
+ # Arch-based:
131
+ sudo pacman -S wget git python3
132
+ ```
133
+ 2. To install in `/home/$(whoami)/stable-diffusion-webui/`, run:
134
+ ```bash
135
+ bash <(wget -qO- https://raw.githubusercontent.com/AUTOMATIC1111/stable-diffusion-webui/master/webui.sh)
136
+ ```
137
+
138
+ ### Installation on Apple Silicon
139
+
140
+ Find the instructions [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Installation-on-Apple-Silicon).
141
+
142
+ ## Contributing
143
+ Here's how to add code to this repo: [Contributing](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing)
144
+
145
+ ## Documentation
146
+ The documentation was moved from this README over to the project's [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki).
147
+
148
+ ## Credits
149
+ - Stable Diffusion - https://github.com/CompVis/stable-diffusion, https://github.com/CompVis/taming-transformers
150
+ - k-diffusion - https://github.com/crowsonkb/k-diffusion.git
151
+ - GFPGAN - https://github.com/TencentARC/GFPGAN.git
152
+ - CodeFormer - https://github.com/sczhou/CodeFormer
153
+ - ESRGAN - https://github.com/xinntao/ESRGAN
154
+ - SwinIR - https://github.com/JingyunLiang/SwinIR
155
+ - Swin2SR - https://github.com/mv-lab/swin2sr
156
+ - LDSR - https://github.com/Hafiidz/latent-diffusion
157
+ - Ideas for optimizations - https://github.com/basujindal/stable-diffusion
158
+ - Doggettx - Cross Attention layer optimization - https://github.com/Doggettx/stable-diffusion, original idea for prompt editing.
159
+ - InvokeAI, lstein - Cross Attention layer optimization - https://github.com/invoke-ai/InvokeAI (originally http://github.com/lstein/stable-diffusion)
160
+ - Rinon Gal - Textual Inversion - https://github.com/rinongal/textual_inversion (we're not using his code, but we are using his ideas).
161
+ - Idea for SD upscale - https://github.com/jquesnelle/txt2imghd
162
+ - Noise generation for outpainting mk2 - https://github.com/parlance-zz/g-diffuser-bot
163
+ - CLIP interrogator idea and borrowing some code - https://github.com/pharmapsychotic/clip-interrogator
164
+ - Idea for Composable Diffusion - https://github.com/energy-based-model/Compositional-Visual-Generation-with-Composable-Diffusion-Models-PyTorch
165
+ - xformers - https://github.com/facebookresearch/xformers
166
+ - DeepDanbooru - interrogator for anime diffusers https://github.com/KichangKim/DeepDanbooru
167
+ - Initial Gradio script - posted on 4chan by an Anonymous user. Thank you Anonymous user.
168
+ - (You)
artists.csv ADDED
The diff for this file is too large to render. See raw diff
 
environment-wsl2.yaml ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: automatic
2
+ channels:
3
+ - pytorch
4
+ - defaults
5
+ dependencies:
6
+ - python=3.10
7
+ - pip=22.2.2
8
+ - cudatoolkit=11.3
9
+ - pytorch=1.12.1
10
+ - torchvision=0.13.1
11
+ - numpy=1.23.1
launch.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # this scripts installs necessary requirements and launches main program in webui.py
2
+ import subprocess
3
+ import os
4
+ import sys
5
+ import importlib.util
6
+ import shlex
7
+ import platform
8
+
9
+ dir_repos = "repositories"
10
+ python = sys.executable
11
+ git = os.environ.get('GIT', "git")
12
+ index_url = os.environ.get('INDEX_URL', "")
13
+
14
+
15
+ def extract_arg(args, name):
16
+ return [x for x in args if x != name], name in args
17
+
18
+
19
+ def run(command, desc=None, errdesc=None):
20
+ if desc is not None:
21
+ print(desc)
22
+
23
+ result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
24
+
25
+ if result.returncode != 0:
26
+
27
+ message = f"""{errdesc or 'Error running command'}.
28
+ Command: {command}
29
+ Error code: {result.returncode}
30
+ stdout: {result.stdout.decode(encoding="utf8", errors="ignore") if len(result.stdout)>0 else '<empty>'}
31
+ stderr: {result.stderr.decode(encoding="utf8", errors="ignore") if len(result.stderr)>0 else '<empty>'}
32
+ """
33
+ raise RuntimeError(message)
34
+
35
+ return result.stdout.decode(encoding="utf8", errors="ignore")
36
+
37
+
38
+ def check_run(command):
39
+ result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
40
+ return result.returncode == 0
41
+
42
+
43
+ def is_installed(package):
44
+ try:
45
+ spec = importlib.util.find_spec(package)
46
+ except ModuleNotFoundError:
47
+ return False
48
+
49
+ return spec is not None
50
+
51
+
52
+ def repo_dir(name):
53
+ return os.path.join(dir_repos, name)
54
+
55
+
56
+ def run_python(code, desc=None, errdesc=None):
57
+ return run(f'"{python}" -c "{code}"', desc, errdesc)
58
+
59
+
60
+ def run_pip(args, desc=None):
61
+ index_url_line = f' --index-url {index_url}' if index_url != '' else ''
62
+ return run(f'"{python}" -m pip {args} --prefer-binary{index_url_line}', desc=f"Installing {desc}", errdesc=f"Couldn't install {desc}")
63
+
64
+
65
+ def check_run_python(code):
66
+ return check_run(f'"{python}" -c "{code}"')
67
+
68
+
69
+ def git_clone(url, dir, name, commithash=None):
70
+ # TODO clone into temporary dir and move if successful
71
+
72
+ if os.path.exists(dir):
73
+ if commithash is None:
74
+ return
75
+
76
+ current_hash = run(f'"{git}" -C {dir} rev-parse HEAD', None, f"Couldn't determine {name}'s hash: {commithash}").strip()
77
+ if current_hash == commithash:
78
+ return
79
+
80
+ run(f'"{git}" -C {dir} fetch', f"Fetching updates for {name}...", f"Couldn't fetch {name}")
81
+ run(f'"{git}" -C {dir} checkout {commithash}', f"Checking out commit for {name} with hash: {commithash}...", f"Couldn't checkout commit {commithash} for {name}")
82
+ return
83
+
84
+ run(f'"{git}" clone "{url}" "{dir}"', f"Cloning {name} into {dir}...", f"Couldn't clone {name}")
85
+
86
+ if commithash is not None:
87
+ run(f'"{git}" -C {dir} checkout {commithash}', None, "Couldn't checkout {name}'s hash: {commithash}")
88
+
89
+
90
+ def version_check(commit):
91
+ try:
92
+ import requests
93
+ commits = requests.get('https://api.github.com/repos/AUTOMATIC1111/stable-diffusion-webui/branches/master').json()
94
+ if commit != "<none>" and commits['commit']['sha'] != commit:
95
+ print("--------------------------------------------------------")
96
+ print("| You are not up to date with the most recent release. |")
97
+ print("| Consider running `git pull` to update. |")
98
+ print("--------------------------------------------------------")
99
+ elif commits['commit']['sha'] == commit:
100
+ print("You are up to date with the most recent release.")
101
+ else:
102
+ print("Not a git clone, can't perform version check.")
103
+ except Exception as e:
104
+ print("versipm check failed",e)
105
+
106
+
107
+ def prepare_enviroment():
108
+ torch_command = os.environ.get('TORCH_COMMAND', "pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113")
109
+ requirements_file = os.environ.get('REQS_FILE', "requirements_versions.txt")
110
+ commandline_args = os.environ.get('COMMANDLINE_ARGS', "")
111
+
112
+ gfpgan_package = os.environ.get('GFPGAN_PACKAGE', "git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379")
113
+ clip_package = os.environ.get('CLIP_PACKAGE', "git+https://github.com/openai/CLIP.git@d50d76daa670286dd6cacf3bcd80b5e4823fc8e1")
114
+ deepdanbooru_package = os.environ.get('DEEPDANBOORU_PACKAGE', "git+https://github.com/KichangKim/DeepDanbooru.git@d91a2963bf87c6a770d74894667e9ffa9f6de7ff")
115
+
116
+ xformers_windows_package = os.environ.get('XFORMERS_WINDOWS_PACKAGE', 'https://github.com/C43H66N12O12S2/stable-diffusion-webui/releases/download/f/xformers-0.0.14.dev0-cp310-cp310-win_amd64.whl')
117
+
118
+ stable_diffusion_repo = os.environ.get('STABLE_DIFFUSION_REPO', "https://github.com/CompVis/stable-diffusion.git")
119
+ taming_transformers_repo = os.environ.get('TAMING_REANSFORMERS_REPO', "https://github.com/CompVis/taming-transformers.git")
120
+ k_diffusion_repo = os.environ.get('K_DIFFUSION_REPO', 'https://github.com/crowsonkb/k-diffusion.git')
121
+ codeformer_repo = os.environ.get('CODEFORMET_REPO', 'https://github.com/sczhou/CodeFormer.git')
122
+ blip_repo = os.environ.get('BLIP_REPO', 'https://github.com/salesforce/BLIP.git')
123
+
124
+ stable_diffusion_commit_hash = os.environ.get('STABLE_DIFFUSION_COMMIT_HASH', "69ae4b35e0a0f6ee1af8bb9a5d0016ccb27e36dc")
125
+ taming_transformers_commit_hash = os.environ.get('TAMING_TRANSFORMERS_COMMIT_HASH', "24268930bf1dce879235a7fddd0b2355b84d7ea6")
126
+ k_diffusion_commit_hash = os.environ.get('K_DIFFUSION_COMMIT_HASH', "f4e99857772fc3a126ba886aadf795a332774878")
127
+ codeformer_commit_hash = os.environ.get('CODEFORMER_COMMIT_HASH', "c5b4593074ba6214284d6acd5f1719b6c5d739af")
128
+ blip_commit_hash = os.environ.get('BLIP_COMMIT_HASH', "48211a1594f1321b00f14c9f7a5b4813144b2fb9")
129
+
130
+ sys.argv += shlex.split(commandline_args)
131
+ test_argv = [x for x in sys.argv if x != '--tests']
132
+
133
+ sys.argv, skip_torch_cuda_test = extract_arg(sys.argv, '--skip-torch-cuda-test')
134
+ sys.argv, reinstall_xformers = extract_arg(sys.argv, '--reinstall-xformers')
135
+ sys.argv, update_check = extract_arg(sys.argv, '--update-check')
136
+ sys.argv, run_tests = extract_arg(sys.argv, '--tests')
137
+ xformers = '--xformers' in sys.argv
138
+ deepdanbooru = '--deepdanbooru' in sys.argv
139
+ ngrok = '--ngrok' in sys.argv
140
+
141
+ try:
142
+ commit = run(f"{git} rev-parse HEAD").strip()
143
+ except Exception:
144
+ commit = "<none>"
145
+
146
+ print(f"Python {sys.version}")
147
+ print(f"Commit hash: {commit}")
148
+
149
+ if not is_installed("torch") or not is_installed("torchvision"):
150
+ run(f'"{python}" -m {torch_command}', "Installing torch and torchvision", "Couldn't install torch")
151
+
152
+ if not skip_torch_cuda_test:
153
+ run_python("import torch; assert torch.cuda.is_available(), 'Torch is not able to use GPU; add --skip-torch-cuda-test to COMMANDLINE_ARGS variable to disable this check'")
154
+
155
+ if not is_installed("gfpgan"):
156
+ run_pip(f"install {gfpgan_package}", "gfpgan")
157
+
158
+ if not is_installed("clip"):
159
+ run_pip(f"install {clip_package}", "clip")
160
+
161
+ if (not is_installed("xformers") or reinstall_xformers) and xformers:
162
+ if platform.system() == "Windows":
163
+ if platform.python_version().startswith("3.10"):
164
+ run_pip(f"install -U -I --no-deps {xformers_windows_package}", "xformers")
165
+ else:
166
+ print("Installation of xformers is not supported in this version of Python.")
167
+ print("You can also check this and build manually: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers#building-xformers-on-windows-by-duckness")
168
+ if not is_installed("xformers"):
169
+ exit(0)
170
+ elif platform.system() == "Linux":
171
+ run_pip("install xformers", "xformers")
172
+
173
+ if not is_installed("deepdanbooru") and deepdanbooru:
174
+ run_pip(f"install {deepdanbooru_package}#egg=deepdanbooru[tensorflow] tensorflow==2.10.0 tensorflow-io==0.27.0", "deepdanbooru")
175
+
176
+ if not is_installed("pyngrok") and ngrok:
177
+ run_pip("install pyngrok", "ngrok")
178
+
179
+ os.makedirs(dir_repos, exist_ok=True)
180
+
181
+ git_clone(stable_diffusion_repo, repo_dir('stable-diffusion'), "Stable Diffusion", stable_diffusion_commit_hash)
182
+ git_clone(taming_transformers_repo, repo_dir('taming-transformers'), "Taming Transformers", taming_transformers_commit_hash)
183
+ git_clone(k_diffusion_repo, repo_dir('k-diffusion'), "K-diffusion", k_diffusion_commit_hash)
184
+ git_clone(codeformer_repo, repo_dir('CodeFormer'), "CodeFormer", codeformer_commit_hash)
185
+ git_clone(blip_repo, repo_dir('BLIP'), "BLIP", blip_commit_hash)
186
+
187
+ if not is_installed("lpips"):
188
+ run_pip(f"install -r {os.path.join(repo_dir('CodeFormer'), 'requirements.txt')}", "requirements for CodeFormer")
189
+
190
+ run_pip(f"install -r {requirements_file}", "requirements for Web UI")
191
+
192
+ if update_check:
193
+ version_check(commit)
194
+
195
+ if "--exit" in sys.argv:
196
+ print("Exiting because of --exit argument")
197
+ exit(0)
198
+
199
+ if run_tests:
200
+ tests(test_argv)
201
+ exit(0)
202
+
203
+
204
+ def tests(argv):
205
+ if "--api" not in argv:
206
+ argv.append("--api")
207
+
208
+ print(f"Launching Web UI in another process for testing with arguments: {' '.join(argv[1:])}")
209
+
210
+ with open('test/stdout.txt', "w", encoding="utf8") as stdout, open('test/stderr.txt', "w", encoding="utf8") as stderr:
211
+ proc = subprocess.Popen([sys.executable, *argv], stdout=stdout, stderr=stderr)
212
+
213
+ import test.server_poll
214
+ test.server_poll.run_tests()
215
+
216
+ print(f"Stopping Web UI process with id {proc.pid}")
217
+ proc.kill()
218
+
219
+
220
+ def start_webui():
221
+ print(f"Launching Web UI with arguments: {' '.join(sys.argv[1:])}")
222
+ import webui
223
+ webui.webui()
224
+
225
+
226
+ if __name__ == "__main__":
227
+ prepare_enviroment()
228
+ start_webui()
requirements.txt ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ basicsr
2
+ diffusers
3
+ fairscale==0.4.4
4
+ fonts
5
+ font-roboto
6
+ gfpgan
7
+ gradio==3.5
8
+ invisible-watermark
9
+ numpy
10
+ omegaconf
11
+ opencv-python
12
+ requests
13
+ piexif
14
+ Pillow
15
+ pytorch_lightning
16
+ realesrgan
17
+ scikit-image>=0.19
18
+ timm==0.4.12
19
+ transformers==4.19.2
20
+ torch
21
+ einops
22
+ jsonmerge
23
+ clean-fid
24
+ resize-right
25
+ torchdiffeq
26
+ kornia
27
+ lark
28
+ inflection
29
+ GitPython
requirements_versions.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ transformers==4.19.2
2
+ diffusers==0.3.0
3
+ basicsr==1.4.2
4
+ gfpgan==1.3.8
5
+ gradio==3.5
6
+ numpy==1.23.3
7
+ Pillow==9.2.0
8
+ realesrgan==0.3.0
9
+ torch
10
+ omegaconf==2.2.3
11
+ pytorch_lightning==1.7.6
12
+ scikit-image==0.19.2
13
+ fonts
14
+ font-roboto
15
+ timm==0.6.7
16
+ fairscale==0.4.9
17
+ piexif==1.1.3
18
+ einops==0.4.1
19
+ jsonmerge==1.8.0
20
+ clean-fid==0.1.29
21
+ resize-right==0.0.2
22
+ torchdiffeq==0.2.3
23
+ kornia==0.6.7
24
+ lark==1.1.2
25
+ inflection==0.5.1
26
+ GitPython==3.1.27
screenshot.png ADDED
script.js ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ function gradioApp(){
2
+ return document.getElementsByTagName('gradio-app')[0].shadowRoot;
3
+ }
4
+
5
+ function get_uiCurrentTab() {
6
+ return gradioApp().querySelector('.tabs button:not(.border-transparent)')
7
+ }
8
+
9
+ function get_uiCurrentTabContent() {
10
+ return gradioApp().querySelector('.tabitem[id^=tab_]:not([style*="display: none"])')
11
+ }
12
+
13
+ uiUpdateCallbacks = []
14
+ uiTabChangeCallbacks = []
15
+ let uiCurrentTab = null
16
+
17
+ function onUiUpdate(callback){
18
+ uiUpdateCallbacks.push(callback)
19
+ }
20
+ function onUiTabChange(callback){
21
+ uiTabChangeCallbacks.push(callback)
22
+ }
23
+
24
+ function runCallback(x, m){
25
+ try {
26
+ x(m)
27
+ } catch (e) {
28
+ (console.error || console.log).call(console, e.message, e);
29
+ }
30
+ }
31
+ function executeCallbacks(queue, m) {
32
+ queue.forEach(function(x){runCallback(x, m)})
33
+ }
34
+
35
+ document.addEventListener("DOMContentLoaded", function() {
36
+ var mutationObserver = new MutationObserver(function(m){
37
+ executeCallbacks(uiUpdateCallbacks, m);
38
+ const newTab = get_uiCurrentTab();
39
+ if ( newTab && ( newTab !== uiCurrentTab ) ) {
40
+ uiCurrentTab = newTab;
41
+ executeCallbacks(uiTabChangeCallbacks);
42
+ }
43
+ });
44
+ mutationObserver.observe( gradioApp(), { childList:true, subtree:true })
45
+ });
46
+
47
+ /**
48
+ * Add a ctrl+enter as a shortcut to start a generation
49
+ */
50
+ document.addEventListener('keydown', function(e) {
51
+ var handled = false;
52
+ if (e.key !== undefined) {
53
+ if((e.key == "Enter" && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
54
+ } else if (e.keyCode !== undefined) {
55
+ if((e.keyCode == 13 && (e.metaKey || e.ctrlKey || e.altKey))) handled = true;
56
+ }
57
+ if (handled) {
58
+ button = get_uiCurrentTabContent().querySelector('button[id$=_generate]');
59
+ if (button) {
60
+ button.click();
61
+ }
62
+ e.preventDefault();
63
+ }
64
+ })
65
+
66
+ /**
67
+ * checks that a UI element is not in another hidden element or tab content
68
+ */
69
+ function uiElementIsVisible(el) {
70
+ let isVisible = !el.closest('.\\!hidden');
71
+ if ( ! isVisible ) {
72
+ return false;
73
+ }
74
+
75
+ while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) {
76
+ if ( ! isVisible ) {
77
+ return false;
78
+ } else if ( el.parentElement ) {
79
+ el = el.parentElement
80
+ } else {
81
+ break;
82
+ }
83
+ }
84
+ return isVisible;
85
+ }
style.css ADDED
@@ -0,0 +1,633 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .container {
2
+ max-width: 100%;
3
+ }
4
+
5
+ #txt2img_token_counter {
6
+ height: 0px;
7
+ }
8
+
9
+ #img2img_token_counter {
10
+ height: 0px;
11
+ }
12
+
13
+ #sh{
14
+ min-width: 2em;
15
+ min-height: 2em;
16
+ max-width: 2em;
17
+ max-height: 2em;
18
+ flex-grow: 0;
19
+ padding-left: 0.25em;
20
+ padding-right: 0.25em;
21
+ margin: 0.1em 0;
22
+ opacity: 0%;
23
+ cursor: default;
24
+ }
25
+
26
+ .output-html p {margin: 0 0.5em;}
27
+
28
+ .row > *,
29
+ .row > .gr-form > * {
30
+ min-width: min(120px, 100%);
31
+ flex: 1 1 0%;
32
+ }
33
+
34
+ .performance {
35
+ font-size: 0.85em;
36
+ color: #444;
37
+ }
38
+
39
+ .performance p{
40
+ display: inline-block;
41
+ }
42
+
43
+ .performance .time {
44
+ margin-right: 0;
45
+ }
46
+
47
+ .performance .vram {
48
+ }
49
+
50
+ #txt2img_generate, #img2img_generate {
51
+ min-height: 4.5em;
52
+ }
53
+
54
+ @media screen and (min-width: 2500px) {
55
+ #txt2img_gallery, #img2img_gallery {
56
+ min-height: 768px;
57
+ }
58
+ }
59
+
60
+ #txt2img_gallery img, #img2img_gallery img{
61
+ object-fit: scale-down;
62
+ }
63
+
64
+ .justify-center.overflow-x-scroll {
65
+ justify-content: left;
66
+ }
67
+
68
+ .justify-center.overflow-x-scroll button:first-of-type {
69
+ margin-left: auto;
70
+ }
71
+
72
+ .justify-center.overflow-x-scroll button:last-of-type {
73
+ margin-right: auto;
74
+ }
75
+
76
+ #random_seed, #random_subseed, #reuse_seed, #reuse_subseed, #open_folder{
77
+ min-width: auto;
78
+ flex-grow: 0;
79
+ padding-left: 0.25em;
80
+ padding-right: 0.25em;
81
+ }
82
+
83
+ #hidden_element{
84
+ display: none;
85
+ }
86
+
87
+ #seed_row, #subseed_row{
88
+ gap: 0.5rem;
89
+ }
90
+
91
+ #subseed_show_box{
92
+ min-width: auto;
93
+ flex-grow: 0;
94
+ }
95
+
96
+ #subseed_show_box > div{
97
+ border: 0;
98
+ height: 100%;
99
+ }
100
+
101
+ #subseed_show{
102
+ min-width: auto;
103
+ flex-grow: 0;
104
+ padding: 0;
105
+ }
106
+
107
+ #subseed_show label{
108
+ height: 100%;
109
+ }
110
+
111
+ #roll_col{
112
+ min-width: unset !important;
113
+ flex-grow: 0 !important;
114
+ padding: 0.4em 0;
115
+ }
116
+
117
+ #roll, #paste, #style_create, #style_apply{
118
+ min-width: 2em;
119
+ min-height: 2em;
120
+ max-width: 2em;
121
+ max-height: 2em;
122
+ flex-grow: 0;
123
+ padding-left: 0.25em;
124
+ padding-right: 0.25em;
125
+ margin: 0.1em 0;
126
+ }
127
+
128
+ #interrogate_col{
129
+ min-width: 0 !important;
130
+ max-width: 8em !important;
131
+ }
132
+ #interrogate, #deepbooru{
133
+ margin: 0em 0.25em 0.9em 0.25em;
134
+ min-width: 8em;
135
+ max-width: 8em;
136
+ }
137
+
138
+ #style_pos_col, #style_neg_col{
139
+ min-width: 8em !important;
140
+ }
141
+
142
+ #txt2img_style_index, #txt2img_style2_index, #img2img_style_index, #img2img_style2_index{
143
+ margin-top: 1em;
144
+ }
145
+
146
+ .gr-form{
147
+ background: transparent;
148
+ }
149
+
150
+ .my-4{
151
+ margin-top: 0;
152
+ margin-bottom: 0;
153
+ }
154
+
155
+ #toprow div{
156
+ border: none;
157
+ gap: 0;
158
+ background: transparent;
159
+ }
160
+
161
+ #resize_mode{
162
+ flex: 1.5;
163
+ }
164
+
165
+ button{
166
+ align-self: stretch !important;
167
+ }
168
+
169
+ .overflow-hidden, .gr-panel{
170
+ overflow: visible !important;
171
+ }
172
+
173
+ #x_type, #y_type{
174
+ max-width: 10em;
175
+ }
176
+
177
+ #txt2img_preview, #img2img_preview, #ti_preview{
178
+ position: absolute;
179
+ width: 320px;
180
+ left: 0;
181
+ right: 0;
182
+ margin-left: auto;
183
+ margin-right: auto;
184
+ margin-top: 34px;
185
+ z-index: 100;
186
+ border: none;
187
+ border-top-left-radius: 0;
188
+ border-top-right-radius: 0;
189
+ }
190
+
191
+ @media screen and (min-width: 768px) {
192
+ #txt2img_preview, #img2img_preview, #ti_preview {
193
+ position: absolute;
194
+ }
195
+ }
196
+
197
+ @media screen and (max-width: 767px) {
198
+ #txt2img_preview, #img2img_preview, #ti_preview {
199
+ position: relative;
200
+ }
201
+ }
202
+
203
+ #txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0, #ti_preview div.left-0.top-0{
204
+ display: none;
205
+ }
206
+
207
+ fieldset span.text-gray-500, .gr-block.gr-box span.text-gray-500, label.block span{
208
+ position: absolute;
209
+ top: -0.6em;
210
+ line-height: 1.2em;
211
+ padding: 0 0.5em;
212
+ margin: 0;
213
+
214
+ background-color: white;
215
+ border-top: 1px solid #eee;
216
+ border-left: 1px solid #eee;
217
+ border-right: 1px solid #eee;
218
+
219
+ z-index: 300;
220
+ }
221
+
222
+ .dark fieldset span.text-gray-500, .dark .gr-block.gr-box span.text-gray-500, .dark label.block span{
223
+ background-color: rgb(31, 41, 55);
224
+ border-top: 1px solid rgb(55 65 81);
225
+ border-left: 1px solid rgb(55 65 81);
226
+ border-right: 1px solid rgb(55 65 81);
227
+ }
228
+
229
+ #settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{
230
+ position: relative;
231
+ border: none;
232
+ margin-right: 8em;
233
+ }
234
+
235
+ .gr-panel div.flex-col div.justify-between label span{
236
+ margin: 0;
237
+ }
238
+
239
+ #settings .gr-panel div.flex-col div.justify-between div{
240
+ position: relative;
241
+ z-index: 200;
242
+ }
243
+
244
+ input[type="range"]{
245
+ margin: 0.5em 0 -0.3em 0;
246
+ }
247
+
248
+ #txt2img_sampling label{
249
+ padding-left: 0.6em;
250
+ padding-right: 0.6em;
251
+ }
252
+
253
+ #mask_bug_info {
254
+ text-align: center;
255
+ display: block;
256
+ margin-top: -0.75em;
257
+ margin-bottom: -0.75em;
258
+ }
259
+
260
+ #txt2img_negative_prompt, #img2img_negative_prompt{
261
+ }
262
+
263
+ #txt2img_progressbar, #img2img_progressbar, #ti_progressbar{
264
+ position: absolute;
265
+ z-index: 1000;
266
+ right: 0;
267
+ padding-left: 5px;
268
+ padding-right: 5px;
269
+ display: block;
270
+ }
271
+
272
+ #txt2img_progress_row, #img2img_progress_row{
273
+ margin-bottom: 10px;
274
+ margin-top: -18px;
275
+ }
276
+
277
+ .progressDiv{
278
+ width: 100%;
279
+ height: 20px;
280
+ background: #b4c0cc;
281
+ border-radius: 8px;
282
+ }
283
+
284
+ .dark .progressDiv{
285
+ background: #424c5b;
286
+ }
287
+
288
+ .progressDiv .progress{
289
+ width: 0%;
290
+ height: 20px;
291
+ background: #0060df;
292
+ color: white;
293
+ font-weight: bold;
294
+ line-height: 20px;
295
+ padding: 0 8px 0 0;
296
+ text-align: right;
297
+ border-radius: 8px;
298
+ }
299
+
300
+ #lightboxModal{
301
+ display: none;
302
+ position: fixed;
303
+ z-index: 1001;
304
+ padding-top: 100px;
305
+ left: 0;
306
+ top: 0;
307
+ width: 100%;
308
+ height: 100%;
309
+ overflow: auto;
310
+ background-color: rgba(20, 20, 20, 0.95);
311
+ user-select: none;
312
+ -webkit-user-select: none;
313
+ }
314
+
315
+ .modalControls {
316
+ display: grid;
317
+ grid-template-columns: 32px 32px 32px 1fr 32px;
318
+ grid-template-areas: "zoom tile save space close";
319
+ position: absolute;
320
+ top: 0;
321
+ left: 0;
322
+ right: 0;
323
+ padding: 16px;
324
+ gap: 16px;
325
+ background-color: rgba(0,0,0,0.2);
326
+ }
327
+
328
+ .modalClose {
329
+ grid-area: close;
330
+ }
331
+
332
+ .modalZoom {
333
+ grid-area: zoom;
334
+ }
335
+
336
+ .modalSave {
337
+ grid-area: save;
338
+ }
339
+
340
+ .modalTileImage {
341
+ grid-area: tile;
342
+ }
343
+
344
+ .modalClose,
345
+ .modalZoom,
346
+ .modalTileImage {
347
+ color: white;
348
+ font-size: 35px;
349
+ font-weight: bold;
350
+ cursor: pointer;
351
+ }
352
+
353
+ .modalSave {
354
+ color: white;
355
+ font-size: 28px;
356
+ margin-top: 8px;
357
+ font-weight: bold;
358
+ cursor: pointer;
359
+ }
360
+
361
+ .modalClose:hover,
362
+ .modalClose:focus,
363
+ .modalSave:hover,
364
+ .modalSave:focus,
365
+ .modalZoom:hover,
366
+ .modalZoom:focus {
367
+ color: #999;
368
+ text-decoration: none;
369
+ cursor: pointer;
370
+ }
371
+
372
+ #modalImage {
373
+ display: block;
374
+ margin-left: auto;
375
+ margin-right: auto;
376
+ margin-top: auto;
377
+ width: auto;
378
+ }
379
+
380
+ .modalImageFullscreen {
381
+ object-fit: contain;
382
+ height: 90%;
383
+ }
384
+
385
+ .modalPrev,
386
+ .modalNext {
387
+ cursor: pointer;
388
+ position: absolute;
389
+ top: 50%;
390
+ width: auto;
391
+ padding: 16px;
392
+ margin-top: -50px;
393
+ color: white;
394
+ font-weight: bold;
395
+ font-size: 20px;
396
+ transition: 0.6s ease;
397
+ border-radius: 0 3px 3px 0;
398
+ user-select: none;
399
+ -webkit-user-select: none;
400
+ }
401
+
402
+ .modalNext {
403
+ right: 0;
404
+ border-radius: 3px 0 0 3px;
405
+ }
406
+
407
+ .modalPrev:hover,
408
+ .modalNext:hover {
409
+ background-color: rgba(0, 0, 0, 0.8);
410
+ }
411
+
412
+ #imageARPreview{
413
+ position:absolute;
414
+ top:0px;
415
+ left:0px;
416
+ border:2px solid red;
417
+ background:rgba(255, 0, 0, 0.3);
418
+ z-index: 900;
419
+ pointer-events:none;
420
+ display:none
421
+ }
422
+
423
+ #txt2img_interrupt, #img2img_interrupt{
424
+ position: absolute;
425
+ width: 50%;
426
+ height: 72px;
427
+ background: #b4c0cc;
428
+ border-radius: 0px;
429
+ display: none;
430
+ }
431
+
432
+ #txt2img_skip, #img2img_skip{
433
+ position: absolute;
434
+ width: 50%;
435
+ right: 0px;
436
+ height: 72px;
437
+ background: #b4c0cc;
438
+ border-radius: 0px;
439
+ display: none;
440
+ }
441
+
442
+ .red {
443
+ color: red;
444
+ }
445
+
446
+ .gallery-item {
447
+ --tw-bg-opacity: 0 !important;
448
+ }
449
+
450
+ #context-menu{
451
+ z-index:9999;
452
+ position:absolute;
453
+ display:block;
454
+ padding:0px 0;
455
+ border:2px solid #a55000;
456
+ border-radius:8px;
457
+ box-shadow:1px 1px 2px #CE6400;
458
+ width: 200px;
459
+ }
460
+
461
+ .context-menu-items{
462
+ list-style: none;
463
+ margin: 0;
464
+ padding: 0;
465
+ }
466
+
467
+ .context-menu-items a{
468
+ display:block;
469
+ padding:5px;
470
+ cursor:pointer;
471
+ }
472
+
473
+ .context-menu-items a:hover{
474
+ background: #a55000;
475
+ }
476
+
477
+ #quicksettings {
478
+ gap: 0.4em;
479
+ }
480
+
481
+ #quicksettings > div{
482
+ border: none;
483
+ background: none;
484
+ flex: unset;
485
+ gap: 0.5em;
486
+ }
487
+
488
+ #quicksettings > div > div{
489
+ max-width: 32em;
490
+ min-width: 24em;
491
+ padding: 0;
492
+ }
493
+
494
+ #refresh_sd_model_checkpoint, #refresh_sd_hypernetwork, #refresh_train_hypernetwork_name, #refresh_train_embedding_name, #refresh_localization{
495
+ max-width: 2.5em;
496
+ min-width: 2.5em;
497
+ height: 2.4em;
498
+ }
499
+
500
+
501
+ canvas[key="mask"] {
502
+ z-index: 12 !important;
503
+ filter: invert();
504
+ mix-blend-mode: multiply;
505
+ pointer-events: none;
506
+ }
507
+
508
+
509
+ /* gradio 3.4.1 stuff for editable scrollbar values */
510
+ .gr-box > div > div > input.gr-text-input{
511
+ position: absolute;
512
+ right: 0.5em;
513
+ top: -0.6em;
514
+ z-index: 200;
515
+ width: 8em;
516
+ }
517
+ #quicksettings .gr-box > div > div > input.gr-text-input {
518
+ top: -1.12em;
519
+ }
520
+
521
+ .row.gr-compact{
522
+ overflow: visible;
523
+ }
524
+
525
+ #img2img_image, #img2img_image > .h-60, #img2img_image > .h-60 > div, #img2img_image > .h-60 > div > img,
526
+ img2maskimg, #img2maskimg > .h-60, #img2maskimg > .h-60 > div, #img2maskimg > .h-60 > div > img
527
+ {
528
+ height: 480px !important;
529
+ max-height: 480px !important;
530
+ min-height: 480px !important;
531
+ }
532
+
533
+ /* Extensions */
534
+
535
+ #tab_extensions table{
536
+ border-collapse: collapse;
537
+ }
538
+
539
+ #tab_extensions table td, #tab_extensions table th{
540
+ border: 1px solid #ccc;
541
+ padding: 0.25em 0.5em;
542
+ }
543
+
544
+ #tab_extensions table input[type="checkbox"]{
545
+ margin-right: 0.5em;
546
+ }
547
+
548
+ #tab_extensions button{
549
+ max-width: 16em;
550
+ }
551
+
552
+ #tab_extensions input[disabled="disabled"]{
553
+ opacity: 0.5;
554
+ }
555
+
556
+ /* The following handles localization for right-to-left (RTL) languages like Arabic.
557
+ The rtl media type will only be activated by the logic in javascript/localization.js.
558
+ If you change anything above, you need to make sure it is RTL compliant by just running
559
+ your changes through converters like https://cssjanus.github.io/ or https://rtlcss.com/.
560
+ Then, you will need to add the RTL counterpart only if needed in the rtl section below.*/
561
+ @media rtl {
562
+ /* this part was added manually */
563
+ :host {
564
+ direction: rtl;
565
+ }
566
+ select, .file-preview, .gr-text-input, .output-html:has(.performance), #ti_progress {
567
+ direction: ltr;
568
+ }
569
+ #script_list > label > select,
570
+ #x_type > label > select,
571
+ #y_type > label > select {
572
+ direction: rtl;
573
+ }
574
+ .gr-radio, .gr-checkbox{
575
+ margin-left: 0.25em;
576
+ }
577
+
578
+ /* automatically generated with few manual modifications */
579
+ .performance .time {
580
+ margin-right: unset;
581
+ margin-left: 0;
582
+ }
583
+ .justify-center.overflow-x-scroll {
584
+ justify-content: right;
585
+ }
586
+ .justify-center.overflow-x-scroll button:first-of-type {
587
+ margin-left: unset;
588
+ margin-right: auto;
589
+ }
590
+ .justify-center.overflow-x-scroll button:last-of-type {
591
+ margin-right: unset;
592
+ margin-left: auto;
593
+ }
594
+ #settings fieldset span.text-gray-500, #settings .gr-block.gr-box span.text-gray-500, #settings label.block span{
595
+ margin-right: unset;
596
+ margin-left: 8em;
597
+ }
598
+ #txt2img_progressbar, #img2img_progressbar, #ti_progressbar{
599
+ right: unset;
600
+ left: 0;
601
+ }
602
+ .progressDiv .progress{
603
+ padding: 0 0 0 8px;
604
+ text-align: left;
605
+ }
606
+ #lightboxModal{
607
+ left: unset;
608
+ right: 0;
609
+ }
610
+ .modalPrev, .modalNext{
611
+ border-radius: 3px 0 0 3px;
612
+ }
613
+ .modalNext {
614
+ right: unset;
615
+ left: 0;
616
+ border-radius: 0 3px 3px 0;
617
+ }
618
+ #imageARPreview{
619
+ left:unset;
620
+ right:0px;
621
+ }
622
+ #txt2img_skip, #img2img_skip{
623
+ right: unset;
624
+ left: 0px;
625
+ }
626
+ #context-menu{
627
+ box-shadow:-1px 1px 2px #CE6400;
628
+ }
629
+ .gr-box > div > div > input.gr-text-input{
630
+ right: unset;
631
+ left: 0.5em;
632
+ }
633
+ }
txt2img_Screenshot.png ADDED
webui-user.bat ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+
3
+ set PYTHON=
4
+ set GIT=
5
+ set VENV_DIR=
6
+ set COMMANDLINE_ARGS=
7
+
8
+ call webui.bat
webui-user.sh ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ #########################################################
3
+ # Uncomment and change the variables below to your need:#
4
+ #########################################################
5
+
6
+ # Install directory without trailing slash
7
+ #install_dir="/home/$(whoami)"
8
+
9
+ # Name of the subdirectory
10
+ #clone_dir="stable-diffusion-webui"
11
+
12
+ # Commandline arguments for webui.py, for example: export COMMANDLINE_ARGS="--medvram --opt-split-attention"
13
+ export COMMANDLINE_ARGS=""
14
+
15
+ # python3 executable
16
+ #python_cmd="python3"
17
+
18
+ # git executable
19
+ #export GIT="git"
20
+
21
+ # python3 venv without trailing slash (defaults to ${install_dir}/${clone_dir}/venv)
22
+ #venv_dir="venv"
23
+
24
+ # script to launch to start the app
25
+ #export LAUNCH_SCRIPT="launch.py"
26
+
27
+ # install command for torch
28
+ #export TORCH_COMMAND="pip install torch==1.12.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113"
29
+
30
+ # Requirements file to use for stable-diffusion-webui
31
+ #export REQS_FILE="requirements_versions.txt"
32
+
33
+ # Fixed git repos
34
+ #export K_DIFFUSION_PACKAGE=""
35
+ #export GFPGAN_PACKAGE=""
36
+
37
+ # Fixed git commits
38
+ #export STABLE_DIFFUSION_COMMIT_HASH=""
39
+ #export TAMING_TRANSFORMERS_COMMIT_HASH=""
40
+ #export CODEFORMER_COMMIT_HASH=""
41
+ #export BLIP_COMMIT_HASH=""
42
+
43
+ ###########################################
webui.bat ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+
3
+ if not defined PYTHON (set PYTHON=python)
4
+ if not defined VENV_DIR (set VENV_DIR=venv)
5
+
6
+ set ERROR_REPORTING=FALSE
7
+
8
+ mkdir tmp 2>NUL
9
+
10
+ %PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
11
+ if %ERRORLEVEL% == 0 goto :start_venv
12
+ echo Couldn't launch python
13
+ goto :show_stdout_stderr
14
+
15
+ :start_venv
16
+ if [%VENV_DIR%] == [-] goto :skip_venv
17
+
18
+ dir %VENV_DIR%\Scripts\Python.exe >tmp/stdout.txt 2>tmp/stderr.txt
19
+ if %ERRORLEVEL% == 0 goto :activate_venv
20
+
21
+ for /f "delims=" %%i in ('CALL %PYTHON% -c "import sys; print(sys.executable)"') do set PYTHON_FULLNAME="%%i"
22
+ echo Creating venv in directory %VENV_DIR% using python %PYTHON_FULLNAME%
23
+ %PYTHON_FULLNAME% -m venv %VENV_DIR% >tmp/stdout.txt 2>tmp/stderr.txt
24
+ if %ERRORLEVEL% == 0 goto :activate_venv
25
+ echo Unable to create venv in directory %VENV_DIR%
26
+ goto :show_stdout_stderr
27
+
28
+ :activate_venv
29
+ set PYTHON="%~dp0%VENV_DIR%\Scripts\Python.exe"
30
+ echo venv %PYTHON%
31
+ goto :launch
32
+
33
+ :skip_venv
34
+
35
+ :launch
36
+ %PYTHON% launch.py %*
37
+ pause
38
+ exit /b
39
+
40
+ :show_stdout_stderr
41
+
42
+ echo.
43
+ echo exit code: %errorlevel%
44
+
45
+ for /f %%i in ("tmp\stdout.txt") do set size=%%~zi
46
+ if %size% equ 0 goto :show_stderr
47
+ echo.
48
+ echo stdout:
49
+ type tmp\stdout.txt
50
+
51
+ :show_stderr
52
+ for /f %%i in ("tmp\stderr.txt") do set size=%%~zi
53
+ if %size% equ 0 goto :show_stderr
54
+ echo.
55
+ echo stderr:
56
+ type tmp\stderr.txt
57
+
58
+ :endofscript
59
+
60
+ echo.
61
+ echo Launch unsuccessful. Exiting.
62
+ pause
webui.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import threading
3
+ import time
4
+ import importlib
5
+ import signal
6
+ import threading
7
+ from fastapi import FastAPI
8
+ from fastapi.middleware.gzip import GZipMiddleware
9
+
10
+ from modules.paths import script_path
11
+
12
+ from modules import devices, sd_samplers, upscaler, extensions
13
+ import modules.codeformer_model as codeformer
14
+ import modules.extras
15
+ import modules.face_restoration
16
+ import modules.gfpgan_model as gfpgan
17
+ import modules.img2img
18
+
19
+ import modules.lowvram
20
+ import modules.paths
21
+ import modules.scripts
22
+ import modules.sd_hijack
23
+ import modules.sd_models
24
+ import modules.shared as shared
25
+ import modules.txt2img
26
+
27
+ import modules.ui
28
+ from modules import devices
29
+ from modules import modelloader
30
+ from modules.paths import script_path
31
+ from modules.shared import cmd_opts
32
+ import modules.hypernetworks.hypernetwork
33
+
34
+ queue_lock = threading.Lock()
35
+
36
+
37
+ def wrap_queued_call(func):
38
+ def f(*args, **kwargs):
39
+ with queue_lock:
40
+ res = func(*args, **kwargs)
41
+
42
+ return res
43
+
44
+ return f
45
+
46
+
47
+ def wrap_gradio_gpu_call(func, extra_outputs=None):
48
+ def f(*args, **kwargs):
49
+
50
+ shared.state.begin()
51
+
52
+ with queue_lock:
53
+ res = func(*args, **kwargs)
54
+
55
+ shared.state.end()
56
+
57
+ return res
58
+
59
+ return modules.ui.wrap_gradio_call(f, extra_outputs=extra_outputs)
60
+
61
+
62
+ def initialize():
63
+ extensions.list_extensions()
64
+
65
+ if cmd_opts.ui_debug_mode:
66
+ shared.sd_upscalers = upscaler.UpscalerLanczos().scalers
67
+ modules.scripts.load_scripts()
68
+ return
69
+
70
+ modelloader.cleanup_models()
71
+ modules.sd_models.setup_model()
72
+ codeformer.setup_model(cmd_opts.codeformer_models_path)
73
+ gfpgan.setup_model(cmd_opts.gfpgan_models_path)
74
+ shared.face_restorers.append(modules.face_restoration.FaceRestoration())
75
+ modelloader.load_upscalers()
76
+
77
+ modules.scripts.load_scripts()
78
+
79
+ modules.sd_models.load_model()
80
+ shared.opts.onchange("sd_model_checkpoint", wrap_queued_call(lambda: modules.sd_models.reload_model_weights(shared.sd_model)))
81
+ shared.opts.onchange("sd_hypernetwork", wrap_queued_call(lambda: modules.hypernetworks.hypernetwork.load_hypernetwork(shared.opts.sd_hypernetwork)))
82
+ shared.opts.onchange("sd_hypernetwork_strength", modules.hypernetworks.hypernetwork.apply_strength)
83
+
84
+ # make the program just exit at ctrl+c without waiting for anything
85
+ def sigint_handler(sig, frame):
86
+ print(f'Interrupted with signal {sig} in {frame}')
87
+ os._exit(0)
88
+
89
+ signal.signal(signal.SIGINT, sigint_handler)
90
+
91
+
92
+ def create_api(app):
93
+ from modules.api.api import Api
94
+ api = Api(app, queue_lock)
95
+ return api
96
+
97
+
98
+ def wait_on_server(demo=None):
99
+ while 1:
100
+ time.sleep(0.5)
101
+ if shared.state.need_restart:
102
+ shared.state.need_restart = False
103
+ time.sleep(0.5)
104
+ demo.close()
105
+ time.sleep(0.5)
106
+ break
107
+
108
+
109
+ def api_only():
110
+ initialize()
111
+
112
+ app = FastAPI()
113
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
114
+ api = create_api(app)
115
+
116
+ api.launch(server_name="0.0.0.0" if cmd_opts.listen else "127.0.0.1", port=cmd_opts.port if cmd_opts.port else 7861)
117
+
118
+
119
+ def webui():
120
+ launch_api = cmd_opts.api
121
+ initialize()
122
+
123
+ while 1:
124
+ demo = modules.ui.create_ui(wrap_gradio_gpu_call=wrap_gradio_gpu_call)
125
+
126
+ app, local_url, share_url = demo.launch(
127
+ share=cmd_opts.share,
128
+ server_name="0.0.0.0" if cmd_opts.listen else None,
129
+ server_port=cmd_opts.port,
130
+ debug=cmd_opts.gradio_debug,
131
+ auth=[tuple(cred.split(':')) for cred in cmd_opts.gradio_auth.strip('"').split(',')] if cmd_opts.gradio_auth else None,
132
+ inbrowser=cmd_opts.autolaunch,
133
+ prevent_thread_lock=True
134
+ )
135
+ # after initial launch, disable --autolaunch for subsequent restarts
136
+ cmd_opts.autolaunch = False
137
+
138
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
139
+
140
+ if launch_api:
141
+ create_api(app)
142
+
143
+ wait_on_server(demo)
144
+
145
+ sd_samplers.set_samplers()
146
+
147
+ print('Reloading extensions')
148
+ extensions.list_extensions()
149
+ print('Reloading custom scripts')
150
+ modules.scripts.reload_scripts()
151
+ print('Reloading modules: modules.ui')
152
+ importlib.reload(modules.ui)
153
+ print('Refreshing Model List')
154
+ modules.sd_models.list_models()
155
+ print('Restarting Gradio')
156
+
157
+
158
+ if __name__ == "__main__":
159
+ if cmd_opts.nowebui:
160
+ api_only()
161
+ else:
162
+ webui()
webui.sh ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ #################################################
3
+ # Please do not make any changes to this file, #
4
+ # change the variables in webui-user.sh instead #
5
+ #################################################
6
+ # Read variables from webui-user.sh
7
+ # shellcheck source=/dev/null
8
+ if [[ -f webui-user.sh ]]
9
+ then
10
+ source ./webui-user.sh
11
+ fi
12
+
13
+ # Set defaults
14
+ # Install directory without trailing slash
15
+ if [[ -z "${install_dir}" ]]
16
+ then
17
+ install_dir="/home/$(whoami)"
18
+ fi
19
+
20
+ # Name of the subdirectory (defaults to stable-diffusion-webui)
21
+ if [[ -z "${clone_dir}" ]]
22
+ then
23
+ clone_dir="stable-diffusion-webui"
24
+ fi
25
+
26
+ # python3 executable
27
+ if [[ -z "${python_cmd}" ]]
28
+ then
29
+ python_cmd="python3"
30
+ fi
31
+
32
+ # git executable
33
+ if [[ -z "${GIT}" ]]
34
+ then
35
+ export GIT="git"
36
+ fi
37
+
38
+ # python3 venv without trailing slash (defaults to ${install_dir}/${clone_dir}/venv)
39
+ if [[ -z "${venv_dir}" ]]
40
+ then
41
+ venv_dir="venv"
42
+ fi
43
+
44
+ if [[ -z "${LAUNCH_SCRIPT}" ]]
45
+ then
46
+ LAUNCH_SCRIPT="launch.py"
47
+ fi
48
+
49
+ # Disable sentry logging
50
+ export ERROR_REPORTING=FALSE
51
+
52
+ # Do not reinstall existing pip packages on Debian/Ubuntu
53
+ export PIP_IGNORE_INSTALLED=0
54
+
55
+ # Pretty print
56
+ delimiter="################################################################"
57
+
58
+ printf "\n%s\n" "${delimiter}"
59
+ printf "\e[1m\e[32mInstall script for stable-diffusion + Web UI\n"
60
+ printf "\e[1m\e[34mTested on Debian 11 (Bullseye)\e[0m"
61
+ printf "\n%s\n" "${delimiter}"
62
+
63
+ # Do not run as root
64
+ if [[ $(id -u) -eq 0 ]]
65
+ then
66
+ printf "\n%s\n" "${delimiter}"
67
+ printf "\e[1m\e[31mERROR: This script must not be launched as root, aborting...\e[0m"
68
+ printf "\n%s\n" "${delimiter}"
69
+ exit 1
70
+ else
71
+ printf "\n%s\n" "${delimiter}"
72
+ printf "Running on \e[1m\e[32m%s\e[0m user" "$(whoami)"
73
+ printf "\n%s\n" "${delimiter}"
74
+ fi
75
+
76
+ if [[ -d .git ]]
77
+ then
78
+ printf "\n%s\n" "${delimiter}"
79
+ printf "Repo already cloned, using it as install directory"
80
+ printf "\n%s\n" "${delimiter}"
81
+ install_dir="${PWD}/../"
82
+ clone_dir="${PWD##*/}"
83
+ fi
84
+
85
+ # Check prerequisites
86
+ for preq in "${GIT}" "${python_cmd}"
87
+ do
88
+ if ! hash "${preq}" &>/dev/null
89
+ then
90
+ printf "\n%s\n" "${delimiter}"
91
+ printf "\e[1m\e[31mERROR: %s is not installed, aborting...\e[0m" "${preq}"
92
+ printf "\n%s\n" "${delimiter}"
93
+ exit 1
94
+ fi
95
+ done
96
+
97
+ if ! "${python_cmd}" -c "import venv" &>/dev/null
98
+ then
99
+ printf "\n%s\n" "${delimiter}"
100
+ printf "\e[1m\e[31mERROR: python3-venv is not installed, aborting...\e[0m"
101
+ printf "\n%s\n" "${delimiter}"
102
+ exit 1
103
+ fi
104
+
105
+ cd "${install_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/, aborting...\e[0m" "${install_dir}"; exit 1; }
106
+ if [[ -d "${clone_dir}" ]]
107
+ then
108
+ cd "${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
109
+ else
110
+ printf "\n%s\n" "${delimiter}"
111
+ printf "Clone stable-diffusion-webui"
112
+ printf "\n%s\n" "${delimiter}"
113
+ "${GIT}" clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git "${clone_dir}"
114
+ cd "${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
115
+ fi
116
+
117
+ printf "\n%s\n" "${delimiter}"
118
+ printf "Create and activate python venv"
119
+ printf "\n%s\n" "${delimiter}"
120
+ cd "${install_dir}"/"${clone_dir}"/ || { printf "\e[1m\e[31mERROR: Can't cd to %s/%s/, aborting...\e[0m" "${install_dir}" "${clone_dir}"; exit 1; }
121
+ if [[ ! -d "${venv_dir}" ]]
122
+ then
123
+ "${python_cmd}" -m venv "${venv_dir}"
124
+ first_launch=1
125
+ fi
126
+ # shellcheck source=/dev/null
127
+ if [[ -f "${venv_dir}"/bin/activate ]]
128
+ then
129
+ source "${venv_dir}"/bin/activate
130
+ else
131
+ printf "\n%s\n" "${delimiter}"
132
+ printf "\e[1m\e[31mERROR: Cannot activate python venv, aborting...\e[0m"
133
+ printf "\n%s\n" "${delimiter}"
134
+ exit 1
135
+ fi
136
+
137
+ printf "\n%s\n" "${delimiter}"
138
+ printf "Launching launch.py..."
139
+ printf "\n%s\n" "${delimiter}"
140
+ "${python_cmd}" "${LAUNCH_SCRIPT}" "$@"